Browse Source

Release beta version 0.9

master
gituser 1 week ago
parent
commit
4f395cc4cc
6 changed files with 194 additions and 88 deletions
  1. 88
    35
      Display.cpp
  2. 12
    6
      Display.h
  3. 15
    7
      EchoLot.ino
  4. 76
    35
      EchoLotSetup.cpp
  5. 2
    4
      EchoLotSetup.h
  6. 1
    1
      sloeber.ino.cpp

+ 88
- 35
Display.cpp View File

****************/ ****************/
Display::Display() : tft(Adafruit_ST7735(CS, DC, RST)) { // @suppress("Abstract class cannot be instantiated") Display::Display() : tft(Adafruit_ST7735(CS, DC, RST)) { // @suppress("Abstract class cannot be instantiated")
starttime = 0; starttime = 0;
configValue = 0.0;
configUnit = "m/s"; configUnit = "m/s";
distance = 0; distance = 0;
environment = 1; environment = 1;
drawXCenteredText("EchoLoT", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 36); drawXCenteredText("EchoLoT", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 36);
drawXCenteredText("designed by", &FreeSans9pt7b, 1, ST7735_WHITE, 64); drawXCenteredText("designed by", &FreeSans9pt7b, 1, ST7735_WHITE, 64);
showBrand(16, 84); showBrand(16, 84);
delay(500);
delay(2000);


redrawFrame(); redrawFrame();
drawText("powered by", &FreeSans9pt7b, 1, ST7735_CYAN, 35, 30); drawText("powered by", &FreeSans9pt7b, 1, ST7735_CYAN, 35, 30);
tft.fillRoundRect(46, 42, 68, 68, 7, ST7735_STM32BLUE); tft.fillRoundRect(46, 42, 68, 68, 7, ST7735_STM32BLUE);
drawBitmap(48, 44, 64, 64, epd_bitmap_stm32duino_logo_icon, ST7735_WHITE); drawBitmap(48, 44, 64, 64, epd_bitmap_stm32duino_logo_icon, ST7735_WHITE);

// tft.drawBitmap(5, 100, epd_bitmap_gear, 24, 24, ST7735_YELLOW);
// tft.drawBitmap(40, 100, epd_bitmap_Zzz_24, 24, 24, ST7735_CYAN);
// tft.drawBitmap(75, 100, epd_bitmap_Measure_25, 25, 25, ST7735_RED);
// tft.fillTriangle(75, 98, 80, 102, 75, 107, ST7735_RED);
// tft.fillTriangle(82, 98, 87, 102, 82, 107, ST7735_RED);
// tft.fillTriangle(89, 98, 94, 102, 89, 107, ST7735_RED);
// tft.fillTriangle(96, 98, 101, 102, 96, 107, ST7735_RED);
//
// tft.drawBitmap(110, 100, epd_bitmap_air, 24, 24, ST7735_CYAN);
// tft.drawBitmap(110, 100, epd_bitmap_water, 24, 24, ST7735_BLUE);
// tft.drawBitmap(110, 100, epd_bitmap_water_s, 24, 24, ST7735_BLUE);
// tft.drawBitmap(1, 160 - 32, thermometer_icon_32, 32, 32, 0xE71C);

delay(500);
delay(2000);
} }


void Display::display(void) { void Display::display(void) {
} }
} }


void Display::setStatusValues(float airTemp, float waterTemp) {
void Display::setStatusValues(float airTemp, float waterTemp, float sonicSpeedAir, uint8_t saltPromilleWater) {
this->airTemp = airTemp; this->airTemp = airTemp;
this->waterTemp = waterTemp; this->waterTemp = waterTemp;
this->sonicSpeedAir = sonicSpeedAir;
this->saltPromilleWater = saltPromilleWater;
} }


void Display::setEnvironment(int environment) { void Display::setEnvironment(int environment) {
if (this->environment != environment) { if (this->environment != environment) {
this->environment = environment; this->environment = environment;
redrawEnvIcon(); redrawEnvIcon();
redrawTempIcon();
} }
} }


} }
} }


void Display::setConfigOption(String configOption) {
if (!this->configOption.equals(configOption)) {
this->configOption = configOption;
redrawConfigOption();
}
}

