Skip to content

Commit 0b1f0dc

Browse files
committed
Merge pull request arduino#109 from thozza/development-leds
Add LEDs blinking into base MySensor class without any library dependency
2 parents f015fa1 + 29b8680 commit 0b1f0dc

File tree

7 files changed

+209
-180
lines changed

7 files changed

+209
-180
lines changed

libraries/MySensors/MyConfig.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,26 @@
4545
#define MY_OTA_FLASH_JDECID 0x1F65
4646

4747

48+
/**********************************
49+
* Information LEDs blinking
50+
***********************************/
51+
// This feature enables LEDs blinking on message receive, transmit
52+
// or if some error occured. This was commonly used only in gateways,
53+
// but now can be used in any sensor node. Also the LEDs can now be
54+
// disabled in the gateway.
55+
56+
// #define WITH_LEDS_BLINKING
57+
58+
// default LEDs blinking period in milliseconds
59+
#define DEFAULT_LED_BLINK_PERIOD 300
60+
// The RX LED default pin
61+
#define DEFAULT_RX_LED_PIN 8
62+
// The TX LED default pin
63+
#define DEFAULT_TX_LED_PIN 9
64+
// The Error LED default pin
65+
#define DEFAULT_ERR_LED_PIN 7
66+
67+
4868
/**********************************
4969
* Message Signing Settings
5070
***********************************/

