Sparkfun 4 Digit Display - Button Counter

Discussion in 'Embedded Systems and Microcontrollers' started by Alex Jurtan, Dec 14, 2015.

  1. Alex Jurtan

    Thread Starter New Member

    Jul 14, 2015
    14
    0
    Hi,
    I have been trying to make a simple Pushbutton counter that adds up everytime a button is pressed.
    I am using the SparkFun 7 Segment serial display and a simple push button. https://www.sparkfun.com/products/11442

    I did not find anything similar in their example library, just tried to follow a tutorial online but it uses different hardware.
    http://missionduke.com/wordpress/2011/05/arduino-button-press-counter/

    The tutorial kinda works but the numbers appear randomly on the screen, meaning it does not count 0001,0002,0003,0004,0005... It counts 0100, 0002, 0300, 0004, 0500, ....
    So it is a little bit confused.

    If anyone can recommend a good example or an idea how to make it simply work. Appreciated a lot!!!
     
  2. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    o you want to build new or want to work on it?
    i have made using pic16f877a
     
  3. Alex Jurtan

    Thread Starter New Member

    Jul 14, 2015
    14
    0
    Hi RRITESH,

    I basically want to hook up the display and button to my arduino and have it working :)
    On the arduino I have a stepper motor running that moves a mechanism and I want to count with a button how many times this mechanism moves.
    I think using the pic16f877a is not really necessary, if I can make it work with the resources I have.

    Thanks!
     
  4. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    Code (C):
    1. #include <htc.h>
    2. #include <stdio.h>
    3. __CONFIG( BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
    4. //LVP_OFF&
    5. #define _XTAL_FREQ 20000000
    6.  
    7. char data[13]={  0b01111110,0b00010010,0b10111100,0b10110110,0b11010010,0b11100110,0b11101110, 0b00110010,0XFF,0b11110110};
    8. main()
    9.     {
    10.     TRISB = 0X00 ;
    11.     TRISC = 0B00000011 ;
    12. TRISA = 0xff ;
    13. ADCON1=0b00000000;
    14. ADCON0=0b10000001;//000 = channel 0, (RA0/AN0)
    15.     ADIF=0;
    16.     ADIE=1;
    17.     PEIE=1;
    18. unsigned int a;
    19. unsigned int c;
    20. unsigned char d1;
    21. unsigned char d2;
    22.  
    23.  
    24. unsigned int div;
    25. unsigned int rem;
    26.  
    27. PORTB=0x00;
    28. while(1){
    29. //d2=eeprom_read(0x00);
    30. //d1=eeprom_read(0x01);
    31. //a=d2;
    32. //a=a<<8;
    33. //a=a+d1;
    34. //c=a;
    35.  
    36.  
    37.  
    38.  
    39.     //GIE=1;
    40.  
    41.     __delay_us(10);
    42. GO_DONE=1;
    43.     __delay_us(10);
    44.  
    45. //c=ADRES;
    46.  
    47. c=0b00000011;
    48.  
    49.  
    50.  
    51. //PORTC=0b10000000;
    52. RC4=1;
    53. RC3=1;
    54. rem = c%10;
    55. c=c/10;
    56. PORTB=data[rem];
    57.  
    58. __delay_ms(20);
    59. PORTB=0x00;
    60. //PORTC=0b01000000;
    61. RC4=1;
    62. RC3=1;
    63. rem=c%10;
    64. PORTB=data[1];
    65. __delay_ms(20);
    66.  
    67. PORTB=0x00;
    68. /*
    69. c=c/10;
    70. PORTC=0b00100000;
    71. rem=c%10;    
    72.  
    73. PORTB=data[rem];
    74. __delay_ms(8);
    75. PORTB=0x00;*/
    76.     }
    77.     }
    78.  
    79.  
    80. /*
    81. if(RC0==1){
    82. __delay_ms(100);
    83. a=a+1;
    84.  
    85. d1=a;
    86. d2=a>>8;
    87. eeprom_write(0x00, d2);
    88. eeprom_write(0x01, d1);
    89. if(a>999){
    90. a=0;
    91. }
    92.  
    93. }
    94.  
    95.   if(RC1==1){
    96. __delay_ms(100);
    97. a=a-1;
    98. if(a>999){
    99. a=0;
    100. }
    101. d1=a;
    102. d2=a>>8;
    103.  
    104. eeprom_write(0x00, d2);
    105. eeprom_write(0x01, d1);
    106. }
    107. */
     
    Last edited: Dec 14, 2015
  5. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    o you understand the code?
     
  6. Alex Jurtan

    Thread Starter New Member

    Jul 14, 2015
    14
    0
    No not really. It doesn't look like an arduino code to me...
    Where do I say the pin of the button and display?
     
  7. nerdegutta

    Moderator

    Dec 15, 2009
    2,515
    785
    Why don't you use code-tags?
     
  8. nerdegutta

    Moderator

    Dec 15, 2009
    2,515
    785
    It looks like code for MPLAB X. The XC compiler....
     
  9. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    see..

    1. Code (C):
      1. if(RC0==1){
      2. __delay_ms(100);
      3. a=a+1;
      4. d1=a;
      5. d2=a>>8;
      6.  
      7. if(a>999){
      8. a=0;
      9. }
      10. }
      11.   if(RC1==1){
      12. __delay_ms(100);
      13. a=a-1;
      14. if(a>999){
      15. a=0;
      16. }
      17. d1=a;
      18. d2=a>>8;
      19.  
      20. }
     
  10. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    you can guess from these part that
    a=a+1 and a=a-1
    are use to store value.
    let a ==0
    then if we press switch it will increment a=1
    again a=2
     
  11. Alex Jurtan

    Thread Starter New Member

    Jul 14, 2015
    14
    0
    Hi RRITESH,

    Thank you for the explanation. I do understand how it counts up.
    But I have no idea how to implement this in an arduino code and make it work with the display.

    This is the code I have at the moment. I used the Stepper example file and added the code from the tutorial I did.
    But as mentioned it is confused displaying it correctly.

    Code (C):
    1.  
    2. /*
    3. Stepper Motor Control - one revolution
    4.  
    5. This program drives a unipolar or bipolar stepper motor.
    6. The motor is attached to digital pins 8 - 11 of the Arduino.
    7.  
    8. The motor should revolve one revolution in one direction, then
    9. one revolution in the other direction.
    10.  
    11.  
    12. Created 11 Mar. 2007
    13. Modified 30 Nov. 2009
    14. by Tom Igoe
    15.  
    16. */
    17. #include <SoftwareSerial.h>  //for software serial communication
    18. #include <Stepper.h>
    19.  
    20.  
    21. #define txPin 5  //change to your serial port on Arduino board
    22. #define rxPin 6  //not used but is required
    23.  
    24.  
    25. SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);
    26. int buttonPressCount;
    27.  
    28. const int  buttonPin = 3;    //the pin that the pushbutton is attached to
    29.  
    30. int buttonPushCounter = 0;   //counter for the number of button presses
    31. int buttonState = 0;         //current state of the button
    32. int lastButtonState = 0;     //previous state of the button
    33.  
    34.  
    35. const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
    36. // for your motor
    37.  
    38. // initialize the stepper library on pins 8 through 11:
    39. Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
    40.  
    41. void setup() {
    42.   // set the speed at 60 rpm:
    43.   myStepper.setSpeed(225);
    44.   pinMode(buttonPin, INPUT);  //initialize the button pin as a input
    45.   // initialize the serial port:
    46.   Serial.begin(9600);
    47.  
    48.    pinMode(txPin, OUTPUT);
    49. //the following resets the board, changes the brightness to 100%, and sets the board to '0000':
    50. mySerial.begin(9600);
    51. mySerial.print(0x7A); //special character
    52. mySerial.print(0x00); //set brightness to full
    53. mySerial.print(0x76); //reset board
    54. mySerial.print(0); //send '0' character
    55. mySerial.print(0); //send '0' character
    56. mySerial.print(0); //send '0' character
    57. mySerial.print(0); //send '0' character
    58. }
    59.  
    60. void loop() {
    61.   // step one revolution  in one direction:
    62.   Serial.println("clockwise");
    63.   myStepper.step(stepsPerRevolution);
    64.  
    65.  
    66. buttonState = digitalRead(buttonPin);  //read the pushbutton input pin
    67.  
    68.   // compare the buttonState to its previous state
    69.   if (buttonState != lastButtonState) {
    70.     // if the state has changed, increment the counter
    71.     if (buttonState == HIGH) {
    72.       // if the current state is HIGH then the button
    73.       // went from off to on:
    74.       buttonPushCounter++;
    75.    
    76.       Serial.print("number of button pushes:  ");
    77.       Serial.println(buttonPushCounter, DEC);
    78.       updateDisplay(buttonPushCounter);  //function to update the display 'requires button press count'
    79.    
    80.    
    81.     }
    82.  
    83.   }
    84.   lastButtonState = buttonState;  // save the current state as the last state, for next time through the loop
    85. }
    86.  
    87.  
    88. void updateDisplay(int buttonPushCounter){
    89. String intString = String(buttonPushCounter);  //changes integer to a string
    90. char displayChars[4];  //create array to hold the four numbers
    91. int stringLength = intString.length();  //get length of the string
    92. //the following will determine if the button press count variable has 1, 2, 3, or 4 numbers in it
    93. //and will fill the empty spaces with '0'. so if the button press count variable is '29' it will end up being '0029':
    94. if(stringLength == 4){
    95.   displayChars[0] = intString.charAt(0);
    96.   displayChars[1] = intString.charAt(1);
    97.   displayChars[2] = intString.charAt(2);
    98.   displayChars[3] = intString.charAt(3);
    99. }else if(stringLength == 3){
    100.   displayChars[0] = 0;
    101.   displayChars[1] = intString.charAt(0);
    102.   displayChars[2] = intString.charAt(1);
    103.   displayChars[3] = intString.charAt(2);
    104. }else if(stringLength == 2){
    105.   displayChars[0] = 0;
    106.   displayChars[1] = 0;
    107.   displayChars[2] = intString.charAt(0);
    108.   displayChars[3] = intString.charAt(1);
    109. }else if(stringLength == 1){
    110.   displayChars[0] = 0;
    111.   displayChars[1] = 0;
    112.   displayChars[2] = 0;
    113.   displayChars[3] = intString.charAt(0);
    114. }
    115. mySerial.print(0x76); //Reset board
    116. mySerial.print(0x76); //Reset board
    117. mySerial.print(displayChars[0]); //Send '0' character
    118. mySerial.print(displayChars[1]); //Send '0' character
    119. mySerial.print(displayChars[2]); //Send '0' character
    120. mySerial.print(displayChars[3]); //Send '0' character
    121.  
    122. delay(100); //this will make it so you don't get double counts. you could also use this to avoid someone pressing the button repeatedly 'for fun!'
    123.  
    124. }
    125.  
    Mod edit: Added C to code tags
     
    Last edited by a moderator: Dec 16, 2015
  12. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    2,804
    832
    It doesn't look like you are debouncing your button input. A push button actually goes high and low many times in the first milliseconds of a press.
    You need to "debounce" the input. Here is a routine which uses interrupts to debounce a button. It is written in Arduino C++, but the logic might help you understand how to debouce an inout.
    Code (C):
    1.  
    2. // Button input related values
    3. static const byte BUTTON_PIN = 2;
    4. static const int  STATE_NORMAL = 0; // no button activity
    5. static const int  STATE_SHORT  = 1; // short button press
    6. static const int  STATE_LONG  = 2; // long button press
    7. volatile int resultButton = 0; // global value set by checkButton()
    8.  
    9. //*****************************************************************
    10. void setup() {
    11.   Serial.begin(9600);
    12.  
    13.   // initialize input button pins
    14.   Serial.println("Initializing Button pin");
    15.   pinMode(BUTTON_PIN, INPUT_PULLUP);
    16.   attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), checkButton, CHANGE);
    17.   Serial.println("Button pin initialized");
    18.  
    19. }
    20.  
    21. //*****************************************************************
    22. void loop() {
    23.   static unsigned int buttonPushCounter=0;
    24.   // if the user presses a button, ...
    25.   if (((resultButton & STATE_SHORT) == STATE_SHORT ) ) {
    26.   Serial.println("Button press detected");
    27.   buttonPushCounter++;
    28.   resultButton = STATE_NORMAL; // reset the button state
    29.   }
    30. }
    31.  
    32. //*****************************************************************
    33. void checkButton() {
    34.   /*
    35.   * This function implements software debouncing for a two-state button.
    36.   * It responds to a short press and a long press and identifies between
    37.   * the two states. Your sketch can continue processing while the button
    38.   * function is driven by pin changes.
    39.   */
    40.  
    41.   const unsigned long DEBOUNCE_DELTA = 30ul; // debounce time
    42.   static int lastButtonStatus = HIGH; // HIGH indicates the button is NOT pressed
    43.   int buttonStatus;  // button atate Pressed/LOW; Open/HIGH
    44.   static unsigned long shortTime = 0ul; // future times to determine is button has been pressed
    45.   boolean Released = true, Transition = false; // various button states
    46.   boolean timeoutShort = false, // flags for the state of the presses
    47.  
    48.   buttonStatus = digitalRead(BUTTON_PIN); // read the button state on the pin "BUTTON_PIN"
    49.   timeoutShort = (millis() > shortTime); // calculate the current time states for the button presses
    50.  
    51.   if (buttonStatus != lastButtonStatus) { // reset the timeouts if the button state changed
    52.   shortTime = millis() + DEBOUNCE_DELTA;
    53.   }
    54.  
    55.   Transition = (buttonStatus != lastButtonStatus); // has the button chnged state
    56.   Released = (Transition && (buttonStatus == HIGH)); // for input pullup circuit
    57.   lastButtonStatus = buttonStatus; // save the button status
    58.  
    59.   if ( ! Transition) { //without a transition, there's no change in inout
    60.   // if there has not been a transition, don't change the previoous result
    61.   resultButton =  STATE_NORMAL | resultButton;
    62.   return;
    63.   }
    64.  
    65.   if (timeoutShort && Released) { // short timeout has occurred (and not long timeout) and button ws just released
    66.   resultButton = STATE_SHORT | resultButton; // ensure the button result reflects a short press
    67.   } else { // else there is no change in status, return the normal state
    68.   resultButton = STATE_NORMAL | resultButton; // with no change in status, ensure no change in button status
    69.   }
    70. }
    71.  
    Mod edit: Added C to code tags
     
    Last edited by a moderator: Dec 16, 2015
  13. shteii01

    AAC Fanatic!

    Feb 19, 2010
    3,388
    497
    buttonPressCount =/= buttonPushCounter
     
  14. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    Hi Alex Jurtan,
    First learn the theory then implement it in digital micro.
    I do understand how it counts up
    See let take a variable that store our value you know char is 8bits an integers are 16bits.
    so, if there is two digit then char is sufficient an if there is 3 or 4 digit then integers will be use.
    so, let char a=0; // a=0 mean the data is initially zero.
    if we will increment it then it will be something like this..
    char a=0b00000000; // 0
    char a=0b00000001;//1
    char a=0b00000010;//2
    char a=0b00000011;//3
    ....
    ..
    .char a=0b00001000;//8
    do you know 8 4 2 1 make bits in 4 bits data??
     
  15. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    But I have no idea how to implement this in an arduino code and make it work with the display.
    I have not use arduino but the procedure will be same with different syntax.
    first light the 7 segment display with simple delay an digital output like show/ispaly 0 1 2 3...
    then we will move forward.
     
  16. Alex Jurtan

    Thread Starter New Member

    Jul 14, 2015
    14
    0
    Hi, Ok I have been reading and trying some things and managed now to have a debounced button that counts the display up 1 every time its pushed. This works perfectly. My next step is now to have a Stepper motor running at the same. I have been trying to make it work with attachinterrupt. But no luck. Does anyone know a way how to have the stepper running continuously while the button can count up numbers?
    Thanks!

    Counter code
    Code (C):
    1.  
    2. #include <SoftwareSerial.h>
    3.  
    4. // These are the Arduino pins required to create a software seiral
    5. //  instance. We'll actually only use the TX pin.
    6. const int softwareTx = 8;
    7. const int softwareRx = 7;
    8.  
    9. const int buttonPin = 2;
    10. int buttonState;
    11. int lastButtonState = LOW;
    12.  
    13. long lastDebounceTime = 0;  // the last time the output pin was toggled
    14. long debounceDelay = 50;    // the debounce time; increase if the output flickers
    15.  
    16.  
    17.  
    18. SoftwareSerial s7s(softwareRx, softwareTx);
    19.  
    20. unsigned int counter = 0;  // This variable will count up to 65k
    21. char tempString[10];  // Will be used with sprintf to create strings
    22.  
    23. void setup(){
    24.  
    25.   pinMode(buttonPin, INPUT);
    26.   // Must begin s7s software serial at the correct baud rate.
    27.   //  The default of the s7s is 9600.
    28.   s7s.begin(9600);
    29. clearDisplay();
    30.  
    31. }
    32.  
    33. void loop(){
    34.   // Magical sprintf creates a string for us to send to the s7s.
    35.   //  The %4d option creates a 4-digit integer.
    36.   sprintf(tempString, "%4d", counter);
    37.  
    38.   // This will output the tempString to the S7S
    39.   s7s.print(tempString);
    40.   setDecimals(0b00001000);  // Sets digit 3 decimal on
    41.  
    42.  
    43. int reading = digitalRead(buttonPin);
    44.  
    45. // If the switch changed, due to noise or pressing:
    46.   if (reading != lastButtonState) {
    47.     // reset the debouncing timer
    48.     lastDebounceTime = millis();
    49.   }
    50.  
    51.   if ((millis() - lastDebounceTime) > debounceDelay) {
    52.     // whatever the reading is at, it's been there for longer
    53.     // than the debounce delay, so take it as the actual current state:
    54.  
    55.     // if the button state has changed:
    56.     if (reading != buttonState) {
    57.       buttonState = reading;
    58.  
    59.       // only toggle the LED if the new button state is HIGH
    60.       if (buttonState == HIGH) {
    61.         counter++;
    62.       }
    63.     }
    64.  
    65. }
    66. lastButtonState = reading;
    67. }
    68.  
    69.  
    70. // Send the clear display command (0x76)
    71. //  This will clear the display and reset the cursor
    72. void clearDisplay()
    73. {
    74.   s7s.write(0x76);  // Clear display command
    75. }
    76.  
    77.  
    78. // Turn on any, none, or all of the decimals.
    79. //  The six lowest bits in the decimals parameter sets a decimal
    80. //  (or colon, or apostrophe) on or off. A 1 indicates on, 0 off.
    81. //  [MSB] (X)(X)(Apos)(Colon)(Digit 4)(Digit 3)(Digit2)(Digit1)
    82. void setDecimals(byte decimals)
    83. {
    84.   s7s.write(0x77);
    85.   s7s.write(decimals);
    86. }

    Attachinterrupt Code
    (This code does not work. On the first button push it counts up 1 and then doesn't react anymore.)
    Code (C):
    1.  
    2.  
    3. #include <SoftwareSerial.h>
    4.  
    5. // These are the Arduino pins required to create a software seiral
    6. //  instance. We'll actually only use the TX pin.
    7. const int softwareTx = 8;
    8. const int softwareRx = 7;
    9.  
    10.  
    11.  
    12. const int buttonPin = 0;
    13. int buttonState;
    14. int lastButtonState = LOW;
    15.  
    16. long lastDebounceTime = 0;  // the last time the output pin was toggled
    17. long debounceDelay = 50;    // the debounce time; increase if the output flickers
    18.  
    19.  
    20.  
    21.  
    22. SoftwareSerial s7s(softwareRx, softwareTx);
    23.  
    24. unsigned int counter = 0;  // This variable will count up to 65k
    25. char tempString[10];  // Will be used with sprintf to create strings
    26.  
    27. void setup(){
    28.   pinMode(buttonPin, INPUT);
    29.   attachInterrupt(buttonPin, count, RISING);
    30.   s7s.begin(9600);
    31. clearDisplay();
    32.  
    33. }
    34.  
    35. void loop(){
    36.   // Magical sprintf creates a string for us to send to the s7s.
    37.   //  The %4d option creates a 4-digit integer.
    38.   sprintf(tempString, "%4d", counter);
    39.  
    40.   // This will output the tempString to the S7S
    41.   s7s.print(tempString);
    42.   setDecimals(0b00001000);  // Sets digit 3 decimal on
    43.  
    44.  
    45.  
    46. }
    47.  
    48. // Send the clear display command (0x76)
    49. //  This will clear the display and reset the cursor
    50. void clearDisplay()
    51. {
    52.   s7s.write(0x76);  // Clear display command
    53. }
    54.  
    55.  
    56. // Turn on any, none, or all of the decimals.
    57. //  The six lowest bits in the decimals parameter sets a decimal
    58. //  (or colon, or apostrophe) on or off. A 1 indicates on, 0 off.
    59. //  [MSB] (X)(X)(Apos)(Colon)(Digit 4)(Digit 3)(Digit2)(Digit1)
    60. void setDecimals(byte decimals)
    61. {
    62.   s7s.write(0x77);
    63.   s7s.write(decimals);
    64. }
    65.  
    66.  
    67. void count() {
    68.  
    69. int reading = digitalRead(buttonPin);
    70.  
    71. // If the switch changed, due to noise or pressing:
    72.   if (reading != lastButtonState) {
    73.     // reset the debouncing timer
    74.     lastDebounceTime = millis();
    75.   }
    76.  
    77.   if ((millis() - lastDebounceTime) > debounceDelay) {
    78.     // whatever the reading is at, it's been there for longer
    79.     // than the debounce delay, so take it as the actual current state:
    80.  
    81.     // if the button state has changed:
    82.     if (reading != buttonState) {
    83.       buttonState = reading;
    84.  
    85.       // only toggle the LED if the new button state is HIGH
    86.       if (buttonState == HIGH) {
    87.         counter++;
    88.       }
    89.     }
    90.  
    91. }
    92. lastButtonState = reading;
    93. }
    Mod edit: Added C to code tags
     
    Last edited by a moderator: Dec 16, 2015
  17. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    2,804
    832
    I have some comments with regard to your attachInterrupt code. Which model Arduino are you using? I suspect that it is the Arduino Uno, given that you only have one hardware serial interface. Many models, including the Uno, can not use digital pin 0 for interrupts. If its not a Micro, Leonardo, Zero or Duo, you need to use a different pin for your button. Pins 2 & 3 are common. Check out the Arduino reference page for attachInterrupt().
     
Loading...