void Display::setConfigText(String configText) {
if (!this->configValue.equals(configText)) {
this->configValue = configText;
redrawConfigValue();
}
}

void Display::setConfigUnit(String configUnit) {
if (!this->configUnit.equals(configUnit)) {
this->configUnit = configUnit;
redrawConfigUnit();
}

}

/* ===== Private methods ===== */ /* ===== Private methods ===== */
void Display::drawBitmap(int x, int y, int w, int h, const uint8_t bitmap[], uint16_t col) { void Display::drawBitmap(int x, int y, int w, int h, const uint8_t bitmap[], uint16_t col) {
tft.drawBitmap(x, y, bitmap, w, h, col); tft.drawBitmap(x, y, bitmap, w, h, col);
tft.drawRoundRect(1, 1, 158, 126, 8, ST7735_CYAN); tft.drawRoundRect(1, 1, 158, 126, 8, ST7735_CYAN);
} }


void Display::redrawGrid() {
void Display::redrawGrid(bool cfg) {
redrawFrame(); redrawFrame();
tft.drawLine(0, 31, 160, 31, ST7735_CYAN); tft.drawLine(0, 31, 160, 31, ST7735_CYAN);
tft.drawLine(0, 32, 160, 32, ST7735_CYAN); tft.drawLine(0, 32, 160, 32, ST7735_CYAN);
tft.drawLine(0, 89, 160, 89, ST7735_CYAN); tft.drawLine(0, 89, 160, 89, ST7735_CYAN);
tft.drawLine(0, 90, 160, 90, ST7735_CYAN); tft.drawLine(0, 90, 160, 90, ST7735_CYAN);
tft.drawLine(80, 90, 80, 128, ST7735_CYAN);
tft.drawLine(81, 90, 81, 128, ST7735_CYAN);
tft.drawLine(cfg ? 120 : 80, 90, cfg ? 120 : 80, 128, ST7735_CYAN);
tft.drawLine(cfg ? 121 : 81, 90, cfg ? 121 : 81, 128, ST7735_CYAN);
} }


void Display::redrawIdleStatus() { void Display::redrawIdleStatus() {
tft.drawBitmap(25, 4, epd_bitmap_Zzz_24, 24, 24, ST7735_CYAN); tft.drawBitmap(25, 4, epd_bitmap_Zzz_24, 24, 24, ST7735_CYAN);
drawText("OPERATIV", &titillium_web_semibold8pt7b, 1, ST7735_WHITE, 55, 21); drawText("OPERATIV", &titillium_web_semibold8pt7b, 1, ST7735_WHITE, 55, 21);


float temp = environment == 1 ? airTemp : waterTemp;
uint16_t col = temp <= 17.0 ? ST7735_WHITE : temp <= 24.0 ? ST7735_GREEN : ST7735_ORANGE;
uint16_t thH = temp <= 17.0 ? 0 : temp <= 24.0 ? 5 : 9;
tft.drawBitmap(0, 92, thermometer_icon_32, 32, 32, col);
tft.drawRect(15, 107 - thH, 2, thH, col);
drawText(String(temp, 1), &titillium_web_semibold8pt7b, 1, col, 35, 114);
drawCircle(72, 102, 2, col);
// float temp = environment == 1 ? airTemp : waterTemp;
// uint16_t col = temp <= 17.0 ? ST7735_WHITE : temp <= 24.0 ? ST7735_GREEN : ST7735_ORANGE;
// uint16_t thH = temp <= 17.0 ? 0 : temp <= 24.0 ? 5 : 9;
// tft.drawBitmap(0, 92, thermometer_icon_32, 32, 32, col);
// tft.drawRect(15, 107 - thH, 2, thH, col);
// drawRightAlignedText(String(temp, 1), &titillium_web_semibold8pt7b, 1, col, 96, 114);
// drawCircle(72, 104, 2, col);
redrawTempIcon();
redrawEnvIcon(); redrawEnvIcon();
redrawDistance(); redrawDistance();
} }


