Pilotare due motori passo passo a distanza con Arduino
Sfruttiamo in maniera più proficua questa comunicazione radio tra Arduino. In questo articolo ti mostro come ho realizzato un sistema per pilotare due motori passo passo a distanza con Arduino, sfruttando il modulo radio nRF24L01.
Iniziamo
Tutto nasce dall’esigenza di un lettore che vorrebbe realizzare una torretta da softair comandata a distanza. La torretta quindi prevede l’utilizzo di due motori passo passo per gestirne i movimenti mentre un servo sarà utilizzato per azionare il grilletto (o qualsiasi cosa la faccia sparare) della replica senza doverla manomettere. Per replica in questo caso si intende la riproduzione di un sistema d’arma.
Nel codice che troverai più in basso ho impostato la potenza delle radio ad un valore LOW, naturalmente andrà modificato secondo le tue necessità. Più potenza, più consumo energetico però…
Per comandare i due motori ho utilizzato i soliti driver A4988, e come sempre ti ricordo che vanno calibrati. Per calibrati si intende, la regolazione della corrente in uscita verso i motori. Questa va tarata secondo le specifiche del motore utilizzato. In diverse occasioni sono stato fortunato ed i miei andavano più che bene con la corrente impostata, ma in altre ho scoperto che se si vogliono far durare i componenti e non danneggiare nulla, occorre per forza eseguire questa buona pratica.
Per chi non sa o non si ricorda come calibrare un driver A4988, consiglio una rapida ricerca su google, o di consultare il sito della Polou (https://www.pololu.com/product/1182) dove ci sarà una bella signorina che ve lo spiega a video (video incorporato anche in qualche mio articolo precedente).
Codice
Passiamo adesso al codice che come sempre è ampiamente commentato. In questa occasione noterai l’utilizzo di una nuova cosa (per me). Si tratta del tipo (type) struct ovvero struttura. Una struct altro non è che un gruppo di dati accorpati insieme sotto un unico oggetto. Questi dati possono essere di qualsiasi tipo e lunghezza. Nel mio caso ho creato una struttura dati chiamata Packet contenente tutte le informazioni che dovranno essere inviate via radio al ricevitore per poter pilotare i motori a distanza con Arduino.
Dall’altro lato ho creato la stessa struttura dati così da poter ricostruire lo stesso tipo di pacchetto durante la fase di lettura del buffer radio.
Ricordati di includere le librerie necessarie. Se non le hai già nel tuo IDE, ho già spiegato in altre occasioni come includerle e nell’articolo precedente Arduino nRF24L01 comunicazione base parlo appunto della RF24.
Trasmettitore
/*
Pilotare due motori passo passo a distanza con Arduino
Autore : Andrea Lombardo
Web : http://www.lombardoandrea.com
Post : https://wp.me/p27dYH-Oz
*/
//Inclusione delle librerie
#include <bounce2.h>
#include <nrf24l01.h>
#include <rf24_config.h>
#include <rf24.h>
//Costanti e PIN
//Pin pulsante incorporato nel modulo joystick che abilita o disabilita il controllo dei motori
const unsigned int pinSwEnable = 2;
//Pin pulsante esterno che controllerà il servo
const unsigned int pinSwTrigger = 3;
//Pin per il LED di stato
const unsigned int ledEnable = 7;
//Chip Select e Chip Enable della Radio
const unsigned int radioCE = 9;
const unsigned int radioCS = 10;
//Pin analogici per il joystick
const unsigned int jX = A0;
const unsigned int jY = A1;
//Definizione indirizzo sul quale stabilire la comunicazione radio
const byte indirizzo[5] = {0, 0, 0, 0, 0};
/*
Variabili utilizzate per definire min e max speed ed eseguire il mapping sui valori del joystick.
Stando alla documentazione della libreria il valore max può essere impostato fino a 4000 per un Arduino UNO.
*/
const unsigned int maxSpeed = 1000;
const unsigned int minSpeed = 0;
/*
La lettura dei potenziometri non è mai affidabile al 100%.
Questo valore aiuta a determinare il punto da considerare come "Stai fermo" nei movimenti.
*/
const unsigned int treshold = 30;
//Millisecondi per il debonuce del bottone
const unsigned long debounceDelay = 10;
//Definisco struttura pacchetto da inviare
struct Packet {
boolean muoviX;
long speedX;
boolean muoviY;
long speedY;
boolean enable;
boolean trigger;
};
//Variabili di appoggio
long valX, mapX, valY, mapY, tresholdUp, tresholdDown;
//Creo istanze dei bottoni
Bounce btnEnable = Bounce(); //istanzia un bottone dalla libreria Bounce
Bounce btnTrigger = Bounce(); //istanzia un bottone dalla libreria Bounce
//Creo istanza della "radio" passandogli il numero dei pin collegati a CE e CSN del modulo
RF24 radio(radioCE, radioCS);
//Creo ed inizializzo istanza pacchetto da inviare
Packet pkt = {
//boolean muoviX;
false,
//long speedX;
0,
//boolean muoviY;
false,
//long speedY;
0,
//boolean enable;
false,
//boolean trigger;
false
};
void setup() {
//Definizione delle modalità dei pin
//LED Enable
pinMode(ledEnable, OUTPUT);
//Tasto enable
pinMode(pinSwEnable, INPUT_PULLUP);
//Tasto grilletto
pinMode(pinSwTrigger, INPUT_PULLUP);
//Inizializzo la radio
radio.begin();
/*
Setto la potenza della radio, nel mio caso a LOW
La radio può lavorare a diverse potenze: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH e RF24_PA_MAX
Che corrispondono a: -18dBm, -12dBm,-6dBM, e 0dBm
*/
radio.setPALevel(RF24_PA_LOW);
//Apro un canale di comunicazione sull'indirizzo specificato (sarà lo stesso per il ricevitore)
radio.openWritingPipe(indirizzo);
//Richiamando questo metodo sto impostando la radio come trasmettitore
radio.stopListening();
//Configuro istanze dei pulsanti
btnEnable.attach(pinSwEnable);
btnEnable.interval(debounceDelay);
btnTrigger.attach(pinSwTrigger);
btnTrigger.interval(debounceDelay);
//Calcolo range valori entro i quali considerare la posizione del joystick come "Stai fermo"
tresholdDown = (maxSpeed / 2) - treshold;
tresholdUp = (maxSpeed / 2) + treshold;
//Invio stato di enable al LED
digitalWrite(ledEnable, pkt.enable);
}
void loop() {
//gestisci stato dei pulsanti
handlePulsanti();
//gestisci valori dei potenziometri
handleJoystick();
//Invia dati tramite la radio
radio.write(&pkt, sizeof(pkt));
}
/*
Si occupa di leggere i valori del joystick, mapparli ed aggiornare le variabili nel Packet
*/
void handleJoystick() {
//esegui lettura analogica dei valori provenienti dai potenziometri del joystick
valX = analogRead(jX);
valY = analogRead(jY);
//mappa i valori letti in funzione della velocità inima e massima
mapX = map(valX, 0, 1023, minSpeed, maxSpeed);
mapY = map(valY, 0, 1023, minSpeed, maxSpeed);
if (mapX <= tresholdDown) {
//x va indietro
pkt.speedX = -map(mapX, tresholdDown, minSpeed, minSpeed, maxSpeed);
pkt.muoviX = true;
} else if (mapX >= tresholdUp) {
//x va avanti
pkt.speedX = map(mapX, maxSpeed, tresholdUp, maxSpeed, minSpeed);
pkt.muoviX = true;
} else {
//x sta fermo
pkt.speedX = 0;
pkt.muoviX = false;
}
if (mapY <= tresholdDown) {
//y va giù
pkt.speedY = -map(mapY, tresholdDown, minSpeed, minSpeed, maxSpeed);
pkt.muoviY = true;
} else if (mapY >= tresholdUp) {
//y va su
pkt.speedY = map(mapY, maxSpeed, tresholdUp, maxSpeed, minSpeed);
pkt.muoviY = true;
} else {
//y sta fermo
pkt.speedY = 0;
pkt.muoviY = false;
}
}
/*
Si occupa di leggere lo stato dei pulsanti ed aggiornare le variabili nel Packet
*/
void handlePulsanti() {
btnEnable.update();
if (btnEnable.fell()) {
pkt.enable = !pkt.enable;
}
//Mostra lo stato di enable con il LED
digitalWrite(ledEnable, pkt.enable);
//Aggiorna stato di pressione del "grilletto"
btnTrigger.update();
pkt.trigger = !btnTrigger.read();
}
Ricevitore
/*
Pilotare due motori passo passo a distanza con Arduino
Autore : Andrea Lombardo
Web : http://www.lombardoandrea.com
Post : https://wp.me/p27dYH-Oz
*/
//Inclusione delle librerie
#include <accelstepper.h>
#include <servo.h>
#include <nrf24l01.h>
#include <rf24_config.h>
#include <rf24.h>
//Costanti e PIN
//Chip Select e Chip Enable della Radio
const unsigned int radioCS = 2;
const unsigned int radioCE = 3;
//Pin direzione e step per il motore X
const unsigned int dirX = 6;
const unsigned int stepX = 7;
//Pin direzione e step per il motore Y
const unsigned int dirY = 8;
const unsigned int stepY = 9;
//Pin che comanda lo stato di enable dei driver
const unsigned int pinEnable = 10;
//Pin PWM che comanderà il servo
const unsigned int pinServo = 11;
//definizione indirizzo sul quale stabilire la comunicazione radio
const byte indirizzo[5] = {0, 0, 0, 0, 0};
//definisco struttura pacchetto che riceverò
struct Packet {
boolean muoviX;
long speedX;
boolean muoviY;
long speedY;
boolean enable;
boolean trigger;
};
/*
Variabili utilizzate dalla libreria AccelStepper
stando alla documentazione della libreria valore max può essere impostato fino a 4000 per un Arduino UNO
*/
const unsigned int maxSpeed = 1000;
const unsigned int minSpeed = 0;
const float accelerazione = 50.0; //numero di step al secondo in accelerazione
//Creo istanze dei motori
AccelStepper motoreX(AccelStepper::DRIVER, stepX, dirX);
AccelStepper motoreY(AccelStepper::DRIVER, stepY, dirY);
//Creo istanza della "radio" passandogli il numero dei pin collegati a CE e CSN del modulo
RF24 radio(radioCE, radioCS);
//Creo istanza del servo motor
Servo servo;
//Creo ed inizializzo istanza pacchetto che userò per i dati ricevuti
Packet pkt = {
//boolean muoviX;
false,
//long speedX;
0,
//boolean muoviY;
false,
//long speedY;
0,
//boolean enable;
false,
//boolean trigger;
false
};
void setup() {
//Definizione delle modalità dei pin
//Pin Enable dei Driver
pinMode(pinEnable, OUTPUT);
//Dico ll'istanza del servo su quale pin interfacciarsi
servo.attach(pinServo);
//Configura parametri dei motori
motoreX.setMaxSpeed(maxSpeed);
motoreX.setSpeed(minSpeed);
motoreX.setAcceleration(accelerazione);
motoreY.setMaxSpeed(maxSpeed);
motoreY.setSpeed(minSpeed);
motoreY.setAcceleration(accelerazione);
//Inizialmente lascio i driver disabilitati
digitalWrite(pinEnable, !pkt.enable);
//Inizializzo la radio
radio.begin();
/*
Setto la potenza della radio, nel mio caso a LOW
La radio può lavorare a diverse potenze: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH e RF24_PA_MAX
Che corrispondono a: -18dBm, -12dBm,-6dBM, e 0dBm
*/
radio.setPALevel(RF24_PA_LOW);
//Apro un canale in lettura sull'indirizzo specificato
radio.openReadingPipe(1, indirizzo);
//Metto la radio in ascolto
radio.startListening();
}
void loop() {
//Se ci sono dati in ricezione sulla radio
if (radio.available()) {
//Leggo i dati sul buffer e li scrivo nell'istanza Packet precedentemente creata
radio.read(&pkt, sizeof(pkt));
} else {
//Se non ricevo dati per un qualsiasi motivo, azzero tutto nell'istanza Packet.
pkt = {
false,
0,
false,
0,
false,
false
};
}
//Se nel pkt il valore del trigger è 1 ruoto di 90° il servo motor
if (pkt.trigger) {
servo.write(90);
} else {
//Altrimenti lo rimetto a 0
servo.write(0);
}
//Interpreta i valori ricevuti ed aziona i motori di conseguenza
pilotaMotori(pkt);
delay(15);
}
/*
Interpreta i valori contenuti nella struttura Packet
ed aziona i motori di conseguenza
*/
void pilotaMotori(Packet pkt) {
//abilita o disabilita i driver
digitalWrite(pinEnable, !pkt.enable);
if (pkt.muoviX) {
motoreX.setSpeed(pkt.speedX);
motoreX.run();
} else {
motoreX.stop();
}
if (pkt.muoviY) {
motoreY.setSpeed(pkt.speedY);
motoreY.run();
} else {
motoreY.stop();
}
}
Come potrai notare, l’unione dei due listati di codice si rifà a quello che è stato il precedente articolo Controllo di due motori passo passo con Arduino e un Joystick.
A titolo informativo, credo sia buona norma effettuare l’upload del codice prima di eseguire i collegamenti, in modo da essere sicuri che sull’Arduino non ci sia vecchio codice che potrebbe generare strani comportamenti del sistema non appena lo connettiamo al PC per la prima volta.
Schemi
Anche in questo caso ho utilizzato un Arduino Nano ed un Arduino Leonardo (mi sono rimasti solo loro 😅 ). Ricordo che le connessioni SPI possono variare in base al modello. Nell’articolo Arduino nRF24L01 comunicazione base ho riportato la tabella ufficiale del sito Arduino ed il pinout della radio nRF24L01 (che troverai comunque nel pacchetto scaricabile a fondo pagina).
Sia nel trasmettitore che nel ricevitore, a meno che nel vostro modulo nRF24L01 non siano incorporati i regolatori di tensione, l’alimentazione deve essere collegata ai 3.3V e non sui 5V.
Nel ricevitore utilizzo la stessa tensione di alimentazione dei motori per alimentare anche l’Arduino e sfrutto la sua uscita a 5V per alimentare i driver A4988. I condensatori elettrolitici sono da 100uF 16V.
Conclusioni sul pilotare i motori a distanza con Arduino
Il progetto funziona e l’ho testato su banco ma non so come si comporterà a distanza e con il peso della replica. Sicuramente prevederei un sistema di ingranaggi per alleggerire il carico sui motori ed in caso diminuirei la velocità per evitare movimenti troppo bruschi.
Certamente non cambierei la risoluzione dei motori abbassando il numero di step come visto in altri articoli. In full step i motori hanno più torsione quindi maggiore forza.
Ho fatto un video durante l’assemblaggio ed il test del progetto, spero di trovare un pò di tempo per montarlo e caricarlo sul mio canale YouTube.
Mi auguro che il buon Marco che mi ha richiesto questo lavoretto, riesca a portare a termine la sua missione. Naturalmente saranno ben graditi foto o video del progetto ultimato 😉
A fine pagina trovi il link per scaricare il pacchetto con codici e schemi di collegamento. Come sempre ti ricordo che acquistando prodotti Amazon passando attraverso i link del mio sito, io percepisco una piccola commissione (parliamo di centesimi) in buoni regalo. Questi buoni sommati alle eventuali donazioni PayPal, servono a mantenere attivo il sito web e ad acquistare nuovi componenti.
Auto Amazon Links: Nessun prodotto trovato.
Auto Amazon Links: Nessun prodotto trovato.
Arduino Nano [A000005] - Scheda di sviluppo compatta e potente, compatibile con Arduino IDE, ideale per progetti elettronici, robot, PLC e applicazioni fai da te.
ELEGOO 3 Pezzi Nano Scheda di Microcontrollore (Kit di 3) Compatibile con Arduino IDE
Nano Scheda di Sviluppo con Cavo Binghe 2 Pezzi Nano-V3 Scheda di Sviluppo con Chip CH340 Type-C Interfaccia 5V 16M 328P Microcontrollore Compatibile con Arduino IDE
13,99 €Nano 328P V3 Scheda di sviluppo microcontrollore AYWHP Scheda madre da 3 pezzi con microchip CH340G con cavo USB Microcontrollore 5V 16M Interfaccia micro USB compatibile con Arduino IDE
11,99 €Nano Modulo Scheda di Sviluppo Compatibile con Arduino, con Type C USB Port,Chip CH340G,5V/16MHz Microcontroller
7,69 €Auto Amazon Links: Nessun prodotto trovato.
Auto Amazon Links: Nessun prodotto trovato.
Auto Amazon Links: Nessun prodotto trovato.



![Arduino Nano [A000005] - Scheda di sviluppo compatta e potente, compatibile con Arduino IDE, ideale per progetti elettronici, robot, PLC e applicazioni fai da te. #1](https://m.media-amazon.com/images/I/51p0HZ18KtL._SL120_.jpg)
![Arduino Nano [A000005] - Scheda di sviluppo compatta e potente, compatibile con Arduino IDE, ideale per progetti elettronici, robot, PLC e applicazioni fai da te. #2](https://m.media-amazon.com/images/I/41g5pY8njrL._SL120_.jpg)
![Arduino Nano [A000005] - Scheda di sviluppo compatta e potente, compatibile con Arduino IDE, ideale per progetti elettronici, robot, PLC e applicazioni fai da te. #3](https://m.media-amazon.com/images/I/51IfbNowHgL._SL120_.jpg)
![Arduino Nano [A000005] - Scheda di sviluppo compatta e potente, compatibile con Arduino IDE, ideale per progetti elettronici, robot, PLC e applicazioni fai da te. #4](https://m.media-amazon.com/images/I/41ceSJfIfHL._SL120_.jpg)
![Arduino Nano [A000005] - Scheda di sviluppo compatta e potente, compatibile con Arduino IDE, ideale per progetti elettronici, robot, PLC e applicazioni fai da te. #5](https://m.media-amazon.com/images/I/41TANpxmbzL._SL120_.jpg)
![Arduino Nano [A000005] - Scheda di sviluppo compatta e potente, compatibile con Arduino IDE, ideale per progetti elettronici, robot, PLC e applicazioni fai da te. #6](https://m.media-amazon.com/images/I/41mGAFfpn9L._SL120_.jpg)


























RSS - Articoli
Commentati Recentemente