Guys,
Here's some code to try out. A slave and a master. The slave goes to sleep, and wakes up every 64 seconds, reads VIN and VBAT and sends them to the master.
It's working nicely. However:
The fields cmd and idx in the message frame are not updating correctly. In the slave code, I set cmd to 0xAA (I presume this is a command code, so I set it to 0xAA which the master would look for), but it is received at the master as 2.
I increment idx each time I transmit a message, however, I'm not seeing that on the master side. It looks like these values are being internally over-written somewhere. Maybe I'm using them wrong?
Sample output from master:
Note idx and cmd above, are incorrect. idx should be incrementing, and cmd should be 0xAA.
Master code:
Slave code:
Here's some code to try out. A slave and a master. The slave goes to sleep, and wakes up every 64 seconds, reads VIN and VBAT and sends them to the master.
It's working nicely. However:
The fields cmd and idx in the message frame are not updating correctly. In the slave code, I set cmd to 0xAA (I presume this is a command code, so I set it to 0xAA which the master would look for), but it is received at the master as 2.
I increment idx each time I transmit a message, however, I'm not seeing that on the master side. It looks like these values are being internally over-written somewhere. Maybe I'm using them wrong?
Sample output from master:
Code: Select all
adio initialised successfully.
Waiting for incoming transmission...
Incoming message detected...
------- MSG Dump: START -------
Headers: HEX [DEC]
Idx: 2 [2]
Cmd: 2 [2]
Sdx: 0 [0]
Src: 1 [1]
Dst: 0 [0]
Rtr: 0 [0]
Length: 4
C:83:0:E:
-------- MSG Dump: END --------
Battery voltage (mV):3203
VIn voltage (mV):14
Waiting for incoming transmission...
Incoming message detected...
------- MSG Dump: START -------
Headers: HEX [DEC]
Idx: 3 [3]
Cmd: 2 [2]
Sdx: 0 [0]
Src: 1 [1]
Dst: 0 [0]
Rtr: 0 [0]
Length: 4
C:83:0:15:
-------- MSG Dump: END --------
Battery voltage (mV):3203
VIn voltage (mV):21
Waiting for incoming transmission...
Incoming message detected...
------- MSG Dump: START -------
Headers: HEX [DEC]
Idx: 2 [2]
Cmd: 2 [2]
Sdx: 0 [0]
Src: 1 [1]
Dst: 0 [0]
Rtr: 0 [0]
Length: 4
C:83:0:15:
-------- MSG Dump: END --------
Battery voltage (mV):3203
VIn voltage (mV):21
Waiting for incoming transmission...
Incoming message detected...
------- MSG Dump: START -------
Headers: HEX [DEC]
Idx: 3 [3]
Cmd: 2 [2]
Sdx: 0 [0]
Src: 1 [1]
Dst: 0 [0]
Rtr: 0 [0]
Length: 4
C:8A:0:7:
-------- MSG Dump: END --------
Battery voltage (mV):3210
VIn voltage (mV):7
Waiting for incoming transmission...
Incoming message detected...
------- MSG Dump: START -------
Headers: HEX [DEC]
Idx: 6 [6]
Cmd: 2 [2]
Sdx: 0 [0]
Src: 1 [1]
Dst: 0 [0]
Rtr: 0 [0]
Length: 4
C:83:0:E:
-------- MSG Dump: END --------
Battery voltage (mV):3203
VIn voltage (mV):14
Waiting for incoming transmission...
Incoming message detected...
------- MSG Dump: START -------
Headers: HEX [DEC]
Idx: 7 [7]
Cmd: 2 [2]
Sdx: 0 [0]
Src: 1 [1]
Dst: 0 [0]
Rtr: 0 [0]
Length: 4
C:7C:0:E:
-------- MSG Dump: END --------
Battery voltage (mV):3196
VIn voltage (mV):14
Waiting for incoming transmission...
Incoming message detected...
------- MSG Dump: START -------
Headers: HEX [DEC]
Idx: 6 [6]
Cmd: 2 [2]
Sdx: 0 [0]
Src: 1 [1]
Dst: 0 [0]
Rtr: 0 [0]
Length: 4
C:74:0:7:
-------- MSG Dump: END --------
Battery voltage (mV):3188
VIn voltage (mV):7
Waiting for incoming transmission...
Master code:
Code: Select all
#include <T2WhisperNode.h>
#include <LowPower.h>
/* You need to configure the Whisper Node Version */
#define T2_WPN_BOARD T2_WPN_VER_RF69
//define T2_WPN_BOARD T2_WPN_VER_LORA
#if T2_WPN_BOARD == T2_WPN_VER_RF69
#include <RH_RF69.h>
RH_RF69 myRadio;
#elif T2_WPN_BOARD == T2_WPN_VER_LORA
#include <RH_RF95.h>
RH_RF95 myRadio;
#endif
// flash memory handler object
T2Flash myFlash;
// Radio
uint8_t packetBuffer[(T2_MESSAGE_HEADERS_LEN + T2_MESSAGE_MAX_DATA_LEN)];
#define RADIO_ENCRYPTION_KEY { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } // Only used by RF69
#define RADIO_FREQUENCY 868.1
#define RADIO_TX_POWER 2
#define HIGH_POWER true
// T2 Message
T2Message myMsg;
#define MASTER_ADDRESS 0x00
#define SLAVE_ADDRESS 0x01
void setup()
{
Serial.begin(115200);
pinMode(6,OUTPUT); // for driving the blue LED
digitalWrite(6,LOW);
// initialise radio
if(myRadio.init()) {
myRadio.setFrequency(RADIO_FREQUENCY);
myRadio.setTxPower(RADIO_TX_POWER, HIGH_POWER); // we're using the high power Talk2 module
#if T2_WPN_BOARD == T2_WPN_VER_RF69
uint8_t myRadioEncryptionKey[] = RADIO_ENCRYPTION_KEY;
myRadio.setEncryptionKey(myRadioEncryptionKey);
#endif
Serial.println(F("Radio initialised successfully."));
}
displayMessage();
}
void loop()
{
uint8_t radioBufLen = sizeof(packetBuffer);
if(myRadio.recv(packetBuffer, &radioBufLen))
{
digitalWrite(6,HIGH); // blue led on
Serial.println(F("Incoming message detected..."));
myMsg.setSerializedMessage(packetBuffer, radioBufLen);
// Uncomment below to print every received message, just be careful as
// delays here can cause messages to be lost.
myMsg.printMessage();
// check that the command type is 0xAA (report supply voltages) and that the
// destination address is 0 (which is the address of the master)
if(myMsg.dst == MASTER_ADDRESS)
{
// we can process this packet
uint16_t vBat;
uint16_t vIn;
vBat = myMsg.data[0] << 8 | myMsg.data[1];
vIn = myMsg.data[2] << 8 | myMsg.data[3];
if(myMsg.src > 0 && myMsg.src <= 8) {
Serial.print(F("Battery voltage (mV):"));
Serial.println(vBat);
Serial.print(F(" VIn voltage (mV):"));
Serial.println(vIn);
} else
Serial.println(F("Illegal slave ID detected in message."));
} else
Serial.println(F("Message detected, but not for this device, or un-supported command"));
displayMessage();
digitalWrite(6,LOW); // blue led off
}
}
void displayMessage() {
Serial.println(F("Waiting for incoming transmission..."));
}
Code: Select all
/*
* Talk2 Example: Wake periodic, transmit data, and go to sleep.
*
* This example demonstrates how you can use the Talk2 Library to transmit
* data over the air, and power down all peripherals and the radio between
* transmissions.
*
* The CPU wakes up every 8 seconds and increments a counter. When the counter
* has been incremented 8 times (thus, every 64 seconds) the CPU will read
* the VBAT and VIN supply voltages and send them over the air.
* When the transmission is complete the CPU powers the radio down and then
* puts itself back to sleep.
*
* The Sketch will uses a digitalWrite to blink the LEDs while transmitting
*
* This sketch is written specifically for the Talk2 Whisper Node, available
* from http://talk2.wisen.com.au
*
* Copyright 2017 by Mark Wills (markwills1970@gmail.com)
*
* This sketch is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <T2WhisperNode.h>
#include <LowPower.h>
/* You need to configure the Whisper Node Version */
#define T2_WPN_BOARD T2_WPN_VER_RF69
//define T2_WPN_BOARD T2_WPN_VER_LORA
#if T2_WPN_BOARD == T2_WPN_VER_RF69
#include <RH_RF69.h>
RH_RF69 myRadio;
#elif T2_WPN_BOARD == T2_WPN_VER_LORA
#include <RH_RF95.h>
RH_RF95 myRadio;
#endif
// flash memory handler object
T2Flash myFlash;
// Radio
uint8_t packetBuffer[(T2_MESSAGE_HEADERS_LEN + T2_MESSAGE_MAX_DATA_LEN)];
#define RADIO_ENCRYPTION_KEY { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } // Only used by RF69
#define RADIO_FREQUENCY 868.1
#define RADIO_TX_POWER 2
#define HIGH_POWER true
// T2 Message
T2Message myMsg;
#define MASTER_ADDRESS 0x00
#define SLAVE_ADDRESS 0x01
/* number of transmissions this slave has sent. This could be used on the Master side
* to determine if the master has missed any transmissions */
uint16_t txCount=0;
/* counter for the number of times we've woken up. when we've woken up 8 times (64 seconds)
* we'll read the voltages and transmit them */
uint16_t wakeCount;
void setup()
{
Serial.begin(115200);
Serial.println(F("Example: Send data over radio and put radio and CPU to sleep "));
Serial.println(F("This program sends the battery voltage (VBAT) and the main power"));
Serial.println(F("supply voltage (VIN) over the air every 64 seconds (approximately)."));
Serial.println(F("The CPU wakes up every 8 seconds and checks if 64 seconds has"));
Serial.println(F("has elasped. If not, the CPU, flash, and radio go back to sleep."));
Serial.println(F("If 64 seconds HAS elapsed, the voltages are checked, and then"));
Serial.println(F("transmitted over the air, then everything goes back to sleep again.\n"));
// Radio - Initialize the radio and put it to sleep to save energy
if(myRadio.init()) {
myRadio.setFrequency(RADIO_FREQUENCY);
myRadio.setTxPower(RADIO_TX_POWER, HIGH_POWER); // we're using the high power Talk2 module
#if T2_WPN_BOARD == T2_WPN_VER_RF69
uint8_t myRadioEncryptionKey[] = RADIO_ENCRYPTION_KEY;
myRadio.setEncryptionKey(myRadioEncryptionKey);
#endif
// Flash - We're not using, so just power it down to save energy
myFlash.init(T2_WPN_FLASH_SPI_CS);
myFlash.powerDown();
pinMode(6,OUTPUT); // set led pin as an output
Serial.println(F("Radio successfully initialised."));
} else
Serial.println(F("** Fatal error: Cannot intialise radio. **"));
}
void loop()
{
// code starts running from here when the CPU wakes up
if((++wakeCount)%8==0) {
// ~64 seconds has elapsed... time to do some work
Serial.println(F("I'm awake!"));
transmitVoltages();
} else
Serial.println("Woke up. Nothing to do!");
// put the radio and the CPU back to sleep
Serial.println(F("Going back to sleep! ZZZZzzzz....\n"));
Serial.flush();
myRadio.sleep();
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
void transmitVoltages() {
uint16_t vBat, vIn;
digitalWrite(6,HIGH); // led on
// read the battery and supply voltages
vBat=T2Utils::readVoltage(T2_WPN_VBAT_VOLTAGE, T2_WPN_VBAT_CONTROL);
vIn=T2Utils::readVoltage(T2_WPN_VIN_VOLTAGE, T2_WPN_VIN_CONTROL);
Serial.print(F("Battery voltage (mV):"));
Serial.println(vBat);
Serial.print(F(" Supply voltage (mV):"));
Serial.println(vIn);
uint8_t packetBufferLen = 0;
// prepare a message to transmit over the air
myMsg.cmd = 0xAA;
myMsg.idx = txCount++;
myMsg.src = SLAVE_ADDRESS;
myMsg.dst = MASTER_ADDRESS;
myMsg.data[0] = vBat >> 8; // most significant 8 bits
myMsg.data[1] = vBat; // lower 8 bits
myMsg.data[2] = vIn >> 8; // most significant 8 bits
myMsg.data[3] = vIn; // lower 8 bits
myMsg.len = 4; // set number of data items in message
// Encode Message into a radio packet and get the full length
myMsg.getSerializedMessage(packetBuffer, &packetBufferLen);
// Send it (this turns the radio on automatically)
myRadio.send(packetBuffer, packetBufferLen);
bool success=myRadio.waitPacketSent(1000);
if(success)
Serial.println(F("Message sent succesfully."));
else
Serial.println(F("Timeout while sending message."));
digitalWrite(6,LOW); // led off
}