void Display::redrawConfigStatus() { void Display::redrawConfigStatus() {
redrawGrid();
redrawGrid(true);
tft.drawBitmap(35, 4, epd_bitmap_gear, 24, 24, ST7735_YELLOW); tft.drawBitmap(35, 4, epd_bitmap_gear, 24, 24, ST7735_YELLOW);
drawText("KONFIG.", &titillium_web_semibold8pt7b, 1, ST7735_WHITE, 65, 21);
drawText("KONFIG.", &titillium_web_semibold8pt7b, 1, ST7735_YELLOW, 65, 21);

redrawConfigValue();
redrawConfigOption();
redrawConfigUnit();
} }


void Display::redrawEnvIcon() { void Display::redrawEnvIcon() {
tft.drawBitmap(108, 97, environmentIcon, 24, 24, col); tft.drawBitmap(108, 97, environmentIcon, 24, 24, col);
} }


void Display::redrawTempIcon() {
float temp = environment == 1 ? airTemp : waterTemp;
uint16_t col = temp <= 17.0 ? ST7735_WHITE : temp <= 24.0 ? ST7735_GREEN : ST7735_ORANGE;
uint16_t thH = temp <= 17.0 ? 0 : temp <= 24.0 ? 5 : 9;
tft.fillRect(4, 92, 75, 30, ST7735_BLACK);
tft.drawBitmap(0, 92, thermometer_icon_32, 32, 32, col);
tft.drawRect(15, 107 - thH, 2, thH, col);
drawRightAlignedText(String(temp, 1), &titillium_web_semibold8pt7b, 1, col, 96, 114);
drawCircle(72, 104, 2, col);
}

