Problemi con menu gestito tramite seriale

#include <Servo.h>


Servo servo;
String posProgSe;  //posizione programmata tramite seriale
int posEff = 0;  //posizione effettiva
char lista;
String t;
int temp = 10;

void velocita();
void movservoAv();
void movservoInd();
void menu();
void stampa();


void setup()
{
  servo.attach(9);
  Serial.begin(9600);
  servo.write(0);


  menu();
}

void loop()
{

}

void menu()
{
  Serial.print("Seleziona a-b-c-d:");
  while (1) {
    if (Serial.available() > 0)
    {
      lista = Serial.read();
      Serial.println(lista);
    }

    switch (lista)
    {
      case 'a':
        velocita();
        break;

      case 'b':
        movservoAv();
        break;

      case 'c':
        movservoInd();
        break;

      case 'd' :
        stampa();
        break;
    }
  }
}
void velocita()
{
  //Serial.println(temp);
  Serial.print("sono dentro");
  t = Serial.readString();
  temp = t.toInt();
  Serial.println("esco");
  menu();
}


void movservoInd()
{
  posProgSe = Serial.readString();  //leggo la stringa dalla seriale

  int posProg = posProgSe.toInt(); //creo una variabile in cui immetto i valori letti dalla seriale convertiti in INT
  Serial.print(posProg);
  Serial.println("°");

  if (posProg < posEff)
  {
    for (int x = posEff; x >= posProg; x--)
    {
      servo.write(x);
      delay(10);
      posEff = posProg;
    }
  } menu();
}

void movservoAv()
{
  posProgSe = Serial.readString();  //leggo la stringa dalla seriale

  int posProg = posProgSe.toInt(); //creo una variabile in cui immetto i valori letti dalla seriale convertiti in INT
  Serial.print(posProg);
  Serial.println("°");

  if (posProg > posEff)
  {
    for (int x = posEff; x <= posProg; x++)
    {
      servo.write(x);
      delay(10);
      posEff = posProg;
    }
  } menu();
}




void stampa()
{
  Serial.println("prova");
  delay(10);
  menu();
}

Volevo creare un menu da gestire direttamente da seriale, però ho riscontrato un problema con le funzioni: velocita, movservoAv, movservoInd.In pratica appena le richiamo attraverso la funzione "menu()" tramite uno swithc, eseguono le istruzioni in loop continuo e anche quando ritorno al "menu()" quest'ultime continuano a venire eseguite e non permetto di passare ad altre funzioni.Ho voluto aggiungere alla fine una funzione semplice che non implementasse il "Serial.read" e con questa "stampa()" il problema non si pone.Ho fatto diversi tentativi ma niente, non capisco come uscire o meglio fermare l'esecuzione di queste funzioni.Grazie in anticipo per l'aiuto.

Non devi richiamare menu() alla fine di ogni funzione richiamata, ci ritorna in automatico al termine

Grazie per la risposta, ho provato ma niente, se non metto "menu()" non esce più rimane dentro e continua ad eseguire il codice in loop, senza possibilità di cambiare funzione...

Certo che se non resetti la variabile "lista" dopo che la hai letta, continuerà a ripeterla

Ok, ma per resettarla, rimuovo il while e la trasferisco nel "void loop" ? potrebbe essere una soluzione? o in che altro modo?
grazie

Infatti io non ho capito il significato di quel wile() dentro in una funzione chiusa in anello nella setup()
Lasciando la loop() desolatamente vuota

Sospetto che tu non abbia chiaro ne il C ne la programmazione specifica di Arduino

Era una prova, infatti anche mettendo il richiamo della funzione nel loop il problema persiste...il while è statp rimosso...

L'errore te lo ha già segnalato Standardoil qui:

... una volta utilizzato il valore, devi pulire la variabile!

Guglielmo

#include <Servo.h>


Servo servo;
String posProgSe;  //posizione programmata tramite seriale
int posEff = 0;  //posizione effettiva
char lista;
String t;
int temp = 10;
int led1 = 10;
int led2 = 11;

void velocita();
void movservoAv();
void movservoInd();
void menu();
void stampa();
void ledBlink();
void ledFade();


void setup()
{
  servo.attach(9);
  Serial.begin(9600);
  servo.write(0);
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  
  Serial.print("Seleziona a-b-c-d-e-f:");

}

void loop()
{
  menu();
}

void menu()
{

  if (Serial.available() > 0)
  {
    lista = Serial.read();
    Serial.println(lista);
  }

  switch (lista)
  {
    case 'a':
      velocita();
      break;

    case 'b':
      movservoAv();
      break;

    case 'c':
      movservoInd();
      break;

    case 'd' :
      stampa();
      break;

    case 'e' :
      ledBlink();
      break;

    case 'f' :
      ledFade();
      break;
  }
}

