Prepared for ack:ing between sensors. And between actuator and gateway. Now using hardware ack when sending messages and burst-mode which gives much more reliable communication.

Use the corresponing development-branch for Vera plugin files.
This commit is contained in:
Henrik Ekblad
2014-05-04 23:47:46 +02:00
parent 40218118f3
commit 960efcd6f7
9 changed files with 83 additions and 43 deletions
-1
View File
@@ -28,7 +28,6 @@
#include <PinChangeInt.h>
#include <Gateway.h>
#include <stdarg.h>
#include <avr/progmem.h>
#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled
#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button
+3 -3
View File
@@ -5,9 +5,9 @@
* Configure Sensor Network
*/
#define RF24_CHANNEL 76 //RF channel for the sensor net, 0-127
#define RF24_DATARATE RF24_250KBPS //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
#define RF24_PA_LEVEL RF24_PA_MAX //Senor PA Level == RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBM, and RF24_PA_HIGH=0dBm
#define RF24_PA_LEVEL_GW RF24_PA_LEVEL //Gateway PA Level, defaults to Sensor net PA Level. Tune here if using an amplified nRF2401+ in your gateway.
#define RF24_DATARATE RF24_1MBPS //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
#define RF24_PA_LEVEL RF24_PA_MAX //Sensor PA Level == RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBM, and RF24_PA_HIGH=0dBm
#define RF24_PA_LEVEL_GW RF24_PA_LOW //Gateway PA Level, defaults to Sensor net PA Level. Tune here if using an amplified nRF2401+ in your gateway.
/***
* Enable/Disable debug logging
+2 -1
View File
@@ -1,5 +1,5 @@
/*
The MySensors Arduino library adds a new layer on top of the RF24 library.
The MySensors library adds a new layer on top of the RF24 library.
It handles radio network routing, relaying and ids.
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
@@ -67,6 +67,7 @@ void Gateway::begin(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e data
// Start up the radio library
setupRadio(paLevel, channel, dataRate);
RF24::openReadingPipe(WRITE_PIPE, BASE_RADIO_ID);
RF24::openReadingPipe(CURRENT_NODE_PIPE, BASE_RADIO_ID);
RF24::startListening();
+1 -1
View File
@@ -1,5 +1,5 @@
/*
The MySensors Arduino library adds a new layer on top of the RF24 library.
The MySensors library adds a new layer on top of the RF24 library.
It handles radio network routing, relaying and ids.
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
+25 -10
View File
@@ -1,5 +1,5 @@
/*
The MySensors Arduino library adds a new layer on top of the RF24 library.
The MySensors library adds a new layer on top of the RF24 library.
It handles radio network routing, relaying and ids.
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
@@ -86,8 +86,20 @@ boolean Relay::messageAvailable() {
}
if (available && pipe<7) {
uint8_t len = RF24::getDynamicPayloadSize()-sizeof(msg.header);
boolean ok = readMessage();
uint8_t len = RF24::getDynamicPayloadSize();
RF24::read(&msg, len);
RF24::writeAckPayload(pipe,&pipe, 1 );
uint8_t valid = validate(len-sizeof(header_s));
boolean ok = valid == VALIDATE_OK;
// Make sure string gets terminated ok for full sized messages.
msg.data[len - sizeof(header_s) ] = '\0';
debug(PSTR("Rx: fr=%d,to=%d,la=%d,ci=%d,mt=%d,t=%d,cr=%d(%s): %s\n"),
msg.header.from,msg.header.to, msg.header.last, msg.header.childId, msg.header.messageType, msg.header.type, msg.header.crc, valid==0?"ok":valid==1?"ec":"ev", msg.data);
//boolean ok = readMessage();
if (ok) {
if (msg.header.messageType == M_INTERNAL &&
msg.header.type == I_PING) {
@@ -130,11 +142,14 @@ boolean Relay::messageAvailable() {
} else {
// If this is variable message from sensor net gateway. Send ack back.
debug(PSTR("Message addressed for this node.\n"));
if (msg.header.from == GATEWAY_ADDRESS &&
msg.header.messageType == M_SET_VARIABLE) {
// Send back ack message to sensor net gateway
// Send set-message back to sender if sender wants this
if (msg.header.messageType == M_SET_WITH_ACK) {
sendVariableAck();
// The library user should not need to care about this ack request. Just treat it as a normal SET.
msg.header.messageType = M_SET_VARIABLE;
}
// Return message to waiting sketch...
if (msg.header.last != GATEWAY_ADDRESS)
addChildRoute(msg.header.from, msg.header.last);
@@ -143,7 +158,7 @@ boolean Relay::messageAvailable() {
}
} else {
// We should probably try to relay this message
relayMessage(len, pipe);
relayMessage(len-sizeof(msg.header), pipe);
}
}
}
@@ -243,14 +258,14 @@ void Relay::clearChildRoutes() {
void Relay::sendChildren() {
// Send in which children that is using this node as an relay.
// TODO: Fix this
debug(PSTR("Send child info to sensor gateway.\n"));
debug(PSTR("Dump beginning of routing table\n"));
for (int i=0;i< 10; i++) {
for (int i=0;i< 50; i++) {
// Serial.println(childNodeTable[i]);
debug(PSTR("rt:%d, %d\n"), i, getChildRoute(i) );
}
//sendInternal(I_CHILDREN, "not implemented");
sendInternal(I_CHILDREN, "not implemented");
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
The MySensors Arduino library adds a new layer on top of the RF24 library.
The MySensors library adds a new layer on top of the RF24 library.
It handles radio network routing, relaying and ids.
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
+43 -18
View File
@@ -22,15 +22,22 @@ void Sensor::setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e
// Start up the radio library
RF24::begin();
RF24::setAutoAck(1);
RF24::enableAckPayload();
if (!RF24::isPVariant()) {
debug(PSTR("Sorry, you'll need to use the P version of NRF24L01.\n"));
while(1);
}
RF24::setChannel(channel);
RF24::setPALevel(paLevel);
RF24::setDataRate(dataRate);
RF24::setAutoAck(true);
RF24::setRetries(2,15);
RF24::setRetries(5,15);
RF24::setCRCLength(RF24_CRC_16);
RF24::enableDynamicPayloads();
// All repeater nodes and gateway listen to broadcast pipe (for PING messages)
if (isRelay) {
RF24::openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS));
@@ -44,6 +51,7 @@ void Sensor::begin(uint8_t _radioId, rf24_pa_dbm_e paLevel, uint8_t channel, rf2
debug(PSTR("Started %s.\n"), isRelay?"relay":"sensor");
setupRadio(paLevel, channel, dataRate);
// Fetch relay from EEPROM
@@ -58,7 +66,8 @@ void Sensor::begin(uint8_t _radioId, rf24_pa_dbm_e paLevel, uint8_t channel, rf2
initializeRadioId();
// Open reading pipe for messages directed to this node
// Open reading pipe for messages directed to this node (set write pipe to same)
RF24::openReadingPipe(WRITE_PIPE, TO_ADDR(radioId));
RF24::openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(radioId));
// Send presentation for this radio node
@@ -224,11 +233,16 @@ boolean Sensor::sendWrite(uint8_t dest, message_s message, int length) {
message.header.from,message.header.to, message.header.last, dest, message.header.childId, message.header.messageType, message.header.type, message.header.crc, message.data);
bool broadcast = message.header.messageType == M_INTERNAL && message.header.type == I_PING;
RF24::stopListening();
RF24::openWritingPipe(TO_ADDR(dest));
bool ok = RF24::write(&message, min(MAX_MESSAGE_LENGTH, sizeof(message.header) + length), broadcast);
RF24::startListening();
//RF24::closeReadingPipe(WRITE_PIPE); // Stop listening to write-pipe after transmit
//delay(50);
if (ok)
debug(PSTR("Sent successfully\n"));
else
@@ -351,11 +365,11 @@ char* Sensor::get(uint8_t nodeId, uint8_t childId, uint8_t sendType, uint8_t rec
}
char* Sensor::getStatus(uint8_t childId, uint8_t variableType) {
return get(GATEWAY_ADDRESS, childId, M_REQ_VARIABLE, M_ACK_VARIABLE, variableType);
return get(GATEWAY_ADDRESS, childId, M_REQ_VARIABLE, M_SET_VARIABLE, variableType);
}
char * Sensor::getStatus(uint8_t nodeId, int8_t childId, uint8_t variableType) {
return get(nodeId, childId, M_REQ_VARIABLE, M_ACK_VARIABLE, variableType);
return get(nodeId, childId, M_REQ_VARIABLE, M_SET_VARIABLE, variableType);
}
@@ -385,22 +399,33 @@ void Sensor::requestIsMetricSystem() {
boolean Sensor::messageAvailable() {
uint8_t pipe;
boolean available = RF24::available(&pipe);
if (available) {
debug(PSTR("Message available on pipe %d\n"),pipe);
}
if (available && pipe<7) {
boolean ok = readMessage();
uint8_t len = RF24::getDynamicPayloadSize();
RF24::read(&msg, len);
RF24::writeAckPayload(pipe,&pipe, 1 );
if (available) {
debug(PSTR("Message available on pipe %d\n"),pipe);
}
uint8_t valid = validate(len-sizeof(header_s));
boolean ok = valid == VALIDATE_OK;
// Make sure string gets terminated ok for full sized messages.
msg.data[len - sizeof(header_s) ] = '\0';
debug(PSTR("Rx: fr=%d,to=%d,la=%d,ci=%d,mt=%d,t=%d,cr=%d(%s): %s\n"),
msg.header.from,msg.header.to, msg.header.last, msg.header.childId, msg.header.messageType, msg.header.type, msg.header.crc, valid==0?"ok":valid==1?"ec":"ev", msg.data);
// boolean ok = readMessage();
if (ok && msg.header.to == radioId) {
// This message is addressed to this node
debug(PSTR("Message addressed for this node.\n"));
if (msg.header.from == GATEWAY_ADDRESS &&
// If this is variable message from sensor net gateway. Send ack back.
msg.header.messageType == M_SET_VARIABLE) {
// Send back ack message to sensor net gateway
// Send set-message back to sender if sender wants this
if (msg.header.messageType == M_SET_WITH_ACK) {
sendVariableAck();
// The library user should not need to care about this ack request. Just treat it as a normal SET.
msg.header.messageType = M_SET_VARIABLE;
}
// Return message to waiting sketch...
return true;
@@ -423,7 +448,7 @@ message_s Sensor::getMessage() {
}
boolean Sensor::readMessage() {
/*boolean Sensor::readMessage() {
uint8_t len = RF24::getDynamicPayloadSize();
RF24::read(&msg, len);
@@ -435,7 +460,7 @@ boolean Sensor::readMessage() {
debug(PSTR("Rx: fr=%d,to=%d,la=%d,ci=%d,mt=%d,t=%d,cr=%d(%s): %s\n"),
msg.header.from,msg.header.to, msg.header.last, msg.header.childId, msg.header.messageType, msg.header.type, msg.header.crc, valid==0?"ok":valid==1?"ec":"ev", msg.data);
return ok;
}
}*/
/*
* calculate CRC8 on message_s data taking care of data structure and protocol version
+4 -4
View File
@@ -1,5 +1,5 @@
/*
The Sensor Net Arduino library adds a new layer on top of the RF24 library.
The MySensors library adds a new layer on top of the RF24 library.
It handles radio network routing, relaying and ids.
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
@@ -41,7 +41,7 @@
// This is the radioId for sensor net gateway receiver sketch (where all sensors should send their data).
// This is also act as base value for sensor radioId
#define BASE_RADIO_ID ((uint64_t)0xABCDABC000LL)
#define BASE_RADIO_ID ((uint64_t)0xA8A8E1FC00LL)
#define GATEWAY_ADDRESS ((uint8_t)0)
#define BROADCAST_ADDRESS ((uint8_t)0xFF)
#define TO_ADDR(x) (BASE_RADIO_ID + x)
@@ -61,7 +61,7 @@ typedef enum {
M_PRESENTATION = 0,
M_SET_VARIABLE = 1,
M_REQ_VARIABLE = 2,
M_ACK_VARIABLE = 3,
M_SET_WITH_ACK = 3,
M_INTERNAL = 4
} messageType;
@@ -278,7 +278,7 @@ class Sensor : public RF24
void findRelay();
boolean send(message_s message, int length);
boolean sendWrite(uint8_t dest, message_s message, int length);
boolean readMessage();
//boolean readMessage();
void buildMsg(uint8_t from, uint8_t to, uint8_t childId, uint8_t messageType, uint8_t type, const char *data, uint8_t length, boolean binary);
void sendInternal(uint8_t variableType, const char *value);
boolean sendVariableAck();
@@ -6,11 +6,11 @@
#include <RF24.h>
#define RELAY_1 3 // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
#define NUMBER_OF_RELAYS 1
#define RELAY_ON 0
#define RELAY_OFF 1
#define NUMBER_OF_RELAYS 1 // Total number of attached relays
#define RELAY_ON 1 // GPIO value to write to turn on attached relay
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
Sensor gw;
Relay gw;
void setup()
{