Come probabilmente avrete avuto modo di verificare gestendo i due servomotori a rotazione continua, pur provenendo dal medesimo costruttore e impostando le medesime configurazione di velocità, hanno un comportamento non sempre identico. Ricordo che si tratta di apparati economici che devono rispondere a specifiche esigenze didattiche, ma in ogni caso è possibile effettuare alcune regolazioni che ne possono migliorare le prestazioni.
Un’altra funzionalità utile è quella dello start/stop del robot che potrebbe servire per evitare immediati movimenti non appena trasferiamo il codice sul robot.
In questa lezione vi dettaglio gli sketch di esempio, lasciando a voi modifiche e miglioramenti.
Regolazione dei motori
Per poter valutare la velocità e l’angolo di rotazione da impostare all’interno dello sketch è possibile attivare la funzione di calibrazione collegando a GND il pin 3, in questo modo sarà possibile dalla Serial Monitor verificare quali sono i giusti valori per:
- velocità di rotazione;
- durata della rotazione;
- motore/i da impostare
e quindi ciò consentirà di impostare i parametri corretti per le funzioni:
- orarioRobot()
- antiorarioRobot()
Pertanto da serial monitor potremo comprendere come far compiere una rotazione di 90° in un senso, oppure come far avanzare di una certa quantità di centimetri il robot e molto altro, tenendo però bene a mente che tutto ciò dipenderà fortemente dalla carica della batteria.
La scelta del pin3 è puramente casuale se ritenete potete scegliere un altro pin digitale.
Esempio 1
/*
Prof. Maffucci Michele
SumoRobot
Data: 26.01.2021
Sketch 03: rotazione oraria e antioraria continua
con funzioni parametrizzate
Per valutare la velocità e l'angolo di rotazione è possibile
attivare la funzione di calibrazione collegando a GND il pin 3,
in questo modo sarà possibile dalla Serial Monitor verificare
quali sono i giusti valori per:
- velocità di rotazione;
- durata della rotazione;
- motore/i da impostare
Ciò consentirà di impostare i parametri corretti per le funzioni:
- orarioRobot()
- antiorarioRobot()
Note:
L'orientamento dei motori è fatto
guardano il robot anteriormente
180: max velocità in senso antiorario
90 : servomotori fermi
0 : max velocità in senso orario
*/
// inclusione della libreria servo.h per il controllo dei servomotori
#include <Servo.h>
// Creazione oggetti servo
Servo motoreDX; // Inizializzazione del servomotore destro
Servo motoreSX; // Inizializzazione del servomotore sinistro
byte pinDx = 4; // Inizializza del pin 4 a cui è connesso il pin segnale del servo destro
byte pinSx = 5; // Inizializza del pin 5 a cui è connesso il pin segnale del servo sinistro
// Per Calibrazione
// per stampare una sola volta il messaggio sulla Serial Monitor
bool abilitaMessaggio = 0;
// per attivare la calibrazione impostare startCalibrazione a 0
bool startCalibrazione = 1;
// Pin di calibrazione se a LOW abilita modalità calibrazione
byte pinCal = 3;
void setup() {
// inizializzazione della seriale
Serial.begin(9600);
// attach() consente di definire a quale pin viene connesso il servomotore
// e lo collega all'oggetto che gestisce il servomotore
motoreDX.attach(pinDx); // pinDx collegato al motore destro
motoreSX.attach(pinSx); // pinSx collegato al motore sinistro
pinMode(pinCal, INPUT);
}
void loop() {
// se sul pinCal è LOW è possibile impostare i motori
if (digitalRead(pinCal) == LOW) {
calibrazione();
}
else
{
orarioRobot(30, 250); // Rotazione in senso orario del robot
stopRobot(3000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
antiorarioRobot(150, 250); // Rotazione in senso antiorario del robot
stopRobot(3000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
}
}
// Funzione da utilizzare una sola volta per impostare
// i tempi necessari per effettuare uno specifico angolo
// di rotazione e la velocità di rotazione desiderata
void calibrazione() {
// consente di visualizzare sulla Serial Monitor
// una sola stampa delle stringa
if (abilitaMessaggio == 0) {
// ritardo che evita la doppia stampa del messaggio
delay(200);
Serial.println("Calibrazione tempo rotazione");
Serial.println("velocità (0-180), durata(ms), motore(1: DX, 2: SX, 3: SX+DX)");
Serial.println();
abilitaMessaggio = 1;
}
// Controlla se è disponibile almeno un carattere sulla seriale
// La Serial.available() restituisce
// 1 se presente un cattere,
// 0 se non è presente un carattere
if (Serial.available()) { // Viene controllato se è disponibile un carattere
// per maggior informazioni sull'uso di parseInt() consultare il link:
// https://wp.me/p4kwmk-4Ah
// inserimento da tastiera su Serial Monitor dei parametri di controllo
// separati da spazio o virgola
int velocita = Serial.parseInt();
int durata = Serial.parseInt();
int motore = Serial.parseInt();
// funzione per il movimento dei servomotori con i parametri
// inseriti sulla serial monitor.
calMotoreRobot(velocita, durata, motore);
}
}
// funzione movimento servomotori per impostazione
// velocità, durata, motore/i
void calMotoreRobot(int calVel, int calDurata, int nMotore) {
if (nMotore == 1) { // motore DX
motoreDX.write(calVel);
delay(calDurata);
motoreDX.write(90); // Ferma il motore DX
motoreSX.write(90); // Ferma il motore SX
Serial.println("Fine calibrazione motore DX");
Serial.println();
}
if (nMotore == 2) { // motore SX
motoreSX.write(calVel);
delay(calDurata);
motoreDX.write(90); // Ferma il motore DX
motoreSX.write(90); // Ferma il motore SX
Serial.println("Fine calibrazione motore SX");
Serial.println();
}
if (nMotore == 3) { // motore SX+DX
motoreDX.write(calVel); // Rotazione oraria del motore DX
motoreSX.write(calVel); // Rotazione antioraria del motore SX
delay(calDurata);
motoreDX.write(90); // Ferma il motore DX
motoreSX.write(90); // Ferma il motore SX
Serial.println("Fine calibrazione motore DX e SX");
Serial.println();
}
}
// rotazione del robot in senso antiorario
// velMaxOraria: velocità massima in senso antiorario
// durata: durata della rotazione
void antiorarioRobot(int velMaxAntioraria, int durata) {
motoreDX.write(velMaxAntioraria); // Rotazione oraria del motore DX
motoreSX.write(velMaxAntioraria); // Rotazione antioraria del motore SX
delay(durata); // durata: durata della rotazione
}
// rotazione del robot in senso orario
// velMaxOraria: velocità massima in senso orario
// durata: durata della rotazione
void orarioRobot(int velMaxOraria, int durata) {
motoreDX.write(velMaxOraria); // Rotazione antioraria del motore DX
motoreSX.write(velMaxOraria); // Rotazione oraria del motore SX
delay(durata); // durata: durata della rotazione
}
// stop del robot
// ferma: durata dello stop del robot
void stopRobot(int ferma) {
motoreDX.write(90); // Ferma il motore DX
motoreSX.write(90); // Ferma il motore SX
delay(ferma); // Durata dello stop
}
La calibrazione viene attivata se la condizione ad inizio loop è vera:
...
// se sul pinCal è LOW è possibile impostare i motori
if (digitalRead(pinCal) == LOW) {
calibrazione();
}
else
{
orarioRobot(30, 250); // Rotazione in senso orario del robot
stopRobot(3000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
antiorarioRobot(150, 250); // Rotazione in senso antiorario del robot
stopRobot(3000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
}
}
...
Se la condizione dell’if risulta vera viene attivata la calibrazione:
...
// se sul pinCal è LOW è possibile impostare i motori
if (digitalRead(pinCal) == LOW) {
calibrazione();
}
else
{
orarioRobot(30, 250); // Rotazione in senso orario del robot
stopRobot(3000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
antiorarioRobot(150, 250); // Rotazione in senso antiorario del robot
stopRobot(3000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
}
}
...
In tal caso viene chiamata la funzione calibrazione:
...
void calibrazione() {
// consente di visualizzare sulla Serial Monitor
// una sola stampa delle stringa
if (abilitaMessaggio == 0) {
// ritardo che evita la doppia stampa del messaggio
delay(200);
Serial.println("Calibrazione tempo rotazione");
Serial.println("velocità (0-180), durata(ms), motore(1: DX, 2: SX, 3: SX+DX)");
Serial.println();
abilitaMessaggio = 1;
}
// Controlla se è disponibile almeno un carattere sulla seriale
// La Serial.available() restituisce
// 1 se presente un cattere,
// 0 se non è presente un carattere
if (Serial.available()) { // Viene controllato se è disponibile un carattere
// per maggior informazioni sull'uso di parseInt() consultare il link:
// https://wp.me/p4kwmk-4Ah
// inserimento da tastiera su Serial Monitor dei parametri di controllo
// separati da spazio o virgola
int velocita = Serial.parseInt();
int durata = Serial.parseInt();
int motore = Serial.parseInt();
// funzione per il movimento dei servomotori con i parametri
// inseriti sulla serial monitor.
calMotoreRobot(velocita, durata, motore);
}
}
...
La prima parte della funzione calibrazione() esegue una sola volta la stampa sulla Serial Monitor dell’help che spiega come inserire i dati:
velocità (0-180), durata(ms), motore(1: DX, 2: SX, 3: SX+DX)
che sono tutti valori interi separati da virgola.
Nella parte restante del codice della funzione viene verificato con il metodo available() se sono presenti sulla seriale caratteri. Serial.available() restituisce TRUE se sono presenti caratteri e il corpo dell’if verrà eseguito. I valori inseriti vengono letti utilizzando la funzione parseInt() di cui trovate spiegazione approfondita con esercizi seguendo il link.
...
if (Serial.available()) { // Viene controllato se è disponibile un carattere
// per maggior informazioni sull'uso di parseInt() consultare il link:
// https://wp.me/p4kwmk-4Ah
// inserimento da tastiera su Serial Monitor dei parametri di controllo
// separati da spazio o virgola
int velocita = Serial.parseInt();
int durata = Serial.parseInt();
int motore = Serial.parseInt();
// funzione per il movimento dei servomotori con i parametri
// inseriti sulla serial monitor.
calMotoreRobot(velocita, durata, motore);
}
...
Non appena premiamo invio sulla tastiera, questi valori vegono acquisiti e passati alla funzione calMotoreRobot()
...
calMotoreRobot(velocita, durata, motore);
...
Tra i parametri che vengono passati alla funzione calMotoreRobot() è presente l’indicazione di quale/i motore/i devono essere controllati, questo parametro può assumere i valori: 1, 2, 3 e questi valori vengono utilizzati per selezionare, tramite i blocchi if corrispondenti, quale azione è da compiere. Nei commenti i dettagli di funzionamento.
...
void calMotoreRobot(int calVel, int calDurata, int nMotore) {
if (nMotore == 1) { // motore DX
motoreDX.write(calVel);
delay(calDurata);
motoreDX.write(90); // Ferma il motore DX
motoreSX.write(90); // Ferma il motore SX
Serial.println("Fine calibrazione motore DX");
Serial.println();
}
if (nMotore == 2) { // motore SX
motoreSX.write(calVel);
delay(calDurata);
motoreDX.write(90); // Ferma il motore DX
motoreSX.write(90); // Ferma il motore SX
Serial.println("Fine calibrazione motore SX");
Serial.println();
}
if (nMotore == 3) { // motore SX+DX
motoreDX.write(calVel); // Rotazione oraria del motore DX
motoreSX.write(calVel); // Rotazione antioraria del motore SX
delay(calDurata);
motoreDX.write(90); // Ferma il motore DX
motoreSX.write(90); // Ferma il motore SX
Serial.println("Fine calibrazione motore DX e SX");
Serial.println();
}
}
...
La parte restante dello sketch riguarda funzioni già analizzate spiegate nelle lezioni precedenti.
Start/stop del robot
Questa semplice funzionalità viene ottenuta nel medesimo modo della calibrazione, utilizziamo il pin2 cortocircuitato a massa per evitare l’avvio del robot, secondo questa regola:
- Pin 2 a GND: robot fermo
- Pin 2 a Vcc: robot start
Questo lo sketch generale:
/*
Prof. Maffucci Michele
SumoRobot
Data: 26.01.2021
Sketch 04: rotazione oraria e antioraria continua
con funzioni parametrizzate con Start e Stop sistema.
Per evitare in avvio immediato del robot si realizza un
un interruttore di start/stop utilizzando il pin 2:
- Pin 2 a GND: robot fermo
- Pin 2 a Vcc: robot start
Note:
L'orientamento dei motori è fatto
guardano il robot anteriormente
180: max velocità in senso antiorario
90 : servomotori fermi
0 : max velocità in senso orario
Per avviare il robot collegare a GND il pin 2
*/
// inclusione della libreria servo.h per il controllo dei servomotori
#include <Servo.h>
// Creazione oggetti servo
Servo motoreDX; // Inizializzazione del servomotore destro
Servo motoreSX; // Inizializzazione del servomotore sinistro
byte pinDx = 4; // Inizializza del pin 4 a cui è connesso il pin segnale del servo destro
byte pinSx = 5; // Inizializza del pin 5 a cui è connesso il pin segnale del servo sinistro
byte pinStart = 2; // Pin di avvio, se a LOW Start sistema
void setup() {
// inizializzazione della seriale
Serial.begin(9600);
// attach() consente di definire a quale pin viene connesso il servomotore
// e lo collega all'oggetto che gestisce il servomotore
motoreDX.attach(pinDx); // pinDx collegato al motore destro
motoreSX.attach(pinSx); // pinSx collegato al motore sinistro
pinMode(pinStart, INPUT); // pin per avviare il sistema
}
void loop() {
// se pinStart a LOW il sistema è in stop
if (digitalRead(pinStart) == LOW) {
stopRobot(1);
}
// se pinStart è diverso da LOW si avvia la sequenza
else
{
orarioRobot(70, 500); // Rotazione in senso orario del robot
stopRobot(1000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
antiorarioRobot(130, 500); // Rotazione in senso antiorario del robot
stopRobot(1000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
}
}
// rotazione del robot in senso antiorario
// velMaxOraria: velocità massima in senso antiorario
// durata: durata della rotazione
void antiorarioRobot(int velMaxAntioraria, int durata) {
motoreDX.write(velMaxAntioraria); // Rotazione antioraria del motore DX
motoreSX.write(velMaxAntioraria); // Rotazione antioraria del motore SX
delay(durata); // durata: durata della rotazione
}
// rotazione del robot in senso orario
// velMaxOraria: velocità massima in senso orario
// durata: durata della rotazione
void orarioRobot(int velMaxOraria, int durata) {
motoreDX.write(velMaxOraria); // Rotazione oraria del motore DX
motoreSX.write(velMaxOraria); // Rotazione oraria del motore SX
delay(durata); // durata: durata della rotazione
}
// stop del robot
// ferma: durata dello stop del robot
void stopRobot(int ferma) {
motoreDX.write(90); // Ferma il motore DX
motoreSX.write(90); // Ferma il motore SX
delay(ferma); // Durata dello stop
}
Come si può notare lo start/stop è regolato dalla parte di codice:
...
// se pinStart a LOW il sistema è in stop
if (digitalRead(pinStart) == LOW) {
stopRobot(1);
}
// se pinStart è diverso da LOW si avvia la sequenza
else
{
orarioRobot(70, 500); // Rotazione in senso orario del robot
stopRobot(1000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
antiorarioRobot(130, 500); // Rotazione in senso antiorario del robot
stopRobot(1000); // Stop rotazione per un tempo fissato (vedere variabile ferma)
}
}
...
Se il pin è collegato a GND, quindi al LOW il robot è in stop, infatti viene chiamata la funzione stopRobot(1);
Nella prossima lezione vedremo come integrare le due funzionalità:
Buon Making a tutti 🙂