Using AccelStepper and RCSwitch - tricky?

242 views
Skip to first unread message

John Goor

unread,
Jan 9, 2015, 6:34:03 AM1/9/15
to accels...@googlegroups.com
Hi,

When I use RCSwitch to listen to RC commands to control a stepper using AccelStepper, my Arduino won't 'listen'  to RC commands as long as de stepper is running. This seems blocking beheaviour but i'm a novice on this topic.
When I comment out the 'run' command, The RC routine show a LED blink on a button puch of the RC.
When I comment in the 'run' command, The RC routine does not show a LED blink on a button puch of the RC.

Here's the code:

#include <RCSwitch.h>
#include <AccelStepper.h>

// Button definitions
#define D3_ON  5246997
#define D3_OFF 5246996

// Arduino pin definitions
#define ENDSWITCHL 4  // Endswitch Left
#define ENDSWITCHR 5  // Endswitch Right
#define LED_PIN 13
#define RECEIVERPIN 0

// Stepper data
#define SPEED 500
#define LEFT -1
#define RIGHT 1
#define STOP 0

// NOTE: The sequence 8-10-9-11 is required for proper sequencing of 28BYJ48. The leading '4' is half-step mode (4-wire)
AccelStepper stepper(4, 8, 10, 9, 11);

// classses
RCSwitch rfSwitch = RCSwitch(); // 434 receiver & transmitter

// Global Variables
unsigned long value;

void setup() {
  pinMode(ENDSWITCHL, INPUT_PULLUP);
  pinMode(ENDSWITCHR, INPUT_PULLUP);
  stepper.setMaxSpeed(SPEED);
  stepper.setSpeed(SPEED);
  Serial.begin(115200);

  // 434 receiver on interrupt #0 (pin #2)
  rfSwitch.enableReceive(RECEIVERPIN);
 
  Serial.println("[+] Listening");
}

int dir = STOP;
void loop() {

  if (rfSwitch.available()) {


    value = rfSwitch.getReceivedValue();
    rfSwitch.resetAvailable();    
      
    switch (value) {
      digitalWrite(LED_PIN, true);
      case D3_ON:
        digitalWrite(LED_PIN, true);
        switch (dir) {
          case LEFT:  dir = STOP; stepper.disableOutputs(); break;
          case STOP:  dir = LEFT; break;
        }
        break;
      case D3_OFF:    
        digitalWrite(LED_PIN, true);
        switch (dir) {
          case RIGHT: dir = STOP; stepper.disableOutputs(); break;
          case STOP:  dir = RIGHT; break;
        }
      break;
    }
    digitalWrite(LED_PIN, false);
  }

  // Some final fysical security measures to prevent de mechanics to crash
  if ((digitalRead(ENDSWITCHL) == LOW) && (dir == LEFT)) {
    dir = STOP;
    stepper.disableOutputs();
    Serial.println("STOP BY ENDSWITCH LEFT");
  }

  if ((digitalRead(ENDSWITCHR) == LOW) && (dir == RIGHT)) {
    dir = STOP;
    stepper.disableOutputs();
    Serial.println("STOP BY ENDSWITCH RIGHT");
  }

  stepper.setSpeed(SPEED * dir);
  stepper.run();

}


Who can help me out?

Thanx!

Mike McCauley

unread,
Jan 9, 2015, 11:32:36 PM1/9/15
to accels...@googlegroups.com
Hi,

I suspect the main problem here is that every time through the main loop you
are checking for messages and button presses, setting the speed and then
calling run().

Instead you should only check for messages and button presses occasionally,
and then based on that set the speed. But call run() as often as possible:

something like:

