From aa78844190f814f01d0f0894dffdda1cf7c704e8 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 27 Jul 2022 17:01:36 +0200 Subject: [PATCH 1/2] esp8266: add an ISR-driven example to protect from WiFi operations --- .../Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino | 48 +++++++++++++++++++ src/AccelStepper.cpp | 12 +++++ src/AccelStepper.h | 7 +++ src/MultiStepper.cpp | 1 + 4 files changed, 68 insertions(+) create mode 100644 examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino diff --git a/examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino b/examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino new file mode 100644 index 0000000..34e1f9e --- /dev/null +++ b/examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino @@ -0,0 +1,48 @@ +// Bounce.pde +// -*- mode: C++ -*- +// +// Make a single stepper bounce from one limit to another +// +// Copyright (C) 2012 Mike McCauley +// $Id: Random.pde,v 1.1 2011/01/05 01:51:01 mikem Exp mikem $ + +#include + +// Define a stepper and the pins it will use +#define DIR 12 // esp8266 gpio +#define STEP 13 // esp8266 gpio +AccelStepper stepper(AccelStepper::DRIVER, STEP, DIR); + +IRAM_ATTR +void stepperRun () +{ + stepper.run(); +} + +void setup() +{ + // Change these to suit your stepper if you want + stepper.setMaxSpeed(10000); + stepper.setAcceleration(10000); + stepper.moveTo(500); + + // initialize ISR + timer1_isr_init(); + timer1_enable(TIM_DIV1, TIM_EDGE, TIM_LOOP); + timer1_attachInterrupt(stepperRun); + timer1_write(microsecondsToClockCycles(100)); +} + +void loop() +{ + // cli() / sei() barriers are necessary when timer is enabled + cli(); + + // If at the end of travel go to the other end + if (stepper.distanceToGo() == 0) + stepper.moveTo(-stepper.currentPosition()); + + sei(); // barrier ends + + delay(1000); // ISR does not care long delays or WiFi operations +} diff --git a/src/AccelStepper.cpp b/src/AccelStepper.cpp index 093d56d..5025c0d 100644 --- a/src/AccelStepper.cpp +++ b/src/AccelStepper.cpp @@ -38,6 +38,7 @@ void AccelStepper::move(long relative) // Implements steps according to the current step interval // You must call this at least once per step // returns true if a step occurred +ISR_ATTR boolean AccelStepper::runSpeed() { // Dont do anything unless we actually have a step interval @@ -69,6 +70,7 @@ boolean AccelStepper::runSpeed() } } +ISR_ATTR long AccelStepper::distanceToGo() { return _targetPos - _currentPos; @@ -94,6 +96,7 @@ void AccelStepper::setCurrentPosition(long position) _speed = 0.0; } +ISR_ATTR void AccelStepper::computeNewSpeed() { long distanceTo = distanceToGo(); // +ve is clockwise from curent location @@ -180,6 +183,7 @@ void AccelStepper::computeNewSpeed() // You must call this at least once per step, preferably in your main loop // If the motor is in the desired position, the cost is very small // returns true if the motor is still running to the target position. +ISR_ATTR boolean AccelStepper::run() { if (runSpeed()) @@ -316,6 +320,7 @@ float AccelStepper::speed() } // Subclasses can override +ISR_ATTR void AccelStepper::step(long step) { switch (_interface) @@ -367,6 +372,7 @@ void AccelStepper::setOutputPins(uint8_t mask) } // 0 pin step function (ie for functional usage) +ISR_ATTR void AccelStepper::step0(long step) { (void)(step); // Unused @@ -379,6 +385,7 @@ void AccelStepper::step0(long step) // 1 pin step function (ie for stepper drivers) // This is passed the current step number (0 to 7) // Subclasses can override +ISR_ATTR void AccelStepper::step1(long step) { (void)(step); // Unused @@ -396,6 +403,7 @@ void AccelStepper::step1(long step) // 2 pin step function // This is passed the current step number (0 to 7) // Subclasses can override +ISR_ATTR void AccelStepper::step2(long step) { switch (step & 0x3) @@ -420,6 +428,7 @@ void AccelStepper::step2(long step) // 3 pin step function // This is passed the current step number (0 to 7) // Subclasses can override +ISR_ATTR void AccelStepper::step3(long step) { switch (step % 3) @@ -442,6 +451,7 @@ void AccelStepper::step3(long step) // 4 pin step function for half stepper // This is passed the current step number (0 to 7) // Subclasses can override +ISR_ATTR void AccelStepper::step4(long step) { switch (step & 0x3) @@ -467,6 +477,7 @@ void AccelStepper::step4(long step) // 3 pin half step function // This is passed the current step number (0 to 7) // Subclasses can override +ISR_ATTR void AccelStepper::step6(long step) { switch (step % 6) @@ -501,6 +512,7 @@ void AccelStepper::step6(long step) // 4 pin half step function // This is passed the current step number (0 to 7) // Subclasses can override +ISR_ATTR void AccelStepper::step8(long step) { switch (step & 0x7) diff --git a/src/AccelStepper.h b/src/AccelStepper.h index 5ab5aba..03e90cd 100644 --- a/src/AccelStepper.h +++ b/src/AccelStepper.h @@ -276,6 +276,13 @@ #define YIELD #endif +// on archs defining IRAM_ATTR (esp8266, esp32), use this attribute for functions callable from ISR +#ifdef IRAM_ATTR + #define ISR_ATTR IRAM_ATTR +#else + #define ISR_ATTR +#endif + ///////////////////////////////////////////////////////////////////// /// \class AccelStepper AccelStepper.h /// \brief Support for stepper motors with acceleration etc. diff --git a/src/MultiStepper.cpp b/src/MultiStepper.cpp index 6a22e11..05e53e6 100644 --- a/src/MultiStepper.cpp +++ b/src/MultiStepper.cpp @@ -49,6 +49,7 @@ void MultiStepper::moveTo(long absolute[]) } // Returns true if any motor is still running to the target position. +ISR_ATTR boolean MultiStepper::run() { uint8_t i; From 2cdd64365890b8ba605c23285f20b405a55b9c6a Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 27 Jul 2022 18:30:30 +0200 Subject: [PATCH 2/2] add missing ISR_ATTR --- examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino | 2 +- src/AccelStepper.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino b/examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino index 34e1f9e..f17daf6 100644 --- a/examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino +++ b/examples/Bounce-ESP8266-ISR/Bounce-ESP8266-ISR.ino @@ -44,5 +44,5 @@ void loop() sei(); // barrier ends - delay(1000); // ISR does not care long delays or WiFi operations + delay(1000); // ISR does not mind long delays or WiFi operations } diff --git a/src/AccelStepper.cpp b/src/AccelStepper.cpp index 5025c0d..19175b4 100644 --- a/src/AccelStepper.cpp +++ b/src/AccelStepper.cpp @@ -359,6 +359,7 @@ void AccelStepper::step(long step) // bit 0 of the mask corresponds to _pin[0] // bit 1 of the mask corresponds to _pin[1] // .... +ISR_ATTR void AccelStepper::setOutputPins(uint8_t mask) { uint8_t numpins = 2;