Go Down

Topic: Pilotare due motori passo passo in base a due sensori IR (Read 1 time) previous topic - next topic

Sergio_A

Salve,
sto realizzando un piccolo robottino mosso da due motori passo passo (NEMA 17 Wantai Mod.42BYGHW609-X) comandati da Arduino UNO e due driver Easy Driver v.4.4, in funzione di due piccoli sensori IR per gli ostacoli a destra e sinistra.
Sono abbastanza autonomo per quanto riguarda l'elettronica, ma quando riguarda la programmazione sono un po' indietro con gli studi e la tentazione della rete e grande... quindi leggendo qua e là sono riuscito a trovare un vecchio progetto che ho adattato al mio.
Lo sketch che sto usando permette anche una comunicazione seriale dove si può vedere se il dispositivo si è acceso correttamente, se rileva gli ostacoli o se ha via libera.
Credo, a parte alcuni passaggi, di aver compreso abbastanza lo sketch e di non trovare nessun errore.
Ecco il codice e in allegato lo schema:

Code: [Select]
#define DIRD 2         //direzione motore destra
#define STEPD 3        //pin di step motore destra
#define IRD 4          //sensore IR a destra
#define DIRS 5         //direzione motore sinistra
#define STEPS 6        //pin di step motore sinistra
#define IRS 7          //sensore IR sinistra
#define LAMA 8         //rele di controllo motore lama
#define INTERVALLO 10  //durata del movimento generale
 
int rilevamentoD = HIGH;
int rilevamentoS = HIGH;

int ritorno = 100;     //durata della rotazione senza controllare nuovamente (variabile perche nel programma il robot potra adattarlo in base alle condizioni)

int i;

void setup()
 {
  Serial.begin(9600);  //inizio della trasmissione seriale (serve soprattutto a noi per capire a che punto del programma si trova)
  Serial.print("Mi sono acceso correttamente.");
  delay(500);

  pinMode(DIRD, OUTPUT);
  pinMode(STEPD, OUTPUT);
  pinMode(IRD, INPUT);
  pinMode(DIRS, OUTPUT);
  pinMode(STEPS, OUTPUT);
  pinMode(IRS, INPUT);
  pinMode(LAMA, OUTPUT);
 }
 
void step(boolean dirAttualeD, boolean dirAttualeS, int steps)
{
  digitalWrite(DIRD, dirAttualeD); //invia al driver destro la direzione attuale
  digitalWrite(DIRS, dirAttualeS); //invia al driver sinistro la direzione attuale
  for(int i=0; i<steps; i++)       //ATTENZIONE: durante il ciclo non controlla i sensori!
  {
    digitalWrite(STEPD, HIGH);
    delay(1.2);
    digitalWrite(STEPS, LOW);
    delay(1.2);
    digitalWrite(STEPD, LOW);
    delay(1.2);
    digitalWrite(STEPS, HIGH);
    delay(1.2);
  }
}
 
void loop()
{
  rilevamentoD = digitalRead(IRD); //rileva la condizione del sensore destro
  rilevamentoS = digitalRead(IRS); //rileva la condizione del sensore sinistro
if(rilevamentoD == HIGH && rilevamentoS == HIGH) //se sentrambi non rilevano ostacoli
{
   Serial.print("\nVia libera!");
   step(true, false, INTERVALLO); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso discorde manderanno avanti o indietro il robot!
}
else
{
  if(rilevamentoD == LOW) //se il sensore destro rileva un ostacolo
  {
    Serial.print("\nOstacolo a destra!");
    for(i=0; i<ritorno; i++) //ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
    {
    step(false, false, INTERVALLO); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso concorde faranno ruotare il robot!
    }
 }
 if(rilevamentoS == LOW) //se il sensore sinistro rileva un ostacolo
 {
    Serial.print("\nOstacolo a sinistra!");
    for(i=0; i<ritorno; i++) //ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
    {
    step(true, true, INTERVALLO); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso concorde faranno ruotare il robot!
    }
 }  
}
}


