Piccolo progetto sviluppato durante il periodo di lockdown di questo maledettissimo 2020.
Di cosa si tratta: avevo un vecchio pilota automatico a barra (autohelm 800) per la mia piccola barchetta a vela che ormai non funzionava più e le uniche parti recuperabili erano l'involucro, la pulsantiera e il motorino con attuatore lineare, mi sono detto " e se rimpiazzo tutta la logica con una scheda arduino compatibile?", da questa semplice domanda ho fatto la lista della spesa cercando di riciclare quello che avevo già in casa ( cioè una schedina nodemcu con wifi e il modulo di controllo L298N per motori in cc), quindi ricapitolando :
- scheda di sviluppo open source ESP8266 NodeMCU
- ponte H L298N per pilotare il motore
- motore cc già presente originale
- pulsantiera già presente originale
Mi sono orientato su questa funzionalità:
ricevere i dati
nmea del navigatore attraverso il collegamento wifi su protocollo UDP della scheda nodemcu e utilizzare questi dati per pilotare il braccio dell'autopilota. Risultato PERFETTO!
Ma vediamo i dettagli cominciando dall'hardware :
Come già detto del vecchio autohelm 800 ho riutilizzato il motore (in corrente continua), l'involucro plastico e la pulsantiera provvista di un led rosso molto comodo.
Mi sono studiato la pulsantiera e sono riuscito a mappare i collegamenti di ogni pulsante, attraverso l'uso di una breadboard ho testato il funzionamento mediante l'uso di una libreria per arduino scritta appositamente per tale scopo, trovate i dettagli a questo indirizzo
Keypad library .
Qui di seguito lo schema elettrico della pulsantiera e di come è stata connessa alla scheda nodemcu:
Adesso passiamo al circuito per pilotare il motore in cc. Per tale scopo ho utilizzato un ponte H ed esattamente il circuito L298N che oltre a fornire la componentistica per pilotare il motore ha anche una uscita da +5v ( pilotandolo con i 12v della batteria) da utilizzare per alimentare la piccola scheda nodemcu.
I collegamenti sono molto semplici : il negativo della batteria è comune sia al L298N che alla scheda di controllo nodemcu, mentre l'alimentazione di quest'ultima viene prelevata dall'uscita da 5v del ponte H ( L298N).
A questi collegamenti vanno aggiunti quelli di controllo ( pin 1 e 2 ) che asseconda che essi sia in stato alto ( +5 v) o basso ( 0 v) determinano il senso di rotazione del motore secondo questo schema:
1 basso , 2 alto -> senso orario
1 alto , 2 basso -> senso antiorario
1 basso, 2 basso -> motore fermo
A questo punto i collegamenti sono finiti e non resta che studiare bene come inscatolare il tutto.
Adesso passiamo al software:
Per un risultato ottimale quello che serve è un algoritmo basato sul controllo
Proporzionale-Integrale-Derivativo, tale algoritmo consente un pilotaggio privo di oscillazioni e permette di effettuare le giuste correzioni di rotta.
L'algoritmo PID meriterebbe un post apposito per la piena comprensione ( perchè no ...).
Ma vediamo sia lo pseudo codice che il codice effettivo poi sviluppato per il nostro autopilota:
previous_error = 0
integral = 0
start:
error = setpoint - measured_value
integral = integral + error*dt
derivative = (error - previous_error)/dt
output = Kp*error + Ki*integral + Kd*derivative
previous_error = error
wait(dt)
goto start
I parametri fondamentali da settare sono Kp ( azione proporzionale), Kd ( azione derivativa) e Ki (azione integrale).
Dopo diverse prove i valori che più hanno soddisfatto le mie attese sono stati questi :
float DT = 500;
float KP = 1.2;
float KI = KP/DT * 0.8;
float KD = KP*DT * 100;
dove DT è l'intervallo di tempo (millisecondi) tra una azione compensativa e l'altra.
Quello che segue è l'implementazione del pseudocodice appena visto adattato allo specifico utilizzo sull'autopilota a barra:
void calculateTargetMotorPosition()
{
float headingDiff = targetHeading - Heading;
if ( headingDiff > 180 ) headingDiff -= 360;
if ( headingDiff < -180 ) headingDiff += 360;
Error = Error + (headingDiff * DT);
if ( Error > MaxError) Error = MaxError;
if ( Error < MinError) Error = MinError;
//Compute error derivative
ErrorDer = (headingDiff - prevError)/DT;
prevError = headingDiff;
//Compute correction
Correction = KP * headingDiff;
Correction += KD * ErrorDer;
Correction += KI * Error ;
if ( abs(Correction) > MaxCorrection) Correction = MaxCorrection;
if ( abs(Correction) > MinCorrection ) moveMotor(abs(Correction), Correction > 0);
}
Il codice completo è disponibile a questo indirizzo: https://www.dropbox.com/s/5554l3br1wuzzof/AutopilotaPID.ino?dl=0
E' importante ricordarsi di configurare correttamente la connessione all hotspot Wifi della barca o del plotter nell'apposita sezione ( linee 12 e 13 del codice):
//WiFi Config
#define WIFI_SSID "wifiSSIDName"
#define WIFI_PASS "WifiPassword"
e configurare il plotter in modo tale che i dati relativi alla rotta da seguire e alla posizionje (gps) siano correttamente trasmessi all'autopilota sulla porta 10112 ( modificabile) su protocollo UDP :
unsigned int UDPPort = 10112;
In questo post potete trovare le informazioni per configurare OpenCPN in modo tale da inviare le informazioni necessarie all'autopilota per poter funzionare. In particolare i messaggi NMEA che servono al pilota per funzionare sono ECAPB per l'ottenimento della rotta da seguire e ECRMC per acquisire quella che è la direzione attuale della barca (COG) .
Per chi non lo sapesse OpenCPN è un software open source disponibile per diversi sistemi operativi. Questo software è in grado di trasformare un computer ( PC o mini computer come Raspberry) in un sistema cartografico.
Ma come funziona una volta programmato e montato ?
Molto semplice: appena acceso l'autopilota può essere mosso attraverso i tasti +10 +1 -10 -1 della pulsantiera che muovono il braccio in maniera proporzionale al numero premuto.
In questa modalità la barra rimarrà ferma e il pilotaggio sarà totalmente manuale.
Per attivare il pilota automatico bisognerà premere il tasto AUTO ( rosso ), solo a questo punto il pilota automatico proverà a connettersi alla rete wifi, precedentemente configurata, e, se tutto funziona a dovere, comincerà a ricevere i dati di navigazione dal plotter, l'intermittenza del led confermerà che questo stia accadendo.
Il progetto è notevolmente migliorabile e sicuramente può essere arricchito di tante funzionalità ...
Aspetto i vostri feedback.