Skip to content

Latest commit

 

History

History
279 lines (209 loc) · 8.11 KB

README.md

File metadata and controls

279 lines (209 loc) · 8.11 KB

Local wired sensor network

sensor_networ

Background and motivation

Problems

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.

Network architecture

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.

Interfaces among blocks

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)

8bit MCU as core of node

I use PIC16F1829/PIC16F1825 that satisfies the requirements of this project.

Clock speed:

  • 4MHz typical
  • 32MHz (8MHz w/ PLL) for high sampling rate

Node prototype

The base board below is a common hardware part of node:

prototype3

pico2

pico1

Networking examples

One I2C master and three I2C slaves are connected with each other via backplane bus on the back of base board

compact2

A similar construct to the above, but all the boards are connected with each other in a daisy-chain manner:

daisy_chain

Implementation

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

Plug&play protocol specification

Some blocks operates in pubsub mode -- how it works.

Implementation: common part among all nodes

All nodes need to import this protocol library:

Implementation: I2C-slave-specific part

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.

Coding

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();
}

Blocks

PIC16F1829

In this project, PIC16F1829 MCU is used for general-purpose blocks such as a scheduler or LCD controller.

PIC16F1825

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).

catwalk

position_detector

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

Initial config

Write I2C slave address on the blocks. For exmaple, if the address is 16 in decimal, then:

#WDA:16
#RDA
$:RDA:16

CLI example

#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

Interface to the scheduler

Use the CLI to control the scheduler or stream sensor data to the cloud.

via VCP over ttyUSBX(Linux)/COM port(Windows)

via D2XX driver

Physical wiring among blocks

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.