3 digit counter

I'm trying to create 3 digit counter but something is not right.
This is my code:

#include <SPI.h>
#include <EEPROM.h>


// Defining pins and their name for better usage
// Buttons
#define increaseButtonPin  4
#define decreaseButtonPin  3
#define limitButtonPin  2

// Feedback
#define buzzer 7
#define ledGreen 0
#define ledRed 1

// DATA
#define PIN_DATA 11
#define PIN_CLOCK 9
#define PIN_LATCH 10

// Prototypes
void update_shift_reg(byte output); // Byte num to displays
void display(int *num);             // Displays number on the 7-segment displays

void setup()
{
 // Shift register
 pinMode(PIN_DATA, OUTPUT);
 pinMode(PIN_CLOCK, OUTPUT);
 pinMode(PIN_LATCH, OUTPUT);

 // Feedback
 pinMode(increaseButtonPin, INPUT);
 pinMode(decreaseButtonPin, INPUT);
 pinMode(limitButtonPin, INPUT);

 // Initialize LEDs and buzzer
 pinMode(buzzer, OUTPUT);
 pinMode(ledGreen, OUTPUT);
 pinMode(ledRed, OUTPUT);

 // Set LEDs and buzzer to low initially
 digitalWrite(ledGreen, LOW);
 digitalWrite(ledRed, LOW);
 digitalWrite(buzzer, LOW);
}

void loop()
{
 // Reads value from the memory
 int num = EEPROM.read(1);
 int limit = EEPROM.read(2);

 // Read button states
 int increaseButtonState = digitalRead(increaseButtonPin);
 int decreaseButtonState = digitalRead(decreaseButtonPin);
 int limitButtonState = digitalRead(limitButtonPin);

 if (increaseButtonState == HIGH)
 {
   num ++;
   display(&num);// Increment the number and display it
   digitalWrite(ledGreen, HIGH); // Perform feedback actions (LED, buzzer)
   tone(buzzer, 100);
   delay(50);
   noTone(buzzer);
   display(&num);
   delay(50);
   display(&num);
   delay(50);
   display(&num);
   delay(50);
   display(&num);
   delay(50);
   display(&num);
   delay(50);
   display(&num);

   int count = 0;//this part will be used for increasing number on dispaly by 10
   while(digitalRead(increaseButtonPin) == HIGH){ //Code for increasing the number with special conditions
     count++;
     display(&num);
     if( count >= 1000  ){
       num += 9;
       count = 0;
       display(&num);
       break;
     }
   }
 }

 if (decreaseButtonState == HIGH)
 {
     num --;// Decrease the number and display it
   display(&num);
  
   tone(buzzer, 100); 
   delay(50);
   noTone(buzzer);
   display(&num);
   delay(50);
   display(&num);
   delay(50);
   display(&num);
   delay(50);
   display(&num);
   delay(50);
   display(&num);
   delay(50);
   display(&num);

    int count = 0; // Code for decreasing the number with special conditions
   while(decreaseButtonState == HIGH){
     count++;
     display(&num);
     if( count >= 1000  ){
       num -= 9;
       count = 0;
       display(&num);
       break;
     }
   }
 }

 if (limitButtonState == HIGH)
 {
   limit = num;
 }

 display(&num);// Display the number on the 7-segment displays
 digitalWrite(ledGreen, LOW); // Perform feedback actions (LEDs) 
 digitalWrite(ledRed, LOW);

 if (num > limit)
 {
   num = limit;
   digitalWrite(ledRed, HIGH);
   digitalWrite(buzzer, HIGH);
   delay(300);
   digitalWrite(ledRed, LOW);
   digitalWrite(buzzer, LOW);
 }

 // Store the updated values in EEPROM memory
 EEPROM.update(1, num);
 EEPROM.update(2, limit);
}

void update_shift_reg(byte output)
{
 digitalWrite(PIN_LATCH, LOW);
 shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, output);
 digitalWrite(PIN_LATCH, HIGH);
}

