Sheet Arduino n.14 (Drive SERVO)

[Lezione del xx yyy 2019]

Drive servo prima parte

La scheda della esercitazione n.14, richiede di pilotare un servo.

Abbiamo due parti. Nella prima, si forza il servo ad assumere gradualmente tutte le posizioni (angoli) possibili. Sia in senso crescente che decrescente.

Non avendo il Grove starter kit, ho adattato l’esercizio utilizzando il servo del kit Arduino, come indicato nel seguente video:

Lo schetch è semplice:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/* Embedded Systems Architecture - hardware
 *  application on xx yyy 2019
 *  
 *  Drive Servo 1st part
 *
 *  drive servo rotating 180° forth and back
 *  
 *  Note: 
 *    - servo.read() give the last request position, NOT the actual one; it's useless
 *    - servo SM-S2309S has a +/- 60° range; hence: 0-120° NOT 180°
 *    - servo SM-S2309S datasheet: https://descargas.cetronic.es/microservo.pdf
 */

#include <Servo.h>

#define PIN_SERVO 5
#define ANG_SPEED 1 / 0.11    // °/sec ?? from servo SM-S2309S datasheet, but it seems to work 
                              //     even using 1/0.01; maybe because we are without load?
#define MAX_ANGLE 120         // ° servo SM-S2309S has a +/- 60° range; hence: 0-120° NOT 180°

#define TT1G (int)(0.05 * 1000)  // msec to do a 1°

Servo servo; // create servo obj

int pos = 0; // servo position

void setup() {
    servo.attach(PIN_SERVO); // servo on pin 5
    pos =  0;
    servo.write(pos);          // go to position 0
    delay(TT1G * MAX_ANGLE);   // max time to execute command
}

void loop() {
    for(pos=0;pos<=MAX_ANGLE;pos++){     // from 0 to 120, step by step
        servo.write(pos);
        delay(TT1G);
    }
    for(pos=MAX_ANGLE;pos>=0;pos--){    // the same but backward
        servo.write(pos);
        delay(TT1G);
    }
    
}

Alla ln 23 inizializzo l’istanza servo della classe Servo, che uso per comandare il servomotore. E alla ln 28 indico il pin PWM 5 per pilotare il servomotore. Dopo di che lo porto in posizione 0° (ln 30) e attendo il tempo più sfavorevole per eseguire il comando precedente (ln 31).

Dopo di che si entra in loop ordinando in sequenza di assumere gli angoli da 0 a 120 e viceversa.

Mi ha deluso la funzione servo.read() in quanto pensavo avesse modo di conoscere l’effettiva posizione del servo. Non è così: riporta solo l’ultima posizione richiesta e non quella effettiva.

Drive servo seconda parte

Nella seconda parte, dobbiamo asservire il servo ad un potenziometro.

Quindi dobbiamo leggere la tensione del potenziometro per poi rovesciarla sul servomotore facendo l’opportuna proporzione.

Lo schetch è il seguente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* Embedded Systems Architecture - hardware
 *  application on xx yyy 2019
 *  
 *  Drive Servo 2nd part
 *
 *  drive servo using trimmer
 *  
 *  Note: 
 *    - servo SM-S2309S datasheet: https://descargas.cetronic.es/microservo.pdf
 */

#include <Servo.h>

#define TRIMMER   A0
#define PIN_SERVO 5
#define MAX_ANGLE 120         // ° servo SM-S2309S has a +/- 60° range; hence: 0-120° NOT 180°

Servo servo; // create servo obj

void setup() {
    servo.attach(PIN_SERVO); // servo on pin 5
}

void loop() {
    int input = analogRead(TRIMMER);
    int angolo = map(input, 0, 1023, 0, MAX_ANGLE);
    servo.write(angolo);
    delay(100);
}

In questo caso il nucleo è alle linee 25, dove leggo la tensione del potenziometro, e 26 dove mappo linearmente la tensione letta all’angolo richiesto al servomotore.