¿Cómo hacer que un Arduino espere hasta que reciba datos en serie?

Así que conecté un pequeño robot con un escudo de sonido y algunos sensores. Estoy tratando de escribir un boceto que permita verificar los sensores.

Lo que me gustaría que hiciera es imprimir un pequeño menú en serie, esperar hasta que el usuario envíe una selección, saltar a la función que coincida con su selección, luego (una vez que la función haya terminado) retroceder e imprimir el menú nuevamente . Esto es lo que he escrito, pero no soy tan bueno programando, así que no funciona. ¿Dónde me estoy equivocando?

#include <Servo.h>
Servodirección;
servo acelerador;
pos int = 0;
valor int = 0;configuración 
vacía () {
   Serial .begin (9600);
  acelerador.escribir(90);
  dirección.escribir(90);
  pinMode(A0, ENTRADA);
  pinMode(7, ENTRADA);
  char ch = 0;
}bucle 
vacío (){
   Serial .println("Menú");
  Serial .println("--------------------");
  Serial .println("1. Lectura de movimiento");
  Serial .println("2. Lectura de distancia");
  Serial .println("3. Listado de Directorio SD");
  Serial .println("4. Prueba de sonido");
  Serial .println("5. Prueba de coche");
  Serial .println("--------------------");
  Serial .println("Escriba el número y presione enter");
  while(char ch = 0){
  ch =  Serie .leer();}
  char ch;
  cambiar (ch)
  {
    caso 1':
    movimiento();
  }
   ch = 0;
}
//menú terminado, pongámonos a trabajar.
movimiento nulo(){
  Serial .println("¡Jaja, funciona!");
}

Estoy bastante seguro de que un bucle While es lo correcto, pero probablemente lo esté implementando mal. ¿Alguien puede arrojar algo de luz sobre esto?

Primero, aquí en el mundo real, "escudo" y "boceto" son palabras normales que no tienen sentido tal como las usaste. No, la gente de marketing de arduino no puede redefinir las palabras estándar en inglés y hacer que el resto de nosotros sigamos. En segundo lugar, este es un problema de software. Seguramente hay una llamada de bloqueo disponible en las bibliotecas para obtener el siguiente byte de la UART.
@OlinLathrop, Etiquetémoslo como arduino y aceptemos que este es el idioma que usan dentro de su comunidad, siéntanse libres de compartir que no es un idioma común en ningún otro lugar, pero está bien si eligen usar ese término.
@Kortuk: No, no estoy de acuerdo con eso. Me doy cuenta de que esos son los términos utilizados en la comunidad arduino, pero tienen significados específicos y diferentes en cualquier otro lugar. Este es un foro de electrónica general, no un foro de arduino. Si la gente de arduino viene aquí, tiene que estar preparada para hablar correctamente de electrónica general. También me molesta profundamente cómo la gente de arduino ha tratado de secuestrar palabras comunes en inglés para su uso privado. Se debe hacer todo lo posible para no tolerar esto en el mundo más grande. Como mínimo, podemos educar a las personas que vienen aquí usando términos incorrectos.
@OlinLathrop, traté de decir esto antes, pero es posible que no me haya comunicado. Explicar las definiciones adicionales de esta palabra es muy útil, especialmente cuando el usuario se ramifica. Las etiquetas son una forma de casi crear subsitios coexistentes, si está hablando en preguntas que tienen la etiqueta arduino , puede esperar que se use escudo de esta manera, intentar forzar a la comunidad a usar una palabra diferente en todas partes hará que las preguntas sean significativamente menos útil para la comunidad arduino en general. Educar pero tratar de aceptar que se utilizará un término diferente en sus preguntas.
@OlinLathrop: Espero que "edjucate" fuera irónico =P
@OlinLathrop Qué suerte que el resto del mundo tenga cuidado de nunca reutilizar o sobrecargar los términos. Como corriente, código, cable o potencia.
@OlinLathrop: El inglés no funciona de la manera que quieres. Es un lenguaje que redefine constantemente los significados de las palabras: ¿ratón? ¿trampa? ¿interrumpir? ¿llamar? ¿operador? ¿monitor? ¿pantalla? ¿puerto? ¿corto? ¿función? ¿autobús? Los ingenieros (como usted) siempre han elegido palabras con significados similares al concepto que tienen en mente. La gente de Arduino no es diferente, ya que ellos mismos suelen ser ingenieros.
@OlinLathrop: si desea un idioma estable que requiera aprobación formal/regulatoria antes de que se pueda usar una palabra, pruebe el francés. O incluso mi lengua materna: malayo (en forma de bahasa malayo, ya que hay varios idiomas malayos por ahí)
@OlinLathrop: Por cierto, el término "boceto" tiene un significado específico porque un bosquejo es un programa C que no tiene principal (tiene configuración y bucle en su lugar). Se compila en un programa que luego se compila en binario. Esto es lo suficientemente específico como para darle un nombre. Al igual que los archivos de interfaz en SWIG (nuevamente una palabra cooptada (me refiero a Interfaz, no a SWIG ya que SWIG es un acrónimo apropiado))

