commit 78f90b4f6ac2341237677f54611fcf7d61cd305f Author: Gordon Bolton Date: Tue Jun 25 21:04:22 2024 +0100 Migrated project to vscode/platformio diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -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" + ] +} diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..377b8d0 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,20 @@ +; 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:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino +lib_deps = + waspinator/AccelStepper@^1.64 + marcoschwartz/LiquidCrystal_I2C@^1.1.4 + paulstoffregen/OneWire@^2.3.8 + milesburton/DallasTemperature@^3.11.0 + chris--a/Keypad@^3.1.1 diff --git a/src/.cproject b/src/.cproject new file mode 100644 index 0000000..7f5fb0d --- /dev/null +++ b/src/.cproject @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..dcd90ee --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,2 @@ +/Release/ +/sloeber.ino.cpp diff --git a/src/.project b/src/.project new file mode 100644 index 0000000..322346a --- /dev/null +++ b/src/.project @@ -0,0 +1,75 @@ + + + AutoFilmESP32 + + + + + + io.sloeber.core.inoToCpp + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.core.ccnature + io.sloeber.arduinonature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + core/core + 2 + ECLIPSE_HOME/arduinoPlugin/packages/esp32/hardware/esp32/3.0.1/cores/esp32 + + + core/variant + 2 + ECLIPSE_HOME/arduinoPlugin/packages/esp32/hardware/esp32/3.0.1/variants/esp32 + + + libraries/AccelStepper + 2 + C:/Users/gordon/Documents/Arduino/libraries/AccelStepper + + + libraries/DallasTemperature + 2 + C:/Users/gordon/Documents/Arduino/libraries/DallasTemperature + + + libraries/Keypad + 2 + C:/Users/gordon/Documents/Arduino/libraries/Keypad + + + libraries/LiquidCrystal_I2C + 2 + C:/Users/gordon/Documents/Arduino/libraries/LiquidCrystal_I2C + + + libraries/OneWire + 2 + C:/Users/gordon/Documents/Arduino/libraries/OneWire + + + libraries/Wire + 2 + ECLIPSE_HOME/arduinoPlugin/packages/esp32/hardware/esp32/3.0.1/libraries/Wire + + + diff --git a/src/.settings/language.settings.xml b/src/.settings/language.settings.xml new file mode 100644 index 0000000..842132e --- /dev/null +++ b/src/.settings/language.settings.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/.settings/org.eclipse.core.resources.prefs b/src/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/src/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/src/.sproject b/src/.sproject new file mode 100644 index 0000000..7ef5964 --- /dev/null +++ b/src/.sproject @@ -0,0 +1,29 @@ +Config.Release.board.BOARD.ID=esp32 +Config.Release.board.BOARD.MENU.CPUFreq=240 +Config.Release.board.BOARD.MENU.DebugLevel=error +Config.Release.board.BOARD.MENU.EraseFlash=none +Config.Release.board.BOARD.MENU.EventsCore=0 +Config.Release.board.BOARD.MENU.FlashFreq=80 +Config.Release.board.BOARD.MENU.FlashMode=qio +Config.Release.board.BOARD.MENU.FlashSize=4M +Config.Release.board.BOARD.MENU.JTAGAdapter=bridge +Config.Release.board.BOARD.MENU.LoopCore=1 +Config.Release.board.BOARD.MENU.PSRAM=enabled +Config.Release.board.BOARD.MENU.PartitionScheme=default +Config.Release.board.BOARD.MENU.UploadSpeed=921600 +Config.Release.board.BOARD.MENU.ZigbeeMode=default +Config.Release.board.BOARD.TXT=C:\Users\gordon\Sloeber\arduinoPlugin\packages\esp32\hardware\esp32\3.0.1\boards.txt +Config.Release.board.PROGRAMMER.NAME=Esptool +Config.Release.board.UPLOAD.PORT=COM10 +Config.Release.compile.sloeber.extra.all= +Config.Release.compile.sloeber.extra.archive= +Config.Release.compile.sloeber.extra.assembly= +Config.Release.compile.sloeber.extra.c.compile= +Config.Release.compile.sloeber.extra.compile= +Config.Release.compile.sloeber.extra.cpp.compile= +Config.Release.compile.sloeber.extra.link= +Config.Release.compile.sloeber.size.custom= +Config.Release.compile.sloeber.size.type=RAW_RESULT +Config.Release.compile.sloeber.warning_level=NONE +Config.Release.compile.sloeber.warning_level.custom= +Config.Release.other.IS_VERSION_CONTROLLED=false diff --git a/src/AutoFilmESP32.ino b/src/AutoFilmESP32.ino new file mode 100644 index 0000000..b0422a0 --- /dev/null +++ b/src/AutoFilmESP32.ino @@ -0,0 +1,46 @@ +#include "config.h" +#include "motor.h" +#include "temperature.h" +#include "display.h" +#include "menu.h" +#include "devSequence.h" +#include "sound.h" +#include "watchdog.h" + +// Function declarations +void setup(); +void loop(); + +void setup() { + Serial.begin(115200); + + // Disable the watchdog timers + disableWatchdogTimers(); + + // Initialize LCD + Wire.begin(21, 22); + lcd.init(); + lcd.backlight(); + + lcd.createChar(0, thermometer); + + // Set pin modes + pinMode(EN_PIN, OUTPUT); + digitalWrite(EN_PIN, HIGH); // Disable motor initially + pinMode(beeperPin, OUTPUT); + // Set stepper motor properties + stepper.setMaxSpeed(SPEED); + stepper.setAcceleration(9600); // Set acceleration + + // Display welcome message + lcd.setCursor(6, 1); + lcd.print("AUTOFILM"); + lcd.setCursor((20 - strlen(version)) / 2, 3); + lcd.print(version); + delay(1000); + lcd.clear(); +} + +void loop() { + startingMenu(); +} diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..9d78bd7 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,43 @@ +#include "config.h" + +// Global variables definition +const char* version = "V0.1.0 20240625"; +const byte ROWS = 5; +const byte COLS = 4; +byte rowPins[ROWS] = { 19, 18, 5, 17, 16 }; +byte colPins[COLS] = { 15, 2, 0, 4 }; + +char keys[ROWS][COLS] = { + { 'F', 'E', '#', '*' }, + { '1', '2', '3', 'U' }, + { '4', '5', '6', 'D' }, + { '7', '8', '9', 'X' }, + { 'L', '0', 'R', 'E' } +}; + +Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); +LiquidCrystal_I2C lcd(0x27, LCD_COLUMNS, LCD_ROWS); +AccelStepper stepper(AccelStepper::DRIVER, PULSE_PIN, DIR_PIN); +OneWire oneWire(TEMP_SENSOR_PIN); +DallasTemperature sensors(&oneWire); + +String devPgm = ""; +int run; +const int beeperPin = 25; + +TaskHandle_t motorTaskHandle = NULL; +TaskHandle_t tempTaskHandle = NULL; + +unsigned long processStartTime; +unsigned long processTimeMillis; + +byte thermometer[8] = { + B00100, + B01100, + B00100, + B01100, + B00100, + B01110, + B01110, + B01110 +}; diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..0352c99 --- /dev/null +++ b/src/config.h @@ -0,0 +1,41 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include +#include +#include +#include +#include +#include + +// Constants and definitions +#define LCD_COLUMNS 20 +#define LCD_ROWS 4 +#define PULSE_PIN 12 +#define DIR_PIN 14 +#define EN_PIN 27 +#define STEPS_PER_REV 4800 +#define RPM 60 +#define SPEED (RPM * STEPS_PER_REV / 60.0) +#define TEMP_SENSOR_PIN 13 +#define NUM_DEV_SEQUENCES 6 + +extern const char* version; +extern Keypad keypad; +extern LiquidCrystal_I2C lcd; +extern AccelStepper stepper; +extern OneWire oneWire; +extern DallasTemperature sensors; +extern String devPgm; +extern int run; +extern const int beeperPin; +extern byte thermometer[8]; + +extern TaskHandle_t motorTaskHandle; +extern TaskHandle_t tempTaskHandle; + +extern unsigned long processStartTime; +extern unsigned long processTimeMillis; + +#endif diff --git a/src/devSequence.cpp b/src/devSequence.cpp new file mode 100644 index 0000000..e2af178 --- /dev/null +++ b/src/devSequence.cpp @@ -0,0 +1,103 @@ +#include "devSequence.h" + +struct devSequence devSequences[NUM_DEV_SEQUENCES] = { + { + "C41", + 7, + { 180, 195, 45, 180, 60, 60, 30 }, //processTime + { "Prewarm", "Developer", "Bleach", "Fix", "Rinse 1", "Rinse 2", "Fin Rinse" }, //processName + { + { 1, 5.5, 5.5, 5.5, 3.5, 3.5, 1 }, //CW rotations processCycle + { 1, 5, 5, 5, 3, 3, 1 } + }, //CCW rotations processCycle + { + { 37.8, 37.8, 32, 32, 32, 32, 32 }, //min processTemp + { 38, 38, 38, 38, 38, 38, 38 }, //preferred processTemp + { 38.2, 38.2, 38.2, 38.2, 38.2, 38.2, 38.2 } //max processTemp + } + }, + { + "E6", + 12, + {180, 360, 120, 120, 360, 120, 360, 240, 120, 120, 120, 30}, + {"Preheat", "FirstDev", "Wash 1", "Reversal", "ColorDev", "PreBleach", "Bleach", "Fixer", "Wash 2", "Wash 3", "Wash 4", "Fin Rinse"}, + { + {1, 5.5, 3.5, 5, 5.5, 5.5, 5.5, 5.5, 3.5, 3.5, 3.5, 3.5}, + {1, 5, 3, 5.5, 5, 5.5, 5.5, 5.5, 3, 3, 3, 3} + }, + { + {37.5, 37.7, 33.0, 37.7, 37.0, 37, 37.5, 37.5, 33.0, 33.0, 33.0, 19.0}, + {38.0, 38.0, 38.0, 38.0, 38.0, 38.0, 38.0, 38.0, 38.0, 38.0, 38.0, 20.0}, + {38.5, 38.3, 38.0, 38.3, 39.0, 38, 38.5, 38.5, 38.5, 38.5, 38.5, 21.0} + } + }, + { + "ECN-2", + 9, + {180, 0, 210, 60, 180, 150, 120, 300, 120}, + {"Prebath", "RemJet", "Developer", "Stop Bath", "Wash", "Bleach", "Fixer", "Wash 2", "Fin Rinse"}, + { + {1, 0, 5.5, 3.5, 3.5, 5.5, 5.5, 3.5, 1}, + {1, 0, 5, 3, 3, 5, 5, 3, 1} + }, + { + {27.0, 0, 40.8, 27.0, 27.0, 27.0, 27.0, 27.0, 27.0}, + {38.0, 0, 41.0, 38.0, 38.0, 38.0, 38.0, 38.0, 38.0}, + {38.0, 0, 41.2, 38.0, 38.0, 38.0, 38.0, 38.0, 38.0} + } + }, + { + "B&W", + 7, + {510, 30, 300, 60, 90, 120, 30}, + {"Developer", "Stop", "Fix", "Rinse 1", "Rinse 2", "Rinse 3", "Fin Rinse"}, + { + { 5.5, 3.5, 3.5, 3.5, 3.5, 3.5, 1}, + { 5, 3, 3, 3, 3, 3, 1} + }, + { + {19, 19, 19, 19, 19, 19, 19}, + {20, 20, 20, 20, 20, 20, 20}, + {21, 21, 21, 21, 21, 21, 21} + } + }, + { + "Custom", + 4, + {10, 10, 10, 10}, + {"Developer", "Stop", "Fix", "Rinse"}, + { + { 5.5, 3.5, 3.5, 3.5}, + { 5, 3, 3, 3} + }, + { + {19, 19, 19, 19}, + {20, 20, 20, 20}, + {21, 21, 21, 21} + } + }, + { + "B&WREV", + 12, + {720, 300, 300, 60, 120, 60, 120, 360, 60, 300, 60, 60}, + {"FirstDev", "Wash 1", "Bleach", "Wash 2", "Clearing", "Wash 3", "Reversal", "SecondDev", "Wash 4", "Fix", "Wash 5", "Fin Rinse"}, + { + {5.5, 3.5, 5.5, 3.5, 5.5, 3.5, 5.5, 5.5, 3.5, 5.5, 3.5, 3.5}, + {5, 3, 5, 3, 5, 3, 5, 5, 3, 5, 3, 3} + }, + { + {19.5, 15.5, 19.5, 15.5, 19.5, 15.5, 19.5, 19.5, 15.5, 19.5, 15.5, 15.5}, + {20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0}, + {20.5, 22.5, 22.5, 22.5, 22.5, 22.5, 22.5, 22.5, 22.5, 22.5, 22.5, 22.5} + } + } +}; + +struct devSequence* findSequenceByName(const char* processName) { + for (int i = 0; i < NUM_DEV_SEQUENCES; i++) { + if (strcmp(devSequences[i].processName, processName) == 0) { + return &devSequences[i]; + } + } + return NULL; // Return NULL if not found +} diff --git a/src/devSequence.h b/src/devSequence.h new file mode 100644 index 0000000..2a4f5df --- /dev/null +++ b/src/devSequence.h @@ -0,0 +1,19 @@ +#ifndef DEVSEQUENCE_H +#define DEVSEQUENCE_H +#define NUM_DEV_SEQUENCES 6 +#include + +struct devSequence { + char processName[7]; + int cycles; + unsigned long int processTime[20]; + char processCycleName[20][10]; + float processCycle[2][20]; + float processTemp[3][20]; +}; + +extern struct devSequence devSequences[NUM_DEV_SEQUENCES]; + +struct devSequence* findSequenceByName(const char* processName); + +#endif diff --git a/src/display.cpp b/src/display.cpp new file mode 100644 index 0000000..828232a --- /dev/null +++ b/src/display.cpp @@ -0,0 +1,56 @@ +#include "display.h" +#include "menu.h" + + +void startingMenu() { + lcd.clear(); + lcd.setCursor(0, 0); + lcd.print("Select Programme:"); + lcd.setCursor(0, 1); + lcd.print("1. C41"); + lcd.setCursor(0, 2); + lcd.print("2. E6"); + lcd.setCursor(0, 3); + lcd.print("3. B&W"); + lcd.setCursor(10, 1); + lcd.print("4. ECN-2"); + lcd.setCursor(10, 2); + lcd.print("5. Custom"); + lcd.setCursor(10, 3); + lcd.print("6. B&W Rev"); + + while (devPgm == "") { + getMenuInput(); + } + lcd.print(devPgm); + + if (devPgm == "C41" || devPgm == "E6" || devPgm == "B&W" || devPgm == "ECN-2" || devPgm == "Custom" || devPgm == "B&WREV") { + startDev(); + } +} + +void processHeadings() { + lcd.clear(); + lcd.setCursor(0, 0); + lcd.print("Step"); + lcd.setCursor(10, 0); + lcd.print("Time"); + lcd.setCursor(16, 0); + lcd.print("Temp"); +} + + + +char* secondsToMinutesSeconds(int seconds) { + char* result = (char*)malloc(6 * sizeof(char)); + if (result == NULL) { + return NULL; + } + + int minutes = seconds / 60; + int secs = seconds % 60; + + snprintf(result, 6, "%02d:%02d", minutes, secs); + + return result; +} diff --git a/src/display.h b/src/display.h new file mode 100644 index 0000000..d4fbd3a --- /dev/null +++ b/src/display.h @@ -0,0 +1,13 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include +#include "config.h" + +void updateTempDisplay(void* parameter); +void startingMenu(); +void processHeadings(); +void readTemperature(); +char* secondsToMinutesSeconds(int seconds); + +#endif diff --git a/src/menu.cpp b/src/menu.cpp new file mode 100644 index 0000000..ae544ea --- /dev/null +++ b/src/menu.cpp @@ -0,0 +1,181 @@ +#include "menu.h" + +void getMenuInput() { + char key = keypad.getKey(); + if (key != NO_KEY) { + switch (key) { + case '1': + devPgm = "C41"; + break; + case '2': + devPgm = "E6"; + break; + case '3': + devPgm = "B&W"; + break; + case '4': + devPgm = "ECN-2"; + break; + case '5': + devPgm = "Custom"; + break; + case '6': + devPgm = "B&WREV"; + break; + } + } +} + + +char getScrollEntEscInput() { + while (true) { + char key = keypad.getKey(); + if (key != NO_KEY) { + if (key == 'U' || key == 'D' || key == 'X' || key == 'E' || key == 'L' || key == 'R') { + return key; + } + } + if (millis() % 1000 == 0) { + readTemperature(); + } + } +} + +char getEntEscInput() { + while (true) { + char key = keypad.getKey(); + if (key != NO_KEY) { + if (key == 'X' || key == 'E') { + return key; + } + } + if (millis() % 1000 == 0) { + readTemperature(); + } + } +} + +int startProcessing(struct devSequence* sequence, int sequenceStep) { + run = 1; + lcd.clear(); + lcd.setCursor(0, 0); + lcd.print(sequence->processCycleName[sequenceStep]); + for (int x = strlen(sequence->processCycleName[sequenceStep]); x < 10; x++) { + lcd.print(" "); + } + + lcd.setCursor(10, 0); + lcd.print(secondsToMinutesSeconds(sequence->processTime[sequenceStep])); + lcd.setCursor(16, 0); + lcd.print(" " + (String)(int)sequence->processTemp[1][sequenceStep] + "C"); + + lcd.setCursor(0, 1); + lcd.print("Ent:start Esc:quit"); + + char key = getEntEscInput(); + if (key == 'X') { + devPgm = ""; + run = 0; + return 0; + } + processTimeMillis = (unsigned long)sequence->processTime[sequenceStep] * 1000; + processStartTime = millis(); + + MotorTaskParams* params = new MotorTaskParams(); + params->cwRotations = sequence->processCycle[0][sequenceStep]; + params->ccwRotations = sequence->processCycle[1][sequenceStep]; + params->processEndTime = processStartTime + processTimeMillis; + + Serial.print("Starting Motor Task with CW Rotations: "); + Serial.print(params->cwRotations); + Serial.print(", CCW Rotations: "); + Serial.print(params->ccwRotations); + Serial.print(", Process End Time: "); + Serial.println(params->processEndTime); + + xTaskCreatePinnedToCore( + runMotorTask, + "MotorTask", + 8192, + (void*)params, + 1, + &motorTaskHandle, + 0); + + while (millis() < processStartTime + processTimeMillis) { + lcd.setCursor(0, 1); + lcd.print("Remaining: " + (String)secondsToMinutesSeconds((processStartTime + processTimeMillis - millis()) / 1000) + " "); + delay(410); + Serial.println("before temp read" + (String) millis() + "\n"); + readTemperature(); + Serial.println("after temp read" + (String) millis() + "\n"); + } + + if (motorTaskHandle != NULL) { + vTaskDelete(motorTaskHandle); + motorTaskHandle = NULL; + } + playAlarmTone(); + + delete params; + return 1; +} + +void startDev() { + const char* searchName = devPgm.c_str(); + struct devSequence* currentSequence = findSequenceByName(searchName); + + for (int i = 0; i < currentSequence->cycles; i++) { + if (run == 1) { + run = startProcessing(currentSequence, i); + continue; + } + + processHeadings(); + lcd.setCursor(0, 1); + lcd.print(currentSequence->processCycleName[i]); + for (int x = strlen(currentSequence->processCycleName[i]); x < 10; x++) { + lcd.print(" "); + } + + lcd.setCursor(10, 1); + lcd.print(secondsToMinutesSeconds(currentSequence->processTime[i])); + lcd.setCursor(16, 1); + lcd.print(" " + (String)(int)currentSequence->processTemp[1][i] + "C"); + + lcd.setCursor(0, 2); + lcd.print("Scroll / Esc / Ent"); + + char key = getScrollEntEscInput(); + if (key == 'U') { + if (i > 0) { + i--; + } + i--; + } else if (key == 'D' && i < currentSequence->cycles - 1) { + continue; + } else if (key == 'D' && i == currentSequence->cycles - 1) { + i--; + continue; + } else if (key == 'X') { + devPgm = ""; + run = 0; + return; + } else if (key == 'E') { + int run = 1; + startProcessing(currentSequence, i); + } else if (key == 'L') { + currentSequence->processTime[i] -= 5; + lcd.setCursor(10, 1); + lcd.print(secondsToMinutesSeconds(currentSequence->processTime[i])); + i--; + } else if (key == 'R') { + currentSequence->processTime[i] += 5; + lcd.setCursor(10, 1); + lcd.print(secondsToMinutesSeconds(currentSequence->processTime[i])); + i--; + } + } + devPgm = ""; + run = 0; +} diff --git a/src/menu.h b/src/menu.h new file mode 100644 index 0000000..b4cad5f --- /dev/null +++ b/src/menu.h @@ -0,0 +1,16 @@ +#ifndef MENU_H +#define MENU_H + +#include "config.h" +#include "devSequence.h" +#include "motor.h" +#include "display.h" +#include "sound.h" + +void getMenuInput(); +char getScrollEntEscInput(); +char getEntEscInput(); +int startProcessing(struct devSequence* sequence, int sequenceStep); +void startDev(); + +#endif diff --git a/src/motor.cpp b/src/motor.cpp new file mode 100644 index 0000000..411b535 --- /dev/null +++ b/src/motor.cpp @@ -0,0 +1,29 @@ +#include "motor.h" + +void runMotorTask(void* parameter) { + MotorTaskParams* params = (MotorTaskParams*)parameter; + + // Enable the motor + digitalWrite(EN_PIN, LOW); + while (true) { + // Rotate clockwise + Serial.println("Rotating CW" + (String)params->cwRotations); + stepper.setCurrentPosition(0); + stepper.moveTo(STEPS_PER_REV * params->cwRotations); + while (stepper.distanceToGo() != 0) { + stepper.run(); + } + + // Rotate counter-clockwise + Serial.println("Rotating CCW" + (String)params->ccwRotations); + stepper.setCurrentPosition(0); + stepper.moveTo(-STEPS_PER_REV * params->ccwRotations); + while (stepper.distanceToGo() != 0) { + stepper.run(); + } + } + // Disable the motor + digitalWrite(EN_PIN, HIGH); + + vTaskDelete(NULL); // Delete the task when done +} diff --git a/src/motor.h b/src/motor.h new file mode 100644 index 0000000..1372a29 --- /dev/null +++ b/src/motor.h @@ -0,0 +1,15 @@ +#ifndef MOTOR_H +#define MOTOR_H + +#include +#include "config.h" + +struct MotorTaskParams { + float cwRotations; + float ccwRotations; + unsigned long int processEndTime; +}; + +void runMotorTask(void* parameter); + +#endif diff --git a/src/sound.cpp b/src/sound.cpp new file mode 100644 index 0000000..4b5154f --- /dev/null +++ b/src/sound.cpp @@ -0,0 +1,30 @@ +#include "sound.h" + + +int melody[] = { + 262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 698, 784, 880, 988, 1047 +}; +int noteDurations[] = { + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250 +}; + +void playTune() { + for (int thisNote = 0; thisNote < 15; thisNote++) { + int noteDuration = noteDurations[thisNote]; + tone(beeperPin, melody[thisNote], noteDuration); + + int pauseBetweenNotes = noteDuration * 1.30; + delay(pauseBetweenNotes); + + noTone(beeperPin); + } +} + +void playAlarmTone() { + for (int i = 1; i <= 10; i++) { + tone(beeperPin, 2000); + delay(500); + noTone(beeperPin); + delay(250); + } +} diff --git a/src/sound.h b/src/sound.h new file mode 100644 index 0000000..67c48f0 --- /dev/null +++ b/src/sound.h @@ -0,0 +1,9 @@ +#ifndef SOUND_H +#define SOUND_H + +#include "config.h" + +void playTune(); +void playAlarmTone(); + +#endif diff --git a/src/spec.d b/src/spec.d new file mode 100644 index 0000000..fbd4303 --- /dev/null +++ b/src/spec.d @@ -0,0 +1,2 @@ +spec.o: \ + C:/Users/gordon/Documents/sloeber-workspace/.metadata/.plugins/org.eclipse.cdt.managedbuilder.core/spec.cpp diff --git a/src/temperature.cpp b/src/temperature.cpp new file mode 100644 index 0000000..e30293a --- /dev/null +++ b/src/temperature.cpp @@ -0,0 +1,29 @@ +#include "temperature.h" + +void readTemperature() { + sensors.requestTemperatures(); + float temperatureC = sensors.getTempCByIndex(0); + lcd.setCursor(13, 3); + lcd.write(byte(0)); + if (temperatureC == DEVICE_DISCONNECTED_C) { + lcd.print("--"); + } else { + lcd.print(temperatureC, 1); + lcd.print("C"); + } +} + +void updateTempDisplay(void* parameter) { + sensors.requestTemperatures(); + float temperatureC = sensors.getTempCByIndex(0); + lcd.setCursor(13, 3); + lcd.write(byte(0)); + if (temperatureC == DEVICE_DISCONNECTED_C) { + lcd.print("--"); + } else { + lcd.print(temperatureC, 1); + lcd.print("C"); + } + + vTaskDelete(NULL); // Delete the task when done +} diff --git a/src/temperature.h b/src/temperature.h new file mode 100644 index 0000000..4bbec4b --- /dev/null +++ b/src/temperature.h @@ -0,0 +1,10 @@ +#ifndef TEMPERATURE_H +#define TEMPERATURE_H + +#include "config.h" + +void readTemperature(); + +void updateTempDisplay(); + +#endif diff --git a/src/watchdog.h b/src/watchdog.h new file mode 100644 index 0000000..e9c8a49 --- /dev/null +++ b/src/watchdog.h @@ -0,0 +1,17 @@ +#ifndef WATCHDOG_H +#define WATCHDOG_H + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_task_wdt.h" + +// Disable the watchdog timers +void disableWatchdogTimers() { + esp_task_wdt_deinit(); + TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); + TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); + esp_task_wdt_delete(idle_0); + esp_task_wdt_delete(idle_1); +} + +#endif diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html