ROBOT PROGRAMABLE

hola amigos, intento hacer un robot, programable, que siempre que encienda realice ciertos movimientos.
el robot es muy sencillo consta del control de dos motores, cada uno hace girar una rueda, si quiero ir al frente giro ambas ruedas en un sentido, si quiero ir de reversa, ambas ruedas giran en el otro sentido, si quiero ir a la derecha solo giro la rueda izquierda y si quiero ir a la izquierda solo giro la derecha.

Para programar el robot, pienso desarrollar una Aplicación en android que envié varios datos de tipo texto vía conexión serial USB por medio del cable OTG, y que estos datos se queden guardados en un vector, para que cuando desconecte el USB y cada vez que encienda el robot, se ejecuten los movimientos.

Este es el código que tengo hasta ahora para arduinonano, pero desconozco si realmente hace los que planteo ya que por cuestiones económicas aun no cuento con los recursos necesario para realizar las pruebas , espero me puedan ayuda en este proyecto, gracias por su atención y cualquier comentario se los agradeceré de antemano

// a= adelante, b= atras c= izquierda, d= derecha, e= pausa 


int izqA = 5; 
int izqB = 6; 
int derA = 9; 
int derB = 10; 
int vel = 255; // Velocidad de los motores (0-255)

void setup()  { 

Serial.begin(9600);  /// CARGAR LOS DATOS del arreglo y el tamaño del   arreglo,   via  OGT USB, para posteriormente ser ejecutados ya sin la conexión  


char coreografia[] = {a, a, b, d, e, c};  

int contador= 0
int tvector= 6


pinMode(derA, OUTPUT);
pinMode(derB, OUTPUT);
pinMode(izqA, OUTPUT);
pinMode(izqB, OUTPUT);
} 

 void loop()

 {

  for( int contador=0; contador<tvector; contador++){

  paso = coreografia[contador];


 if(paso = a){
 analogWrite(derA, vel);  // Frente 2 segundos
 analogWrite(izqA, vel); 
 delay (2000);
 }

if(paso = b){
analogWrite(derB, vel);  // Reversa 2 segundos
analogWrite(izqB, vel); 
delay (2000);        
}

if(paso = c){
analogWrite(derA, 0);    // Izquierda 0,5 segundos
analogWrite(izqA, vel); 
delay (500);      
}

if(paso = d){
analogWrite(derA, vel);  // Derecha 0,5 segundos
analogWrite(izqA, 0); 
delay (500);     
}

if(paso = e){
analogWrite(derB, 0);  // Detiene los Motores por 0,5 segundos 
analogWrite(izqB, 0); 
delay (500);    
}
}
}

//Al prender el robot, se ejecutaran las instrucciones pre-cargadas

famjaes:
para que cuando desconecte el USB y cada vez que encienda el robot, se ejecuten los movimientos.

Supongo que es para evitar tener que reprogramar por completo el Arduino.
Si dices que “cada vez que se encienda”, entonces no esperes que el programa recuerde información si no es almacenado de antemano en un medio no volátil.

Cada vez que el “array” de la secuencia de pasos cambie, debe escribirse en esa pequeña memoria no volátil llamada EEPROM, la cual no se borra ni reprogramando el Arduino.

PD: código entre etiquetas generados por </>

Muchas gracias por responder, en caso que desee escribir nuevos pasos de baile, entonces puedo volver a trasferir vía USB los nuevos pasos, y borrar los anteriores?

En vez de usar EL for un arreglo, puedo usarlos en la memoria EEPROM para recorrerla?

Mi idea es la siguiente:

  • El tamaño del array debe ser constante (podría ser de 65 ya que 64 bytes es el tamaño por defecto del búfer serial).
  • En el setup se lee el contenido en la EEPROM, y se guarda en este array.
  • En el loop es dónde se verifica si hay contenido nuevo en el serial; si lo hay, almacenarlo en el array para posteriormente actualizarlo en la EEPROM.

Porque no miras lo que ya esta hecho. Este tema esta hecho como auto de control de radio numerosas veces, sea por BlueTooth, Radio, nRF24L01, ZigBee o Wifi
En este foro hay muchos ejemplos.