void display(int *num)
{
 byte ones = *num % 10;
 byte tens = (*num / 10) % 10;
 byte hundreds = (*num / 100) % 10;

 byte _data = B00000000;
 update_shift_reg(_data);
 _data = _data | B00000001;
 _data = _data | (ones << 3);
 update_shift_reg(_data);

 _data = B00000000;
 update_shift_reg(_data);
 _data = _data | B00000010;
 _data = _data | (tens << 3);
 update_shift_reg(_data);

 _data = B00000000;
 update_shift_reg(_data);
 _data = _data | B00000100;
 _data = _data | (hundreds << 3);
 update_shift_reg(_data);
}


Can you find the problem?

Forget that useless Fritzing diagram. Please post a proper schematic (hand drawn is fine).

1 Like

Welcome to the forum

That is a very inadequate description of a problem. What should the code do ? What does the code actually do ?

So here is a schematic:



My friend sad that it meant to be counter, but I realy can't understand what actually this code do. I like to create a counter, which has 3 digits and 3 buttons (increse +1, decrese -1, reset 000) How I can do that if myprograming skills in this area are so poor :frowning:

you can look at the schematic for the multifunction shield (corrected link) to see how the 7 segments displays should be wired.

since each display requires at least 7 pins plus a ground, they are typically multiplexed. what this means is that the pins driving the segments for all displays are set and one display is turned on. so there's a sequence when each display is driven round robin.

and in your case, there needs to be code to shift the bits out that drive both the segments and the enables for each digit

the foreground code set the values for each display and some background processing (e.g. interrupt) processes one digit each iteration, reading the digit value, determining what segments to turn-on, turn on the display for that digit and then pause. when done at 50Hz, our eyes done see any flicker

1 Like

It would be much better to start with a display that doesn't require so much support code.

The schematic is missing the chip designations.

Do you know how to write code to create simple counter based on my schematic and circuit? If it takes few minutes for you, I was sooo happy, because I'm trying to make it work more than 5 hours using chatgpt, google, youtube and other stuff :frowning:
here is link to my project Login | Tinkercad

it's more than a few minutes

but i think you need to fix your wiring first.

bear in mind, each segment needs a resistor otherwise the LED will be damaged

1 Like

A good start would be to ask your friend for the code to display an arbitrary number.

If you are using an UNO, avoid using pins 0 and 1 because that can interfere with uploading code, and you will not be able to use Serial for debugging.

Are you using common cathode LEDs? Your code seems to imply that the common connection for the LED needs a HIGH from the 74HC595 to turn on, which would be common anode, and will not work directly from a CD4511.

Your display() function very rapidly flashes the ones and tens digits, likely so fast that you will never see anything unless you are in a dark room, then leaves the hundreds digit on. When multiplexing a three digit display, each digit should be on approximately 1/3 of the time, and as @gcjr mentioned you need to cycle through all three digits at least 50 times per seconds so that the display does not appear to blink/flicker.

2 Likes

here's the schematic from the Multifunction shield that also uses a multiplexed display and shifter registers. you can find the code for it on the Hackatronincs page. but the OP might be better of just getting a Multifunction shield which has the display, LEDs, buttons and buzzer

1 Like

Hello, almost 10 hours straight I'm trying to finish the simple counter project (with 3 buttons - increase, decrease and reset) Check my project please and find the mistakes:
LINKhttps://www.tinkercad.com/things/ilvROdG18Nn-4digitcounteraos/editel?returnTo=%2Fdashboard%3Ftype%3Dcircuits%26collection%3Ddesigns

Please post real material here, not links.

Sorry for that. I'm new on tinkercad so I have a lot of problems with my project. Via link everyone can see schematic, circuit, code stc. Everyone can edit it so it's simplier than trying to understand someone experienced advice because I have no clue how to understand them :slight_smile:

