A simple wireless protocol to let my examples communicate each other. ssWi stands for Shared Slotted Wireless protocol

Dependents:   rover_car rover_pc supervisor watering_unit ... more

This library aims at implementing a simple communication protocol among nodes, abstracting from the hardware. The name ssWi stands for Shared Slotted Wireless. Wireless is part of the name, even though the library abstracts from the hardware, as the first version was entirely focused on the XBee modules and then the name has not been changed.

The communication channel is represented by ssWiChannel, an abstract class which models the channel that the transceivers access to. The concrete classes must implement the functions: init, read and write. The protocol automatically sends and receives data through the selected channel, exploiting the operting system timers. Addresses are not considered as the communication lays on broadcast transmissions.

The protocol provides the ssWiPort abstraction which is like memory areas shared among all the connected nodes. Reading from one port lets the node retrieve the last written value from the other nodes. Writing on one port means sending such value to other nodes.

Objects instantiated from ssWiSocket are the interface for allowing nodes to access the protocol ports.

/media/uploads/mariob/scheme.png

TODO:

  • improve the parsing of the received messages
  • communication tests with many nodes (so far, only 2 nodes have been tested)
Committer:
mariob
Date:
Mon Apr 20 20:27:01 2020 +0000
Revision:
24:80345e511574
Parent:
20:36931ee9af85
few more comments

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mariob 15:fb0f6cbc0ed5 1 /** \file xbee.cpp
mariob 20:36931ee9af85 2 *
mariob 15:fb0f6cbc0ed5 3 * \brief implementation of the ssWi channel using the XBee module
mariob 15:fb0f6cbc0ed5 4 *
mariob 15:fb0f6cbc0ed5 5 */
mariob 20:36931ee9af85 6
mariob 15:fb0f6cbc0ed5 7 #include "xbee.hpp"
mariob 15:fb0f6cbc0ed5 8
mariob 15:fb0f6cbc0ed5 9 #include <sstream>
mariob 15:fb0f6cbc0ed5 10
mariob 15:fb0f6cbc0ed5 11 void XBeeModule::readResponse (char* msg)
mariob 15:fb0f6cbc0ed5 12 {
mariob 15:fb0f6cbc0ed5 13 char c = 0;
mariob 15:fb0f6cbc0ed5 14 int i = 0;
mariob 24:80345e511574 15
mariob 24:80345e511574 16 // read until it sends \r
mariob 24:80345e511574 17 while (c != '\r') {
mariob 20:36931ee9af85 18 if (serial_xbee.readable()) {
mariob 20:36931ee9af85 19 c = serial_xbee.getc();
mariob 15:fb0f6cbc0ed5 20 msg[i++] = c;
mariob 15:fb0f6cbc0ed5 21 }
mariob 20:36931ee9af85 22 }
mariob 15:fb0f6cbc0ed5 23 }
mariob 15:fb0f6cbc0ed5 24
mariob 15:fb0f6cbc0ed5 25 bool XBeeModule::executeWithOk (const char* cmd)
mariob 15:fb0f6cbc0ed5 26 {
mariob 15:fb0f6cbc0ed5 27 char msg[5];
mariob 24:80345e511574 28
mariob 24:80345e511574 29 // send command
mariob 20:36931ee9af85 30 serial_xbee.printf("%s", cmd);
mariob 24:80345e511574 31 // read response
mariob 15:fb0f6cbc0ed5 32 readResponse(msg);
mariob 24:80345e511574 33 // check response
mariob 24:80345e511574 34 if (strncmp(msg, "OK\r", 3) != 0)
mariob 15:fb0f6cbc0ed5 35 return false;
mariob 24:80345e511574 36
mariob 15:fb0f6cbc0ed5 37 return true;
mariob 15:fb0f6cbc0ed5 38 }
mariob 15:fb0f6cbc0ed5 39
mariob 15:fb0f6cbc0ed5 40 void XBeeModule::executeWithRes (const char* cmd, char* res)
mariob 15:fb0f6cbc0ed5 41 {
mariob 24:80345e511574 42 // send command
mariob 20:36931ee9af85 43 serial_xbee.printf("%s", cmd);
mariob 24:80345e511574 44 // read response
mariob 15:fb0f6cbc0ed5 45 readResponse(res);
mariob 15:fb0f6cbc0ed5 46 }
mariob 15:fb0f6cbc0ed5 47
mariob 20:36931ee9af85 48 bool XBeeModule::initSequence()
mariob 20:36931ee9af85 49 {
mariob 20:36931ee9af85 50 // wait 1 second before starting
mariob 20:36931ee9af85 51 ThisThread::sleep_for(1000);
mariob 20:36931ee9af85 52 // send start command
mariob 20:36931ee9af85 53 if (!executeWithOk("+++"))
mariob 20:36931ee9af85 54 return false;
mariob 20:36931ee9af85 55 // wait 1 more second after start command
mariob 20:36931ee9af85 56 ThisThread::sleep_for(1000);
mariob 20:36931ee9af85 57
mariob 20:36931ee9af85 58 return true;
mariob 20:36931ee9af85 59 }
mariob 15:fb0f6cbc0ed5 60
mariob 24:80345e511574 61 XBeeModule::XBeeModule (PinName tx, PinName rx, int panID, int channel)
mariob 24:80345e511574 62 : serial_xbee(tx, rx, 9600) {
mariob 24:80345e511574 63 status = _getLocalAddr() && _setChannel(channel) && _setPanID(panID);
mariob 15:fb0f6cbc0ed5 64 }
mariob 15:fb0f6cbc0ed5 65
mariob 20:36931ee9af85 66 bool XBeeModule::getDstAddress (XBeeAddress &addr)
mariob 15:fb0f6cbc0ed5 67 {
mariob 15:fb0f6cbc0ed5 68 char tmp[10];
mariob 15:fb0f6cbc0ed5 69 std::stringstream s1, s2;
mariob 20:36931ee9af85 70 uint32_t high, low;
mariob 20:36931ee9af85 71
mariob 20:36931ee9af85 72 // start communication with transceiver
mariob 20:36931ee9af85 73 if (!initSequence())
mariob 20:36931ee9af85 74 return false;
mariob 20:36931ee9af85 75 // read high address
mariob 15:fb0f6cbc0ed5 76 executeWithRes("ATDH \r", tmp);
mariob 15:fb0f6cbc0ed5 77 s1<<std::hex<<tmp;
mariob 15:fb0f6cbc0ed5 78 s1>>high;
mariob 20:36931ee9af85 79 // read low address
mariob 15:fb0f6cbc0ed5 80 executeWithRes("ATDL \r", tmp);
mariob 15:fb0f6cbc0ed5 81 s2<<std::hex<<tmp;
mariob 15:fb0f6cbc0ed5 82 s2>>low;
mariob 20:36931ee9af85 83 // terminate
mariob 15:fb0f6cbc0ed5 84 if (!executeWithOk("ATCN \r"))
mariob 20:36931ee9af85 85 return false;
mariob 20:36931ee9af85 86 addr.setAddress(low, high);
mariob 15:fb0f6cbc0ed5 87
mariob 20:36931ee9af85 88 return true;
mariob 15:fb0f6cbc0ed5 89 }
mariob 15:fb0f6cbc0ed5 90
mariob 15:fb0f6cbc0ed5 91
mariob 15:fb0f6cbc0ed5 92 bool XBeeModule::setDstAddress (XBeeAddress addr)
mariob 15:fb0f6cbc0ed5 93 {
mariob 15:fb0f6cbc0ed5 94 char s[10];
mariob 15:fb0f6cbc0ed5 95 string low, high;
mariob 20:36931ee9af85 96
mariob 20:36931ee9af85 97 // start communication with transceiver
mariob 20:36931ee9af85 98 if (!initSequence())
mariob 15:fb0f6cbc0ed5 99 return false;
mariob 20:36931ee9af85 100 // send high address
mariob 20:36931ee9af85 101 sprintf(s, "ATDH%X \r", addr.getHighAddr());
mariob 15:fb0f6cbc0ed5 102 if (!executeWithOk(s))
mariob 15:fb0f6cbc0ed5 103 return false;
mariob 20:36931ee9af85 104 // send low address
mariob 20:36931ee9af85 105 sprintf(s, "ATDL%X \r", addr.getLowAddr());
mariob 15:fb0f6cbc0ed5 106 if (!executeWithOk(s))
mariob 15:fb0f6cbc0ed5 107 return false;
mariob 20:36931ee9af85 108 // terminate
mariob 15:fb0f6cbc0ed5 109 if (!executeWithOk("ATCN \r"))
mariob 15:fb0f6cbc0ed5 110 return false;
mariob 24:80345e511574 111 ThisThread::sleep_for(1000);
mariob 15:fb0f6cbc0ed5 112
mariob 15:fb0f6cbc0ed5 113 return true;
mariob 15:fb0f6cbc0ed5 114 }
mariob 15:fb0f6cbc0ed5 115
mariob 15:fb0f6cbc0ed5 116 bool XBeeModule::_getLocalAddr ()
mariob 15:fb0f6cbc0ed5 117 {
mariob 15:fb0f6cbc0ed5 118 char tmp[10];
mariob 20:36931ee9af85 119 uint32_t high, low;
mariob 15:fb0f6cbc0ed5 120 std::stringstream s1, s2;
mariob 15:fb0f6cbc0ed5 121
mariob 20:36931ee9af85 122 // start communication with transceiver
mariob 20:36931ee9af85 123 if (!initSequence())
mariob 15:fb0f6cbc0ed5 124 return false;
mariob 20:36931ee9af85 125 // read high address
mariob 15:fb0f6cbc0ed5 126 executeWithRes("ATSH \r", tmp);
mariob 15:fb0f6cbc0ed5 127 s1<<std::hex<<tmp;
mariob 15:fb0f6cbc0ed5 128 s1>>high;
mariob 20:36931ee9af85 129 // read low address
mariob 15:fb0f6cbc0ed5 130 executeWithRes("ATSL \r", tmp);
mariob 15:fb0f6cbc0ed5 131 s2<<std::hex<<tmp;
mariob 15:fb0f6cbc0ed5 132 s2>>low;
mariob 20:36931ee9af85 133 // terminate
mariob 15:fb0f6cbc0ed5 134 if (!executeWithOk("ATCN \r"))
mariob 15:fb0f6cbc0ed5 135 return false;
mariob 20:36931ee9af85 136 // save address
mariob 15:fb0f6cbc0ed5 137 local = XBeeAddress(low, high);
mariob 20:36931ee9af85 138
mariob 15:fb0f6cbc0ed5 139 return true;
mariob 15:fb0f6cbc0ed5 140 }
mariob 15:fb0f6cbc0ed5 141
mariob 15:fb0f6cbc0ed5 142
mariob 15:fb0f6cbc0ed5 143 bool XBeeModule::_setChannel (int channel)
mariob 15:fb0f6cbc0ed5 144 {
mariob 15:fb0f6cbc0ed5 145 char s[10];
mariob 20:36931ee9af85 146
mariob 20:36931ee9af85 147 // start communication with transceiver
mariob 20:36931ee9af85 148 if (!initSequence())
mariob 15:fb0f6cbc0ed5 149 return false;
mariob 15:fb0f6cbc0ed5 150 sprintf(s, "ATCH%d \r", channel);
mariob 15:fb0f6cbc0ed5 151 if (!executeWithOk(s))
mariob 15:fb0f6cbc0ed5 152 return false;
mariob 15:fb0f6cbc0ed5 153 if (!executeWithOk("ATCN \r"))
mariob 15:fb0f6cbc0ed5 154 return false;
mariob 24:80345e511574 155
mariob 15:fb0f6cbc0ed5 156 return true;
mariob 15:fb0f6cbc0ed5 157 }
mariob 15:fb0f6cbc0ed5 158
mariob 15:fb0f6cbc0ed5 159 int XBeeModule::getChannel ()
mariob 15:fb0f6cbc0ed5 160 {
mariob 15:fb0f6cbc0ed5 161 int channel;
mariob 15:fb0f6cbc0ed5 162 char s[10];
mariob 20:36931ee9af85 163
mariob 20:36931ee9af85 164 // start communication with transceiver
mariob 20:36931ee9af85 165 if (!initSequence())
mariob 20:36931ee9af85 166 return false;
mariob 15:fb0f6cbc0ed5 167 executeWithRes("ATCH \r", s);
mariob 15:fb0f6cbc0ed5 168 channel = atoi(s);
mariob 15:fb0f6cbc0ed5 169 if (!executeWithOk("ATCN \r"))
mariob 15:fb0f6cbc0ed5 170 return -1;
mariob 20:36931ee9af85 171 ThisThread::sleep_for(1000);
mariob 24:80345e511574 172
mariob 15:fb0f6cbc0ed5 173 return channel;
mariob 15:fb0f6cbc0ed5 174 }
mariob 15:fb0f6cbc0ed5 175
mariob 15:fb0f6cbc0ed5 176
mariob 15:fb0f6cbc0ed5 177 bool XBeeModule::_setPanID (int panID)
mariob 15:fb0f6cbc0ed5 178 {
mariob 15:fb0f6cbc0ed5 179 char s[10];
mariob 20:36931ee9af85 180
mariob 20:36931ee9af85 181 // start communication with transceiver
mariob 20:36931ee9af85 182 if (!initSequence())
mariob 15:fb0f6cbc0ed5 183 return false;
mariob 15:fb0f6cbc0ed5 184 sprintf(s, "ATID%d \r", panID);
mariob 15:fb0f6cbc0ed5 185 if (!executeWithOk(s))
mariob 15:fb0f6cbc0ed5 186 return false;
mariob 15:fb0f6cbc0ed5 187 if (!executeWithOk("ATCN \r"))
mariob 15:fb0f6cbc0ed5 188 return false;
mariob 20:36931ee9af85 189
mariob 15:fb0f6cbc0ed5 190 return true;
mariob 15:fb0f6cbc0ed5 191 }
mariob 15:fb0f6cbc0ed5 192
mariob 15:fb0f6cbc0ed5 193 int XBeeModule::getPanID ()
mariob 15:fb0f6cbc0ed5 194 {
mariob 15:fb0f6cbc0ed5 195 int id;
mariob 15:fb0f6cbc0ed5 196 char s[10];
mariob 20:36931ee9af85 197
mariob 20:36931ee9af85 198 // start communication with transceiver
mariob 20:36931ee9af85 199 if (!initSequence())
mariob 20:36931ee9af85 200 return false;
mariob 15:fb0f6cbc0ed5 201 executeWithRes("ATID \r", s);
mariob 15:fb0f6cbc0ed5 202 id = atoi(s);
mariob 15:fb0f6cbc0ed5 203 if (!executeWithOk("ATCN \r"))
mariob 15:fb0f6cbc0ed5 204 return -1;
mariob 20:36931ee9af85 205
mariob 15:fb0f6cbc0ed5 206 return id;
mariob 15:fb0f6cbc0ed5 207 }
mariob 15:fb0f6cbc0ed5 208
mariob 15:fb0f6cbc0ed5 209
mariob 15:fb0f6cbc0ed5 210 int XBeeModule::read (char* msg)
mariob 15:fb0f6cbc0ed5 211 {
mariob 15:fb0f6cbc0ed5 212 int i = 0;
mariob 24:80345e511574 213
mariob 20:36931ee9af85 214 while (serial_xbee.readable())
mariob 20:36931ee9af85 215 msg[i++] = serial_xbee.getc();
mariob 24:80345e511574 216
mariob 15:fb0f6cbc0ed5 217 return i;
mariob 15:fb0f6cbc0ed5 218 }
mariob 15:fb0f6cbc0ed5 219
mariob 15:fb0f6cbc0ed5 220 void XBeeModule::write (const char* msg, int n)
mariob 15:fb0f6cbc0ed5 221 {
mariob 15:fb0f6cbc0ed5 222 for (int i=0; i<n; i++) {
mariob 20:36931ee9af85 223 while(!serial_xbee.writeable());
mariob 20:36931ee9af85 224 serial_xbee.putc(msg[i]);
mariob 15:fb0f6cbc0ed5 225 }
mariob 15:fb0f6cbc0ed5 226 }