Go Down

Topic: Touchy Program - How do I fix? (Read 1 time) previous topic - next topic

mrmm314

I'm pretty new to programming in C, so I tried to write a program to use with a 7 segment display, and the following is what I came up with.  the only problem is that it is pretty touchy, and doesn't quite do what the button presses should be telling it to do every time, although sometimes it works with 1 to 3 button presses.  Any suggestions would be greatly appreciated.

Code: [Select]
/*While button2 is pressed (HIGH), the program counts
the presses (HIGH) of button, then displays the count
number with a 7 Segment Display*/

//Button Count Variables
int state = LOW;
int lastState = LOW;
int count = 10;

//7 Segment Display Pins
int segF = 4;
int segG = 5;
int segE = 6;
int segD = 7;
int segA = 8;
int segB = 9;
int segC = 10;

//Button Pins
int button = 11;
int button2 = 12;

void setup()
 {
   Serial.begin(9600);
   pinMode(button, INPUT);
   pinMode(button2, INPUT);
   state = digitalRead(button);
   pinMode(segA, OUTPUT);
   pinMode(segB, OUTPUT);
   pinMode(segC, OUTPUT);
   pinMode(segD, OUTPUT);
   pinMode(segE, OUTPUT);
   pinMode(segF, OUTPUT);
   pinMode(segG, OUTPUT);
   
 }

void loop()
 {
   while(digitalRead(button2) == HIGH)
   {
         
   if (state == HIGH && lastState == LOW)
   {
     count++;
   }
   
   lastState = state;
   state = digitalRead(button);
   }
   
   switch (count)
   {
 case 1:
   //Turns on and off the LEDs on the 7seg to display "1"
   digitalWrite(segA, LOW);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, LOW);
   break;
 case 2:
   /*Same as 1, but this displays "2", and so on for the
   rest of these*/
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, LOW);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, LOW);
   digitalWrite(segG, HIGH);
   break;
 case 3:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, HIGH);
   break;
 case 4:
   digitalWrite(segA, LOW);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 5:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, LOW);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 6:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, LOW);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 7:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, LOW);
   break;
 case 8:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 9:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 10:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, LOW);
   break;
 default:
   break;
   }
   
   count = 0;
 }


pluggy

The circuit you have connected to the 'button' pins would help.  Are you using a pulldown resistor ?
http://pluggy.is-a-geek.com/index.html

mrmm314

I have a 10k resistor connected from ground to the button pins, and the buttons connected to 5v, so when it is pressed, it returns (HIGH), and unpressed returns (LOW).

pluggy

Is the intended behaviour that nothing happens until the first button is pressed and then the 2nd button increments the number displayed ? So you have to press both buttons to increment the count (the number displayed ?
http://pluggy.is-a-geek.com/index.html

mrmm314

@pluggy,  Yes.  When the one button is pressed, it goes into the While loop, while it then counts the button presses of the other button.  And when the first button is let go, it should display the number of times I pressed the second button.  But it is very touchy, and only seems to work semi-consistently with 1 to 3.

PaulS

Code: [Select]
while(digitalRead(button2) == HIGH)
   {
   if (state == HIGH && lastState == LOW)
   {
     count++;
   }
   
   lastState = state;
   state = digitalRead(button);
   }

Do you have an idea how many times this while loop gets executed while you are holding the button2 pin switch down? There is no debouncing of either button happening, so the random results you are seeing are not surprising.

mrmm314

I hadn't though about the number of times affecting how it works, but it aside from interference, it shouldn't count any more or less than what I am pressing, right?  I was thinking that a better way of doing this could be to use interrupts, and basically use one button to count, while the second button actually changes the displayed number to the correct number of presses. so that instead of cycling, a desired number of presses could be achieved, and then displayed.

mrmm314

Here is the program rewritten and modified with interrupts.  The first button (interrupt 0) counts how many times it is pressed, and stores that to the variable [glow]countPress[/glow].  Then when the second button (interrupt 1) is pressed, it should display the correct number of presses on the first button.  The buttons do not have to be pressed at the same time at all.
Code: [Select]
int countPress = 0;

//7 Segment Display Pins
int segF = 4;
int segG = 5;
int segE = 6;
int segD = 7;
int segA = 8;
int segB = 9;
int segC = 10;

//Button Pins
int button = 2;
int button2 = 3;

void setup()
 {
   Serial.begin(9600);
   attachInterrupt(0, count, RISING);
   attachInterrupt(1, disp, RISING);
   pinMode(segA, OUTPUT);
   pinMode(segB, OUTPUT);
   pinMode(segC, OUTPUT);
   pinMode(segD, OUTPUT);
   pinMode(segE, OUTPUT);
   pinMode(segF, OUTPUT);
   pinMode(segG, OUTPUT);
   
 }

void loop()
 {
   
 }

void count()
 {
   countPress = ++countPress;
 }

void disp()
 {
   switch (countPress)
   {
 case 1:
   //Turns on and off the LEDs on the 7seg to display "1"
   digitalWrite(segA, LOW);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, LOW);
   break;
 case 2:
   /*Same as 1, but this displays "2", and so on for the
   rest of these*/
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, LOW);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, LOW);
   digitalWrite(segG, HIGH);
   break;
 case 3:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, HIGH);
   break;
 case 4:
   digitalWrite(segA, LOW);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 5:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, LOW);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 6:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, LOW);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 7:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, LOW);
   break;
 case 8:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 9:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 10:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, LOW);
   break;
 default:
   break;
   }
   
   countPress = 0;
 }


