Tapatalk

Whisper node temp example

Whisper node temp example

7

PostMay 30, 2017#1

Hi, Have had my whisper nodes for a while and now just getting around to doing something.

I am looking at adding a few DS18B20 sensors and with an environmental sensor (press and humid), after looking at the Voltage node example I have a few questions about the protocol/ msg format.

Obviously I can just add the library I need, dependant of course on the compiled size and insert the relevant setup and loop routines.


My first questions regarding the code snippet below,
  • Does this section send two messages ? one with voltage 1 and another with voltage 2?.
  • what is the purpose of myMsg.sdx as it is not in the prepare msg section, but I can see it in the T2message protocol section of the Library

Code: Select all

 if(supply == 1)

  {
    voltage = T2Utils::readVoltage(T2_WPN_VBAT_VOLTAGE, T2_WPN_VBAT_CONTROL);
    myMsg.sdx = 0x64; // Battery
  }

  if(supply == 2)
  {
    voltage = T2Utils::readVoltage(T2_WPN_VIN_VOLTAGE, T2_WPN_VIN_CONTROL);
    myMsg.sdx = 0x65; // Supply
  }
Just wanting to understand the msg format more.

The first four are easy, msg format, node and base address for comms. But am curious about the data ones
  • myMsg.data[0] = 0x01; // Operation Last Reading .what role function does this play
  • myMsg.data[1] = 0x01; // Battery/Supply Index, if multiple supplies. does I change this for two voltages ??
  • myMsg.data[2] = voltage >> 8; why the bitshift right ??
  • myMsg.data[3] = voltage; other part of the voltage meausrement
  • myMsg.len = 4; //Update length[/code] data length
data[0]

Code: Select all

// Prepare Message

  myMsg.cmd = 0x00;
  myMsg.idx = 0x06;
  myMsg.src = nodeAddr;
  myMsg.dst = baseAddr;
  myMsg.data[0] = 0x01; // Operation Last Reading
  myMsg.data[1] = 0x01; // Battery/Supply Index, if multiple supplies
  myMsg.data[2] = voltage >> 8;
  myMsg.data[3] = voltage;
  myMsg.len = 4; //Update length

So I want to add for example two temps and a humidity, can I just adjust the prepare msg to include my temps etc and then change the msg length to suit???


Apologies for all the question just couldn't see anything directly relating to the protocol and msg make up...


Regards Paul

1885
1885

PostMay 30, 2017#2

Hi Paul,

Thanks for getting in contact. Your questions are very valid and we still have an article to finish about our suggested message protocol/format.

Just before starting, bear in mind that the message format is something not tied to the hardware or to the RFM69 library (see RadioHead library if you need examples). That's something we've been using on other projects and we've used in our examples as a suggestions to the users.

Now about the message format, it has been designed to be compatible with the CAN Bus frame size, as this is a common platform we develop many other solutions. You can find brief explanation about it on this link: https://talk2.wisen.com.au/2015/11/11/t ... -protocol/.

Having the CAN Bus message format as starting point, we make use of the 29 bits index (or CAN ID), to build the message header, as you probably noticed. The first step is to break those 29 bits in 5 fields, on the following order:

IDX - Index (3 bits or 0 to 7 decimal)
CMD - Command (2 bits or 0 to 3 decimal)
SDX - Sub-Index (8 bits or 0 to 254 decimal)
SRC - Source (8 bits or 0 to 254 decimal)
DST - Destination (8 bits or 0 to 254 decimal)

With the fields above we can identify the message type, direction and other things. The fields can be used they use you prefer to build your own protocol standard. But here a more detailed description how we normally use the fields:

IDX - Index
This determine the type of the message and we have the following standards:

0x00 to 0x02: Reserved
0x03: Non-standard. Different for each node Type/Model - High Priority
0x04: Actuators
0x05: Human Interaction Device and Sensors
0x06: Node: Details, Status and Configuration
0x07: Non-standard. Different for each node Type/Model - Low Priority

CMD - Command
This is used to tell the if kind of action the message is representing.

