Go Down

Topic: Leer palabra y hacer menú 100 casos? (Read 260 times) previous topic - next topic

radicalpepo

Hola chicos,
Tengo que recurrir a vosotros dado que mis conocimientos no son muy buenos en arduino.
La idea que tengo es desde una app en android pulsar botones o seleccionar de una lista y que se envie una palabra, dicha palabra dependiendo de lo que es que me haga una cosa u otra el arduino,. Serían alrededor de 100 palabras distintas, como puedo hacer el código en Arduino?
La parte de Android la tengo más o menos vista.
Gracias saludos

surbyte

Android y arduino se comunican por Bluetooth o por Internet. Tu elige y de ahi como seguir.

radicalpepo

En un principio por bluetooth, al pulsar un botón en la app que mande una palabra y el arduino que busque entre unos 100 casos y el caso que tenga esa palabra realice unas acciones.

surbyte

Usar BT es como usar el Monitor Serie para enviarle comandos asi que puedes probar con el enviando mensajes y que Arduino los reciba y haga lo que deba hacer.

Ahora el siguiente paso es que tienes 100 palabras. Bueno eso no es problema para Arduino. Se pueden almacenar en memoria flash para no consumir RAM.

Hagamos una lista con 10 palabras  y luego tu lo expandes a las otras 90.

Te daré dos ejemplos uno estilo sin Strings y otro con Strings. cual es el problema? que los Strings si no se usan bien suelen dar problemas pero no nos ocupemos de eso ahora.

Sin strings

Code: [Select]

#define CMDBUFFER_SIZE 32

void setup()
{
Serial.begin(9600);
}

void loop()
{
 
}
void serialEvent()
{
 static char cmdBuffer[CMDBUFFER_SIZE] = "";
 char c;
 while(Serial.available())
 {
   c = processCharInput(cmdBuffer, Serial.read());
   Serial.print(c);
   if (c == '\n')
   {
     Serial.println();
     //Full command received. Do your stuff here!
     if (strcmp("HELLO", cmdBuffer) == 0)
     {
        Serial.println("\r\nYou typed hello!");
     }
     cmdBuffer[0] = 0;
   }
 }
 delay(1);
}

char processCharInput(char* cmdBuffer, const char c)
{
 //Store the character in the input buffer
 if (c >= 32 && c <= 126) //Ignore control characters and special ascii characters
 {
   if (strlen(cmdBuffer) < CMDBUFFER_SIZE)
   {
     strncat(cmdBuffer, &c, 1);   //Add it to the buffer
   }
   else 
   {   
     return '\n';
   }
 }
 else if ((c == 8 || c == 127) && cmdBuffer[0] != 0) //Backspace
 {

   cmdBuffer[strlen(cmdBuffer)-1] = 0;
 }

 return c;
}


El segundo caso es con String

Code: [Select]

//zoomkat 3-5-12 simple delimited ',' string parce
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,
 
  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      //do stuff
      Serial.println(readString); //prints string to serial port out
      readString=""; //clears variable for new input     
     } 
    else {     
      readString += c; //makes the string readString
    }
  }
}


Una vez que tienes el valor en la variable readString simplemente lo comparas asi

Code: [Select]
if (readString == "Hola") {
   // Accion
}



Yo pondría las 100 palabras en un vector de modo que se puedan comparar dentro de un ciclo.


radicalpepo

Buenas,
Entiendo que cuando dices con vectores que use:
"string vector[5] = {"5", "hola", "2.7", "8,9", "adios"};"
Pero como lo intengro en el codigo exactaemnte?
gracias saludos

surbyte

Ahh bueno, ya entendiste los dos códigos que sugerí?

Pues como te dije, dentro de un cliclo for, lo vas barriendo por índice.
El vector tiene un índice que identifica su elemento.

De tu ejemplo el
vector[0] es "5"
vector[1] es "hola"

por lo tanto si tu tienes un
Code: [Select]
for(byte i=0; i<5; i++) {
     if (readString == vector[i])
         valor = i;                      // este valor es el que te permite luego elegir que hacer
}


Con ese valor que previamente definiste como byte por supuesto.

Dentro de un switch case puedes controlar que hacer con cada palabra que resultó positiva a la comparación.
Habran 99 falsos y 1 positivo y arduino responderá a eso.

Ahora veo un programa algo grande de modo que cuidado con el arduino que uses y el consumo de memoria.

Desde ya que usar String vector[100] = {cada item} no es de mi agrado por el gran consumo en RAM.