void Display::runMeasureAnimation(bool run) { void Display::runMeasureAnimation(bool run) {
if (!this->doMeasureAnimation && run) { if (!this->doMeasureAnimation && run) {
this->starttime = millis(); this->starttime = millis();
} }


void Display::redrawDistance() { void Display::redrawDistance() {
tft.fillRect(4, 34, 152, 56, ST7735_BLACK);
tft.fillRect(4, 34, 152, 54, ST7735_BLACK);
if (distance == 0) { if (distance == 0) {
drawXCenteredText("- - -", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 69);
drawXCenteredText("- - -", &titillium_web_regular16pt7b, 1, ST7735_WHITE, 69);
} else { } else {
if (environment == 1) { if (environment == 1) {
uint16_t dist_CM = distance / 10; uint16_t dist_CM = distance / 10;
drawXCenteredText(String(dist_CM) + " cm", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 69);
drawXCenteredText(String(dist_CM) + " cm", &titillium_web_regular16pt7b, 1, ST7735_WHITE, 69);
} else { } else {
float dist_M = float(distance) / 1000; float dist_M = float(distance) / 1000;
drawXCenteredText(String(dist_M, 1) + " m", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 69);
drawXCenteredText(String(dist_M, 1) + " m", &titillium_web_regular16pt7b, 1, ST7735_WHITE, 69);
} }
} }
} }

void Display::redrawConfigValue() {
tft.fillRect(4, 34, 152, 54, ST7735_BLACK);
drawXCenteredText(configValue, &titillium_web_regular16pt7b, 1, ST7735_ORANGE, 69);
}

void Display::redrawConfigOption() {
tft.fillRect(4, 92, 116, 30, ST7735_BLACK);
drawText(configOption, &titillium_web_semibold8pt7b, 1, ST7735_WHITE, 6, 113);
}

void Display::redrawConfigUnit() {
int16_t x1, y1; // Top-left corner of text
uint16_t w, h; // Width and height
tft.getTextBounds(configUnit, 0, 0, &x1, &y1, &w, &h);

tft.fillRect(123, 92, 35, 30, ST7735_BLACK);
drawRightAlignedText(configUnit, &titillium_web_semibold8pt7b, 1, ST7735_WHITE, (37 - w) / 2 + 2, 113);
if (configUnit.equals(" C")) {
drawCircle(121 + ((37 - w) / 2), 105, 2, ST7735_WHITE);
} else if (configUnit.equals(" / ")) {
drawCircle(124 + ((37 - w) / 2), 105, 2, ST7735_WHITE);
drawCircle(124 + ((37 - w) / 2) + 10, 110, 2, ST7735_WHITE);
drawCircle(124 + ((37 - w) / 2) + 15, 110, 2, ST7735_WHITE);
}

}


+ 12
- 6
Display.h View File

class Display { class Display {
private: private:
Adafruit_ST7735 tft; // @suppress("Abstract class cannot be instantiated") Adafruit_ST7735 tft; // @suppress("Abstract class cannot be instantiated")
String configText;
String configValue;
String configOption; String configOption;
float configValue;
String configUnit; String configUnit;
bool refreshScreen; bool refreshScreen;
bool doMeasureAnimation; bool doMeasureAnimation;
unsigned long starttime; unsigned long starttime;
float airTemp; float airTemp;
float waterTemp; float waterTemp;
float sonicSpeedAir;
uint8_t saltPromilleWater;
int environment; int environment;
uint16_t distance; uint16_t distance;


void drawBitmap(int x, int y, int w, int h, const uint8_t bitmap[], uint16_t col); void drawBitmap(int x, int y, int w, int h, const uint8_t bitmap[], uint16_t col);
void drawRGBBitmap(int x, int y, int w, int h, const uint16_t bitmap[]); void drawRGBBitmap(int x, int y, int w, int h, const uint16_t bitmap[]);
void redrawFrame(); void redrawFrame();
void redrawGrid();
void redrawGrid(bool cfg = false);
void redrawIdleStatus(); void redrawIdleStatus();
void redrawConfigStatus(); void redrawConfigStatus();
void redrawEnvIcon(); void redrawEnvIcon();
void redrawIdleIcon();
void redrawTempIcon();
void redrawDistance(); void redrawDistance();
void redrawConfigValue();
void redrawConfigOption();
void redrawConfigUnit();


public: public:
Display(); Display();
void drawRightAlignedText(String txt, const GFXfont *font, uint8_t s, uint16_t c, int16_t xOffset, int16_t y); void drawRightAlignedText(String txt, const GFXfont *font, uint8_t s, uint16_t c, int16_t xOffset, int16_t y);
void drawText(String txt, const GFXfont *font, uint8_t s, uint16_t c, int16_t x, int16_t y); void drawText(String txt, const GFXfont *font, uint8_t s, uint16_t c, int16_t x, int16_t y);
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color); void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void setStatusValues(float airTemp, float waterTemp);
void setStatusValues(float airTemp, float waterTemp, float sonicSpeedAir, uint8_t saltPromilleWater);
void setEnvironment(int environment); void setEnvironment(int environment);
void setDistance(uint32_t distance); void setDistance(uint32_t distance);
void runMeasureAnimation(bool run); void runMeasureAnimation(bool run);

void setConfigOption(String configOption);
void setConfigText(String configText);
void setConfigUnit(String configUnit);
}; };


#endif /* DISPLAY_H_ */ #endif /* DISPLAY_H_ */

+ 15
- 7
EchoLot.ino View File

void Initialize() { void Initialize() {
display.showInitialization(); display.showInitialization();
echoLotSetup.initialize(); echoLotSetup.initialize();
echoLotSetup.drawInitScreen();
delay(2000);
} }
void setup() { void setup() {
rotaryControler.loop(); rotaryControler.loop();
if (originStatus != CONFIGURATION) { if (originStatus != CONFIGURATION) {
display.setRefreshScreen(); display.setRefreshScreen();
display.showFrame(actualStatus);
echoLotSetup.initialize();
}
if (rotaryControler.isSwitchPressed()) {
echoLotSetup.onRotaryControlerSwitch();
} }
display.showFrame(actualStatus);
echoLotSetup.onRotaryControlerTurn(rotaryControler.getEncoderMove()); echoLotSetup.onRotaryControlerTurn(rotaryControler.getEncoderMove());
if (rotaryControler.isSwitchLongPressed()) { if (rotaryControler.isSwitchLongPressed()) {
Serial.println("RotaryEnc Long SwitchPressed"); Serial.println("RotaryEnc Long SwitchPressed");
delay(50); delay(50);
// TODO: Save the edited config values
echoLotSetup.onRotaryControlerLongSwitch();
echoLotSetup.initialize();
SetActualStatus(IDLE); SetActualStatus(IDLE);
} }
SetActualStatus(CONFIGURATION); SetActualStatus(CONFIGURATION);
} }
environmentPostion = threePositionSwitch.getPosition();
display.setEnvironment(environmentPostion);
if (measureBtn.isPressing()) { if (measureBtn.isPressing()) {
SetActualStatus(MEASURING); SetActualStatus(MEASURING);
} }
environmentPostion = threePositionSwitch.getPosition();
display.setEnvironment(environmentPostion);
originStatus = IDLE; originStatus = IDLE;
delay(50); delay(50);
break; break;
delayMicroseconds(20); delayMicroseconds(20);
digitalWrite(trigPin, LOW); digitalWrite(trigPin, LOW);
//TODO: calculate real distanz according settings
uint32_t duration = pulseIn(echoPin, HIGH); uint32_t duration = pulseIn(echoPin, HIGH);
uint32_t distance = calculateDistance(duration); uint32_t distance = calculateDistance(duration);
display.setDistance(distance); display.setDistance(distance);
display.runMeasureAnimation(true);
delay(200); delay(200);
} else { } else {
display.setDistance(0); display.setDistance(0);

+ 76
- 35
EchoLotSetup.cpp View File

*/ */


#include "EchoLotSetup.h" #include "EchoLotSetup.h"
#include "fonts/titillium_web_regular16pt7b.h"
#include "fonts/FreeSans7pt7b.h" #include "fonts/FreeSans7pt7b.h"
//#include <Fonts/FreeSans9pt7b.h>


#define ADDR_AIR_TEMP 0 // WORD #define ADDR_AIR_TEMP 0 // WORD
#define ADDR_WATER_TEMP 2 // +2 WORDs #define ADDR_WATER_TEMP 2 // +2 WORDs
// Initialisierung // Initialisierung
// -------------------------------------------------- // --------------------------------------------------
void EchoLotSetup::initialize() { void EchoLotSetup::initialize() {
EEPROM.init();
readFromEEPROM();
display.setStatusValues(airTemp, waterTemp);

display.clearDisplay();
display.showFrame(INITIALIZATION);
printValues();
delay(2000);
if (doInitialization) {
EEPROM.init();
readFromEEPROM();
configStepIndex = 0;


configStepIndex = 0;
doInitialization = false;
String stepTxt = ConfigStep[configStepIndex];
String unit = getCfgOptUnitForStepIndex(configStepIndex);
display.setStatusValues(airTemp, waterTemp, sonicSpeedAir, saltPromilleWater);
display.setConfigText(String(airTemp, 1));
display.setConfigOption(stepTxt);
display.setConfigUnit(unit);
doInitialization = false;
}
} }


// -------------------------------------------------- // --------------------------------------------------
// -------------------------------------------------- // --------------------------------------------------
void EchoLotSetup::onRotaryControlerSwitch() { void EchoLotSetup::onRotaryControlerSwitch() {
configStepIndex++; configStepIndex++;
if (configStepIndex >= 5) {
if (configStepIndex > 3) {
configStepIndex = 0; configStepIndex = 0;
} }

display.setConfigText(getCfgValueForStepIndex(configStepIndex));
display.setConfigOption(ConfigStep[configStepIndex]);
display.setConfigUnit(getCfgOptUnitForStepIndex(configStepIndex));
} }


// -------------------------------------------------- // --------------------------------------------------
// Rotary Switch (lang) // Rotary Switch (lang)
// -------------------------------------------------- // --------------------------------------------------
void EchoLotSetup::onRotaryControlerLongSwitch() { void EchoLotSetup::onRotaryControlerLongSwitch() {

save();
doInitialization = true;
} }


// -------------------------------------------------- // --------------------------------------------------
// Rotary Drehung // Rotary Drehung
// -------------------------------------------------- // --------------------------------------------------
void EchoLotSetup::onRotaryControlerTurn(RotaryEncoder::Direction turn)
{
float delta = (turn == RotaryEncoder::Direction::CLOCKWISE) ? 1.0f : -1.0f;
void EchoLotSetup::onRotaryControlerTurn(RotaryEncoder::Direction turn) {


switch (configStepIndex) {
case 0:
airTemp += delta;
break;
case 1:
waterTemp += delta;
break;
case 2:
sonicSpeedAir += delta;
break;
case 3:
saltPromilleWater += delta;
break;
default:
break;
if (turn != RotaryEncoder::Direction::NOROTATION) {

String value = "";
int index = 0;
int sign = (turn == RotaryEncoder::Direction::CLOCKWISE) ? 1 : -1;

switch (configStepIndex) {
case 0:
setAirTemp(min(max(0.0, getAirTemp() + 0.5 * sign), 40.0));
value = String(getAirTemp(), 1);
break;
case 1:
setWaterTemp(min(max(0.0, getWaterTemp() + 0.5 * sign), 40.0));
value = String(getWaterTemp(), 1);
break;
case 2:
setSonicSpeedAir(min(max(330.0, getSonicSpeedAir() + 0.5 * sign), 343.5));
value = String(getSonicSpeedAir(), 1);
break;
case 3:
setSaltPromilleWater(min(max(0, getSaltPromilleWater() + sign), 50));
value = String(getSaltPromilleWater());
break;
default:
break;
}

display.setConfigText(value);
} }


} }
// Abbrechen // Abbrechen
// -------------------------------------------------- // --------------------------------------------------
void EchoLotSetup::cancel() { void EchoLotSetup::cancel() {
readFromEEPROM();
doInitialization = true;
} }


// -------------------------------------------------- // --------------------------------------------------
display.clearDisplay(); display.clearDisplay();
} }


