#include "AiEsp32RotaryEncoder.h"
#include <U8g2lib.h>
// Pins
#define BUZZER_PIN 5 // buzzer
#define ROTARY_ENCODER_A_PIN 32 // rotary encoder 1
#define ROTARY_ENCODER_B_PIN 33 // rotary encoder 2
#define ROTARY_ENCODER_BUTTON_PIN 14 // rotary encoder switch
#define ROTARY_ENCODER_STEPS 4
#define VERSION "v1.0"
// Default voltage control values
#define VOLT_MIN 410 // min selectable voltage
#define VOLT_MAX 594 // max selectable voltage
#define VOLT_DEFAULT 545 // default start voltage
#define VOLT_STEP 1 // rotary encoder voltage change steps
// Default voltage control values
#define CURR_MIN 50 // min selectable current
#define CURR_MAX 635 // max selectable current
#define CURR_DEFAULT 580 // default start current
#define CURR_STEP 1 // rotary encoder current change steps
// Control values
#define BEEP_ENABLE true // enable/disable buzzer
#define ECREVERSE true // enable/disable rotary encoder reverse
#define MAINSCREEN 1 // type of main screen (0: big numbers; 1: more infos)
// Default values that can be changed by the user and stored in the EEPROM
uint16_t DefaultVolt = VOLT_DEFAULT;
uint16_t DefaultCurr = CURR_DEFAULT;
bool beepEnable = BEEP_ENABLE;
bool ECReverse = ECREVERSE;
// Menu items
const char *SetupItems[] = { "Setup Menu", "V/A Settings", "Information", "Return" };
const char *VAItems[] = { "V/A Settings", "Set Voltage online", "Set Current online", "Default Voltage", "Default Current", "Return" };
const char *SetVoltItems[] = { "Voltage online", "V" };
const char *SetCurrItems[] = { "Current online", "A" };
const char *DefaultVoltItems[] = { "Default Voltage", "V" };
const char *DefaultCurrItems[] = { "Default Current", "A" };
// Variables for control
uint16_t SetVoltage = VOLT_DEFAULT;
uint16_t SetCurrent = CURR_DEFAULT;
uint16_t Step;
AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS);
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
void IRAM_ATTR readEncoderISR()
{
rotaryEncoder.readEncoder_ISR();
}
void setup()
{
Serial.begin(115200);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW); // must be LOW when buzzer not in use
rotaryEncoder.begin();
rotaryEncoder.setup(readEncoderISR);
rotaryEncoder.setAcceleration(0);
rotaryEncoder.correctionOffset = 2; //try with zero or ROTARY_ENCODER_STEPS/2
rotaryEncoder.isButtonPulldown = false;
rotaryEncoder.areEncoderPinsPulldownforEsp32 = true;
setForOption(0);
u8g2.begin();
}
// creates a short beep on the buzzer
void beep(){
if (beepEnable) {
for (uint8_t i=0; i<255; i++) {
digitalWrite(BUZZER_PIN, HIGH);
delayMicroseconds(125);
digitalWrite(BUZZER_PIN, LOW);
delayMicroseconds(125);
}
}
}
String options[] = {"Select fast food", "How many (1...10)", "Do you want fast delicery for 2$?"};
String foods[] = {"Hot dog", "Pizza", "Hamburger", "Cheeseburger"};
String selectedFood = "";
String delivery[] = {"Normal", "Fast for extra 2$"};
String selectedDelivery = "";
int selectedQuantity = 1;
int currentOption = 0;
void setForOption(int newOption)
{
currentOption = newOption;
switch (newOption)
{
case 0:
rotaryEncoder.setBoundaries(0, 3, true); //food type 0..3
rotaryEncoder.setEncoderValue(0);
break;
case 1:
rotaryEncoder.setBoundaries(1, 10, false); //how many pieces 1 to 10; do not go from 10 to 1
rotaryEncoder.setEncoderValue(1);
break;
case 2:
rotaryEncoder.setBoundaries(0, 1, false); //select delivery
rotaryEncoder.setEncoderValue(0);
break;
default:
break;
}
Serial.print(">");
Serial.println(options[currentOption]);
showSelection();
}
void rotary_onButtonClick()
{
static unsigned long lastTimePressed = 0;
if (millis() - lastTimePressed < 200)
return;
if (millis() - lastTimePressed >= 500){
SetupScreen();
}
lastTimePressed = millis();
int selecedValue = rotaryEncoder.readEncoder();
switch (currentOption)
{
case 0: //"Select fast food"
selectedFood = foods[selecedValue];
setForOption(1);
break;
case 1: //"Select quantity"
selectedQuantity = selecedValue;
setForOption(2);
break;
case 2: //"Select delivery"
selectedDelivery = delivery[selecedValue];
showOrder();
setForOption(0);
break;
default:
break;
}
}
void showOrder()
{
Serial.println("++++++++++++++++++++++++ ORDER DETAILS ++++++++++++++++++++++++++++++++++++++++++");
Serial.print("You ordered ");
Serial.print(selectedFood);
Serial.print(", quantity: ");
Serial.print(selectedQuantity);
Serial.print(". Delivery: ");
Serial.println(selectedDelivery);
Serial.println("---------------------------------------------------------------------------------");
Serial.println("");
Serial.print("NEW ORDER ");
}
void showSelection()
{
int selecedValue = rotaryEncoder.readEncoder();
switch (currentOption)
{
case 0: //"Select fast food"
Serial.print(">");
Serial.println(foods[selecedValue]);
break;
case 1: //"Select quantity"
Serial.print("Quantity: ");
Serial.println(selecedValue);
break;
case 2: //"Select delivery"
Serial.println(delivery[selecedValue]);
break;
default:
break;
}
}
void loop()
{
MainScreen(); // updates the main page on the OLED
if (rotaryEncoder.encoderChanged())
{
//showSelection();
Serial.println("encoderChanged");
}
if (rotaryEncoder.isEncoderButtonClicked())
{
rotary_onButtonClick();
Serial.println("EncoderButtonClicked");
}
}
// draws the main screen
void MainScreen() {
u8g2.firstPage();
do {
// draw voltage/current
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setFontPosTop();
u8g2.drawStr( 10, 0, "SET:");
u8g2.setCursor(45,0);
u8g2.print((float)SetVoltage/10, 1);u8g2.print(F(" V "));
u8g2.print((float)SetCurrent/10, 1);u8g2.print(F(" A"));
float U=54.5;
float A=25.0;
u8g2.setFont(u8g2_font_fur17_tf);
u8g2.setFontPosTop();
u8g2.setCursor(0,22);
u8g2.print(U, 1);u8g2.print(F("V "));u8g2.print(A, 1);u8g2.print(F("A"));
} while(u8g2.nextPage());
}
// setup screen
void SetupScreen() {
beep();
uint16_t SaveSetVoltage = SetVoltage;
uint8_t selection = 0;
bool repeat = true;
while (repeat) {
selection = MenuScreen(SetupItems, sizeof(SetupItems), selection);
switch (selection) {
case 0: VAScreen(); break;
case 1: InfoScreen(); break;
default: repeat = false; break;
}
}
// updateEEPROM();
// handleMoved = true;
// SetVoltage = SaveSetVoltage;
// setRotary(VOLT_MIN, VOLT_MAX, VOLT_STEP, SetVoltage);
}
// menu screen
uint8_t MenuScreen(const char *Items[], uint8_t numberOfItems, uint8_t selected) {
uint8_t lastselected = selected;
int8_t arrow = 0;
if (selected) arrow = 1;
numberOfItems >>= 1;
setRotary(0, numberOfItems - 2, 1, selected);
bool lastbutton = (!digitalRead(SWITCH_PIN));
do {
selected = getRotary();
arrow = constrain(arrow + selected - lastselected, 0, 2);
lastselected = selected;
u8g.firstPage();
do {
u8g.setFont(u8g_font_7x14);
u8g.setFontPosTop();
u8g.drawStr( 0, 0, Items[0]);
u8g.drawStr( 0, 16 * (arrow + 1), ">");
for (uint8_t i=0; i<3; i++) {
uint8_t drawnumber = selected + i + 1 - arrow;
if (drawnumber < numberOfItems)
u8g.drawStr( 12, 16 * (i + 1), Items[selected + i + 1 - arrow]);
}
} while(u8g.nextPage());
if (lastbutton && digitalRead(SWITCH_PIN)) {delay(10); lastbutton = false;}
} while (digitalRead(SWITCH_PIN) || lastbutton);
beep();
return selected;
}
esp:VIN
esp:GND.2
esp:D13
esp:D12
esp:D14
esp:D27
esp:D26
esp:D25
esp:D33
esp:D32
esp:D35
esp:D34
esp:VN
esp:VP
esp:EN
esp:3V3
esp:GND.1
esp:D15
esp:D2
esp:D4
esp:RX2
esp:TX2
esp:D5
esp:D18
esp:D19
esp:D21
esp:RX0
esp:TX0
esp:D22
esp:D23
oled1:GND
oled1:VCC
oled1:SCL
oled1:SDA
encoder1:CLK
encoder1:DT
encoder1:SW
encoder1:VCC
encoder1:GND