Corso programmazione PICMicro in C – Approfondimenti – Pilotare un servocomando usando un trimmer

Abbiamo visto in un articolo precedente cos’è un servocomando e soprattutto come deve essere fatto il segnale per poterlo pilotare. Se non avete letto quell’articolo vi consiglio di farlo prima di continuare. Riassumo in ogni caso le caratteristiche che deve avere il segnale di pilotaggio:

  • Deve avere una frequenza di 50Hz, ovvero un periodo di 20mS
  • Il livello logico alto deve avere una durata variabile tra 500μS (servo tutto girato in un verso) e 2500μS (servo tutto girato nel verso opposto). Questi due valori estremi vanno bene per quei servocomandi che sono in grado di eseguire una rotazione di 180° (la stragrande maggioranza)
  • Il segnale deve essere inviato di continuo affinchè il servo, sotto sforzo, possa mantenere la sua posizione

Dobbiamo quindi generare un’onda quadra, tenendola a livello alto per il tempo necessario ad impostare un determinato valore di rotazione e quindi a livello basso per il tempo rimanente per ottenere un periodo di 20mS. E’ una cosa abbastanza semplice da realizzare sfruttando ritardi e cambiamenti di stato logico del pin al quale è connesso il cavo segnale del servo.

Nell’esempio allegato vi mostro come è semplice far ruotare un servocomando in base alla rotazione di un trimmer. Il programma è scritto come sempre in Hitech-C (9.81) per pic16F877A quarzato a 20MHz, montato su FreedomII. Andremo quindi a sfruttare il trimmer collegato alla porta AN1 eseguendo tutte le impostazioni del caso come già imparato.

Il valore restituito dal convertitore A/D viene memorizzato nella variabile ADval, prima di impostare il servo vengono eseguite due letture e quindi eseguita la media sfruttando un bitshift di 1 posizione verso destra, che abbiamo imparato serve a dividere per due. La durata del livello logico alto per controllare il servo è memorizzata nella variabile Pulse ed è un valore che deve variare da 500 a 2500.

Dobbiamo quindi trovare un sistema per far corrispondere la dinamica di valori fornita dal convertitore A/D (0÷1023) nel range di valori da sfruttare per il servo (500÷2500). Cominciamo col notare che il range di azione del servo è di 2500-500 = 2000μS. Basta quindi eseguire una proporzione per “trasformare” il valore letto dal modulo ADC in un valore di μS da assegnare al servo:

Il valore di Pulse in base al valore di ADval sarà quindi dato da:

(1)

A tale valore andrà quindi aggiunto 500 per ottenere un valore tra 500 e 2500:

(2)

C’è da notare una cosa. Dichiaro le variabili Pulse e ADval come unsigned int, per cui si tratta di valori a 16bit. Eseguendo l’operazione definita dalla [1], a meno che ADval non valga 1023, otterrò sempre zero come risultato. Ricordo difatti che in C una divisione tra interi restituisce sempre un numero intero per cui con valori di ADval minori di 1023 la frazione varrà sempre 0 virgola qualcosa e quindi verrà sempre restituito un valore pari a zero. La [1] quindi mi serve unicamente per rilevare il trimmer girato tutto verso 5V, che mi restituisce il valore 1023. Potete anche fare la prova: girando il trimmer, il servo rimarrà sempre tutto da un lato fino a che non raggiungete l’estremità e quindi il servo si sposterà completamente in direzione opposta.

Dobbiamo quindi recuperare i valori intermedi. Nulla di più facile utilizzando l’operatore resto della divisione (%). Dopo aver eseguito la [1] dobbiamo sommare la parte decimale:

(3)

L’operazione che stiamo eseguendo è in pratica la stessa eseguita nella [1] per trovare la proporzionalità tra valore letto dall’A/D e valore da assegnare il servo, l’unica differenza è che stiamo usando l’operatore % per trovare il resto della divisione e quindi moltiplichiamo per 2 anzichè per 2000 perchè il resto della divisione è in realtà la parte millesimale (le 3 cifre dopo la virgola). Dopo aver eseguito la [1] e la [3] possiamo quindi aggiungere le 500 unità con la [2].

Possiamo infine creare il segnale con una semplicissima sequenza di ritardi:

// impulso positivo al servo
SERVO=1;
// per la durata calcolata in base alla posizione del trimmer
DelayBigUs(Pulse); // DelayBigUs accetta un INT come argomento (0-65535)
// impulso negativo
SERVO=0;
// per il resto del tempo che manca per arrivare a 20mS (50Hz)
DelayBigUs(20000-Pulse);

La funzione DelayBigUs è contenuta nelle routine di delay enhanced precision del sito MicrochipC.com.

Il ritardo ottenuto con queste routine è preciso e possiamo osservare all’oscilloscopio la bontà delle funzioni che vi ho appena esposto. Con il trimmer tutto girato da un lato possiamo osservare la pulsazione da 500μS (0.5mS):

Mentre girando tutto il trimmer nella direzione opposta:

Alcune raccomandazioni:

  • Il servo deve essere alimentato preferibilmente con una tensione diversa da quella che usate per alimentare il PIC. Potete anche usare la stessa linea di alimentazione ma predisporre un regolatore separato per i servocomandi. I servocomandi funzionano da 5 a 6V. Ovviamente a 6V forniscono il massimo valore di coppia. Se dovete acquistare un regolatore consiglio un 7806CV che è in grado di fornire fino a 2A. Se usate la stessa indentica linea di alimentazione potrete notare (ma non è sempre detto) come i disturbi generati dal servo fanno impazzire il pic che a sua volta invierà dei segnali di comando sbagliati facendo impazzire il servo.
  • Se usate due alimentatori separati non dimenticate di mettere le masse in comune.
  • Se agli estremi di rotazione notate che il servo fischia o fa molto rumore, fatelo tornare indietro: non è fatto per raggiungere quella posizione e rimanerlo così ne potrebbe causare la rottura.
  • Il codice è scritto per Hitech-C versione da 9.81 a salire. Se il codice così come l’ho scritto vi crea problemi e state impazzendo vuol dire che non avete letto questo. Comunque sia dato che una piccola percentuale legge col prosciutto davanti agli occhi ho messo tra le note del sorgente le poche modifiche da fare per farlo funzionare con le vecchie versioni (mannaggia a voi che non vi aggiornate!).
  • Ovviamente se il vostro programma deve eseguire tanta altra roba nel main, questo sistema potrebbe non essere buono in quanto i ritardi tra l’invio di un segnale e il successivo aumenterebbero di molto. In questo caso vi conviene utilizzare un sistema che piloti i servo sfruttando l’interrupt. Ovviamente più avete un Fosc elevato e più risoluzione potete ottenere.

Download

Comandare un servocomando con un trimmer (860 download)
Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)