**Edita tu post inicial y pon el código usando tags o etiquetas. **
Lee las normas del foro!!!
Ya respondiste desobedeciendo el consejo de Lucario448, ahora te lo pide un moderador.

@Lucario448 gracias, algo así tenia pensado, si detecta el cable serial o si detecta la transferencia de datos, ejecutar un FOR o un bucle para ir llenando o actualizando los datos la memoria EEPROM,

si no hay ningún cable o no se esta trasfiriendo nada vía serial, ejecutar un FOR para recorrer la memoria EEPROM y ejecutar los movimiento del robot
.....
amigo @surbyte, ya he visto varios proyectos de este pero usan dispositivo como bluethoo, Wifi etc.

en mi caso lo que pretendo es conectar el robot con un cable USB a mi movil, y con una APP cargar las instrucciones al robot, luego desconectar el robot de mi movil, y por ultimo que sólito el robot realice los movimientos cargados, y que esto ocurra cada vez que se encienda el robot, así también poder volver a cargar nuevas instrucciones a futuro

famjaes:
@Lucario448 gracias, algo así tenia pensado, si detecta el cable serial o si detecta la transferencia de datos, ejecutar un FOR o un bucle para ir llenando o actualizando los datos la memoria EEPROM,

si no hay ningún cable o no se esta trasfiriendo nada vía serial, ejecutar un FOR para recorrer la memoria EEPROM y ejecutar los movimiento del robot

Veo que ya nos vamos entendiendo, solo que yo preferiría cuidar más de esta EEPROM. Cómo? Fácil:

  • La lectura se hace “a bulto”, y únicamente en el setup (al arrancar el programa). Los datos se quedan en memoria (array).
  • La escritura se hace únicamente cada vez que algo nuevo ingresa (primero en memoria, luego “a bulto” en la EEPROM).

Hola amigos del foro, actualizando un poco los avances del proyecto, este es e esquema de conexión,
me gustaría que lo revisasen para ver si esta correcto, no voy a usar un protoard debido a los costos, así que necesito saber si esta correctamente conectado el circuito, gracias por el apoyo de antemano y saludos, también estoy pesando utilizar la batería de celular de 3.7v para alimentar todo el proycto entonces debo conectar a la ranura del arduinonano a 3.3V en vez de 5 ?

No debiste crear otro hilo preguntando sobre eso.
Por las entradas de voltaje no estoy seguro; pero el resto se ve bien.

Ahora el tema de la EEPROM:

Lucario448:
solo que yo preferiría cuidar más de esta EEPROM. Cómo? Fácil:

  • La lectura se hace “a bulto”, y únicamente en el setup (al arrancar el programa). Los datos se quedan en memoria (array).
  • La escritura se hace únicamente cada vez que algo nuevo ingresa (primero en memoria, luego “a bulto” en la EEPROM).

Veo que no sabes qué es “a bulto”, así que te daré un ejemplo:

#include <EEPROM.h>

char coreografia[65];
byte caracteresValidos;

void setup() {
  leerEEPROM();
  // El resto de cosas
}

void loop () {
  if (Serial.available()) {
    delay(100);
    programarCoreografía();
  }
  ejecutarCoreografía();
}

void leerEEPROM() {
  EEPROM.get(0, coreografia);
  caracteresValidos = strlen(coreografia);
}

void programarCoreografía() {
  coreografia[Serial.readBytes(coreografia, Serial.available())] = 0;
  caracteresValidos = strlen(coreografia);
  EEPROM.put(0, coreografia);
}

void ejecutarCoreografía() { 
  for (byte i = 0; i < caracteresValidos; i++) {
// La nueva secuencia no se programará hasta que esta acabe; si esa no es la idea, entonces habrá que hacerlo un poco diferente.
    switch (coreografia[i]) {
      // Lo de aquí supongo que es historia ya conocida
    }
  }
}

Gracias por responder amigo @lucario, pensé que ya estaba descontinuado el tema, bueno estuve googleando y googleando y encontré un simulador de arduino y con prueba y error este es el codigo que hasta el momento me esta funcionando.

aunque creo que no es eficiente, y que tendré que estar metiendo el total de datos para sobreescribir en la memoria, te lo muestro para que me comentes tu opinión

