diff options
author | Jonas Smedegaard <dr@jones.dk> | 2023-10-13 08:58:30 +0200 |
---|---|---|
committer | Jonas Smedegaard <dr@jones.dk> | 2023-10-13 08:58:30 +0200 |
commit | 658e842eaa63d70e681a6d78f16f106cee23da6f (patch) | |
tree | d665a172b9315df13b4f88c1bef2938273d9d415 /src/src.ino | |
parent | 08ceb51898402b6dbe16630c28816e33d1ed31eb (diff) |
move code to subdir src
Diffstat (limited to 'src/src.ino')
-rw-r--r-- | src/src.ino | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/src.ino b/src/src.ino new file mode 100644 index 0000000..fe80680 --- /dev/null +++ b/src/src.ino @@ -0,0 +1,222 @@ +// Pill dispenser + +// Requires libraries EasyButton, BlinkControl, FastLED, ServoEasing +// Optionally requires libraries GxEPD2, GEM + +#include <EasyButton.h> +#include <BlinkControl.h> + +const int longpress_duration = 2000; // time in milliseconds + +// use built-in buttons and LEDs when possible +#if defined(ESP32) +// dirty hack: assume that any ESP32 board is a Lilygo T5 V2.2 +#define LILYGO_T5_V22 +#include "boards.h" // source: https://github.com/lewisxhe/GxEPD/blob/master/src/boards.h +#define HAS_DISPLAY + +const byte BUTTON_PIN_MOVE = BUTTON_1; +const byte BUTTON_PIN_SELECT = BUTTON_2; +const byte BUTTON_PIN_ACTION = BUTTON_3; +BlinkControl led(LED_PIN); +#define LEDS_PIN 12 +#define SERVO_PIN 5 // see ServoEasing PinDefinitionsAndMore.h +#else +const byte BUTTON_PIN_MOVE = 4; +const byte BUTTON_PIN_SELECT = 5; +const byte BUTTON_PIN_ACTION = 2; +BlinkControl led(LED_BUILTIN); // pin 13 is built-in LED on many Arduino boards +#define LEDS_PIN 6 +#define SERVO_PIN 9 // see ServoEasing PinDefinitionsAndMore.h +#endif + +#define LEDS_AMOUNT 10 + +// serial port speed +#define BAUDRATE 115200 + +EasyButton button_move(BUTTON_PIN_MOVE); +EasyButton button_select(BUTTON_PIN_SELECT); +EasyButton button_action(BUTTON_PIN_ACTION); + +#include <FastLED.h> + +CRGB leds[LEDS_AMOUNT]; + +#if defined(HAS_DISPLAY) +#define ENABLE_GxEPD2_GFX 0 + +#include <GxEPD2_BW.h> +#include <Fonts/FreeMonoBold9pt7b.h> + +// source: https://github.com/ZinggJM/GxEPD2/blob/master/examples/GxEPD2_Example/GxEPD2_display_selection.h#L192 +GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> displayEPaper(GxEPD2_290(EPD_CS, EPD_DC, EPD_RSET, EPD_BUSY)); + +// FIXME: really disable GLCD, since it cannot build on ESP32 +// as dirty workaround, edit file `libraries/GEM/src/config.h` +#define GEM_DISABLE_GLCD 1 +#include <GEM_adafruit_gfx.h> + +// Create variables that will be editable through the menu and assign them initial values +int number = -512; +boolean enablePrint = false; + +// Create two menu item objects of class GEMItem, linked to number and enablePrint variables +GEMItem menuItemInt("Number:", number); +GEMItem menuItemBool("Enable print:", enablePrint); + +// Create menu button that will trigger printData() function. It will print value of our number variable +// to Serial monitor if enablePrint is true. We will write (define) this function later. However, we should +// forward-declare it in order to pass to GEMItem constructor +void printData(); // Forward declaration +GEMItem menuItemButton("Print", printData); + +// Create menu page object of class GEMPage. Menu page holds menu items (GEMItem) and represents menu level. +// Menu can have multiple menu pages (linked to each other) with multiple menu items each +GEMPage menuPageMain("Main Menu"); + +GEM_adafruit_gfx menu(displayEPaper, GEM_POINTER_ROW, GEM_ITEMS_COUNT_AUTO); +#endif + +#define MAX_EASING_SERVOS 1 +#include "ServoEasing.hpp" + +ServoEasing servo; + +#define SERVO_POS_INIT 60 +#define SERVO_POS_MAX 100 + +volatile int pills_requested = 0; + +void setup() { + Serial.begin(BAUDRATE); + while (!Serial) { + ; + } + Serial.println(); + + button_move.begin(); + button_select.begin(); + button_action.begin(); + button_move.onPressed(onButtonMovePressed); + button_move.onPressedFor(longpress_duration, onButtonMoveLongpressed); + button_select.onPressed(onButtonSelectPressed); + button_action.onPressed(onButtonActionPressed); + + led.begin(); + led.breathe(2000); + FastLED.addLeds<NEOPIXEL, LEDS_PIN>(leds, LEDS_AMOUNT); + +#if defined(HAS_DISPLAY) + displayEPaper.init(115200, true, 2, false); + displayEPaper.setTextColor(GxEPD_BLACK); + displayEPaper.firstPage(); + do + { + displayEPaper.fillScreen(GxEPD_WHITE); + // comment out next line to have no or minimal Adafruit_GFX code + displayEPaper.print("Hello World!"); + } + while (displayEPaper.nextPage()); + + menu.init(); + setupMenu(); + menu.drawMenu(); +#endif + + Serial.println(F("Attach servo at pin " STR(SERVO_PIN))); + if (servo.attach(SERVO_PIN, SERVO_POS_INIT) == INVALID_SERVO) { + led.blink2(); + Serial.println(F("Error attaching servo")); + } + + // Wait for servo to reach start position. + delay(500); + + servo.setSpeed(90); // This speed is taken if no further speed argument is given. +} + +void loop() { + led.loop(); + button_move.read(); + button_select.read(); + button_action.read(); + servoLoop(); +} + +#if (ESP32) +IRAM_ATTR // avoid crash e.g. when other code reads SD card +#endif +void onButtonMovePressed() { + Serial.println("button MOVE clicked"); + led.blink2(); +} + +#if (ESP32) +IRAM_ATTR // avoid crash e.g. when other code reads SD card +#endif +void onButtonMoveLongpressed() { + Serial.println("button MOVE long-clicked"); + led.off(); +} + +#if (ESP32) +IRAM_ATTR // avoid crash e.g. when other code reads SD card +#endif +void onButtonSelectPressed() { + Serial.println("button SELECT clicked"); + led.on(); +} + +#if (ESP32) +IRAM_ATTR // avoid crash e.g. when other code reads SD card +#endif +void onButtonActionPressed() { + Serial.println("button ACTION clicked"); + led.fastBlinking(); + pills_requested++; + rolling_green(); +} + +void rolling_green() { + for (int dot = 0; dot < LEDS_AMOUNT; dot++) { + leds[dot] = CRGB::Green; + FastLED.show(); + // clear this LED for the next time around the loop + leds[dot] = CRGB::White; + delay(60); + } +} + +#if defined(HAS_DISPLAY) +void setupMenu() { + // Add menu items to menu page + menuPageMain.addMenuItem(menuItemInt); + menuPageMain.addMenuItem(menuItemBool); + menuPageMain.addMenuItem(menuItemButton); + + // Add menu page to menu and set it as current + menu.setMenuPageCurrent(menuPageMain); +} + +void printData() { + // If enablePrint flag is set to true (checkbox on screen is checked)... + if (enablePrint) { + // ...print the number to Serial + Serial.print("Number is: "); + Serial.println(number); + } else { + Serial.println("Printing is disabled, sorry:("); + } +} +#endif + +// source: https://robojax.com/learn/arduino/?vid=robojax_Servo_PB1_move_return +void servoLoop() { + if (pills_requested > 1) { + servo.easeTo(SERVO_POS_MAX); + delay(500); + servo.easeTo(SERVO_POS_INIT); + pills_requested--; + } +} |