Enviando datos por PJON

Sigo haciendo experimentos con el sistema de comunicación PJON, un bus de comunicación One Wire sencillo y de código abierto.

Una cosa que pasa con todos los sistemas de comunicación es que los datos que enviamos se transmiten Byte a Byte, esto también pasa con el bus Serial o el I2C, y a nosotros un Byte no nos resulta de demasiada utilidad. Lo útil para cualquier desarrollador es poder intercambiar datos que sean del mismo tipo que las variables con las que trabajamos en la parte del montaje que recoge la información, es decir, si yo capturo un dato de tipo int me interesa que al pasarlo a otra máquina por el bus que sea al recibirlo también sea un int…. y esto no es posible.

Seguro que a más de uno le ha pasado esto trabajando con el bus Serial, que suele ser el que más tocamos. Es por ello que en todos los ejemplos de código enviamos caracteres ASCII, ya que sólo ocupan un Byte y es fácil trabajar con ellos. Pero cuando intentamos enviar un int por Serial la cosa se complica ya que el receptor lo que lee son dos Bytes y si no tienes un poco de picardía volver a unirlos puede ser un infierno.

Para trabajar con el bus Serial la propia librería que contiene el Arduino IDE tiene funciones muy interesantes como parseInt() o parseFloat(), pero cuando saltamos a otro tipo de bus hay que recurrir a métodos que nos obligan a trabajar a nivel de bits. Tranquilos, no es tan difícil como parece.

En el caso concreto del bus PJON los datos se transmiten Byte a Byte y para hacerlo aún más interesante en forma de un array de tipo char, así que para transmitir un int (que como todos sabéis está formado por dos Bytes) lo primero que toca es dividirlo en dos Bytes independientes. Recordemos que si un número binario está compuesto por varios Bytes el que está más a la izquierda, el que contiene los bits que más pesan, se dice que es el más significativo o MSB (de Most Significant Byte en inglés), y por contra el que esté más a la derecha será el menos significativo o LSB (Less Significant Byte en inglés).

El lenguaje de Arduino nos da dos funciones muy útiles para eso, son highByte() y lowByte(). Como os podéis imaginar la primera saca el Byte alto o más significativo y la segunda hace lo mismo con el menos significativo.

En el ejemplo de código de envío veréis que hago esta división al mismo tiempo que meto los Bytes en un array de tipo char para poder enviarlos y para ello es necesario convertir esos Bytes al tipo char.

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
29
30
31
32
33
34
35
36
37
38
39
40
41
/**************************************************
 *
 * From int to char array
 *
 **************************************************/


#include <PJON.h>

// <Strategy name> bus(selected device id)
PJON<SoftwareBitBang> bus(44); // Sender

int count = 0;

void setup() {

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

  Serial.begin(9600);

};

void loop() {
  char package[1]; // 2 position array
  package[0] = char(highByte(count));
  package[1] = char(lowByte(count));
 
  bus.send(45, package, 2); // send package array, 2 bytes
  bus.update();

// this is only for debbuging
//  Serial.print(count);
//  Serial.print(" HighByte: ");
//  Serial.print(byte(package[0]));
//  Serial.print(" LowByte: ");
//  Serial.println(byte(package[1]));
 
  delay(100);
  count++;

};

Ahora solo tenemos que hacer que el Arduino que reciba el mensaje trabaje esos dos chars para que vuelvan a ser un int. Para ello vamos a utilizar un procedimiento muy sencillo: primero cogemos la posición [0] del array payload, que es donde se han almacenado los datos recibidos y lo metemos en la variable que contendrá el int. El Byte que está en la posición [0] de ese array es el más significativo pero al meterlo en el int se ha convertido en el menos significativo por lo que hay que desplazarlo a la izquierda ocho bits y por último cogemos este int y le sumamos el Byte menos significativo, que está almacenado en la posición [1] del array. Los componentes del array son de tipo char por lo que es muy importante transformarlos en tipo byte.

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
29
30
31
32
33
34
/**************************************************
 *
 * From 2 chars to 1 int
 *
 **************************************************/

#include <PJON.h>

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

int num;

void setup() {
  bus.set_pin(12);
  bus.begin();
  bus.set_receiver(receiver_function);

  Serial.begin(9600);
}

void receiver_function(uint8_t id, uint8_t *payload, uint8_t length) {
  // payload[0] to byte and put it in num
  num = byte(payload[0]);
  // shift the bits to the left 8 positions
  num = num << 8;
  // add payload[1]
  num |= byte(payload[1]);

  Serial.println(num);
}

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

…y ya está, hemos transportado un int de un Arduino a otro, y de la misma forma podríamos transportar un float o un long, con lo que tener un montón de Arduinos conectados entre ellos por un bus PJON e intercambiar información entre ellos ya no es problema, podemos pasar cualquier tipo de variable de uno a otro.

Un saludo.


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.


Una estúpida ley me obliga a molestarte con algo obvio: este sitio utiliza cookies. Aquí tienes el ladrillo en cuestión por si quieres leerlo