un rápida explicación, primero compruebo si existe un valor mayor a 0, si existe entonces en el bucle recorro y guardo en la EEPROM los datos que recibo desde android, y posteriormente se ejecutan las instrucciones de forma similar como las guarde pero ahora las voy leyendo…

entonces cuando trasfiera los datos vía serial USB OTG desde android, desconecto el cable de energía de los motores, una vez que termine la trasferencia conecto la bateria y se comienzan a ejecutar las instrucciones guardadas en la eeprom una y otra vez, entoces si quiero cambiar las instrucciones nuevamente conecto el usb otg y trasfiero los datos desde android para reescribirlos en la memoria eeprom y ejecutar los nuevos pasos

  #include <EEPROM.h>

int izqA = 5; 
int izqB = 6; 
int derA = 9; 
int derB = 10; 
int vel = 255;            // Velocidad de los motores (0-255)
int estado2 = 'e';// inicia detenido
int estado = 'e';// inicia detenido
int i = 0; 
int j = 0;


void setup()  { 
  Serial.begin(9600);    // inicia el puerto serial para comunicacion con el USB
  pinMode(derA, OUTPUT);
  pinMode(derB, OUTPUT);
  pinMode(izqA, OUTPUT);
  pinMode(izqB, OUTPUT);
  pinMode(13,OUTPUT);
  
  
  
} 

void loop()  { 
  
 
 
 if(Serial.available()>0){        // lee el datos de USB y almacena en la eeprom
    estado = Serial.read();
    EEPROM.write(i, estado);
    i = i + 1; 
  }
  
  
  estado2 = EEPROM.read(j);
  
  if(estado2=='a'){           // frente
   analogWrite(derB, 0);     
    analogWrite(izqB, 0); 
    analogWrite(derA, vel);  
    analogWrite(izqA, vel); 
    delay (2000);     
  }
  if(estado2=='b'){           //izquierda
  analogWrite(derB, 0);     
    analogWrite(izqB, 0); 
    analogWrite(derA, 0);  
    analogWrite(izqA, vel);
    delay (2000); 
  }
  if(estado2=='c'){          //alto       
     analogWrite(derB, 0);     
    analogWrite(izqB, 0); 
    analogWrite(derA, 0);    
    analogWrite(izqA, 0);
    delay (2000); 
  }
  if(estado2=='d'){          
    analogWrite(derB, 0);     // derecha 
    analogWrite(izqB, 0);
    analogWrite(izqA, 0);
    analogWrite(derA, vel); 
    delay (2000); 
  } 

  if(estado2=='e'){          
    analogWrite(derA, 0);    /// reversa
    analogWrite(izqA, 0);
    analogWrite(derB, vel);  
    analogWrite(izqB, vel);  
    delay (500);     
  }
  
  

  
  
 j = j + 1;
  
    if (j == EEPROM.length()) {
   j = 0;
 }
  
   if (i == 5) {
   i = 0;
 }
 
  
}

amigo @surbyte, ya he visto varios proyectos de este pero usan dispositivo como bluethoo, Wifi etc.

en mi caso lo que pretendo es conectar el robot con un cable USB a mi movil, y con una APP cargar las instrucciones al robot, luego desconectar el robot de mi movil, y por ultimo que sólito el robot realice los movimientos cargados, y que esto ocurra cada vez que se encienda el robot, así también poder volver a cargar nuevas instrucciones a futuro

Y cual es la diferencia?
BT, o OTG terminan enviando datos por Serial. RF aunque hay variatens por SPI todo se traduce a lo mismo.
El concepto es el mismo en todos los casos.

Cuando miras otros casos, surgen ideas para el tuyo.

Tu problema para mi es otro y es como le dices al robot que camino seguir con ordenes simples.
Debes crear un lenguaje de órdenes que luego sepa interpretar. Se las pasas por Serial y las almacena en EEPROM o SD como gustes.
Pero busca un modo estilo
F frente
R atras
D derecha
I izquierda
y luego le das una distancia
un camino podria ser algo asi suponiendo tiempo ya que no mides distancia pero podrias hacerlo si mides el giro de cada rueda.
Ahora imagina con tiempo en segundos
F030 es de frente 30 seg
D010 es derecha 10 seg, hablo de un giro a 90 no que quede girando... eso hay que estudiarlo lo mismo que Izq

