Offline
Newbie
Karma: 0
Posts: 13
|
 |
« on: January 25, 2013, 01:38:11 pm » |
buonasera a tutti. non so se ho sbagliato sezione del forum, essendo il primo topic che apro. il mio problema è questo, ho applicato ad ARDUINO UNO un sensore IR Sharp2D120X, con questo sensore vorrei fare in modo che il mio servo motore si muova facendo chiudere una specie di gate al passaggio avvenuto di una persona (come un cancello automatico insomma). lo schema di programmazione sarebbe questo: apro il gate tramite pulsante, il sensore rileva il passaggio della persona/macchina chiudo il gate. posto qui il mio programma, sperando in un consiglio su come poter risolvere il problema: //APERTURA A PULSANTE E CHIUSURA CON IR
#include <Servo.h> #include <DistanceGP2Y0A21YK.h>
//variabili IR DistanceGP2Y0A21YK IR; int distFissa; int distVariabile; int pinIR=A5;
//variabili servo Servo gate; int pinGate=3; int pinPul=A0; int pos=0;
void setup(){ pinMode(pinPul, INPUT);//sceglie il pulsante come input nell'uscita A0 IR.begin(pinIR);//attacca l'IR al pin di uscita A5 }
void detachGate(){ gate.detach(); }
void setGatePos(){ gate.attach(pinGate); gate.write(pos); delay(1000); detachGate(); }
void openGate(){ gate.attach(pinGate); for(pos=0;pos<=90;pos++){ gate.write(pos); delay(15); } detachGate(); } void closeGate(){ gate.attach(pinGate); for(pos=90;pos>=0;pos--){ gate.write(pos); delay(15); } detachGate(); } void loop(){ setGatePos(); distFissa=IR.getDistanceCentimeter();
if (analogRead(pinPul)>900){ distVariabile=IR.getDistanceCentimeter(); openGate(); delay(1000); while(distFissa>distVariabile){ delay(1000); distVariabile=IR.getDistanceCentimeter(); if(distVariabile>=distFissa){ closeGate(); } } } //valore max del pulsante = 1023 in attivazione } grazie infinite dell'attenzione.
|
|
|
|
« Last Edit: January 25, 2013, 04:21:57 pm by UweFederer »
|
Logged
|
Neglected emotions lead to catastrophic voyage on the other side. Gojira
|
|
|
|
BZ (I)
Offline
Brattain Member
Karma: 162
Posts: 15760
+39 349 2158303
|
 |
« Reply #1 on: January 25, 2013, 04:27:24 pm » |
Descrivi per favore il problema che hai incontrato.
perplessitá: Perché leggi il pulsante in modo analogico e non digitale? Hai messo una resistenza Pullup o pulldown?
Ciao Uwe
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 13
|
 |
« Reply #2 on: January 25, 2013, 05:22:07 pm » |
problema: non riesco a capire come far abbassare il gate dopo che il soggetto vi passa attraverso. il mio programma non funziona correttamente, dato che va giù a random quando vuole lui.
la resistenza è in pullup e il pulsante l'ho sempre usato così, è sbagliato?
|
|
|
|
|
Logged
|
Neglected emotions lead to catastrophic voyage on the other side. Gojira
|
|
|
|
ivrea (to)
Offline
God Member
Karma: 10
Posts: 647
|
 |
« Reply #3 on: January 25, 2013, 06:01:04 pm » |
Sono anche io neofita di Arduino ma sono un programmatore professionista. scrivi: void loop(){ setGatePos(); distFissa=IR.getDistanceCentimeter(); Ma la funzione loop() viene eseguita di continuo da Arduino. Quei comandi mi sembrano delle funzioni da richiamare solo una prima volta (inizializzazioni), quindi da mettere nella void setup() Poi, cosa vuol dire non riesci a chiudere il gate ? Non ti funziona il servo? Hai provato a comandare il servo senza tanti casini? Ovvero sai comandare il servo con uno sketch semplice semplice senza sensori da cui prendere input? Come alimenti il servo? Alimentando da cavo USB l'Arduino, potresti avere poca corrente 
|
|
|
|
|
Logged
|
|
|
|
|
Marche
Offline
Edison Member
Karma: 25
Posts: 2063
|
 |
« Reply #4 on: January 25, 2013, 06:17:48 pm » |
Un consiglio: abituati ad usare millis() al posto di delay, ne vedo diversi... In questo modo eviti di bloccare tutto il micro, quindi letture del sensore e movimento del servo compresi
|
|
|
|
|
Logged
|
|
|
|
|
ivrea (to)
Offline
God Member
Karma: 10
Posts: 647
|
 |
« Reply #5 on: January 25, 2013, 06:35:38 pm » |
Altro consiglio, il codice dovrebbe essere indentato bene per essere leggibile al primo sguardo. Non sò se il tuo originale era indentato bene, ma quello postato è poco leggibile: void loop() { setGatePos(); distFissa=IR.getDistanceCentimeter(); if (analogRead(pinPul)>900) { distVariabile=IR.getDistanceCentimeter(); openGate(); delay(1000); while(distFissa>distVariabile) { delay(1000); distVariabile=IR.getDistanceCentimeter(); if(distVariabile>=distFissa) { closeGate(); } } // while } //valore max del pulsante = 1023 in attivazione }
|
|
|
|
|
Logged
|
|
|
|
|
ivrea (to)
Offline
God Member
Karma: 10
Posts: 647
|
 |
« Reply #6 on: January 25, 2013, 06:43:22 pm » |
Il problema mi sembra anche di logica di programmazione. Credo tu debba considerare una programmazione utilizzando una variabile di stato. Ovvero una variabile dove 0=fase iniziale, 1=ha premuto il tasto, 2=altro momento. La loop() viene eseguita di continuo. Perciò internamente alla loop secondo me devi usare uno switch() sulla variabile di stato per sapere in quale "momento" sei. void loop() { ... switch(iState) { case 0: ... if(premuto pulsante) iState=1; break; case 1: //premuto il pulsante // allora qui verifico distanza break; case 2: ... } }
Guarda questo libro (purtroppo in inglese): http://books.google.it/books?id=hDUucEEaNLwC&printsec=frontcover&dq=Creating+Cool+MINDSTORMS+NXT+Robots&hl=it&sa=X&ei=yhgDUfjpCIXj4QTyioGoBw&ved=0CC8Q6AEwAAil capitolo 3 parla delle macchine a stato (il tipo italiano ha creato ottimi robot con i lego nxt, programmati in c) su goglebooks sono leggibili i primi 3 capitoli. Il capitolo 3 è sulle macchine di stato. Spero possa esserti di aiuto.
|
|
|
|
« Last Edit: January 25, 2013, 06:47:52 pm by nid69ita »
|
Logged
|
|
|
|
|
BZ (I)
Offline
Brattain Member
Karma: 162
Posts: 15760
+39 349 2158303
|
 |
« Reply #7 on: January 25, 2013, 08:19:53 pm » |
Se hai messo una resistenza pullup e il pulsante tra entrata e massa la condizione del IF nel codice sottostante é vera quando il pulsnate non é premuto e non quando qualcuno lo preme per aprire la porta. Percui la porta resta sempre aperta. Ciao Uwe void loop(){ setGatePos(); distFissa=IR.getDistanceCentimeter();
if (analogRead(pinPul)>900){ distVariabile=IR.getDistanceCentimeter(); openGate(); delay(1000); ...
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 13
|
 |
« Reply #8 on: January 26, 2013, 02:36:25 pm » |
vi ringrazio infinitamente per i consigli, siccome stasera sono di fretta domani e lunedì leggo tutto meglio con calma, faccio tutte le prove e vi saprò dire!!.. non sono esperta per niente, sono una studentessa e sto facendo questo progetto per l'esame di maturità. comunque in risposta a: Sono anche io neofita di Arduino ma sono un programmatore professionista. scrivi: void loop(){ setGatePos(); distFissa=IR.getDistanceCentimeter(); Ma la funzione loop() viene eseguita di continuo da Arduino. Quei comandi mi sembrano delle funzioni da richiamare solo una prima volta (inizializzazioni), quindi da mettere nella void setup() Poi, cosa vuol dire non riesci a chiudere il gate ? Non ti funziona il servo? Hai provato a comandare il servo senza tanti casini? Ovvero sai comandare il servo con uno sketch semplice semplice senza sensori da cui prendere input? Come alimenti il servo? Alimentando da cavo USB l'Arduino, potresti avere poca corrente  il gate si chiude, ma quando vuole lui. ho già programmato il servo più di una volta senza pasticci vari in mezzo di sensori e so per certo che funziona. l'arduino è alimentato esternamente, e faccio girare il programma dopo averlo caricato e staccato il cavo usb da pc.
|
|
|
|
|
Logged
|
Neglected emotions lead to catastrophic voyage on the other side. Gojira
|
|
|
|
BZ (I)
Offline
Brattain Member
Karma: 162
Posts: 15760
+39 349 2158303
|
 |
« Reply #9 on: January 26, 2013, 04:10:02 pm » |
scollega il servo e collega l' arduino al PC tramite USB. Poi metti in alcuni posti un serial.print() per controllare che valori hanno le variabili /lettura dei sensori. Puoi leggerli nel teminale del IDE.
Ciao Uwe
|
|
|
|
|
Logged
|
|
|
|
|
ivrea (to)
Offline
God Member
Karma: 10
Posts: 647
|
 |
« Reply #10 on: January 26, 2013, 05:58:19 pm » |
Come suggerito giustamente da uwefed mi sembra importante mettere un pò di Serial.println per debuggare il progamma. Mettili dopo ogni istruzione (soprattutto nelle istruzioni condizionali) stampando anche il valore delle variabili. nel setup() Serial.begin(9600); Serial.println("Fase 1");
poi nel loop() Serial.println("Fase 2"); setGatePos(); Serial.println("Fase 3"); distFissa=IR.getDistanceCentimeter(); Serial.println("Fase 4 distFissa="); Serial.print(distFissa); newvar=analogRead(pinPul); Serial.println("Fase 5 newvar="); Serial.print(newvar); if (newvar>900) { Serial.println("Fase 5 if vero"); distVariabile=IR.getDistanceCentimeter(); Serial.println("Fase 6 distVariabile="); Serial.print(distVariabile); openGate(); ...etc...
|
|
|
|
|
Logged
|
|
|
|
|
Cagliari
Offline
Faraday Member
Karma: 49
Posts: 3031
|
 |
« Reply #11 on: January 28, 2013, 11:44:47 am » |
Ciao, perchè stacchi il servo dopo averlo mosso?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 13
|
 |
« Reply #12 on: January 28, 2013, 12:01:46 pm » |
Un consiglio: abituati ad usare millis() al posto di delay, ne vedo diversi... In questo modo eviti di bloccare tutto il micro, quindi letture del sensore e movimento del servo compresi
ma millis() non ritorna un valore finito di tempo da quando il programma è partito? non saprei come usarlo al posto di delay() non mi sembra la stessa cosa.
|
|
|
|
|
Logged
|
Neglected emotions lead to catastrophic voyage on the other side. Gojira
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 13
|
 |
« Reply #13 on: January 28, 2013, 12:03:53 pm » |
Ciao, perchè stacchi il servo dopo averlo mosso?
ciao, lo stacco per essere sicura che finita l'azione (se magari ci sono parti di programma che funzionano male) il servo non continui a ruotare magari accumulando tensione e rompendosi. Dici che potrebbe essere sbagliato?
|
|
|
|
|
Logged
|
Neglected emotions lead to catastrophic voyage on the other side. Gojira
|
|
|
|
Forum Moderator
Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« Reply #14 on: January 28, 2013, 12:15:38 pm » |
Un consiglio: abituati ad usare millis() al posto di delay, ne vedo diversi... In questo modo eviti di bloccare tutto il micro, quindi letture del sensore e movimento del servo compresi
ma millis() non ritorna un valore finito di tempo da quando il programma è partito? non saprei come usarlo al posto di delay() non mi sembra la stessa cosa. delay() ti ferma il programma. Il programa non fa nient'altro finché non è passato il tempo prestabilito. Con millis puoi fare la stessa cosa con un semplice if. Guardati lo sketch di esempio allegato all'IDE "Blink Without Delay".
|
|
|
|
|
Logged
|
|
|
|
|
|