Comunicación entre dos Arduinos mediante APC220

Hola a todos

Quiero controlar un servo conectado a un Arduino mediante un potenciometro conectado a otro Arduino. Para ello tengo los modulos APC220. El programa de ejemplo Knob me vale perfectamente, salvo que lo que quiero es distribuirlo entre los dos Arduinos 2009: uno con el potenciometro conectado al pin 0, y el otro con el servo conectado al pin Digital 9

El problema es que no sé por donde empezar a mirar para aprender a programar la comunicación entre ambos...

Mirando otros sketches, he puesto en forma estos dos, que -por supuesto- no funcionan ;D

Si me pudierais corregir, decirme si los tiros van por allí, qué me falta, vamos cualquier ayudita, estaría genial

Sketch emisor:

int potpin = 0; int val;

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

void loop() { val = analogRead(potpin); val = map(val, 0, 1023, 0, 179); Serial.println(val); delay(100); }

Y el receptor (servo)

#include <Servo.h>

Servo myservo; // create servo object to control a servo

int val; // variable to read the value from the analog pin

void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.begin(9600);
}

void loop()
{
if (Serial.available() > 0)
{
val = Serial.read();
myservo.write(val); // sets the servo position according to the scaled value
delay(50); // waits for the servo to get there
}
}

Hola

Es un error que he visto cometer muchas veces a mis alumnos...

Yo creo que la clave está en entender como funciona la trasmisión por el puerto serie y en especial Serial.read

Hay una diferencia muy importante entre Serial.print y Serial.read: mientras que Serial.print "se adapta" al tipo de dato, Serial.Read no lo hace.

Vemos que la variable val está definida como int, esto quiere decir que ocupa 16 bits ó dos bytes de 8 bits, esto es correcto si queremos almacenar el valor de una entrada analógica (que son 10 bits).

Ahora bien, si ponemos:

Serial.println(val);

Enviaremos el valor de "val" no como un número binario de 16 bits, si no como una "cadena de caracteres ASCII" que representan dicho número de forma que se pueda visualizar (en el terminal, por ejemplo). Ademas hemos puesto Serial.println y no Serial.print, así que la función añade un caracter de retorno de línea para que el terminal represente cada valor en una línea distinta, esto es que si la variable "val" valiese 1023 (en decimal), enviaríamos por el puerto serie cuatro bytes: 0x31, 0x30, 0x32, 0x33 y 0xD (yo prefiero ponerlo en hexadecimal). Esto puede ser muy útil para comunicar una placa Arduino con un terminal, pero no mucho para comunicar dos placas Arduinos.

Por otra parte, en el otro Arduino leemos byte a byte (es lo único que puede hacer la función Serial.read) y metemos cada uno de estos valores en su variable "val", pero como si fueran números distintos.

El error común está en pensar que si "val" es "int" y ponemos:

val = Serial.read();

leeremos un número "int". Esto no es así, ya que solo leemos un byte.

Ante esto ¿que podemos hacer?

Lo primero es pensar cual es la resolución real que necesitamos. Esto es, leemos una entrada analógica de 10 bits (de 0 a 1023) y con esa información movemos un servo. ¿que resolución tenemos?, ¿cuantos grados queremos mover?. Si miramos la documentación de la librería para el manejo de servos vemos que el recorrido máximo son 180 grados y la resolución es de 1 grado, esto es, que podemos representar esa información con un único valor de 8 bits, (un byte).

Así pues lo primero que haremos es escalar la lectura de nuestro potenciómetro en el Arduino que manda el valor:

val = analogRead(potpin); val = map(val, 0, 1023, 0, 179);

y ahora enviamos un único byte:

Serial.print (val, BYTE);

De esta forma el valor (byte) que leemos en el otro Arduino si es un número comprendido entre 0 y 179 que correspondera a la posición del servo

Cuanta sabiduría! Me consuela al menos saber que no soy el único en hacer ese error... ;)

He tenido que resolver luego un pequeño problema (en una unidad los cables Rx y Tx han de ir invertidos) pero ¡YA FUNCIONA!

Mil gracias!!

Por cierto, cuando dices "mis alumnos", quieres decir que haces cursillos de Arduino? Porque eso a mí me interesaría...

Si tienes entre 5 y 18 años ;)

Desde hace 8 años nos dedicamos a la robótica educativa y hace 2 hemos incorporado Arduino y Wiring con chic@s de 13-18 años hasta ahora y desde los 10 años este curso. Veremoa a ver que tal resultado.

Vaya, pues me voy un poco… Que lastima que no hayan hecho este tipo de cosas cuando yo tenia esa edad, me habría encantado… Y clases normales sin limites de edad, se hacen en algún sitio?