void velocita()
{
  //Serial.println(temp);
  Serial.print("sono dentro");
  t = Serial.readString();
  temp = t.toInt();
  Serial.println("esco");
  menu();
}


void movservoInd()
{
  posProgSe = Serial.readString();  //leggo la stringa dalla seriale

  int posProg = posProgSe.toInt(); //creo una variabile in cui immetto i valori letti dalla seriale convertiti in INT
  Serial.print(posProg);
  Serial.println("°");

  if (posProg < posEff)
  {
    for (int x = posEff; x >= posProg; x--)
    {
      servo.write(x);
      delay(10);
      posEff = posProg;
    }
  } Serial.print("ma che");
}

void movservoAv()
{
  posProgSe = Serial.readString();  //leggo la stringa dalla seriale

  int posProg = posProgSe.toInt(); //creo una variabile in cui immetto i valori letti dalla seriale convertiti in INT
  Serial.print(posProg);
  Serial.println("°");

  if (posProg > posEff)
  {
    for (int x = posEff; x <= posProg; x++)
    {
      servo.write(x);
      delay(10);
      posEff = posProg;
    }
  }
}


void stampa()
{
  Serial.println("prova");
  delay(10);
  menu();
}

void ledBlink()
{
  for(int i = 0;i <= 10; i++)
  { 
  digitalWrite(led1, 1);
  delay(1000);
  digitalWrite(led1, 0);
  delay(1000);
  };
  menu();
}
void ledFade()
{
  for (int i = 0; i <= 255; i++)
  {
    analogWrite(led2, i);
    delay(20);
  }
  for (int i = 255; i >= 0; i--)
  {
    analogWrite(led2, i);
    delay(20);
  }
  menu();
}


Ho aggiunto altre funzioni e come per la funzione "stampa()" non ci sono problemi, appena finisce l'esecuzione torna nella funzione "menu()" grazie al richiamo di quest'ultimo, senza rimane bloccato nella funzione, ma il problema rimane per le altre funzioni in cui è implicato Serial.read() a quanto pare bisogna trovare il modo di uscire dal loop che si crea entrando in quelle funzioni, ma non so come...
Ok ma come posso pulire la variabile se continua a restituirmi il valore 0 in loop anche dopo aver inserito un valore, cioè lo spostamento del servo avviene con il valore che inserisco tramite il seriale, ma subito dopo continua a stamparmi il valore 0 e non c'è modo di uscire, anche riuscendo a tornare al menu continua a stampare 0 gradi...

Guarda

Io cosa fare te lo ho detto

Come farlo lo devi sapere tu,

Visto che programmi robot di movimentazione prova a immaginare come lo faresti con un robot

Giusta regola, e qui cambio discorso, io quando ho imparato a programmare robot di saldatura e di movimentazione sapevo già programmare in generale
Ma comunque saper programmare dovrebbe essere quasi universale

Come faresti, e qui torno a bomba, a far eseguire l'azione al robot una volta sola anche se, per esempio il micro di avvio rimanesse impegnato?

Ah, per chi se lo chiedesse...

Quando ero roboticista io non programmavo robot, insegnavo a programmarli...

Torna?

Continuo a dire che hai problemi col C

Perché non torna, e alla lunga fa anche peggio che non mettere il "richiamo di quest'ultimo"

Quindi ti conviene "pensare" a cosa vuol dire chiamare una funzione e cosa vuol dire ritornare da una funzione

Quando avrai chiaro questo punto se ne riparla, prima è inutile

Ah, gia che ci sei togli quelle inutili String, ti fanno solo danni
Anche questo non è un consiglio, ma una condizione mecessaria per proseguire

Senza gli string non muovo il servo, dunque mi servono e torna intendo richiamare il menu non tornare il risultato di una funzione, cmq senza richiamare la funzione si ferma senza fare più nulla e ho provato vari modi per svuotare il buffer ma non c'è modo continua ad andare in loop...il problema è come posso interrompere momentaneamente il Serial.read??? perchè da come si comporta sembra che continui a richiamare la lettura della seriale...e ripeto questo problema si manifesta solo con le funzioni che implicano serial.read, nelle altre funziona perfettamente...

ciao jonny2031,

sinceramente non capisco perchè non fai quanto suggerito...che ti risolverebbe il problema...ed intendo il post #2 ed il post #4 (ribadito al post #8).

Diciamo che non sai muoverlo, è differente

Fai un giro su
Aiutateci ad aiutarvi
E
La pappa è fatta

Poi se ne parla

Aggiunta ultim'ora

Serio sei?