// --------------------------------------------------
// Initial screen zeichnen
// --------------------------------------------------
void EchoLotSetup::drawInitScreen() {
display.clearDisplay();
display.showFrame(INITIALIZATION);
printValues();
}

// -------------------------------------------------- // --------------------------------------------------
// EEPROM lesen // EEPROM lesen
// -------------------------------------------------- // --------------------------------------------------
switch (index) { switch (index) {
case 0: case 0:
case 1: case 1:
return "°C";
return " C";
case 2: case 2:
case 3:
return "m/s"; return "m/s";
default: default:
return "";
return " / "; // for Promille painting
}
}

String EchoLotSetup::getCfgValueForStepIndex(byte configStepIndex) {
switch (configStepIndex) {
case 0:
return String(getAirTemp(), 1);
case 1:
return String(getWaterTemp(), 1);
case 2:
return String(getSonicSpeedAir(), 1);
case 3:
return String(getSaltPromilleWater());
default:
return "- - -";
} }
} }



+ 2
- 4
EchoLotSetup.h View File

byte configStepIndex; byte configStepIndex;
String getCfgOptForStepIndex(byte configStepIndex); String getCfgOptForStepIndex(byte configStepIndex);
String getCfgOptUnitForStepIndex(byte configStepIndex); String getCfgOptUnitForStepIndex(byte configStepIndex);
String getCfgValueForStepIndex(byte configStepIndex);


