Fermare servomotori ed iniziare un altro ciclo

Salve gente! Vi scrivo perché ho un problema e spero possiate aiutarmi a risolverlo. Allora io sto facendo il progetto di un robot (non so se avete visto un mio post precedente). Comunque riepilogando è uno scarafaggio che cammina, quando incontra un ostacolo torna indietro e si gira. Io sono riuscito a farlo camminare e a farlo andare indietro. Adesso devo farlo girare, so come deve muoversi, ma non so come scriverlo nel programma. Per capirci meglio, inserisco l’ultima parte del programma che serve a farlo indietreggiare e vi mostro dov’è il mio problema:

#include <Servo.h>
Servo motore1;
Servo motore2;
Servo motore3;
int pos1 = 75;
int pos2 = 75;
int pos3 = 0;

void setup () {
 motore1.attach(2);
 motore2.attach(3);                                                  
 motore3.attach(4);
 pinMode(8,INPUT);
} 

void loop() {
if (digitalRead(8)== HIGH) {                        // se viene pressato il pulsante
   motore3.write(140);                               // si alza la zampa centrale di sinistra
for (pos1= 20; pos1 <130; pos1+= 1) {        // il motore porta le zampe di sinistra avanti, spingendo indietro il robot
          motore1.write (pos1);
          
          delay(10);
 }
  motore3.write(60);                                // si alza la zampa centrale di destra

 for (pos2= 150; pos2 >20; pos2-= 1) {    //  il motore porta le zampe di destra avanti, spingendo indietro il robot
          motore2.write (pos2);
          delay(10);
 }}

Allora il robot così indietreggia. Adesso io per far sì che il ragno giri devo fermare il motore1, lasciare il motore3.write(60), ma cambiare le posizioni da fare del motore2. Praticamente la posizione che devo far assumere ad esso è:

for (pos2= 50; pos2 <=150; pos2+= 1) {                        
          motore2.write (pos2);
          delay(5);

Non so come fare per scriverlo nel programma, sapreste darmi una mano? Per qualsiasi altra informazione, non esitate a chiedere! Grazie in anticipo!

Qualche commento nel listato aiuterebbe a capire a cosa corrispondono i motori, cioè che funzione svolgono.

Editato (ho aggiunto l'if, che avevo dimenticato) Comunque l'intero programma che ho scritto, consiste solo nell'ultima fase del movimento, cioè quando incontra un ostacolo, deve andare indietro e infine girare. La parte iniziale per farlo camminare, l'ho già eseguita e va bene. Il mio problema è come scrivere di smettere di indietreggiare, e far fare l'altro passo che ho scritto alla fine. Spero di essere stato chiaro.

Da quanto ho capito il motore 3 è quello che decide quale delle gambe poggia per terra mediante un sistema a bilancia.

Per girare, perciò, occorre che alternativamente una gamba avanzi e l’altra retroceda.
Ho capito bene?

Praticamente il robot è composto da 6 zampe. le 2 zampe di destra sono comandante da un servomotore, le 2 zampe di sinistra da un altro servo motore ed un ultimo servomotore comanda le zampe centrali. Bene, le zampe centrali si alzano in maniera alternativa per permettere il passo delle rispettive zampe collegate. Quindi, quando si alza la zampa centrale destra, le zampe posteriori e anteriori di destra vanno indietro in modo da permettere il passo in avanti e stessa cosa per la parte sinistra. Quando il robot incontra un ostacolo, torna indietro facendo avanzare le zampe (vedi la prima parte del programma). Dopo che torna indietro, deve girare ed io so come farlo girare (vedi seconda parte del programma). Praticamente per farlo girare le zampe di un lato devono restare poggiate a terra, e le altre avanzare, in modo che quelle bloccate facciano da peso e spostino il robot dall'altra parte. Il mio problema e come scrivere nel programma " smetti di indietreggiare e fai quest'altra cosa".

Ciao Aleg, per quello che vedo nel codice mi viene da dire una cosa: i cicli for che hai messo per gestire il movimento delle zampe (penso..) non possono essere interrotti in alcun modo in quanto hai solo un processo. Penso che dovresti lanciare il movimento della zampa e proseguire proseguire con il loop (senza restare chiuso all'interno dei for) e gestire quindi anche tutto il resto. In questo modo il tuo loop non dovrebbe superare i 3 o 4 ms totali (dipende da quanto codice hai scritto) e al giro successivo avresti la possibilità di fermare o partire con quello che ti serve. Spero di essermi spiegato.....

Ciauu

dgaito: Ciao Aleg, per quello che vedo nel codice mi viene da dire una cosa: i cicli for che hai messo per gestire il movimento delle zampe (penso..) non possono essere interrotti in alcun modo in quanto hai solo un processo. Penso che dovresti lanciare il movimento della zampa e proseguire proseguire con il loop (senza restare chiuso all'interno dei for) e gestire quindi anche tutto il resto. In questo modo il tuo loop non dovrebbe superare i 3 o 4 ms totali (dipende da quanto codice hai scritto) e al giro successivo avresti la possibilità di fermare o partire con quello che ti serve. Spero di essermi spiegato.....

Ciauu

Ciao, non mi è chiarissimo quello che intendi. Potresti spiegarmelo con qualche esempio? Grazie mille!

Vediamo se riesco....

int pos1 = 20;

void loop() {

if (digitalRead(8)== HIGH) {                        // se viene pressato il pulsante
   motore3.write(140);                               // si alza la zampa centrale di sinistra
  motore1.write (pos1);
  pos1++;
  //        delay(10);        //Questo delay io lo toglierei ma devi gestire il tempo in un'altro modo potresti usare mills();

 }

//Resto del codice

}

In modo moooolto semplificato sarebbe circa questo: in questo modo viene eseguito un movimento ad ogni giro di loop, solo che con il resto del codice puoi verificare ingressi o situazioni che richiedono una modifica all'azione in corso...

dgaito: Vediamo se riesco....

int pos1 = 20;

void loop() {

if (digitalRead(8)== HIGH) {                        // se viene pressato il pulsante   motore3.write(140);                              // si alza la zampa centrale di sinistra   motore1.write (pos1);   pos1++;   //        delay(10);        //Questo delay io lo toglierei ma devi gestire il tempo in un'altro modo potresti usare mills();

}

//Resto del codice

}




In modo moooolto semplificato sarebbe circa questo: in questo modo viene eseguito un movimento ad ogni giro di loop, solo che con il resto del codice puoi verificare ingressi o situazioni che richiedono una modifica all'azione in corso...

Ma se togliessi il for, e scrivessi direttamente la posizione del motore, non farebbe un vero e proprio movimento ma solo un passo no? Pos1++ incrementa la posizione, ma non devo dargli anche un limite come faccio con il for?

Infatti ad ogni giro di loop la zampa farebbe uno step, ma se hai un loop che gira in 3ms credo sarebbe anche troppo veloce...

per il limite ci vuole poco:

if (pos1 > 130) pos1 = 130;

Penso però che dovresti gestire la copsa con 2 array: Una contenente le quote reali di ogni zampa, e una contenente le quote targhet (sempre per ogni zampa).

A questo punto basterebbe una funzione che fa fare uno step verso la quota targhet ad ogni zampa ogni giro di loop: in questo modo fermare una zampa significa impostare la quota targhet uguale alla quota reale, e cambiare direzione significa solo cambiare il valore di una quota targhet.

Vedresti tutte le gambe che si muovono simultaneamente e in modo apparentemente asincrono verso la posizione comandata.

E avresti modo durante il movimento di verificare sensori/ingressi per capire se devi correggere qualcosa..

Ma il loop deve essere veloce: nessun ritardo.

Non so se mi sono spiegato bene: sono un tantino una frana a spiegare le cose :)....

Ciauuu

Ti spieghi bene, soltanto che io non sono esperto con Arduino... Cosa sarebbe questo array ? Cioè come dovrei impostare io adesso il programma?

Un’array è un insieme di dati es…

int quoteTarghet[5]; //array su base 0 delle quote targhet
int quoteReali[5];      //quote reali

//Per assegnare i valori ad una quota targhet
quoteTarghet[4] = 20;  //Assegna 20 alla quinta zampa (l'indice delll'array va da 0 a 5)

//Per assegnare i valori a tutti i membri dell'array
for (int i=0; i<5; i++) {
  quoteTarghet[i] = 20;  //Assegna 20 ad ogni quota targhet
}

…solo che come strutturare il tuo codice io non te lo posso dire: di sicuro gestire un codice di questo tipo è più complesso rispetto quello che avevi ipotizzato tu…

Spero di essere stato utile…

Ciauuu

Quale sarebbe quindi la funzione dei targhet? Non ho capito bene perchè dovrei usarli...

In ogni caso se l'idea mia ti sembra troppo complessa, ne avresti di altre per far girare il robot? Io avevo ipotizzato quella di far bloccare una parte in modo da far pendenza e far muovere l'altra. Ma era una mia ipotesi magari inesatta o complessa come dici tu. Sapresti allora consigliarmi un altro movimento da fare alla pressione del pulsante? Grazie mille in ogni caso per l'aiuto e soprattutto per la pazienza!

Non voglio farti cambiare idea su come far muovere il robot: quello che ho cercato di fare è solo proporti una soluzione per poter fare muovere assieme tutte le zampe avendone anche il controllo per poter interrompere o cambiare i movimenti.

Le array sono semplicemente uno strumento che ti permette di memorizzare i valori: ma potrebbe essere anche così:

int posizioneRealeZampa1 = 20;
int posizioneRealeZampa2 = 20;
int posizioneRealeZampa3 = 20;
int posizioneRealeZampa4 = 20;
int posizioneRealeZampa5 = 20;
int posizioneRealeZampa6 = 20;

int posizioneVolutaZampa1 = 20;
int posizioneVolutaZampa2 = 20;
int posizioneVolutaZampa3 = 20;
int posizioneVolutaZampa4 = 20;
int posizioneVolutaZampa5 = 20;
int posizioneVolutaZampa6 = 20;

//Al cambiare della posizione voluta la zampa inizia a muoversi

..... facendo lo stesso usando delle array hai la possibilità di fare il tutto in modo più semplice e con un codice più pulito....

Ciauuu

E dopo aver memorizzato i valori, devo procedere con l' if in che modo?

int quoteTarghet[5];
int quoteReali[5];

void setup {
  for (int i=0; i<5; i++) {
    quoteTarghet[i] = 20; //Posizione di partenza
    quoteReali[i] = 20; //Posizione di partenza
  } 
}

void loop {
  //Eseguo uno step verso la posizione finale per ogni zampa
  for (int i=0; i<5; i++) {
    if (quoteTarghet[i] < quoteReali[i]) {
      quoteReali[i]++;  //Sposto la zampa in positivo
    }
    if (quoteTarghet[i] > quoteReali[i]) {
      quoteReali[i]--;  //Sposto la zampa in negativo
    }
   //Muovo il motore portandolo a  quoteReali[i]
  NuoviMotore[i]; //I e' l'indice della zampa da muovere
  }

  //Resto del codice di controllo del robot
  if (iButton) {
    //Sposto tutte le zampe a 130
    for (int i=0; i<5; i++) {
      quoteTarghet[i] = 130; //nuova posizione
    } 
  } else {
   //Sposto tutte le zampe a 20
    for (int i=0; i<5; i++) {
      quoteTarghet[i] = 20; //nuova posizione
    } 
  }

}

…prova a vedere qui…

Ciaooo

Il problema è che i servo non si muovono allo stesso modo: ognuno di essi (a parte il motore3 che gli dico semplicemente di alzare da un lato o dall'altro) ha un'istruzione diversa per farlo avanzare o indietreggiare...

Se non ho capito male…

  if (digitalRead(8) == HIGH) {                        // se viene premuto il pulsante...
    for (byte I = 0;  I < 110; I ++) {       
      motore3.write(140);
      pos1 = I + 20; {
      motore1.write (pos1);
      motore3.write(60);
      pos2 = 130 - I;
      motore1.write (pos2);
      delay(10);     
    }
  }

Se vi mostrassi la prima parte del programma, sapreste darmi una bozza? Perchè così non riesco proprio a connettere le cose :S
Ecco la prima parte del programma che fa andare avanti il robot:

#include <Servo.h>
Servo motore1;
Servo motore2;
Servo motore3;
int pos1 = 75;
int pos2 = 75;


void setup () {
 motore1.attach(2);
 motore2.attach(3);
 motore3.attach(4);
pinMode(8,INPUT);
 
} 

void loop () {
motore3.write(140);                                       // Si alza la zampa centrale di sinistra
 for (pos1= 100; pos1 >=20; pos1-= 1) {    // La zampa anteriore e posteriore di sinistra indietreggiano, portando avanti il robot              
          motore1.write (pos1);
          delay(5);
 }

 motore3.write(60);                                       // si alza la zampa centrale di destra e automaticamente si abbassa quella di sinistra

 for (pos2= 50; pos2 <=150; pos2+= 1) {   // la zampa anteriore e posteriore di destra indietreggiano, portando il robot avanti
          motore2.write (pos2);
          delay(5);
 }

Per indietreggiare, deve far il lavoro opposto, quindi quello che ho scritto all’inizio della discussione, ovvero:.

If (digitalRead(8)== HIGH) {
 motore3.write(140);
 for (pos1= 20; pos1 <130; pos1+= 1) {
          motore1.write (pos1);
           delay(10);
 }
 
 motore3.write(60);

 for (pos2= 150; pos2 >20; pos2-= 1) {
          motore2.write (pos2);
          delay(10);
}}

Adesso come faccio per girare seguendo le istruzioni che mi avete dato? Oppure sapreste riscrivermi l’intero programma come dite voi? Ho messo foto del robot , così magari potete focalizzare meglio.

Ti ho scritto la prima parte di codice: prova a vedere se lo capisci e se ti piace…
Facendo così i movimenti sono sequenziali, ma il sistema non è bloccato durante i movimenti e puoi fermare o invertire la direzione quando ti serve…

#include <Servo.h>
Servo motore[2];
int posizioniReali[2];
int posizioniTarghet[2];
int sequenza = 0;


void setup () {
  motore[0].attach(2);
  motore[1].attach(3);
  motore[2].attach(4);
  pinMode(8,INPUT);

} 

void loop () {
  //Gestisce la posizione dei motori
  posizionaMotori(); //se invece di ogni loop chiamo questa funzione ogni 2 o 3 loop i motori saranno più lenti

    if (digitalRead(8)== HIGH) {
    switch (sequenza) {
    case 0: //si alza la zampa centrale di sinistra
      posizioniTarghet[2] = 140;
      if (posizioniTarghet[2] == posizioniReali[2]) sequenza++; //Incremento la sequenza appena arrivo in quota
      break;
    case 1: // La zampa anteriore e posteriore di sinistra avanzano (ma dovrebbero essere già avanti)  
      posizioniTarghet[0] = 100;
      if (posizioniTarghet[0] == posizioniReali[0]) sequenza++; //Incremento la sequenza appena arrivo in quota
      break;
    case 2: // La zampa anteriore e posteriore di sinistra indietreggiano, portando avanti il robot  
      posizioniTarghet[0] = 20;
      if (posizioniTarghet[0] == posizioniReali[0]) sequenza++; //Incremento la sequenza appena arrivo in quota
      break;
    case 3: // si alza la zampa centrale di destra e automaticamente si abbassa quella di sinistra
      posizioniTarghet[2] = 60;
      if (posizioniTarghet[2] == posizioniReali[2]) sequenza++; //Incremento la sequenza appena arrivo in quota
      break;
    case 4: // la zampa anteriore e posteriore di destra avanzano (ma dovrebbero essere già avanti)
      posizioniTarghet[1] = 50;
      if (posizioniTarghet[1] == posizioniReali[1]) sequenza++; //Incremento la sequenza appena arrivo in quota
    case 5: // la zampa anteriore e posteriore di destra indietreggiano, portando il robot avanti
      posizioniTarghet[1] = 150;
      if (posizioniTarghet[1] == posizioniReali[1]) sequenza++; //Incremento la sequenza appena arrivo in quota
      break;
    default:
      sequenza = 0; //Riparto con la sequenza
      break;
    }

  } 
  else {



  }


  //Resto del codice di gestione


}

void posizionaMotori() {
  for (int i=0; i<2; i++) {
    if (posizioniTarghet[i] > posizioniReali[i]) {
      //Sposto il motore in +
      posizioniReali[i]++;
    }
    if (posizioniTarghet[i] < posizioniReali[i]) {
      //Sposto il motore in +
      posizioniReali[i]--;
    }
    motore[i].write(posizioniReali[i]); //Muovo effettivamente il motore
  }

}