SERVO ARDUINO - COME TENERLI FERMI!

Ho una domanda:

SERVO come evitare il movimento iniziale al reset di Arduino.

Usando la libreria servo ogni volta che si resetta Arduino il servo va nella posizione iniziale

DETACH non serve a nulla.
Qualcuno ha risolto in qualche modo?

Modificando la libreria magari? o con altro stratagemma?

questa forse la parte della libreria incriminata...forse

public:
  Servo();
  uint8_t attach(int pin);           // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
  uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes. 
  void detach();
  void write(int value);             // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds 
  void writeMicroseconds(int value); // Write pulse width in microseconds 
  int read();                        // returns current pulse width as an angle between 0 and 180 degrees
  int readMicroseconds();            // returns current pulse width in microseconds for this servo (was read_us() in first release)
  bool attached();                   // return true if this servo is attached, otherwise false

Se qualcuno che ci capisce di più può aiutarci
Sarebbe bellissimo.

In sostanza usando i servomotori sg o mg90s
Per un robottino che ha delle braccia
Ogni volta che si carica un nuovo programma o si resetta i servo vanno di scatto in posizione iniziale e poi tornano dove erano prima.

Ma cosi si rompe tutto perchè noi li muoviamo lentamente visto il peso...e in questa fase vanno alla massima velocità.

Vorremmo evitare questo fenomeno
Ma ancora non abbiamo capito come.

Per iscrizione. Curioso di una eventuale risposta.

Purtroppo non c'è modo di sapere dopo un reset in quale posizione si trovano i servo.

Durante il reset di arduino il segnale generato per controllare il servo viene a mancare, cosa accade al servo quando è privo di segnale non me lo ricordo.

Si potrebbe tentare di aggirare il problema tramite un circuito di reset ritardato che alzi un pin 100ms di secondo prima di resettare. Il pin alzato letto da arduino serve a memorizzare l'attuale posizione dei servo in memoria eeprom. Al riavvio se sono presenti dati in eeprom dovranno essere caricati in memoria ram e usati nel setup().

Oppure spetta all'utente pigiare un pulsante prima di effettuare un reset (reset che avviene prima di scrivere lo sketch), pulsante che una volta premuto porta i servo nella posizione zero.

Ciao.

Ciao, non si può, il servo, almeno quello che hai, riceve ma non invia nessun segnale sulla sua posizione quindi quando fai il reset riceve il comando di andare al grado X e lui esegue.
Un modo per aggirare il problema potrebbe essere scrivere ogni tot la posizione nelle EEPROM cosi quando fai il reset o togli alimentazione l'ultima posizione e stata salvata nella EEPROM che al riavvio potresti metterla come posizione iniziale e quindi il servo, salvo se non fatto girare da forze esterne, rimarrebbe fermo, o meglio rimarrebbe nella posizione al momento del reset salvo forze esterne come detto prima.
Però non ho mai usato questa memoria e non so nemmeno se sia fattibile dato che dovresti sovrascrivere il dato ad ogni movimento del servo, magari qualcuno che sa meglio potrebbe dirti se si o no.
Un altro modo sarebbe quello di mettere un encoderino sull'albero del servo ma qua vai a modificare hardware e complichi il software,
Ciao

fedale:
Ogni volta che si carica un nuovo programma o si resetta i servo vanno di scatto in posizione iniziale e poi tornano dove erano prima.

Appunto... il problema non è salvare o meno la posizione del servo... almeno da quello che leggo... dici che a reset completo tornano nella posizione in cui vuoi...

quindi il problema non è il valore servo.write() da recuperare, semmai è continuare a pulsare mentre Arduino si resetta...

la mia ignorante soluzione? un PCA9685 "probabilmente" fa il caso tuo... ma ripeto... è la prima cosa che mi viene in testa...
quando resetti Arduino non resetti contestualmente le periferiche i2c, paradossalmente sembra si resettino (se così vogliamo dire) solo quando riparte lo schetch, ma non per via di un vero e proprio reset delle periferiche, ma perché il programma riparte da 0 e quindi riaprono solo in quel momento la comunicazione i2c comunicando i nuovi parametri. Ben comprendi che se all'inizio dellk sketch non comunichi variazioni alla periferica i2c questa continua a comportarsi con l'ultima configurazione inviatagli. non so se sono stato chiaro.
un esempio pratico che mi viene sono gli schermi i2c...
se tu tramite seriale gli invii il nome Antonio per visualizzarlo sul display, ed effettivamente lui lo visualizza, anche se riavvii Arduino fino a quando non gli dici di ripulire lo schermo o gli invii un altro nome visualizzerà sempre il nome Antonio... nonostante il riavvio di Arduino...
ripeto non so se vale anche con quell'integrato che ti ho segnalato, ma è una prova che potresti fare...adafruit lo vende già pronto...

