I'm new in arduino and not particularly awaken when it comes to code ;) . I'm developing a device SD logging Temperatures from 2 thermocouple . Hardware works well and I'm now trying to refine use of the LCD with a menu.
I want to be able to, while logging data on the SD card (lets say every second), browsing a menu to:
See current temperatures
see the max value from the measurements
see time already elapsed
etc.
I've used a menu code from (https://www.instructables.com/id/Arduino-Uno-Menu-Template/)
The thing is when I enter a sub-menu(menuItem()), while I'm not out of this sub menu the code is not looping anymore, so data logging would be paused.
So my question is: how should I organize my code to be able to do a repetitive task in background(logging temperatures) while browsing a menu giving information and/or proposing actions (Stop datalogging, reset etc).
Here is the code from instructables modified to be used with adafruit LCD shield:
/***************************************************************************************
Name : LCD Button Shield Menu
Author : Paul Siewert
Created : June 14, 2016
Last Modified: June 14, 2016
Version : 1.0
Notes : This code is for use with an Arduino Uno and LCD/button shield. The
intent is for anyone to use this program to give them a starting
program with a fully functional menu with minimal modifications
required by the user.
License : This program is free software. You can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
***************************************************************************************/
/*
This program is designed to get you as close as possible to a finished menu for the standard Arduino Uno LCD/button shield. The only required modifications
are to add as menu items to the master menu (menuItems array) and then modify/adjust the void functions below for each of those selections.
*/
// You can have up to 10 menu items in the menuItems[] array below without having to change the base programming at all. Name them however you'd like. Beyond 10 items, you will have to add additional "cases" in the switch/case
// section of the operateMainMenu() function below. You will also have to add additional void functions (i.e. menuItem11, menuItem12, etc.) to the program.
String menuItems[] = {"ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"};
// Navigation button variables
int readKey;
// Menu control variables
int menuPage = 0;
int maxMenuPages = round(((sizeof(menuItems) / sizeof(String)) / 2) + .5);
int cursorPosition = 0;
// Creates 3 custom characters for the menu display
byte downArrow[8] = {
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b10101, // * * *
0b01110, // ***
0b00100 // *
};
byte upArrow[8] = {
0b00100, // *
0b01110, // ***
0b10101, // * * *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100 // *
};
byte menuCursor[8] = {
B01000, // *
B00100, // *
B00010, // *
B00001, // *
B00010, // *
B00100, // *
B01000, // *
B00000 //
};
#include <Wire.h>
#include <LiquidCrystal.h>
// Setting the LCD shields pins
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
void setup() {
// Initializes serial communication
Serial.begin(9600);
// Initializes and clears the LCD screen
lcd.begin(16, 2);
lcd.clear();
// Creates the byte for the 3 custom characters
lcd.createChar(0, menuCursor);
lcd.createChar(1, upArrow);
lcd.createChar(2, downArrow);
}
//////////////////////////////////////////////
void loop() {
mainMenuDraw();
drawCursor();
operateMainMenu();
Serial.print("Loop");
}
///////////////////////////////////////////////
// This function will generate the 2 menu items that can fit on the screen. They will change as you scroll through your menu. Up and down arrows will indicate your current menu position.
void mainMenuDraw() {
Serial.print(menuPage);
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(menuItems[menuPage]);
lcd.setCursor(1, 1);
lcd.print(menuItems[menuPage + 1]);
if (menuPage == 0) {
lcd.setCursor(15, 1);
lcd.write(byte(2));
} else if (menuPage > 0 and menuPage < maxMenuPages) {
lcd.setCursor(15, 1);
lcd.write(byte(2));
lcd.setCursor(15, 0);
lcd.write(byte(1));
} else if (menuPage == maxMenuPages) {
lcd.setCursor(15, 0);
lcd.write(byte(1));
}
}
// When called, this function will erase the current cursor and redraw it based on the cursorPosition and menuPage variables.
void drawCursor() {
for (int x = 0; x < 2; x++) { // Erases current cursor
lcd.setCursor(0, x);
lcd.print(" ");
}
// The menu is set up to be progressive (menuPage 0 = Item 1 & Item 2, menuPage 1 = Item 2 & Item 3, menuPage 2 = Item 3 & Item 4), so
// in order to determine where the cursor should be you need to see if you are at an odd or even menu page and an odd or even cursor position.
if (menuPage % 2 == 0) {
if (cursorPosition % 2 == 0) { // If the menu page is even and the cursor position is even that means the cursor should be on line 1
lcd.setCursor(0, 0);
lcd.write(byte(0));
}
if (cursorPosition % 2 != 0) { // If the menu page is even and the cursor position is odd that means the cursor should be on line 2
lcd.setCursor(0, 1);
lcd.write(byte(0));
}
}
if (menuPage % 2 != 0) {
if (cursorPosition % 2 == 0) { // If the menu page is odd and the cursor position is even that means the cursor should be on line 2
lcd.setCursor(0, 1);
lcd.write(byte(0));
}
if (cursorPosition % 2 != 0) { // If the menu page is odd and the cursor position is odd that means the cursor should be on line 1
lcd.setCursor(0, 0);
lcd.write(byte(0));
}
}
}
void operateMainMenu() {
int activeButton = 0;
while (activeButton == 0) {
int buttons;
buttons = lcd.readButtons();
switch (buttons) {
case 0: // When button returns as 0 there is no action taken
break;
case 2: // This case will execute if the "forward" button is pressed
buttons = 0;
switch (cursorPosition) { // The case that is selected here is dependent on which menu page you are on and where the cursor is.
case 0:
menuItem1();
break;
case 1:
menuItem2();
break;
case 2:
menuItem3();
break;
}
activeButton = 2;
mainMenuDraw();
drawCursor();
break;
case 8:
buttons = 0;
if (menuPage == 0) {
cursorPosition = cursorPosition - 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
}
if (menuPage % 2 == 0 and cursorPosition % 2 == 0) {
menuPage = menuPage - 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
if (menuPage % 2 != 0 and cursorPosition % 2 != 0) {
menuPage = menuPage - 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
cursorPosition = cursorPosition - 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
mainMenuDraw();
drawCursor();
activeButton = 2;
break;
case 4:
buttons = 0;
if (menuPage % 2 == 0 and cursorPosition % 2 != 0) {
menuPage = menuPage + 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
menuPage = menuPage + 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
cursorPosition = cursorPosition + 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
mainMenuDraw();
drawCursor();
activeButton = 2;
break;
}
}
}
// If there are common usage instructions on more than 1 of your menu items you can call this function from the sub
// menus to make things a little more simplified. If you don't have common instructions or verbage on multiple menus
// I would just delete this void. You must also delete the drawInstructions()function calls from your sub menu functions.
void drawInstructions() {
lcd.setCursor(0, 1); // Set cursor to the bottom line
lcd.print("Use ");
lcd.print(byte(1)); // Up arrow
lcd.print("/");
lcd.print(byte(2)); // Down arrow
lcd.print(" buttons");
}
void menuItem1() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Sub Menu 1");
while (activeButton == 0) {
int buttons;
buttons = lcd.readButtons();
switch (buttons) {
case 16: // This case will execute if the "back" button is pressed
buttons = 0;
activeButton = 1;
break;
}
}
}
void menuItem2() { // Function executes when you select the 2nd item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Sub Menu 2");
while (activeButton == 0) {
int buttons;
buttons = lcd.readButtons();
switch (buttons) {
case 16: // This case will execute if the "back" button is pressed
buttons = 0;
activeButton = 1;
break;
}
}
}
void menuItem3() { // Function executes when you select the 3rd item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Sub Menu 3");
while (activeButton == 0) {
int buttons;
buttons = lcd.readButtons();
switch (buttons) {
case 16: // This case will execute if the "back" button is pressed
buttons = 0;
activeButton = 1;
break;
}
}
}
I thank you for your help, and hope it will be helpful for others