i am trying to get my rc transmiter to control my nema17 stepper motor. i can get the receiver to work in the serial monitor, but cant figure out how to use that data to activate my stepper motor. i am using a switch to change the speed and a joystick to control direction.
here is the receiver code as i have it now. currently i am only try to get one motor to work with one axis of the joystick
/*
DIY Arduino based RC Transmitter Project
== Receiver Code - ESC and Servo Control ==
by Dejan Nedelkovski, www.HowToMechatronics.com
Library: TMRh20/RF24, GitHub - nRF24/RF24: OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices
*/ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #include <Stepper.h>
RF24 radio(10, 9); // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
int Delay=10;
byte directionPin = 9;
byte stepPin = 8;
int numberOfSteps = 100;
byte ledPin = 13;
int pulseWidthMicros = 20; // microseconds
int millisbetweenSteps = 250; // milliseconds - or try 1000 for slower steps
// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
byte j1PotX;
byte j1PotY;
byte j1Button;
byte j2PotX;
byte j2PotY;
byte j2Button;
byte pot1;
byte pot2;
byte tSwitch1;
byte tSwitch2;
byte button1;
byte button2;
byte button3;
byte button4;
};
Data_Package data; //Create a variable with the above structure
void setup() {
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
radio.startListening(); // Set the module as receiver
resetData();
pinMode(directionPin, OUTPUT);
pinMode(stepPin, OUTPUT);
// Declare pins as Outputs
}
void loop() {
// Check whether we keep receving data, or we have a connection between the two modules
currentTime = millis();
if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection
resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function
}
// Check whether there is data to be received
if (radio.available()) {
radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
lastReceiveTime = millis(); // At this moment we have received the data
}
if (byte(data.tSwitch2)==0){
int millisbetweenSteps=5;
}
if (data.tSwitch2==1){
int millisbetweenSteps=25;
}
if (byte(data.j2PotY)<120){
digitalWrite(directionPin,LOW);
digitalWrite(stepPin,HIGH);
delay(millisbetweenSteps);
digitalWrite(stepPin,LOW);
delay(millisbetweenSteps);
}
// Print the data in the Serial Monitor
Serial.print("; tSwitch2: ");
Serial.print(data.tSwitch2);
Serial.print("; j1PotX: ");
Serial.print(data.j1PotX);
Serial.print("; j2PotY: ");
Serial.print(data.j2PotY);
Serial.print("; j2PotX: ");
Serial.print(data.j2PotX);
Serial.print("; button1: ");
Serial.print(data.button1);
Serial.print("; button3: ");
Serial.print(data.button3);
Serial.print(";tSwitch1: ");
Serial.print(data.tSwitch1);
Serial.print("millisbetweenSteps:");
Serial.println(millisbetweenSteps);
}
void resetData() {
// Reset the values when there is no radio connection - Set initial default values
data.j1PotX = 127;
data.j1PotY = 127;
data.j2PotX = 127;
data.j2PotY = 127;
data.j1Button = 1;
data.j2Button = 1;
data.pot1 = 1;
data.pot2 = 1;
data.tSwitch1 = 1;
data.tSwitch2 = 1;
data.button1 = 1;
data.button2 = 1;
data.button3 = 1;
data.button4 = 1;
data.tSwitch1 = 1;
}
i am very new to this, so I am not very good at programing. i am trying to build the DIY RC transmitter from this website,https://howtomechatronics.com/projects/diy-arduino-rc-transmitter/. The site gives examples for servo and DC motors but not stepper motors. I can get the transmitter and receiver to talk to each other and show the data in serial monitor. I can also get the motor to work as desired seperatly from the receiver code. im have no idea how you use the data.j2PotY to control the stepper motor step/dir pins. I am using an a4988 stepper driver, forgot to mention that.
i did what you suggested and eliminated the int, tSwitch2 now changes the variable. thank you. any ideas on how to use data.j2PotY (0-255) to manipulate the step/dir pins for the a4988 that drives my motor? the code i am using works but the motor is going very slow, maybe 3 steps per second.
First figure out how to control the motor programmatically, and only then add back the receiver code and connect them up - you are trying to do two complicated/tricky things at once, whereas you will get much better results if you tackle and understand each separately, then combine them.
I have found multiple examples of programs to run the motor, and can get them to work. My problem is that all of the examples move the motor a set number of rotations. I can not find one that show how to move the motor continuously as long as there is a signal from the joystick. Or one that demonstrates how to use a switch to toggle the speed. I would be greatful for any suggestions.
Have you looked at all the examples with the AccelStepper library for instance?
The ProportionalControl example and ConstantSpeed examples show setSpeed(),
runSpeed() and runSpeedToPosition() methods.
I think you probably just need to update setSpeed() when direction and speed commands are received, and use runSpeed() in loop()?
AccelStepper handles speed ramping so you don't risk stalling at sudden changes
in speed like the Stepper library does...
I tried using Accelstepper library and was successful with increasing the speed. the problem is that accelstepper deals in absolute movements once i plug the motor code into my receiver code the motor pulses. also i cant figure out how to do a direction change. can someone direct me to an example using an a4988 motor driver, joystick, nema17 stepper motor, and data from RC receiver, to control speed and direction of stepper motor with a high speed (500+ rpm)
When using the moveTo() function the moves are absolute. So a moveTo(250) will move the stepper 250 steps. If you issue another moveTo(250), nothing will happen because the stepper is already at 250. To reverse, send moveTo(0), that will reverse the motor back to start. Or, from 0, move(-500) will move the stepper 500 steps in reverse to position -500.
The move() function is relative. Say move(250) the stepper moves to 250. Do it again and the stepper moves to 500. Negative steps to reverse the motor. So move(-500) will put the stepper back to 0.
I can get that to work no problem. That is not what i am trying to do though. I am building a remote turret for my paintball gun. i need the joystick to mover a stepper, at a set speed, as long as the value is within set ranges (CCW <400 CW >600. then stop when it is in the middle position (500). i am using the input from a toggle switch to change between two pre-determined speeds. hopefully that will make my goal a little clearer.
i took your advice in post #13, kinda. i found a code that does what i want, but with a nasty side effect. when you change directions you must let the deceleration finish before the motor will change direction. i added a section to reset the current position variable, but thats is going to cause issues with my limits, if my origin point is constantly moving. is there a way to save the current position before resetting it, basically reset it to the same position. here is the code in question.
``/*
DIY Arduino based RC Transmitter Project
== Receiver Code - ESC and Servo Control ==
by Dejan Nedelkovski, www.HowToMechatronics.com
Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <AccelStepper.h>
RF24 radio(10, 9); // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
AccelStepper stepper1(1, 6, 7);
int X_val = 0; // Value for X pos of JS
int Y_val = 0; // Value for Y pos of JS
int position_to_go_max = 6000;
int position_to_go_min = 0;// Arbitrary Position for motor to go
int previousPosition;
// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
byte j1PotX;
byte j1PotY;
byte j1Button;
byte j2PotX;
byte j2PotY;
byte j2Button;
byte pot1;
byte pot2;
byte tSwitch1;
byte tSwitch2;
byte button1;
byte button2;
byte button3;
byte button4;
};
Data_Package data; //Create a variable with the above structure
void setup() {
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
radio.startListening(); // Set the module as receiver
//Stepper
stepper1.setMaxSpeed(10000);
stepper1.setAcceleration(1000);
stepper1.setSpeed(10000);
stepper1.setCurrentPosition(3000);
//stepper1.moveTo(position_to_go_max);
}
void loop() {
// Check whether we keep receving data, or we have a connection between the two modules
currentTime = millis();
// Check whether there is data to be received
if (radio.available()) {
radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
lastReceiveTime = millis(); // At this moment we have received the data
}
X_val = (data.j2PotX);
Y_val = (data.j2PotY);
Serial.println(Y_val);
if (Y_val>100 &&Y_val<140){
stepper1.currentPosition=(stepper1.currentPosition);
}
if ( Y_val < 100) {
stepper1.run();
stepper1.moveTo(position_to_go_min);
}
if ( Y_val > 140) {
stepper1.run();
stepper1.moveTo(position_to_go_max);
}
}
`