Sunday, November 15, 2015

Wireless Communication on Microchip Sub-GHz

http://yangweinian.blogspot.co.id/2015/11/wireless-communication-on-microchip-sub.html

Sub-GHz refers to operating frequency close to but not exceeding 1 GHz. For example commonly found 433 MHz, 868 MHz and 915 MHz which are listed as legal Sub-GHz ISM frequency band that allows Industrial uses, Scientific research and Medical operation.
2.4 GHz and Sub-GHz Applications


1. Why Sub-GHz?
Considered as lower division in UHF (Ultra High Frequency) band which span across 300 MHz to 3 GHz, Sub-GHz has considerably long wavelength, approximately 1 meter for a 300 MHz radio wave. This leads to further wave traveling capability therefore transmission can occur from one node to another over amazing distance. For instance, 900 MHz wave can travel 2.6 times further than radio wave of 2.4 GHz under similar transmission efficiency.
In contrast to 2.4 GHz application such as Wi-Fi or Bluetooth, Sub-GHz possesses much lower power consumption, further signal coverage and more susceptible to interference (communication traffic on Sub-GHz is not as crowded as 2.4 GHz). Power consumption is directly proportional to frequency, that is, higher frequency needs more power to run because the crystal vibrate much more attempts in certain period of time.
Sub-GHz is commonly found in proprietary wireless application such as car alarm and home automation which require more secure communication. However it also comes with several downsides including requirement of proprietary remote control and larger antenna size (this can be optimized with printed patch antenna design).
Key Parameters


2. Communication Protocol
Unlike Wi-Fi whose communication protocol has been standardized worldwide, abundant vendors provide Sub-GHz application and each one of them have different communication protocol, this is why Sub-GHz application sometimes is referred to "proprietary application" where there is no dedicated protocol worldwide. Among other vendors, Microchip provides simple communication protocol for its proprietary Sub-GHz product line named MiWi, a subsidiary of IEEE 802.15.4 standard has made handshake much simpler than its original version. For instance, IEEE 802.15.4 defined five compulsory steps in handshake process between Sub-GHz devices, MiWi P2P protocol simplified it down to only two steps.
IEEE 802.15.4 Standard : Handshake Process
MiWi Simplified Handshake Process
Although simple Sub-GHz application usually doesn't require advance verification such as car alarm, handshake process ensures devices clearly identified each other hence allowing communication in more secure manner, which will be useful in advance network application. In MiWi P2P protocol, this network is called PAN (Personal Area Network) where several devices  may form a star topology network and communicate effectively through Sub-GHz.


3. Hardware
I found MRF89XAM8A Sub-GHz module from Microchip as one of most appealing options mainly due to its competitive price, aesthetic printed patch antenna design which minimizes module size and robust library support for proprietary MiWi protocol. As specified in its datasheet, this transceiver module is compatible with Microchip's micro-controller unit families (PIC16, PIC18, PIC24, dsPIC33 and PIC32) through 4-wire SPI communication. Unlike in "How to Make Simple Web-Server with Tiva C and CC3000", all modules here are not on development board anymore, therefore a programming device is required to burn program code into target MCU.
There are total 3 required items here, all supplied by Microchip :
- Host MCU : Microchip dsPIC33FJ64MC802
- Programming Device : Microchip Microstick
- Sub-GHz Module : Microchip MRF89XAM8A 

Microchip dsPIC33FJ64MC802 (package SPDIP) costs US$5, can be purchased HERE.
dsPIC33FJ64MC802 SPDIP IC
Microchip Microstick DM330013 costs US$34.95, can be purchased HERE.
Microstick DM330013
Microchip MRF89XAM8A costs US$7.95, can be purchased HERE.
MRF89XAM8A 898MHz Module


4. Programming Environment
I used MPLAB X as programming environment to write code in C++ and burn it into dsPIC33F IC with help of Microstick. I also used MLA (Microchip Libraries for Application) to write more efficient code and achieve more features associated with its MRF89XAM8A product.

Start to write program code by download and install MPLAB X HERE.

Original MPLAB X installation package doesn't include code compiler, in the case to successfully program dsPIC33F we need XC16 in compiling the code to language 16-bits IC can understand. Download and install XC16 HERE.