const int greenled = 5;  // Connected to green LED
const int redled = 6;  // Connected to red LED
const int buttonIncreasePin = 2;
const int buttonDecreasePin = 3;
const int buttonResetPin = 4;
const int piezoPin = 7;
const int shiftRegisterClockPin = 9;
const int ljOutputRegisterClockPin = 10;
const int shiftRegisterInputPin = 11;

// Other global variables
int currentValue = 0;  // The current value displayed on the 7-segment display

void setup() {
  Serial.begin(9600);const int greenled = 5;  // Connected to green LED
const int redled = 6;  // Connected to red LED
const int buttonIncreasePin = 2;
const int buttonDecreasePin = 3;
const int buttonResetPin = 4;
const int piezoPin = 7;
const int shiftRegisterClockPin = 9;
const int ljOutputRegisterClockPin = 10;
const int shiftRegisterInputPin = 11;

// Other global variables
int currentValue = 0;  // The current value displayed on the 7-segment display

void setup() {
  Serial.begin(9600);
  // Initialize pins
  pinMode(greenled, OUTPUT);
  pinMode(redled, OUTPUT);
  pinMode(buttonIncreasePin, INPUT_PULLUP);
  pinMode(buttonDecreasePin, INPUT_PULLUP);
  pinMode(buttonResetPin, INPUT_PULLUP);
  pinMode(piezoPin, OUTPUT);
  pinMode(shiftRegisterClockPin, OUTPUT);
  pinMode(ljOutputRegisterClockPin, OUTPUT);
  pinMode(shiftRegisterInputPin, OUTPUT);

  // Initial display update
  updateDisplay();
}

void loop() {
   delay(1000);
  // Read button states
bool increaseButtonState = digitalRead(buttonIncreasePin);
bool decreaseButtonState = digitalRead(buttonDecreasePin);
bool resetButtonState = digitalRead(buttonResetPin);
  // Handle button presses
  if (increaseButtonState) {
    currentValue++;
  } else if (decreaseButtonState) {
    if (currentValue == 0){
      currentValue = 999;
    }
    else
    currentValue--;
  } else if (resetButtonState) {
    currentValue = 0;
  }

  // Update 7-segment display using shift register
  updateDisplay();

  // Output the current value to the serial monitor (for debugging)
  Serial.println(currentValue);

  // Add your additional logic or actions here as needed
}

void updateDisplay() {
  // Ensure the value is between 0 and 999
  currentValue = constrain(currentValue, 0, 999);

  int digit1, digit2, digit3;
  
  if (currentValue < 10) {
    digit3 = currentValue % 10;
    digit2 = 0;
    digit1 = 0;
  } else if (currentValue < 100) {
    digit3 = currentValue % 10;
    digit2 = (currentValue / 10) % 10;
    digit1 = 0;
  } else {
    digit3 = currentValue % 10;
    digit2 = (currentValue / 10) % 10;
    digit1 = (currentValue / 100) % 10;
  }

  // Print the values to Serial Monitor
  Serial.print("Digit1: ");
  Serial.print(digit1);
  Serial.print("  Digit2: ");
  Serial.print(digit2);
  Serial.print("  Digit3: ");
  Serial.println(digit3);

  // Send each digit to the shift register in reverse order
  shiftOut(shiftRegisterInputPin, shiftRegisterClockPin, LSBFIRST, digit1);
  shiftOut(shiftRegisterInputPin, shiftRegisterClockPin, LSBFIRST, digit2);
  shiftOut(shiftRegisterInputPin, shiftRegisterClockPin, LSBFIRST, digit3);

  // Pulse the latch (output register clock) to update the display
  digitalWrite(ljOutputRegisterClockPin, HIGH);
  digitalWrite(ljOutputRegisterClockPin, LOW);
}
  // Initialize pins
  pinMode(greenled, OUTPUT);
  pinMode(redled, OUTPUT);
  pinMode(buttonIncreasePin, INPUT_PULLUP);
  pinMode(buttonDecreasePin, INPUT_PULLUP);
  pinMode(buttonResetPin, INPUT_PULLUP);
  pinMode(piezoPin, OUTPUT);
  pinMode(shiftRegisterClockPin, OUTPUT);
  pinMode(ljOutputRegisterClockPin, OUTPUT);
  pinMode(shiftRegisterInputPin, OUTPUT);

  // Initial display update
  updateDisplay();
}