loop()
{
if (100ms has elapsed)
{
if (there is a message)
setSpeed() or whatever
}
stepper.run();
--
Mike McCauley VK4AMM mi...@airspayce.com
Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
http://www.airspayce.com
Phone +61 7 5598-7474

John Goor

unread,
Jan 11, 2015, 5:29:51 PM1/11/15
to accels...@googlegroups.com
Hello Mike,

Thanks for you fast response.

I modified the code as you suggested. Sounded plausible.
Unfortunely without success.

I connected the endswitches to an interrupt. Also now I 'listen' every 800ms to the RC.

The code is as follows:

#include <RCSwitch.h>
#include <AccelStepper.h>

// Button definitions
#define D3_ON  5246997
#define D3_OFF 5246996

// Arduino pin definitions
#define EndSwitchInt 0  // Interrupt 0
#define EndSwitchPin 2  // Pin is not the same as interrupt
#define LedPin 13
#define ReceiverPin 1
#define MotorPin1 8
#define MotorPin2 10
#define MotorPin3 9
#define MotorPin4 11

// Stepper data
#define SPEED  1000

#define LEFT  -1
#define RIGHT  1
#define STOPR  2
#define STOPL -2
#define STOP   0

// Global variables
volatile int dir = STOP;

// Classses

// NOTE: The sequence 8-10-9-11 is required for proper sequencing of 28BYJ48. The leading '4' is half-step mode (4-wire)
AccelStepper stepper(8, MotorPin1, MotorPin2, MotorPin3, MotorPin4);

RCSwitch rfSwitch = RCSwitch(); // 434 receiver


// Functions
void stopSwitch() { // Interrupt routine
  if (dir == LEFT) {
    dir = STOPL;
  }

  if (dir == RIGHT) {
    dir = STOPR;
  }
  stepper.setSpeed(0);
  stepper.disableOutputs();
}


void flash_led() {
  digitalWrite(LedPin, true);
  digitalWrite(LedPin, false);
}


int get_RC() {
    // RC commands
    switch (rfSwitch.getReceivedValue()) {
    case D3_ON:
      if (dir != STOPL) {
        dir = LEFT;
        stepper.setSpeed(-SPEED);
      }
      break;
    case D3_OFF:    
      if (dir != STOPR) {
        dir = RIGHT;
        stepper.setSpeed(SPEED);
      }
      break;
    }
  return(dir);
}


void setup() {
  stepper.setMaxSpeed(SPEED);
  digitalWrite(EndSwitchPin, INPUT_PULLUP);
  attachInterrupt(EndSwitchInt, stopSwitch, FALLING);
  rfSwitch.enableReceive(ReceiverPin);
  Serial.begin(115200);
  Serial.println("[+] Listening");
}

long previousMillis = 0;
long interval = 800;
void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    if (rfSwitch.available()) {
      flash_led();
      dir = get_RC();
      rfSwitch.resetAvailable();
    }
    previousMillis = currentMillis;
  }
  stepper.runSpeed();

}


I tried lots of things but getting pretty desperate/frustrated..
If you (or anyone else) could advice me some more, I'd be very grateful.

Kind regards,
John




--
You received this message because you are subscribed to a topic in the Google Groups "accelstepper" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/accelstepper/37KgKoXhwwU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mike McCauley

unread,
Jan 11, 2015, 7:38:51 PM1/11/15
to accels...@googlegroups.com
Hi,

That looks like better code. What are the symptoms now?
I notice that you are not setting the motor acceleration anywhere? The default
is very slow accel.

Cheers.

John Goor

unread,
Jan 12, 2015, 3:04:33 AM1/12/15
to accels...@googlegroups.com
Hi,

I made some improvements indeed :-)
I used http://www.airspayce.com/mikem/arduino/AccelStepper/ConstantSpeed_8pde-example.html#a3 as example. Apparently for runSpeed no acceleration is neccesary.

The symptoms now are the same, also after playing with the interval (50 .. 1000 ms).
I use led_pin (13) for flash on receiving an RC signal. No flash while the motor runs however...

Regards,
John

Mike McCauley

unread,
Jan 12, 2015, 4:49:23 PM1/12/15
to accels...@googlegroups.com
Hi,

Im not sure whats going on there. The fact the flashing stop (if true) when the
motor runs is very unexpected. Suggest you pare your code back more to
understand whats going on better.

Cheers.

On Monday, January 12, 2015 09:04:31 AM John Goor wrote:
> Hi,
>

John Goor

unread,
Jan 13, 2015, 1:41:34 AM1/13/15
to accels...@googlegroups.com
Hi,

I did as you suggested. Now there's a Finite State Machine. Also the RC routine is separated and is polled every 500ms. The enddswitches are still connected to an external interrupt.
To me It's obvious now that the 'runSpeed()' routine gets all the time there is. Strangely enough there's no difference with the previous setup.

Here it is...:

#include <RCSwitch.h>
#include <AccelStepper.h>

// Button definitions
#define D3_ON  5246997
#define D3_OFF 5246996

// Arduino pin definitions
#define EndSwitchInt 0  // Interrupt 0
#define EndSwitchPin 2  // Pin is not the same as interrupt
#define LedPin 13
#define ReceiverPin 1
#define MotorPin1 8
#define MotorPin2 10
#define MotorPin3 9
#define MotorPin4 11

// Stepper data
#define SPEED  500

// States
#define STOPPED    0
#define STOP_LEFT  1
#define STOP_RIGHT 2
#define TURN_LEFT  3
#define TURN_RIGHT 4

// Global variables
int volatile state = STOPPED;