Also, download and install MLA (Microchip Libraries for Application) HERE.

After all installations are completed, make sure to configure MPLAB X to run on XC16 compiler, Microstick programming hardware and link necessary library files to project. All of these configuration can be made in "Project Properties" tab.
Configuring Compiler and Programming Hardware
Include Libraries
To successfully write program for Sub-GHz application, two compulsory library folders are "Transceiver" and "WirelessProtocols" where first library defines how MCU should communicate to MRF89XAM8A through SPI while the latter defines communication protocol between transceivers over Sub-GHz. Both of them are equally important to create harmonized and successful Sub-GHz communication. Once all of above are prepared, all left is writing and designing a program to suit any application. Unlike creating web-server in TivaC+CC3000 Project where only one device has to be programmed and the rest can be credited to creator of smartphone, Sub-GHz communication requires at least two proprietary devices to communicate successfully to each other.


5. Application Example
Simple network application consists of only two types of device, one server and one/several clients. In Microchip MiWi protocol, server is called PAN Coordinator where it has to initiate a communication platform and wait for client to join its network, much similar to a Wi-Fi router. Thanks to MiWi library, we only need to write original programming code for specific application in "main.c", configurations such as protocol or hardware initialization are provided in files such as "hardwareprofile.c", "hardwareprofile.h", and "configapp.h". Although small tweak needs to be done to fulfill specific needs, it's relatively simple.

This example shows a simple Sub-GHz communication where server and client are connected over MiWi P2P protocol. Base on user's input, client is able to transmit one byte of data to server. Server will then toggle its output, such as LED base on the byte it receives. In basic application, one PAN coordinator allows up to 9 clients connected to it. Every device in MiWi protocol is assigned by unique 8-bits Node ID, this address is essential once the network grows bigger into more than two devices.

Below code window shows "hardwareprofile.c" for PAN coordinator, mainly about setting up hardware. Microchip MRF89XAM8A communicate to any host IC with 4-wire SPI, this chunk of code mainly defines pin configuration for peripheral feature and input/output.
#include "SystemProfile.h"
#include "Compiler.h"
#include "WirelessProtocols/Console.h"
#include "WirelessProtocols/LCDBlocking.h"
#include "TimeDelay.h"
#include "HardwareProfile.h"

    _FOSCSEL(FNOSC_PRI);                              //primary osc
    _FOSC(OSCIOFNC_ON & POSCMD_XT)                    // XT Osc
    _FWDT(FWDTEN_OFF & WDTPOST_PS2)                   // Disable Watchdog timer

void BoardInit(void)
{
    OSCCONbits.Control = 0x46;   //Unlocking the register writing restriction on RP
    OSCCONbits.Control = 0x57;
    OSCCONbits.IOLOCK = 0;       //Clear the lock bit to allow changes made

    RPINR20bits.SDI1R = 3;      //Assign SPI1 data input to RP3
    RPINR1bits.INT2R = 1;       //Assign Interrupt2 to RP1
    RPOR6bits.RP12R = 7;        //Assign SPI1 data output to RP12
    RPOR5bits.RP11R = 8;        //Assign SPI1 clock output to RP11

    AD1PCFGL = 0x3F;

    // set I/O ports
    LED_R_TRIS = 0;
    LED_G_TRIS = 0;
    OUTPUT_A_TRIS = 0;
    OUTPUT_B_TRIS = 0;
 
    SDI_TRIS = 1;
    SDO_TRIS = 0;
    SCK_TRIS = 0;
    SPI_SDO = 0;
    SPI_SCK = 0;

    Data_nCS_TRIS = 0;
    Config_nCS_TRIS = 0;
    Data_nCS = 1;
    Config_nCS = 1;
    IRQ1_INT_TRIS = 1;

    SPI1CON1 = 0b0000000100111110;
    SPI1STAT = 0x8000;
    INTCON2bits.INT2EP = 0;
    IPC7bits.INT2IP2 = 1;
    IPC7bits.INT2IP1 = 0;
    IPC7bits.INT2IP0 = 0;

    PHY_IRQ1_En = 1;
    PHY_IRQ1 = 0;
    PHY_RESETn_TRIS = 0;
}

