diff --git a/pousseseringue-arduino.cpp b/pousseseringue-arduino.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d85496a644a42658f6a1cdde1d5d52c14a57460 --- /dev/null +++ b/pousseseringue-arduino.cpp @@ -0,0 +1,319 @@ + +// Feather esp8266 +// Feather LCD +// Feather motor controler + +#define STASSID "laas-capture" +#define STAPSK "" + +#define NAME "PousseSeringue" + +#define OLED_HW Adafruit128x32 +#define BTNA 0 // gpio A adafruit feather oled 128x32 +#define BTNB 16 // gpio B adafruit feather oled 128x32 +#define BTNC 2 // gpio C adafruit feather oled 128x32 +#define OLED_I2C 0x3c // adafruit feather oled 128x32 + +#if 1 // 1 for laas board + +// A4988 PINOUT +#define DIR 15 // esp8266 gpio +#define STEP 13 // esp8266 gpio +#define SLEEP 12 // esp8266 gpio + +#else // primilinary proto pinout + +#warning WARNING NOT LAAS BOARD ! + +// A4988 PINOUT +#define DIR 12 // esp8266 gpio +#define STEP 13 // esp8266 gpio +#define SLEEP 14 // esp8266 gpio + +#endif // proto pinout + +// should this be configurable through a GUI ? +#define MOTOR_STEPS 200 // 17HS19 +#define MICROSTEPS_CONF 16 // hardware configuration: A4988's MS1,MS2,MS3 tied up + +#define STEPPER_RPM 60 // some value is necessary for the driver XXXXX see below + +#define STEP_DURATION_MIN_MS 2 +#define STEP_DURATION_DEFAULT_MS 5 + + + + + +#include <ESP8266WiFi.h> // internal, wifi library +#include <DNSServer.h> // internal, access point mode +#include <SSD1306AsciiWire.h> // https://github.com/greiman/SSD1306Ascii +#include <A4988.h> // https://github.com/laurb9/StepperDriver + +#include "Debouncer.h" // local, debouncer, short counter, long detector +#include "common.h" + + + + +enum class Modes { TURN, TURNSetup, RPM, RPMSetup, INFO }; + + + +millis_t nowMs; // to update on main loop(): "nowMs = millis();" + +Debouncer<nowMs> bA, bB, bC; +A4988 a4988(MOTOR_STEPS, DIR, STEP, SLEEP); +SSD1306AsciiWire oled; +constexpr int DNS_PORT = 53; +DNSServer dnsServer; + +char ssid[65]; + +Modes mode = Modes::TURN; + +millis_t lastMoveMs = 0; +int move = 0; + +// TURN mode +constexpr float step2deg = 360.0 / MOTOR_STEPS / MICROSTEPS_CONF; // deg for 1 step +int steps = MOTOR_STEPS * MICROSTEPS_CONF / 100; // =1/100 turn + +// RPM mode +int stepsPerDuration = 1; +int stepDurationMs = STEP_DURATION_DEFAULT_MS; +float stepsPerDuration2rpm () { return 60.0 * stepsPerDuration / ((MOTOR_STEPS * MICROSTEPS_CONF) * (stepDurationMs / 1000.0)); } +int rpming = 0; // -1, 0 or +1 + +const char* oledMode () +{ + switch (mode) + { + case Modes::TURN: return "TURN"; + case Modes::TURNSetup: return "TURN Setup"; + case Modes::RPM: return "RPM"; + case Modes::RPMSetup: return "RPM Setup"; + case Modes::INFO: return "Informations"; + } + return "mode?"; +} + +void oledPrintMode () +{ + oled.printf("\n mode: %s", oledMode()); +} + +void oledRedisplay () +{ + oled.clear(); + + switch (mode) + { + case Modes::TURN: + oled.printf("<%g dR <<turn", steps * step2deg); + oledPrintMode(); + oled.printf("\n"); + oled.printf("\n<%g dL <<turn", steps * step2deg); + break; + case Modes::TURNSetup: + oled.printf("<+1 << +10 steps"); + oledPrintMode(); + oled.printf("\n current:%d (%g d)", steps, steps * step2deg); + oled.printf("\n<-1 << -10 steps"); + break; + case Modes::RPM: + oled.printf("<stop <<start"); + oledPrintMode(); + oled.printf("\n %g rpm", stepsPerDuration2rpm()); + oled.printf("\n<stop <<start"); + break; + case Modes::RPMSetup: + oled.printf("<+1st <<+1ms st:%d", stepsPerDuration); + oledPrintMode(); + oled.printf("\n %g rpm", stepsPerDuration2rpm()); + oled.printf("\n<-1st <<-1ms t:%dms", stepDurationMs); + break; + case Modes::INFO: + oled.printf("IP:%s", WiFi.localIP().toString().c_str()); + uint8_t mac[6]; + WiFi.macAddress(mac); + oled.printf("\n%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + oled.printf("\nAPSSID & hostname:"); + oled.printf("\n%s", ssid); + break; + + default: + oled.printf("?"); + } +} + +void changeMode () +{ + switch (mode) + { + case Modes::TURN: mode = Modes::TURNSetup; break; + case Modes::TURNSetup: mode = Modes::RPM; break; + case Modes::RPM: mode = Modes::RPMSetup; break; + case Modes::RPMSetup: mode = Modes::INFO; break; + case Modes::INFO: mode = Modes::TURN; break; + } + oledRedisplay(); +} + + + +// button status management, per mode + +void buttons (int shortp, int longp) +{ + // log debug on serial console + Serial.printf("button change: short:%d long:%d\n", shortp, longp); + + rpming = 0; // anything stops rpming + + switch (mode) + { + case Modes::TURN: + move += shortp * steps; + move += longp * MOTOR_STEPS * MICROSTEPS_CONF; + break; + case Modes::TURNSetup: + steps += shortp; + steps += longp * 10; + oledRedisplay(); + break; + case Modes::RPM: + if (longp) + rpming = longp; // move will be increased in main loop + if (shortp) + move = 0; // stop moving + break; + case Modes::RPMSetup: + if ((stepDurationMs += longp) < STEP_DURATION_MIN_MS) + stepDurationMs = STEP_DURATION_MIN_MS; + if ((stepsPerDuration += shortp) < 1) + stepsPerDuration = 1; + oledRedisplay(); + break; + default: + Serial.printf("press not handled in buttons()\n"); + } +} + + + +void setup() +{ + Serial.begin(74880); + Serial.setDebugOutput(true); + Wire.begin(); + Wire.setClock(400000L); + delay(500); + + oled.begin(&OLED_HW, OLED_I2C); + oled.setFont(System5x7); + oled.setScrollMode(SCROLL_MODE_AUTO); + oled.clear(); + oled.println("Booting...\n"); + + a4988.begin(STEPPER_RPM); // some value is necessary + a4988.setEnableActiveState(LOW); + a4988.setMicrostep(MICROSTEPS_CONF); + a4988.enable(); + + uint8_t mac[6]; + WiFi.macAddress(mac); + sprintf(ssid, NAME "-%02x%02x%02x", mac[3], mac[4], mac[5]); + WiFi.mode(WIFI_AP_STA); + WiFi.softAP(ssid); + WiFi.begin(STASSID, STAPSK); + WiFi.hostname(ssid); + + // redirect everything to my AP ip: + dnsServer.setErrorReplyCode(DNSReplyCode::NoError); + dnsServer.start(DNS_PORT, "*", WiFi.softAPIP()); + + Serial.printf("AP: ssid='%s' (no password)\n", ssid); + Serial.printf("---> Connect to this SSID '%s' and head to http://%s <---\n", ssid, WiFi.softAPIP().toString().c_str()); + Serial.printf("---> Within SSID %s, connect to http://%s <----\n", STASSID, ssid); + Serial.printf("---> (or read IP address on screen)\n"); + Serial.printf("connecting to ssid '%s'\n", STASSID); + + webSetup(); + + pinMode(BTNA, INPUT_PULLUP); + pinMode(BTNB, INPUT_PULLUP); + pinMode(BTNC, INPUT_PULLUP); + + oledRedisplay(); +} + + +void loop() +{ + nowMs = millis(); + + // button management (nowMs must be updated) + bool changeA = bA.update(!digitalRead(BTNA)); + bool changeB = bB.update(!digitalRead(BTNB)); + bool changeC = bC.update(!digitalRead(BTNC)); + + if (changeA) + { + // button values (::shortCount(), ::longState()) + // are not cleared until they are read + int shortA = bA.shortCount(); + bool longA = bA.longState(); + + buttons(shortA, longA); + } + + if (changeC) + { + int shortC = bC.shortCount(); + bool longC = bC.longState(); + + buttons(-shortC, -longC); + } + + if (changeB) + { + int shortB = bB.shortCount(); + bool longB = bB.longState(); + + if (longB) + changeMode(); + (void)shortB; + + move = 0; + } + + // Stepper + // MOVE THIS BLOCK INTO A TIMER/ISR + // (it is randomly slowed down by prints / web / wifi) + // (or? use A4988 RPM mode, related: a4988.begin(STEPPER_RPM);) + if (lastMoveMs - nowMs > (millis_t)stepDurationMs) + { + if (rpming && move < MOTOR_STEPS * MICROSTEPS_CONF && move > -(MOTOR_STEPS * MICROSTEPS_CONF)) + { + move += rpming * MOTOR_STEPS * MICROSTEPS_CONF; + //Serial.printf("feeding %d\n", move); + } + + if (move >= stepsPerDuration) + { + move -= stepsPerDuration; + a4988.move(stepsPerDuration); // forward revolution + } + if (move <= -stepsPerDuration) + { + move += stepsPerDuration; + a4988.move(-stepsPerDuration); // backward revolution + } + + lastMoveMs += stepDurationMs; + } + + webLoop(); + dnsServer.processNextRequest(); // AP redirection +} diff --git a/pousseseringue-arduino.ino b/pousseseringue-arduino.ino index 6d85496a644a42658f6a1cdde1d5d52c14a57460..7ff2db19720f6f9bc7f09dc8ce5ed259fe644529 100644 --- a/pousseseringue-arduino.ino +++ b/pousseseringue-arduino.ino @@ -1,319 +1,2 @@ -// Feather esp8266 -// Feather LCD -// Feather motor controler - -#define STASSID "laas-capture" -#define STAPSK "" - -#define NAME "PousseSeringue" - -#define OLED_HW Adafruit128x32 -#define BTNA 0 // gpio A adafruit feather oled 128x32 -#define BTNB 16 // gpio B adafruit feather oled 128x32 -#define BTNC 2 // gpio C adafruit feather oled 128x32 -#define OLED_I2C 0x3c // adafruit feather oled 128x32 - -#if 1 // 1 for laas board - -// A4988 PINOUT -#define DIR 15 // esp8266 gpio -#define STEP 13 // esp8266 gpio -#define SLEEP 12 // esp8266 gpio - -#else // primilinary proto pinout - -#warning WARNING NOT LAAS BOARD ! - -// A4988 PINOUT -#define DIR 12 // esp8266 gpio -#define STEP 13 // esp8266 gpio -#define SLEEP 14 // esp8266 gpio - -#endif // proto pinout - -// should this be configurable through a GUI ? -#define MOTOR_STEPS 200 // 17HS19 -#define MICROSTEPS_CONF 16 // hardware configuration: A4988's MS1,MS2,MS3 tied up - -#define STEPPER_RPM 60 // some value is necessary for the driver XXXXX see below - -#define STEP_DURATION_MIN_MS 2 -#define STEP_DURATION_DEFAULT_MS 5 - - - - - -#include <ESP8266WiFi.h> // internal, wifi library -#include <DNSServer.h> // internal, access point mode -#include <SSD1306AsciiWire.h> // https://github.com/greiman/SSD1306Ascii -#include <A4988.h> // https://github.com/laurb9/StepperDriver - -#include "Debouncer.h" // local, debouncer, short counter, long detector -#include "common.h" - - - - -enum class Modes { TURN, TURNSetup, RPM, RPMSetup, INFO }; - - - -millis_t nowMs; // to update on main loop(): "nowMs = millis();" - -Debouncer<nowMs> bA, bB, bC; -A4988 a4988(MOTOR_STEPS, DIR, STEP, SLEEP); -SSD1306AsciiWire oled; -constexpr int DNS_PORT = 53; -DNSServer dnsServer; - -char ssid[65]; - -Modes mode = Modes::TURN; - -millis_t lastMoveMs = 0; -int move = 0; - -// TURN mode -constexpr float step2deg = 360.0 / MOTOR_STEPS / MICROSTEPS_CONF; // deg for 1 step -int steps = MOTOR_STEPS * MICROSTEPS_CONF / 100; // =1/100 turn - -// RPM mode -int stepsPerDuration = 1; -int stepDurationMs = STEP_DURATION_DEFAULT_MS; -float stepsPerDuration2rpm () { return 60.0 * stepsPerDuration / ((MOTOR_STEPS * MICROSTEPS_CONF) * (stepDurationMs / 1000.0)); } -int rpming = 0; // -1, 0 or +1 - -const char* oledMode () -{ - switch (mode) - { - case Modes::TURN: return "TURN"; - case Modes::TURNSetup: return "TURN Setup"; - case Modes::RPM: return "RPM"; - case Modes::RPMSetup: return "RPM Setup"; - case Modes::INFO: return "Informations"; - } - return "mode?"; -} - -void oledPrintMode () -{ - oled.printf("\n mode: %s", oledMode()); -} - -void oledRedisplay () -{ - oled.clear(); - - switch (mode) - { - case Modes::TURN: - oled.printf("<%g dR <<turn", steps * step2deg); - oledPrintMode(); - oled.printf("\n"); - oled.printf("\n<%g dL <<turn", steps * step2deg); - break; - case Modes::TURNSetup: - oled.printf("<+1 << +10 steps"); - oledPrintMode(); - oled.printf("\n current:%d (%g d)", steps, steps * step2deg); - oled.printf("\n<-1 << -10 steps"); - break; - case Modes::RPM: - oled.printf("<stop <<start"); - oledPrintMode(); - oled.printf("\n %g rpm", stepsPerDuration2rpm()); - oled.printf("\n<stop <<start"); - break; - case Modes::RPMSetup: - oled.printf("<+1st <<+1ms st:%d", stepsPerDuration); - oledPrintMode(); - oled.printf("\n %g rpm", stepsPerDuration2rpm()); - oled.printf("\n<-1st <<-1ms t:%dms", stepDurationMs); - break; - case Modes::INFO: - oled.printf("IP:%s", WiFi.localIP().toString().c_str()); - uint8_t mac[6]; - WiFi.macAddress(mac); - oled.printf("\n%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - oled.printf("\nAPSSID & hostname:"); - oled.printf("\n%s", ssid); - break; - - default: - oled.printf("?"); - } -} - -void changeMode () -{ - switch (mode) - { - case Modes::TURN: mode = Modes::TURNSetup; break; - case Modes::TURNSetup: mode = Modes::RPM; break; - case Modes::RPM: mode = Modes::RPMSetup; break; - case Modes::RPMSetup: mode = Modes::INFO; break; - case Modes::INFO: mode = Modes::TURN; break; - } - oledRedisplay(); -} - - - -// button status management, per mode - -void buttons (int shortp, int longp) -{ - // log debug on serial console - Serial.printf("button change: short:%d long:%d\n", shortp, longp); - - rpming = 0; // anything stops rpming - - switch (mode) - { - case Modes::TURN: - move += shortp * steps; - move += longp * MOTOR_STEPS * MICROSTEPS_CONF; - break; - case Modes::TURNSetup: - steps += shortp; - steps += longp * 10; - oledRedisplay(); - break; - case Modes::RPM: - if (longp) - rpming = longp; // move will be increased in main loop - if (shortp) - move = 0; // stop moving - break; - case Modes::RPMSetup: - if ((stepDurationMs += longp) < STEP_DURATION_MIN_MS) - stepDurationMs = STEP_DURATION_MIN_MS; - if ((stepsPerDuration += shortp) < 1) - stepsPerDuration = 1; - oledRedisplay(); - break; - default: - Serial.printf("press not handled in buttons()\n"); - } -} - - - -void setup() -{ - Serial.begin(74880); - Serial.setDebugOutput(true); - Wire.begin(); - Wire.setClock(400000L); - delay(500); - - oled.begin(&OLED_HW, OLED_I2C); - oled.setFont(System5x7); - oled.setScrollMode(SCROLL_MODE_AUTO); - oled.clear(); - oled.println("Booting...\n"); - - a4988.begin(STEPPER_RPM); // some value is necessary - a4988.setEnableActiveState(LOW); - a4988.setMicrostep(MICROSTEPS_CONF); - a4988.enable(); - - uint8_t mac[6]; - WiFi.macAddress(mac); - sprintf(ssid, NAME "-%02x%02x%02x", mac[3], mac[4], mac[5]); - WiFi.mode(WIFI_AP_STA); - WiFi.softAP(ssid); - WiFi.begin(STASSID, STAPSK); - WiFi.hostname(ssid); - - // redirect everything to my AP ip: - dnsServer.setErrorReplyCode(DNSReplyCode::NoError); - dnsServer.start(DNS_PORT, "*", WiFi.softAPIP()); - - Serial.printf("AP: ssid='%s' (no password)\n", ssid); - Serial.printf("---> Connect to this SSID '%s' and head to http://%s <---\n", ssid, WiFi.softAPIP().toString().c_str()); - Serial.printf("---> Within SSID %s, connect to http://%s <----\n", STASSID, ssid); - Serial.printf("---> (or read IP address on screen)\n"); - Serial.printf("connecting to ssid '%s'\n", STASSID); - - webSetup(); - - pinMode(BTNA, INPUT_PULLUP); - pinMode(BTNB, INPUT_PULLUP); - pinMode(BTNC, INPUT_PULLUP); - - oledRedisplay(); -} - - -void loop() -{ - nowMs = millis(); - - // button management (nowMs must be updated) - bool changeA = bA.update(!digitalRead(BTNA)); - bool changeB = bB.update(!digitalRead(BTNB)); - bool changeC = bC.update(!digitalRead(BTNC)); - - if (changeA) - { - // button values (::shortCount(), ::longState()) - // are not cleared until they are read - int shortA = bA.shortCount(); - bool longA = bA.longState(); - - buttons(shortA, longA); - } - - if (changeC) - { - int shortC = bC.shortCount(); - bool longC = bC.longState(); - - buttons(-shortC, -longC); - } - - if (changeB) - { - int shortB = bB.shortCount(); - bool longB = bB.longState(); - - if (longB) - changeMode(); - (void)shortB; - - move = 0; - } - - // Stepper - // MOVE THIS BLOCK INTO A TIMER/ISR - // (it is randomly slowed down by prints / web / wifi) - // (or? use A4988 RPM mode, related: a4988.begin(STEPPER_RPM);) - if (lastMoveMs - nowMs > (millis_t)stepDurationMs) - { - if (rpming && move < MOTOR_STEPS * MICROSTEPS_CONF && move > -(MOTOR_STEPS * MICROSTEPS_CONF)) - { - move += rpming * MOTOR_STEPS * MICROSTEPS_CONF; - //Serial.printf("feeding %d\n", move); - } - - if (move >= stepsPerDuration) - { - move -= stepsPerDuration; - a4988.move(stepsPerDuration); // forward revolution - } - if (move <= -stepsPerDuration) - { - move += stepsPerDuration; - a4988.move(-stepsPerDuration); // backward revolution - } - - lastMoveMs += stepDurationMs; - } - - webLoop(); - dnsServer.processNextRequest(); // AP redirection -} +// please edit this file: pousseseringue-arduino.cpp \ No newline at end of file