Problem with Wirelessly Controlled Step Motor

Hi there!

I'm working on a project where I wirelessly control two step motors using an arduino uno. To send commands to the motors, I have a second uno connected to my laptop. Commands are entered into the serial monitor, sent to the arduino hooked to my computer, and then transmitted wirelessly using the virtual wire library to the arduino connected to the motors.

The problem I'm having is that when I control the motors wirelessly, one of the motors only turns weakly in one direction. Both of the motors work fine when I directly control them from my laptop (using a separate program). However, when I send the commands wirelessly one motor works while the other only works in one direction.

I read on this post: Stepper motor, doesn't turn counter clockwise, wrong steps number indication - Motors, Mechanics, Power and CNC - Arduino Forum that changing the order of the pins might help. I tried all 24 permutations, but all I found were 8 ways to make it work in just one direction.

The motors are powered by a wall adapted, so it probably isn't a problem with the power supply.

Here is the program used to transmit the commands:

#include <VirtualWire.h>
//Transmitter Code

char buffer[5];
void setup()
{
  Serial.begin(9600);
  vw_setup(2000);
  vw_set_tx_pin(7);
  
}

void loop()
{
  if(Serial.available()>0){
    Serial.readBytes(buffer,5);
   
      vw_send((uint8_t*)buffer,5);
      vw_wait_tx();
   
  }
}

And here is the program I've been using to receive the commands and turn the motor. First digit specifies which motor, second digit specifies direction, and last two digits tell it how far to rotate (64=full turn).

#include <Stepper.h>
#include<VirtualWire.h>

String command;
int anglei;
String angle;
char buffer[5];
int i;

int motorPin1 = 8;
int motorPin2 = 10;
int motorPin3 = 9;
int motorPin4 = 11;

int motorPin5 = 4;   
int motorPin6 = 6;  
int motorPin7 = 5;    
int motorPin8 = 7;

String a;
String b;
String c;
String d;

Stepper stepper1(64, motorPin1, motorPin2, motorPin3, motorPin4);
Stepper stepper2(64, motorPin5, motorPin6, motorPin7, motorPin8);

void setup()
{
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  
  pinMode(motorPin5, OUTPUT);
  pinMode(motorPin6, OUTPUT);
  pinMode(motorPin7, OUTPUT);
  pinMode(motorPin8, OUTPUT);
  
  stepper1.setSpeed(400);
  stepper2.setSpeed(200);
  
  vw_setup(2000);
  vw_set_rx_pin(2);
  vw_rx_start(); 
  
}

void loop(){
  uint8_t buflen=VW_MAX_MESSAGE_LEN;
  uint8_t buf[buflen];
  
  if(vw_get_message(buf, &buflen))
  {
    for(int i=0;i<buflen;i++)
    {
      a=String(int(buf[0])-48); 
      b=String(int(buf[1])-48);
      c=String(int(buf[2])-48);
      d=String(int(buf[3])-48);
  
      command=a+b+c+d;
      angle=String(command.charAt(2))+String(command.charAt(3));
      anglei=32*(angle.toInt());
      if(command.charAt(0)=='1')
      {
        if(command.charAt(1)=='1')
        {
         stepper1.step(anglei);
        }
    
       if(command.charAt(1)=='2')
       {
         anglei=int(anglei*-1);
          stepper1.step(int(anglei));
       }  
      }
      if(command.charAt(0)=='2')
      {
        if(command.charAt(1)=='1')
        {
          stepper2.step(anglei);
        }
        if(command.charAt(1)=='2')
        {
          anglei=int(anglei*-1);
          stepper2.step(int(anglei));
        }
      }
  break;
  }
  }
}

I've gotten both motors to work fine when connected to my laptop, but just can't get it to work wirelessly. Any help will be greatly appreciated.

Thanks!

Without a wiring diagram and more information about your setup, it is not likely that you will get much useful help.

What motor driver do you have, what motors (or what are the current and voltage ratings of the motors) and how much current at what voltage does the wall adapter supply?

