Grave difetto nella libreria servo

Antefatto, ieri è passato a trovarmi un amico assieme al suo Arduino UNO e 12 servo Futaba di fascia alta, parliamo di servo digitali che costano più di 100 E l’uno, che deve usare per realizzare un braccio robotico, fin qui niente di strano, però quando mi ha fatto vedere il problema che lo bloccava mi è venuto subito il dubbio che la colpa era della libreria servo.
Premesso che i servo sono alimentati tramite un pacco batteria LiPo 2s da 5000 mAh, ha realizzato un apposito pcb che provvede alla distribuzione dell’alimentazione e preleva i segnali di controllo dalla UNO, in particolare pin da 2 a 7 per i primi sei servo e pin da 14 a 19 (A0-A5) per gli altri sei servo, pertanto ho escluso da subito problemi dovuti all’alimentazione o ai contatti.
Il problema è che quando i 12 servo vengono pilotati con impulsi, tutti uguali durante il test, minori di 1850 us funziona tutto perfettamente, non appena si supera questa soglia i servo si bloccano e tornano a funzionare non appena si torna sotto la soglia.
Mi ci è voluto un pochino per capire la natura del problema, sotto trovate uno screen shot dell’analizzatore di stati logici che evidenzia la causa del problema, però non appena fatta una misura strumentale dei segnali applicati ai servo la cosa è diventata chiara.
In pratica la libreria servo funziona in questo modo, andando in ordine di creazione delle varie xxxx.attach() emette gli impulsi di controllo in sequenza partendo dal primo servo dichiarato per finire con l’ultimo, fin qui nulla di strano però fino a che i servo sono pochi e/o gli impulsi di controllo non sono di valori elevati, range classico 500-2500 us per 0-180°, il frame rate (tempo di ripetizione dei vari impulsi) è circa 20 ms (50 Hz) come deve essere, non appena si usano molti servo con tempi lunghi questo modo di funzionamento porta a frame rate minori di 20 ms, nel caso specifico con 12 servo a 2500 us (180°) si arriva a oltre 30 ms (< 33 Hz).
Avere un frame rate lento causa due tipi di problemi, il primo è la perdita di reattività del servo e minore fludità di movimento, la seconda è che a seconda del modello di servo si può incorrere nel blocco del funzionamento dello stesso, come nel caso in oggetto visto che i servo digitali Futaba non accettano frame rate minori di 45 Hz, come valore massimo accettano 75 Hz.
Sebbene questo problema viene fuori solo in condizioni particolari è comunque un grave difetto della libreria servo, non è ammissibile che il frame rate varia a seconda del numero di servo usati e la durata degli impulsi.
Purtroppo questo problema non è risolvibile correggendo qualche riga di codice della libreria, va riscritta completamente modificando la logica di funzionamento.

Screen capture dell’analizzatori di stati logici con 12 servo e impulsi a 2500 us, le tracce sono solo 9 perché questi sono i canali collegati, gli impulsi servo collegati vanno da 1 a 8 e il 12, 9-10-11 sono mancanti ma si vede comunque che si trovano in mezzo tra 8 e 12,

servo_fail.png

x iscrizione

La descrizione della libreria dice: The Servo library supports up to 12 motors on most Arduino boards and 48 on the Arduino Mega. Servo - Arduino Reference
Percui dovrebbe essere possibile usare 12 Servo sulla UNO, ma come hai verificato questa descrizione non é valida se si vuole rispettare i 50Hz di ripetizione del segnale per il Servo.
Astrobeed hai controllato la situazione usando un Arduino MEGA 2560?

Ciao Uwe

Si il problema è presente anche sulla Mega2560, dipende dalla logica con cui vengono sintetizzati gli impulsi e non dal tipo di hardware, sulla Mega cambia solo il timer usato, anzi i timer (1-3-4-5) perché in questo caso vengono usati fino a 4 timer 16 bit, ognuno si occupa di 12 servo.
Sto elaborando una soluzione, sotto forma di libreria in C puro, dove oltre a non esserci più il limite dei 12 servo sulla UNO, volendo si possono usare tutti i 20 pin disponibili, è anche possibile gestire il frame rate in modo da poterlo aumentare, se il servo lo permette, così da migliorare la risposta del servo e la fluidità dei movimenti.
Con la mia soluzione tutti gli impulsi PPM vengono emessi quasi in parallelo, invece che in sequenza, così si elimina anche la latenza tra il primo e l'ultimo canale servo, altro problema dell'attuale libreria servo.

Allora in sintesi se si usano meno di 12 Servo per timer funziona tutto correttamente. Sulla Mega si riesce a definire quale uscita usa quale Timer?

Una libreria che funziona correttamente é ovviamente la soluzione migliore.

Ciao Uwe

Il limite è dato sia dal numero di servo che dall’escursione massima richiesta, p.e. anche con solo 10 servo con escursione di 180°, impulsi fino a 2500 us, si arriva ad un valore massimo di durata del frame di oltre 25 ms, pari a 40 Hz, valore che a seconda del modello di servo, in particolare con quelli digitali, è troppo bassa per consentire un corretto funzionamento.
Sulla Mega2560, stando alla descrizione della libreria servo, dovrei controllare il sorgente, se si usano fino a 12 servo viene usato il timer 3, se si utilizzano più servo inizia ad usare anche il timer 1, poi il 4 e infine 5, quanti timer vengono usati dipende dal numero di servo inizializzati, fino a 12 solo un timer, se sono 13 due timer, se sono 25 tre timer, etc., quali pin usare è indipendente dal timer, sono gestiti a livello di interrupt.
Altro dettaglio sulla libreria servo, dato che il suo interrupt non è atomico, in modo da non far perdere conteggi alla millis o caratteri ricevuti sulla seriale, questo comporta la possibilità di avere dei glitch , anche di qualche grado, su i movimenti dei servo, è scritto chiaramente nel playground alla voce Limitations, vorrei eliminare anche questo problema.