Issues with running a Stepper Motor using a LORA Receiver

Hi All,

I’m trying to get two LORA modules to talk to each other to run a stepper motor.
I’ve tested the code by simply getting an LED blink on/off (which works fine) - but when I substitute the LED code for the stepper motor code, it will run once and then stop receiving packets from the other module.

How can I get this to receive a message, turn the stepper motor a set distance and then turn again next time it receives the next message?

#include <SPI.h>
#include <LoRa.h>
#include <Adafruit_SSD1306.h>
#include <Arduino.h>
#include <Accelstepper.h>
#include <Stepper.h>
#include <Wire.h> 

//Define stepper motor variables
//PIN SETUP
//PIN 14 = STEP
//PIN 27 = DIRECTION - HIGH spins one way and LOW spins the other way.
//PIN 26 = MS1
//PIN 25 = MS2

AccelStepper stepper(AccelStepper::DRIVER, 14,27);

int pos = 500;
int newpos = 0;
int StepCounter = 0;
int Stepping = false;
// These pins are for determining microstepping
int ms1 = 26;
int ms2 = 25;
//Define LED variables.
//YELLOW
int LED1 = 13;
//RED
int LED2 = 12;
//BLUE
int LED3 = 33;
//GREEN
int LED4 = 32;
//Dissect transmitted sections into each function
char ID1[2]; 
char ID2[2];
char ID3[2];
char ID4[2];

//Define type of OLED used
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1

//screen display
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
//OLED pins to ESP32 GPIOs via this connection:
//OLED_SDA -- GPIO4
//OLED_SCL -- GPIO15
//OLED_RST -- GPIO16
// WIFI_LoRa_32 ports
// GPIO5  -- SX1278's SCK
// GPIO19 -- SX1278's MISO
// GPIO27 -- SX1278's MOSI
// GPIO18 -- SX1278's CS
// GPIO14 -- SX1278's RESET
// GPIO26 -- SX1278's IRQ(Interrupt Request)
 
#define SS      18
#define RST     14
#define DI0     26
#define BAND    915E6
 
void setup() {
  //Define Stepper Motor
  pinMode(27, OUTPUT);    
  pinMode(14, OUTPUT);
  digitalWrite(27, LOW);
  digitalWrite(14, LOW);

  //These pins are for determining microstepping
  pinMode(ms1, OUTPUT);
  pinMode(ms2,OUTPUT);
  digitalWrite(ms1,HIGH);
  digitalWrite(ms2,HIGH);

 stepper.setMaxSpeed(10000);
 stepper.setAcceleration(1000);
 
  //Define LED
  pinMode(LED1,OUTPUT);
  pinMode(LED2,OUTPUT);
  pinMode(LED3,OUTPUT);
  pinMode(LED4,OUTPUT);
  //Define OLED screen
  pinMode(16,OUTPUT);
  digitalWrite(16, LOW);    // set GPIO16 low to reset OLED
  delay(50); 
  digitalWrite(16, HIGH);

  display.begin(SSD1306_SWITCHCAPVCC,0x3C);  // enable internal HV supply for display
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.clearDisplay(); 
  display.display();

  //Transmission code
  Serial.begin(115200);
  while (!Serial); //if just the the basic function, must connect to a computer
  delay(1000);
 
  display.setCursor(0,0); 
  display.print("LoRa Receiver"); 
  display.display();
  SPI.begin(5,19,27,18);
  LoRa.setPins(SS,RST,DI0);
  delay(2000);
  display.clearDisplay();
  display.display();
   
  if (!LoRa.begin(BAND)) {
    display.setCursor(0,0); 
    display.print("Starting LoRa failed!");
    display.display();
    while (1);
  }

  display.setCursor(0,0);
  display.print("LoRa Initializing OK");
  display.display();

  delay(2000);
  display.clearDisplay();
  display.display();
}

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packets
    display.clearDisplay();
    display.setCursor(0,0); 
    display.print("Received packet ");
    display.display();

    // read packet
    while (LoRa.available()) {
    String data = LoRa.readString();

   //use data from packet to execute command
   //each charcacter in string represents command
    ID1[0] = data.charAt(0);
    ID2[0] = data.charAt(1);
    ID3[0] = data.charAt(2);
    ID4[0] = data.charAt(3);

    //display packet data on screen
    display.setCursor(0,15);
    display.print(data);
    display.display();
    }

    // print RSSI of packet
    display.setCursor(0,30);
    display.print("RSSI:  ");
    display.print((String)LoRa.packetRssi());
    display.display();
  
    //run stepper motor is command is equal to 1.
    if (ID2[0]=='1')
    {
    newpos = newpos + pos;
    stepper.moveTo(newpos);

    //this is causing the issue
    while (stepper.distanceToGo() !=0)
    {
    stepper.run();
    }
    ID2[0] = '0';
    }
  }
   display.clearDisplay();
   display.display();
}

