Go Down

Topic: Reading and writing to a single digital pin (Read 5 times) previous topic - next topic

PaulS

Quote
I am starting to think this single input output think may not be possible...

If the pin starts as an input pin, and you read that the switch is pressed, and convert it to an output pin and turn the LED on (regardless of how the switch is wired), how will you ever read the switch again?

I've thought from the beginning that using one pin for input and output would not work.

GoForSmoke

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

0

Quote
Don't forget Charlieplexing.

will make the circuit more complex and wiring even more difficult.. and if 1 led or so might fail it could be very hard debug... Anyways nice thought though... never thought about it myself :)

Quote
I've thought from the beginning that using one pin for input and output would not work.


So I guess this a dead end then... :( Really hoped to get it working this way... Back to the usual method now... Thank you everyone for your valuable inputs :)

johncc

I believe that it will work the way you have said you want it to, if you follow PeterH's suggestions.

If it is not, check your wiring and pin assignments?  What exactly is it doing/not doing?

Code: [Select]

// "When a button is pressed, latch it's own LED on and turn off all the others"

buttonState_1 = digitalRead(button_1);
buttonState_2 = digitalRead(button_2);

if(buttonState_1 == 0)   // Button 1 is pressed. Switch shorted with ground
{
    // "turn off all the others"
    pinMode(button_2,INPUT);
    digitalWrite(button_2,HIGH); // note active LOW, so this turns led2 off
   
    // "turn my own led on"
    digitalWrite(button_1,LOW);  //  active LOW to enable led1
    pinMode(button_1, OUTPUT); // turn it on
}

if(buttonState_2 == 0)   // Button 2 is pressed. Switch shorted with ground
{
    // "turn off all the others"
    pinMode(button_1,INPUT);
    digitalWrite(button_1,HIGH);
   
    // "turn my own led on"
    digitalWrite(button_2,LOW);
    pinMode(button_2, OUTPUT);
}

0


johncc

Ok, I see.  You have never said though, what does your serial output show?  Is it tracking properly with your button presses?  You might want to slow your loop down, e.g. delay(500) instead of delay(50).  Also you could put serial.prints within your if statements like "Turning 1 on", "Turning 2 on".  And maybe even a delay(250) in between the two if statements.  All together this may allow you to see what's going on.  E.g. are you sure you don't have a sticking switch, etc.

Cheers,
John

i.e. pseudocode
read both buttons
print button values
if button1
   print "Turning 1 on"
   turn 1 on, 2 off
endif
delay 250
if button2
   print "Turning 2 on"
   turn 2 on, 1 off
endif

delay 500

PeterH

The symptoms seem consistent with switch 2 sticking on. Have you actually confirmed it's a momentary switch and not a latching one? Can you print out the switch state transitions that your sketch sees to confirm that the switch inputs are giving you the values you expect?

I don't think the approach you're taking is very sensible (it feels like a complex solution to a simple problem) but it is feasible and I can't see any reason why it couldn't be made to work.
I only provide help via the forum - please do not contact me for private consultancy.

PaulS

Quote
but it is feasible and I can't see any reason why it couldn't be made to work.

I'm not understanding how. If the pin starts in INPUT mode, then reading the switch makes sense. If the pin is then switched to OUTPUT mode, and written HIGH or LOW, future readings of that pin will only return the state that the pin was last written to, not the state of the switch that is attached to the pin.

johncc

Yes, good point.  He should avoid  reading the one that has already been latched on-- and only read the other ones.  That is the problem with his current code.

johncc

#39
Feb 18, 2013, 12:41 am Last Edit: Feb 18, 2013, 02:47 am by johncc Reason: 1
@OOO

I think your approach is interesting and am looking forward to seeing it work.

You need to avoid reading the button/led that you have already turned on.

Maybe something like this (compiled but not tested)
Code: [Select]

/*
   "Radio Buttons"
   When a button is pressed, latch its own LED on, and turn all the others off
*/
const int nButtons=3;
int buttons[]= { 7, 12, 14 };  // each "button" is a button/led pair
int currentOn = 0;

void latch( int onPin)
{
    // turn onPin on,
    digitalWrite( onPin, LOW);
    pinMode( onPin, OUTPUT);

    // if there is an other pin on, turn it off
    if (currentOn > 0)
    {
       pinMode( currentOn, INPUT);
       digitalWrite( currentOn, HIGH);  // pullup
    }
}

void loop()
{
 for (int i=0; i< nButtons; i++)
 {  
     // read all but the currenly-on button
     if ( buttons[i] != currentOn && digitalRead( buttons[i])== LOW)  // active LOW
     {
         latch( buttons[i]);
         currentOn = buttons[i];
         break;
     }
 }
}


Cheers,
John

GoForSmoke


Quote
Don't forget Charlieplexing.

will make the circuit more complex and wiring even more difficult.. and if 1 led or so might fail it could be very hard debug... Anyways nice thought though... never thought about it myself :)

Quote


Now try just understanding that there are ways and apps that use multi-state pins as opposed to advice to "use Charlieplexing".

Oh BTW you can you turn the led off long enough to read the switch? Who would notice?
I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

0

@johncc @peterH
I had tried that earlier by stopping the reading when it was LED was on. but it didnt work...

But your code actually works... Thanks  :)  So I guess mine was a coding error.

Sorry will write up a detailed reply tomorrow. got to prepare for a test for tomorrow...
Thank you again will get back to you guys tomorrow

Docedison

Perhaps out of line considering the previous discussion.. But OP did I think mention turning a LED on for a specific time on button stimulus Why not use PCF8574's?. IIC but easily chained, read the registers, write those that have changed state whether by input or timeout.

Bob
--> WA7EMS <--
"The solution of every problem is another problem." -Johann Wolfgang von Goethe
I do answer technical questions PM'd to me with whatever is in my clipboard

0

Back... :)

Quote
Yes, good point.  He should avoid  reading the one that has already been latched on-- and only read the other ones.  That is the problem with his current code.


Believe it or not I had tried this with flags but I was getting the same results so I quit trying(it was one late night) rather than thinking it could be a coding error. I think I coded it badly that day because my algorithm was exactly same as @johncc

Anyways I got it working with johncc code. :D Thank you so very much. :)
So its actually possible to do it.

So for completion if someone ever faces this same problem. I have attached the code I used for 10 Ledpairs and and the schematic of one.
All thanks to johncc and PeterH :)

Code: [Select]
const int nButtons=10;  // Number of buttons
int ledButtons[]= {
  2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };  // Enter all the LED/Button pair pins on Arduino
int currentOn = -1;

void turnLedOn( int onPin)
{
  // Turn the particular LED pin on,
  digitalWrite(onPin, LOW);
  pinMode(onPin, OUTPUT);

  // if there is an other pin on, turn it off
  if (currentOn > -1)
  {
    pinMode( currentOn, INPUT_PULLUP);  // Enable pullup and turn off other LEDs
  }
}

void setup()
{
  for(int i=0; i<nButtons; i++)
  {
    pinMode(ledButtons[i],INPUT_PULLUP);  // Enabling internal pullups
  }
}

void loop()
{
  for (int i=0; i< nButtons; i++)
  {   
    // read all but the currenly-on button
    if (ledButtons[i] != currentOn && digitalRead( ledButtons[i])== LOW)  // active LOW
    {
      turnLedOn(ledButtons[i]);
      currentOn = ledButtons[i];
      break;
    }
  }
}




Go Up