Here is corresponding "main.c" for simple PAN coordinator.
#include "ConfigApp.h"
#include "WirelessProtocols/MCHP_API.h"
#include "WirelessProtocols/Console.h"
#include "HardwareProfile.h"
#include "WirelessProtocols/MSPI.h"

#define ServerID  0x01
#define ClientID  0x02

BYTE AdditionalNodeID[ADDITIONAL_NODE_ID_SIZE] = {ServerID};
BYTE myChannel = 24;
BYTE data;
BYTE client_available;
BOOL commandavailable;

int main(void)
{
    BoardInit();      
    
    LED_R = 0;
    LED_G = 0;
    OUTPUT_A = 0;
    OUTPUT_B = 0;

    MiApp_ProtocolInit(FALSE);
    MiApp_SetChannel(myChannel);
    MiApp_ConnectionMode(ENABLE_ALL_CONN);
    
    if (MiApp_StartConnection(START_CONN_DIRECT, 10, 0) == TRUE)
        LED_G = 1;

    while(1)
    {
        if(ConnectionTable[0].status.bits.isValid && ConnectionTable[0].PeerInfo[0] == ClientID)
        {
             client_available = 1;
             break;
         }
         else
             client_available = 0;
                
        LED_R = client_available;
        if( MiApp_MessageAvailable() )
        {
            for(i = 0; i < rxMessage.PayloadSize; i++)
                data = rxMessage.Payload[i];
            MiApp_DiscardMessage();
            commandavailable = TRUE;
        }
        if(commandavailable == TRUE)
        {
            if(data == 'A')
                OUTPUT_A ^= 1;
            else if(data == 'B')
                OUTPUT_B ^= 1;
            commandavailable = FALSE;
        }
    }
}

Personal Area Network coordinator is responsible of initiating a network which runs on Sub-GHz wave and wait for other device to join/connect. In this case, those connecting devices are called network clients. It searches for any Sub-GHz network within its vicinity by broadcasting a beacon request. Here is "hardwareprofile.c" for network client. It includes two push buttons for user input and a 7-segment LED display as simple user interface.
#include "SystemProfile.h"
#include "Compiler.h"
#include "WirelessProtocols/Console.h"
#include "WirelessProtocols/LCDBlocking.h"
#include "TimeDelay.h"
#include "HardwareProfile.h"

    _FOSCSEL(FNOSC_PRI);                                    //primary osc
    _FOSC(OSCIOFNC_OFF & POSCMD_XT)                         // XT Osc
    _FWDT(FWDTEN_OFF & WDTPOST_PS2)                         // Disable Watchdog timer

#define DEBOUNCE_TIME 0x00003FFF

BOOL PUSH_BUTTON_pressed;
MIWI_TICK PUSH_BUTTON_press_time;

void BoardInit(void)
{
    OSCCONbits.Control = 0x46;
    OSCCONbits.Control = 0x57;
    OSCCONbits.IOLOCK = 0;

    RPINR20bits.SDI1R = 3;
    RPINR1bits.INT2R = 1;
    RPOR6bits.RP12R = 7;
    RPOR5bits.RP11R = 8;
    AD1PCFGL = 0x3F;

        Button_Change_TRIS = 1;
        Button_Send_TRIS = 1;
        LED_R_TRIS = 0;
        LED_G_TRIS = 0;
        Segment_A_TRIS = 0;
        Segment_B_TRIS = 0;
        Segment_C_TRIS = 0;
        Segment_D_TRIS = 0;
        Segment_E_TRIS = 0;
        Segment_F_TRIS = 0;
        Segment_G_TRIS = 0;
        Segment_H_TRIS = 0;
        Output_AC_TRIS = 0;
        
        SDI_TRIS = 1;
        SDO_TRIS = 0;
        SCK_TRIS = 0;
        SPI_SDO = 0;        
        SPI_SCK = 0;             
 
            Data_nCS_TRIS = 0;
            Config_nCS_TRIS = 0;
            Data_nCS = 1;
            Config_nCS = 1;
            IRQ1_INT_TRIS = 1;

            SPI1CON1 = 0b0000000100111110;
            SPI1STAT = 0x8000; 
            INTCON2bits.INT2EP = 0;
            IPC7bits.INT2IP2 = 1;
            IPC7bits.INT2IP1 = 0;
            IPC7bits.INT2IP0 = 0;

            PHY_IRQ1_En = 1;
            PHY_IRQ1 = 0;
            PHY_RESETn_TRIS = 0;
}