PaulS

#8
Nov 20, 2010, 02:18 am Last Edit: Nov 20, 2010, 02:18 am by PaulS Reason: 1
countPress should be declared volatile, so that its value is fetched every time.

Code: [Select]
   countPress = ++countPress;
As opposed to just countPress++;? Why?

disp() does nothing but reset countPress is countPress is greater than 10. Is that reasonable?

Since there is no debouncing of the buttons, a bounce could cause the interrupt to be fired again before the ISR has finished. Since countPress is an integer, it is possible for it to become corrupted if the ISR fires and suspends the ISR that is running.

This couldn't happen if countPress were a byte. The ISR could fire while the ISR is still running, but it wouldn't corrupt countPress.

In disp(), before you turn any segments on, you should turn them all off. Otherwise, displaying 4 after displaying 3 will look like a 9.

Otherwise, it looks good.

Of course, using interrupts to catch humans pressing buttons is silly. The Arduino loops often enough to catch every button press, no matter how quickly a human presses and releases a button. After all, at 16,000,000 instructions a second, you'd have to be awfully darn fast to get a switch pressed and released before the Arduino noticed.

mrmm314

I recently found out about the debounce library, implemented it, and now I have a program that works the way that the interrupt version should have worked, but this doesn't use interrupts.  Here is my code:
Code: [Select]
#include <Bounce.h>

//Button Count Variable
int count = 0;

//7 Segment Display Pins
int segF = 4;
int segG = 5;
int segE = 6;
int segD = 7;
int segA = 8;
int segB = 9;
int segC = 10;

//Button Pins
int button = 11;
int button2 = 12;

//Bounce Objects
Bounce bouncer = Bounce(button, 25);
Bounce bouncer2 = Bounce(button2, 25);

void setup()
 {
   Serial.begin(9600);
   pinMode(button, INPUT);
   pinMode(button2, INPUT);
   pinMode(segA, OUTPUT);
   pinMode(segB, OUTPUT);
   pinMode(segC, OUTPUT);
   pinMode(segD, OUTPUT);
   pinMode(segE, OUTPUT);
   pinMode(segF, OUTPUT);
   pinMode(segG, OUTPUT);
   
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, LOW);
 }

void loop()
 {
   bouncer.update();  //Updates bouncer
   int value = bouncer.risingEdge();
   
   if (value == HIGH)
     {
       count++;
     }
   
   bouncer2.update();  //Updates bouncer2
   int value2 = bouncer2.risingEdge();
   
   if (value2 == HIGH)
   {
   switch (count)
   {
 case 1:
   //Turns on and off the LEDs on the 7seg to display "1"
   digitalWrite(segA, LOW);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, LOW);
   break;
 case 2:
   /*Same as 1, but this displays "2", and so on for the
   rest of these*/
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, LOW);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, LOW);
   digitalWrite(segG, HIGH);
   break;
 case 3:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, HIGH);
   break;
 case 4:
   digitalWrite(segA, LOW);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 5:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, LOW);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 6:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, LOW);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 7:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, LOW);
   digitalWrite(segE, LOW);
   digitalWrite(segF, LOW);
   digitalWrite(segG, LOW);
   break;
 case 8:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 9:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, LOW);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, HIGH);
   break;
 case 10:
   digitalWrite(segA, HIGH);
   digitalWrite(segB, HIGH);
   digitalWrite(segC, HIGH);
   digitalWrite(segD, HIGH);
   digitalWrite(segE, HIGH);
   digitalWrite(segF, HIGH);
   digitalWrite(segG, LOW);
   break;
 default:
   break;
   }
   
   count = 0;
   }
 }

Go Up
 

Quick Reply

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

Note: this post will not display until it's been approved by a moderator.
Name:
Email:

shortcuts: alt+s submit/post or alt+p preview