Arduino Premi Pulsante Automatico (pigiocchio)

Alcuni giorni fa un amico mi ha chiesto come costruire un dispositivo che periodicamente prema un pulsante. Dopo averci pensato un po’ su ho escogitato questa soluzione utilizzando un Arduino ed un servo motore.

Un servo motore (servo) è un motore che può posizionare con precisione il suo albero. Per posizionare l’albero il dispositivo che pilota il servo deve usare un segnale PWM; la maggior parte dei servo per modelli radiocomandati lavora ad una frequenza di 50Hz (impulsi di 20mS) con la parte positiva dell’impulso che varia da 1 a 2 mS.
Questo significa che se vogliamo usare Arduino per generare una forma d’onda di quel tipo, dobbiamo fare qualche trucco, perchè  la analogWrite dell’Arduino genera un segnale PWM a 490Hz.
La lunghezza della parte positiva dell’impulso determina la posizione dell’albero.

Il Servo che ho usato per questo progetto è un EK2-508 un pezzo di ricambio per il mio splendido elicottero radiocomandato E-Sky Co-Comanche; è economico e facile da reperire in commercio, ma credo che un qualunque servo a 5V vada bene lo stesso.

Per regolare con precisione la posizione dell’albero ho utilizzato una trimmer da 100K che genera un segnale da 0 a 5V. Arduino legge il valore in uscita dal trimmer tramite la linea analogica A0 e genera un impulso che ha la parte positiva proporzionale al segnale letto.

 

Connessioni per il Premi Pulsante Automatico

Attenztione !! per generare questa immagine ho usato Fritzing ma l’Arduino Nano della libreria Fritzing ha una piedinatura differente dal mio dispositivo. Quindi controllate con attenzione la piedinatura del vostro Arduino, non fidatevi dell’immagine.

In questo video potete vedere il pigiocchio in azione: un led verde si accende quando il pulsante viene premuto

Il software è piuttosto semplice. Il PWM è ottenuto “a mano” usando la funzione digitalWrite. L’unica cosa da notare è che siccome la durata dell’impulso positivo va da 1 a 2mS ho utilizzato la delayMicroseconds per avere la massima risoluzione. Per la restante parte dell’impulso (sempre bassa) ho utilizzando una delay da 18mS, anche perchè la delayMicroseconds non può generare intervalli così lunghi.

Siccome il Servo ha una tolleranza di ± 2mS possiamo trascurare il tempo utilizzato dal software per generare gli impulsi.

#define SERVO_PIN        4
#define TRIMMER_PIN      A0

#define PUSH_TIME_MS                200
#define TIME_BETWEEN_PUSHES_MS       3000

#define MAX_POSITIVE_PULSE_TIME_uS    2000
#define MIN_POSITIVE_PULSE_TIME_uS    1000

void setup()
{
    pinMode(SERVO_PIN, OUTPUT);

    //leggiamo l'ADC aspettiamo e buttiamo il valore letto
    //la prima lettura può essere errata
    analogRead(TRIMMER_PIN);
    delay(300);

    //Seriale per il Debug
    Serial.begin(9600);
}

void SetServo(unsigned int pHighPulseWidthInMillis)
{
    //La generazione dell'impulso di 20mS è divisa in due parti
    //1) i primi 2 mS
    //2) i restanti 18 mS

    //Questa parte genera i primi 2 mS
    //Impulso positivo
    digitalWrite(SERVO_PIN, HIGH);
    delayMicroseconds(pHighPulseWidthInMillis);
    //impulso basso (up to 2000uS)
    digitalWrite(SERVO_PIN, LOW);
    delayMicroseconds(MAX_POSITIVE_PULSE_TIME_uS -
                            pHighPulseWidthInMillis);

    //siccome la delayMicroseconds non genera intervalli per più di 16384 uS
    //usiamo una delay di 18mS per la parte bassa dell'impulso
    delay(18);
}

void loop()
{
    for(;;)
    {
        unsigned long t;
        unsigned int pulseUs;
        unsigned int analogValue;

        //Legaimo dal trimmer la duarata dell'impulso positivo  (0..1023)
        //e convertiamola in (0..1000)
        analogValue = (double)analogRead(TRIMMER_PIN) / 1023.0 * 
           (MAX_POSITIVE_PULSE_TIME_uS - MIN_POSITIVE_PULSE_TIME_uS);

        Serial.print("Trimmer Value --> ");
        Serial.println(analogValue);

        //Agiungiamo la durata del minimo impulso positivo
        pulseUs = MIN_POSITIVE_PULSE_TIME_uS + analogValue;        

        Serial.print("Positive Pulse Width (uS) --> ");
        Serial.println(pulseUs);

        //Impostiamo la posizione del servo per  PUSH_TIME_MS
        for(t = millis() + PUSH_TIME_MS; t > millis();)
            SetServo(pulseUs);        

        //Impostiamo la posizione a riposo del servo per TIME_BETWEEN_PUSHES_MS
        for(t = millis() + TIME_BETWEEN_PUSHES_MS; t > millis();)
            SetServo(MAX_POSITIVE_PULSE_TIME_uS);
    }
}

A presto per nuove avventure con Arduino ;)

This entry was posted in Arduino Projects, Hardware. Bookmark the permalink.

Lascia un Commento

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *

*

È possibile utilizzare questi tag ed attributi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>