Hi there
I wrote a code for a vending machine.
There are menus with options so that a service person can change stuff like price, amount etc...
I m using a atmega with lcd 2*16 and sd card module a nfc reader a thermostat and some buttons.
the problem is that my program gets stuck at the menus when it gets back to the main screen and as you can see on the serial monitor sd card reading also fails ??????????????
sometimes the lcd will go blank as well when i get back to main menu screen.
see below my code
many thanks
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SD.h>
#define BUTTON_UP 19
#define BUTTON_DOWN 18
#define BUTTON_ENTER 8
#define NOKEY 0
#define KEYUP 1
#define KEYDOWN 2
#define KEYENTER 3
//menu's
#define MAXMENUOPTIONS 8
#define MAINMENU 0
#define CREATEGROUPMENU 1
#define PRICEMENU 2
#define AMOUNTMENU 3
#define UNITFORSALEFORSUBSCRIBERMENU 5
#define PRICEFORSUBSCRIBERMENU 6
#define PRICEPERUNITFORGROUPS 7
//define error codes
#define NO_MILK 1
#define HIGH_TEMP 2
#define LOW_TEMP 3
#define NO_CHANGE 4
//thermostat
#define ONE_WIRE_BUS 25
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
#define MIN_ALOWED_TEMP 12
#define MAX_ALOWED_TEMP 30
#define MAX_ALOWED_TIME_AT_EXTREME_TEMP 60000
bool onceTempTimer;
int globalPrice = 5;//globalPrice for one vend of milk (1 unit equals 10 agurot)
int amount = 0;//amount in msec dispenced in one vend
int globalPriceForSubscribers;
int globalUnitsForSaleForSubscribers;
int pricePerUnitForGroups;
LiquidCrystal lcd(12, 11, 5, 4, 23, 22);
int menuPosition = 0;
byte upSign[8] = {
0b00000,
0b00000,
0b00100,
0b00100,
0b01110,
0b01110,
0b11111,
0b00000
};
byte downSign[8] = {
0b00000,
0b11111,
0b01110,
0b01110,
0b00100,
0b00100,
0b00000,
0b00000
};
byte enterSign[8] = {
0b00001,
0b00001,
0b00001,
0b00101,
0b01101,
0b11111,
0b01100,
0b00100
};
byte celciusSign[8] = {
0b00111,
0b00101,
0b00111,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000
};
void setup() {
// put your setup code here, to run once:
sensors.begin();
lcd.begin(16, 2);// set up the LCD's number of columns and rows:
lcd.createChar(0, celciusSign);
lcd.createChar(1, downSign);
lcd.createChar(2, upSign);
lcd.createChar(3, enterSign);
lcd.clear();
Serial.begin(115200);
pinMode(BUTTON_UP, INPUT);
pinMode(BUTTON_DOWN, INPUT);
pinMode(BUTTON_ENTER, INPUT);
if (!SD.begin(53)) {
Serial.println("initialization SD failed!");
// while (1);
}
Serial.println("initialization SD done.");
}
void loop() {
menu();
}
void menu() {
switch (key()) {
case KEYUP:
menuPosition++;
if (menuPosition >= MAXMENUOPTIONS) {
menuPosition = 0;
}
break;
case KEYDOWN:
menuPosition--;
if (menuPosition < 0) {
menuPosition = MAXMENUOPTIONS - 1;
}
break;
case KEYENTER:
bool hitEnter = false;
switch (menuPosition) {
case PRICEPERUNITFORGROUPS:
do {
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("קבע מחיר לקבוצות");
lcd.leftToRight();
lcd.setCursor(9, 1);
lcd.print(pricePerUnitForGroups * 10);
switch (key()) {
case KEYUP:
if (pricePerUnitForGroups < 1000) {//price cant be more then 100 shekel
pricePerUnitForGroups++;
}
break;
case KEYDOWN:
if (pricePerUnitForGroups > 1) {//globalPrice cant be less then 1
pricePerUnitForGroups--;
}
break;
case KEYENTER:
hitEnter = true;
break;
}
} while (!hitEnter);
break;
case PRICEFORSUBSCRIBERMENU:
do {
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("קבע מחיר למנוים ");
lcd.leftToRight();
lcd.setCursor(9, 1);
lcd.print(globalPriceForSubscribers * 10);
switch (key()) {
case KEYUP:
if (globalPriceForSubscribers < 1000) {//price cant be more then 100 shekel
globalPriceForSubscribers++;
}
break;
case KEYDOWN:
if (globalPriceForSubscribers > 1) {//Price cant be less then 1
globalPriceForSubscribers--;
}
break;
case KEYENTER:
hitEnter = true;
break;
}
} while (!hitEnter);
break;
case PRICEMENU:
do {
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("קבע מחיר באגורות");
lcd.leftToRight();
lcd.setCursor(9, 1);
lcd.print(globalPrice * 10);
switch (key()) {
case KEYUP:
if (globalPrice < 1000) {//price cant be more then 100 shekel
globalPrice++;
}
break;
case KEYDOWN:
if (globalPrice > 1) {//price cant be less then 1
globalPrice--;
}
break;
case KEYENTER:
hitEnter = true;
break;
}
} while (!hitEnter);
break;
case AMOUNTMENU:
do {
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("כמות: cesm ");
lcd.leftToRight();
lcd.setCursor(0, 0);
lcd.print(amount * 100);
if (amount < 99) {
lcd.setCursor(4, 0);
lcd.print(" ");
}
switch (key()) {
case KEYUP:
if (amount < 200) {//amount cant be more then 20 sec
amount++;
}
break;
case KEYDOWN:
if (amount > 1) {//price cant be less then 1
amount--;
}
break;
case KEYENTER:
hitEnter = true;
break;
}
} while (!hitEnter);
break;
case UNITFORSALEFORSUBSCRIBERMENU:
do {
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("יחידות למכירה: ");
lcd.leftToRight();
lcd.setCursor(9, 1);
lcd.print(globalUnitsForSaleForSubscribers);
switch (key()) {
case KEYUP:
if (globalUnitsForSaleForSubscribers < 500) {//amount cant be more then 1 byte
globalUnitsForSaleForSubscribers++;
}
break;
case KEYDOWN:
if (globalUnitsForSaleForSubscribers > 1) {//price cant be less then 1
globalUnitsForSaleForSubscribers--;
}
break;
case KEYENTER:
hitEnter = true;
break;
}
} while (!hitEnter);
break;
case CREATEGROUPMENU:
int groupName[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int currentposition = 12;
static int enterPressed = 0;
int letter = 221;
bool clearOnce = false;
static long lastTimeOff;
do {
if (!clearOnce) {
clearOnce = true;
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("שם: ");
}
lcd.setCursor(currentposition, 0);
unsigned long currentMillis = millis();
static long previousMillis;
static bool letterOn;
if (currentMillis - previousMillis >= 500) {
previousMillis = currentMillis;// save the last time you blinked the letter
if (!letterOn) {// if the letter is off turn it on and vice-versa:
lcd.write(letter);
groupName[currentposition] = letter;
letterOn = true;
} else {
lcd.write(159);
letterOn = false;
}
}
switch (key()) {
case KEYUP:
enterPressed = 0;
if (letter == 221) {
letter = 159;
}
if (letter == 186) {
letter = 159;
}
if (letter < 186) {//taf 187
letter++;
}
Serial.println(letter);
break;
case KEYDOWN:
enterPressed = 0;
if (letter == 221) {
letter = 187;
}
if (letter == 160) {
letter = 187;
}
if (letter > 160) {//alef 159
letter--;
}
Serial.println(letter);
break;
case KEYENTER:
if (!letterOn) {
lcd.write(letter);
}
if (currentposition > 0) {
currentposition--;
}
letter = 221;
enterPressed++;
if (enterPressed == 2 ) {
hitEnter = true;
}
break;
}
} while (!hitEnter);
long timer = millis() +10000;
do {
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("הצג כרתיס לשמור");
//if (IsthereATagToRead()) {AddNewUidToGroup(globalUid,1,createNewGroup(groupName));
//printHeb("נוסף קבוצה חדש");delay(1500);brake;
} while (timer > millis());
menuPosition = MAINMENU;
break;
}
}
switch (menuPosition) {
case MAINMENU:
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("מחיר: ");
lcd.leftToRight();
if (globalPrice < 10) {
lcd.setCursor(0, 0);
lcd.print("0.");
lcd.print(globalPrice);
lcd.print("0 ");
}
else {
int aftercomma = globalPrice % 10;
int beforecomma = globalPrice / 10;
lcd.setCursor(0, 0);
lcd.print(beforecomma);
lcd.print(".");
lcd.print(aftercomma);
lcd.print("0 ");
}
lcd.setCursor(0, 1);
lcd.leftToRight();
lcd.print(" ");
static long displayTimer;
if (displayTimer < millis()) {
thermostat();
Serial.println("thermostat()");
displayTimer = millis() + 3000;
}
break;
case PRICEMENU:
//lcd.clear();
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb(" קבע מחיר ");
displayButtons();
break;
case AMOUNTMENU:
//lcd.clear();
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb(" קבע כמות ");
displayButtons();
break;
case CREATEGROUPMENU:
//lcd.clear();
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb(" הוספת קבוצה ");
displayButtons();
break;
case UNITFORSALEFORSUBSCRIBERMENU:
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("קבע כמות למנוים");
displayButtons();
break;
case PRICEFORSUBSCRIBERMENU:
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("קבע מחיר למנוים");
displayButtons();
break;
case PRICEPERUNITFORGROUPS:
lcd.setCursor(15, 0);
lcd.rightToLeft();
printHeb("קבע מחיר לקבוצות");
displayButtons();
break;
}
}
void displayButtons() {
lcd.setCursor(0, 1);
lcd.write(byte(1));
lcd.setCursor(3, 1);
lcd.write(byte(2));
lcd.setCursor(6, 1);
lcd.write(byte(3));
lcd.setCursor(7, 1);
lcd.leftToRight();
printHeb(" ");
}
int key() {
static long lastTimeSButtonA;
static long lastTimeSButtonB;
static long lastTimeSButtonC;
if (digitalRead(BUTTON_UP) == LOW && millis() - lastTimeSButtonA > 200) { // left
lastTimeSButtonA = millis();
Serial.println("<up>");
return KEYUP;
} else if (digitalRead(BUTTON_DOWN) == LOW && millis() - lastTimeSButtonB > 200) { // right
lastTimeSButtonB = millis();
Serial.println("<down>");
return KEYDOWN;
} else if (digitalRead(BUTTON_ENTER) == LOW && millis() - lastTimeSButtonC > 200) { // enter
lastTimeSButtonC = millis();
Serial.println("<enter>");
return KEYENTER;
} else {
return NOKEY;
}
}
void printHeb(char *str)
{
byte i; // Input
byte k = 0; // Output
char arr[15]={0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0};
for (i = 0; i < strlen(str); i++)
{
if ((byte)str[i] < 127)
{
arr[k++] = (byte)(str[i]);
}
else
{
arr[k++] = (byte)(str[i + 1]) + 16; // -144+160;
i++;
}
}
arr[k] = 0;
//Serial.println(strlen(str));
lcd.print(arr);
// lcd.print(arr[1]);
//for (int positionn = 0; positionn < strlen(str) - 14; positionn++) {
// for (int y = positionn; y < positionn+16; y++) {
// lcd.print(arr[y]);
// Serial.println(y);
// }
// delay(1000);
// lcd.setCursor(15, 0);
// }
}
void thermostat() {
File myFile;
myFile = SD.open("members.txt");
if (myFile) {
Serial.println("members.txt");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening members.txt");
}
myFile = SD.open("groups.txt");
if (myFile) {
Serial.println("groups.txt");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening groups.txt");
}
/* Serial.print("Celsius temperature: ");
// Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
Serial.println(sensors.getTempCByIndex(0));*/
sensors.requestTemperatures();
//char tempForScreen[] = {'-', 3, 1, '.', 3, 0};
//dtostrf(sensors.getTempCByIndex(0), 6, 2, tempForScreen);
lcd.leftToRight();
lcd.setCursor(9, 1);
//for (int x = 0; x < 5; x++) {
lcd.print(sensors.getTempCByIndex(0) );
//lcd.print(tempForScreen[1] );
//lcd.print(tempForScreen[2] );
//lcd.print(tempForScreen[3] );
// }
lcd.setCursor(13, 1);
lcd.write(byte(0));
lcd.print("C");
static float LastTimeTempRead;
if (sensors.getTempCByIndex(0) < MIN_ALOWED_TEMP) {
if (onceTempTimer) {
LastTimeTempRead = millis();
onceTempTimer = false;
}
if (sensors.getTempCByIndex(0) < MIN_ALOWED_TEMP && millis() - LastTimeTempRead > MAX_ALOWED_TIME_AT_EXTREME_TEMP) {
error(LOW_TEMP);
}
}
if (sensors.getTempCByIndex(0) > MAX_ALOWED_TEMP) {
if (onceTempTimer) {
LastTimeTempRead = millis();
onceTempTimer = false;
}
if (sensors.getTempCByIndex(0) > MAX_ALOWED_TEMP && millis() - LastTimeTempRead > MAX_ALOWED_TIME_AT_EXTREME_TEMP) {
error(HIGH_TEMP);
}
}
if (sensors.getTempCByIndex(0) > MIN_ALOWED_TEMP && sensors.getTempCByIndex(0) < MAX_ALOWED_TEMP ) {
static int counter;
counter ++;
if (counter == 10) {
onceTempTimer = true;
counter = 0;
}
}
}
void error(int errortype) {
switch (errortype) {
case NO_MILK:
lcd.begin(16, 2);
lcd.setCursor(11, 0);
lcd.rightToLeft();
printHeb("אין חלב");
while (1) {};
break;
case HIGH_TEMP:
lcd.begin(16, 2);
lcd.setCursor(4, 0);
lcd.print("ERROR HT");
while (1) {
lcd.setCursor(5, 1);
lcd.print(sensors.getTempCByIndex(0));
};
break;
case LOW_TEMP:
lcd.begin(16, 2);
lcd.setCursor(4, 0);
lcd.print("ERROR LT");
while (1) {
lcd.setCursor(5, 1);
lcd.print(sensors.getTempCByIndex(0));
};
break;
}
}
and serial monitor
Found chip PN532
Firmware ver. 1.6
Waiting for an ISO14443A or ISO14443B Card ...
initialization SD done.
getting price from eeprom
price is: 39 agurot
getting amount open time from eeprom
amount of open time in msec is: 50
getting group price from sd
group price is: 5 agurot
getting subscriber price from sd
subscriber price is: 50 agurot
getting subscriber amount for sale from sd
subscriber amount is: 100
members.txt
8B83B979,00001,1;!groups.txt
,160162000000000000000000000000000000000000000000:00000!thermostat()
<up>
<up>
<up>
<up>
<up>
<up>
<up>
<up>
initialization SD done.
members.txt
8B83B979,00001,1;!groups.txt
,160162000000000000000000000000000000000000000000:00000!initialization SD done.
members.txt
8B83B979,00001,1;!groups.txt
,160162000000000000000000000000000000000000000000:00000!thermostat()
<up>
<up>
<up>
<up>
<up>
<up>
<up>
<up>
members.txt
groups.txt
⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮```