initial commit

This commit is contained in:
Ultrablob 2025-01-20 10:58:40 -05:00
commit 62d5adbd76
11 changed files with 607 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.pio
.vscode/
Documents/
CAD/

10
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

5
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"files.associations": {
"*.tcc": "cpp"
}
}

51
diagram.json Normal file
View file

@ -0,0 +1,51 @@
{
"version": 1,
"author": "Anonymous maker",
"editor": "wokwi",
"parts": [
{ "type": "board-esp32-devkit-c-v4", "id": "esp", "top": -38.4, "left": 81.64, "attrs": {} },
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": 6.2,
"left": -115.2,
"attrs": { "color": "red" }
},
{
"type": "wokwi-pushbutton",
"id": "btn2",
"top": 54.2,
"left": -115.2,
"attrs": { "color": "yellow" }
},
{
"type": "wokwi-pushbutton",
"id": "btn3",
"top": 102.2,
"left": -115.2,
"attrs": { "color": "green" }
},
{
"type": "wokwi-lcd2004",
"id": "lcd1",
"top": -281.6,
"left": 53.6,
"attrs": { "pins": "i2c" }
}
],
"connections": [
[ "esp:TX", "$serialMonitor:RX", "", [] ],
[ "esp:RX", "$serialMonitor:TX", "", [] ],
[ "btn2:2.r", "esp:27", "gold", [ "h0" ] ],
[ "btn1:2.r", "esp:CMD", "black", [ "h9.8", "v0.2" ] ],
[ "esp:CMD", "btn2:1.r", "black", [ "h-124.65", "v-86.4" ] ],
[ "btn3:1.r", "esp:CMD", "black", [ "v0", "h9.8", "v38.4" ] ],
[ "btn3:2.r", "esp:14", "green", [ "h67.4", "v0.2" ] ],
[ "btn1:1.r", "esp:26", "#8f4814", [ "v0", "h19.4", "v57.6" ] ],
[ "lcd1:GND", "esp:CMD", "black", [ "h-48", "v403.2", "h-28.8" ] ],
[ "lcd1:VCC", "esp:3V3", "red", [ "h-38.4", "v0.1" ] ],
[ "lcd1:SDA", "esp:21", "green", [ "h-28.8", "v173", "h172.8", "v48" ] ],
[ "lcd1:SCL", "esp:22", "green", [ "h-19.2", "v153.9", "h172.8", "v67.2" ] ]
],
"dependencies": {}
}

67
display.ino Normal file
View file

