Summary

An update to the Tilt Hydrometer Simulator to allow individual advertising packets to be turned on & off using the Multi-Advertising Capability of PSoC & CYW43012

Story

After I finished the last article I was sure that I was done with the Tilt Simulator.  But, when I walked away I started thinking about what I had done, and I decided that I needed to make one more update.  Specifically I wanted to add two more commands, “enable” and “disable”.  I also realized that I had the wrong idea about the implementation of multi-adv.  I thought that you had to have all of the slots from 1 to n active at the same time.  The more I thought about it the more I realized that was wrong.  This is really cool for my situation as there are 8 different color Tilts and the are at least 8 slots.  So, I can assign each Tilt to its own slot in the controller.

This series is broken up into the following 12 articles with a few additional possible articles. 

Tilt Hydrometer (Part 1) Overview & Out-of-Box

Tilt Hydrometer (Part 2) Architecture

Tilt Hydrometer (Part 3) Advertising Scanner

Tilt Hydrometer (Part 4) Advertising Packet Error?

Tilt Hydrometer (Part 5) Tilt Simulator & Multi Advertising iBeacons

Tilt Hydrometer (Part 6) Tilt Simulator an Upgrade

Tilt Hydrometer (Part 7) Advertising Database

Tilt Hydrometer (Part 8) Read the Database

Tilt Hydrometer (Part 9) An LCD Display

Tilt Hydrometer (Part 10) The Display State Machine

Tilt Hydrometer (Part 11) Draw the Display Screens

Tilt Hydrometer (Part 12) CapSense

Tilt Hydrometer: LittleFS & SPI Flash (Part ?)

Tilt Hydrometer: WiFi Introducer (Part ?)

Tilt Hydrometer: WebServer (Part ?)

Tilt Hydrometer: Amazon MQTT (Part ?)

Tilt Hydrometer: Printed Circuit Board (Part ?)

You can get the source code from git@github.com:iotexpert/Tilt2.git  This repository has tags for each of the articles which can be accessed with "git checkout part12"  You can find the Tilt Simulator at  git@github.com:iotexpert/TiltSimulator.git.

 

Change the Database

Remember that my database is just an array of tilt_t structures.  That array goes from 0 to NUM_TILT and that the multi advertising capability goes from 1-a bunch.  So my algorithm for assigning tilts is just to put i+1, in other words the first Tilt is 0 and it will go in slot 1 etc.  Here is the original structure.

typedef struct  {
    char *colorName;    // The color string
    int slot;           // Which Bluetooth ADV Slot this Tilt is using
    bool dirty;         // A flag to tell if there has been a change since the adv was last written
    int rate;           // rate in ms
    int tempUpdate;     // The update rate for temperature
    int gravUpdate;     // The update rate for gravity
    uint8_t advData[TILT_IBEACON_LEN];
} tilt_t;

To make this work, I will

  1. Get rid of slot
  2. Add a boolean field called “enable”
typedef struct  {
    char *colorName;    // The color string
    bool enable;
    bool dirty;         // A flag to tell if there has been a change since the adv was last written
    int rate;           // rate in ms
    int tempUpdate;     // The update rate for temperature
    int gravUpdate;     // The update rate for gravity
    uint8_t advData[TILT_IBEACON_LEN];
} tilt_t;

Add an Initialization Function

Instead of re-initializing each advertising slot each time, I realized that I could initialize them all at once.  So, I create a function to do just that.

void btm_initialize()
{
    static wiced_bt_ble_multi_adv_params_t myParams = {
    .adv_int_min       = BTM_BLE_ADVERT_INTERVAL_MIN,
    .adv_int_max       = 96,
    .adv_type          = MULTI_ADVERT_NONCONNECTABLE_EVENT,
    .channel_map       = BTM_BLE_ADVERT_CHNL_37 | BTM_BLE_ADVERT_CHNL_38 | BTM_BLE_ADVERT_CHNL_39,
    .adv_filter_policy = BTM_BLE_ADVERT_FILTER_ALL_CONNECTION_REQ_ALL_SCAN_REQ,
    .adv_tx_power      = MULTI_ADV_TX_POWER_MAX_INDEX,
    .peer_bd_addr      = {0},
    .peer_addr_type    = BLE_ADDR_PUBLIC,
    .own_bd_addr       = {0},
    .own_addr_type     = BLE_ADDR_PUBLIC,
    };

    for(int i=0;i<NUM_TILT;i++)
    {
        wiced_set_multi_advertisement_data(tiltDB[i].advData,sizeof(tiltDB[i].advData),i+1);
        wiced_set_multi_advertisement_params(i+1,&myParams);
        wiced_start_multi_advertisements( MULTI_ADVERT_STOP, i+1);
    }
}

