Go Down

Topic: Arduino uno,pulsanti e servocomandi (Read 473 times) previous topic - next topic

ClaBos

Jul 11, 2018, 08:49 pm Last Edit: Jul 11, 2018, 09:28 pm by ClaBos
Ciao a tutti.Da poco ho iniziato a leggere riguardo Arduino e la settimana scorsa mi sono preso un kit Arduino uno perchè vorrei utilizzarlo nel mio plastico ferroviario.

Il mio progetto sarebbe quello di comandare 4 o 6 servocomandi tramite relativi pulsanti.

I servocomandi,indipendenti tra loro nel funzionamento,dovranno muoversi alcuni gradi sia in un senso che nell'altro.

Ho trovato alcuni sketch e alcuni esempi ma non mi aggradano molto.

Io vorrei che premendo una sola volta il pulsante il servo vada da una posizione,ipotesi 0 gradi fino all'altra,ipotesi 40 gradi ma senza dover star li a tenere premuto il pulsante.

Come posso procedere?

Avrei trovato questo schema ma non saprei ne come poter aggiungere altri servi (a quali pin collegarli) ne come modificare lo sketch originale....




Code: [Select]
[code]
/* controllo servo con un pulsante e indicatore led */
/* sal727 */

#include <Servo.h>
const int servoPin = 8; // Servo pin
const int led1 = 11; // led1 pin
const int led2 = 12; // led2 pin
const int buttonPin = 9; // Pushbutton pin
int buttonState = 0; // imposta variabile pulsante
int directionState = 0; // imposta variabile direzione
Servo servo; // dichiara il servo
int pos = 45; // imposta i gradi del servo

void setup() {
  servo.write(pos); // stato iniziale del servo
  servo.attach(8);
  pinMode(buttonPin, INPUT); // imposta il pulsante come INPUT
  pinMode(led1, OUTPUT); // imposta il led1 come INPUT
  pinMode(led2, OUTPUT); // imposta il led2 come INPUT
  digitalWrite(led1, HIGH); // stato iniziale del led uguale a quello del servo
}

void loop() {
  buttonState = digitalRead(buttonPin); // leggi lo stato del pulsante
  if (directionState == 0) { // se direzione è 0 ed il pulsante premuto
    if (buttonState == HIGH) {
      directionState = 1; // la direzione va a 1
      for (pos = 45; pos < 135; pos += 1) // parte da 45° fino a 135° i9ncremen tata di 1
      {
        digitalWrite(led1, LOW); // led1 spento
        digitalWrite(led2, HIGH); // led2 acceso
        servo.write(pos);
        delay(15); // aspetta 15ms per raggiungere la posizione

      }
    }

  } else if (directionState == 1) { // se invece la direzione è a 1 ed ilpulsante premuto
    if (buttonState == HIGH) {
      directionState = 0; // la direrzione ritorna a 0

      for (pos = 135; pos >= 45; pos -= 1) // riparte da 135° e torna a 45° scalata di 1
      {
        digitalWrite(led1, HIGH); // led1 acceso
        digitalWrite(led2, LOW); // led2 spento
        servo.write(pos);
        delay(15); // aspetta 15ms per raggiungere la posizione
      }
    }
  }
}
[/code]

gpb01

#1
Jul 11, 2018, 08:57 pm Last Edit: Jul 11, 2018, 08:57 pm by gpb01
>ClaBos:   ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo
Search is Your friend ... or I am Your enemy !

gpb01

... inoltre, se dall'IDE prendi il tuo programma è usi la funzione Tools -> Auto format ... avrai il codice sistemato ed indentato come si deve dato che, così come è ora ... è molto poco leggibile !

Guglielmo
Search is Your friend ... or I am Your enemy !

ClaBos

Chiedo scusa per il mio errore nell'apertura del post...ho modificato sperando di aver fatto le cose per bene.

krypton18

#4
Jul 11, 2018, 10:16 pm Last Edit: Jul 12, 2018, 12:11 am by krypton18
Quote
Avrei trovato questo schema ma non saprei ne come poter aggiungere altri servi (a quali pin collegarli) ne come modificare lo sketch originale....
Aggiungere ulteriori servo nel software:

Code: [Select]
#include <Servo.h>
const int servo1Pin = 8; //Servo1 collegato a PIN 8
const int servo2Pin = 7; //Servo2 collegato a PIN 7