void loop() {
   delay(1000);
  // Read button states
bool increaseButtonState = digitalRead(buttonIncreasePin);
bool decreaseButtonState = digitalRead(buttonDecreasePin);
bool resetButtonState = digitalRead(buttonResetPin);
  // Handle button presses
  if (increaseButtonState) {
    currentValue++;
  } else if (decreaseButtonState) {
    if (currentValue == 0){
      currentValue = 999;
    }
    else
    currentValue--;
  } else if (resetButtonState) {
    currentValue = 0;
  }

  // Update 7-segment display using shift register
  updateDisplay();

  // Output the current value to the serial monitor (for debugging)
  Serial.println(currentValue);

  // Add your additional logic or actions here as needed
}

void updateDisplay() {
  // Ensure the value is between 0 and 999
  currentValue = constrain(currentValue, 0, 999);

  int digit1, digit2, digit3;
  
  if (currentValue < 10) {
    digit3 = currentValue % 10;
    digit2 = 0;
    digit1 = 0;
  } else if (currentValue < 100) {
    digit3 = currentValue % 10;
    digit2 = (currentValue / 10) % 10;
    digit1 = 0;
  } else {
    digit3 = currentValue % 10;
    digit2 = (currentValue / 10) % 10;
    digit1 = (currentValue / 100) % 10;
  }

  // Print the values to Serial Monitor
  Serial.print("Digit1: ");
  Serial.print(digit1);
  Serial.print("  Digit2: ");
  Serial.print(digit2);
  Serial.print("  Digit3: ");
  Serial.println(digit3);

  // Send each digit to the shift register in reverse order
  shiftOut(shiftRegisterInputPin, shiftRegisterClockPin, LSBFIRST, digit1);
  shiftOut(shiftRegisterInputPin, shiftRegisterClockPin, LSBFIRST, digit2);
  shiftOut(shiftRegisterInputPin, shiftRegisterClockPin, LSBFIRST, digit3);

  // Pulse the latch (output register clock) to update the display
  digitalWrite(ljOutputRegisterClockPin, HIGH);
  digitalWrite(ljOutputRegisterClockPin, LOW);
}`Попередньо форматований текст`
![Screenshot_2|684x500](upload://AlMRenj2SNV2zLrBLT1OG8CJlsB.png)
![Screenshot_3|690x470](upload://8HyRpBXC6cNoIVFR12F3XlipTfI.png)


That's not the way members are adviced.

That's not the way forum works. This is not a private clininc fixing Your priavte matters. The goal is that other members can search and find the replies given to You.

The forum idea is to help members learn and grow in programming Arduino controllers.

That's bad but no helper will try to guess what the problems are.

3 Likes

Have you actually build this circuit, or has it only been simulated in tinkercad? Personally, I am not signing up for a TinkerCad account just so I can see the project.

Do the LEDs display anything? You never answered my questions from the original post.

Sorry for not replying in the previous post, I apply some advices from your message to my code actualy, I liked the message almost instantly when you send it. I built the scheme myself, maybe I made a mistake. Displays should show the number that results from button interaction, buttons can increase the number by 1, decrease by 1, or reset to 0

I have merged your cross-posts @gpdk45.

Cross-posting is against the Arduino forum rules. The reason is that duplicate posts can waste the time of the people trying to help. Someone might spend a lot of time investigating and writing a detailed answer on one topic, without knowing that someone else already did the same in the other topic.

Repeated cross-posting can result in a suspension from the forum.

In the future, please only create one topic for each distinct subject matter. This is basic forum etiquette, as explained in the "How to get the best out of this forum" guide. It contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

1 Like