Servocomandi e pulsanti

Buongiorno a tutti ragazzi,

avrei la necessità di movimentare 2 fari a led montati su di una colonna fari, ho pensato di farlo con l’utilizzo di 2 servocomandi con 4 tasti, ovvero 2 per ogni servo, che in base alla pressione aumentano o diminuiscono i gradi. Fino a qui tutto bene in quanto scopiazzando qua e là ho scritto uno sketch ed anche testato sulla breadboard funziona tutto…
Vorrei ora aggiungere un pulsante, che alla pressione di questo, i due servi si posizionino entrambi a 90° portandomi quindi i 2 fari nella posizione di partenza, permettendomi di ripiegare la colonna fari in modo che i fari entrino nell’alloggiamento…Mi potreste dare qualche dritta? io ci ho provato ma senza successo… vi faccio vedere il codice che ho scritto… Il famoso tasto l’ho dichiarato due volte chiamandolo ripDX e ripSX ed assegnandogli il medesimo Pin…(magari è qui l’errore…)

#include <Servo.h>

#define servoPinDX 10
#define servoPinSX 11

Servo servoDX;
Servo servoSX;
 
int gradoDX = 90;
int minGradDX = 40;
int maxGradDX = 130;
int pinServoDX = 10;
int prevDX = A0;
int nextDX = A1;
int ripDX = A2;

int gradoSX = 90;
int minGradSX = 40;
int maxGradSX = 130;
int pinServoSX = 11;
int prevSX = A3;
int nextSX = A4;
int ripSX = A2;

void setup()
{
  servoDX.attach( servoPinDX );
  servoDX.write( gradoDX );

  servoSX.attach( servoPinSX );
  servoSX.write( gradoSX );
 
  pinMode( prevDX, INPUT );
  pinMode( nextDX, INPUT );
  pinMode( ripDX, INPUT );

  pinMode( prevSX, INPUT );
  pinMode( nextSX, INPUT );
  pinMode( ripSX, INPUT );
} 
 
void loop()
{
  if ( analogRead( prevDX ) > 1000 ) { gradoDX--; }
  if ( analogRead( nextDX ) > 1000 ) { gradoDX++; }
  if ( analogRead( ripDX ) > 1000 ) { gradoDX = 90; }
 
  if ( gradoDX > maxGradDX ) { gradoDX = maxGradDX; }
  if ( gradoDX < minGradDX ) { gradoDX = minGradDX; }

  if ( analogRead( prevSX ) > 1000 ) { gradoSX--; }
  if ( analogRead( nextSX ) > 1000 ) { gradoSX++; }
  if ( analogRead( ripSX ) > 1000 ) { gradoSX = 90; }
 
  if ( gradoSX > maxGradSX ) { gradoSX = maxGradSX; }
  if ( gradoSX < minGradSX ) { gradoSX = minGradSX; }
 
  servoDX.write( gradoDX );
  delay(15);

  servoSX.write( gradoSX );
  delay(15);
}

Grazie a chi vorrà darmi un aiuto…

Benvenuto. Essendo il tuo primo post, nel rispetto del regolamento, ti chiediamo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con attenzione il su citato REGOLAMENTO... Grazie.
Qui una serie di link utili, non inerenti al tuo problema:

Chiedo scusa, faccio subito, non avevo fatto caso alla sezione.. sorry.. e grazie per i link

Ecco una foto della colonna, giusto per avere un’idea reale di quel che volevo realizzare…

Se usi pulsanti non li devi leggere come fossero analogici, un pulsante ha solo due stati 1 o 0 mentre una tensione analogica può assumere valori da 0 a 1023 (su arduino). Inoltre al pulsante deve esserci un de-bounce altrimenti avrai una marea di letture falsate quando premi il pulsante. Riassumendo, studia la differenza tra analogRead e digitalRead e dai una lettura a questo [u]link[/u]

Grazie mille per i consigli, caspita devo rifare tutto.. adesso studio un po e ci provo.. non ho ben capito anche leggendo il link come dovrei fare fare il de-bounce ma credo che prima debba rifare lo sketch con il digitalread..

Ecco, ho impostato per ora uno sketch con un solo servo e due pulsanti… l’IDE non mi da problemi nella verifica…

#include <Servo.h> 

