Moteino, RFM12PiV2 & Rioja (Raspberry Pi et non OpenStack)

2015-04-26

Moteino, RFM12PiV2 & Rioja (Raspberry Pi et non OpenStack)

Machine-translated — the English original is authoritative.

Alors, enfin j’ai eu le temps de lancer mon projet d’automatisation domestique tant attendu – mon excuse pour jouer avec tout le « Internet des objets » (IoT). À long terme, j’aimerais impliquer mon école locale – amener l’IoT à la communauté. Comme mon travail de jour nécessite de fouiner avec beaucoup de technologies amusantes, de protocoles et de python (hacker et non programmeur), le tout au nom de l’automatisation des datacenters (alias cloud computing pour les gens du marketing là-bas), je vais tirer parti de ces compétences pour créer un écosystème d’automatisation domestique robuste. Les DL360 et les iLO seront remplacés par des Raspberry Pis et des Arduinos.

Il y a beaucoup de superbes blogs sur l’inter-tubes qui m’ont inspiré, tels que JeeLabs , LowPowerLabs et Martin’s corner on the web. Ces gars sont des experts ! Veuillez consulter ces sites si vous souhaitez construire le vôtre. Je construis pour apprendre, d’excellents systèmes tout faits existent déjà maintenant. Ce blog se contentera de présenter les découvertes que je pense pouvoir intéresser les autres tout au long de mon voyage…

Jouer avec les communications RF basse consommation

Si vous vous demandez pourquoi je ne me contente pas du WiFi pour les communications, la réponse est simplement la puissance et la portée ! Les modules WiFi sont gourmands en énergie par rapport aux dispositifs RF plus simples. Tous les dispositifs à relier à Internet ne seront pas à proximité d’une source d’alimentation, il sera donc nécessaire de les faire fonctionner sur batterie – par exemple, des moniteurs de plantes, des capteurs de température à distance, etc. En fin de compte, ces dispositifs sur batterie enverront leurs informations à Internet via une passerelle Raspberry Pi (RPi). Le RPi aura à la fois une connectivité Internet et une connectivité RF.

Le premier défi auquel j’ai été confronté a été d’évaluer certains dispositifs RF prêts à l’emploi à faible coût, qui comprenaient quelques Moteinos (ceux-ci sont superbes), de Felix chez LowPowerLabs.com et le RFM12PiV2 du projet OpenEnergyMonitor. Cet appareil se branche sur le Raspberry Pi et servira de passerelle vers Internet pour tous mes dispositifs IoT basés sur le RF.

Moteino RFM12PiV2

Comme j’ai choisi des dispositifs RF de deux projets différents, ils nécessitent quelques ajustements pour qu’ils puissent communiquer correctement entre eux, et c’est ce que le reste de ce blog couvrira.

Ce que ces deux dispositifs ont en commun, c’est qu’ils utilisent tous les deux la plateforme de développement compatible Arduino basée sur la puce ATMega328. Par conséquent, ils peuvent tous les deux être programmés à l’aide de l’IDE Arduino. Les dispositifs ont également une carte fille intégrée qui contient le transceiver HopeRF RFM12B.

Ils diffèrent en ce qu’ils exécutent tous les deux des programmes différents (également appelés croquis dans le monde Arduino) et que leurs horloges matérielles ont également été architecturées légèrement différemment. Le Moteino utilise un signal d’horloge externe de 16 Mhz, tandis que le RFM12PiV2 utilise l’horloge interne de 8 Mhz qui est intégrée à l’ATMega328. Cette dernière information est vitale lors de la synchronisation des transmissions entre les dispositifs.

J’ai décidé d’utiliser les croquis de test des Moteinos situés ici – Node et Gateway en ne changeant que l’adressage et le débit binaire comme on peut le voir ci-dessous :

Croquis Node

// Test sketch that is loaded on slave Moteinos
// It will send an encrypted message to the master/gateway every TRANSMITPERIOD
// It will respond to any ACKed messages from the master
// Every 3rd message will also be ACKed (request ACK from master).
#include <RFM12B.h>
#include <SPIFlash.h>
#include <SPI.h>b
#include <avr/sleep.h>

#define MYID 123 // node ID used for this unit
#define NETWORKID 50
#define GATEWAYID 1
#define FREQUENCY RF12_433MHZ //Match this with the version of your Moteino! (others: RF12_433MHZ, RF12_915MHZ)
#define KEY "ABCDABCDABCDABCD"
int TRANSMITPERIOD = 500; //transmit a packet to gateway so often (in ms)