Da seriale Arduino mi dice che è tutto ok (quando i sensori non sono oscurati "via Libera";Sensore destro oscurato "ostacolo a destra"; sensore sinistro oscurato "ostacolo a sinistra"). Tuttavia Arduino impegna solo un motore passo passo in modo corretto, cioè fa cambiare la rotazione quando il sensore corretto è oscurato. L'altro motore rimane perennemente fermo.

Ho voluto testare tutti i componenti hardware singolarmente per avere la certezza della loro integrità (driver motori e motori); tutto ok.

La cosa che mi è sconosciuta è la parte dello cketch che dice:

Code: [Select]
void step(boolean dirAttualeD, boolean dirAttualeS, int steps)

Ringrazio anticipatamente e attendo con pazienza qualsiasi suggerimento.




 

PaoloF_60

Ciao Sergio

Se lo schema rispecchia i collegamenti fatti hai invertito i segnali step e dir del motore sinistro
pin 5 e 6 di arduino. Se quello è il motore che non gira credo che il problema sia li.

Code: [Select]


void step(boolean dirAttualeD, boolean dirAttualeS, int steps)
{
  digitalWrite(DIRD, dirAttualeD); //invia al driver destro la direzione attuale
  digitalWrite(DIRS, dirAttualeS); //invia al driver sinistro la direzione attuale
  for(int i=0; i<steps; i++)       //ATTENZIONE: durante il ciclo non controlla i sensori!
  {
    digitalWrite(STEPD, HIGH);
    delay(1);//modificata la delay accetta valori unsigned long
    digitalWrite(STEPS, HIGH);//modificata
    delay(1);
    digitalWrite(STEPD, LOW);
    delay(1);
    digitalWrite(STEPS, LOW);//modificata
    delay(1);
  }
}



la funzione esegue x passi (steps) sui due motori nella direzione indicata dai valori
direzione attuale dx sx

il passo viene comandato da transizione low - high - low di step

vedi immagine allegata




Sergio_A

Grazie Newbie,
non so come ho fatto ad incaponirmi cosi tanto sullo sketch ed aver commesso un errore cosi grossolano.
Approfondirò la mia conoscenza sulla funzione da te spiegatami.

Grazie mille!!

Sergio_A

Scusa... nella fretta ho sbagliato a ringraziare.. volevo scrivere "Grazie PaoloF_60"!!  :smiley-confuse:

Sergio_A

Tutto adesso funziona correttamente e volevo così riallegare lo schema aggiornato.
Ho ancora due perplessità:
1. Velocità motori; la parte dello sketch che riguarda tale argomento è:

Code: [Select]
void step(boolean dirAttualeD, boolean dirAttualeS, int steps)
{
  digitalWrite(DIRD, dirAttualeD); //invia al driver destro la direzione attuale
  digitalWrite(DIRS, dirAttualeS); //invia al driver sinistro la direzione attuale
  for(int i=0; i<steps; i++)       //ATTENZIONE: durante il ciclo non controlla i sensori!
  {
    digitalWrite(STEPD, HIGH);
    delay(1.2);
    digitalWrite(STEPS, LOW);
    delay(1.2);
    digitalWrite(STEPD, LOW);
    delay(1.2);
    digitalWrite(STEPS, HIGH);
    delay(1.2);


Diminuendo i delay aumento la velocità... giusto?
Ho provato quindi a diminuire questo valore fino ad "1" ed effettivamente la velocità e un po' aumentata che però rimane comunque molto bassa. Come posso aumentare la velocità di tali motori?

2.Easy Driver v.4.4 (driver motore passo passo): E' normale che tale integrato A3967SLB scaldi cosi
   tanto? Ho letto il data sheet il quale definisce una Junction Temperature di +150°; se non ho capito
   male questo integrato può arrivare a tale temperatura senza dannegiarsi? (forse qui non sono nella
   sezione giusta, vi prego di scusarmi).

Grazie

PaoloF_60

Ti ho inserito alcune modifiche ed ho aggiunto una variabile velo per la velocità
calcolata come ritardo in microsecondi fra uno step e l' altro.
I motori passo passo sono generalmente 200 step giro ma probabilmente il tuo
modulo è impostato a 1/8 step quindi ci vogliono 1600 step per un giro completo.
Ho cambiato il valore di INTERVALLO da 10 a 8 che moltiplicato il Valore di RITORNO 100
da appunto mezzo giro motore ogni controllo sensore che viene fatto ogni mezzo giro.
La velocità è impostata a 10 su un massimo di 100 per cui al momento il motore fa un giro
al secondo circa 1,024 secondi per la precisione. Se la porti a 100 farà un giro in 100mS circa.
Può essere più veloce valori velo da 1 a 400 a 400 raggiungi il limite di Arduino sulla risoluzione
della funzione delayMicroseconds che per valori inferiori a 8 ha dei problemi.
Prova così e facci sapere leggi le note aggiunte. Ti ho spostato la funzione step sotto la loop.

Per quanto riguarda il riscaldamento del componente ha un limitatore di corrente interno che
dovrebbe impedirgli di danneggiarsi, temperature dell' ordine dei 50 60 gradi sono normali.

Dovrebbe esserci un trimmer per regolare la corrente massima negli avvolgimenti motore.

Vedi Tp1 sullo schema. Penso che tu abbia JP5 JP6 JP7 chiusi. Se così non fosse allora
non è più come si è detto in partcolare Jp5 e Jp6 stabiliscono il funzionamento del driver

Table 1.  Microstep Resolution Truth Table
MS1     MS2     Resolution
  L         L        Full step (2 phase)
  H         L        Half step
  L         H        Quarter step
  H         H        Eighth step

Code: [Select]


#define DIRD 2         //direzione motore destra
#define STEPD 3        //pin di step motore destra
#define IRD 4          //sensore IR a destra
#define DIRS 5         //direzione motore sinistra
#define STEPS 6        //pin di step motore sinistra
#define IRS 7          //sensore IR sinistra
#define LAMA 8         //rele di controllo motore lama
#define INTERVALLO 8   //durata del movimento generale 8 * 100 (ritorno) = 800 passi per 1/2 giro ritorno = 200 per un giro completo
 
int rilevamentoD = HIGH;
int rilevamentoS = HIGH;

int ritorno = 100;//durata della rotazione senza controllare nuovamente (variabile perche nel programma il robot potra adattarlo in base alle condizioni)
int velo=10;//velocita movimento da 1 a 100 ritardo step successivi
int i;

void setup()
 {
  Serial.begin(9600);  //inizio della trasmissione seriale (serve soprattutto a noi per capire a che punto del programma si trova)
  Serial.print("Mi sono acceso correttamente.");
  delay(500);

  pinMode(DIRD, OUTPUT);
  pinMode(STEPD, OUTPUT);
  pinMode(IRD, INPUT);
  pinMode(DIRS, OUTPUT);
  pinMode(STEPS, OUTPUT);
  pinMode(IRS, INPUT);
  pinMode(LAMA, OUTPUT);
 }
 
void loop() {
  rilevamentoD = digitalRead(IRD); //rileva la condizione del sensore destro
  rilevamentoS = digitalRead(IRS); //rileva la condizione del sensore sinistro
  if(rilevamentoD == HIGH && rilevamentoS == HIGH) { //se sentrambi non rilevano ostacoli

    Serial.print("\nVia libera!");
    for(i=0;i<ritorno;i++) {//aggiunta perchè mancante quando va dritto
      step(true, false, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso discorde manderanno avanti o indietro il robot!
   }
  }
  else {
    if(rilevamentoD == LOW) {//se il sensore destro rileva un ostacolo
      Serial.print("\nOstacolo a destra!");
      for(i=0; i<ritorno; i++) {//ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
        step(false, false, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso concorde faranno ruotare il robot!
      }
    }
    if(rilevamentoS == LOW) {//se il sensore sinistro rileva un ostacolo
      Serial.print("\nOstacolo a sinistra!");
      for(i=0; i<ritorno; i++) {//ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
        step(true, true, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso concorde faranno ruotare il robot!
      }
    } 
  }
}

void step(boolean dirAttualeD, boolean dirAttualeS, int steps,int velo) {//velo 1 ... 100
  digitalWrite(DIRD, dirAttualeD); //invia al driver destro la direzione attuale
  digitalWrite(DIRS, dirAttualeS); //invia al driver sinistro la direzione attuale
  for(int i=0; i<steps; i++) {//ATTENZIONE: durante il ciclo non controlla i sensori!
    digitalWrite(STEPD, HIGH);
    digitalWrite(STEPS, HIGH);
    delayMicroseconds(3200/velo);//doppio ritardo fra step min 32uS puo' essere abbassato fino a 8uS
    digitalWrite(STEPD, LOW);
    digitalWrite(STEPS, LOW);
    delayMicroseconds(3200/velo);//doppio ritardo fra step min 32uS puo' essere abbassato fino a 8uS
  }
}


Sergio_A

Grazie Paolo,
adesso la velocità è decisamente più modulabile alle mie esigenze.

Ho fatto diverse prove sulle impostazioni di "velo" e sono arrivato ad una velocità massima di 30 oltre a quel valore uno dei motori si blocca; la velocità che hai impostato tu di un giro al secondo è più che sufficiente per il mio progettino.
C'è solo un piccolo inconveniente:
. Se il sensore di destra individua un ostacolo il motore di destra  inverte la rotazione (OK, giro a destra);
. Se il sensore di sinistra individua un ostacolo il motore di sinistra inverte la rotazione (OK, giro a sinistra);
. Se ambedue i sensori individuano un ostacolo ambedue i motori dovrebbero cambiare la rotazione (OK,
  retromarcia) ma invece invertono la rotazione alternativamente con un ritardo di mezzo secondo circa
  (Avanti e Indietro frequenza mezzo secondo circa).

Farò alcuni tentativi per capire il motivo e se riesco ad anticiparti per me sarà una vittoria!!  :)

Per quanto riguarda i driver ho abbassato i trimmer TP1 e la temperatura si è decisamente abbassata.
Non ho capito però che cosa intendi per "chiusi" quando parli dei contatti JP5 e JP6.

GRAZIE MILLE



PaoloF_60

Quote
. Se ambedue i sensori individuano un ostacolo ambedue i motori dovrebbero cambiare la rotazione (OK,
  retromarcia) ma invece invertono la rotazione alternativamente con un ritardo di mezzo secondo circa
  (Avanti e Indietro frequenza mezzo secondo circa).


in effetti non è contemplata nel tuo sketch

Code: [Select]


void loop() {
  rilevamentoD = digitalRead(IRD); //rileva la condizione del sensore destro
  rilevamentoS = digitalRead(IRS); //rileva la condizione del sensore sinistro
  if(rilevamentoD == HIGH && rilevamentoS == HIGH) { //se sentrambi non rilevano ostacoli

    Serial.print("\nVia libera!");
    for(i=0;i<ritorno;i++) {//aggiunta perchè mancante quando va dritto
      step(true, false, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso discorde manderanno avanti o indietro il robot!
   }
  }
  else {
    if(rilevamentoD == LOW && rilevamentoS == LOW) {//se entrambi rilevano ostacoli retromarcia
      Serial.print("\nRetromarcia!");
      //aggiungi tu la parte mancante
    }
   
    if(rilevamentoD == LOW) {//se il sensore destro rileva un ostacolo
      Serial.print("\nOstacolo a destra!");
      for(i=0; i<ritorno; i++) {//ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
        step(false, false, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso concorde faranno ruotare il robot!
      }
    }
    if(rilevamentoS == LOW) {//se il sensore sinistro rileva un ostacolo
      Serial.print("\nOstacolo a sinistra!");
      for(i=0; i<ritorno; i++) {//ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
        step(true, true, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso concorde faranno ruotare il robot!
      }
    } 
  }
}




aggiungi ciò che manca io intanto cerco e documento il resto.

PaoloF_60

Quote
Non ho capito però che cosa intendi per "chiusi" quando parli dei contatti JP5 e JP6.

fonte informazioni

https://www.futurashop.it/easy-driver-passo-passo-stepper-6168-easydriver

Mi sono sbagliato ... nessun ponticello da chiudere i segnali ms1 e ms2 sono già a vcc con pullup.
Come si vede da schema allegato.

http://www.schmalzhaus.com/EasyDriver/

http://bildr.org/2011/06/easydriver/



Sergio_A

Grazie Paolo,

grazie al tuo suggerimento sono riuscito a partorire questa modifica allo sketch (perdona il ritardo, ma tra Pasqua ed impegni vari...):

Code: [Select]
#define DIRD 2         //direzione motore destra
#define STEPD 3        //pin di step motore destra
#define IRD 4          //sensore IR a destra
#define DIRS 5         //direzione motore sinistra
#define STEPS 6        //pin di step motore sinistra
#define IRS 7          //sensore IR sinistra
#define LAMA 8         //rele di controllo motore lama
#define INTERVALLO 8   //durata del movimento generale 8 * 100 (ritorno) = 800 passi per 1/2 giro ritorno = 200 per un giro completo
 
int rilevamentoD = HIGH;
int rilevamentoS = HIGH;

int ritorno = 100;//durata della rotazione senza controllare nuovamente (variabile perche nel programma il robot potra adattarlo in base alle condizioni)
int velo=10;//velocita movimento da 1 a 100 ritardo step successivi
int i;

void setup()
 {
  Serial.begin(9600);  //inizio della trasmissione seriale (serve soprattutto a noi per capire a che punto del programma si trova)
  Serial.print("Mi sono acceso correttamente.");
  delay(500);

  pinMode(DIRD, OUTPUT);
  pinMode(STEPD, OUTPUT);
  pinMode(IRD, INPUT);
  pinMode(DIRS, OUTPUT);
  pinMode(STEPS, OUTPUT);
  pinMode(IRS, INPUT);
  pinMode(LAMA, OUTPUT);
 }
 
void loop() {
  rilevamentoD = digitalRead(IRD); //rileva la condizione del sensore destro
  rilevamentoS = digitalRead(IRS); //rileva la condizione del sensore sinistro
 
    if(rilevamentoD == HIGH && rilevamentoS == HIGH) { //se sentrambi non rilevano ostacoli
      Serial.print("\nVia libera!");
      for(i=0;i<ritorno;i++) {//aggiunta perchè mancante quando va dritto
        step(true, false, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso discorde manderanno avanti o indietro il robot!
   }
  }
  else {
    if(rilevamentoD == LOW && rilevamentoS == HIGH) {//se il sensore destro rileva un ostacolo
      Serial.print("\nOstacolo a destra!");
      for(i=0; i<ritorno; i++) {//ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
        step(false, false, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso concorde faranno ruotare il robot!
      }
    }
    if(rilevamentoS == LOW && rilevamentoD == HIGH) {//se il sensore sinistro rileva un ostacolo
      Serial.print("\nOstacolo a sinistra!");
      for(i=0; i<ritorno; i++) {//ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
        step(true, true, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi le rotazioni in senso concorde faranno ruotare il robot!
      }
    }
    if(rilevamentoS == LOW && rilevamentoD == LOW) {//se il sensore sinistro rileva un ostacolo
      Serial.print("\nRetromarcia!");
      for(i=0; i<ritorno; i++) {//ripeti ritorno-1 volte la funzione senza ricontrollare i sensori
        step(false, true, INTERVALLO,velo); //ATTENZIONE: i motori sono opposti sullo stesso asse quindi faranno indietreggiare il robot!
      }
    } 
  }
}

void step(boolean dirAttualeD, boolean dirAttualeS, int steps,int velo) {//velo 1 ... 100
  digitalWrite(DIRD, dirAttualeD); //invia al driver destro la direzione attuale
  digitalWrite(DIRS, dirAttualeS); //invia al driver sinistro la direzione attuale
  for(int i=0; i<steps; i++) {//ATTENZIONE: durante il ciclo non controlla i sensori!
    digitalWrite(STEPD, HIGH);
    digitalWrite(STEPS, HIGH);
    delayMicroseconds(3200/velo);//doppio ritardo fra step min 32uS puo' essere abbassato fino a 8uS
    digitalWrite(STEPD, LOW);
    digitalWrite(STEPS, LOW);
    delayMicroseconds(3200/velo);//doppio ritardo fra step min 32uS puo' essere abbassato fino a 8uS
  }
}


Quindi adesso funziona tutto regolarmente.
Adesso mi darò all'Hardware per creare un prototipo su carrello con le ruote che poggiano a terra per vedere nella realtà come si comporterà il Robot. Ovviamente posterò tutti gli sviluppi.

Grazie

PaoloF_60

unica cosa che non ti ho indicato evitare di fare destra e sinistra se già vai indietro

intendo che la if diventa

if avanti ok
  vado avanti
else
  if indietro ok
    vado indietro
  else
    if destra no ok
      vado a sx
    if sinistra no ok
      vado a dx
  endif
endif

Sergio_A

Rieccomi,

Ho impegnato due ore stanotte per costruire un prototipo su cartone in modo da far compiere i primi passi al mio robottino... Tutto apposto... Unico inghippo è che i sensori, oltre ad essere molto sensibili al sole, la loro regolazione permette una distanza massima dall'ostacolo di pochi centimetri, quindi quando si avvicina ad un muro, il robottino, inizia a ballare la macarena davanti allo stesso.

Allora ho cominciato a pensare se esistesse un comando che potesse far persistere lo stato dei motori in base allo stato dei sensori per una frazione di tempo ad esempio 3 secondi:

.Ostacolo a destra: inversione rotazione motore di destra per tre secondi;
.Ostacolo a sinistra: inversione rotazione motore di sinistra per tre secondi;
.Ostacolo a destra e sinistra: inversione rotazione di ambedue i motori per tre secondi.

Come funzioni tempo di Arduino ho trovato solo "delay" che solo un ritardo e "millis" il quale ancora mi crea un po' di confusione.

Adesso ho la mia compagna che mi guarda in cagnesco, visto che è Pasquetta, ed è meglio che vada...

Grazie

PaoloF_60

Quindi ti chiedo che tipo di sensori usi ? Sensori ad ultrasuoni tipo questi

https://www.amazon.it/azdelivery-HC-SR04-ultrasuoni-Misuratore-Distanza-Raspberry/dp/B072N473HD/ref=sr_1_7?ie=UTF8&qid=1522697151&sr=8-7&keywords=sensori+ultrasuoni

ti permetterebbero di rilevare distanze da pochi cm 2/4 a 4m e non sono sensibili alla luce.

ti ho proposto 3 sensori per avere il controllo destra sinistra e frontale. Ne vendono anche 5 due potresti usarli dietro. Esiste anche il supporto volendo.

https://www.amazon.it/Supporto-sensore-ultrasuoni-distanza-prossimit%C3%A0/dp/B01MT1F798/ref=sr_1_8?ie=UTF8&qid=1522697151&sr=8-8&keywords=sensori+ultrasuoni

C' è anche chi monta un solo sensore su un motore servo e rileva le distanze sui tre o 4 lati ruotando il servo con il sensore nelle 3 o 4 direzioni, ma mi sembra complesso. Un sensore usa due pin del micro quindi già con 3 sensori impegni 6 pin. Uno o due posteriori richiedono altri 2/4 pin.

Comunque toglierei i cicli che fai con la variabile i<ritorno in modo da avere rilevamenti sui sensori molto
più frequenti e immediati. Utilizzi solo step e velo (passi motori e velocità). Togli tutte queste for.

Code: [Select]


for(i=0; i<ritorno; i++) {//ripeti ritorno-1 volte la funzione senza ricontrollare i sensori



Agisci su INTERVALLO magari la chiami PASSI se provi con 200 fai un ottavo di giro motore non so se la ruota è connessa direttamente o hai un moto riduttore. SE fosse diretta puoi valutare di quanto si sposta misurando la circonferenza della ruota dividendola per 8 se hai un moto riduttore devi conoscere
il rapporto di riduzione e calcolare di conseguenza ... dovrai aumentare il numero di passi in questo caso

 

Sergio_A

Eccomi,
è incredibile quanto la realtà differisca dalla teoria... però a me piace!

I sensori che sto usando sono FC-51 i quali differiscono molto dalle caratteristiche del produttore (dichiarati regolabili da 2 cm a 30 cm in realtà distanza massima 10 cm scarsi) e molto sensibili ala luce solare.

Ho fatto diverse prove le quali mi hanno fatto considerare l'utilizzo dei sensori ad ultrasuoni (grazie Paolo).

Problematiche riscontrate:
1. Il comando "retromarcia" non risulta efficace in quanto, quando i due sensori rilevano un ostacolo,
    fanno andare avanti e indietro il robot ad intervalli regolari scanditi dal ritardo di rilettura dello stato
    degli stessi; sarebbe più corretto una retromarcia più una rotazione.
2. Quando il robot transita radente ad un muro, rischia di toccarlo ed incastrarsi perché i due sensori
    anteriori sono fuori portata.

Quindi vorrei utilizzare due sensori ad ultrasuoni anteriormente per la direzione in base agli ostacoli e due sensori infrarossi lateralmente per ovviare il problema del radente al muro.
Poi sarebbe bello sviluppare la modifica alla retromarcia con rotazione.
Intanto provo ad modificare lo schema elettrico per individuare i pin da utilizzare.
Non ho mai usato sensori ad ultrasuoni e  spero di non commettere cavolate.

Grazie

PaoloF_60

Ho fatto alcune prove con il sensore HC SR04 a cui bisogna fornire un impulso alto di 10uS al piedino di triger, quindi il sensore invia 8 treni di impulsi a 40khz e ne misura il tempo di ritorno che viene fornito con un impulso alto sul piedino echo di lunghezza proporzionale alla distanza dall' ostacolo rilevato. Il sensore genera l' impulso di uscita dopo circa 500uS dalla ricezione dell' impulso di triger. Limitando la misura a 25cm riusciamo ad ottenere una misura in 2mS.

Code: [Select]


#include <Wire.h> //serve solo per il display
#include <LiquidCrystal_I2C.h>//serve solo per il display

LiquidCrystal_I2C lcd(0x27,20,4);  // Set the LCD I2C address

#define trig 6 //Trig hc sr04
#define echo 7 //Echo hc sr04

long timed;//variabile long per la pulseIn

void setup() {
  lcd.init();
  lcd.begin(20,4);// initialize the lcd
  lcd.setBacklight(1);//retroilluminazione lcd
  pinMode(trig,OUTPUT);//uscita per trig
  pinMode(echo,INPUT);//ingresso per echo
}

void loop() {
  digitalWrite(trig,HIGH);//impulso di triger al sensore
  delayMicroseconds(10);//temporizzo a 10uS
  digitalWrite(trig,LOW);
  /*misuro impulso uscita con timeout a 2000 limito la massima distanza a 25cm circa
   *e riduco il tempo di misurazione altrimenti il timeout della pulsin sarebbe 1S
   *in questo modo otterò misure fina a 25cm oppure 0 se la distanza è > 25cm per
   *tanto sarà molto semplice testare il sensore con if distanza > 0 ostacolo da evitare*/
  timed=pulseInLong(echo,HIGH,2000);//misura l' impulso alto su echo se > 2mS restituisce 0
  lcd.setCursor(0,0);//posizione display
  lcd.print("Distanza = ");lcd.print(timed / 58);lcd.print(" Cm");//stampa distanza senza decimali
  delay(1000);//questa l' ho messa per la mia prova tu non la dovrai usare
}



Per quanto riguarda la retromarcia è normale che con un ostacolo davanti e i lati liberi dopo la retromarcia devi imporre tu una rotazione dalla parte libera o casuale se lo sono entrambe.
Potresti addirittura considerare di fare una retromarcia lunga se hai anche entrambi i lati occupati.
metti che si infili un un cunicolo chiuso in fondo devi tornare fino a dove ai un lato libero.

Go Up