//Dichiariamo le costanti e le variabili.
Servo myservoDx;//Impostiamo il servomotore con il nome myservoDx.
int Button_Dx1;//Dichiariamo la varibile per il controllo dello stato del pulsante movimento antiorario del faro Dx.
int Button_Dx2;//Dichiariamo la varibile per il controllo dello stato del pulsante movimento orario del faro Dx.
int Posizione_Servo=90;//Assegniamo il valore della posizione di partenza del servo.

void setup() {
  myservoDx.attach(3);//Impostiamo il pin 3 come pin pwm per il controllo del servomotore.
  pinMode(4, INPUT);//Impostiamo il pin 4 collegato al pulsante sinistro come ingresso.
  pinMode(5, INPUT);//Impostiamo il pin 5 collegato al pulsante destro come ingresso.
  myservoDx.write(Posizione_Servo);//Posiziona il servomotore ad ogni avvio nella posizione 0.
}
//Il programma si ripete in un loop infinito.
void loop() {
  Button_Dx1 = digitalRead(4);//Legge il valore logico del pin 4 e assegna tale valore alla varibile dello stato del pulsante sinistro.
  Button_Dx2 = digitalRead(5);//Legge il valore logico del pin 5 e assegna tale valore alla varibile dello stato del pulsante destro.
  //Verifica che i pulsanti non si trovino allo stesso stato logico.(Esegue le istruzioni di incremento se un solo pulsante è premuto).
  if(Button_Dx1 != Button_Dx2){
    if(Button_Dx1 == HIGH){
      Posizione_Servo = --Posizione_Servo;//Decrementa il valore della varibile.
      }
    if(Button_Dx2 == HIGH){
      Posizione_Servo = ++Posizione_Servo;//Incrementa il valore della varibile.
      }
    myservoDx.write(Posizione_Servo);//Muove il servomotore alla posizione corrispondente al valore della variabile.
    delay(10);//Ritardo in millisecondi per stabilizzare il sistema.
    }
}

Ora dovrei aggiungere le istruzioni per il secondo servo, il de-bounce e il terzo pulsante che riposizioni entrambi i servi a 90°… qualcuno riesce a darmi un aiuto? grazie

Ciao, da molti esempi proposti non si impara il modo più efficiente di scrivere un programma.
Adesso dirti tutto quello che si può cambiare nel tuo programma diventa un po lunga, comunque i tuoi non sono errori è solo un modo di programmare non ottimale :slight_smile:

Ti do alcuni consigli

  1. Quando vuoi incrementare di uno il valore di una variabile, non scrivere variabile=++variabile, ma
    scrivi semplicemente variabile++;

  2. Non c’è bisogno di salvare il valore restituito da digitalRead() in una varibile, puoi usare direttamente
    digitalRead() in un if(), il valore che restituisce poi sarà valutato

  3. Arduino è velocissimo :slight_smile: quindi quando premi un pulsate lui leggerà tante volte lo stesso stato,
    per evitare ciò esistono diversi sistemi, in questo caso io userei un semplice delay() che attende
    che tu tolga il dito dal pulsante.

  4. Non c’è bisogno a mio avviso di controllare se stai premendo due pulsanti contemporaneamente, male che vada arduino eseguirà una delle due azioni in successione e non ci saranno grossi problemi.

Riordinando un po il tuo codice senza fargli troppe modifiche.

#include <Servo.h> 

//Dichiariamo le costanti e le variabili.
Servo myservoDx;//Impostiamo il servomotore con il nome myservoDx.

int Posizione_Servo=90;