Respuestas (3)

Aquí hay algunas sugerencias:

  • mover la declaración de ch arriba del ciclo while
  • usó = en lugar de ==, por lo que while( ch = 0)se repetirá para siempre, porque ch = 0 siempre se evaluará como verdadero. Debería serwhile( ch == 0)
  • refactorice la visualización de su menú en una DisplayMenu()función, solo porque es más limpio de esa manera, luego llame DisplayMenu()desde loop().
Tampoco cambie el valor del carácter que lee. Haz algo como "mientras (repetir)" y cambia el valor de repetir a falso cuando quieras detenerlo. No olvides inicializar "repeat=true"
No estoy de acuerdo con esto, ya que es una práctica perfectamente válida y estándar evaluar un carácter de entrada en un ciclo while. Simplemente tuvo un error de sintaxis de igualdad y usó = en lugar de ==. Pero dentro de un bucle, estaría de acuerdo con lo que dijiste sobre modificar el valor del carácter de entrada, ya que obviamente eso anula el objetivo de capturar la entrada del teclado.
No digo que no deba evaluar un carácter de entrada en un ciclo while, solo digo que no debe cambiar su valor dentro del ciclo.
lo siento, pensé que te referías a cómo cambió el valor dentro de la evaluación. ;)

si colgara su programa hasta que haya un comando serial:

usa esto como ejemplo

Serial.flush(); //flush all previous received and transmitted data
while(!Serial.available()) ; // hang program until a byte is received notice the ; after the while()
/*continue program ...*/

y tal vez puedas escribir una función

void displayMenu(){
...
}

y llámalo cuando quieras

votado porque responde claramente a la pregunta. Desafortunadamente, el error tipográfico en while (ch == 0); no fue mencionado.

Este código es para el coche robot arduino.

#include "SPI.h"
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include "HMC5883L.h"
#include "Servo.h"
Servo Servo_8;
Servo Servo_9;
Servo Servo_10;
Servo Servo_11;
Servo Servo_12;
Servo Servo_13;
int IN1=23;
int IN2=22;
int IN3=24;
int IN4=25;
int ENA=5                            ;
int ENB=4;
int LED1=11;
int LED2=12;
float k_8;
float k_9;
float k_10;
float k_11;
float k_12;
float k_13;
float speed_9=1500;
float speed_8=1500;
float speed_10=1500;
float speed_11=1500;
float speed_12=1500;
float speed_13=1500;


struct Axis  // Datas from remote control 
{
 uint16_t axis_1;
 uint16_t axis_2;
  uint16_t axis_3;
 uint16_t axis_4;
 uint16_t axis_5;
 uint16_t axis_6;
 uint16_t axis_7;
  uint16_t axis_8;
};
Axis axis_x;

struct Gesture  // Datas send back to remote control 
{
  long Joystick_1_X;
  long Joystick_1_Y;
  long Joystick_2_X;
  long Joystick_2_Y;
  long Joystick_1;
  long Joystick_2;
  uint16_t null_1;
  uint16_t null_2;
};
Gesture data;

void setup()
{
  Wire.begin();
  Serial.begin(115200);
  ///////////////////////////////////////////
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);
  pinMode(ENA,OUTPUT);
  pinMode(ENB,OUTPUT);
  pinMode(LED1,OUTPUT);
  pinMode(LED2,OUTPUT);
  digitalWrite(IN1,HIGH);
  digitalWrite(IN2,HIGH);
  digitalWrite(IN3,HIGH);
  digitalWrite(IN4,HIGH);
  Servo_8.attach(8);
   Servo_9.attach(9);
  Servo_10.attach(10);
  Servo_11.attach(11);
  Servo_12.attach(12);
  Servo_13.attach(13);

  /* Part of the protection codes.If he robot was turned on with the angle over 45(-45) degrees,the wheels 
   will not spin until the robot is in right position. */

  // 24L01 initialization
  Mirf.cePin = 53;
  Mirf.csnPin = 48;
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte *)"serv1");
  Mirf.payload = 1
  //////////////////////////////////////////////
}

void loop() 
{   
   Recive();
   Arm_Control();

}
 //////////////////////////////////////////////////////
