Hi everyone !
Last year, thanks to this forum's help, I achieved a project which was about controlling stepper motors, relays and mp3 shield at the same time, following a precise timetable. It was my first time working with stepper motors and i really enjoyed learning how to.
Here is the code i used :
#include "SerialMP3Player.h"
#define TX 15
#define RX 14
SerialMP3Player mp3(RX,TX);
#include <AccelStepper.h>
#define turn 3200
#define quar 400
AccelStepper stepper1(AccelStepper::DRIVER, 22, 23);
AccelStepper stepper2(AccelStepper::DRIVER, 28, 29);
AccelStepper stepper3(AccelStepper::DRIVER, 34, 35);
AccelStepper stepper4(AccelStepper::DRIVER, 40, 41);
AccelStepper stepper5(AccelStepper::DRIVER, 52, 53);
unsigned long startMillis;
unsigned long currentMillis;
struct Evenement
{
uint32_t temps;
float relay1;
float mp3;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
float vitesseMoteur3;
float accelerationMoteur3;
uint8_t nbPasMoteur3;
float vitesseMoteur4;
float accelerationMoteur4;
uint8_t nbPasMoteur4;
float relay2;
float vitesseMoteur5;
float accelerationMoteur5;
uint8_t nbPasMoteur5;
float relay3;
};
int mouvement = 0;
Evenement evenements[] = {
//temps rel1 mp3 stepper1 stepper2 stepper3 stepper4 Rel2 stepper5 Rel3
{0000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{5000, 1, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{10000, 0, 1, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{18000, 0, 0, 1500, 1000, 4, 1500, 1000, 4, 1500, 1000, 4, 1500, 1000, 4, 0, 0.0, 0.0, 0, 0},
{30000, 0, 0, 1500, 1000, 2, 0.0, 0.0, 0, 1500, 1000, 2, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{33000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 2, 0.0, 0.0, 0, 1500, 1000, 2, 0, 0.0, 0.0, 0, 0},
{36000, 0, 0, 1500, 1000, 4, 0.0, 0.0, 0, 1500, 1000, 4, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{42000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 4, 0.0, 0.0, 0, 1500, 1000, 4, 0, 0.0, 0.0, 0, 0},
//8
{48000, 0, 0, 1500, 1000, 0, 0.0, 0.0, 0, 1500, 1500, 3, 1500, 1000, 0, 0, 0.0, 0.0, 0, 0},
{51000, 0, 0, 0.0, 0.0, 0, 1500, 1500, 3, 1500, 1500, 4, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{54000, 0, 0, 0.0, 0.0, 0, 1500, 1500, 4, 1500, 1500, 3, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{57000, 0, 0, 0.0, 0.0, 0, 1500, 1500, 3, 1500, 1500, 4, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{60000, 0, 0, 0.0, 0.0, 0, 1500, 1500, 4, 1500, 1500, 3, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{63000, 0, 0, 0.0, 0.0, 0, 1500, 1500, 3, 1500, 1500, 4, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{66000, 0, 0, 0.0, 0.0, 0, 1500, 1500, 4, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
//15
{69000, 0, 0, 1500, 1000, 4, 1500, 1000, 6, 1500, 1000, 6, 1500, 1000, 4, 0, 0.0, 0.0, 0, 0},
{75000, 0, 0, 1500, 1000, 6, 1500, 1000, 4, 1500, 1000, 4, 1500, 1000, 6, 0, 0.0, 0.0, 0, 0},
{83000, 0, 0, 1500, 1000, 3, 1500, 1000, 2, 1500, 1000, 1, 1500, 1000, 0, 0, 0.0, 0.0, 0, 0},
{93000, 0, 0, 1500, 1000, 0, 1500, 1000, 1, 1500, 1000, 2, 1500, 1000, 3, 0, 0.0, 0.0, 0, 0},
//19
{96000, 0, 0, 1500, 1000, 3, 1500, 1000, 3, 1500, 1000, 3, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{102000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 1, 0, 0.0, 0.0, 0, 0},
{104000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 1, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{106000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 1, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{108000, 0, 0, 1500, 1000, 1, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0, 0.0, 0.0, 0, 0},
{110000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{112000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{114000, 0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 1, 0, 0.0, 0.0, 0, 0},
{116000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 1, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{118000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 1, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{120000, 0, 0, 1500, 1000, 1, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0, 0.0, 0.0, 0, 0},
{122000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{124000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{126000, 0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{129000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 2, 0, 0.0, 0.0, 0, 0},
{130000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 2, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{131000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 2, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{132000, 0, 0, 1500, 1000, 2, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0, 0.0, 0.0, 0, 0},
{133000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{134000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{135000, 0, 0, 1500, 1000, 3, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
//40
{140000, 0, 0, 1200, 1000, 0, 1200, 1000, 6, 1200, 1000, 6, 1200, 1000, 0, 0, 0.0, 0.0, 0, 0},
{151000, 0, 0, 1200, 1000, 4, 1200, 1000, 10, 1200, 1000, 10, 1200, 1000, 4, 0, 0.0, 0.0, 0, 0},
{163000, 0, 0, 0.0, 0.0, 0, 1500, 1000, 9, 0.0, 0.0, 0, 1500, 1000, 3, 0, 0.0, 0.0, 0, 0},
{166000, 0, 0, 1500, 1000, 3, 1500, 1000, 10, 1500, 1000, 9, 1500, 1000, 4, 0, 0.0, 0.0, 0, 0},
{169000, 0, 0, 1500, 1000, 4, 1500, 1000, 9, 1500, 1000, 10, 1500, 1000, 3, 0, 0.0, 0.0, 0, 0},
{172000, 0, 0, 1500, 1000, 3, 1500, 1000, 10, 1500, 1000, 9, 1500, 1000, 4, 0, 0.0, 0.0, 0, 0},
// 46
{175000, 0, 0, 1500, 1000, 4, 1500, 1000, 9, 1500, 1000, 8, 1500, 1000, 5, 0, 0.0, 0.0, 0, 0},
{181000, 0, 0, 1500, 1000, 5, 1500, 1000, 8, 1500, 1000, 9, 1500, 1000, 4, 0, 0.0, 0.0, 0, 0},
{184000, 0, 0, 1500, 1000, 4, 1500, 1000, 9, 1500, 1000, 8, 1500, 1000, 5, 0, 0.0, 0.0, 0, 0},
{187000, 0, 0, 1500, 1000, 5, 1500, 1000, 8, 1500, 1000, 9, 1500, 1000, 4, 0, 0.0, 0.0, 0, 0},
{190000, 0, 0, 1500, 1000, 4, 1500, 1000, 9, 1500, 1000, 8, 1500, 1000, 5, 0, 0.0, 0.0, 0, 0},
//51
{195000, 0, 0, 1500, 1000, 0, 1500, 1000, 0, 1500, 1000, 0, 1500, 1000, 0, 0, 0.0, 0.0, 0, 0},
{222000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{224300, 1, 2, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
//part 2
//54
{240000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1, 0.0, 0.0, 0, 0},
{241000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{320000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 1},
{330000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1, 0.0, 0.0, 0, 1},
{331000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 1},
{355000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 400, 300, 1, 1},
{375000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 400, 300, 2, 1},
{395000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 400, 300, 4, 1},
{415000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 400, 300, 2, 1},
{435000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 400, 300, 3, 1},
{455000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 400, 300, 0, 1},
{475000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1, 0.0, 0.0, 0, 0},
{476000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{625000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 1, 0.0, 0.0, 0, 0},
{626000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0},
{640000, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0, 0}
};
void setup()
{
Serial.begin(115200); //start Serial in case we need to print debugging info
startMillis = millis();
Serial.print ("millis() = ");
Serial.println (millis());
mp3.begin(9600); // start mp3-communication
delay(500); // wait for init
mp3.sendCommand(CMD_SEL_DEV, 0, 2); //select sd-card
delay(500); // wait for init
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
}
void loop()
{
if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 70))
{
{
if (evenements[mouvement].vitesseMoteur1 > 0)
{
stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
}
if (evenements[mouvement].vitesseMoteur2 > 0)
{
stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
}
if (evenements[mouvement].vitesseMoteur3 > 0)
{
stepper3.setMaxSpeed(evenements[mouvement].vitesseMoteur3);
stepper3.setAcceleration(evenements[mouvement].accelerationMoteur3);
stepper3.moveTo(evenements[mouvement].nbPasMoteur3 * turn);
}
if (evenements[mouvement].vitesseMoteur4 > 0)
stepper4.setMaxSpeed(evenements[mouvement].vitesseMoteur4);
stepper4.setAcceleration(evenements[mouvement].accelerationMoteur4);
stepper4.moveTo(evenements[mouvement].nbPasMoteur4 * turn);
}
if (evenements[mouvement].vitesseMoteur5 > 0)
{
stepper5.setMaxSpeed(evenements[mouvement].vitesseMoteur5);
stepper5.setAcceleration(evenements[mouvement].accelerationMoteur5);
stepper5.moveTo(evenements[mouvement].nbPasMoteur5 * quar);
}
if (evenements[mouvement].relay1 == 1)
{
digitalWrite(9,LOW);
}
if (evenements[mouvement].relay1 == 0 )
{
digitalWrite(9,HIGH);
}
if (evenements[mouvement].relay2 == 1)
{
digitalWrite(10,LOW);
}
if (evenements[mouvement].relay2 == 0 )
{
digitalWrite(10,HIGH);
}
if (evenements[mouvement].relay3 == 1)
{
digitalWrite(11,LOW);
}
if (evenements[mouvement].relay3 == 0 )
{
digitalWrite(11,HIGH);
}
if (evenements[mouvement].mp3 == 1 )
{
mp3.setVol(25);
mp3.play(1);
}
if (evenements[mouvement].mp3 == 2 )
{
mp3.stop();
}
if (evenements[mouvement].temps == 640000)
{
mouvement = 0; // On repart au début des mouvements
startMillis=millis(); // Remet le chornomètre à 0
}
mouvement++; // on a traité ce mouvement, on passe au suivant
}
}
stepper1.run();
stepper2.run();
stepper3.run();
stepper4.run();
stepper5.run();
}
I'm here today because i would like to adapt this code for a new project, using relays and a windshield wipper motor controlled by a double BTS7960 shield (like this one).
I started to rework the code using the exemple made by Robojax for the BTS7960 :
#define RPWM 2 // define pin 3 for RPWM pin (output)
#define R_EN 23 // define pin 2 for R_EN pin (input)
#define R_IS 25 // define pin 5 for R_IS pin (output)
#define LPWM 3 // define pin 6 for LPWM pin (output)
#define L_EN 24 // define pin 7 for L_EN pin (input)
#define L_IS 26 // define pin 8 for L_IS pin (output)
#define CW 1 //do not change
#define CCW 0 //do not change
#define debug 1 //change to 0 to hide serial monitor debugging infornmation or set to 1 to view
#include <RobojaxBTS7960.h>
RobojaxBTS7960 motor(R_EN,RPWM,R_IS, L_EN,LPWM,L_IS,debug);
void setup() {
// BTS7960 Motor Control Code by Robojax.com 20190622
Serial.begin(9600);// setup Serial Monitor to display information
motor.begin();
// BTS7960 Motor Control Code by Robojax.com 20190622
}
void loop() {
// BTS7960 Motor Control Code by Robojax.com 20190622
motor.rotate(100,CW);// run motor with 100% speed in CW direction
delay(5000);//run for 5 seconds
motor.stop();// stop the motor
delay(3000);// stop for 3 seconds
motor.rotate(100,CCW);// run motor at 100% speed in CCW direction
delay(5000);// run for 5 seconds
motor.stop();// stop the motor
delay(3000); // stop for 3 seconds
// slowly speed up the motor from 0 to 100% speed
for(int i=0; i<=100; i++){
motor.rotate(i,CCW);
delay(50);
}
// slow down the motor from 100% to 0 with
for(int i=100; i>0; i--){
motor.rotate(i,CCW);
delay(50);
}
motor.stop();// stop motor
delay(3000); // stop for 3 seconds
// BTS7960 Motor Control Code by Robojax.com 20190622
}// loop ends
For this project, i want the motor to rotates and stops, following the timetable. Each rotation should begin and end with accelaration and decelaration, with a constant speed in between that varies from one rotation to another.
I was thinking a good way to do that would be to have 5 "commands" for the motor :
1 Motor stop
2 Motor starts rotating CCW with an accelaration
3 Motor stops rotating CCW with a deceleration
4 Motor starts rotating CW with an accelaration
5 Motor stops rotating CW with a deceleration
So far i've got this, which obviously doesn't work as i expected (I focused on the motors, the relays are meant to be added after i sort this out) :
#define RPWM 2 // define pin 3 for RPWM pin (output)
#define R_EN 23 // define pin 2 for R_EN pin (input)
#define R_IS 25 // define pin 5 for R_IS pin (output)
#define LPWM 3 // define pin 6 for LPWM pin (output)
#define L_EN 24 // define pin 7 for L_EN pin (input)
#define L_IS 26 // define pin 8 for L_IS pin (output)
#define CW 1 //do not change
#define CCW 0 //do not change
#define debug 1 //change to 0 to hide serial monitor debugging infornmation or set to 1 to view
#include <RobojaxBTS7960.h>
RobojaxBTS7960 motor(R_EN,RPWM,R_IS, L_EN,LPWM,L_IS,debug);
unsigned long startMillis;
unsigned long currentMillis;
struct Evenement
{
uint32_t temps;
float sensMoteur;
float vitesseMoteur;
float accelerationMoteur;
};
int mouvement = 0;
Evenement evenements[] = {
//temps sensM vitm accM
{0000, 0, 0, 0},
{5000, 1, 10, 0},
{10000, 2, 20, 0},
{15000, 0, 0, 0},
{20000, 4, 40, 0},
{25000, 2, 20, 0},
{30000, 0, 0, 0},
{35000, 0, 0, 0}
};
void setup()
{
Serial.begin(115200); //start Serial in case we need to print debugging info
startMillis = millis();
Serial.print ("millis() = ");
Serial.println (millis());
motor.begin();
}
void loop()
{
if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 8))
{
{
if (evenements[mouvement].sensMoteur = 0)
{
motor.stop();
}
if (evenements[mouvement].sensMoteur = 1)
{
for(int vitesseMoteur=0; vitesseMoteur<=100; vitesseMoteur++){
motor.rotate(vitesseMoteur,CCW);
}
}
if (evenements[mouvement].sensMoteur = 2)
{
for(int vitesseMoteur=vitesseMoteur; vitesseMoteur>0; vitesseMoteur--){
motor.rotate(vitesseMoteur,CCW);
}
motor.stop();
}
if (evenements[mouvement].sensMoteur = 3)
{
for(int vitesseMoteur=0; vitesseMoteur<=100; vitesseMoteur++){
motor.rotate(vitesseMoteur,CW);
}
}
if (evenements[mouvement].sensMoteur = 4)
{
for(int vitesseMoteur=vitesseMoteur; vitesseMoteur>0; vitesseMoteur--){
motor.rotate(vitesseMoteur,CW);
}
motor.stop();
}
if (evenements[mouvement].temps == 35000)
{
mouvement = 0; // On repart au début des mouvements
startMillis=millis(); // Remet le chornomètre à 0
}
mouvement++; // on a traité ce mouvement, on passe au suivant
}
}
}
When the code is uploaded, the motor rotate and then get like shaky, with little CW and CCW rotations
If anyone has had the opportunity to work on similar projects and have some advice to help me,
that'd be great !