Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Can write an INPUT HIGH but not LOW ?

  1. #1
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,915

    Can write an INPUT HIGH but not LOW ?

    I made an error with #defines and ended up re-using the same pin for two functions one INPUT and one OUTPUT. This won't work obviously and my simplified code demonstrates this error, in the first two lines. It was subtly mixed in with other stuff I need to clean up - but moving it from three working boards with a unique array of pins to a fourth board the change crept in.

    The code below shows anomalous behavior it seems to me that made debugging it not what it first seemed it would be. Second post to follow doing this on LED_BUILTIN pin acts differently

    Intro: I set up an OUTPUT pin to LOW. ( Correct ) The same pin is then set out INPUT. ( Error )

    Logically: Given the pin is now INPUT I would expect any attempt to write to the pin to be ignored.

    Problem: The code below shows the pin will take a digitalWrite(LED_BUILTIN, HIGH); but not a corresponding digitalWrite(LED_BUILTIN, LOW);

    Question: Is there any reason to expect or consider this behavior normal, or is it a bug?

    Sample: Code below demonstrates the problem. I put in a 10 sec wait between the three steps as the LED_BUILTIN changes to match the pin 3 value as read for confirmation.

    Code:
    #define THREE 3
    #define FOUR 3    // This represents the coding error I made
    elapsedMillis aTime;
    void showstatus( String info );
    
    void setup() {
      Serial.begin(9600);
      while (!Serial && (millis () <= 5000)) ;  // Wait for Serial to come online
      Serial.println("\n\n\nHello Out & In Error");
      pinMode(LED_BUILTIN, OUTPUT);
      digitalWrite(LED_BUILTIN, HIGH);
      pinMode(THREE, OUTPUT);
      digitalWrite(THREE, LOW);
      pinMode(FOUR, INPUT);
      showstatus( " setup() : user err OUTPUT redefined INPUT " );
    }
    
    void loop() {
      if ( aTime >= 10000 && aTime <10001) {
        showstatus( " loop() NO CHANGE" );
        delay(2); // prevent re-entry this millisecond
      }
      if ( aTime >= 20000 && aTime <20001) {
        digitalWrite(THREE, HIGH);       // set INPUT HIGH - WORKS
        showstatus( " loop() Set INPUT HIGH - THIS WORKS ???" );
        delay(2); // prevent re-entry this millisecond
      }
      if ( aTime >= 30000 && aTime <30001) {
        digitalWrite(THREE, LOW);        // set INPUT LOW - FAILS
        showstatus( " loop() Set INPUT LOW - THIS FAILS ???" );
        delay(2); // prevent re-entry this millisecond
      }
    }
    
    void showstatus( String info ) {
      Serial.print(info);
      Serial.print(" time at: ");
      Serial.println(aTime);
      digitalWrite(LED_BUILTIN, digitalRead( THREE ));
      if ( digitalRead( THREE ) )   Serial.print("       INPUT pin THREE reads HIGH ");
      else   Serial.print("       INPUT pin THREE reads LOW ");
      Serial.println();
    }

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,915
    Update:

    Cleanup: I thought the sample code could be shorter if I went right to the LED_BUILTIN pin, and it saved a few lines

    Problem1: The digitalWrite(LED_BUILTIN, HIGH); set the pin to an ODD not fully lit state, and in fact reads as LOW

    Problem2: The digitalWrite(LED_BUILTIN, LOW); does set the pin LOW and the LED goes off

    Code:
    #define LED LED_BUILTIN
    #define NOT_LED LED_BUILTIN    // This represents the coding error I made
    elapsedMillis aTime;
    void showstatus( String info );
    
    void setup() {
      Serial.begin(9600);
      while (!Serial && (millis () <= 5000)) ;  // Wait for Serial to come online
      Serial.println("\n\n\nHello Out & In Error");
      pinMode(LED, OUTPUT);
      digitalWrite(LED, LOW);
      pinMode(NOT_LED, INPUT);
      showstatus( " setup() : user err OUTPUT redefined INPUT " );
    }
    
    void loop() {
      if ( aTime >= 10000 && aTime <10001) {
        showstatus( " loop() NO CHANGE" );
        delay(2); // prevent re-entry this millisecond
      }
      if ( aTime >= 20000 && aTime <20001) {
        digitalWrite(LED, HIGH);       // set INPUT HIGH - WORKS
        showstatus( " loop() Set INPUT HIGH - THIS WORKS HALFWAY on LED_BUILTIN, dim but reads LOW ???" );
        delay(2); // prevent re-entry this millisecond
      }
      if ( aTime >= 30000 && aTime <30001) {
        digitalWrite(LED, LOW);        // set INPUT LOW - FAILS
        showstatus( " loop() Set INPUT LOW - Turns the LED_BUILTIN OFF ???" );
        delay(2); // prevent re-entry this millisecond
      }
    }
    
    void showstatus( String info ) {
      Serial.print(info + " time at: ");
      Serial.println(aTime);
      if ( digitalRead( LED ) )   Serial.print("       INPUT LED pin reads HIGH ");
      else   Serial.print("       INPUT LED pin reads LOW ");
      Serial.println();
    }
    Last edited by defragster; 02-10-2016 at 08:42 AM. Reason: Second artifact or error

  3. #3
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,905
    I had thought the Teensy3 was different but in Arduino the register for output is also the one for setting the input pullups. So digitalWrite(3,HIGH); will set pullups to high if a pin is an input. I'm assuming this is a nice and simple electrical way to do things.

    Unsure if the Teensy3 actually has hardware working that way but even if it doesn't it would be quite possible the compatibility code would be setting the pullups anway in case a library was using the feature for something.

  4. #4
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,905
    Well having referred to the good book (t3 version https://www.pjrc.com/teensy/K20P64M72SF1RM.pdf) seems that the pullups are in different registers from the IO so it's not hardware behavior so guess next step is a look at the digitalWrite code.

    edit:
    If I'm reading it right the avr_emulation.h IO section lines (repeats for all pins)
    Code:
    			digitalWriteFast(1, HIGH);
    			if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) CORE_PIN1_CONFIG = CONFIG_PULLUP;
    are writing the value and also configuring pullups if the port direction register is set as input

    So the pullups coming on if you set a input pin high is a feature. And is one of the things that digitalWriteFast doesn't do.
    Last edited by GremlinWrangler; 02-10-2016 at 11:20 AM.

  5. #5
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,915
    GremlinWrangler: Thanks for (fast) research - I suspected(WAG) it was triggering pullups - especially when I saw the DIM LED_BUILTIN. Suppose it is the LED support that makes the pin13 act differently.

    At this time I am using #define and digitalWriteFast() may have acted differently as you suggest - but when I work to make this right it will come from a runtime variable and digitalWriteFast() wouldn't be used so I skipped testing that.

    It was my error and I should not have done it - but the resulting behavior obscured debugging the source of the problem. Seeing the OUTPUT show HIGH was expected - so I assumed a hardware problem not letting it go low. Had the CONFIG_PULLUP dropped on writing LOW I would not have seen my error until even later - when I tried to use the 'second' pins function.

    Indeed a one line pin write wouldn't be the same if it had to double check the pinMode() against the user actual usage. I tried to make the title unassuming but suggestive for future searches - though following the forum rule should result in catching this before other random posts. In fact it was during my plan to minimize the sketch after I repro'd on a new T_3.2 what I saw on an older T_3.1 reading the sketch code I assumed was 'safe' from question when I caught the problem obscured by conflicting #define's.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •