/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
const char* menuOptions[] = {"Geolocation","Pump active time","Krumplifozelek fasirozottal","Borzsonyi csirkeszarnyak Egermama modra"};
int totalOptions = sizeof(menuOptions) / sizeof(menuOptions[0]);
int currentOption = 0;
// const int buttonPin =4;
bool scrollDirectionLeft = true;
unsigned long lastScrollTime = 0;
int scrollPos = 0;
bool isScrolling = false;
TaskHandle_t UIHandle;
TaskHandle_t CoreFunction;
// LED pins
const int led1 = 2;
const int led2 = 18;
struct Button {
const uint8_t PIN;
uint32_t numberSingleKeyPresses;
uint32_t numberLongKeyPresses;
uint32_t numberDoubleKeyPresses;
uint32_t numberKeyTransitions; // press and release
unsigned long int buttonPressDuration;
bool pressed;
bool longpressed;
bool doublepressed;
//bool changed;
};
volatile Button button1 = {4, 0, 0, 0, 0, 0, false, false, false};
//variables to keep track of the timing of recent interrupts
unsigned long int button_time = 0;
unsigned long int last_button_time = 0; // last button event, press or release
unsigned long int llast_button_time = 0; // debug var
unsigned long int last_press_time = 0;
unsigned long int last_release_time = 0;
unsigned long int button_event_duration = 0;
unsigned long int button_press_duration = 0;
int currentState;
void IRAM_ATTR ISR_button_pressed()
{
button1.numberSingleKeyPresses++;
button1.numberKeyTransitions++;
button1.pressed =1;
currentState = digitalRead(button1.PIN);
}
void IRAM_ATTR ISR_button_released()
{
button1.numberKeyTransitions++;
button1.pressed =1;
}
void setup()
{
Wire.begin(13,14);
Serial.begin(115200);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
//pinMode(buttonPin, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
//pinMode(4, INPUT);
//attachInterrupt(button1.PIN, isr, FALLING);
//attachInterrupt(button1.PIN, button_pressed, FALLING);
//attachInterrupt(digitalPinToInterrupt(button1.PIN), ISR_button_pressed, RISING);
//attachInterrupt(digitalPinToInterrupt(4), ISR_button_pressed, RISING);
attachInterrupt(4, ISR_button_pressed, FALLING);
//attachInterrupt(4, ISR_button_released, RISING);
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
//LCD, buttons, menu, parameter settings, deepsleep semaphore 1
xTaskCreatePinnedToCore(
//Task1code, /* Task function. */
UIHandleCode,
//"Task1", /* name of task. */
"UIHandle",
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
//&Task1, /* Task handle to keep track of created task */
&UIHandle,
0); /* pin task to core 0 */
delay(500);
//create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
// Wifi communication, sensor reading, database communication, deepsleep semaphore 2
xTaskCreatePinnedToCore(
//Task2code, /* Task function. */
CoreFunctionCode,
//"Task2", /* name of task. */
"CoreFunction",
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
//&Task2, /* Task handle to keep track of created task */
&CoreFunction,
1); /* pin task to core 1 */
delay(500);
}
//Task1code: blinks an LED every 1000 ms
//void Task1code( void * pvParameters )
void UIHandleCode( void * pvParameters )
{
Serial.print("UI running on core ");
Serial.println(xPortGetCoreID());
lcd.print("SELECTED OPTION:");
updateMenu();
for(;;)
{
if (button1.pressed || button1.doublepressed || button1.longpressed )
{
//button_press_duration = button_time-last_press_time;
Serial.printf("\nNumber of button transitions: %u times.\nButton has been single pressed %u times.\nCurrent button state is: %u\n", button1.numberKeyTransitions, button1.numberSingleKeyPresses, currentState);
//Serial.printf("\nActual button press time: %u.\nPrevious button press time: %u.\nButton press duration: %u.\
//\nNumber of button transitions: %u times.\nButton has been single pressed %u times.\
//\nButton has been double pressed %u times.\nButton has been long pressed %u times.\n",
//button_time, last_press_time, button_press_duration, button1.numberKeyTransitions,
//button1.numberSingleKeyPresses, button1.numberDoubleKeyPresses,button1.numberLongKeyPresses);
//currentOption = (currentOption + 1) % totalOptions;
currentOption = (button1.numberSingleKeyPresses) % totalOptions;
//updateMenu();
//button1.pressed = false;
}
if (button1.pressed)
{
button1.pressed = false;
}
if (button1.longpressed)
{
button1.longpressed = false;
}
if (button1.doublepressed)
{
button1.doublepressed = false;
}
/*
if(digitalRead(buttonPin) == LOW)
{
delay(200);
while(digitalRead(buttonPin) == LOW);
currentOption = (currentOption + 1) % totalOptions;
updateMenu();
}
*/
if(isScrolling && millis() - lastScrollTime >= 300)
{
scrollText();
lastScrollTime = millis();
}
//digitalWrite(led1, HIGH);
//delay(1000);
//digitalWrite(led1, LOW);
//delay(1000);
}
}
//Task2code: blinks an LED every 700 ms
//void Task2code( void * pvParameters )
void CoreFunctionCode( void * pvParameters )
{
Serial.print("Base function running on core ");
Serial.println(xPortGetCoreID());
for(;;)
{
digitalWrite(led2, HIGH);
delay(700);
digitalWrite(led2, LOW);
delay(700);
}
}
void loop()
{
}
void updateMenu()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("SELECTED OPTION:");
const char* text = menuOptions[currentOption];
String paddedText = String(text)+" "; // Add spaces for smooth scrolling
int textLength = paddedText.length();
if(textLength <= 16){
lcd.setCursor(0,1);
lcd.print(text);
isScrolling = false;
}
else {
lcd.setCursor(0,0);
lcd.print(paddedText.substring(0,16));
scrollPos =0;
isScrolling = true;
scrollDirectionLeft = true;
}
}
void scrollText()
{
const char* text = menuOptions[currentOption];
String paddedText = String(text)+""; // Ensure smooth scrolling
int textLength = paddedText.length();
if(scrollDirectionLeft)
{
if(scrollPos < textLength -16)
{
scrollPos++;
}
else
{
delay(2000);
scrollDirectionLeft = true;
}
}
lcd.setCursor(0,1);
lcd.print(paddedText.substring(scrollPos,scrollPos+16));
}