====== XnorBee-Slave an XBEE Slave devices library ====== ===== Instantiate 'XnorBeeSlave' object ===== - Include the Xbee and XnorBeeSlave libraries globally. - Instantiate byte array variable. This is used as a shared memory on the XBEE network. Size of array is free to choose. - Instantiate an XBee object. - Instantiate XnorBeeSlave object, passing the previously instantiated xbee object by reference, followed by the previously instantiated byte array. #include #include "XnorBeeSlave.h" byte shared_memory[4]; XBee xbee = XBee(); XnorBeeSlave xbs(&xbee, shared_memory); // pass xbee obj by reference to xbs + shared_memory array. //Example code above creates a shared_memory byte array that is 4 bytes long. \\ Secondary an XBee object is instantiated, then the XnorBeeSlave object. \\ At initialization of the XnorBeeSlave object we pass the XBee object by reference combined with the shared_bus memory byte array. // ===== Set serial eventloop ===== Based on what serialport that is used, the correct serialEvent configuration has to be set. \\ In this example serial3 is used for the xbee device on an atmega2560, so serialEvent3() has to be un-commented. //void serialEvent0(){xbs.SerialEventProc();} //void serialEvent1(){xbs.SerialEventProc();} //void serialEvent2(){xbs.SerialEventProc();} void serialEvent3(){xbs.SerialEventProc();} ===== Setup ===== In the setup function we have to start the serial communication on the serial port where the XBee is connected to, by using the begin function. In this example Serial3 was used. \\ Secondary we have to set the serial for the xbee object using xbee.setSerial(Serial3). Serial3.begin(9600); // start serial port where xbee is connected to xbee.setSerial(Serial3); // pass this serial port to xbee object. Keep in mind that the whole shared byte array is read/write accessible for the entire XBee network! ===== Downloads: ===== Download full slaves library code + example: {{ :xnorit:public:dependencies:xnorbee:xnorbeeslave.rar |}} \\ Dependencies: install 'xbee-arduino library' by Andrew Rapp (tested with v0.6.0) using the library manager. \\ === Known bugs! === None === Fixed bugs: === ** 28/05/2020: ** \\ Line 71 in library file payload[i] --> change to: --> payload[i-startindex] \\ ** Corrected version: ** // Set payload data: byte payload[byteCount]; for(int i=startIndex; i < (startIndex+byteCount); i++) payload[i-startIndex] = _bus_memory[i]; \\ \\ \\ ====== XBEE Master devices ====== ===== Master protocol: ===== The master has to send data following the correct protocol to read/write data from a slave XnorBee device. \\ The data to send exists out of minimum 2 bytes, for a read request. More than 2 bytes defaults to a write request. ==== Read request: ==== To read data from the slave device the master has to send 2 bytes. Those 2 bytes configure the start index and amount of data we request from the slaves 'shared' byte array. * ** First byte: ** \\ Determines the start index. \\ When we want to read from the first index from the array we use '0', \\ When we want to read from the last index in an byteArray of size 4, we use '3'. * ** Second byte: ** \\ Determines the amount of bytes we want to read. \\ * **For example: ** \\ When the first byte is set to '01' and we read '02' bytes from the array. We read the values at index 1 & 2. \\ When the first byte is set to '00' and we read '03' bytes from the array. We read the values at index 0, 1 & 2. ==== Write request: ==== To write data to the slave device, the master just has to send more than 2 bytes. The first 2 bytes keep the same logic as in read mode, following bytes are written to the 'shared' byte array. * ** First byte: ** \\ Determines the start index. \\ When we want to write to the first index from the array we use '0', \\ When we want to write to the last index in an byteArray of size 4, we use '3'. * ** Second byte: ** \\ Determines the amount of bytes we want to write. \\ * **For example: ** \\ When the first byte is set to '01' and we write '02' bytes to the array. We write the values at index 1 & 2. \\ When the first byte is set to '00' and we write '03' bytes to the array. We write the values at index 0, 1 & 2. \\ ===== Requesting data: ===== ==== Manual, using XCTU: ==== {{ :xnorit:public:dependencies:xnorbee:xctu_xnorbeemaster_framegeneratorexample.png?400|}} Reading and/or writing data to the slave device can be done from the XCTU software inside the console mode. \\ Create a frame using the 'Frame Generator' tool inside XCTU. * **Protocol:** \\ Zigbee (defaults to 'all' afterwards) * **Frame type:** \\ 0x10 - Transmit Request * **64-bit dest.address:** \\ * **RF data:** \\ In the print-screen we notice a write request using '03 01 00'. \\ This writes the value '00' of length '01' to index '03'. Keep in mind that XCTU has to be set in "HEX" mode/tab to work! \\ And always use double digits !!! === Download: === XCTU software download: \\ [[https://www.digi.com/products/embedded-systems/digi-xbee/digi-xbee-tools/xctu#productsupport-utilities]] \\ \\ \\ \\ \\ \\ \\ ==== Automated, using Python3: ==== Using the custom created python XnorBee and XnorBeeMaster class makes reading or writing data to slave devices quite easy. Before you can use those classes, you need to import the correct modules: from XnorBee.XnorBee import XnorBee from XnorBee.XnorBeeMaster import XnorBeeMaster === XnorBee class === The XnorBee class contains the lower level functions using the Digi.XBee API. \\ This class can be used to: * Add the local XBEE devices serial port to the object. * Add remote devices to the device list. Returns numeric ID values. * Send data to an remote device, this in decimal or hexadecimal notation. * Receive raw data from a remote device. == Instantiate local device and remote device: == xbe = XnorBee("COM13", 9600) # Add the local devices communication port and bautrate. rZBid = xbe.SetRemoteZigbeeDevice("0013A200409A0EA8") # Set remote device MAC. Returns easy numeric ID for further usage. // Note that multiple remote devices can be set to the XnorBee class. Each remote device gets an unique ID as return value. // == Usage of SendData and ReceiveData functions/methods: == state = xbe.SendData(rZBid, "blub" , pMode="DEC") # Write strings to an remote device on the network. state = xbe.SendData(rZBid, ["\x03", "\x01"] , pMode="HEX") # Write bytes in hexadecimal format to remote device on the network. print(state) # Prints complex to use status output containing execution information. time.sleep(1) # Timing before receiving data has to be manually estimated and added. xbee_message = xbe.ReceiveData() # Receives data in an complex to use dict layout. print(xbee_message) # Prints barely readable dict layout. //Note that the returned values inside 'state' and 'xbee_message' contain rather difficult to read dictionary and object data. For easy data access combine this class with the XnorBeeMaster class. // == Read or write IO-Lines: == If you need to read or set an IOLine in/out-put, this can be done as follow. from XnorBee.XnorBee import XnorBee from digi.xbee.devices import IOMode from digi.xbee.io import IOLine # Get the basic functionality using the XnorBee class: xbe = XnorBee("COM13", 9600) rZBid = xbe.SetRemoteZigbeeDevice("0013A20041AE5856") # PIN / IOLine interactions: rZBDEV = xbe.GetRemoteZigbeeDevice(rZBid) # Get the remote device object from the xbe object using the remote devices ID. rZBDEV.set_io_configuration(IOLine.DIO10_PWM0, IOMode.DIGITAL_IN) # Configure the pin as an input. io_state = rZBDEV.get_dio_value(IOLine.DIO10_PWM0) # Read the pin state HIGH or LOW print(io_state) \\ \\ === XnorBeeMaster class === The XnorBeeMaster class contains the higher level functions for the [[xnorit:public:dependencies:xnorbee#XnorBee class|XnorBee]] class. \\ This class can be used to: * Write data to a slave device following the correct [[xnorit:public:dependencies:xnorbee#Master protocol:|Master protocol]]. * Read data from a slave device, following the correct [[xnorit:public:dependencies:xnorbee#Master protocol:|Master protocol]]. == Initialization & usage: == * Init of this class requires the XnorBee object to be passed onto the XnorBeeMaster class as a variable. * ReadRequest, used to request data from a slave device. This requires an slave ID, start-position and byte count to request. * WriteRequest, used to write data to a slave devices memory. This requires an slave ID, start-position and data. The byte count is calculated automatically. xbm = XnorBeeMaster(xbe) # Init XnorBeeMaster, pass XnorBee object to it. Required as the Master class uses functions from the XnorBee class. # Read requests: answ = xbm.ReadRequest(rZBid, 3,1) # Read 1 byte from the array at position 3. answ = xbm.ReadRequest(rZBid, 9,4) # Read 4 bytes from the array, starting from position 9. Read 9, 10, 11 and 12. answ = xbm.ReadRequest(rZBid, 0,16) # Read the whole memory array of 16 bytes long. print(answ) # Prints the whole easy to use dictionary. print(answ["data"]) # Prints the data parameter from this dictionary. Shows all requested data in an easy to use byte / int array. # Write requests: state = xbm.WriteRequest(rZBid, 3, [0]) # Write value 0 to index 3 in the slaves memory. state = xbm.WriteRequest(rZBid, 9, [40,50,60,70,80]) # Write the byte array to the slaves memory, starting at position 9. # Slaves memory at index 9 will contain 40 after execution. print(state) # Prints True or False based on how execution went. === Download: === Download full Masters library code + example: {{ :xnorit:public:dependencies:xnorbee:xnorbeemaster.rar |}} \\ dependencies: [[https://xbplib.readthedocs.io/en/latest/getting_started_with_xbee_python_library.html]] === Known bugs: === Due to delayed response from remote nodes data can be intercepted at later request to another node. This causes data to be shuffled inside the gateway/receivers array. Data should be checked for integrity using the sending-nodes mac address to prevent issues like this. ReceiveData function should be updated to hold an timeout delay in the future!