void setup() {
  myservoDx.attach(3);//Impostiamo il pin 3 come pin pwm per il controllo del servomotore.
  pinMode(4, INPUT);//Impostiamo il pin 4 collegato al pulsante sinistro come ingresso.
  pinMode(5, INPUT);//Impostiamo il pin 5 collegato al pulsante destro come ingresso.
  myservoDx.write(Posizione_Servo);//Posiziona il servomotore ad ogni avvio nella posizione 0.
}
//Il programma si ripete in un loop infinito.
void loop() {
        
    
    
    if(digitalRead(4)){// Se pin pulsante è nello stato HIGH

        Posizione_Servo--; 
        mysevoDx.write(Posizione_Servo);
        delay(200); // Attendo che il dito si sposti dal pulsante

        // Tendendo premuto il pulsante incrementa con intervalli di 200 millisecondi
      
    }else if(digitalRead(5)){// Se pin pulsante è nello stato HIGH

        Posizione_Servo++; 
        mysevoDx.write(Posizione_Servo);
        delay(200); // Attendo che il dito si sposti dal pulsante

        // Tendendo premuto il pulsante incrementa con intervalli di 200 millisecondi
      
    }else if( digitalRead(6)){ // Se premo un pin specifico

         mysevoDx.write(90); // porto a posizione 90
          // se ho due servi copio la riga sopra con un nome diverso per il servo
        delay(200); // Attendo che il dito si sposti dal pulsante
  

    }

    
}

Caspita grazie, sei stato gentilissimo, eh sinceramente sto imparando a programmare (diciamo che ci provo un po ) quindi non mi sono chiare molte cose e faccio casini.. ora ho acquistato un libro su arduino e sulla programmazione in modo da studiare un po..
Comunque ora guardo un po di aggiungere un secondo servo che chiamerò myservoSx con i suoi relativi pulsanti e stasera proverò a testare il tutto..
Quando arriverò a riuscirci posterò anche delle foto.. comunque l'impiego è per movimentare una colonna fari di un mezzo da soccorso quindi devo riuscire a fare un buon lavoro..

Ah, una ultima domanda sicuramente stupida e banale per voi, ma per aggiungere il secondo servo e pulsanti, basta copiare le righe che interessano assegnandogli un nome diverso al servo e pin diversi ai pulsanti oppure c’è un modo più corretto? grazie

Ciao, intanto il copia e incolla è un metodo veloce ma può succedere che si verificano errori che poi è difficile trovarli. Meglio scrivere il codice da tastiera usando al minimo il copia incolla :slight_smile:

Devi crearti un altro oggetto servo con nome diverso e usare pin diversi.

Piccola considerazioni sui pulsanti e i pin di arduino: i pin di input su arduino hanno una alta impedenza (sono molto sensibili) percui quando si collega un pulsante non basta collegare un pin di questo ad arduino a l'altro al positivo o negativo di alimentazione in quanto quando il pulsante non è premuto (aperto) il pin di arduino non è collegato da nessuna parte e basta anche avvicinarsi con un dito per fargli commutare come se il pulsante fosse premuto, la soluzione è collegare tra il pin di arduino e positivo o negativo una resistenza di 10Kohm, ovvio che se la resistenza la colleghi al positivo l'altro piedino del pulsante va collegato al negativo e viceversa. Quando si definisce il pinmode si può abilitare la resistenza interna al positivo (pullup) senza bisogno di metterne una esterna, ma in questo caso essendo il pulsante collegato al negativo quando è premuto sigifica che quando è aperto per arduino il pin è High.
Se abiliti la pullup da pin mode devi quindi cambiare logica di lettura dei pulsanti, quello che prima era:

if(digitalRead(4)){ esegui la if se il pin è High

diventa

if(!digitalRead(4)){ esegue la if se il pin è Low (nota il segno di negazione "!")

Grazie mille a entrambi per i preziosi consigli, pian piano cercherò di capire al meglio tutto quanto in modo in futuro da applicare tutto questo… per intanto ho provato a raddoppiare servo e pulsanti, e siccome nel circuito avevo già previsto resistenze da 10Kohm ho lasciato le istruzioni if(digitalRead(4)){ esegui la if se il pin è High
ecco il codice… può andare ragazzi?

#include <Servo.h> 

//Dichiariamo le costanti e le variabili.
Servo myservoDx;//servomotore Dx con il nome myservoDx.
Servo myservoSx; //servomotore Sx con il nome myservoSx.
int Posizione_Servo=90;

void setup() {
  myservoDx.attach(3);//Impostiamo il pin 3 come pin pwm per il controllo del servo dx.
  pinMode(4, INPUT);//Impostiamo il pin 4 collegato al pulsante sinistro come ingresso.
  pinMode(5, INPUT);//Impostiamo il pin 5 collegato al pulsante destro come ingresso.
  myservoDx.write(Posizione_Servo);//Posiziona il servomotore ad ogni avvio nella posizione 90.

  myservoSx.attach(6);//Impostiamo il pin 6 come pin pwm per il controllo del servo dx.
  pinMode (7,INPUT);//Impostiamo il pin 7 collegato al pulsante sinistro come ingresso.
  pinMode (8,INPUT);//Impostiamo il pin 8 collegato al pulsante destro come ingresso.
  myservoSx.write(Posizione_Servo);//Posiziona il servomotore ad ogni avvio nella posizione 90.
}

//Il programma si ripete in un loop infinito.
void loop() {
        
        
    if(digitalRead(4)){// Se pin pulsante è nello stato HIGH

        Posizione_Servo--; 
        myservoDx.write(Posizione_Servo);
        delay(200); // Attendo che il dito si sposti dal pulsante

        // Tendendo premuto il pulsante incrementa con intervalli di 200 millisecondi
       
          
    }else if(digitalRead(5)){// Se pin pulsante è nello stato HIGH

        Posizione_Servo++; 
        myservoDx.write(Posizione_Servo);
        delay(200); // Attendo che il dito si sposti dal pulsante

        // Tendendo premuto il pulsante incrementa con intervalli di 200 millisecondi
       
       // Aggiungo comandi per secondo servo
    }
        if(digitalRead(7)){// Se pin pulsante è nello stato HIGH

        Posizione_Servo--; 
        myservoSx.write(Posizione_Servo);
        delay(200); // Attendo che il dito si sposti dal pulsante

        // Tendendo premuto il pulsante incrementa con intervalli di 200 millisecondi
      
    }else if(digitalRead(8)){// Se pin pulsante è nello stato HIGH

        Posizione_Servo++; 
        myservoSx.write(Posizione_Servo);
        delay(200); // Attendo che il dito si sposti dal pulsante

        // Tendendo premuto il pulsante incrementa con intervalli di 200 millisecondi
      
    }else if( digitalRead(9)){ // Se premo un pin specifico

         myservoDx.write(90); // porto a posizione 90 servo dx
         myservoSx.write(90); // porto a posizione 90 servo sx
          // se ho due servi copio la riga sopra con un nome diverso per il servo
        delay(200); // Attendo che il dito si sposti dal pulsante
       }
    }

Ciao, il programma in se va bene, ma se vuoi che i due servo possano avere anche posizioni diverse luno
dall'altro, allora devi usare due variabili Posizione_Servo++; e Posizione_Servo2++; ad esempio.

Ricorda di dichiarare a inizio programma

int Posizione_Servo2=90;

Grazie mille, gentilissimo davvero.. non vedo l'ora di testarlo.. :slight_smile:

Ciao, testato ma purtroppo non funziona, appena alimentato i servi si posizionano a 90, poi iniziano a ruotare piano piano a fine corsa e poi stop… posto lo schema di come ho fatto i collegamenti, arduino lo alimento con 9v, mentre i servi sono alimentati a parte con 6v

Ciao, nel programma secondo me non ci sono errori, potrebbero essere problemi nel circuito ma io in elettronica non sono molto esperto.

Il fatto che i servo non devono muoversi se non premi il pulsante, a parte posizionarsi a 90 gradi ad inizio programma.

Per vedere se i pulsanti danno falsi contatti, collega la scheda al computer con usb, nei vai if() dei pulsanti
metti un Serial.println("pulsante nome pulsante"); , se sulla seriale vedi le scritte sai quale pulsante è collegato male e invia segnali ad arduino.

Ricordati che per usare la seriale nel setup devi mettere Serial.begin(9600);

Grazie mille Torn24, sempre gentilissimo... ci provo stasera, caspita spero di risolvere perchè ci serve presto tutto questo marchingegno..

se hai collegato le 4 pile come da schema avrai fuso qualcosa, a parte questo non vedo errori nei collegamenti. Nell'ultimo codice postato manca la definizione con pinmode del piedino 9 ma dubito che possa essere questo il problema. Non è che hai inserito male il pulsante nella breadbord ed è come se fosse sempre premuto?

Si scusa ho visto ora l'errore nello schema, ovviamente no l'alimentatore l'ho collegato giusto :slight_smile:
potrebbe essere, in che senso intendi inserito male in modo che sia sempre premuto?