BYTE ButtonPressed(void)
{
    MIWI_TICK tickDifference;
        
    if(Button_Change == 1)
    {
        if(PUSH_BUTTON_pressed == FALSE)
        {
            PUSH_BUTTON_pressed = TRUE;
            PUSH_BUTTON_press_time = MiWi_TickGet();
            return 1;
        }
    }
    else if(Button_Connect == 1)
    {
        if(PUSH_BUTTON_pressed == FALSE)
        {
            PUSH_BUTTON_pressed = TRUE;
            PUSH_BUTTON_press_time = MiWi_TickGet();
            return 2;
        }
    } 
    else
    {
        MIWI_TICK t = MiWi_TickGet();
        tickDifference.Val = MiWi_TickGetDiff(t,PUSH_BUTTON_press_time);
        if(tickDifference.Val > DEBOUNCE_TIME)
        {
            PUSH_BUTTON_pressed = FALSE;
            return 0;
     }
}

Here is corresponding "main.c" for simple network client.
#include "ConfigApp.h"
#include "WirelessProtocols/MCHP_API.h"
#include "WirelessProtocols/Console.h"
#include "HardwareProfile.h"

#define ServerID  0x01
#define ClientID  0x02

BYTE AdditionalNodeID[ADDITIONAL_NODE_ID_SIZE] = {ClientID};
BYTE myChannel = 24;
BYTE data_byte[2] = {'A', 'B'}
BYTE display[2] = {0x60,0xDA}
BYTE SERVER;
BYTE j;

int main(void)
{
    BYTE i;
    BYTE command;
    BYTE x = 2;

    BoardInit();

    LED_R = 0;
    LED_G = 0;

    MiApp_ProtocolInit(FALSE);
    MiApp_SetChannel(myChannel);
    MiApp_ConnectionMode(ENABLE_ALL_CONN);

    i = MiApp_EstablishConnection(0xFF, CONN_MODE_DIRECT);
    if( i != 0xFF )
        LED_G = 1;

    for(j = 0; j < 9; j++)
    {
        if(ConnectionTable[j].status.bits.isValid && ConnectionTable[j].PeerInfo[0] == serverID)
        {
            SERVER = j;
            break;
         }
    }

    while(1)
    {
        command = ButtonPressed();
        switch(command)
        {
            case 1 :
            {
                if(x < 2)
                    x = x + 1;
                else
                    x = 0;
                Segment_A = (display[x]>>7) & 0x01;
                Segment_B = (display[x]>>6) & 0x01;
                Segment_C = (display[x]>>5) & 0x01;
                Segment_D = (display[x]>>4) & 0x01;
                Segment_E = (display[x]>>3) & 0x01;
                Segment_F = (display[x]>>2) & 0x01;
                Segment_G = (display[x]>>1) & 0x01;
                Segment_H = display[x] & 0x01;
            }break;
            case 2 :
            {
                MiApp_FlushTx();
                MiApp_WriteData(data_byte[x]);
                LED_R = 0;
                MiApp_UnicastConnection(SERVER,FALSE);
                DelayMs(200);
                LED_R = 1;
            }break;
            default : break;
        }
    }
}

Back in 2014, I combined both TivaC+CC3000 and MRF89XA+dsPIC33F into a single light switch system which capable of running on Wi-Fi and Sub-GHz. I also did minor market research on topic if respondents find this product will be useful to their life. It was real fun to see this integration turned out pretty well. It also had me graduated from school of engineering with, well, pretty good score.
One of my FYP Schematic
One of my FYP PCB Design
Wi-Fi + Sub-GHz Wireless Light Switch

I hope this post is useful and informative, especially to those who want to start (or maybe has started) their Sub-GHz project. Microchip's MRF89XA turns out to be the best Sub-GHz module in its class, supported by robust resources and small in size. The application is not limited to simple light switch feature, but way more than that such as complete home automation and interactive messaging.


SEE ALSO : How To Make Simple Web Server with Tiva C and CC3000

SEE ALSO : My Traveling Adventure