Servo servo1; //Creazione oggetto servo1
Servo servo2; //Creazione oggetto servo2

void setup() {

  servo1.attach(servo1Pin); //servo1 è collegato all'indirizzo di PIN contenuto in servo1Pin
  servo2.attach(servo2Pin); //servo2 è collegato all'indirizzo di PIN contenuto in servo2Pin

...
}


I servo, non si dice servi (della gleba :D), li puoi collegare ai PIN digitali restanti ed eventualmente sfruttare anche i PIN analogici A0, A1 ecc. come PIN digitali. Vedo che come I/O digitali nativi hai a disposizione i PIN da 0 a 7, 10 e 13. Sta a te decidere dove collegarli e ad assegnarli correttamente nel software. Se non sai come farlo, leggi la Arduino reference al capitolo Digital I/O (pinMode, digitalRead, digitalWrite). https://www.arduino.cc/reference/en/

Quote
Io vorrei che premendo una sola volta il pulsante il servo vada da una posizione,ipotesi 0 gradi fino all'altra,ipotesi 40 gradi ma senza dover star li a tenere premuto il pulsante.
Se vuoi usare dei pulsanti veri e propri, e non dei selettori ON/OFF, dovrai intercettare il fronte di salita della premuta del pulsante ed eseguire la movimentazione del motore quando si verifica il fronte. Ti scrivo in pseudocodice, da tradurre nel linguaggio C comprensibile ad Arduino, come intercettare il fronte di salita:

Code: [Select]

bool pulsanteServo1 = LOW;
bool fronteSalitaServo1 = LOW;
bool statoPrecServo1 = LOW;

void setup() {
 ...
 }