#define SERIAL_BAUD 115200
#define ACK_TIME 50 // # of ms to wait for an ack

char input = 0;
RFM12B radio;
SPIFlash flash(8, 0xEF30); //EF30 for Windbond 4mbit flash
boolean requestACK = false;
byte sendSize=0;
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";

void setup()
{
Serial.begin(SERIAL_BAUD);
radio.Initialize(MYID, FREQUENCY, NETWORKID, 0);
radio.Encrypt((byte*)KEY);
char buff[50];
sprintf(buff, "Transmitting at %d Mhz...", FREQUENCY == RF12_433MHZ ? 433 : FREQUENCY== RF12_868MHZ ? 868 : 915);
Serial.println(buff);
if (flash.initialize())
Serial.println("SPI Flash Init OK!");
else
Serial.println("SPI Flash Init FAIL! (is chip present?)");
}

long lastPeriod = -1;
void loop()
{
//process any serial input
if (Serial.available() > 0) {
input = Serial.read();
if (input >= 48 && input <= 57) //[0,9]
{
TRANSMITPERIOD = 100 * (input-48);
if (TRANSMITPERIOD == 0) TRANSMITPERIOD = 1000;
Serial.print("\nChanging delay to ");
Serial.print(TRANSMITPERIOD);
Serial.println("ms\n");
}
else if (input == 'd') //d=dump flash area
{
Serial.println("Flash content:");
int counter = 0;

while(counter<=256){
Serial.print(flash.readByte(counter++), HEX);
Serial.print('.');
}
while(flash.busy());
Serial.println();
}
else if (input == 'e')
{
Serial.print("Erasing Flash chip ... ");
flash.chipErase();
while(flash.busy());
Serial.println("DONE");
}
else if (input == 'i')
{
Serial.print("DeviceID: ");
Serial.println(flash.readDeviceId(), HEX);
}
}

//check for any received packets
if (radio.ReceiveComplete())
{
if (radio.CRCPass())
{
Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] ");
for (byte i = 0; i < *radio.DataLen; i++)
Serial.print((char)radio.Data[i]);

if (radio.ACKRequested())
{
radio.SendACK();
Serial.print(" - ACK sent.");
}
Blink(9,5);
}
}

int currPeriod = millis()/TRANSMITPERIOD;
if (currPeriod != lastPeriod)
{
lastPeriod=currPeriod;
//Send data periodically to GATEWAY
Serial.print("Sending[");
Serial.print(sendSize);
Serial.print("]: ");
for(byte i = 0; i < sendSize; i++)
Serial.print((char)payload[i]);

requestACK = ((sendSize % 3) == 0); //request ACK every 3rd xmission
radio.Send(GATEWAYID, payload, sendSize, requestACK);
if (requestACK)
{
Serial.print(" - waiting for ACK...");
if (waitForAck(GATEWAYID)) Serial.print("ok!");
else Serial.print("nothing...");
}

sendSize = (sendSize + 1) % 31;
Serial.println();
Blink(9,5);
}
//else { Serial.print("currPeriod = "); Serial.print(currPeriod); Serial.print(" lastPeriod = "); Serial.println(lastPeriod); }
}

// wait a few milliseconds for proper ACK to me, return true if indeed received
static bool waitForAck(byte theNodeID) {
long now = millis();
while (millis() - now <= ACK_TIME) {
if (radio.ACKReceived(theNodeID))
return true;
}
return false;
}

void Blink(byte PIN, int DELAY_MS)
{
pinMode(PIN, OUTPUT);
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}

Croquis Gateway

// Test sketch that is loaded on master Moteinos
// It will listen for any packets received from slave Moteinos
// If an ACK request message is received, it sends and ACK and also
// sends an ACKed message to the slave, ensuring that 2-way
// communication is functional on the slave Moteino

#include <RFM12B.h>

#define SERIAL_BAUD 115200
#define NODEID 1 // network ID used for this unit
#define NETWORKID 50
#define FREQUENCY RF12_433MHZ //Match this with the version of your Moteino! (others: RF12_433MHZ, RF12_915MHZ)
#define KEY "ABCDABCDABCDABCD" //encryption key
#define ACK_TIME 50 // # of ms to wait for an ack
uint8_t input[RF12_MAXDATA];
RFM12B radio;