// Classses
// NOTE: The sequence 8-10-9-11 is required for proper sequencing of 28BYJ48. The leading '4' is half-step mode (4-wire)
AccelStepper stepper(4, MotorPin1, MotorPin2, MotorPin3, MotorPin4);

RCSwitch rfSwitch = RCSwitch(); // 434 receiver


// Functions
void stopSwitch() { // Interrupt routine
  if (state == TURN_LEFT) {
    state = STOP_LEFT;
  }

  if (state == TURN_RIGHT) {
    state = STOP_RIGHT;
  }
}

int get_RC() {
  if (rfSwitch.available()) {
    flash_led();

    // RC commands
    switch (rfSwitch.getReceivedValue()) {
    case D3_ON:   
      state = TURN_LEFT;
      break;
    case D3_OFF:    
      state = TURN_RIGHT;
      break;
    }
    rfSwitch.resetAvailable();

  }
}

void flash_led() {
  digitalWrite(LedPin, true);
  digitalWrite(LedPin, false);
}


void setup() {
  stepper.setMaxSpeed(SPEED);
  stepper.setSpeed(0);

  digitalWrite(EndSwitchPin, INPUT_PULLUP);
  attachInterrupt(EndSwitchInt, stopSwitch, FALLING);
  rfSwitch.enableReceive(ReceiverPin);
  Serial.begin(115200);
  Serial.println("[+] Listening");
  flash_led();
}


long previousRCMillis = 0;
long interval = 500;
int lastState = STOPPED;

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousRCMillis > interval) {
    get_RC(); // state is set from get_RC (TURN_LEFT, TURN_RIGHT)       
    previousRCMillis = currentMillis;
  }

  if (lastState != state) {
    switch (state) {
    case STOPPED:
      Serial.println("STOPPED");
      stepper.setSpeed(0);
      stepper.disableOutputs();
      break;
    case TURN_LEFT:
      if (lastState != STOP_LEFT) {
        Serial.println("TURN_LEFT");
        stepper.setSpeed(-SPEED);
      }
      break;
    case TURN_RIGHT:
      if (lastState != STOP_RIGHT) {
        Serial.println("TURN_RIGHT");
        stepper.setSpeed(SPEED);
      }
      break;
    case STOP_LEFT:
      Serial.println("STOP_LEFT");
      stepper.setSpeed(0);
      stepper.disableOutputs();
      break;
    case STOP_RIGHT:
      Serial.println("STOP_RIGHT");
      stepper.setSpeed(0);
      stepper.disableOutputs();
      break;
    }
    lastState = state;
  }
  stepper.runSpeed();
}

Hope this helps..

Regards,
John

Mike McCauley

unread,
Jan 13, 2015, 1:48:07 AM1/13/15
to accels...@googlegroups.com
On Tuesday, January 13, 2015 07:41:32 AM John Goor wrote:
> Hi,
>
> I did as you suggested. Now there's a Finite State Machine. Also the RC
> routine is separated and is polled every 500ms. The enddswitches are still
> connected to an external interrupt.
> To me It's obvious now that the 'runSpeed()' routine gets all the time
> there is. Strangely enough there's no difference with the previous setup.

So what are the symptoms now?

Im not sure what you mean by "'runSpeed()' routine gets all the time there
is".

runSpeed() must be called as often as possible in your main loop. Occasionally
it will determine that its time to step the motor. But in any case, it returns
very quickly, and never blocks.

Cheers.

John Goor

unread,
Jan 13, 2015, 1:56:59 AM1/13/15
to accels...@googlegroups.com
Well, the main loop() is functionally reduced to the minimum.:
* Once in the 500ms poll for RC
* Use statemachine only if state differs from previous state
* runSpeed();

It seems to me there's no obstruction there and runSpeed() is called as much as possible (no conditions).
There's no difference btw if I set the interval eg 100ms or 1000ms for  RC polling.

The symptoms:
* I push button (led flash)
* Motor starts
* I push button (NO led flash)
* no reaction
* Motor stops dus to endswitch
* I push button (led flash)
* I can start motor again.

Regards,
John

Mike McCauley

unread,
Jan 13, 2015, 2:07:02 AM1/13/15
to accels...@googlegroups.com
Hi,

I dont know what the problem is. I suspect some interaction between your code
and AccelStepper.
Maybe you should confirm whether runSpeed() is really returning promptly is it
should?

Cheers.

John Goor

unread,
Jan 13, 2015, 2:24:34 AM1/13/15
to accels...@googlegroups.com
I did:
  unsigned long m1 = micros();
  stepper.runSpeed();
  unsigned long m2 = micros();
  Serial.println(m2 - m1);

The serial output:
(No motor action)
4
8
8
8
4
8
etc..

(Motor is running)
12
12
12
12
12
56
12
12
etc