void Recive()
{
  if(!Mirf.isSending() && Mirf.dataReady()){  // Read datas from the romote    contYawer
    Mirf.getData((byte *) &axis_x);
    //Serial.print("data="); Serial.print(axis_x);
//Serial.print("axis_1=");
//Serial.println(axis_x.axis_1);
/*Serial.print("  axis_2=");
Serial.print(axis_x.axis_2);
Serial.print("  axis_3=");
Serial.print(axis_x.axis_3);
Serial.print("  axis_4=");
Serial.print(axis_x.axis_4);
Serial.print("  axis_5=");
Serial.print(axis_x.axis_5);
Serial.print("  axis_6=");
Serial.print(axis_x.axis_6);
Serial.print("  axis_7=");
Serial.print(axis_x.axis_7);
Serial.print("  axis_8=");
Serial.println(axis_x.axis_8);*/

Mirf.setTADDR((byte *)"clie1");
Mirf.send((byte *) &data);  // Send datas back to the contYawer


 }
  else
  {
    axis_x.axis_1 = axis_x.axis_2 = 500;
   }
}
 void Arm_Control()
{
  if((axis_x.axis_5==1)&&(axis_x.axis_1 > 550))
 {
   k_10 = -map(axis_x.axis_1, 531, 1023, 0, 500)*0.01;
  }
  else if((axis_x.axis_5==1)&&(axis_x.axis_1 < 450))
  {
    k_10 = -map(axis_x.axis_1, 0, 469, -500, 0)*0.01;
  }
  else{
    k_10 = 0;
  }

  if((axis_x.axis_5==1)&&(axis_x.axis_2 > 550))
  {
    k_8 = -map(axis_x.axis_2, 531, 1023, 0, 500)*0.01;
  }
  else if((axis_x.axis_5==1)&&(axis_x.axis_2 < 450))
  {
    k_8 = -map(axis_x.axis_2, 0, 469, -500, 0)*0.01;
  }
   else{
    k_8 = 0;
  }
    if((axis_x.axis_5==0)&&(axis_x.axis_2 > 550))
  {
    k_9 = -map(axis_x.axis_2, 531, 1023, 0, 500)*0.01;
  }
  else if((axis_x.axis_5==0)&&(axis_x.axis_2 < 450))
  {
    k_9 = -map(axis_x.axis_2, 0, 469, -500, 0)*0.01;
  }
  else{
    k_9 = 0;
  }

  if((axis_x.axis_5==0)&&(axis_x.axis_1 > 550))
  {
    k_12= -map(axis_x.axis_1, 531, 1023, 0, 500)*0.01;
  }
   else if((axis_x.axis_5==0)&&(axis_x.axis_1 < 450))
  {
    k_12= -map(axis_x.axis_1, 0, 469, -500, 0)*0.01;
  }
  else{
    k_12 = 0;
    }
  if((axis_x.axis_6==0)&&(axis_x.axis_4 > 550))
  {
    k_13= -map(axis_x.axis_4, 531, 1023, 0, 500)*0.01;
  }
  else if((axis_x.axis_6==0)&&(axis_x.axis_4 < 450))
  {
    k_13= -map(axis_x.axis_4, 0, 469, -500, 0)*0.01;
  }
  else{
    k_13 = 0;
  }
   if((axis_x.axis_6==1)&&(axis_x.axis_4 > 550))
  {
    k_11= -map(axis_x.axis_4, 531, 1023, 0, 500)*0.001;
  }
  else if((axis_x.axis_6==1)&&(axis_x.axis_4 < 450))
  {
    k_11= -map(axis_x.axis_4, 0, 469, -500, 0)*0.001;
  }
  else{
    k_11 = 0;
  }
  speed_8 = min(2000, max(800, speed_8 += k_8));
  speed_9 = min(1800, max(1000, speed_9 += k_9));
  speed_10 = min(2500, max(500, speed_10 += k_10));
  speed_11 = min(1800, max(1000, speed_11 += k_11));
  speed_12 = min(1800, max(1000, speed_12 += k_12));
  speed_13 = min(1900, max(1200, speed_13 += k_13));

 Serial.print("  speed_8="); Serial.print(speed_8);Serial.print("        speed_9="); Serial.print(speed_9);
 Serial.print("  speed_10="); Serial.print(speed_10);Serial.print("   speed_11="); Serial.print(speed_11);
 Serial.print("  speed_12="); Serial.print(speed_12);Serial.print("     speed_13="); Serial.println(speed_13);

 Servo_9.writeMicroseconds(speed_9);  
 Servo_8.writeMicroseconds(speed_8);
 Servo_10.writeMicroseconds(speed_10);
 Servo_11.writeMicroseconds(speed_11);
 Servo_12.writeMicroseconds(speed_12);
 Servo_13.writeMicroseconds(speed_13);
 }