Go Down

Topic: Toggle Project (Read 955 times) previous topic - next topic

mgbnut

Hey everybody! It's my 1st post, and I'm a newbie to Arduino and programming. I am a field service technician given the task of creating a "toggling" control for our labeling machines. I'm starting simple. I found some code that will let me toggle an 'on' state of each of 2 LED's in turn with a pushbutton. What I need is that, plus add a button for each LED so that, when pushed, it's LED won't get a turn and the opposite LED comes on with each push. Here is my code so far:

Quote

//Circuit: Switch to Pin2, 10k resistor to Pin2, switch to ground
//LED on pin12, LED on pin13, both with 1k resistor to ground

int inPin0 = 2;   // choose the input pin (for Main pushbutton)
int inPin1 = 6;   // the number of the input pin
int inPin2 = 8;   // the number of the input pin
int val = 0;     // variable for reading the pin status
bool pushed = false;
bool greenState = true;
bool redState = false;

void setup() {
  pinMode(12, OUTPUT);  // declare LED as output
  pinMode(13, OUTPUT);  // declare LED as output
  pinMode(inPin0, INPUT);   // declare pushbutton as input
  pinMode(inPin1, INPUT);   // declare pushbutton as input
  pinMode(inPin2, INPUT);   // declare pushbutton as input
  digitalWrite(12, HIGH);  // turn LED ON
  digitalWrite(13, LOW);  // turn LED ON
  Serial.begin(9600);
}

void green(bool state) {
   digitalWrite(12, state ? HIGH : LOW);
   greenState = state;
}

void red(bool state) {
   digitalWrite(13, state ? HIGH : LOW);
   redState = state;
}

void toggle() {
  green(!greenState);
  red(!redState);
  printState();
}

void printState() {
  Serial.print("Red "); Serial.print(redState, DEC);
  Serial.print(" Green "); Serial.println(greenState, DEC);
}

void loop(){  

  // remote control
  if (Serial.available() > 0) {
    int b = Serial.read();
    if (b == 'g')  {
      Serial.println("Turning on green");
      red(false);
      green(true);
    }
    if (b == 'r') {
      Serial.println("Turning on red");
      red(true);
      green(false);
    }
    if (b == 's') {
      printState();
    }
    Serial.flush();
  }

  // button0 handler
  val = digitalRead(inPin0);  // read input value
  if (val == HIGH) {         // check if the input is HIGH (button released)
    if(pushed) {
      pushed = false;
      Serial.println("Button0 Released");
      toggle();
    }
  } else {
    if(!pushed) {
      pushed = true;
      Serial.println("Button0 Pushed");
    }
  }
  
}



I've added the int inPin1 and inPin2 for the 2 extra buttons, but I don't know where to go from there. I would love some help on this, as I am new and have little experience programming. Thanks!!

PaulS