Ma se il serial.read() è dentro una if()...

Torno a dire: studia un pochino

void menu()
{
  Serial.print("Seleziona a-b-c-d:");
  while (1) {
    lista = 0;  // azzera la variabile lista
    if (Serial.available() > 0)
    {
      lista = Serial.read();
      Serial.println(lista);
    }

Rimuovi le chiamate ricorsive alla funzione menu().

Oppure se non ti serve che lista sia globale la dichiari locale al posto dell'azzeramento di lista.

Ciao.

#include <Servo.h>


Servo servo;
//String posProgSe;  //posizione programmata tramite seriale
//int posEff = 0;  //posizione effettiva
char lista;
int temp;
int led1 = 10;
int led2 = 11;


void velocita();
void movservoAv();
void movservoInd();
void menu();
void stampa();
void ledBlink();
void ledFade();


void setup()
{
  servo.attach(9);
  Serial.begin(9600);
  servo.write(0);
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  
  Serial.print("Seleziona a-b-c-d-e-f:");

}

void loop()
{
  menu();
}

void menu()
{

  if (Serial.available() > 0)
  {
    lista = Serial.read();
    Serial.println(lista);
  }

  switch (lista)
  {
    case 'a':
      velocita();
      break;

    case 'b':
      movservoAv();
      break;

    case 'c':
      movservoInd();
      break;

    case 'd' :
      stampa();
      break;

    case 'e' :
      ledBlink();
      break;

    case 'f' :
      ledFade();
      break;
  }
}

void velocita()
{
  temp = 0;
  delay(100);
  
  if(Serial.available() > 0)
  {
  temp = Serial.read();
  lista = " ";
  }
  
}


void movservoInd()
{
  lista = " ";
}

void movservoAv()
{
  lista = " ";
}


void stampa()
{
  Serial.println("prova");
  delay(10);

  lista = " ";
}

void ledBlink()
{
  for(int i = 0;i <= 10; i++)
  { 
  digitalWrite(led1, 1);
  delay(1000);
  digitalWrite(led1, 0);
  delay(1000);
  }
  lista = " ";
}
void ledFade()
{
  for (int i = 0; i <= 255; i++)
  {
    analogWrite(led2, i);
    delay(20);
  }
  for (int i = 255; i >= 0; i--)
  {
    analogWrite(led2, i);
    delay(20);
  }
  lista = " ";
}

Ho rimosso tutte le chiamate alla funzione "menu()" e ora va meglio,però ancora non ho trovato un modo per inserire dei valori tramite seriale per gestire i gradi del servo e anche il settaggio della velocità, dovrei trovare un modo di mappare il valore restituito dalla seriale, oltre a trovare il modo di non fargli interpretare come valore, il carattere che invio per eseguire la funzione.
Inoltre ho cercato altri modi per gestire un servo, ma per ora non sono riuscito a farli funzionare correttamente.

lista = " ";

Non così, ma come ti ho indicato io. Tra l'altro " " questa è una cstring e non un char dove servono gli apici singoli.

Ma vai tranquillo con lista = 0;

Ciao.

Non avevo visto, ok sistemato, ora cerco un modo per utilizzare i servi e impostare la velocità...intanto ti ringrazio.

#include <Servo.h>

Servo servo;
char valo[4];    //creo un vettore 3  per gli elementi da iserire e 1 per il carattere di ritorno                                 
int i = 0;                                                    
int pos;
void setup() {
  
  servo.attach(9);
  Serial.begin(9600);
}
void loop() {
  if (Serial.available() > 0) {   //se il seriale è disponibile
    char ch = Serial.read();     //utilizzo una variabile  per leggere i caratteri dalla seriale                           
    if (i < 3 && ch >= '0' && ch <= '9') {  //se la variabile i è minore di 3 e la variabile "read" è minore di 0 e maggiore di 9, se rimane all'interno del range di caratteri da 0 a 9                   
      valo[i++]=ch;    //carico nel mio vettore i valori letti dalla variabile "read "                                   
    }
    else {        //una volta che la variabile 'i' a superato il valore 3 e rispettato il range esce da if ed entra in "else".                                           
      valo[i] = 0;         //resetta il vettore                                      
      pos = atoi(valo);        // con la funzione atoi converto la stringa in un intero                                 
      i = 0;             //resetto la variabile                                      
    }
    
    Serial.print(ch);
  }
  servo.write(pos);
}

Ho trovato questo esempio, per creare una stringa di array char e convertire poi in int,quello che non capisco è quel "reset" al vettore prima di riversarlo nella variabile "pos" ?

Reset?
Se ti riferisci a questa riga
valo[i] = 0;
non è un reset, mette solo il terminarore di stringa.