0

I have a have project of Up Down counter using Arduino with seven segments, in which when I continuously press the push button, the counter moves upward from 0 to 99. When I release the push button, the counter moves downwards from the previous value.

For example: I continuously press the button counter from 0 to 58, then when I release the button, the counter moves backward from 58 to 0.

The problem is that when I simulate the code in Proteus software, the counter starts from 99 because the button is not pressed. But when I press the button the counter moves upward not accurately.

Also the other big issue is that when the button is released, the counter does not move backwards although the counter moves upwards continuously and the button is not working (whether the button is pressed or not).

Here my code and Proteus simulator circuit image.

int num_array_1[10][7] =
  { { 1,1,1,1,1,1,0 }, // 0
  { 0,1,1,0,0,0,0 }, // 1
  { 1,1,0,1,1,0,1 }, // 2
  { 1,1,1,1,0,0,1 }, // 3
  { 0,1,1,0,0,1,1 }, // 4
  { 1,0,1,1,0,1,1 }, // 5
  { 1,0,1,1,1,1,1 }, // 6
  { 1,1,1,0,0,0,0 }, // 7
  { 1,1,1,1,1,1,1 }, // 8
  { 1,1,1,0,0,1,1 }}; // 9
int num_array_2[10][7] =
  { { 1,1,1,1,1,1,0 }, // 0
  { 0,1,1,0,0,0,0 }, // 1
  { 1,1,0,1,1,0,1 }, // 2
  { 1,1,1,1,0,0,1 }, // 3
  { 0,1,1,0,0,1,1 }, // 4
  { 1,0,1,1,0,1,1 }, // 5
  { 1,0,1,1,1,1,1 }, // 6
  { 1,1,1,0,0,0,0 }, // 7
  { 1,1,1,1,1,1,1 }, // 8
  { 1,1,1,0,0,1,1 }}; // 9

const int button = 35;
const int alarm = 50;

//function header
void Num_Write_1(int);
void Num_Write_2(int);