Then I updated the stack startup event to call the initialize function.

        case BTM_ENABLED_EVT:
            printf("Started BT Stack Succesfully\n");
            btm_initialize();
            btm_cmdQueue = xQueueCreate(10,sizeof(btm_cmdMsg_t));
            wiced_init_timer_ext(&btm_processDataTimer,btm_processCmdQueue,0,WICED_TRUE);
            wiced_start_timer_ext(&btm_processDataTimer,BTM_QUEUE_RATE);
        break;

Update the Function btm_setAdvPacket

When it is time to update the advertising packets, I just loop through the database

  1. If the tilt is dirty
  2. Then update the data
  3. And either turn on/off the advertisements for the tilt based on the state of the enable flag
void btm_setAdvPacket()
{
    for(int i=0;i<NUM_TILT;i++)
    {
        if(tiltDB[i].dirty)
        {   
            tiltDB[i].dirty = false;
            wiced_set_multi_advertisement_data(tiltDB[i].advData,sizeof(tiltDB[i].advData),i+1);
        
            if(tiltDB[i].enable)
                wiced_start_multi_advertisements( MULTI_ADVERT_START, i+1 );
            else
                wiced_start_multi_advertisements( MULTI_ADVERT_STOP, i+1 );
        }
    }
}

Add New Commands

Now I need to add two new commands, BTM_CMD_ENABLE and BTM_CMD_DISABLE

typedef enum {
    BTM_CMD_SET_DATA,
    BTM_CMD_PRINT_TABLE,
    BTM_CMD_SET_UPDATE,
    BTM_CMD_ENABLE,
    BTM_CMD_DISABLE,
} btm_cmd_t;

The code for enable is just to turn the enable flag on then turn on the advertising

            case BTM_CMD_ENABLE:
                tiltDB[msg.num].enable = true;
                wiced_start_multi_advertisements( MULTI_ADVERT_START, msg.num+1 );
            break;

A function for usrcmd is just to queue the message to enable

void btm_updateEnable(int num)
{
    if(btm_cmdQueue == 0 || num<0 || num>=NUM_TILT)
    {
        return;
    }
    btm_cmdMsg_t msg;
    msg.cmd =    BTM_CMD_ENABLE;
    msg.num = num;
    xQueueSend(btm_cmdQueue,&msg,0);
}

The command for disable just disables the flag and the advertising

            case BTM_CMD_DISABLE:
                tiltDB[msg.num].enable = false;
                wiced_start_multi_advertisements( MULTI_ADVERT_STOP, msg.num+1 );
            break;

And the usrcmd function just queues the message.

void btm_updateDisable(int num)
{
    if(btm_cmdQueue == 0 || num<0 || num>=NUM_TILT)
        return;
    btm_cmdMsg_t msg;
    msg.cmd =    BTM_CMD_DISABLE;
    msg.num = num;
    xQueueSend(btm_cmdQueue,&msg,0);
}

Update the Printing

Fix the print out to show the state of enabling instead of the “slot”

void btm_printTable()
{
    printf("\n# Color   E   Rate T  UpT Grav UpG TxP\n");

    for(int i=0;i<NUM_TILT;i++)
    {
        printf("%d %6s  %d %5d %3d %2d %4d %2d %3d\n",i,
            tiltDB[i].colorName,tiltDB[i].enable,
            tiltDB[i].rate*BTM_QUEUE_RATE,
            btm_getTemperature(i),tiltDB[i].tempUpdate,
            btm_getGravity(i),tiltDB[i].gravUpdate,
            tiltDB[i].advData[29]);
    }
}

Program and Test

When I program the board I can

  1. set
  2. print
  3. enable
  4. print
  5. disable
  6. print

And see with the Tilt app on my phone that everything is working

Recommended Posts

No comment yet, add your voice below!


Add a Comment

Your email address will not be published. Required fields are marked *