You have this code now:
Code: [Select]
// button0 handler
 val = digitalRead(inPin0);  // read input value
 if (val == HIGH) {         // check if the input is HIGH (button released)


How is the button wired up? Generally, buttons are wired so that the pin goes HIGH when the button is pushed, and LOW when released.

You will eventually have 3 push buttons - NoA, NoB, and Toggle.

When neither NoA or NoB is pushed, Toggle will turn A on and B off on one press, and A off and B on on the next press, right?

When NoA is pressed, Toggle will turn B on, then B off, right?
When NoB is pressed, Toggle will turn A on, then A off, right?

What happens when both NoA and NoB are pressed? What does Toggle do then?

If NoA cancels NoB, and NoB cancels NoA, then you have these states:

canToggleA = true
canToggleB = true
First press of Toggle sets aState to HIGH and bState to LOW, and writes aState to pinA and bState to pinB
Subsequent presses of Toggle set aState to !aState and bState to !bState, and writes aState to pinA and bState to pinB

canToggleA = false
canToggleB = true
First press of Toggle sets aState to LOW and bState to HIGH, and writes aState to pinA and bState to pinB
Subsequent presses of Toggle set bState to !bState, and writes bState to pinB

canToggleA = true
canToggleB = false
First press of Toggle sets aState to HIGH and bState to LOW, and writes aState to pinA and bState to pinB
Subsequent presses of Toggle set aState to !aState, and writes aState to pinA

The things you need to keep track of, then, are whether a can be toggled (determined when A is pressed), whether B can be toggled (determined when B is pressed), and how many times Toggle has been pressed (reset when A or B is pressed).

This should be simple to convert into code. If not, more help can be given, but you'll learn a lot more if you try to make the changes yourself, first.
You already toggle LEDs A and B, ignoring whether buttons A or B was pressed. In the Toggle block, you simply need to look at whether A's state should change, or not, and whether B's state should change, or not.

mgbnut

You're on the right track. To clarify, I am doing this project to control the "go" signal on 2 labeling machines. They need a contact closure for Go, and give a closure for if the system is down. So I need 1 button to toggle the state of 2 signals, (the leds) and 2 more buttons to control the 'system down' for each machine. When the main button (button0) is pushed, the LED should come on for 1 second and turn off.  When either of the 'system down' buttons (button1, button2) are pushed, the corresponding LED should not light, and the opposite LED should get all the attention. If both button1 and button2 are pushed, neither should light. I think that sums it up. What do you think? Thanks for your quick response, by the way!

PaulS

#3
Jan 05, 2010, 01:37 am Last Edit: Jan 05, 2010, 01:39 am by PaulS Reason: 1
The system down buttons are what I was referring to as buttonA and buttonB. If both can be pressed (i.e. system A and system B can both be down, then the only difference to what I initially wrote is that pressing button A does not affect that status of button B (i.e. does not "unpress" button B) and pressing button A does not affect the status of button A.

In loop, add a block of code before the existing button state code to see if button A has been pressed. If it has, change the value of canToogleA to !canToggleA (initially set to true).

Add another block to see if button B has been pressed. If it has, change the value of canToggleB to !canToggleB (also initially set to true).

The canToggleA and canToggleB variables are bool's, by the way.

In the toggle function, just add an if test (if(canToggleA) or if(canToggleB)) in front of the calls to green and red.

Add an else clause after each if, to turn call green or red with false.

Code: [Select]
if(canToggleA)
  green(!greenState);
else
  green(false);

mgbnut

Thanks for your reply, i'll look at it and get back to you. To answer your question, the switch iswired as the first line says:

//Circuit: Switch to Pin2, 10k resistor to Pin2, switch to ground.

Not to be rude, i just wanted to copy/paste it. the other 2 switches are wired like it right now, but to pins 5 and 8.

Thanks again!

mgbnut

OK, I'm still rather clueless. It looks to me like I should put something in void setup about the state of the button1 and button 2.  Is the block of code at the bottom the block that you suggested to be added in loop? OK Maybe it's too much at one time. To start, how do I make it so the LED turns on for 1 second, then off, instead of on until the button is pushed again? After that we can address the others. Can you stick with me for awhile on this? I really value your help.

PaulS

The code to initialize everything goes either before the startup function, when the declaration and initialization is performed with one statement:

Code: [Select]
int button1Pin = 5;
bool isOneAvailable = false;


or it goes in setup:

Code: [Select]
void setup()
{
   [glow]pinMode(button1Pin, INPUT);[/glow]
}


As for how to make the LED light up for one second and then turn off, there are two ways to do it. The simple way:

Code: [Select]
digitalWrite(led1Pin, HIGH);  // Turn the LED on
delay(1000);  // Wait for one second
digitalWrite(led1Pin, LOW);  // Turn the LED off


The advantage of this code is that it's straightforward and easy to understand. The disadvantage is that the Arduino can do nothing else while the LED is lit. Button presses are ignored, incoming serial data backs up.

The way around this is to note when the LED was turned on, and check the time every time through loop, and turn the LED off when enough time has passed.

Code: [Select]
unsigned long onTime;
int onDuration = 1000;
bool ledOn = false;

void loop()
{
   if(!ledOn)
   {
      int btnState = digitalRead(buttonPin);
      if(btnState == HIGH)
      {
         digitalWrite(ledPin, HIGH); // Turn LED on
         onTime = millis();  // Check the time
         ledOn = true; // Record that the LED is on
      }
   }
   else // The LED is on
   {
       unsigned long now = millis();
       if(now - onTime > onDuration) // Has the LED been on long enough
       {
           // It has. Turn it off
           digitalWrite(ledPin, LOW);
           ledOn = false;
       }
   }
}


While this code is a lot longer, it should be relatively easy to understand and expand upon. The millis function returns the number of milliseconds that have elapsed since the Arduino was started. Everything is measured relative to that event.

If the LED is not on, and a button was pushed (any event can be used) to indicate that the LED should be turned on, the LED is turned on, and when that happened is stored.

On each pass through loop, whether the LED is on, or not, is checked. If it is, the current time is recorded, and compared against the previous time.

If now is sufficiently later than then, the LED is turned off.

Don't try to integrate this change into the existing sketch. Create a new sketch, and play around with different intervals, and activation methods. Try expanding the concept so that the light turns on automatically, and stays on for 5 seconds, then goes off for 2 seconds, and repeats the on 5/off 2 cycle.

Don't worry about feeling overwhelmed. There is a lot to learn, but it'll become easier as you learn.

Go Up