Yo sugería que usaras PROGMEM.

Si no lo sabes es la opción que te da Arduino para guardar datos en la memoria FLASH y no consumir RAM.

radicalpepo

Buenas,
Muchas gracias por toda la ayuda que me prestas, Como se usaria PROGMEM?
Yo tengo un arduino mega.
saludos gracias

radicalpepo

#7
May 18, 2018, 04:02 pm Last Edit: May 18, 2018, 04:33 pm by surbyte
Buenas Adjunto el codigo que llevo echo hasta ahora.


Code: [Select]


#include <SoftwareSerial.h>
SoftwareSerial Bluetooth(2,3); // RX, TX Esto le decimos en que pines esta conectado el Bluetooth
                         //Cuando conecte el bluetooth pondre los pines donde lo conecte

int pin18 = 18;  //reserva
int pin19 = 19;  //reserva

int pin20 = 20;
int pin21 = 21;
int pin22 = 22;
int pin23 = 23;
int pin24 = 24;
int pin25 = 25;
int pin26 = 26;
int pin27 = 27;
int pin28 = 28;
int pin29 = 29;
int pin30 = 30;
int pin31 = 31;
int pin32 = 32;
int pin33 = 33;
int pin34 = 34;
int pin35 = 35;
int pin36 = 36;
int pin37 = 37;
int pin38 = 38;
int pin39 = 39;
int pin40 = 40;
int pin41 = 41;
int pin42 = 42;
int pin43 = 43;
int pin44 = 44;
int pin45 = 45;
int pin46 = 46;
int pin47 = 47;
int pin48 = 48;
int pin49 = 49;
int pin50 = 50;
int pin51 = 51;
int pin52 = 52;
int espera = 150; // El tiempo que se esperara

String dato = "";

void setup(){

for(int i=18;i<=52;i++){ //SE INICIALIZAN TODOS LOS PINES COMO SALIDA
 pinMode(i, OUTPUT);
}


//Inicializamos el valor de transmisión.
Serial.begin(9600);//Inicializamos el serial normal
Bluetooth.begin(9600); //inicializamos bluetooth

}

void loop() {
//INICIALIZAMOS TODOS LOS PINES COMO APAGDOS
    for (int i= 18; i<=52; i++)
     {
    digitalWrite(i,LOW);
     //delay(500);
     }
//Declaramos un sentencia, Mientras el puerto Serial este disponible se empieza el ciclo

while (Bluetooth.available())
 {
  

   String dato = Bluetooth.readStringUntil('\n');
   switch ('dato'){
   case 'dato' == 'A.ON' ; //Si en el caso de ser A.ON la varible enviada, entonces
      {
       digitalWrite(pin20,HIGH);
       }
       break;
      
   case 'dato' == 'A.OFF' ; //Si en el caso de ser A.OFF la variable enviada, entonceS
     {
       digitalWrite(pin20,LOW);
     }
       break;

  
//escribimos los demas casos!


   }
 }
}

surbyte