Entonces un comando sería
**F030D010F020D010I010D010F010D010F030 **
y debería volver al mismo punto
Tal vez me haya equivocado pero intenta entender la idea.

hola @surbyte gracias pro responder precisamente esa es la idea, pero para no hacerlo mas complicado para mi, ya los tiempos estarían definidos FFDRIDRD por ejemplo
y F que viene siendo a en el código que muestro tendiera una duración de 2s

También quisiera comentar lo siguiente, veo que para alimentar arduinonano se requieren 9v, pero el costo de las baterías es alto y actualmente solo dispongo de baterías para celular usadas de 3.7v y 1350mah, mi pregunta es ¿Puedo conectar estas baterías en serie? ¿ Existirá algún daño para las baterías o para el arduino o para el drive l293d?

famjaes:
hola @surbyte gracias pro responder precisamente esa es la idea, pero para no hacerlo mas complicado para mi, ya los tiempos estarían definidos FFDRIDRD por ejemplo
y F que viene siendo a en el código que muestro tendiera una duración de 2s

No vi ningún comentario que dijera que esa era la idea, pero bueno me alegro que te gustara.
Solo veía que el hilo daba vueltas e incluso esto esta mal.

int estado = 'e';// inicia detenido
..................
 if (Serial.available()>0){        // lee el datos de USB y almacena en la eeprom
    estado = Serial.read();
    EEPROM.write(i, estado);
    i = i + 1; 
  }

estado debería ser byte porque eso es lo que EEPROM.write(i, estado) va a guardar en la posición i. Ver EEPROM.write

No comprendo esto, en realidad me guié con el link que me compartiste para implementar el uso del eeprom
pero no comprendo lo de byte, estado lo lee de serial solo para escribirlo en la eeprom, y luego en estado2 es lo que le de la eeprom para mandarlo a los if y ejecutar las acciones

famjaes:
No comprendo esto, en realidad me guié con el link que me compartiste para implementar el uso del eeprom
pero no comprendo lo de byte, estado lo lee de serial solo para escribirlo en la eeprom, y luego en estado2 es lo que le de la eeprom para mandarlo a los if y ejecutar las acciones

Por eso pensé que leer/escribir a bulto era más fácil.

Reitero mi sugerencia:

Lucario448:
Ahora el tema de la EEPROM:
Veo que no sabes qué es “a bulto”, así que te daré un ejemplo:

#include <EEPROM.h>

char coreografia[65]; // Aquí es donde se obtendrán los pasos de la coreografía.
byte caracteresValidos;
// Este contador sirve para indicar hasta dónde se ha llenado el array. No creo que una coreografía sea siempre de 64 pasos, o sí?

void setup() {
 leerEEPROM();
 // El resto de cosas
}

void loop () {
 if (Serial.available()) {
   delay(100);
   programarCoreografía();
 }
 ejecutarCoreografía();
}

void leerEEPROM() {
 EEPROM.get(0, coreografia); // Recuerda los pasos programados; lo tiene que hacer siempre al inicio
 caracteresValidos = strlen(coreografia); // Calcula cuántos pasos tiene la coreografía; no siempre es de 64 pasos.
}

void programarCoreografia() {
 coreografia[Serial.readBytes(coreografia, Serial.available())] = 0;
  // En resumen: lectura a bulto del serial. Máximo de 64 caracteres.
 caracteresValidos = strlen(coreografia); // Recalcular la cantidad de pasos.
 EEPROM.put(0, coreografia); // Escribe a bulto la nueva secuencia
  // No hace falta releerla desde la EEPROM porque los datos ya están actualizados en memoria; y ahora para un posterior reinicio también.
}

void ejecutarCoreografia() {
 for (byte i = 0; i < caracteresValidos; i++) {
// La nueva secuencia no se programará hasta que esta acabe; si esa no es la idea, entonces habrá que hacerlo un poco diferente.
   switch (coreografia[i]) {
     // Lo de aquí supongo que es historia ya conocida (algo equivalente a un montón de if)
   }
 }
}

En realidad alteré un poco la cita, porque al código le faltaban comentarios.

