Hi. I have a project in which I have to command two steppers with ULN2003 using Bluetooth module HC-05 and the app Serial bluetooth. It has a chance to freeze each time I execute a command that is unknown or that cannot be executed. It does not freeze when I let any of the drivers be active after an execution of a command.
The only current way to get it to work again is to have a print spam messages in the monitor and will unfreeze it.
#include <Stepper.h>
#include <AccelStepper.h>
#include <MultiStepper.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <EEPROM.h>
// Definirea adreselor EEPROM pentru pozițiile motoarelor
#define MOTOR1_EEPROM_ADDRESS 0
#define MOTOR2_EEPROM_ADDRESS 10
// Pini pentru motorul 1
#define motor1Pin1 7
#define motor1Pin2 6
#define motor1Pin3 5
#define motor1Pin4 4
// Pini pentru motorul 2
#define motor2Pin1 11
#define motor2Pin2 10
#define motor2Pin3 9
#define motor2Pin4 8
#define bluetoothTx 1
#define bluetoothRx 0
// Definirea adresei I2C pentru LCD QAPASS
#define LCD_ADDRESS 0x27
#define LCD_COLUMNS 16
#define LCD_ROWS 2
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS);
// Pini pentru modulul Bluetooth HC-05
#define bluetoothEn 2 // Pinul EN al modulului Bluetooth
#define bluetoothState 3 // Pinul STATE al modulului Bluetooth
AccelStepper motor1(AccelStepper::FULL4WIRE, motor1Pin1, motor1Pin3, motor1Pin2, motor1Pin4);
AccelStepper motor2(AccelStepper::FULL4WIRE, motor2Pin1, motor2Pin3, motor2Pin2, motor2Pin4);
#define MAX_COMMAND_LENGTH 10 // Ajustează dimensiunea maximă a comenzilor
char receivedCommand[MAX_COMMAND_LENGTH + 1]; // Adăugăm un spațiu suplimentar pentru terminator
int commandIndex = 0;
long motor1Position = 0;
long motor2Position = 0;
// Timeout pentru comenzi
unsigned long lastCommandTime = 0;
const unsigned long commandTimeout = 5000; // 5 secunde timeout
// Debug flag
bool debug = true;
void setup() {
lcd.setBacklight(LOW); // Setează retroiluminarea la nivel scăzut (LOW) pentru a o opri
delay(1000); // Așteaptă o secundă pentru a permite stabilizarea
lcd.setBacklight(HIGH);
// Citește pozițiile salvate din EEPROM
EEPROM.get(MOTOR1_EEPROM_ADDRESS, motor1Position);
EEPROM.get(MOTOR2_EEPROM_ADDRESS, motor2Position);
// Setează pozițiile curente ale motoarelor
motor1.setCurrentPosition(motor1Position);
motor2.setCurrentPosition(motor2Position);
Serial.begin(9600);
pinMode(bluetoothEn, INPUT);
pinMode(bluetoothState, OUTPUT);
Wire.begin();
lcd.begin(LCD_COLUMNS, LCD_ROWS, LCD_5x8DOTS);
lcd.print("Bun venit!");
// Afișează informații suplimentare pe LCD, dacă este cazul
lcd.setCursor(0, 1);
lcd.print("UNSTPB");
delay(5000);
// Afiseaza mesajul original
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Proiect Arduino");
motor1.setMaxSpeed(1000);
motor1.setAcceleration(100);
motor2.setMaxSpeed(1000);
motor2.setAcceleration(100);
// Inițializează modulul Bluetooth
digitalWrite(bluetoothEn, HIGH); // Activează modulul Bluetooth
// Inițializează modulul Bluetooth HC-05
delay(500); // Așteaptă 500 de milisecunde pentru a permite stabilizarea modulului
// Pini pentru motorul 1
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(motor1Pin3, OUTPUT);
pinMode(motor1Pin4, OUTPUT);
// Pini pentru motorul 2
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
pinMode(motor2Pin3, OUTPUT);
pinMode(motor2Pin4, OUTPUT);
// Dezactivează motoarele inițial
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor1Pin3, LOW);
digitalWrite(motor1Pin4, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
digitalWrite(motor2Pin3, LOW);
digitalWrite(motor2Pin4, LOW);
lastCommandTime = millis(); // Inițializează timpul ultimei comenzi
}
void loop() {
if (Serial.available() > 0) {
char receivedChar = Serial.read();
lastCommandTime = millis(); // Resetează timer-ul la primirea unei comenzi
if (receivedChar == '\n') {
// S-a primit o comandă completă, procesează șirul de caractere acumulat
receivedCommand[commandIndex] = '\0'; // Adaugă terminatorul de șir
processBluetoothCommand(receivedCommand);
commandIndex = 0; // Resetează indexul pentru următoarea comandă
} else if (receivedChar != '\r') {
if (commandIndex < MAX_COMMAND_LENGTH) {
// Adaugă caracterul la șirul de caractere acumulat
receivedCommand[commandIndex++] = receivedChar;
} else {
// Gestionare eroare: comanda este prea lungă
Serial.println("Comanda prea lungă");
commandIndex = 0; // Resetează indexul în caz de depășire
}
}
}
// Verifică dacă a trecut timpul de timeout fără a primi comenzi noi
if (millis() - lastCommandTime > commandTimeout) {
debugPrint("Timeout: Resetează sistemul");
// Cod pentru resetarea sistemului sau pentru a lua măsuri adecvate
lastCommandTime = millis(); // Resetează timer-ul pentru următorul ciclu
}
}
void saveMotorPositions() {
// Salvează pozițiile curente ale motoarelor în EEPROM
EEPROM.put(MOTOR1_EEPROM_ADDRESS, motor1.currentPosition());
EEPROM.put(MOTOR2_EEPROM_ADDRESS, motor2.currentPosition());
}
void moveMotorToPosition(AccelStepper &motor, long targetPosition) {
motor.moveTo(targetPosition);
motor.runToPosition();
deactivateMotorPins(motor);
}
void deactivateMotorPins(AccelStepper &motor) {
if (&motor == &motor1) {
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor1Pin3, LOW);
digitalWrite(motor1Pin4, LOW);
} else if (&motor == &motor2) {
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
digitalWrite(motor2Pin3, LOW);
digitalWrite(motor2Pin4, LOW);
}
}
void processBluetoothCommand(char* command) {
debugPrint("Comanda primita: " + String(command)); // Afișează comanda primită
// Afișează comanda și pe LCD
lcd.clear();
lcd.setBacklight(HIGH);
lcd.setCursor(0, 0);
lcd.print("Comanda: ");
lcd.setCursor(0, 1);
lcd.print(command);
if (strcmp(command, "1/90") == 0) {
motor1.runToNewPosition(512);
deactivateMotorPins(motor1);
saveMotorPositions();
} else if (strcmp(command, "2/90") == 0) {
motor2.runToNewPosition(512);
deactivateMotorPins(motor2);
saveMotorPositions();
} else if (strcmp(command, "0") == 0) {
motor1.runToNewPosition(0);
motor2.runToNewPosition(0);
deactivateMotorPins(motor1);
deactivateMotorPins(motor2);
saveMotorPositions();
} else if (strcmp(command, "1/45") == 0) {
motor1.runToNewPosition(256);
deactivateMotorPins(motor1);
saveMotorPositions();
} else if (strcmp(command, "2/45") == 0) {
motor2.runToNewPosition(256);
deactivateMotorPins(motor2);
saveMotorPositions();
} else if (strcmp(command, "01") == 0) {
motor1.runToNewPosition(0);
deactivateMotorPins(motor1);
saveMotorPositions();
} else if (strcmp(command, "02") == 0) {
motor2.runToNewPosition(0);
deactivateMotorPins(motor2);
saveMotorPositions();
} else if (strcmp(command, "12/90") == 0) {
motor1.runToNewPosition(512);
motor2.runToNewPosition(512);
deactivateMotorPins(motor1);
deactivateMotorPins(motor2);
} else if (strcmp(command, "12/45") == 0) {
motor1.runToNewPosition(262);
deactivateMotorPins(motor1);
motor2.runToNewPosition(262);
deactivateMotorPins(motor1);
deactivateMotorPins(motor2);
} else {
// Tratează cazurile de comenzi necunoscute
debugPrint("Comanda Bluetooth necunoscuta");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Comanda: ");
lcd.setCursor(0, 1);
lcd.print("NECUNOSCUTA");
}
}
void debugPrint(String message) {
if (debug) {
Serial.println(message);
}
}