@ -0,0 +1,67 @@
// GxEPD2_HelloWorld.ino by Jean-Marc Zingg
//
// Display Library example for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
//
// Display Library based on Demo Example from Good Display: https://www.good-display.com/companyfile/32/
//
// Author: Jean-Marc Zingg
//
// Version: see library.properties
//
// Library: https://github.com/ZinggJM/GxEPD2
// Supporting Arduino Forum Topics (closed, read only):
// Good Display ePaper for Arduino: https://forum.arduino.cc/t/good-display-epaper-for-arduino/419657
// Waveshare e-paper displays with SPI: https://forum.arduino.cc/t/waveshare-e-paper-displays-with-spi/467865
//
// Add new topics in https://forum.arduino.cc/c/using-arduino/displays/23 for new questions and issues
// see GxEPD2_wiring_examples.h for wiring suggestions and examples
// if you use a different wiring, you need to adapt the constructor parameters!
// uncomment next line to use class GFX of library GFX_Root instead of Adafruit_GFX
//#include <GFX.h>
#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold24pt7b.h>
// alternately you can copy the constructor from GxEPD2_display_selection.h or GxEPD2_display_selection_added.h to here
// e.g. for Wemos D1 mini:
GxEPD2_BW<GxEPD2_750_T7, GxEPD2_750_T7::HEIGHT> display(GxEPD2_750_T7(/*CS=5*/ 5, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
// for handling alternative SPI pins (ESP32, RP2040) see example GxEPD2_Example.ino
char HelloWorld[] = "Hello World!";
void setup()
{
delay(1000);
//display.init(115200); // default 10ms reset pulse, e.g. for bare panels with DESPI-C02
display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
updateMessage(HelloWorld);
display.hibernate();
}
void updateMessage(char text[])
{
display.setRotation(0);
display.setFont(&FreeMonoBold24pt7b);
display.setTextColor(GxEPD_BLACK);
int16_t tbx, tby; uint16_t tbw, tbh;
display.getTextBounds(text, 0, 0, &tbx, &tby, &tbw, &tbh);
// center the bounding box by transposition of the origin:
uint16_t x = ((display.width() - tbw) / 2) - tbx;
uint16_t y = ((display.height() - tbh) / 2) - tby;
display.setFullWindow();
display.firstPage();
do
{
display.fillScreen(GxEPD_WHITE);
display.setCursor(x, y);
display.print(text);
}
while (display.nextPage());
}
void loop() {};

4
libraries.txt Normal file
View file

@ -0,0 +1,4 @@
# Wokwi Library List
# See https://docs.wokwi.com/guides/libraries
LiquidCrystal I2C

19
platformio.ini Normal file
View file

@ -0,0 +1,19 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32]
platform = espressif32
framework = arduino
board = esp32dev
lib_deps =
zinggjm/GxEPD2
; marcoschwartz/LiquidCrystal_I2C@^1.1.4
ncmreynolds/wordwrap
blynkkk/Blynk

232
sketch.backup Normal file
View file

@ -0,0 +1,232 @@
#define BLYNK_PRINT Serial
#define BLYNK_TEMPLATE_ID "TMPL2TbG1EPUc"
#define BLYNK_TEMPLATE_NAME "Feedback Machine"
#define BLYNK_AUTH_TOKEN "X0ZcPLZjfDvRN1SsEFzvfGG91iKy4mlQ"
#include <BlynkSimpleEsp32.h>
#include <LiquidCrystal_I2C.h>
#include <Preferences.h>
#include "Wire.h"
#define GOOD 14
#define OK 27
#define BAD 26
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define SSID "Wokwi-GUEST"
#define PASSWORD ""
String question = "Generic Question";
int positiveFeedback = 0;
int negativeFeedback = 0;
bool blynkConnected = false;
Preferences preferences;
void setup() {
pinMode(BAD, INPUT_PULLUP);
pinMode(OK, INPUT_PULLUP);
pinMode(GOOD, INPUT_PULLUP);
Serial.begin(115200);
preferences.begin("feedback", false);
lcd.init();
lcd.print("Connecting to WIFI");
Blynk.begin(BLYNK_AUTH_TOKEN, SSID, PASSWORD);
while (!blynkConnected) {
delay(100);
}
lcd.setCursor(0,0);
lcd.print("Initializing Data ");
preferences.putInt("bad", 0);
preferences.putInt("ok", 0);
preferences.putInt("good", 0);
}
void loop() {
//wait for a second
while (true) {
delay(10);
if (digitalRead(GOOD) == LOW) {
preferences.putInt("good", preferences.getInt("good") + 1);
Blynk.virtualWrite(V0, preferences.getInt("good"));
break;
} else if (digitalRead(OK) == LOW) {
preferences.putInt("ok", preferences.getInt("ok") + 1);
Blynk.virtualWrite(V1, preferences.getInt("ok"));
break;
} else if (digitalRead(BAD) == LOW) {
preferences.putInt("bad", preferences.getInt("bad") + 1);
Blynk.virtualWrite(V2, preferences.getInt("bad")); //! fix this duplication later
break;
}
Blynk.run();
}
// tell the screen to write on the top row
lcd.setCursor(0,3);
lcd.print("Feedback sent!");
delay(1000);
lcd.setCursor(0,3);
lcd.print(" ");
}
BLYNK_CONNECTED()
{
blynkConnected = true;
Blynk.syncVirtual(V10);
}
BLYNK_WRITE(V10) {
lcd.clear();
String newQuestion = param.asString();
if (newQuestion.length() > 20) {
lcd.print(newQuestion.substring(0, 20));
lcd.setCursor(0,1);
lcd.print(newQuestion.substring(20));
} else {
lcd.println(newQuestion);
}
if (!blynkConnected) {
return;
}
preferences.putInt("bad", 0);
preferences.putInt("ok", 0);
preferences.putInt("good", 0);
Blynk.virtualWrite(V0, 0);
Blynk.virtualWrite(V1, 0);
Blynk.virtualWrite(V2, 0);
}
#define BLYNK_TEMPLATE_ID "TMPL2TbG1EPUc"
#define BLYNK_TEMPLATE_NAME "Feedback Machine"
#define BLYNK_AUTH_TOKEN "X0ZcPLZjfDvRN1SsEFzvfGG91iKy4mlQ"
#include <BlynkSimpleEsp32.h>
#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold24pt7b.h>
#include <Preferences.h>
#include "Wire.h"
#define GOOD 14
#define OK 27
#define BAD 26
GxEPD2_BW<GxEPD2_750_T7, GxEPD2_750_T7::HEIGHT> display(GxEPD2_750_T7(/*CS=5*/ 5, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
#define SSID "Wokwi-GUEST"
#define PASSWORD ""
String question = "Generic Question";
int positiveFeedback = 0;
int negativeFeedback = 0;
bool blynkConnected = false;
Preferences preferences;
void setup() {
pinMode(BAD, INPUT_PULLUP);
pinMode(OK, INPUT_PULLUP);
pinMode(GOOD, INPUT_PULLUP);
Serial.begin(115200);
preferences.begin("feedback", false);
display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
updateMessage("Initializing...");
Blynk.begin(BLYNK_AUTH_TOKEN, SSID, PASSWORD);
preferences.putInt("bad", 0);
preferences.putInt("ok", 0);
preferences.putInt("good", 0);
}
void loop() {
//wait for a second
while (true) {
delay(10);
if (digitalRead(GOOD) == LOW) {
preferences.putInt("good", preferences.getInt("good") + 1);
Blynk.virtualWrite(V0, preferences.getInt("good"));
break;
} else if (digitalRead(OK) == LOW) {
preferences.putInt("ok", preferences.getInt("ok") + 1);
Blynk.virtualWrite(V1, preferences.getInt("ok"));
break;
} else if (digitalRead(BAD) == LOW) {
preferences.putInt("bad", preferences.getInt("bad") + 1);
Blynk.virtualWrite(V2, preferences.getInt("bad")); //! fix this duplication later
break;
}
Blynk.run();
}
delay(1000);
}
void updateMessage(const char text[])
{
display.setRotation(0);
display.setFont(&FreeMonoBold24pt7b);
display.setTextColor(GxEPD_BLACK);
int16_t tbx, tby; uint16_t tbw, tbh;
display.getTextBounds(text, 0, 0, &tbx, &tby, &tbw, &tbh);
// center the bounding box by transposition of the origin:
uint16_t x = ((display.width() - tbw) / 2) - tbx;
uint16_t y = ((display.height() - tbh) / 2) - tby;
display.setFullWindow();
display.firstPage();
do
{
display.fillScreen(GxEPD_WHITE);
display.setCursor(x, y);
display.print(text);
}
while (display.nextPage());
}
BLYNK_CONNECTED()
{
blynkConnected = true;
Blynk.syncVirtual(V10);
}
BLYNK_WRITE(V10) {
updateMessage(param.asStr());
display.hibernate();
if (!blynkConnected) {
return;
}
preferences.putInt("bad", 0);
preferences.putInt("ok", 0);
preferences.putInt("good", 0);
Blynk.virtualWrite(V0, 0);
Blynk.virtualWrite(V1, 0);
Blynk.virtualWrite(V2, 0);
}

211
src/sketch.ino Normal file
View file

@ -0,0 +1,211 @@
#define BLYNK_TEMPLATE_ID "TMPL2TbG1EPUc"
#define BLYNK_TEMPLATE_NAME "Feedback Machine"
#define BLYNK_AUTH_TOKEN "X0ZcPLZjfDvRN1SsEFzvfGG91iKy4mlQ"
#include <BlynkSimpleEsp32.h>
#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold24pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <Preferences.h>
#include "Wire.h"
#include <wordwrap.h>
#define GOOD 13
#define OK 12
#define BAD 14
GxEPD2_BW<GxEPD2_750_T7, GxEPD2_750_T7::HEIGHT> display(GxEPD2_750_T7(/*CS=5*/ 5, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
#define SSID "IHDSB.CA"
#define PASSWORD "HDSBsecure"
String question = "Generic Question";
bool blynkConnected = false;
bool disabled = false;
Preferences preferences;
void setup() {
pinMode(BAD, INPUT_PULLUP);
pinMode(OK, INPUT_PULLUP);
pinMode(GOOD, INPUT_PULLUP);
preferences.begin("feedback", false);
wordwrap.crlf = false;
display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
updateMessage("Connecting to WiFi...");
Blynk.begin(BLYNK_AUTH_TOKEN, SSID, PASSWORD);
int retries = 0;
while (!Blynk.connected()) {
delay(100);
retries++;
if (retries == 600) {
updateSubtitle("Error 23");
}
}
if (retries >= 600) {
clearSubtitle();
}
// preferences.putInt("bad", 0);
// preferences.putInt("ok", 0);
// preferences.putInt("good", 0);
delay(2000);
}
void loop() {
//wait for a second
while (true) {
delay(10);
if (disabled) {
continue;
}
if (digitalRead(GOOD) == LOW) {
preferences.putInt("good", preferences.getInt("good") + 1);
Blynk.virtualWrite(V0, preferences.getInt("good"));
break;
} else if (digitalRead(OK) == LOW) {
preferences.putInt("ok", preferences.getInt("ok") + 1);
Blynk.virtualWrite(V1, preferences.getInt("ok"));
break;
} else if (digitalRead(BAD) == LOW) {
preferences.putInt("bad", preferences.getInt("bad") + 1);
Blynk.virtualWrite(V2, preferences.getInt("bad")); //! fix this duplication later
break;
}
Blynk.run();
}
updateSubtitle("Thank you for your feedback!");
delay(1000);
clearSubtitle();
}
void updateSubtitle(const char message[]) {
display.setPartialWindow(0, 440, display.width(), 40);
display.firstPage();
int16_t tbx, tby;
uint16_t tbw, tbh;
display.getTextBounds(message, 0, 0, &tbx, &tby, &tbw, &tbh);
do
{
display.fillScreen(GxEPD_WHITE);
display.setCursor(((display.width() - tbw) / 2) - tbx, 460);
display.setFont(&FreeMonoBold12pt7b);
display.print(message);
} while (display.nextPage());
}
void clearSubtitle()
{
display.firstPage();
do
{
display.fillScreen(GxEPD_WHITE);
} while (display.nextPage());
}
void updateMessage(const char text[])
{
// Define the maximum number of characters per line
const int maxLineLength = 25;
char wrappedText[128]; // Adjust size as needed
wordwrap.wrap(text, maxLineLength).toCharArray(wrappedText, 128);
display.setRotation(0);
display.setFont(&FreeMonoBold24pt7b);
display.setTextColor(GxEPD_BLACK);
// Calculate the bounding box for the entire wrapped text
int16_t tbx, tby;
uint16_t tbw, tbh;
display.getTextBounds(wrappedText, 0, 0, &tbx, &tby, &tbw, &tbh);
// Calculate the x-coordinate to center the text
uint16_t x = ((display.width() - tbw) / 2) - tbx;
// Calculate the y-coordinate for the first line
uint16_t y = ((display.height() - tbh) / 2) - tby;
display.setFullWindow();
display.firstPage();
do
{
display.fillScreen(GxEPD_WHITE);
// Print each line separately
char *line = strtok(wrappedText, "\n");
uint16_t lineHeight = 40; // Adjust this value based on your font size
while (line != NULL)
{
display.setCursor(x, y);
display.print(line);
y += lineHeight; // Move y-coordinate down for the next line
line = strtok(NULL, "\n");
}
}
while (display.nextPage());
}
BLYNK_CONNECTED()
{
Blynk.syncVirtual(V10);
}
BLYNK_WRITE(V10) {
if (strlen(param.asStr()) > 100) {
updateSubtitle("Error 31");
return;
}
updateMessage(param.asStr());
preferences.putInt("bad", 0);
preferences.putInt("ok", 0);
preferences.putInt("good", 0);
Blynk.virtualWrite(V0, 0);
Blynk.virtualWrite(V1, 0);
Blynk.virtualWrite(V2, 0);
}
BLYNK_WRITE(V9) {
if (param.asInt() == 0) {
disabled = false;
clearSubtitle();
}
if (param.asInt() == 1) {
disabled = true;
updateMessage("Out of Order");
updateSubtitle("Error 42");
}
}

4
wokwi.toml Normal file
View file

@ -0,0 +1,4 @@
[wokwi]
version = 1
elf = ".pio/build/esp32/firmware.elf"
firmware = ".pio/build/esp32/firmware.bin"