i think you need to consider the following
- do you want to accept case before a selection is made
- do you want a button to cancel and return any collected case
in the code below, buttons are monitored using an internal function that handles debounce.
buttons are enumerated a a switch statement processes the buttons.
"select" tracks the selected item. it is also used to determine when to accept cash as well as when to check if there's a sufficient amount deposited.
one button is allocated for returning any deposited cash.
lcdDisp() deals with displaying strings.
// vending machine
#undef MyHW
#ifdef MyHW
# include "sim.h"
// return select coins
byte pinsBut [] = { A1, A4, A4, A2, A5, A5, A3, A5 }; // have 3 buttons
# define N_BUT sizeof(pinsBut)
// ----------------------------------------
#else
# include <Servo.h>
# include <Wire.h>
# include <LiquidCrystal_I2C.h>
# include <mechButton.h>
byte pinsBut [] = { 1, 2, 3, 4, 5, 6, 7, 8 };
#endif
// -----------------------------------------------------------------------------
LiquidCrystal_I2C lcd (0x27, 16, 2);
byte servopins [] = {17, 18, 19, 20};
#define NumberOfServos sizeof(servopins)
// enum values below correspond to pinsBut [] above
enum { R, S0, S1, S2, C2, C1, C0_5, C0_2, NONE };
int select = NONE;
Servo servos [NumberOfServos];
int servodelays [NumberOfServos] = {1500, 100, 2450, 1300}; // DELAYS FOR EACH SERVO
float cash;
char s0 [20];
char s1 [20];
enum { Off = HIGH, On = LOW };
// -----------------------------------------------------------------------------
void
reset (void)
{
select = NONE;
cash = 0;
digitalWrite (LED_BUILTIN, Off);
lcdDisp ((char *)"Select option");
}
// -----------------------------------------------------------------------------
void
lcdDisp (
char *s )
{
lcd.init ();
lcd.setBacklight (1);
lcd.setCursor (1, 0);
lcd.print (s);
}
// -----------------------------------------------------------------------------
byte butState [N_BUT];
int
chkButtons ()
{
for (unsigned n = 0; n < sizeof(pinsBut); n++) {
byte but = digitalRead (pinsBut [n]);
if (butState [n] != but) {
butState [n] = but;
delay (10); // debounce
if (On == but)
return n;
}
}
return -1;
}
// -----------------------------------------------------------------------------
void
monitorButtons (void)
{
byte but = chkButtons ();
switch (but) {
case R:
cashDrop ();
break;
case S0:
case S1:
case S2:
select = but;
digitalWrite (LED_BUILTIN, On);
break;
case C2:
cashUpdate (2.0);
break;
case C1:
cashUpdate (1.0);
break;
case C0_5:
cashUpdate (0.5);
break;
case C0_2:
cashUpdate (0.2);
break;
}
}
// -----------------------------------------------------------------------------
void
cashDrop ()
{
Serial.println (__func__);
reset ();
}
// -----------------------------------------------------------------------------
void
cashUpdate (
float coin )
{
if (NONE == select)
return;
cash += coin;
dtostrf (cash, 4, 2, s1);
sprintf (s0, "$%s", s1);
lcdDisp (s0);
digitalWrite (LED_BUILTIN, On);
delay (200);
digitalWrite (LED_BUILTIN, Off);
}
// -----------------------------------------------------------------------------
void
loop ()
{
monitorButtons ();
if (NONE != select && cash >= 2.50) {
lcdDisp ((char *)"Dispense");
servos [select].writeMicroseconds (1000); // rotate
delay (servodelays [select]); // delay for that servo
servos [select].writeMicroseconds (1500); // stop
reset ();
}
}
// -----------------------------------------------------------------------------
void
setup ()
{
Serial.begin (9600);
for (unsigned n = 0; n < sizeof(pinsBut); n++) {
pinMode (pinsBut [n], INPUT_PULLUP);
butState [n] = digitalRead (pinsBut [n]);
}
digitalWrite (LED_BUILTIN, Off);
pinMode (LED_BUILTIN, OUTPUT);
reset ();
}