The next question people will have is how is this all wired.

Have you tested the stepper code on its own, with no display or Radio device, with say a switch advancing the stepper ?

This piece of code

  //this is causing the issue
    while (stepper.distanceToGo() !=0)
    {
    stepper.run();
    }

should be inside loop() but outside any other code blocks to make sure it is called in every iteration of loop().

And the while (stepper.distanceToGo() !=0) is unnecessary. Calls to stepper.run() will have no effect after the motor has reached its destination.

If another part of your code needs to know whether the motor has reached its destination then just check that (in the appropriate place) with if (stepper.distanceToGo() == 0) {

...R

To anyone who runs into this same issue, the solution was to run this piece of code (see below) after where ever there is stepper.run();

 if (!LoRa.begin(BAND)) {
    u8x8.drawString(0,1,"LoRa failed!");
   delay(2000);
   while (1);
  }

anon001:
To anyone who runs into this same issue,

Thanks for the update.

It would be useful for other readers if you post the complete working program.

...R

#include <LoRa.h>
#include <U8x8lib.h>
#include <Arduino.h>
#include <Accelstepper.h>
#include <Stepper.h>
#include <Wire.h> 

//Define stepper motor variables
//PIN SETUP
//PIN 14 = STEP
//PIN 27 = DIRECTION - HIGH spins one way and LOW spins the other way.
//PIN 26 = MS1
//PIN 25 = MS2

AccelStepper stepper(AccelStepper::DRIVER, 14,27);

int pos = 2000;
int newpos = 0;
int StepCounter = 0;
int Stepping = false;
String posstring;
String newposstring;

// These pins are for determining microstepping
int ms1 = 26;
int ms2 = 25;
//Define LED variables.
//YELLOW
int LED1 = 13;
//RED
int LED2 = 12;
//BLUE
int LED3 = 33;
//GREEN
int LED4 = 32;
//Dissect transmitted sections into each function

//LED
char ID1[2]; 
//Fixed distance
char ID2[2];
char ID3[2];
//Reverse direction
char ID4[2];


//This is the unique code that get recieved. This is default value.
char message[4] = {'0','0','0','0'};
//This is the RSSI. I.e. measure of strength of signal.
String rssi = "RSSI --";

// the OLED used
U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16);


//OLED pins to ESP32 GPIOs via this connection:
//OLED_SDA -- GPIO4
//OLED_SCL -- GPIO15
//OLED_RST -- GPIO16
// WIFI_LoRa_32 ports
// GPIO5  -- SX1278's SCK
// GPIO19 -- SX1278's MISO
// GPIO27 -- SX1278's MOSI
// GPIO18 -- SX1278's CS
// GPIO14 -- SX1278's RESET
// GPIO26 -- SX1278's IRQ(Interrupt Request)
 
#define SS      18
#define RST     14
#define DI0     26
#define BAND    915E6
 
