A la fecha en la que escribo este tutorial hace unos meses ya que tuve mi última reunión informal con mi mentor y amigo David Cuartielles, que como todos a sabéis es uno de los creadores de Arduino, una de los temas que le comenté esperando su consejo era mi intención de diseñar un controlador para servos que no necesitase de una conexión directa con Arduino, si no que se pudiesen conectar múltiples controladores el serie y que funcionaran de forma independiente tras recibir un comando desde Arduino indicando la posición en la que debía situarse cada servo. Yo le mencioné que mi idea era comunicar los controladores mediante I2C por motivos de sencillez, estuvimos un rato hablando de las ventajas e inconvenientes de ese bus y otros y luego me comentó que un italiano había liberado un protocolo One Wire libre al que había llamado PJON. Esa misma noche hice un rápida búsqueda por Google y encontré la página de Github donde está alojada la librería y una página con un ejemplo básico de uso y, la verdad, quedé muy impresionado por las posibilidades que se abren con este tipo de comunicación.

Como he dicho han pasado varios meses en los que he estado ocupado trabajando en diversos proyectos y no ha sido hasta hoy que me he podido poner manos a la obra con esta nueva forma de comunicación libre y tan prometedora. Las primeras impresiones no pueden ser mejores, es muy fácil de utilizar y tal como promete podemos comunicar dos o más Arduino con un solo cable, lo cual es perfecto para mi proyecto, tanto es así que he descartado otros sistemas de comunicación y mis controladores de servos se comunicarán exclusivamente por este sistema.

Os voy a compartir los ejemplos de envío y recepción que he hecho para probar su funcionamiento, se trata de una modificación del ejemplo PhysicalPixel en la que el emisor envía los caracteres “h” y “l” a intervalos de un segundo y el receptor pone en estado alto el pin 13 cuando recibe la “h” o lo pone en estado bajo si recibe una “l” haciendo que un led conectado al pin 13 se encienda y se apague a intervalos de un segundo.

El código del emisor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <PJON.h>

// <Strategy name> bus(selected device id)
PJON<SoftwareBitBang> bus(44); // This node id is 44

void setup() {

  // Bus pin is 12
  bus.set_pin(12);
  // Start communication
  bus.begin();

};

void loop() {

  // Compose a message to device 45 a character h, only 1 byte
  bus.send(45, "h", 1);
  // Now send the message
  bus.update();
  // Wait for a second
  delay(1000);

  // Repeat but send a character l
  bus.send(45, "l", 1);
  bus.update();
  delay(1000);
};

¿Véis que simple? llamamos a la librería y creamos el objeto bus con la id del dispositivo, en este caso 44 pero podría ser un número entre 0 y 254… si, podemos tener hasta 255 dispositivos conectados a un mismo bus.

Dentro del setup() definimos que pin vamos a utilizar para la comunicación y la inicializamos.

Luego, dentro del loop(), componemos un mensaje con tres simples parámetros: la id del dispositivo al que le mandamos el mensaje, el propio mensaje y el número de bytes que componen el mensaje (por aquello de corregir errores en la recepción).

Ahora el código del receptor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <PJON.h>

// <Strategy name> bus(selected device id)
PJON<SoftwareBitBang> bus(45); // Receiver

void setup() {
  pinModeFast(13, OUTPUT);
  digitalWriteFast(13, LOW); // Initialize LED 13 to be off

  bus.set_pin(12);
  bus.begin();

  bus.set_receiver(receiver_function);

}

void receiver_function(uint8_t id, uint8_t *payload, uint8_t length) {
 if((char)payload[0] == 'h') {
    digitalWrite(13, HIGH);
  }
 if((char)payload[0] == 'l') {
    digitalWrite(13, LOW);
  }
}

void loop() {
  bus.receive(1000);
}

Una vez más nos encontramos con una forma muy sencilla de recibir la información: se llama a la librería y se crea el objeto, esta vez con la id 45. Se establece el pin del bus como el 12 y se inicializa la comunicación, luego en el setup() establecemos que en caso de recibir algo se llama a la función receiver_function() y pasamos a definirla, esta simplemente enciende el led de la pata 13 si recibe el carácter “h” y lo apaga si recibe el carácter “l”.

Los bytes que llegan se almacenan en el array payload[], aun me falta buscar como es de largo y si se vacía tras cada recepción, en la wiki del proyecto no lo he encontrado.

Como habréis observado esta vez el código que pongo está en inglés, esto responde a que me estoy pensando muy seriamente si migrar todo mi contenido a este idioma. Veréis, esto quizá moleste a alguno, hace ya meses que puse en todos los tutoriales el botón de donativos de Paypal y pese a tener más de 30.000 visitas al mes nadie a donado ni un céntimo, redactar tutoriales requiere tiempo y es tiempo que no le dedico a trabajos que si me permiten vivir, no me importa compartir de forma libre pero entended que si tengo que dedicar todo mi tiempo a lo que da dinero no habrá más tutoriales, un donativo aunque sea sólo de 1 euro me ayuda a que dedicar tiempo a escribir en esta página no sea tiempo perdido. El 95 por ciento de mi audiencia es hispano-parlante y si no hay donativos traduciré todo el contenido al inglés, un idioma cuyos usuarios son menos reticentes a colaborar económicamente con los desarrolladores. No quiero hacerlo pero aquí en España se están viviendo tiempos muy duros y toca tomar medidas drásticas.

Un saludo a todos.


Si este tutorial te ha sido de utilidad puedes considerar hacerme un donativo, por pequeño que sea estarás contribuyendo a que siga con esta labor.