Design your program so that the identical code is used to drive the motors on the program directly connected to your laptop and on the program that's controlled wirelessly. Then you can be sure the problem is in the wireless code.

...R

Thanks for the suggestions!

The step motors that I'm using are 28BYJ-48 step motors with a ULN 2003 driver board that I bought off ebay. They are rated for 92mA and between 5 and 12 volts. The wall adapter I'm using is 500 mA and 12 volts. I've also tried powering the arduino using a 9V battery and connected to a USB separate from the transmitter. None of these solutions have worked. I've tried switching the pins that each step motor is plugged into, and got the opposite motor to not work. This suggests something wrong with one of the pins, but I also tried changing the microcontroller controlling the motors and it still failed to work.

As for wiring, the two step motors are connected to the arduino with the 5V and GND pins daisy chained to the arduino.

Here is the program that I use to control the motors using the USB. This program works successfully, and the code for controlling the motors is identical to the code for controlling them wirelessly; the only difference is how the commands are received.

#include <Stepper.h>

String command;
int anglei;
String angle;
char buffer[5];

int motorPin1 = 8;
int motorPin2 = 10;
int motorPin3 = 9;
int motorPin4 = 11;

int motorPin5 = 4;   
int motorPin6 = 6;  
int motorPin7 = 5;    
int motorPin8 = 7;

Stepper stepper1(64, motorPin1, motorPin2, motorPin3, motorPin4);
Stepper stepper2(64, motorPin5, motorPin6, motorPin7, motorPin8);

void setup()
{
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  
  pinMode(motorPin5, OUTPUT);
  pinMode(motorPin6, OUTPUT);
  pinMode(motorPin7, OUTPUT);
  pinMode(motorPin8, OUTPUT);
  
  stepper1.setSpeed(300);
  stepper2.setSpeed(300);
  
  Serial.begin(9600);
}

void loop(){
  if (Serial.available()>0)
  {
  Serial.readBytes(buffer,5);
  command=String(buffer);
  angle=String(command.charAt(2))+String(command.charAt(3));
  anglei=32*(angle.toInt());
  if(command.charAt(0)=='1')
  {
    if(command.charAt(1)=='1')
    {
     stepper1.step(anglei);
    }
    
   if(command.charAt(1)=='2')
   {
     anglei=int(anglei*-1);
      stepper1.step(int(anglei));
   }  
  }
  if(command.charAt(0)=='2')
  {
    if(command.charAt(1)=='1')
    {
      stepper2.step(anglei);
    }
    if(command.charAt(1)=='2')
    {
      anglei=int(anglei*-1);
      stepper2.step(int(anglei));
    }
  }
  Serial.println(anglei);
}
}

I'm strongly suspecting that the problem is with how I receive the code from the transmitter using virtual wire. Using serialprint, I noticed that the 4 digit commands being sent were appearing as hexadecimal, so for the receiver code I subtract 48 from each character to return to the original number. I suspect that this is the wrong way to do it, though it does work for one of the motors (but not the other). Is there a proper way of translating the hexadecimal that the virtual wire sends it as back to the original form? It's strange because the wireless program works, but only for one of the motors. Should I just try buying some more motors?

Much thanks!

mechanist123:
I've gotten both motors to work fine when connected to my laptop, but just can't get it to work wirelessly. Any help will be greatly appreciated.

Was your test done with the same two Arduinos running, but with a physical wire carrying the data between them instead of the wireless? If so, then your local-vs-remote test proves your driver and the motors are fine, as well as all the code that is not related to the radio.

I think you are correct to suspect something with the way the values are transmitted, or received. It sounds like some sort of data conversion, or dropped character in your code. I don't actually know if this following idea is possible, but I throw it out as an idea to consider; Have your receiving Arduino write some value to a static memory location, and then later connect it to your computer to read that value. This might be done at several important steps along the way, as a way to see what the data looks like at those steps.

Note that I am personally interested in this project, not because I want to transmit this sort of data wirelessly, but that I want to control two motors that are up to 100ft apart. I need some sort of data connection that can span the distance, but don't want radio. So, I need to convert to something like RS232, or RS485. I imagine this sort of conversion will have similar difficulties you what you are experiencing.