void setup() {
  // set pin modes for Display 1
  pinMode(22, OUTPUT);
  pinMode(23, OUTPUT);
  pinMode(24, OUTPUT);
  pinMode(25, OUTPUT);
  pinMode(26, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(28, OUTPUT);
  // set pin modes for Display 2
  pinMode(40, OUTPUT);
  pinMode(41, OUTPUT);
  pinMode(42, OUTPUT);
  pinMode(43, OUTPUT);
  pinMode(44, OUTPUT);
  pinMode(45, OUTPUT);
  pinMode(46, OUTPUT);
  // set pin for alarm indication
  pinMode(alarm,OUTPUT);
  // set pin for button input
  pinMode(button,INPUT);
  int i = 1;
  int j = 1;
  int counter_1 = 0; // for counter 1
  int counter_2 = 0; // for counter 2
}

void loop() {
  int counter_1; // for counter 1
  int counter_2; // for counter 2
  int button_state = digitalRead(button);
  // check the button state
  //counter loop
  if (button_state == HIGH) {
    // if button is pressed , counter moves Upward(0,1,2,3,....,99)
    boolean start = true;
    while (start) {
      // when button pressed , loop is continuously running
      if (counter_1 == 10) {
        // if counter 1 is value 10
        counter_1 = 0; // reset counter1 to 0
        counter_2 = counter_2 + 1; // counter2 is starting now
        Num_Write_1(counter_1); // display value of counter1
        Num_Write_2(counter_2); // display value of counter2
        button_state = digitalRead(button); // check the button state
        if (button_state == LOW) {
          // if low then condition of while is false
          // button is released, button_state is low
          start = !start; // toggle the while condition true to false
          // which terminate the while loop
        }
      } else {
        counter_1 = counter_1 + 1; // incr. 1 by 1
        Num_Write_1(counter_1); // display value of counter1
        delay(200);
      }
      button_state = digitalRead(button);
      // again check the button state
      // button is released, button_state is low
      while (button_state == LOW) {
        // if low then condition of while is false
        start = !start;
      }
    }
  } else {
    //if button is release , counter moves Downward(56,55,54,...,0)
    Num_Write_1(counter_1); // show previous values on both counters
    Num_Write_2(counter_2); // b/c decr. starts from incremented values
    boolean start = true;
    while (start) {
      // when button release , loop is continuously running
      if (counter_1 == 0) {
        //if counter 1 is value 0
        counter_1 = 9; // reset counter1 to 9
        counter_2 = counter_2 - 1; // counter2 is starting now
        Num_Write_1(counter_1); // display on counter1
        Num_Write_2(counter_2); // display on counter2
        button_state = digitalRead(button); // check the button state
        if (button_state == HIGH) {
          // if high then condition of while is false
          // button is pressed, button_state is high
          start = !start; //toggle the condition
        }
      } else {
        counter_1 = counter_1 - 1; // decr. 1 by 1
        Num_Write_1(counter_1); // display on counter1
        delay(200);
      }
      button_state = digitalRead(button); // again check the button_state
      // if button pressed , button_state goes high
      if (button_state == HIGH) {
        start = !start;
        // toggle the while condition true to false
        // which terminate the while loop
      }
    }
  }
}
// this functions writes values to the sev seg pins for counter1
void Num_Write_1(int number) {
  int pin= 22;
  for (int j=0; j < 7; j++) {
    digitalWrite(pin, num_array_1[number][j]);
    pin++;
  }
}
// this functions writes values to the sev seg pins for counter2
void Num_Write_2(int number) {
  int pin= 40;
  for (int j=0; j < 7; j++) {
    digitalWrite(pin, num_array_2[number][j]);
    pin++;
  }
}

cirduit diagram of counter

If button pressed ----------> logic goes HIGH If button release ----------> logic goes LOW

Please resolve my problem. I have tried for 2 weeks solving this problem but still I'm stuck. Any little advice will be important for me.

  • Your next question should deal with managing switch bouncing. You may get away without such extra code. But you may also get some unexpected results. – st2000 Dec 21 '16 at 21:50
2

I'd throw that code away and start over from scratch; it's overly verbose and needlessly repetitious, which may account for the kinds of errors you are seeing.

A few notes:

• The contents of num_array_1 look identical to those of num_array_2. Ordinarily there is no need to have two copies of the same constant array, so get rid of one or the other.

• It doesn't make sense to use four different lengthy sections of code that do about the same trivial things, incrementing or decrementing a counter, displaying its value, and then doing some kind of switch check. Instead, use one section of code that handles all the cases. See example 1 below.

• In three of those four different sections of code just referred to, in effect you say
if (button_state == LOW) { start = !start; } and in one of them, you say
while (button_state == LOW) { start = !start; }. That statement loops forever if encountered when button_state is LOW.

int counter_1 and int counter_2 declared in setup() are not the same variables as the ones of the same name declared in loop(). If you want them to be the same, declare them at global scope before setup(), and don't declare them within either of setup() or loop().

• As declared in loop(), counter_1 and _2 are automatic local variables, uninitialized and technically of undefined value. See discussion in an answer to “local variable initialized to zero in C” on stackoverflow.

• It doesn't make sense to use two different display-a-digit functions that do about the same thing. Instead, use one function to handle both cases. See example 2 below.

• You can save 126 bytes each of RAM and Flash by storing the ones and zeroes of num_array_1 or _2 packed into bytes. See example 3 below.


Example 1: First, declare int dir, which will be 1 when counting up, and -1 when counting down. To change direction, say dir = -dir;. To step the count, say:

count += dir;
if (dir<0)  dir = 0;
if (dir>99) dir = 99;
showDigit(count/10, 40); // Hi digit ports are 40...46
showDigit(count%10, 22); // Lo digit ports are 22...28

After stepping the counter and showing its digits, you can do your check some kind of switch thing, once in one place instead of spread out in four different places. Note, you could (and should) create symbolic constants that stand for 40 and 22, via an enum like the following, and then use the symbols instead of hardcoded numbers in the showDigit() calls.

enum { hiDigitAt=40, loDigitAt=22};
...
showDigit(count/10, hiDigitAt);
showDigit(count%10, loDigitAt);

Example 2: Your Num_Write_1() and _2 functions are identical except that one says int pin= 22; and the other int pin= 40;. To combine them, you can add a parameter specifying the starting pin number:

void showDigit(byte value, byte basePin) {
  for (byte j=0; j < 7; ++j) {
    digitalWrite(basePin+j, num_array_1[value][j]);
}

Example 3: Instead of using 14 bytes of RAM and 14 bytes of Flash for each entry in your digit-segments-pattern arrays, you can pack the seven ones and zeroes that represent one digit into a single byte. For example, { 0,1,1,0,0,0,0 }, // 1 converts to 0b0110000, // 1. Then use shifts to unpack the bits, as below.

byte digitPats[10] = 
     { 0b1111110, 0b0110000, 0b1101101, 0b1111001, 0b0110011,
       0b1011011, 0b1011111, 0b1110000, 0b1111111, 0b1110011
     };
...
void showDigit(byte value, byte basePin) {
  byte pattern = digitPats[value], bitj;
  for (byte j=0; j < 7; ++j) {
    bitj = (pattern & 64)>>6;
    digitalWrite(basePin+j, bitj);
    pattern *= 2;  // Shift the pattern one bit left
}
1

Your counter variables only have scope within the methods they are declared in. So initializing them in the setup() method will have no effect in other methods.

Instead, declare these variables as global or at least with "file" scope as you did with your array variables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.