libraries/MySensors/MySensor.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,19 @@ static inline bool isValidDistance( const uint8_t distance ) {
5252
MySensor::MySensor(MyTransport &_radio, MyHw &_hw
5353
#ifdef MY_SIGNING_FEATURE
5454
, MySigning &_signer
55+
#endif
56+
#ifdef WITH_LEDS_BLINKING
57+
, uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period
5558
#endif
5659
)
5760
:
5861
radio(_radio),
5962
#ifdef MY_SIGNING_FEATURE
6063
signer(_signer),
6164
#endif
65+
#ifdef WITH_LEDS_BLINKING
66+
pinRx(_rx), pinTx(_tx), pinEr(_er), ledBlinkPeriod(_blink_period),
67+
#endif
6268
#ifdef MY_OTA_FIRMWARE_FEATURE
6369
flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID),
6470
#endif
@@ -90,6 +96,64 @@ bool MySensor::isValidFirmware() {
9096

9197
#endif
9298

99+
#ifdef WITH_LEDS_BLINKING
100+
void MySensor::handleLedsBlinking() {
101+
static unsigned long next_time = hw_millis() + ledBlinkPeriod;
102+
103+
// Just return if it is not the time...
104+
// http://playground.arduino.cc/Code/TimingRollover
105+
if ((long)(hw_millis() - next_time) < 0)
106+
return;
107+
else
108+
next_time = hw_millis() + ledBlinkPeriod;
109+
110+
// do the actual blinking
111+
if(countRx && countRx != 255) {
112+
// switch led on
113+
digitalWrite(pinRx, LOW);
114+
}
115+
else if(!countRx) {
116+
// switching off
117+
digitalWrite(pinRx, HIGH);
118+
}
119+
if(countRx != 255)
120+
--countRx;
121+
122+
if(countTx && countTx != 255) {
123+
// switch led on
124+
digitalWrite(pinTx, LOW);
125+
}
126+
else if(!countTx) {
127+
// switching off
128+
digitalWrite(pinTx, HIGH);
129+
}
130+
if(countTx != 255)
131+
--countTx;
132+
133+
if(countErr && countErr != 255) {
134+
// switch led on
135+
digitalWrite(pinEr, LOW);
136+
}
137+
else if(!countErr) {
138+
// switching off
139+
digitalWrite(pinEr, HIGH);
140+
}
141+
if(countErr != 255)
142+
--countErr;
143+
}
144+
145+
void MySensor::rxBlink(uint8_t cnt) {
146+
if(countRx == 255) { countRx = cnt; }
147+
}
148+
149+
void MySensor::txBlink(uint8_t cnt) {
150+
if(countTx == 255) { countTx = cnt; }
151+
}
152+
153+
void MySensor::errBlink(uint8_t cnt) {
154+
if(countErr == 255) { countErr = cnt; }
155+
}
156+
#endif
93157

94158
void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, boolean _repeaterMode, uint8_t _parentNodeId) {
95159
hw_init();
@@ -111,6 +175,23 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b
111175
hw_readConfigBlock((void*)doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(doSign));
112176
#endif
113177

178+
#ifdef WITH_LEDS_BLINKING
179+
// Setup led pins
180+
pinMode(pinRx, OUTPUT);
181+
pinMode(pinTx, OUTPUT);
182+
pinMode(pinEr, OUTPUT);
183+
184+
// Set initial state of leds
185+
digitalWrite(pinRx, HIGH);
186+
digitalWrite(pinTx, HIGH);
187+
digitalWrite(pinEr, HIGH);
188+
189+
// initialize counters
190+
countRx = 0;
191+
countTx = 0;
192+
countErr = 0;
193+
#endif
194+
114195
if (isGateway) {
115196
// Set configuration for gateway
116197
nc.parentNodeId = GATEWAY_ADDRESS;
@@ -246,12 +327,18 @@ boolean MySensor::sendRoute(MyMessage &message) {
246327
// If we still don't have any parent id, re-request and skip this message.
247328
if (nc.parentNodeId == AUTO) {
248329
findParentNode();
330+
#ifdef WITH_LEDS_BLINKING
331+
errBlink(1);
332+
#endif
249333
return false;
250334
}
251335

252336
// If we still don't have any node id, re-request and skip this message.
253337
if (nc.nodeId == AUTO) {
254338
requestNodeId();
339+
#ifdef WITH_LEDS_BLINKING
340+
errBlink(1);
341+
#endif
255342
return false;
256343
}
257344

@@ -288,10 +375,16 @@ boolean MySensor::sendRoute(MyMessage &message) {
288375
}
289376
if (hw_millis() - enter > MY_VERIFICATION_TIMEOUT_MS) {
290377
debug(PSTR("nonce tmo\n"));
378+
#ifdef WITH_LEDS_BLINKING
379+
errBlink(1);
380+
#endif
291381
return false;
292382
}
293383
if (!signOk) {
294384
debug(PSTR("sign fail\n"));
385+
#ifdef WITH_LEDS_BLINKING
386+
errBlink(1);
387+
#endif
295388
return false;
296389
}
297390
// After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed,
@@ -350,6 +443,9 @@ boolean MySensor::sendRoute(MyMessage &message) {
350443
if (!ok) {
351444
// Failure when sending to parent node. The parent node might be down and we
352445
// need to find another route to gateway.
446+
#ifdef WITH_LEDS_BLINKING
447+
errBlink(1);
448+
#endif
353449
failedTransmissions++;
354450
if (autoFindParent && failedTransmissions > SEARCH_FAILURES) {
355451
findParentNode();
@@ -364,6 +460,9 @@ boolean MySensor::sendWrite(uint8_t to, MyMessage &message) {
364460
mSetVersion(message, PROTOCOL_VERSION);
365461
uint8_t length = mGetSigned(message) ? MAX_MESSAGE_LENGTH : mGetLength(message);
366462
message.last = nc.nodeId;
463+
#ifdef WITH_LEDS_BLINKING
464+
txBlink(1);
465+
#endif
367466
bool ok = radio.send(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length));
368467

369468
debug(PSTR("send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,st=%s:%s\n"),
@@ -408,6 +507,11 @@ void MySensor::requestTime(void (* _timeCallback)(unsigned long)) {
408507

409508
boolean MySensor::process() {
410509
hw_watchdogReset();
510+
511+
#ifdef WITH_LEDS_BLINKING
512+
handleLedsBlinking();
513+
#endif
514+
411515
uint8_t to = 0;
412516
if (!radio.available(&to))
413517
{
@@ -418,6 +522,9 @@ boolean MySensor::process() {
418522
debug(PSTR("fw upd fail\n"));
419523
// Give up. We have requested MY_OTA_RETRY times without any packet in return.
420524
fwUpdateOngoing = false;
525+
#ifdef WITH_LEDS_BLINKING
526+
errBlink(1);
527+
#endif
421528
return false;
422529
}
423530
fwRetry--;
@@ -439,6 +546,9 @@ boolean MySensor::process() {
439546
#endif
440547

441548
uint8_t len = radio.receive((uint8_t *)&msg);
549+
#ifdef WITH_LEDS_BLINKING
550+
rxBlink(1);
551+
#endif
442552

443553
#ifdef MY_SIGNING_FEATURE
444554
// Before processing message, reject unsigned messages if signing is required and check signature (if it is signed and addressed to us)
@@ -451,10 +561,16 @@ boolean MySensor::process() {
451561
if (!mGetSigned(msg)) {
452562
// Got unsigned message that should have been signed
453563
debug(PSTR("no sign\n"));
564+
#ifdef WITH_LEDS_BLINKING
565+
errBlink(1);
566+
#endif
454567
return false;
455568
}
456569
else if (!signer.verifyMsg(msg)) {
457570
debug(PSTR("verify fail\n"));
571+
#ifdef WITH_LEDS_BLINKING
572+
errBlink(1);
573+
#endif
458574
return false; // This signed message has been tampered with!
459575
}
460576
}
@@ -468,6 +584,9 @@ boolean MySensor::process() {
468584

469585
if(!(mGetVersion(msg) == PROTOCOL_VERSION)) {
470586
debug(PSTR("ver mismatch\n"));
587+
#ifdef WITH_LEDS_BLINKING
588+
errBlink(1);
589+
#endif
471590
return false;
472591
}
473592

libraries/MySensors/MySensor.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ class MySensor
145145
MySensor(MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver()
146146
#ifdef MY_SIGNING_FEATURE
147147
, MySigning &signer=*new MySigningNone()
148+
#endif
149+
#ifdef WITH_LEDS_BLINKING
150+
, uint8_t _rx=DEFAULT_RX_LED_PIN,
151+
uint8_t _tx=DEFAULT_TX_LED_PIN,
152+
uint8_t _er=DEFAULT_ERR_LED_PIN,
153+
unsigned long _blink_period=DEFAULT_LED_BLINK_PERIOD
148154
#endif
149155
);
150156

@@ -299,6 +305,15 @@ class MySensor
299305
*/
300306
int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0);
301307

308+
#ifdef WITH_LEDS_BLINKING
309+
/**
310+
* Blink with LEDs
311+
* @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms
312+
*/
313+
void rxBlink(uint8_t cnt);
314+
void txBlink(uint8_t cnt);
315+
void errBlink(uint8_t cnt);
316+
#endif
302317

303318
protected:
304319
NodeConfig nc; // Essential settings for node to work
@@ -324,6 +339,20 @@ class MySensor
324339
MySigning& signer;
325340
#endif
326341

342+
#ifdef WITH_LEDS_BLINKING
343+
uint8_t pinRx; // Rx led pin
344+
uint8_t pinTx; // Tx led pin
345+
uint8_t pinEr; // Err led pin
346+
347+
// these variables don't need to be volatile, since we are not using interrupts
348+
uint8_t countRx;
349+
uint8_t countTx;
350+
uint8_t countErr;
351+
352+
unsigned long ledBlinkPeriod;
353+
void handleLedsBlinking(); // do the actual blinking
354+
#endif
355+
327356
MyTransport& radio;
328357
MyHw& hw;
329358

libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
* E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003
4747
*
4848
* LED purposes:
49+
* - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h
4950
* - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved
5051
* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
5152
* - ERR (red) - fast blink on error during transmission error or recieve crc error
@@ -68,7 +69,6 @@
6869
#include <MyParserSerial.h>
6970
#include <MySensor.h>
7071
#include <stdarg.h>
71-
#include <MsTimer2.h>
7272
#include <PinChangeInt.h>
7373
#include "GatewayUtil.h"
7474

@@ -104,7 +104,12 @@ MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
104104
MyHwATMega328 hw;
105105

106106
// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
107+
// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h
108+
#ifdef WITH_LEDS_BLINKING
109+
MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
110+
#else
107111
MySensor gw(transport, hw /*, signer*/);
112+
#endif
108113

109114

110115
#define IP_PORT 5003 // The port you want to open
@@ -136,11 +141,8 @@ void output(const char *fmt, ... ) {
136141
void setup()
137142
{
138143
Ethernet.begin(mac, myIp);
139-
setupGateway(RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN, INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output);
140144

141-
// Add led timer interrupt
142-
MsTimer2::set(300, ledTimersInterrupt);
143-
MsTimer2::start();
145+
setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output);
144146

145147
// Add interrupt for inclusion button to pin
146148
PCintPort::attachInterrupt(pinInclusion, startInclusionInterrupt, RISING);

0 commit comments

Comments
 (0)