void writeFloatToEEPROM(uint16_t addr, float value); void writeFloatToEEPROM(uint16_t addr, float value);
float readFloatFromEEPROM(uint16_t addr); float readFloatFromEEPROM(uint16_t addr);
int readIntegerFromEEPROM(uint16_t addr); int readIntegerFromEEPROM(uint16_t addr);


public: public:
// int eeprom_start_adress = 0;
const static int eeprom_signatur = 1024;
const static uint8_t version = 1;

EchoLotSetup(Display &display); EchoLotSetup(Display &display);
void initialize(); void initialize();
void drawInitScreen();
void onRotaryControlerSwitch(); void onRotaryControlerSwitch();
void onRotaryControlerLongSwitch(); void onRotaryControlerLongSwitch();
void onRotaryControlerTurn(RotaryEncoder::Direction turn); void onRotaryControlerTurn(RotaryEncoder::Direction turn);

+ 1
- 1
sloeber.ino.cpp View File

//This is a automatic generated file //This is a automatic generated file
//Please do not modify this file //Please do not modify this file
//If you touch this file your change will be overwritten during the next build //If you touch this file your change will be overwritten during the next build
//This file has been generated on 2026-01-25 22:30:05
//This file has been generated on 2026-01-27 21:30:42


#include "Arduino.h" #include "Arduino.h"
#include "Arduino.h" #include "Arduino.h"

Loading…
Cancel
Save