0x00: Event - Imagine a sensor being triggered, this will cause an "event" to be broadcasted
0x01: Write - This is used to change a register value, or to control an actuator for example
0x02: Read - This can be used to get values from a sensor, pooling information from a register
0x03: Return - This is the data sent back from a Read (or Write) or when you have an error after a Write

SDX - Subindex
The subindex, is used to specify exactly what object you're working with. For example, a Temperature sensor would have a IDX=0x05 (Sensors) and the SIDX=0x0A (Temperature).

You can build your own mapping of objects here. For example 0x0A for Temperature, 0x0B for Hunidity, etc.

SRC and DST
Well, this is quite clear. But we also suggest to reserve a few values, like 0x00 or 0xFF for broadcast, so all nodes that get the message will process it. But again, it might vary according to your needs and implementation.

DATA[0-7]
Here is the message payload, and as well you have the flexibility to format it the way you prefer. For example, if you have a node with multiple temperature sensors, would make more sense to reserve the first byte as a "index" to identify which sensor the message is referring to.

The Voltage message, for example, counts with more than that. In the example message we suggest using a "operation" and a "index" byte. This is not fixed, it's just a proposed model where you could use the operation to define if you're reading the sensor value, defining a threshold, disabling regular voltage readings broadcasts, doesn't really matter. And again, the index would be useful if you have a node monitoring multiple voltage sources, or multiple batteries.

Again, for the example, we read the battery voltage and provide the information in millivolts, so the message could contain any value from 0 to 65,535 millivolts as the data uses 2 bytes.

DATA Byte shifting
The byte shifting is necessary as a message is sent as an array of bytes and not as a long or a int32_t, etc. In this matter is important to determine if you prefer to use MSB or LSB. For example, the number -12329, it won't fit in a single byte, so you need to break it in at least two:

If you have a variable type int16_t with the value of -12329, in binary it's the same as 11001111 11010111. If you try to assign it to a 8 bits variable, like uint_8t, the MCU will only grab the lower 8 bits, ignoring everything else. That's why you need to always shift right to send the data and shift left when receiving it:

(11001111 11010111 >> 8) will result in 00000000 11001111 and now you can assign it to an 8-bit variable to load the higher bits.

For example:
int16_t send = -12329
data[0] = send >> 8
data[1] = send

That's the same as:
send = 11001111 11010111
data[0] = 11001111
data[1] = 11010111

Doing the opposite, you can re-build the same int16_t:
int16t receive = 0
receive = data[0]
receive = received << 8 || data[1]

That's the same as:
receive = 00000000 00000000
receive = 00000000 11001111
receive = 11001111 11010111

LEN
This is required for the message decoder to know the payload size, otherwise we would need to always send fixed message sizes, which can be not the most optimized.

What's Next?
As you can see there's not a 100% fixed protocol, we've just create a "Talk 2 Message" in a flexible way for each person to implement their needs, the way they prefer. At the same time we try to facilitate the implementation by giving some ready-to-use header fields, which are small and optimized to low-power wireless communication.

If you plan to have many kinds of messages and many different nodes, it's very important to create a table of messages format. Nothing prevent you to use messages like: temp=24.5, but that would be a huge message and a waste of memory together with non-optimized wireless transmission.

As a rule of thumb, is important to design your protocol to use only the amount of data require to send the data, nothing extra.

For your project, sure you can modify the message format. If you always going to send temp and humidity at the same time, makes more sense to join both in a single message. Using, for example, the first two bytes for temperature and the next two for humidity.

My suggestion is to always use intXX_t and uintXX_t instead of short, byte, long etc. This will always work independent of the platform and the variable size will always be very clear. For transporting the data, always use a uint8_t, independent if the value is a negative integer, float, etc. For transporting, bits are bits, the negative or float are only representation of it.

Well, hopefully I haven't complicated things too much. Please let me know if something is not very clear.

Cheers,
Mike M.

7

PostMay 30, 2017#3

Hi, Thanks for your reply

Given me some things to ponder and learn. :)

Have been doing monitoring with Open Energy Monitor for a while now and they use a somewhat simpler yet not as fancy or efficient in sending data but can see the positives of the CAN style format.

Will have a play and see how I go.

Thanks Heaps Paul