void setup() {
  //Define Stepper Motor
  pinMode(27, OUTPUT);    
  pinMode(14, OUTPUT);
  digitalWrite(27, LOW);
  digitalWrite(14, LOW);

  //These pins are for determining microstepping
  pinMode(ms1, OUTPUT);
  pinMode(ms2,OUTPUT);
  digitalWrite(ms1,HIGH);
  digitalWrite(ms2,HIGH);

//Accelstepper variables
 stepper.setAcceleration(1000);
 stepper.setMaxSpeed(2000);

  //Define LED
  pinMode(LED1,OUTPUT);
  pinMode(LED2,OUTPUT);
  pinMode(LED3,OUTPUT);
  pinMode(LED4,OUTPUT);
  //Define OLED screen
  pinMode(16,OUTPUT);
  digitalWrite(16, LOW);    // set GPIO16 low to reset OLED
  delay(50); 
  digitalWrite(16, HIGH);


//Set parameters for text of OLED.
  u8x8.begin();
  u8x8.setFont(u8x8_font_chroma48medium8_r);

  //Transmission code
  Serial.begin(115200);
  while (!Serial); //if just the the basic function, must connect to a computer
  delay(1000);
 
u8x8.drawString(0,1,"LoRa Receiver");
  delay(1000);

  SPI.begin(5,19,27,18);
  LoRa.setPins(SS,RST,DI0);
   
  if (!LoRa.begin(BAND)) {
    while (1);
  }

    u8x8.drawString(0,1,"                     ");
    u8x8.drawString(0,1,"LoRa OK");
    delay(1000);
    u8x8.drawString(0,1,"                     ");

}

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {

    // read packet
    while (LoRa.available()) {
    String data = LoRa.readString();

   //use data from packet to execute command
   //each charcacter in string represents command
    ID1[0] = data.charAt(0);
    ID2[0] = data.charAt(1);
    ID3[0] = data.charAt(2);
    ID4[0] = data.charAt(3);
    
    message[0] = data.charAt(0);
    message[1] = data.charAt(1);
    message[2] = data.charAt(2);
    message[3] = data.charAt(3);

    //display packet data on screen
    u8x8.drawString(0,1,"                  ");
    u8x8.drawString(0,1,message);
    }
    // print RSSI of packet
    rssi = "RSSI " + String(LoRa.packetRssi());
    // Need c_str() to convert to string format that drawString can read.
    u8x8.drawString(0,2,rssi.c_str());
    delay(1000);



   //Turn ON LED ifd ESTOP activated.
      if (ID1[0]=='1')
    {
      digitalWrite(LED1,HIGH);
    }

    //Turn OFF LeD if ESTOP is not activated.
    if(ID1[0]=='0')
    {
      digitalWrite(LED1,LOW);
    }
    
    //Run stepper motor forward if ID2 is equal to 1 and direction is equal to 0.
    //Only run if Estop not activated.

    if (ID2[0]=='1'&& ID4[0]=='0'&& ID1[0] != '1')
    {
    

    newpos = newpos + pos;
    stepper.moveTo(newpos);


      //Display movement
      posstring = String(pos);
      newposstring = String(newpos);
      u8x8.drawString(0,3,posstring.c_str());
      u8x8.drawString(0,4,newposstring.c_str());
      delay(1000);


    //Run stepper motor
    //Only run if Estop not activated.
    while (stepper.distanceToGo() !=0 && ID1[0] !='1')
    {
    stepper.run();
    
    ID2[0] = '0';
    }
    }

  //Run stepper motor bacwards if ID2 is equal to 1 and direction is equal to 1.
    if (ID2[0]=='1'&& ID4[0]=='1'&& ID1[0] !='1')
    {
    
    newpos = newpos - pos;
    stepper.moveTo(newpos);

     //Display movement
      posstring = String(pos);
      newposstring = String(newpos);
      u8x8.drawString(0,3,posstring.c_str());
      u8x8.drawString(0,4,newposstring.c_str());
      delay(1000);

    //Run stepper motor
    while (stepper.distanceToGo() !=0&& ID1[0] !='1')
    {
    stepper.run();
    
    ID2[0] = '0';
    }
    }


    
  //Clear display
  u8x8.drawString(0,1,"                  ");
  u8x8.drawString(0,2,"                  ");
  u8x8.drawString(0,3,"                  ");
  u8x8.drawString(0,4,"                  ");

  if (!LoRa.begin(BAND)) {
   while (1);
  }
  }
}