/**
ESP32RotaryEncoder: LeftOrRight.ino
This is a simple example of how to track whether the knob was
turned left or right instead of tracking a numeric value
Created 1 November 2023
By Matthew Clark
*/
#include <ESP32RotaryEncoder.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define GREEN 0x07E0
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C //< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
double aktTemp = 26.0f;
double aktTargetTemp = 12;
bool heaterState = true;
bool inputTarget = true;
bool progMode = false;
int progressCounter = 0;
// Change these to the actual pin numbers that
// you've connected your rotary encoder to
const uint8_t DI_ENCODER_A = 2;
const uint8_t DI_ENCODER_B = 5;
const int8_t DI_ENCODER_SW = 19;
const int8_t DO_ENCODER_VCC = 18;
RotaryEncoder rotaryEncoder( DI_ENCODER_A, DI_ENCODER_B, DI_ENCODER_SW, DO_ENCODER_VCC );
// Used by the `loop()` to know when to
// fire an event when the knob is turned
volatile bool turnedRightFlag = false;
volatile bool turnedLeftFlag = false;
volatile bool buttonPressedFlag = false;
void turnedRight()
{
Serial.println( "Right ->" );
// Set this back to false so we can watch for the next move
if (aktTargetTemp < 121) {
aktTargetTemp++;
printToOled();
}
turnedRightFlag = false;
}
void turnedLeft()
{
Serial.println( "<- Left" );
if (aktTargetTemp > -21) {
aktTargetTemp--;
printToOled();
}
// Set this back to false so we can watch for the next move
turnedLeftFlag = false;
}
void buttonPressed() {
Serial.println("button pressed");
progMode = !progMode;
Serial.println(progMode);
if (progMode) {
progressCounter=100;
printToOledProgMode();
} else {
printToOled();
}
}
void knobCallback( long value )
{
// See the note in the `loop()` function for
// an explanation as to why we're setting
// boolean values here instead of running
// functions directly.
// Don't do anything if either flag is set;
// it means we haven't taken action yet
if ( turnedRightFlag || turnedLeftFlag )
return;
// Set a flag that we can look for in `loop()`
// so that we know we have something to do
switch ( value )
{
case 1:
turnedRightFlag = true;
break;
case -1:
turnedLeftFlag = true;
break;
}
// Override the tracked value back to 0 so that
// we can continue tracking right/left events
rotaryEncoder.setEncoderValue( 0 );
}
void buttonCallback( unsigned long duration )
{
//Serial.printf( "boop! button was down for %lu ms\n", duration );
buttonPressed();
buttonPressedFlag = true;
}
void printToOled() {
char tempTxt[10];
dtostrf( aktTemp, 6, 1, tempTxt );
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
if (heaterState) {
display.setTextSize(1.5);
display.setCursor(110, 0);
//display.write(236);
display.print("H");
}
display.setTextSize(2.5);
display.setCursor(10, 18);
display.print(tempTxt);
display.print(" ");
display.println("C");
if (inputTarget) {
dtostrf( aktTargetTemp, 3, 0, tempTxt );
display.setCursor(10, 45);
display.setTextSize(1.5);
display.print("Target: ");
display.setTextSize(1.6);
display.print(tempTxt);
display.write(247);
} else {
dtostrf( aktTemp, 3, 0, tempTxt );
display.setCursor(20, 50);
display.setTextSize(0.5);
display.print("user temp input ");
}
display.setCursor(0, 0);
display.display(); // actually display all of the above
}
void printToOledProgMode() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
drawProgressbar(0,56,120,8, progressCounter );
display.display();
}
void drawProgressbar(int x, int y, int width, int height, int progress)
{
progress = progress > 100 ? 100 : progress;
progress = progress < 0 ? 0 : progress;
float bar = ((float)(width - 1) / 100) * progress;
display.drawRect(x, y, width, height, WHITE);
display.fillRect(x + 2, y + 2, bar, height - 4, WHITE);
// Display progress text
if ( height >= 15) {
display.setCursor((width / 2) - 3, y + 5 );
display.setTextSize(1);
display.setTextColor(WHITE);
if ( progress >= 50)
display.setTextColor(BLACK, WHITE); // 'inverted' text
display.print(progress);
display.print("%");
}
}
void setup()
{
Serial.begin( 115200 );
Serial.printf("-------------- init ------------------");
// This tells the library that the encoder has its own pull-up resistors
rotaryEncoder.setEncoderType( EncoderType::HAS_PULLUP );
// The encoder will only return -1, 0, or 1, and will not wrap around.
rotaryEncoder.setBoundaries( -1, 1, false );
// The function specified here will be called every time the knob is turned
// and the current value will be passed to it
rotaryEncoder.onTurned( &knobCallback );
// The function specified here will be called every time the button is pushed and
// the duration (in milliseconds) that the button was down will be passed to it
rotaryEncoder.onPressed( &buttonCallback );
// This is where the inputs are configured and the interrupts get attached
rotaryEncoder.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
printToOled();
//printToOledProgMode();
}
void loop()
{
if ( turnedRightFlag )
turnedRight();
else if ( turnedLeftFlag )
turnedLeft();
if (progMode && 1==1){
progressCounter--;
printToOledProgMode();
if (progressCounter<1){
progMode=false;
printToOled();
}
}
delay(1);
}