EDIT: ovviamente devi includere la libreria e modificare lo sketch in funzione di questa..

Provo a dire la mia da programmatore ignorante ma cercando un workaround.
Lo so che a livello hardware potrebbe essere un poco problematico il cablaggio, ma non potreste aggiungere una uscita al quale collegate un relè che taglia/chiude alimentazione dei servo?
In pratica all'accensione/reset di arduino il relè (o mosfet o quello che volete) è diseccitato, i servo non sono alimentati e non si muovono. Dopo x tempo il relè (o altro) viene eccitato e da alimentazione ai servo che però stanno già ricevendo informazioni sulla posizione precedentemente memorizzata (EEPROM).
In questo modo non dovreste avere bruschi spostamenti.

per non avere bruschi movimenti bisogna aggiungere una rampa sul software, ma se il servo in assenza di segnale si ferma in posizioni casuali non serve a nulla nemmeno la rampa

Grazie a tutti delle risposte.

forse la strada che impatta meno e più "pulita" sembrerebbe essere questa:

"Si potrebbe tentare di aggirare il problema tramite un circuito di reset ritardato che alzi un pin 100ms di secondo prima di resettare. Il pin alzato letto da arduino serve a memorizzare l'attuale posizione dei servo in memoria eeprom. Al riavvio se sono presenti dati in eeprom dovranno essere caricati in memoria ram e usati nel setup().

ma non è alla nostra portata oggettivamente...
Io non saprei neanche da dove partire... :slight_smile:

ma non è alla nostra portata oggettivamente...
Io non saprei neanche da dove partire... :slight_smile:

Se usassi un arduino su breadboard potrei spiegarti come fare, ma usando arduino standard credo non sia possibile senza fare modifiche hardware. In sostanza serve un condensatore da 10uf (C) e una resistenza da 22kohm (R). C va connesso tra +5V e pin reset del ATmega328, la R va connessa allo stesso pin, l'altro capo di R va al pin RESET del convertitore Serial.

Con questi valori ritardi il reset di circa 100ms. Ora un pin di arduino viene connesso al pin RESET del convertitore Serial, questo pin sente il comando di reset all'instante, il codice lo rileva, salva i valori e resta in attesa senza fare nulla (un delay 1000), quando C si scarica è la tensione sul pin reset del 328 scende sotto 3.5V la MCU si resetta.

Comunque prima di affrontare questa modifica conviene creare lo stesso meccanismo ma attivabile manualmente attraverso un pulsante da premere prima di scrivere un nuovo sketch.

Ciao.

icio:
per non avere bruschi movimenti bisogna aggiungere una rampa sul software, ma se il servo in assenza di segnale si ferma in posizioni casuali non serve a nulla nemmeno la rampa

Io avrei due soluzioni per eliminare lo scatto improvviso che hanno i servo alla partenza del programma, di cui una provata da me con esito positivo.

Queste soluzioni funzionano se si utilizza la schedina PCA9685 per comandare i servo.

  1. Visto che non sappiamo dove il servo si è fermato, quando vi è stato il precedente reset, oppure l'alimentazione è stata tolta, per creare una rampa software, ho inserito un ciclo for nel setup dove vado ad utilizzare in alternanza le funzioni slep() e wakeup(), ( uso la libreria Adafruit_PWMServoDrive ).

Queste due funzioni non fanno altro che attivare / disattivare l'oscillatore interno per generare l'impulso, che deve essere settato prima di entrare nel ciclo for.

Dalle prove che ho fatto un valore ottimale è inserire delayMicroseconds(2000); dopo il wakeup(), mentre dopo lo slep(); si può usare un delay( 200 ) o più a piacere.

  1. mentre per la seconda soluzione, da provare, si può utilizzare il pin OE della scheda PCA9685 che altro non fa che abilitare / disabilitare tutte le uscite, cioè togliere/fornisce l'alimentazione ai servo. Ulitizzando lo stesso principio del punto uno, si comanda tramite un pin dell'arduino il pin OE della scheda dei servo, utilizzando il digitalWrite().