Vending Machine with 4-bit display

Hello.

I am having some trouble with my project. It is a vending machine, with a counter and some LED's which display when you can afford a type of soda. Coke=4 presses, Fanta=6 and so... This works fine, but I am also trying to connect a 4-bit 7-segment (7447), and would like the display to show the current presses (the value called buttonPushCounter). The code pasted below only kind of works, but the display shows zero, but you need 2 presses for it to reach 1, and the buttonPushCounter-value is then 3, so the display is always -1 behind the actual value.

The second issue is that whenever we press a item (for example Fanta), the display won't update, but the leds do. I am not sure how to do this. If you want to see how the code works and all I have createda TinkerCAD project below, and you can see the problem for yourself.

Just hit "simulate". The display is replaced by some LED's showing the 4-bit value, you will see that it is behind and will no update until you press the money button again.

Any help is appreciated.

// Vending machine
const int moneyButtonPin =  2;     // button that counts money
const int ColaLEDPin =   3;      // the pin that the LED is attached to
const int FantaLEDPin =   4;      // the pin that the LED is attached to
const int SpriteLEDPin =   5;      // the pin that the LED is attached to
const int ColaButtonPin =   6;     // button for COLA
const int FantaButtonPin =  7;     // button for FANTA
const int SpriteButtonPin = 8;     // button for SPRITE
const int c = 4;             // cola price
const int f = 6;             // fanta price
const int s = 8;             // sprite price
byte displayPin[] = {9,10,11,12};
const byte numPins = 4; // how many leds


// Variables will change:
int buttonPushCounter = 0;    // counter for the number of button presses
int buttonState = 0;          // current state of the button
int lastButtonState = 0;      // previous state of the button
int state;

void setup() {
  pinMode(moneyButtonPin, INPUT);   // initialize the button pin as a input
  pinMode(ColaButtonPin, INPUT);   // initialize Cola-button pin as a input
  pinMode(FantaButtonPin, INPUT);  // initialize Fanta-button pin as a input
  pinMode(SpriteButtonPin, INPUT); // initialize Sprite-button pin as a input
  pinMode(ColaLEDPin, OUTPUT);   // initialize ColaLED pin as a input
  pinMode(FantaLEDPin, OUTPUT);  // initialize FantaLED button pin as a input
  pinMode(SpriteLEDPin, OUTPUT); // initialize SpriteLED button pin as a input
  for(int i = 0; i < numPins; i++) {
  pinMode(displayPin[i], OUTPUT);
    }
}

void loop() {
  String binNumber = String(buttonPushCounter, BIN);
  buttonState = digitalRead(moneyButtonPin);    // read the pushbutton input pin
  if (buttonState != lastButtonState) {   // compare the buttonState to its previous state
  if (buttonState == HIGH) {        // if the state has changed, increment the counter
      buttonPushCounter++;      // if the current state is HIGH then the button went from off to on:
  int binLength = binNumber.length(); 
  if(buttonPushCounter <= 9) {  // if we have less or equal to 9 presses
    for(int i = 0, x = 1; i < binLength; i++, x+=2) { 
      if(binNumber[i] == '0') state = LOW;
      if(binNumber[i] == '1') state = HIGH;
      digitalWrite(displayPin[i] + binLength - x, state);
      }  
    }
  }
    delay(50);    // Delay a little bit to avoid button-bouncing
  }
  lastButtonState = buttonState; //Save button state before reset
  if (buttonPushCounter >= c) {
    digitalWrite(ColaLEDPin, HIGH);//Set ColaLED (Red) HIGH
  } else {
    digitalWrite(ColaLEDPin, LOW);//Set ColaLED (Red) HIGH
  }
  if (buttonPushCounter >= f) {
    digitalWrite(FantaLEDPin, HIGH);//Set ColaLED (Red) HIGH
  } else {
    digitalWrite(FantaLEDPin, LOW);//Set ColaLED (Red) HIGH
  }
  if (buttonPushCounter >= s) {
    digitalWrite(SpriteLEDPin, HIGH);//Set ColaLED (Red) HIGH
  } else {
    digitalWrite(SpriteLEDPin, LOW);//Set ColaLED (Red) LOW
  }
  if (digitalRead(ColaButtonPin) == HIGH) {
      digitalWrite(ColaLEDPin, LOW);
      if(buttonPushCounter >= c){
      buttonPushCounter = buttonPushCounter - c;
      }
      delay(500);
    }
  if (digitalRead(FantaButtonPin) == HIGH) {//Set FantaLED (Yellow) HIGH
      digitalWrite(FantaLEDPin, LOW);//Set FantaLED (Yellow) LOW
      if(buttonPushCounter >= f){
      buttonPushCounter = buttonPushCounter - f;
      }
      delay(500);
    }
  if (digitalRead(SpriteButtonPin) == HIGH) {//Set SpriteLED (Green) HIGH
      digitalWrite(SpriteLEDPin, LOW);//Set SpriteLED (Green) LOW
      if(buttonPushCounter >= s){
      buttonPushCounter = buttonPushCounter - s;
      }
      delay(500);
      
  }
}

