Azioni in contemporanea

ciao a tutti, sto scrivendo un programma per una gara di robotica, devo leggere con un sensore delle barre colorate di fila, ho sviluppato un void che tramite un sensore di colore tcs 34725 legge i dati. Il robottino affinché legga tutta la striscia in maniera continua deve però andare avanti; il robot si muove con 4 stepper nema 17, comandati da cnc shild e programmate con la libreria Accelstepper. Io ho pensato di fare un ciclo while(colorScannerVettore()){muovi_avanti(200);}, ciò però non accade, ho trasformato le varie funzioni in bool "nome funzione"() ma non cambia, scannerizza prima e al termine dello scan si muove, qualcuno sa come posso fare?

void muovi_avanti(float tick) {
  anteriore_destra.setCurrentPosition(0);
  while(anteriore_destra.currentPosition() != tick) {
    anteriore_destra.setSpeed(velocita);
    anteriore_sinistra.setSpeed(-velocita);
    posteriore_destra.setSpeed(velocita);
    posteriore_sinistra.setSpeed(velocita);
    anteriore_sinistra.runSpeed();
    posteriore_destra.runSpeed();
    posteriore_sinistra.runSpeed();
    anteriore_destra.runSpeed();
  }
  Serial.println("eseguito");
}
void colorScannerVettore() {
  //finché non ha rilevato tutti i colori del vettore continua a rilevare, altrimenti fermati
  while (o < 11) {
    if (dt > 500) {
      //fai la media di 10 valori e ottieni i valori "puliti" RGB
      for (h = 0; h < divisore; h++) {
        rileva();
        valueRed += valueRedRaw;
        valueGreen += valueGreenRaw;
        valueBlue += valueBlueRaw;
        delay(20);  //tempo di pausa tra ogni rilevazione
      }
      valueRed = valueRed / divisore;
      valueGreen = valueGreen / divisore;
      valueBlue = valueBlue / divisore;
      tempo = millis();
    }

    while (s < 1) {
      vettore[o][0] = valueRed;
      vettore[o][1] = valueGreen;
      vettore[o][2] = valueBlue;
#ifdef STAMPA
      Serial.println(" ");
      Serial.println("--------------------------------------------------------------------------------------------------------");
      Serial.println(" ");
#endif STAMPA
      delay(20);
      s++;
    }

#ifdef STAMPA
    Serial.print(o);
    Serial.print("   RGB:  ");
    Serial.print(valueRed);
    Serial.print(" ");
    Serial.print(valueGreen);
    Serial.print(" ");
    Serial.print(valueBlue);
    Serial.print("\t");
    Serial.print("\t");
    Serial.print(vettore[2][0]);  //componente red
    Serial.print("\t");
    Serial.print(vettore[3][0]);
    Serial.print("\t");
    Serial.print(vettore[4][0]);
    Serial.print("\t");
    Serial.print(vettore[5][0]);
    Serial.print("\t");
    Serial.print(vettore[6][0]);
    Serial.print("\t");
    Serial.print(vettore[7][0]);
    Serial.print("\t");
    Serial.print(vettore[8][0]);
    Serial.print("\t");
    Serial.print(vettore[9][0]);
    Serial.print("\t");
    Serial.println(vettore[10][0]);
#endif STAMPA

    //se le variabili "pulite" rilevano valori diversi (+-K) rispetto al colore immagazzinato
    //in precedenza, allora incrementano le variabili per gestire il processo e salvano
    //il nuovo colore in una nuova posizione nell'array
    if ((valueRed < (vettore[o][0] - K) || valueRed > (vettore[o][0] + K)) ||
        (valueGreen < (vettore[o][1] - K) || valueGreen > (vettore[o][1] + K)) ||
        (valueBlue < (vettore[o][2] - K) || valueBlue > (vettore[o][2] + K)))
    {
      o++;
      s = 0;
      delay(PROCESSO);
    }
    dt = millis() - tempo;
  }

  //  -------------------------------------------------------------------------
  //                   CODIFICA COLORI (rosso, giallo, verde)
  //  -------------------------------------------------------------------------
  //associa all'array colore alcuni valori dell'array vettore che corrispondono
  //al red, blue, yellow
  for (int w = 0; w < 3; w++) {
    color[0][w] = vettore[2][w];
    color[1][w] = vettore[5][w];
    color[2][w] = vettore[8][w];
  }

  bubbleSortColor(); //funzione per ordinare l'array color in base alla variabile RED

  //ordinamento array in ordine crescente
  //il primo colore dell'array ordinato è il green, il secondo è il yellow, il terzo è il red
  g[0] = color[0][0];
  g[1] = color[0][1];
  g[2] = color[0][2];

  y[0] = color[1][0];
  y[1] = color[1][1];
  y[2] = color[1][2];

  r[0] = color[2][0];
  r[1] = color[2][1];
  r[2] = color[2][2];

  //ciclo while usato per stampare solamente una volta
  while (l < 1) {
    findElementPosition(g[0]);  //trova la posizione del colore green nell'array vettore
    posizioneGreen = posizione;

#ifdef STAMPA
    Serial.print("il VERDE si trova nella posizione:  ");
    Serial.println(posizioneGreen);
#endif STAMPA
    findElementPosition(r[0]);  //trova la posizione del colore red nell'array vettore
    posizioneRed = posizione;
#ifdef STAMPA
    Serial.print("il ROSSO si trova nella posizione:  ");
    Serial.println(posizioneRed);
#endif STAMPA
    findElementPosition(y[0]);  //trova la posizione del colore yellow nell'array vettore
    posizioneYellow = posizione;
#ifdef STAMPA
    Serial.print("il GIALLO si trova nella posizione:  ");
    Serial.println(posizioneYellow);
#endif STAMPA

    l++;  //variabile gestione ciclo while()
  }

  //  -------------------------------------------------------------------------
  //                        CODIFICA COLORI (blu, viola)
  //  -------------------------------------------------------------------------
  //si associano i blu e i viola a due a due in tre array differenti
  for (int w = 0; w < 3; w++) {
    routeOne[0][w] = vettore[3][w];
    routeOne[1][w] = vettore[4][w];
    routeTwo[0][w] = vettore[6][w];
    routeTwo[1][w] = vettore[7][w];
    routeThree[0][w] = vettore[9][w];
    routeThree[1][w] = vettore[10][w];
  }

  bubbleSortRouteOne(); //si ordina l'array One in base alla variabile RED
  bubbleSortRouteTwo(); //si ordina l'array Two
  bubbleSortRouteThree(); //si ordina l'array Three

  v[0] = routeOne[1][0];
  v[1] = routeOne[1][1];
  v[2] = routeOne[1][2];

  b[0] = routeOne[0][0];
  b[1] = routeOne[0][1];
  b[2] = routeOne[0][2];

  Rv2 = routeTwo[1][0];
  Rb2 = routeTwo[0][0];

  Rv3 = routeThree[1][0];
  Rb3 = routeThree[0][0];

  vettore[0][0] = 0;
  vettore[1][0] = 0;
  vettore[2][0] = 0;
  vettore[5][0] = 0;
  vettore[8][0] = 0;

  while (m < 1) {
    findElementPosition(b[0]); //trova posizione del blu One
    posizioneBlue[0] = posizione;
    //dopo aver trovato la posizione azzera il valore relativo nell'array
    //vettore in modo tale da non creare confusione nelle rilevazioni successive
    vettore[posizioneBlue[0]][0] = 0;

    findElementPosition(Rb2); //trova posizione del blu Two
    posizioneBlue[1] = posizione;
    vettore[posizioneBlue[1]][0] = 0;

    findElementPosition(Rb3); //trova posizione del blu Three
    posizioneBlue[2] = posizione;
    vettore[posizioneBlue[2]][0] = 0;

    findElementPosition(v[0]);
    posizioneViolet[0] = posizione;
    vettore[posizioneViolet[0]][0] = 0;

    findElementPosition(Rv2);
    posizioneViolet[1] = posizione;
    vettore[posizioneViolet[1]][0] = 0;

    findElementPosition(Rv3);
    posizioneViolet[2] = posizione;
    vettore[posizioneViolet[2]][0] = 0;

#ifdef STAMPA
    Serial.print("il BLU si trova nelle posizioni:  ");
    Serial.print(posizioneBlue[0]);
    Serial.print("  ");
    Serial.print(posizioneBlue[1]);
    Serial.print("  ");
    Serial.println(posizioneBlue[2]);
    Serial.print("il VIOLA si trova nelle posizioni:  ");
    Serial.print(posizioneViolet[0]);
    Serial.print("  ");
    Serial.print(posizioneViolet[1]);
    Serial.print("  ");
    Serial.println(posizioneViolet[2]);
#endif STAMPA

    m = 1; //variabile gestione ciclo while()
  }
}
void loop(){
  muovi_avanti(150);
  delay(1000);
 while (colorScannerVettore()){
  muovi_avanti(2000);
 }

Non devi usare while. Usa if, facendo una cosa per volta e verificando quando il valore viene raggiunto.

Grazie per il consiglio, però il robot, dovendo leggere un foglio lungo 18 cm diviso in 9 parti diversamente colorate deve muoversi per forza, sennò il robot sarebbe fermo solo sulla prima striscia colorata.

Datman intendeva dirti che devi pensare in maniera diversa il codice.
Ricorda che la loop è già un while,ovvero il programma principale di Arduino core (main nascosto) richiama 1 volta la setup e poi di continuo la loop (dentro ad un while)

ora capisco, però non so bene come scrivere il codice.

Nella funzione colorScannerVettore() usi un while, dentro questo vedo un altro while. Questi while sono cicli innestati (annidati) dentro il ciclo principale.

void loop() {  // ciclo principale
    while (o < 11) { // 1° ciclo annidato
         for (h = 0; h < divisore; h++) { 2° ciclo annidato
         }
         while (s < 1) { // 3° ciclo annidato
         }
    }
}

In aggiunta c'è anche un delay. Ora quanto tempo ci vuole per eseguire la funzione colorScannerVettore()?

void loop() {
    uint32_t us = micros();
    colorScannerVettore();
    Serial.println(micros() - us);
}

Questa informazione è fondamentale, poiché runSpeed() verrà chiamata in ritardo di tot microsecondi, maggiore è questo tempo più lento sarà l'avanzamento dei motori.

void colorScannerVettore() {
  while (o < 11) {
       anteriore_sinistra.runSpeed();
       posteriore_destra.runSpeed();
       posteriore_sinistra.runSpeed();
       anteriore_destra.runSpeed();
       if (dt > 500) {
       }  
  }

Anche in questo modo se il ciclo for con il suo delay 20 dura troppo tempo diciamo 200ms, dopo questo tempo verranno chiamate le runSpeed().

In sostanza runSpeed() deve essere chiamato alla più alta frequenza possibile, se la frequenza è troppo bassa la velocità impostata non potrà essere rispettata.

PS: non conosco affatto il modulo tcs34725 e non ho idea di quanto tempo richiede per fare una lettura. Se è necessario temporizzare le letture è necessario usare millis ad esempio per eseguire una lettura ogni 50ms.

L'alternativa visto che usi la MEGA è freeRTOS, ma è cosa assai complicata.

Ciao.

quindi dovrei mettere "muovi_avanti()" nel while? Perché ci avevo già provato e prima si muoveva il robot e poi iniziava la scansione. Il sensore TCS nel void scansione vettore deve scannerizzare 9 parti colorate, mette negli array la posizione dei vari colori e poi stampa la posizione dei colori. A me serve una cosa contemporanea, mentre legge il robot si muove tipo a velocità 200. Non capisco come posso fare.

Mettiamo in chiaro che io la soluzione non la ho in tasca e non è che non voglio dartela, non la ho proprio la soluzione.
Però è evidente che runSpeed() se ha qualcosa da fare la fa, se non ha nulla da fare la chiamata termina in circa 50us. Ora se durante il while contenuto colorScannerVettore() non chiami runSpeed() i motori resteranno fermi per tutto il tempo che dura il while. Esageriamo se la chiamata a colorScannerVettore() richiede un minuto per un minuto i motori resteranno fermi. Come detto per fare avanzare i motori runSpeed() deve essere chiamata alla più alta frequenza possibile.

setSpeed() non serve chiamarla spesso se velocita non cambia, per cui, solo runSpeed() dovrebbe andare sia in while che in for. Dico dovrebbe perché è tutto relazionato alla velocità impostata con setSpeed().

Poiché non hai ben compreso come funziona la libreria accelstepper è bene che fai degli esperimenti.

Ciao.

Io temo che non sia solo una questione di spostare pezzi di codice da una parte all'altra, ma di fare una revisione completa di tutto lo sketch pensandolo in modo completamente non bloccante.

Ad esempio, in questo semplice sketch ho inserito uno stepper che si muove alla posizione impostata con un potenziometro. Contemporaneamente, quando è in movimento viene fatto blinkare un semplice led. Come puoi vedere, l'unico loop che c'è è quello principale della funzione loop(), nessun while e nessun for.

Ottimo esempio quello di @cotestatnt, esempio a cui basta aggiungere un delay(100) per vedere e capire l'effetto disastroso che fa.

void blinkLed() {
  delay(100);
  static uint32_t blinkTime = millis();
  if (millis() - blinkTime >= 150) {
    blinkTime = millis();
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
}

Il led lampeggia alla corretta frequenza, ma il servo è lentissimo.

Ciao.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.