I have developed a lot of IoT prototypes so far, then I have observed that most of my IoT projects require a communication protocol for wired sensor networking, satisfiying the requirements below:
- low power consumption and lower voltage (5V or 3.3V)
- bus topology (daisy-chain) rather than hub and spoke (star)
- two-wire or one-wire
- cheap (<$10 per node on average) and open
- small software footprint
There are a lot of such technologies for in-vehicle network (CAN/LIN), buidling management (BACnet) or factory automation (PROFINET), but none of them satisfies all the requirements above.
This is a project to develop a networking protocol and building blocks for local wired sensor network.
The network is composed of multiple nodes(blocks) and one scheduler.
-----+---------------------+---------------------------+-------- I2C bus | | | +------|-----+ +------|-----+ +------|-----+ | [node] | | [node] | | [node] | | | | | | | | | | ( ) | [sensor] | | [sensor] | | +------------[IoT GW(*1)]---( Cloud ) +------------+ +------------+ . . . +------------+ ( ) block block scheduler (slave) (slave) (master) (*1) I use Node-RED (on RasPi or PC) and Android as IoT gateways. Note: I am going to support CAN bus as well.
All the blocks developed in this project support Plug&Play protocol that runs on UART.
USB hub +---+ [block A]--UART/USB--| | [block B]--UART/USB--| |--USB--[IoT GW] [block C]--UART/USB--| | +---+ hub&spoke topology It also runs on I2C.
<- - - - - I2C backplane - - - - -> [block A]---[block B]---[block C]---[Scheduler]--UART/USB--[IoT GW] bus topology (daisy-chain) I use PIC16F1829/PIC16F1825 that satisfies the requirements of this project.
Clock speed:
- 4MHz typical
- 32MHz (8MHz w/ PLL) for high sampling rate
The base board below is a common hardware part of node:
One I2C master and three I2C slaves are connected with each other via backplane bus on the back of base board
A similar construct to the above, but all the boards are connected with each other in a daisy-chain manner:
I use Microchip's MPLAB-X IDE. I also use MPLAB Code Configurator (MCC) to automatically generate code for EUSART, I2C(master/slave), ADC, Timer etc. I modify the generated I2C slave code to support Plug&Play protocol.
Plug&play protocol specification
Some blocks operates in pubsub mode -- how it works.
All nodes need to import this protocol library:
I2C slaves also require I2C-slave-specific code -- I modified MCC-generated I2C slave code (i2c1.c) to support the protocol on I2C slave side. See this modifed code: i2c1.c.
The following is an example of main routine:
void main(void) { // Protocol initialization PROTOCOL_Initialize(DEVICE_ID, NULL, NULL, NULL, inv_handler, 250); // avoid using SYSTEM_Initialize() automatically generated by MCC, // because I2C1_Initialize() must be last in the initialization order PIN_MANAGER_Initialize(); OSCILLATOR_Initialize(); WDT_Initialize(); ADC_Initialize(); TMR0_Initialize(); EUSART_Initialize(); I2C1_Initialize(); // Enable interrupt INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); // Infinite loop PROTOCOL_Loop(); } In this project, PIC16F1829 MCU is used for general-purpose blocks such as a scheduler or LCD controller.
- 5V: Scheduler (BACKPLANE-MASTER)
- 5V: Character LCD actuator block (AQM1602XA-RN-GBW)
- 5V: Acceleration sensor block (KXR94-2050)
- 5V: Speed sensor block (A1324LUA-T)
- 5V: Temperature and humidity sensor block (HDC1000)
- 5V: Position detector block
In this project, PIC16F1825 MCU is used for purpose-specific blocks such as a position detector having multiple analog ports.
A typical usage of the position detector is to detect a position of a moving object such as a doll on a catwalk miniature (not a belt conveyer).
Example of its usage
#WHO $:WHO:MULTI_A1324LUA_T #MAP $:MAP:21,22 #RSC $:RSC:0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0 #POS:0 #WSC:21 #POS:1 #WSC:22 #RSC $:RSC:21,22,0,0|0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0 #I2C:21 #WHO $:WHO:21 #SET:15 #I2C:22 #SET:9 #I2C:1 #STA %21:UINT8_T:0,1,0,0 %21:UINT8_T:0,0,0,0 %21:UINT8_T:0,0,0,1 %21:UINT8_T:0,0,0,0 %21:UINT8_T:0,0,0,1 %21:UINT8_T:0,0,0,0 %21:UINT8_T:0,1,0,0 %21:UINT8_T:0,0,0,0 %21:UINT8_T:1,0,0,0 %21:UINT8_T:0,0,0,0 %21:UINT8_T:0,1,0,0 %21:UINT8_T:0,0,0,0 %21:UINT8_T:0,0,0,1 %21:UINT8_T:0,0,0,0 %21:UINT8_T:0,0,1,0 %21:UINT8_T:0,0,0,0 %22:UINT8_T:0,0,0,1 %22:UINT8_T:0,0,0,0 %22:UINT8_T:1,0,0,0 %22:UINT8_T:0,0,0,0 Write I2C slave address on the blocks. For exmaple, if the address is 16 in decimal, then:
#WDA:16 #RDA $:RDA:16 #WHO $:WHO:BACKPLANE-MASTER #SCN #MAP $:MAP:16,17,19 $:RSC:0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0|17,0,0,0|0,0,0,0 #POS:12 #WSC:19 #RSC $:RSC:0,0,0,0|0,0,0,0|0,0,0,0|19,0,0,0|0,0,0,0|17,0,0,0|0,0,0,0 #STA %17:UINT16_T:0 %19:FLOAT:-0.07,-0.08,0.94 %19:FLOAT:-0.05,-0.06,0.94 %19:FLOAT:-0.07,-0.06,0.94 %19:FLOAT:-0.06,-0.07,0.93 %19:FLOAT:-0.07,-0.08,0.94 %19:FLOAT:-0.05,-0.09,0.94 %19:FLOAT:-0.06,-0.09,0.94 %19:FLOAT:-0.05,-0.08,0.93 %19:FLOAT:-0.07,-0.08,0.93 %19:FLOAT:-0.06,-0.07,0.94 %19:FLOAT:-0.07,-0.07,0.94 %19:FLOAT:-0.06,-0.07,0.93 %19:FLOAT:-0.07,-0.08,0.93 : #I2C:16 $:WHO:16 #CLR #LED:ON #LED:OFF #STR:Hello World! #NWL #STR:Guten Tag! #I2C:1 : #STP *:STP:ACK Use the CLI to control the scheduler or stream sensor data to the cloud.
- Python: pySerial
- Node.js: serialport
- Java/Android: D2XX driver
In some projects, I used telephone line (6P4C) with RJ11 moduler plug/jack, as I2C bus. I used this tool to make wires among nodes: Crimper for RJ11. Telephone line makes physical wirling very easy.
6P4C telephone line is suitable for I2C with power line: SDA, SCL, 5V, GND.