Hola @lucario trate de implementar tu código peor no pude hacerlo porque me manda errores en el simulador de arduino, tambien en la parte de los Ifs al usar un switch, no se como poner los cases para que se valide el caracter que se lee de la eeprom, y no entiendo como va recorriendo la memoria eeprom, eso lo hace con put?
esto es lo que intente.

#include <EEPROM.h>
char coreografia[65]; // Aquí es donde se obtendrán los pasos de la coreografía.
byte caracteresValidos;
int izqA = 5; 
int izqB = 6; 
int derA = 9;
int derB = 10; 
int vel = 255;  
int i=0;


// Este contador sirve para indicar hasta dónde se ha llenado el array. No creo que una coreografía sea siempre de 64 pasos, o sí?

void setup() {
  leerEEPROM();
   Serial.begin(9600);    // inicia el puerto serial para comunicacion con el USB
  pinMode(derA, OUTPUT);
  pinMode(derB, OUTPUT);
  pinMode(izqA, OUTPUT);
  pinMode(izqB, OUTPUT);
  pinMode(13,OUTPUT);
}

void loop() {
  if (Serial.available()) {
    delay(100);
    programarCoreografía();
  }
  ejecutarCoreografía();
}

void leerEEPROM() {
  EEPROM.get(0, coreografia); // Recuerda los pasos programados; lo tiene que hacer siempre al inicio
  caracteresValidos = strlen(coreografia); // Calcula cuántos pasos tiene la coreografía; no siempre es de 64 pasos.
}

void programarCoreografia() {
  coreografia[Serial.readBytes(coreografia, Serial.available())] = 0;
  // En resumen: lectura a bulto del serial. Máximo de 64 caracteres.
  caracteresValidos = strlen(coreografia); // Recalcular la cantidad de pasos.
  EEPROM.put(0, coreografia); // Escribe a bulto la nueva secuencia
  // No hace falta releerla desde la EEPROM porque los datos ya están actualizados en memoria; y ahora para un posterior reinicio también.
}

void ejecutarCoreografia() { 


  
  for (byte i = 0; i < caracteresValidos; i++) {
// La nueva secuencia no se programará hasta que esta acabe; si esa no es la idea, entonces habrá que hacerlo un poco diferente.
    switch (coreografia[i]) {


     if(coreografia=='a'){  // frente
    analogWrite(derB, 0);     
    analogWrite(izqB, 0); 
    analogWrite(derA, vel);  
    analogWrite(izqA, vel); 
    delay (2000);     
  }
  if(coreografia=='b'){           //izquierda
  analogWrite(derB, 0);     
    analogWrite(izqB, 0); 
    analogWrite(derA, 0);  
    analogWrite(izqA, vel);
    delay (2000); 
  }
  if(coreografia=='c'){          //alto       
     analogWrite(derB, 0);     
    analogWrite(izqB, 0); 
    analogWrite(derA, 0);    
    analogWrite(izqA, 0);
    delay (2000); 
  }
  if(coreografia=='d'){          
    analogWrite(derB, 0);     // derecha 
    analogWrite(izqB, 0);
    analogWrite(izqA, 0);
    analogWrite(derA, vel); 
    delay (2000); 
  } 

  if(coreografia=='e'){          
    analogWrite(derA, 0);    /// reversa
    analogWrite(izqA, 0);
    analogWrite(derB, vel);  
    analogWrite(izqB, vel);  
    delay (500);     
  }
  
    }
  }
}

Bueno... lo que pasa es que un bloque switch espera sentencias case, no if directamente. Lo correcto sería:

switch (coreografia[i]) {

  // if(coreografia=='a') // Mal
  case 'a': // Bien

   // analogsWrite y delay

   break; // Debe ser la última instrucción de cada case, y nunca debe faltar.
   // Es como el cierre de un bloque if
}

Oh y olvidé aclarar una cosa:

Las funciones get y put de EEPROM, son para lectura y escritura "a bulto"; aunque no se limita solo a arrays, también funciona para leer/escribir int, long, float, struct y no sé si hasta "objetos".

Geeenial Gracias @lucario448 Funciona, voy a ir avanzando con el proyecto, para armar el robot, y comenzar a desarrollar una aplicación para enviar los datos, estaré compartiendo los avances o las dudas en los próximos días :smiley: mucho karma