-Joe

Joe, when I got both motors to run I had the one arduino that was connected to the two step motors directly linked to my laptop using a USB cable. I controlled it using the serial monitor, so I only had to use the one arduino. I'm also reaching the conclusion that the motors, microcontrollers, and code are all fine and that the problem is with the conversion of data. I'll definitely look into your suggestion! Good luck with your project as well!

I don't know virtualWire so there may be some nuance of your program that isn't obvious to me.

I suggest writing a short standalone sketch that sends data over virtual wire and load that onto your "remote" Arduino. Then put the "receiver" code on the Arduino connected to your PC with suitable Serial.print commands so you can monitor what it is actually receiving.

One thought (since you say one motor works) is that the transmitted chars are not where you expect them to be so the chars for (say) motor1 are not found and the chars for motor2 are used for motor1.

...R

Thanks for all the helpful suggestions!

I suggest writing a short standalone sketch that sends data over virtual wire and load that onto your "remote" Arduino. Then put the "receiver" code on the Arduino connected to your PC with suitable Serial.print commands so you can monitor what it is actually receiving.

I've tried doing that, and what prints is what I expect. Still no luck though.

I've been trying something a little different. Instead of sending a four digit code that tells the remote arduino which motor, direction, and number of steps, I made a much simpler code. There are four characters that can be sent (a, b, c, d). Each character moves one motor one direction a certain number of steps. For example, sending the character "a" makes motor1 turn clockwise 320 steps, character "b" makes motor1 turn counterclockwise 320 steps, and etc.

Here is the code I wrote to do this:

#include <Stepper.h>
#include<VirtualWire.h>



int motorPin1 = 8;
int motorPin2 = 10;
int motorPin3 = 9;
int motorPin4 = 11;

int motorPin5 = 4;   
int motorPin6 = 6;  
int motorPin7 = 5;    
int motorPin8 = 7;


Stepper stepper1(64, motorPin1, motorPin2, motorPin3, motorPin4);
Stepper stepper2(64, motorPin5, motorPin6, motorPin7, motorPin8);

void setup()
{
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  
  pinMode(motorPin5, OUTPUT);
  pinMode(motorPin6, OUTPUT);
  pinMode(motorPin7, OUTPUT);
  pinMode(motorPin8, OUTPUT);
  
  stepper1.setSpeed(400);
  stepper2.setSpeed(200);
  
  vw_setup(2000);
  vw_set_rx_pin(2);
  vw_rx_start(); 
  
}

void loop(){
  uint8_t buflen=VW_MAX_MESSAGE_LEN;
  uint8_t buf[buflen];
  
  if(vw_get_message(buf, &buflen))
  {
    for(int i=0;i<buflen;i++)
    {
      if(buf[i]=='a')
      {
        stepper1.step(-320);
      }
      if(buf[i]=='b')
      {
        stepper1.step(320);
      }
      if(buf[i]=='c')
      {
        stepper2.step(320);
      }
      if(buf[i]=='d')
      {
        stepper2.step(-320);
      }
      break;
    }
  }
}

I thought that this would be a simple way of at least getting all of the motors moving, even if it meant that I can't control the number of steps. However, even with this code only one of the motors is working with the other one moving sluggishly one direction and not moving at all the other direction. I'm suspecting that I'm doing something very wrong with Virtual Wire, and I have to admit that this is becoming very frustrating.

if(buf[i]='a')

This won't work. Use "==" for comparisons.

^^^I had that originally, and I realized that that was why it wasn't working. I changed it to == and now it works, but one of the motors still refuses to turn one direction even though the motor works fine with a serial connection.

If (as you say) the receiver is getting the correct data the problem MUST be in the way the receiver interprets that data.

...R

Agreed. I'm going to start looking into fundamentally how virtual wire works and how it interprets data. I'm suspecting that there's something wrong with data conversions from one data type to another.

While errors in library code are possible, they are much less likely than an error in your (or my) own code.

...R