Buonasera a tutti.
Rieccomi a chiedere il vostro aiuto , pian pino procedo con il mio progetto di robot pulitore finito il trasmettitore sono passato al ricevitore e dopo aver progettato il pcb atteso i normali tempi di consegna dei vari componenti ,ho assemblato o meglio collegato il tutto al ricevitore .
Funziona in ogni comando che riceve dal trasmettitore per i vari comandi on / off ed altre funzioni che ho programmato , resta solo un problema i motori passo passo , premetto che non ho molta esperienza con questo tipo di motore ma ho ritenuto che fossero più adatti per un progetto simile visto la loro precisione nei movimenti .
Detto questo vi espongo il mio problema ,comando i motori con un driver TB6600 il motore è un Nema 17 quando muovo il joystick per eseguire un movimento il motore si avvia ma va a scatti non è un movimento fluido e sembra che ci sia anche un secondo problema che fino ad un quarto di leva del joystick la velocità sembra essere controllata mentre oltre quella posizione del joystick fino a fine corsa la velocità del motore sembra sempre la stessa , non so se è una causa dovuta dal fatto che il motore va a scatti e non è fluido il movimento .
Nello sketch ho usato la libreria AccelStepper e non riesco a capire se sia un problema di software o di hardware , sul TB6600 ci sono dei micro interruttori da sw1 a sw6 per regolare gli step e la corrente ho provato a fare alcune impostazioni ma non cambia nulla se non che il motore o vibra più forte o meno forte .
Secondo me invece non è una buona scelta progettuale.
I motori stepper sono l'ideale quando devi posizionare un cinematismo in una determinata posizione all'interno un sistema con buona precisione e ripetibilità, ma se stai parlando di un robot significa che li stai usando per fare "auto-trazione" ed in questo ambito sono una scelta sbagliata.
Come prima cosa, se ti aspetti di posizionare il tuo robot nello spazio solo ed esclusivamente tenendo conto del numero degli step che fai eseguire ai tuoi motori, non otterrai mai un risultato decente (slittamento delle ruote, robot che si incastra etc etc).
Inoltre, immagino che il tuo robot avrà delle batterie e gli stepper sono motori energivori che sono sempre in coppia (devi disabilitare in modo esplicito il driver quando non servono). A parità di corrente assorbita e/o peso, un classico motore DC offre molta molta più coppia.
Non è un caso se in questo genere di sistemi, come ad esempio i robottini per pulire casa, vengono sempre usati dei motori DC con encoder (per il controllo di velocità, non di posizione).
Nema 17 definisce solo la grandezza meccanica della flange del motore ma non le sue catatterisiche elettriche.
Il TB6600 é un driver di corrente che vuol dire che imprime al motore una corrente impostata o una frazione di questa per fare i microstepping. Con gli interuttori imposti la corrente del motore che dovrebbe corrispondere con la corrente nominale e il numero di microsteping.
Il motore deve essere adatto per essere pilotato in corrente ( tensione nominale bassa (intorno 3-4 volt) e corrente alta (qualche ampere). Il driver deve essere alimentato con una tensione alta (almeno 4 volte la tensione nominale). Piú alta meglio é ( 12 o 24V).
Che motore hai? con che tensione alimenti il driver del motore (alimentazione motore)?
Si puó monatre sul asse del motore CC anche una ruota con buchi e un fotoaccopiatore a forcella misurando la velociá e i giri del motore.
Ciao Uwe
Ciao Cotestatnt
Il mio robot non è altro che un cingolato con due motori per la trazione e due motori per far ruotare delle spazzole e servirà per pulire un impianto fotovoltaico , quindi se slitta o perde i passi poco mi interessa , non mi interessa che ci sia uno spostamento millimetrico , deve andare avanti svoltare a destra o sinistra ed a volte andare in retromarcia .
Per quanto riguarda la sua alimentazione non ci saranno batterie ma un cavo di alimentazione visto che oltre a quello ci sarò un tubo in gomma per portare l'acqua alle spazzole "ovviamente acqua in osmosi ".
Quindi anche il problema delle batterie non esiste , perchè la scelta di motori passo passo semplicemente ne ho in casa una certa quantità nuovi ritirati anni fa da un fallimento e mi sembrava utile usarli senza dover spendere soldi per altri motori .
Non discuto che non siano la scelta giusta ma sono li e mi sembrava uno spreco non usarli , ho previsto una funzione per disabilitare i driver controllata da un interruttore sul tx , ma il fatto che da fermi restino in coppia e quindi frenati nel mio caso è tutto di guadagnato.
Ciao Uwefed
Perdona la mia ignoranza in fatto di motori passo passo , i motori che ho sono Stepper Motor: Bipolar, 200 Steps/Rev, 57×76mm, 3.2V, 2.8 A/Phase.
Alimento i driver a 12 v .
Beh, con queste premesse allora il discorso cambia e quindi la scelta degli stepper ha un suo perché.
Per quanto riguarda il problema che stai riscontrando, può dipendere sia da un cablaggio errato, che dal software (ad esempio nel caso in cui lo stepping dei motori sia fatto in modo bloccante).
Prova a condividere lo sketch se ti va.
Il motore é adatto col Driver.
Che potenza ha l'alimentatore da 12V?
Ciao Uwe
Ciao Cotestatnt
Nessun problema a condividere lo sketch , domani rientro a casa e lo condivido , magari mi date una dritta per risolvere il problema .
Ciao Uwefed
Il mio alimentatore è un 12 V 10 A Switching.
Questi motori erano montati su un macchinario che serviva a spelare i fili e con loro i driver , il macchinario era in fase di assemblaggio quindi sia driver che motori erano e sono nuovi ,hanno chiuso l'attività per fallimento e sono riuscito ad acquistare ad un prezzo irrisorio diversi componenti di questi macchinari , compresi di driver e motori e se funzionavano a loro immagino sia adatto il motore al driver .
La prova è che avevo una macchina praticamente quasi finita e funzionava perfettamente con questo tipo di motore e di driver , credo che il problema sia nel mio software .
Comunque non sono nema17 ma nema23
Buonasera a tutti ecco il mio sketch.
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <AccelStepper.h>
// -------------- Indirizzi RF --------------
const byte COMMAND_ADDRESS[6] = "00001"; // dove ascoltare i comandi dal trasmettitore
const byte FEEDBACK_ADDRESS[6] = "00002"; // dove mandare i feedback (litri, emergenza locale)
RF24 radio(9, 10); // CE=9, CSN=10
// -------------- Strutture dati --------------
struct JoystickData {
int8_t x;
int8_t y;
bool emergency;
bool autoRover;
uint8_t roverSpeed;
bool pulizia;
uint8_t brushSpeed;
bool puliziaForte;
bool acqua;
bool ultraDisable;
bool driverEnable;
bool resetLiters; // <-- Gestisce il reset litri da remoto
};
struct FlowData {
float liters;
bool localEmergency; // stato emergenza locale
};
// Variabile per ricevere i dati
JoystickData receivedData;
// -------------- Motori --------------
#define LEFT_STEP_PIN 2
#define LEFT_DIR_PIN 3
#define RIGHT_STEP_PIN 4
#define RIGHT_DIR_PIN 5
#define SPZ_STEP_PIN 22
#define SPZ_DIR_PIN 23
#define SPZ2_STEP_PIN 30
#define SPZ2_DIR_PIN 31
// Con AccelStepper in modalità DRIVER, il costruttore è (interface, pinStep, pinDir)
AccelStepper leftMotor (AccelStepper::DRIVER, LEFT_STEP_PIN, LEFT_DIR_PIN);
AccelStepper rightMotor(AccelStepper::DRIVER, RIGHT_STEP_PIN, RIGHT_DIR_PIN);
AccelStepper spazzolaMotor (AccelStepper::DRIVER, SPZ_STEP_PIN, SPZ_DIR_PIN);
AccelStepper spazzolaMotor2(AccelStepper::DRIVER, SPZ2_STEP_PIN, SPZ2_DIR_PIN);
// -------------- Relè acqua --------------
#define ACQUA_RELAY_PIN 6
// -------------- LED emergenza --------------
#define EMERGENCY_LED_PIN 33
// -------------- Driver enable --------------
#define DRIVER_ENABLE_PIN 34
// -------------- Flussometro --------------
#define FLOW_SENSOR_PIN 18 // interrupt esterno su MEGA
volatile unsigned long pulseCount = 0;
const float PULSES_PER_LITER = 450.0;
float totalLiters = 0.0;
unsigned long lastFlowUpdate = 0;
void flowSensorISR() {
pulseCount++;
}
// -------------- Ultrasuoni --------------
#define ULTRA1_TRIGGER_PIN 26
#define ULTRA1_ECHO_PIN 27
#define ULTRA2_TRIGGER_PIN 28
#define ULTRA2_ECHO_PIN 29
long readUltrasonic(int trigPin, int echoPin) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH, 30000UL);
long distance = duration * 0.034 / 2; // cm
return distance;
}
// -------------- Costanti motori --------------
const int MAX_SPEED = 200; // step/s massimi per i motori principali
const int MAX_BRUSH_SPEED = 200; // step/s massimi per i motori spazzola
const int JOYSTICK_DEADBAND = 10;
// Impostiamo anche un'accelerazione (step/s^2) per movimenti fluidi
const int ACCELERATION = 300;
// -------------- Pulizia forte --------------
const unsigned long STRONG_FORWARD_TIME = 6000;
const unsigned long STRONG_STOP_TIME = 4000;
const unsigned long STRONG_REVERSE_TIME = 5000;
enum CleaningState { CLEAN_OFF, CLEAN_FORWARD, CLEAN_STOP, CLEAN_REVERSE };
CleaningState cleaningState = CLEAN_OFF;
unsigned long cleaningCycleStart = 0;
// -------------- Logica ultrasuoni invertita --------------
// dist > 10 => STOP(4s) + REVERSE(4s) + STOP(10s)
const unsigned long US_STOP1_TIME = 4000;
const unsigned long US_REVERSE_TIME = 4000;
const unsigned long US_STOP2_TIME = 10000;
enum UltraState { US_NORMAL, US_STOP1, US_REVERSE, US_STOP2, US_DONE };
UltraState ultraState = US_NORMAL;
unsigned long ultraStateStart = 0;
// -------------- 4 LED extra + LED motori --------------
#define LED_FORTE_PIN 35
#define LED_ACQUA_PIN 36
#define LED_ULTRA_DISABLE_PIN 37
#define LED_AUTO_ROVER_PIN 38
#define LED_MOTORS_PIN 39
#define LED_REVERSE_PIN 40
// -------------- Pulsante emergenza locale --------------
#define LOCAL_EMERGENCY_PIN 49
bool localEmergencyActive = false;
// Per lampeggio LED emergenza locale
static unsigned long lastBlinkTime = 0;
static bool emergencyLedState = false;
void setup() {
Serial.begin(9600);
// Pin LED emergenza
pinMode(EMERGENCY_LED_PIN, OUTPUT);
digitalWrite(EMERGENCY_LED_PIN, LOW);
pinMode(DRIVER_ENABLE_PIN, OUTPUT);
digitalWrite(DRIVER_ENABLE_PIN, LOW);
pinMode(ACQUA_RELAY_PIN, OUTPUT);
digitalWrite(ACQUA_RELAY_PIN, LOW);
// Flussometro
pinMode(FLOW_SENSOR_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_PIN), flowSensorISR, FALLING);
// Ultrasuoni
pinMode(ULTRA1_TRIGGER_PIN, OUTPUT);
pinMode(ULTRA1_ECHO_PIN, INPUT);
pinMode(ULTRA2_TRIGGER_PIN, OUTPUT);
pinMode(ULTRA2_ECHO_PIN, INPUT);
// Pulsante emergenza locale
pinMode(LOCAL_EMERGENCY_PIN, INPUT_PULLUP);
// nRF24
radio.begin();
radio.setPALevel(RF24_PA_LOW);
radio.openReadingPipe(1, COMMAND_ADDRESS);
radio.startListening();
// -------------------------
// Configurazione motori
// -------------------------
leftMotor.setMaxSpeed(MAX_SPEED);
leftMotor.setAcceleration(ACCELERATION);
rightMotor.setMaxSpeed(MAX_SPEED);
rightMotor.setAcceleration(ACCELERATION);
spazzolaMotor.setMaxSpeed(MAX_BRUSH_SPEED);
spazzolaMotor.setAcceleration(ACCELERATION);
spazzolaMotor2.setMaxSpeed(MAX_BRUSH_SPEED);
spazzolaMotor2.setAcceleration(ACCELERATION);
// Altri LED
pinMode(LED_FORTE_PIN, OUTPUT); digitalWrite(LED_FORTE_PIN, LOW);
pinMode(LED_ACQUA_PIN, OUTPUT); digitalWrite(LED_ACQUA_PIN, LOW);
pinMode(LED_ULTRA_DISABLE_PIN, OUTPUT); digitalWrite(LED_ULTRA_DISABLE_PIN, LOW);
pinMode(LED_AUTO_ROVER_PIN, OUTPUT); digitalWrite(LED_AUTO_ROVER_PIN, LOW);
pinMode(LED_MOTORS_PIN, OUTPUT); digitalWrite(LED_MOTORS_PIN, LOW);
pinMode(LED_REVERSE_PIN, OUTPUT); digitalWrite(LED_REVERSE_PIN, LOW);
Serial.println("Rx MEGA avviato, con gestione emergenze, ultrasuoni, pulizia forte e contatore litri (fluido).");
}
// Aggiorna contatore litri ogni ~1 s
void updateFlowMeasurement() {
if (millis() - lastFlowUpdate >= 1000) {
float litersThisInterval = pulseCount / PULSES_PER_LITER;
totalLiters += litersThisInterval;
pulseCount = 0;
lastFlowUpdate = millis();
Serial.print("Flow => +");
Serial.print(litersThisInterval, 4);
Serial.print(" L, Totale: ");
Serial.print(totalLiters, 4);
Serial.println(" L");
}
}
void updateStrongCleaning() {
unsigned long elapsed = millis() - cleaningCycleStart;
switch (cleaningState) {
case CLEAN_FORWARD:
// spazzola 1 avanti, spazzola 2 indietro
spazzolaMotor.setSpeed(MAX_BRUSH_SPEED);
spazzolaMotor2.setSpeed(-MAX_BRUSH_SPEED);
if (elapsed >= STRONG_FORWARD_TIME) {
cleaningState = CLEAN_STOP;
cleaningCycleStart = millis();
}
break;
case CLEAN_STOP:
// entrambe ferme
spazzolaMotor.setSpeed(0);
spazzolaMotor2.setSpeed(0);
if (elapsed >= STRONG_STOP_TIME) {
cleaningState = CLEAN_REVERSE;
cleaningCycleStart = millis();
}
break;
case CLEAN_REVERSE:
// spazzola 1 indietro, spazzola 2 avanti
spazzolaMotor.setSpeed(-MAX_BRUSH_SPEED);
spazzolaMotor2.setSpeed(MAX_BRUSH_SPEED);
if (elapsed >= STRONG_REVERSE_TIME) {
cleaningState = CLEAN_OFF; // finita la pulizia forte
}
break;
default:
break;
}
}
// Sequenza ultrasuoni invertita: dist > 10 => STOP(4s) + REVERSE(4s) + STOP(10s)
void updateUltrasonicOverride(int &leftSpeed, int &rightSpeed) {
// Se l'autoRover non è attivo o se gli ultrasuoni sono disabilitati, ignora la logica
if (!receivedData.autoRover || receivedData.ultraDisable) {
ultraState = US_NORMAL;
return;
}
long dist1 = readUltrasonic(ULTRA1_TRIGGER_PIN, ULTRA1_ECHO_PIN);
long dist2 = readUltrasonic(ULTRA2_TRIGGER_PIN, ULTRA2_ECHO_PIN);
long minDist = (dist1 < dist2) ? dist1 : dist2;
switch (ultraState) {
case US_NORMAL:
if (minDist > 10) {
ultraState = US_STOP1; // STOP di 4s
ultraStateStart = millis();
}
break;
case US_STOP1:
leftSpeed = 0;
rightSpeed = 0;
if (millis() - ultraStateStart >= US_STOP1_TIME) {
ultraState = US_REVERSE;
ultraStateStart = millis();
}
break;
case US_REVERSE:
leftSpeed = -50;
rightSpeed = -50;
if (millis() - ultraStateStart >= US_REVERSE_TIME) {
ultraState = US_STOP2;
ultraStateStart = millis();
}
break;
case US_STOP2:
leftSpeed = 0;
rightSpeed = 0;
if (millis() - ultraStateStart >= US_STOP2_TIME) {
ultraState = US_DONE;
}
break;
case US_DONE:
// Restiamo qui finché dist <= 10
if (minDist <= 10) {
ultraState = US_NORMAL;
}
break;
}
}
void loop() {
// 1) Aggiorna misurazione del flusso
updateFlowMeasurement();
// 2) Leggi eventuale comando radio
if (radio.available()) {
radio.read(&receivedData, sizeof(receivedData));
// Debug seriale
Serial.print("RX => EmergenzaR=");
Serial.print(receivedData.emergency);
Serial.print(" autoR=");
Serial.print(receivedData.autoRover);
Serial.print(" X=");
Serial.print(receivedData.x);
Serial.print(" Y=");
Serial.print(receivedData.y);
Serial.print(" resetLiters=");
Serial.println(receivedData.resetLiters);
// Se trasmettitore chiede reset litri, azzeriamo contatore
if (receivedData.resetLiters) {
totalLiters = 0.0;
pulseCount = 0;
Serial.println("***** Contatore litri AZZERATO dal comando remoto! *****");
}
}
// 3) Controllo pulsante emergenza locale (LOW = premuto)
if (digitalRead(LOCAL_EMERGENCY_PIN) == LOW) {
localEmergencyActive = true;
} else {
localEmergencyActive = false;
}
// 4) Gestione LED emergenza (lampeggio o fisso)
if (receivedData.emergency) {
// PRIORITA' emergenza remota => LED fisso
digitalWrite(EMERGENCY_LED_PIN, HIGH);
} else if (localEmergencyActive) {
// Lampeggio
if (millis() - lastBlinkTime >= 300) {
lastBlinkTime = millis();
emergencyLedState = !emergencyLedState;
digitalWrite(EMERGENCY_LED_PIN, emergencyLedState ? HIGH : LOW);
}
} else {
// Nessuna emergenza => LED spento
digitalWrite(EMERGENCY_LED_PIN, LOW);
}
// 5) Driver enable (attivo basso)
digitalWrite(DRIVER_ENABLE_PIN, (receivedData.driverEnable ? LOW : HIGH));
// 6) LED forte, acqua, ultrasuoni, auto
digitalWrite(LED_FORTE_PIN, (receivedData.puliziaForte ? HIGH : LOW));
digitalWrite(LED_ACQUA_PIN, (receivedData.acqua ? HIGH : LOW));
digitalWrite(LED_ULTRA_DISABLE_PIN, (receivedData.ultraDisable ? HIGH : LOW));
digitalWrite(LED_AUTO_ROVER_PIN, (receivedData.autoRover ? HIGH : LOW));
// 7) Se emergenza (remota o locale), stop motori
if (receivedData.emergency || localEmergencyActive) {
// Fermo tutte le velocità
leftMotor.setSpeed(0);
rightMotor.setSpeed(0);
spazzolaMotor.setSpeed(0);
spazzolaMotor2.setSpeed(0);
cleaningState = CLEAN_OFF;
ultraState = US_NORMAL;
// Spegni LED motori + retromarcia
digitalWrite(LED_MOTORS_PIN, LOW);
digitalWrite(LED_REVERSE_PIN, LOW);
} else {
// Nessuna emergenza => esegui comandi
int leftSpeed, rightSpeed;
// Calcolo velocità base in base a autoRover oppure joystick
if (receivedData.autoRover) {
// Mappiamo roverSpeed (0..127) a (0..MAX_SPEED)
int roverSpd = map(receivedData.roverSpeed, 0, 127, 0, MAX_SPEED);
leftSpeed = roverSpd;
rightSpeed = roverSpd;
} else {
// Logica differenziale con joystick
int leftCalc = receivedData.y + receivedData.x;
int rightCalc = receivedData.y - receivedData.x;
if (abs(receivedData.x) < JOYSTICK_DEADBAND) {
// Se X è piccolo, consideriamo entrambi = Y
leftCalc = receivedData.y;
rightCalc = receivedData.y;
}
leftSpeed = constrain(leftCalc, -MAX_SPEED, MAX_SPEED);
rightSpeed = constrain(rightCalc, -MAX_SPEED, MAX_SPEED);
}
// Override ultrasuoni
updateUltrasonicOverride(leftSpeed, rightSpeed);
// --- Pulizia forte: ferma i motori principali ed esegue sequenza sulle spazzole ---
if (receivedData.puliziaForte) {
leftSpeed = 0;
rightSpeed = 0;
if (cleaningState == CLEAN_OFF) {
cleaningState = CLEAN_FORWARD;
cleaningCycleStart = millis();
}
updateStrongCleaning();
} else {
// Pulizia NORMALE (solo se NON è attiva la pulizia forte)
cleaningState = CLEAN_OFF;
if (receivedData.pulizia) {
int brushSpd = map(receivedData.brushSpeed, 0, 127, 0, MAX_BRUSH_SPEED);
// spazzola 1 avanti, spazzola 2 indietro
spazzolaMotor.setSpeed( brushSpd);
spazzolaMotor2.setSpeed(-brushSpd);
} else {
spazzolaMotor.setSpeed(0);
spazzolaMotor2.setSpeed(0);
}
}
// Acqua
digitalWrite(ACQUA_RELAY_PIN, (receivedData.acqua ? HIGH : LOW));
// LED MOTORI => ON se uno dei due motori != 0
if (leftSpeed != 0 || rightSpeed != 0) {
digitalWrite(LED_MOTORS_PIN, HIGH);
} else {
digitalWrite(LED_MOTORS_PIN, LOW);
}
// LED RETROMARCIA => ON se entrambi < 0
if (leftSpeed < 0 && rightSpeed < 0) {
digitalWrite(LED_REVERSE_PIN, HIGH);
} else {
digitalWrite(LED_REVERSE_PIN, LOW);
}
// Imposta la velocità "di destinazione" per i motori principali.
// Con run(), AccelStepper accelererà/decelererà automaticamente.
leftMotor.setSpeed(leftSpeed);
rightMotor.setSpeed(rightSpeed);
}
// 8) Esegui "run()" per generare gli step in modo fluido su tutti i motori
leftMotor.run();
rightMotor.run();
spazzolaMotor.run();
spazzolaMotor2.run();
// 9) Invia feedback litri + emergenza locale via nRF24
FlowData feedback;
feedback.liters = totalLiters;
feedback.localEmergency = localEmergencyActive;
radio.stopListening();
radio.openWritingPipe(FEEDBACK_ADDRESS);
bool ok = radio.write(&feedback, sizeof(feedback));
if (!ok) {
Serial.println("Invio FlowData fallito!");
}
radio.openReadingPipe(1, COMMAND_ADDRESS);
radio.startListening();
// ----------------------------------------------------------------
// NIENTE PIÙ delay(50): se vuoi un microscopico ritardo, fai delay(1)
// ----------------------------------------------------------------
delay(1);
}
Se qualcuno sa darmi qualche indicazione per eliminare la vibrazione del motore e che giri molto più piano rispetto a quello che avevo calcolato .
grazie ancora a tutti.
Ho fatto alcun prove e sono quasi sicuro che il problema sia legato al processore atmega2560 , il mio software è troppo pesante e non riesce a generare velocemente gli impulsi per pilotare il driver alleggerendo un pò il programma il motore gira molto meglio ma ovviamente perdo delle funzioni .
Credo che dovrò passare ad un ESP32 molto più potente e veloce nella gestione sia dei motori che dei vari segnali in arrivo dal tx o in uscita verso il tx
Potevi dirlo prima che il motore e il Driver l'hai recuperato da un apparecchio e percui sono funzionanti in questa combinazione.
readUltrasonic() si prende 12us. Le print si prendono poco tempo poiché scrivono sul buffer ring, però quando il registro della seriale è vuoto si solleva un IRQ che interrompe per un breve periodo la funzione loop() e ciò accade per ogni carattere inviato. Per il resto non ho idea se c'è qualche funzione di libreria che detiene il controllo per "troppo" tempo. La mega mi pare abbia tanti timer hardware che potrebbero essere configurati per generare il segnale di clock per i stepper driver, evitando così di dovere usare AccelStepper.
Nonostante ciò, l'idea di usare una MCU con frequenza di clock maggiore è sicuramente un vantaggio e chissà potresti anche continuare ad usare AccelStepper. Quindi secondo me l'idea di passare a ESP32 è ottima, anche per il fatto che ogni pin può generare segnale PWM a frequenza configurabile, senza consumare tempo CPU.
Dall'altro lato passando ad ESP32 devi verificare che ogni libreria che stai usando funzioni anche con ESP32.
PS: Perché quel delay(1) alla fine?
Ciao.
Ha senso inviare questi dati ad ogni giro di loop()?
Non sarebbe meglio temporizzarli e quindi lasciare più tempo libero al microcontrollore per generare correttamente gli step?
Ciao Maurotec
Il delay alla fine mi serve per creare una piccola pausa per poter far si che il ricevitore possa leggere correttamente i vari comandi ricevuti dal Tx , se non metto questa pausa il ricevitore non esegue più i comandi ricevuti dal Tx o li esegue molto in ritardo e quando dico molto in ritardo passano anche 2 minuti dal invio comando ad eseguire il comando .
Ciao Cotestatnt
In effetti non ci avevo pensato ad una temporizzazione per l'invio di questi dati , potrebbe essere una soluzione per alleggerire il lavoro al microcontrollore .
In serata provo a modificare il software e vi aggiorno del risultato .
Dovresti anche risolvere il problema che ti ha reso necessario inserire il delay(1).
Come dice @cotestatnt, devi risolvere quel problema in modo diverso, del resto con un delay(1) all'interno del ciclo questo non può che essere eseguito alla frequenza di 1/0.001=1000Hz, se ci fosse solo il delay, ma c'è altro codice che consuma tempo cpu.
Se hai un analizzatore logico puoi usarlo al fine di verificare quando tempo ci impiega un ciclo di loop ad essere eseguito, diversamente ti puoi fare una idea vaga impiegando la seguente funzione:
void calcAndPrintTcm() {
static uint32_t loopCounter;
static uint32_t oneSec = millis();
loopCounter++;
if (millis() - oneSec >= 1000) {
oneSec = millis();
float tcm = 1000.0/loopCounter;
Serial.print("Tcm: ");
Serial.print(tcm, 5);
Serial.println(" ms");
//Serial.print("loopCounter: "); // (1)
//Serial.println(loopCounter); // (2)
loopCounter = 0;
}
}
Chiami la funzione all'inizio del loop(). Questa stampa ogni secondo il tempo di ciclo medio. Nel tuo caso con il delay(1) stampera:
Tcm: 1.01420 ms
Tcm: 1.51515 ms
Tcm: 1.12360 ms
Tcm: 1.12233 ms
In sostanza il tempo non sarà mai inferiore a 1ms.
Per ricavare quanti cicli di loop vengono eseguiti in un secondo basta eseguire:
lc = 1000 / tcm
Dove lc è abbreviazione di loop counter.
Esempio: 1000 / 1.12233 = 891 cicli ogni secondo.
Ciao.
Allora ho modificato il software come da consiglio di Cotestatnt temporizzando i feedback ,ed i motori si muovono più fluidi anche nella regolazione della velocità è più regolare , ho un solo difetto che durante la rotazione sui 360 gradi ad un certo punto fa un piccolo stop come un salto di setp .
Con questa modifica sono riuscito ad eliminare anche il delay , dovrò modificare il software del TX perche riceve si i feedback ma in ritardo e non li tiene più in memoria i litri appaiono ma se il sensore non sente più il passaggio acqua il conteggio torna a zero e stessa cosa per emergenza locale se premuta non viene segnalato sul TX ma continua a cambiare stato da OK ad Emergenza , diciamo che sono cose che dovrei risolver senza problemi .
Anche se da quello che ho capito un ESP32 sarebbe più indicato a svolgere la funzione di RX .