So that seems Ok. (right?)

I'm really puzzled here since my code is pretty trivial. There's not much to it and thats whats frustrtating about it.

I'll proceed trying. I'll let you know when the problem is solved.

Regards,
John

Mike McCauley

unread,
Jan 13, 2015, 2:31:30 AM1/13/15
to accels...@googlegroups.com
Yes that looks OK.

Cheers.

John Goor

unread,
Jan 13, 2015, 6:54:13 AM1/13/15
to accels...@googlegroups.com
Update: Thusfar I pinpointed the problem to the RCSwitch library, function 'handleInterrupt'.

There is a line in that function as follows:

if (duration > 5000 && duration > RCSwitch::timings[0] - 200 && duration < RCSwitch::timings[0] + 200) {

While the motor is running, this routine is called but this line is blocking for some reason until the motor has stopped.

I'll keeop on looking...

Sigmund Baginov

unread,
Nov 3, 2019, 6:20:23 PM11/3/19
to accelstepper
Please, 
i have exactly the same issue here. 
I tried different version of the code, i use both accelStepper and simple Stepper, but the result is the same. 
And online I only found your post in few forum... 
did you have any chance to solve it? 
> > > > > > > > > > accels...@googlegroups.com.

> > > > > > > > > > For more options, visit https://groups.google.com/d/optout
> >
> > .
> >
> > > > > > > > --
> > > > > > > > Mike McCauley           VK4AMM
> > > >
> > > > mi...@airspayce.com
> > > >
> > > > > > > > Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223
> > > >
> > > > Australia
> > > >
> > > > > > > > http://www.airspayce.com
> > > > > > > > Phone +61 7 5598-7474
> > > > > > > >
> > > > > > > > --
> > > > > > > > You received this message because you are subscribed to a
> >
> > topic in
> >
> > > > the
> > > >
> > > > > > > > Google Groups "accelstepper" group.
> > > > > > > > To unsubscribe from this topic, visit
> > > >
> > > > https://groups.google.com/d/topic/accelstepper/37KgKoXhwwU/unsubscribe
> > > >
> > > > > > .
> > > > > >
> > > > > > > > To unsubscribe from this group and all its topics, send an
> >
> > email
> >
> > > > > > > > to
> > > > > > > > accels...@googlegroups.com.

> > > > > > > > For more options, visit https://groups.google.com/d/optout.
> > > > > >
> > > > > > --
> > > > > > Mike McCauley           VK4AMM
> >
> > mi...@airspayce.com
> >
> > > > > > Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223
> >
> > Australia
> >
> > > > > > http://www.airspayce.com
> > > > > > Phone +61 7 5598-7474
> > > > > >
> > > > > > --
> > > > > > You received this message because you are subscribed to a topic in
> >
> > the
> >
> > > > > > Google Groups "accelstepper" group.
> > > > > > To unsubscribe from this topic, visit
> >
> > https://groups.google.com/d/topic/accelstepper/37KgKoXhwwU/unsubscribe
> >
> > > > .
> > > >
> > > > > > To unsubscribe from this group and all its topics, send an email
> > > > > > to

> > > > > > For more options, visit https://groups.google.com/d/optout.
> > > >
> > > > --
> > > > Mike McCauley           VK4AMM                   mi...@airspayce.com
> > > > Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
> > > > http://www.airspayce.com
> > > > Phone +61 7 5598-7474
> > > >
> > > > --
> > > > You received this message because you are subscribed to a topic in the
> > > > Google Groups "accelstepper" group.
> > > > To unsubscribe from this topic, visit
> > > > https://groups.google.com/d/topic/accelstepper/37KgKoXhwwU/unsubscribe
> >
> > .
> >
> > > > To unsubscribe from this group and all its topics, send an email to

> > > > For more options, visit https://groups.google.com/d/optout.
> >
> > --
> > Mike McCauley           VK4AMM                   mi...@airspayce.com
> > Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
> > http://www.airspayce.com
> > Phone +61 7 5598-7474
> >
> > --
> > You received this message because you are subscribed to a topic in the
> > Google Groups "accelstepper" group.
> > To unsubscribe from this topic, visit
> > https://groups.google.com/d/topic/accelstepper/37KgKoXhwwU/unsubscribe.
> > To unsubscribe from this group and all its topics, send an email to

> > For more options, visit https://groups.google.com/d/optout.

--
Mike McCauley           VK4AMM                   mi...@airspayce.com
Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
http://www.airspayce.com
Phone +61 7 5598-7474

--
You received this message because you are subscribed to a topic in the Google Groups "accelstepper" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/accelstepper/37KgKoXhwwU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to accels...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages