From 5735cbabb8093fb2d9d7244756a699419e75127a Mon Sep 17 00:00:00 2001 From: Ronald Schaten Date: Thu, 27 Jan 2022 21:06:40 +0100 Subject: [PATCH] initial commit --- PhotoStepper/PhotoStepper.ino | 262 ++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 PhotoStepper/PhotoStepper.ino diff --git a/PhotoStepper/PhotoStepper.ino b/PhotoStepper/PhotoStepper.ino new file mode 100644 index 0000000..daf67af --- /dev/null +++ b/PhotoStepper/PhotoStepper.ino @@ -0,0 +1,262 @@ +/* + * PhotoStepper © 2022 by Ronald Schaten is licensed under CC BY-NC 4.0. + * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/4.0/ + */ + +// this project makes heavy use of the following libraries: +// - https://www.arduino.cc/reference/en/libraries/arduinomenu-library/ +// - https://www.arduino.cc/reference/en/libraries/stepperdriver/ +// - https://www.arduino.cc/reference/en/libraries/analogkeypad/ +// +// this is still WIP, the menu is basically taken from example code. + +#include +#include +#include +#include +#include +#include +#include +#include + +//using namespace Menu; + +// analog keypad +#define PIN_BUTTON 0 +// 2x16 LCD +#define PIN_LCD_DB4 4 +#define PIN_LCD_DB5 5 +#define PIN_LCD_DB6 6 +#define PIN_LCD_DB7 7 +#define PIN_LCD_RS 8 +#define PIN_LCD_EN 9 +#define PIN_LCD_BL 10 +// stepper motor +#define PIN_STEPPER_DIR 2 +#define PIN_STEPPER_STEP 3 +// on-board led +#define PIN_LED 13 + +// motor configuration +#define STEPPER_STEPS 200 +#define STEPPER_RPM 120 +#define STEPPER_MICROSTEPS 1 +#define STEPPER_ACCEL 2000 +#define STEPPER_DECEL 1000 + +#define MAX_DEPTH 2 + +const int KeypadMap[] = {0, 96, 250, 402, 636}; +const uint16_t KeypadHoldTimeMs = 5000; +const uint8_t KeypadAnalogPin = PIN_BUTTON; +AnalogKeypad keypad(KeypadAnalogPin, KeypadMap, countof(KeypadMap), KeypadHoldTimeMs); + +LiquidCrystal lcd(PIN_LCD_RS, PIN_LCD_EN, PIN_LCD_DB4, PIN_LCD_DB5, PIN_LCD_DB6, PIN_LCD_DB7); + +BasicStepperDriver stepper(STEPPER_STEPS, PIN_STEPPER_DIR, PIN_STEPPER_STEP); + +// === + +result doAlert(eventMask e, prompt &item); + +result showEvent(eventMask e) { + Serial.print("event: "); + Serial.println(e); + return proceed; +} + +int test=55; + +result action1(eventMask e,navNode& nav, prompt &item) { + Serial.print("action1 event:"); + Serial.println(e); + Serial.flush(); + return proceed; +} + +result action2(eventMask e) { + Serial.print("actikon2 event:"); + Serial.println(e); + Serial.flush(); + return quit; +} + +int ledCtrl=LOW; + +result myLedOn() { + ledCtrl=HIGH; + return proceed; +} +result myLedOff() { + ledCtrl=LOW; + return proceed; +} + +TOGGLE(ledCtrl,setLed,"Led: ",doNothing,noEvent,wrapStyle//,doExit,enterEvent,noStyle + ,VALUE("On",HIGH,doNothing,noEvent) + ,VALUE("Off",LOW,doNothing,noEvent) +); + +int selTest=0; +SELECT(selTest,selMenu,"Select",doNothing,noEvent,wrapStyle + ,VALUE("Zero",0,doNothing,noEvent) + ,VALUE("One",1,doNothing,noEvent) + ,VALUE("Two",2,doNothing,noEvent) +); + +int chooseTest=-1; +CHOOSE(chooseTest,chooseMenu,"Choose",doNothing,noEvent,wrapStyle + ,VALUE("First",1,doNothing,noEvent) + ,VALUE("Second",2,doNothing,noEvent) + ,VALUE("Third",3,doNothing,noEvent) + ,VALUE("Last",-1,doNothing,noEvent) +); + +//customizing a prompt look! +//by extending the prompt class +class altPrompt:public prompt { +public: + altPrompt(constMEM promptShadow& p):prompt(p) {} + Used printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len,idx_t) override { + return out.printRaw(F("special prompt!"),len);; + } +}; + +MENU(subMenu,"Sub-Menu",doNothing,anyEvent,wrapStyle + ,OP("Sub1",showEvent,enterEvent) + ,OP("Sub2",showEvent,enterEvent) + ,OP("Sub3",showEvent,enterEvent) + ,altOP(altPrompt,"",showEvent,enterEvent) + ,EXIT(" strIn;//buffer size: 2^5 = 32 bytes, eventually use 0 for a single byte +serialIn serial(Serial); +// use this commented lines if you want your stringIn object to be used as part or normal menu input +// menuIn* inputsList[]={&serial,&strIn}; +// chainStream in(inputsList); +// NAVROOT(nav,mainMenu,MAX_DEPTH,in,out); +NAVROOT(nav,mainMenu,MAX_DEPTH,serial,out); + +result alert(menuOut& o,idleEvent e) { + if (e==idling) { + o.setCursor(0,0); + o.print("alert test"); + o.setCursor(0,1); + o.print("[select] to continue..."); + Serial.println("rotating..."); + stepper.startRotate(360); + } + return proceed; +} + +result doAlert(eventMask e, prompt &item) { + nav.idleOn(alert); + return proceed; +} + +result idle(menuOut& o,idleEvent e) { + switch(e) { + case idleStart:o.print("suspending menu!");break; + case idling:o.print("suspended...");break; + case idleEnd:o.print("resuming menu.");break; + } + return proceed; +} + +// === + +void ButtonHandler(const ButtonParam& param) +{ + Serial.print(param.button); + Serial.print(" "); + switch (param.state) { + case ButtonState_Up: + Serial.print("Up"); + break; + case ButtonState_Down: + Serial.print("Down"); + break; + case ButtonState_Click: + Serial.print("Click"); + switch (param.button) { + case 0: // right + break; + case 1: // up + nav.doNav(upCmd); + break; + case 2: // down + nav.doNav(downCmd); + break; + case 3: // left + break; + case 4: // select + nav.doNav(enterCmd); + break; + } + nav.doOutput(); + break; + case ButtonState_DoubleClick: + Serial.print("Double Click"); + break; + case ButtonState_Hold: + Serial.print("Hold"); + break; + } + Serial.println(); +} + +void setup() { + Serial.begin(115200); + while(!Serial); + Serial.println("PhotoStepper -- schatenseite.de"); + + pinMode(PIN_LED, OUTPUT); + + // control backlight + pinMode(PIN_LCD_BL, OUTPUT); + digitalWrite(PIN_LCD_BL, HIGH); + + nav.idleTask=idle;//point a function to be used when menu is suspended + + stepper.begin(STEPPER_RPM, STEPPER_MICROSTEPS); + stepper.setSpeedProfile(stepper.LINEAR_SPEED, STEPPER_ACCEL, STEPPER_DECEL); + + lcd.begin(16,2); + lcd.setCursor(0, 0); + lcd.print("PhotoStepper"); + lcd.setCursor(0, 1); + lcd.print("schatenseite.de"); + delay(500); +} + +void loop() { + keypad.loop(ButtonHandler); + stepper.nextAction(); + digitalWrite(PIN_LED, ledCtrl); +}