Code: [Select]
switch ('dato'){
   case 'dato' == 'A.ON' ; //Si en el caso de ser A.ON la varible enviada, entonces



'dato' no puede ser un elemento dentro de switch()
switch() espera una variable que toma estados enteros.

case 'dato' tampoco puede ser y menos esto

Code: [Select]
   case 'dato' == 'A.ON'


Los strings van entre "" o sea algo mas apropiado sería "A.ON" pero aún asi esta mal

Te expliqué como debes hacerlo.

Y toda duda que tengas solo pones en google : Arduino PROGMEM y sabrás como se usa.



surbyte

Prueba asi

Code: [Select]
#include <SoftwareSerial.h>
SoftwareSerial Bluetooth(2,3); // RX, TX Esto le decimos en que pines esta conectado el Bluetooth
                         //Cuando conecte el bluetooth pondre los pines donde lo conecte

int pin18 = 18;  //reserva
int pin19 = 19;  //reserva

int pin20 = 20;
int pin21 = 21;
int pin22 = 22;
int pin23 = 23;
int pin24 = 24;
int pin25 = 25;
int pin26 = 26;
int pin27 = 27;
int pin28 = 28;
int pin29 = 29;
int pin30 = 30;
int pin31 = 31;
int pin32 = 32;
int pin33 = 33;
int pin34 = 34;
int pin35 = 35;
int pin36 = 36;
int pin37 = 37;
int pin38 = 38;
int pin39 = 39;
int pin40 = 40;
int pin41 = 41;
int pin42 = 42;
int pin43 = 43;
int pin44 = 44;
int pin45 = 45;
int pin46 = 46;
int pin47 = 47;
int pin48 = 48;
int pin49 = 49;
int pin50 = 50;
int pin51 = 51;
int pin52 = 52;
int espera = 150; // El tiempo que se esperara
String vector[5] PROGMEM = {"A.ON", "A.OFF", "B.ON", "B.OOF", "OFF"};
String dato = "";

void setup(){
    for (int i=18;i<=52;i++){ //SE INICIALIZAN TODOS LOS PINES COMO SALIDA
        pinMode(i, OUTPUT);
    }
    //Inicializamos el valor de transmisión.
    Serial.begin(9600);//Inicializamos el serial normal
    Bluetooth.begin(9600); //inicializamos bluetooth
}

void loop() {
//INICIALIZAMOS TODOS LOS PINES COMO APAGDOS
  for (int i= 18; i<=52; i++)  {
      digitalWrite(i,LOW);
      //delay(500);
  }
  //Declaramos un sentencia, Mientras el puerto Serial este disponible se empieza el ciclo
  while (Bluetooth.available()) {
   
    String dato = Bluetooth.readStringUntil('\n');
    for (byte i = 0; i<5; i++) {
        if (dato == vector[i]) { // si coincide entonces i me dice que posicion coincidió
            valor = i;
        }
    }
  }
  switch (valor){
      case 0:   //Si en el caso de ser A.ON la varible enviada, entonces
                digitalWrite(pin20,HIGH);
                break;
      case 1:   //Si en el caso de ser A.OFF la variable enviada, entonceS
                digitalWrite(pin20,LOW);
                break;
      case 2:   //Si en el caso de ser B.ON la variable enviada, entonceS
                digitalWrite(pin21, HIGH);
                break;
      case 3:   //Si en el caso de ser B.OFF la variable enviada, entonceS
                digitalWrite(pin21,LOW);
                break;
      case 4:   //Si en el caso de ser OFF la variable enviada, entonceS
                digitalWrite(pin22,LOW);
                break;
  }
}

radicalpepo

#10
Jul 18, 2018, 10:42 am Last Edit: Jul 18, 2018, 08:44 pm by surbyte Reason: Agregado de etiquetas de código y errores.
Buenas, ya he retomado el proyecto,
Me esta dando errores y a ver si me puedes ayudar.
gracias

Code: [Select]

#include <SoftwareSerial.h>
SoftwareSerial Bluetooth(0,1); // RX, TX Esto le decimos en que pines esta conectado el Bluetooth
                          //Cuando conecte el bluetooth pondre los pines donde lo conecte


int pin18 = 18;  //reserva
int pin19 = 19;  //reserva

int pin20 = 20; //Defino los pines con nombres para poder diferenciar mejor
int pin21 = 21; //En vez de poner solo 21 ponemos pin21
int pin22 = 22; //asi sabemos que pin21 es la salida digital 21
int pin23 = 23;
int pin24 = 24;
int pin25 = 25;
int pin26 = 26;
int pin27 = 27;
int pin28 = 28;
int pin29 = 29;
int pin30 = 30;
int pin31 = 31;
int pin32 = 32;
int pin33 = 33;
int pin34 = 34;
int pin35 = 35;
int pin36 = 36;
int pin37 = 37;
int pin38 = 38;
int pin39 = 39;
int pin40 = 40;
int pin41 = 41;
int pin42 = 42;
int pin43 = 43;
int pin44 = 44;
int pin45 = 45;
int pin46 = 46;
int pin47 = 47;
int pin48 = 48;
int pin49 = 49;
int pin50 = 50;
int pin51 = 51;
int pin52 = 52;
int espera = 150; // El tiempo que se esperara

String vector[5] PROGMEM = {"A.ON", "A.OFF", "B.ON", "B.OOF", "OFF"};
String dato = "";

void setup(){

for(int i=18;i<=52;i++){ //SE INICIALIZAN TODOS LOS PINES COMO SALIDA
  pinMode(i, OUTPUT);
}

Serial.begin(9600);//Inicializamos el serial normal
Bluetooth.begin(9600); //inicializamos bluetooth

}

void loop() {
//INICIALIZAMOS TODOS LOS PINES COMO APAGDOS
     for (int i= 18; i<=52; i++)
      {
     digitalWrite(i,LOW);
      //delay(500);
      }
//Declaramos un sentencia, Mientras el puerto Serial este disponible se empieza el ciclo
while (Bluetooth.available())
  {
    
//Declaramos una variable de tipo cadena y Se lee lo enviado desde el Bluetooth.  
    String dato = Bluetooth.readStringUntil('\n'); //lee la cadena que enviamos por bluetooth
    for (byte i = 0; i<5; i++) {
        if (dato == vector[i]) { // si coincide entonces i me dice que posicion coincidió
            valor = i;
        }
    }

    
    
    
    
    
    switch (valor){
    case 'dato' == "A.ON"; //Si en el caso de ser A.ON la varible enviada, entonces:
       {
        digitalWrite(pin20,HIGH);
        }
        break;
    case 'dato' == "A.OFF"; //Si en el caso de ser A.OFF la variable enviada, entonceS:
      {
        digitalWrite(pin20,LOW);
      }
        break;

    
//seguir todos los casos como entradas tengamos


    }
  }
}


ArduMyth

#11
Jul 18, 2018, 03:49 pm Last Edit: Jul 18, 2018, 04:00 pm by ArduMyth
Para mí todo el planteamiento en modo "cascada" no es muy útil.
Luego analiza que si tus comandos van a ser letras hay un problema respecto a tu código y es que tienes mas pines que letras del abecedario así que al parsear esto vas a complicar más tu código.

¿No sería más útil para quien maneje la APP que el comando fuera un número y no una letra y que este número corresponda NO con el pin del Arduino sino con led numerado que quisiera cambiar; el primero, tercer o decimosexto led...

Así que replantea tu sketch y analiza ¿Realmente necesitas toda esa cascada?
Hay gente en el foro que tiende a molestarse por correcciones pero piensa que yo no saco nada ayudando. Puedes plantear lo que digo o pasar, yo ni pierdo ni gano y aunque la gente se moleste creo que es mejor 20 líneas que 200.

Esto es un ejemplo. Por favor nótese que no está hecho a tú medida, es un ejemplo para Arduino UNO, en tu caso cambia los valores desdePin y hastaPin por el primer led y el último que utilices, luego los pines del blutooth, elimina la línea donde se asigna el valor a la variable dato y posteriormente descomenta la lectura del bluetooth

Repito es un ejemplo, no tienes por qué hacerlo así, pero fíjate cómo variando el planteamiento se reduce todo y encima está completo y funciona.
Code: [Select]

#define desdePin 2
#define hastaPin 9

#include <SoftwareSerial.h>
SoftwareSerial Bluetooth(10, 11); // RX | TX

bool estados[hastaPin + 1 - desdePin] = {};
String dato = "";

void setup() {
  Serial.begin(9600);
  Bluetooth.begin(9600); 
  for(byte i = desdePin; i <= hastaPin; i++){
    pinMode(i, OUTPUT);
  }
}

void loop() {
  /*while(Bluetooth.available()) {
    dato = Bluetooth.readStringUntil('\n');
  }*/
  dato = "3.ON"; //eliminar línea al hacer la lectura blueooth (esto es un ejemplo)
  int separador = dato.indexOf(".");

  if( separador != -1 ){
    int pin = dato.substring(0,separador).toInt();
    dato = dato.substring(separador+1);
    if( pin < hastaPin + 1 - desdePin && (dato == "ON" || dato == "OFF") ){
      estados[pin - desdePin + 1] = (dato == "ON") ? true : false;
      //Serial.println(pin);
    }
  }
  else if(dato == "ON" || dato == "OFF"){
    for(byte e = 0; e < hastaPin + 1 - desdePin; e++){
      estados[e] = (dato == "ON") ? true : false;
    }
  }

  for(byte i = 0; i < hastaPin + 1 - desdePin; i++){
    digitalWrite(i + desdePin, estados[i]);
    //Serial.println("pin: " + String(i + desdePin) + " : " + String(estados[i]));
  }
}

Si te fijas al poner "ON" encenderíamos todo, "OFF" apagaría todo, y en el caso concreto del ejemplo donde pongo "3.ON" indica que el tercer LED (pin: 4, al empezar desde el pin 2) estará encendido.

Cómo además se guardan los estados en un array de bools mantendremos el estado de los leds hasta que se asigne un valor que indique lo opuesto.

Es decir que adaptándolo a tus pines "3.ON" encendería el pin pin20 ya que partes del 18.
18,19,20... Al usuario no le interesa el pin, sólo el número del led que quiere encender y es más simple de proceder que usando una letra.

Saludos.

Go Up