void setup()
{
pinMode(9, OUTPUT);
radio.Initialize(NODEID, FREQUENCY, NETWORKID);
radio.Encrypt((byte*)KEY);
Serial.begin(SERIAL_BAUD);
char buff[50];
sprintf(buff, "Listening at %d Mhz...", FREQUENCY == RF12_433MHZ ? 433 : FREQUENCY== RF12_868MHZ ? 868 : 915);
Serial.println(buff);
}

byte recvCount = 0;

void loop()
{
if (radio.ReceiveComplete())
{
if (radio.CRCPass())
{
digitalWrite(9,1);
Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] ");
for (byte i = 0; i < *radio.DataLen; i++)
Serial.print((char)radio.Data[i]);

if (radio.ACKRequested())
{
byte theNodeID = radio.GetSender();
radio.SendACK();
//when a node requests an ACK, respond to the ACK and also send a packet requesting an ACK
//This way both TX/RX NODE functions are tested on 1 end at the GATEWAY
Serial.print(" - ACK sent. Sending packet to node ");
Serial.print(theNodeID);
delay(10);
radio.Send(theNodeID, "ACK TEST", 8, true);
Serial.print(" - waiting for ACK...");
if (waitForAck(theNodeID)) Serial.print("ok!");
else Serial.print("nothing...");
}
delay(5);
digitalWrite(9,0);
}
else Serial.print("BAD-CRC");

Serial.println();
}
}

// wait a few milliseconds for proper ACK to me, return true if indeed received
static bool waitForAck(byte theNodeID) {
long now = millis();
while (millis() - now <= ACK_TIME) {
if (radio.ACKReceived(theNodeID))
return true;
}
return false;
}

Téléchargement du croquis sur le Moteino

C’est simple en connectant le Moteino directement à un PC exécutant l’IDE Arduino et en utilisant le processus Arduino standard. Ces dispositifs ont également une capacité de programmation sans fil très utile qui est couverte ici.

Moteino_Node

Téléchargement du croquis sur le RFM12PiV2 (en utilisant le Raspberry Pi)

Ce processus est un peu plus délicat. Nous devons d’abord compiler le croquis de la passerelle à l’aide de l’IDE Arduino, puis localiser le fichier bin compilé.

Activez la sortie verbose dans les préférences de l’IDE Arduino comme indiqué ci-dessous :
ArduinoVerboseSetting
Maintenant, lorsque vous compilez le croquis, la fenêtre de sortie vous donnera l’emplacement du fichier compilé que vous devrez transférer sur le Raspberry Pi.
GatewayBinFile

Assurez-vous que le port série sur le Raspberry Pi a été activé comme détaillé ici.

La dernière pièce de ce puzzle – Comment télécharger un nouveau code du Raspberry Pi vers le RFM12PiV2 – a déjà été documentée ici mais sera également décrite à nouveau ci-dessous :

$ sudo apt-get update
$ sudo apt-get install -y arduino python-dev python-rpi.gpio
$ git clone https://github.com/mharizanov/avrdude-rpi.git
$ cd avrdude-rpi
$ sudo cp autoreset /usr/bin
$ sudo cp avrdude-autoreset /usr/bin
$ sudo mv /usr/bin/avrdude /usr/bin/avrdude-original
$ sudo ln -s /usr/bin/avrdude-autoreset /usr/bin/avrdude
# Change to the directory where the binary file has been copied
$ avrdude -v  -c arduino -p ATMEGA328P -P /dev/ttyAMA0 -b 38400 -U flash:w:<Enter Filename Here and remove arrow brackets>

Enfin, utilisez votre outil de choix pour lire le port série sur le Raspberry Pi – j’ai opté pour screen. À long terme, j’utiliserai un script python.

NOTE N’oubliez pas la différence de vitesse d’horloge – cela entre en jeu maintenant. Malgré le fait que les deux croquis définissent le débit binaire à 115200, lors de la connexion au RFM12PiV2 qui fonctionne à moitié de la vitesse d’horloge, 8MHz au lieu de 16MHz, il est nécessaire de définir le débit binaire à 57600 et PAS 115200.

pi_screen_cmd

Maintenant, vous devriez voir quelque chose comme ceci
PI_Gateway

Mettre tout cela ensemble vous donnera un système de communication de base fonctionnel Moteino vers RFM12PiV2.
NodeandGateway

Taaaa – Daaaa !

Malheureusement, apparemment le module RFM12B est maintenant en fin de vie, donc je devrai tout refaire avec le RFM69 ou peut-être essaierai-je ceux-ci
🙂

Originally published on allthingscloud.eu (2015-04-26).

← All posts