Hello POT82ES,
Welcome to the forum.

If you have read 'how to use this forum - please read' you will know we need more information, such as a circuit diagram. Without that how do you suppose we know how you have connected anything? There are some clever people on here but I am confident that none of them are telepathic.

TinkerCAD link? :slight_smile:

  String binNumber = String(buttonPushCounter, BIN);

Why are you using Strings ?

PerryBebbington:
none of them are telepathic.

I knew you were going to say that....

POT82ES:
Coke=4 presses, Fanta=6 and so...

Why's Fanta more expensive than Coke, anyway?

Not sure. I am new to code so the display-part is taken from another code, where he used strings. What would be the right way to do it?

This is the code I have used for the display.

/* source: https://www.electroschematics.com/9809/arduino-8-bit-binary-led/ */
int button = 2; // pin to connect the button
int presses = 0; // variable to store number of presses
long time = 0; // used for debounce
long debounce = 100; // how many ms to "debounce"
const byte numPins = 8; // how many leds
int state; // used for HIGH or LOW
 // pins to connect leds
byte pins[] = {5, 6, 7, 8, 9, 10, 11, 12};

void setup()
{
 /* we setup all led pins as OUTPUT */
 for(int i = 0; i < numPins; i++) {
 pinMode(pins[i], OUTPUT);
 }
 pinMode(button, INPUT);
 /* use pin 2 which has interrupt 0 on Arduino UNO */
 attachInterrupt(0, count, LOW);
}

void loop()
{
 /* convert presses to binary and store it as a string */
 String binNumber = String(presses, BIN);
 /* get the length of the string */
 int binLength = binNumber.length(); 
 if(presses <= 255) { // if we have less or equal to 255 presses
                // here is the scary code
 for(int i = 0, x = 1; i < binLength; i++, x+=2) { 
 if(binNumber[i] == '0') state = LOW;
 if(binNumber[i] == '1') state = HIGH;
 digitalWrite(pins[i] + binLength - x, state);
 } 
 } else {
 // do something when we reach 255
 }
}

/* function to count the presses */
void count() { 
 // we debounce the button and increase the presses
 if(millis() - time > debounce) presses++;
 time = millis();
}

No reason Fanta is more expensive other than to show that there is different prices. :slight_smile:

What would be the right way to do it?

It looks like you are using the Strings as arrays

      if(binNumber[i] == '0') state = LOW;
      if(binNumber[i] == '1') state = HIGH;

You could use a single byte variable instead and the bitRead() function (or other more advanced methods) to read the value of each bit in the byte

POT82ES:
TinkerCAD link? :slight_smile:

Which takes me to a web page that is asking me to to sign in. You of course don't have to supply a diagram, but in not doing so you are limiting the number of people who will help you.