void loop() {

pulsanteServo1 = leggi(indirizzo_pin_pulsanteServo1)
 
fronteSalitaServo1 = pulsanteServo1 AND NOT statoPrecServo1

statoPrecServo1 = pulsanteServo1;

IF fronteSalitaServo1 THEN movimentazione servo1


Di quest'ultimo argomento ne ho parlato in una discussione di qualche giorno fa dove ho fornito maggiori dettagli: Funzione Auto Manuale

edit: ho trovato un tutorial ufficiale su Arduino.cc sul rilevamento dei fronti di salita
StateChangeDetection

gpb01

... aggiungo solo una cosa ... prevdere un alimentatore esterno per alimentare i vari servo, in quanto il pin +5V di Arduino NON è certo in grado di alimentare 5 o 6 servo (in realtà neanche uno di quelli "seri" :smiley-mr-green:).  Ovviamnete il GND di tale alimentatore esterno dovrà essere in comune con il GND di Arduino.


Guglielmo
Search is Your friend ... or I am Your enemy !

ClaBos

Grazie mille per i preziosi consigli e per le guide da leggere.

Mentre cercavo su internet guide a destra e a manca mi sono imbattuto nel sito di uno che ha utilizzato un servo (sta volta l'ho scritto corretto :) ) per un suo test e utilizzava la funzione che stavo cercando io..ovvero,premo una volta e il servo ruota.





Code: [Select]
#include <Servo.h>
 const int servoPin = 8;  // Servo pin
 const int buttonPin = 9;  // Pushbutton pin
 int buttonState = 0;
 int directionState = 0;
 Servo myservo;
 int pos = 0;
 
void setup() {
   myservo.attach(8);
   pinMode(buttonPin, INPUT);
 }

 void loop(){
   buttonState = digitalRead(buttonPin);
   if (directionState == 0){
     if (buttonState == HIGH) {
       directionState = 1;
       for(pos = 0; pos < 180; pos += 1)
       {
         myservo.write(pos); 
         delay(15);  // waits 15ms to reach the position
       }
     }

   } else if (directionState == 1) {
     if (buttonState == HIGH) {
       directionState = 0;   
       
      for (pos = 180; pos>=1; pos -=1)
       {
         myservo.write(pos);
         delay(15);
       }
     }
   }
 }



Con questo progetto potrei pilotare 4 servocomandi però perderei sicuramente i led che mi indicano la posizione.

Credete sia possibile implementarli a quest'ultimo esempio che vi ho mostrato?

Silente

Non vedo perché perderesti i led. Da quanto riesco a vedere tu colleghi solo poche uscite (3 digitali+ forse 3 analogiche). Le altre 13-2seriale-3usate uscite digitali, vale a dire 8 uscite digitali, restano libere. A te ne servono sei, quindi lato hw si può fase.
Quanto al listato credo si possa farlo, e facilmente. Basta sapere come si vogliono accendere i led (in quali condozioni, se accesi o lampeggianti...) e sapere cosa fa il programma.
Dove va un numero va una variabile o una funzione. E dove va una boolean va un insieme di test.

Se vuoi ottenere devi saper spiegare

In pochi capiscono l'importanza di formattare, sii tra di essi

Silente

Ma poi, ora che vedo, nel codice hai UN servo, non quattro. Sicuro che sia quello giusto?
Dove va un numero va una variabile o una funzione. E dove va una boolean va un insieme di test.

Se vuoi ottenere devi saper spiegare

In pochi capiscono l'importanza di formattare, sii tra di essi

krypton18

#9
Jul 14, 2018, 10:26 pm Last Edit: Jul 14, 2018, 10:38 pm by krypton18
Quote
Mentre cercavo su internet guide a destra e a manca mi sono imbattuto nel sito di uno che ha utilizzato un servo (sta volta l'ho scritto corretto :) ) per un suo test e utilizzava la funzione che stavo cercando io..ovvero,premo una volta e il servo ruota.
Ma quel programma l'hai provato?  Sono molto dubbioso che possa svolgere la funzione da te descritta. Seguendo la logica del codice, se premi il pulsante il servo gira di continuo e si ferma quando rilasci il pulsante. Non è un tipo di movimentazione a singoli impulsi.
Quote
Con questo progetto potrei pilotare 4 servocomandi però perderei sicuramente i led che mi indicano la posizione.
Posizione o direzione (senso di rotazione) ??! C'è una differenza abissale. Nel caso della posizione due LED ti possono indicare, al massimo, il raggiungimento di una posizione iniziale o finale.
Quote
Credete sia possibile implementarli a quest'ultimo esempio che vi ho mostrato?
E' possibile se intanto segui il consiglio di Guglielmo di usare un alimentatore dedicato ai servo, poi visto che vuoi montare un numero di LED relativamente alto devi prevedere l'uso di transistor per limitare la corrente erogata da Arduino. Cioè fra il PIN di Arduino e la serie resistenza/LED, va interposto un transistor il cui collettore riceve corrente da un alimentatore esterno, eventualmente lo stesso dei servo.

pgiagno

Ho aggiunto alcune istruzioni al programma che hai postato. Come dice giustamente kripton18 viene intercettata SOLO la pressione del pulsante (digitalRead(buttonPin)=HIGH) e non il suo rilascio.

Code: [Select]
/* Questo programma posiziona un servo e accende due led alla pressione di un pulsante
 * All'inizio il servo è posizionato a 0°, li led 1 è acceso e il led2 è spento
 * Premendo il pulsante una prima volta il servo si porta a 180°, il led 1 si spegne e il led2 si accende
 * Premendo il pulsante una seconda volta il servo si porta a 0°, il led 1 si accende e il led2 si spegne
 * E così via
 */

#include <Servo.h>
const int servoPin = 8;  // Servo pin
const int buttonPin = 9;  // Pushbutton pin
//--inserito {
const int led1 = 11; // led1 pin
const int led2 = 12; // led2 pin
//---------- }
int buttonState = 0;
int directionState = 0;
Servo myservo;
int pos = 0;
 
void setup() {
  myservo.attach(8);
  pinMode(buttonPin, INPUT);
//--inserito {
  myservo.write(pos); // stato iniziale del servo
  pinMode(led1, OUTPUT); // imposta il led1 come OUTPUT
  pinMode(led2, OUTPUT); // imposta il led2 come OUTPUT
  digitalWrite(led1, HIGH); // stato iniziale del led uguale a quello del servo
  digitalWrite(led2, LOW);
//---------- }
 }

 void loop(){
   buttonState = digitalRead(buttonPin);
   if (directionState == 0){
     if (buttonState == HIGH) {
       directionState = 1;
       for(pos = 0; pos < 180; pos += 1)
       {
         myservo.write(pos); 
         delay(15);  // waits 15ms to reach the position
       }
//--inserito {
       digitalWrite(led1, LOW);
       digitalWrite(led2, HIGH);
//---------- }
     }

   } else if (directionState == 1) {
     if (buttonState == HIGH) {
       directionState = 0;   
       for (pos = 180; pos>=1; pos -=1)
       {
         myservo.write(pos);
         delay(15);
       }
//--inserito {
       digitalWrite(led1, HIGH);
       digitalWrite(led2, LOW);
//---------- }
     }
   }
 }


Il servo impiega circa 2,7 secondi per portarsi alla sua posizione finale, perché hai inserito il delay di 15ms ALL'INTERNO del ciclo di for, e quindi viene ripetuto per 179 volte (15*179=2685). Se il pulsante viene rilasciato PRIMA dei 2,7s sembra che tutto funzioni, ma se lo tieni premuto per PIU' di 2,7s il servo va su e giù e i led si accendono e spengono di conseguenza.

Per un funzionamento corretto è necessario intercettare anche IL RILASCIO del pulsante fra una pressione e l'altra.

Attenzione in questo caso al RIMBALZO dei contatti meccanici del pulsante.

Ciao,
P.

P.S. il programma NON L'HO PROVATO, mi sono limitato alla compilazione corretta.

ClaBos

Ancora grazie di avermi risposto.
Purtroppo non ho ancora provato nulla perché sto aspettando che mi arrivi la breadboard per fare i test.

Al momento, con poco tempo a disposizione, sto cercando di capire le basi di Arduino.

Purtroppo di programmazione ne so meno di zero e di questo me ne scuso.


Per ora i miei dubbi sono:nell'ipotesi di poter collegare 4 servocomandi con relativi 8 led, quali sono i pin da usare?

Se al posto del pulsante, a questo punto, volessi mettere 4 interruttori a levetta dovrei cambiare totalmente lo sketch o basterebbe modificarlo?

krypton18

#12
Jul 17, 2018, 10:29 pm Last Edit: Jul 17, 2018, 11:43 pm by krypton18
Quote
Al momento, con poco tempo a disposizione, sto cercando di capire le basi di Arduino.
Hai fatto bene a privilegiare l'apprendimento piuttosto che il fare senza capire.
Quote
Purtroppo di programmazione ne so meno di zero e di questo me ne scuso.
Siamo tutti qui per imparare.
Quote
Per ora i miei dubbi sono:nell'ipotesi di poter collegare 4 servocomandi con relativi 8 led, quali sono i pin da usare?
Non ci sono particolari vincoli. Tieni presente che i PIN disponibili per gli I/O digitali vanno dallo 0 al 13. I pin 0, 1 (gestione seriale) e 13 (collegato al LED integrato) sono un po' diversi dagli altri. Se pensi di non usare la seriale (PIN 0 e 1) e non ti interessa se il LED inegrato si accende (pin 13), li si può tranquillamente usare. Se poi non ti bastano, perché in futuro prevedi di aggiungere altri I/O, e non ti servono ingressi analogici, hai la scorta dei 6 PIN analogici che si possono riassegnare come digitali (A0-A5).
https://www.arduino.cc/en/Tutorial/AnalogInputPins
Quote
Se al posto del pulsante, a questo punto, volessi mettere 4 interruttori a levetta dovrei cambiare totalmente lo sketch o basterebbe modificarlo?
Si può modificare. Con gli interruttori, se ti risulta difficile l'uso dei fronti di salita come li ho descritti in precedenza, puoi memorizzare l'attivazione del selettore su ON con una variabile, detta in gergo flag, che si riazzera quando commuti il selettore su OFF. Il flag ti permette di eseguire il movimento completo, una volta sola, alla commutazione su ON. Esempio:

Code: [Select]

bool flag = false;

void loop(){
buttonState = digitalRead(buttonPin);

if (buttonState == LOW) flag = false;

if (buttonState == HIGH && flag == false) {
movimentazione motore
flag = true;
}

...................eccetera..................


La variabile "flag" viene usata come variabile di test, insieme a buttonState, per fare la movimentazione del motore.

edit: ho modificato l'esempio, avevo messo delle condizioni non corrette. Presta anche attenzione al fatto che devi adattare l'esempio al tuo programma.

ClaBos

Entro fine settimana faccio un po' di compilazione di sketch e faccio i test a video per vedere cosa ne esce fuori.

Go Up