AnyCloud Bluetooth Advertising Scanner (Part 2)

Summary

The second article in a series discussing the creation of a PSoC 6 + CYW43xxx Advertising Scanner using the AnyCloud SDK.  This article will use the learning from Part 1 to create a template project that starts the BLE stack.

Story

In the previous article I discussed the structure of the Cypress/Infineon Bluetooth Stack and its integration into AnyCloud.  A bunch of “theory”, well I say BS to that.  Let’s build something.

For this series of articles I will:

  1. Discuss an overview of Bluetooth Application Architecture (Part 1)
  2. Explain how to Start the AnyCloud Bluetooth Stack (Part 1) 
    1. Discuss the configuration structure: bt_platform_cfg_setting (Part 1)
    2. Discuss the configuration structure: wiced_bt_cfg_settings (Part 1)
    3. Discuss the Tasks created by the Bluetooth Stack (Part 1)
    4. Build the Basic Project (Part 2)
    5. Discuss BLE Advertising - Scanner/Observer (Part 3)
    6. Discuss BLE Advertising - Advertiser (Part 3)
    7. Add BLE Scanning Code to the project (Part 3)

    Recall from Part 1 that you need three things to startup the Bluetooth Stack

    • The Hardware Configuration Structure that matches : cybt_platform_config_t
    • The Bluetooth Stack Configuration Structure that matches : wiced_bt_cfg_settings_t
    • The Bluetooth Management Callback that matches : typedef wiced_result_t (wiced_bt_management_cback_t) (wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data);

    Then you need to call

    • The hardware initialization function : cybt_platform_config_init
    • The stack initialization function : wiced_bt_stack_init

    Ok let’s do this!

    Basic Project

    You can do all of these steps from the Eclipse IDE for ModusToolbox.  Or you can do it from the individual programs and the command line.  I like Visual Studio code, so this article will be done completely from the command line and individual configurators.

    Run the new project creator from the start menu.  Start by creating a project for the development kit that you have, in my case the one currently plugged into my computer is the CY8CKIT-062S2-43012, so that is what I pick.  But, this project will work with any of the WiFI/BT combo chips attached to PSoC 6.

    In previous articles I discussed the template that I use to get things going with FreeRTOS.  I won’t discuss that here, but I want FreeRTOS and the NTShell, so pick the IoT Expert FreeRTOS NTShell Template.

    After about a minute you should have a project.  I always like to build the project to make sure that everything is working before I get too far down the road of modifying anything.  Run “make -j build”

    Then to be sure it is working, program the development kit.

    When that is done, open up a terminal window and you should have a functioning base project.  Notice that I ran “help” and “tasks” from the command shell.

    Now that we have a basic project working, add the Bluetooth libraries.  Run the library manager by typing “make modlibs”.  Then select “bluetooth-freertos” and the library manager will automatically select the other libraries you need.  Press Update then Close.

    Next, run the bluetooth configurator by running “make config_bt”  This tool will help you make the bluetooth stack configuration structure.  When the configurator starts, press “New”

    Then select our device (the PSoC 6 and the Combo chip)

    Click on the “GAP Settings”.  Then press the Plus and add “Observer configuration”

    Then setup the scan settings (more detail on these numbers in the next article)

    • Low duty scan window (ms) = 60
    • Low duty scan interval (ms) = 60
    • Low duty scan timeout = deselected (meaning no timeout)

    Then save your configuration file.  Notice that I called it “btconfig”

    When you are done you will have a directory called “GeneratedSource” inside of your project with the needed files.

    The next step is to fix up the Makefile.  I like changing the name of the “App”.

    Then you need the “FREERTOS WICED_BLE” components.

    If you run make vscode it will update the workspace with all of the stuff needed for Visual Studio Code to be able to find all of the files.

    Inside of Visual Studio Code, create a new file called “bt_platform_cfg_settings.h” and add:

    Inside of Visual Studio Code, create a new file called “bt_platform_cfg_settings.c” and add:

    Inside of Visual Studio Code, create bluetoothManager.h.  Remember this is the Bluetooth Stack Management Callback

    Inside of Visual Studio code, create bluetoothManager.c.  This function does a whole lotta nothin… except saying that things got started.

    Next, update main.c with the required includes.

    Then update main.c to start the stack

    Now build and program it, remember “make -j build” and “make program”.  Look, we have a functioning stack with the two bluetooth thread running.

    In the next article Ill finally get around to building the Bluetooth Scanner.

    AnyCloud Bluetooth Advertising Scanner (Part 1)

    Summary

    The first of several articles discussing the use of the AnyCloud BLE Stack to build advertising scanner/observers.

    Story

    A few summers ago while I was writing the WICED Bluetooth Academy book, I created a WICED based BLE advertising scanner.  Actually, I created a framework for the scanner and the remarkable summer intern I had finished the work.  That project has been sitting in the source code repository for the Bluetooth class, mostly only shown to face-to-face students.  This scanner is built using some of the original code combined with the new AnyCloud Bluetooth SDK.  It will act sort-of-like LightBlue or one of the other Bluetooth advertising scanners you might run on your phone, but with a serial console.

    Sometime in the last few months we released the Bluetooth SDK for AnyCloud (things have been crazy and I have lost track of time)  This SDK has all of the stuff needed to add Bluetooth to your AnyCloud project using one of the Cypress Bluetooth/WiFi combo chips.  I had not had a chance to try it out, so I decided to build a Bluetooth project and then port the scanning code.

    For this series of articles I will:

    1. Discuss an overview of Bluetooth Application Architecture (Part 1)
    2. Explain how to Start the AnyCloud Bluetooth Stack (Part 1) 
      1. Discuss the configuration structure: bt_platform_cfg_setting (Part 1)
      2. Discuss the configuration structure: wiced_bt_cfg_settings (Part 1)
      3. Discuss the Tasks created by the Bluetooth Stack (Part 1)
      4. Build the Basic Project (Part 2)
      5. Discuss BLE Advertising - Scanner/Observer (Part 3)
      6. Discuss BLE Advertising - Advertiser (Part 3)
      7. Add BLE Scanning Code to the project (Part 3)

      Bluetooth Application Architecture

      Bluetooth applications are divided into these four pieces

      1. You user application which responds to events and sends messages from/to the Bluetooth host stack
      2. A Bluetooth Host Stack
      3. A Bluetooth Controller Stack
      4. The Bluetooth Radio

      These four pieces can be divided into multiple chips, as few as one or as many as four.  However, for this article, the project will be built to run on a PSoC 6 + CYW43012 WiFi/Bluetooth Combo chip.  Specifically:

      1. My scanner application running on the PSoC 6
      2. The Bluetooth Host Stack running on the PSoC 6
      3. The BlueTooth Controller Firmware running on the CYW43012
      4. A Bluetooth Radio on the CYW43012

      But how do they talk?  Simple, there is:

      1. A UART Host Controller Interface (HCI) between the two chips
      2. A GPIO to serve as a deep sleep wakeup from the 43012 –> PSoC 6
      3. A GPIO to serve as the bluetooth controller wakeup from the PSoC 6 –> 43012
      4. A GPIO to turn on the Bluetooth regulator from the PSoC 6 –> 43012

      Here is the block diagram from the CY8CKIT-062S2-43012 Kit Guide.  Notice that signals labeled UART and Control going between the PSoC 6 and the CYW43012.

      And when you read more deeply into the schematic you can see the signals labeled

      • BT_UART_TXD/RXD/CTS/RTS
      • BT_HOST_WAKE
      • BT_DEV_WAKE
      • BT_REG_ON

      How to Start the AnyCloud Bluetooth Stack

      To actually start the AnyCloud Bluetooth stack you will call two functions

      1. cybt_platform_config_init – that will setup the hardware interface to the CYW43012
      2. wiced_bt_stack_init that will:
        1. Start a task to manage the Host Controller Interface
        2. Download the controller firmware to the CYW43012
        3. Start a task to manage the host stack
        4. Initialize both the host and the controller
        5. Call you back when that is all done

      Here is an example from main.

      When you look at these two function calls, you will find that you need to provide three things:

      1. A platform hardware configuration structure called bt_platform_cfg_settings
      2. The Bluetooth stack configuration settings structure called wiced_bt_cfg_settings
      3. A management callback called app_bt_management_callback

      bt_platform_cfg_settings

      The purpose of the hardware configuration structure is to define the UART + parameters and the wakeup GPIOs.  Specifically, the hardware configuration structure defines the configuration of the host controller interface (hci)

      1. The HCI transport scheme (in this case UART)
      2. The pins of the UART
      3. Baud Rate
      4. Data Bits
      5. Stop Bits
      6. Parity
      7. Flow Control

      And the controller low power behavior (in the .controller_config member)

      This is a fairly standard configuration and I think that we should help you by providing this structure somewhere in the BSP.  But for now, you need to provide it (in an upcoming article I’ll update the IoT Expert Bluetooth Library to provide it).  Here is the specific structure that I will be using.

      wiced_bt_cfg_settings

      The Cypress WICED Bluetooth Stack has a boatload of configuration settings.  When you call the stack start function you need to provide all of those settings in a structure of type “wiced_bt_cfg_settings_t” which is actually a structure of structures.  There are several basic ways to set these settings

      • Start from scratch and build you own settings
      • Copy from an example project
      • Use the Bluetooth Configurator to generate the structure

      For the purposes of THIS project I started by copying the structure from on of the example projects and then modifying the three numbers that were relevant to me.  Specifically

      • max_simultanous_link – which I changed to 0 because this is simply a Bluetooth Observer
      • low_duty_scan_interval – how long in the window to listen for advertising packets
      • low_duty_scan_window – how wide the window of listening should be

      app_bt_management_callback

      The last thing that you need to provide is a management callback.  This function is called by the Bluetooth Stack when a “management event” occurs.  There is a big-long-list of enumerated events of type wiced_bt_management_event_t.  The events include things like the the stack started “BTM_ENABLED_EVENT”.  Each event may have data associated with the event which is passed to you in a pointer to wiced_bt_management_event_data_t.

      You typically deal with these events with a giant switch statement like this:

      Tasks

      The Bluetooth stack on the PSoC6 is operated with two tasks.  Specifically, when you call the wiced_bt_stack_init it will startup:

      1. CYBT_HCI_Task – a task that sends and receives HCI packets going to the Radio chip
      2. CY_BT_Task – a task that manages the Bluetooth Host Stack

      Here is print of the task list from my project:

       

      Now with the background in place, in the next article I will discuss Bluetooth advertising and how to build the observer project.

      PSoC 6 BLE Events

      Edit: It turns out that I wrote this article in February of 2018 and never published it.  But it has good stuff… so here it is.

      Summary

      Over the last several weeks I have been spending time working with the PSoC 6 BLE.  Specifically the BLE part of the system.  Last weekend I found myself having problems with my design and I was really struggling to figure them out.  I realized that I “knew” what was happening with the BLE callbacks… but that I didn’t really “KNOW!”.  So I decided to build a simple project to show what events were happening and why.

      In this article I will show/tell you how (to):

      1. The BLE is supposed to work
      2. The PSoC 6 BLE example project
      3. Write the firmware
      4. Test the system

      You can “git” this workspace at git@github.com:iotexpert/PSoC-6-BLE-Events.git or GitHub.

      How the PSoC 6 BLE is supposed to work

      Honestly, the first time I started looking at the BLE (in my case it was the PSoC 4 BLE), it felt overwhelming.  But, it is actually pretty simple.  You, the firmware developer, send commands to the BLE stack using the Cypress PDL BLE middleware API.  Then, when “something” happens, the BLE stack sends you back an “event” in the callback.  That “something” can either be an acknowledgement that your API call has done something, or, it can be that something has happened on the radio side (e.g. you have been connected to by a client).  When you write a PSoC 6 BLE program you need to provide an event handler function (so that the BLE stack can send you events).  The function prototype for that handler is:

      This function has two arguments.

      1. An integer that is an eventCode (which you can put into the switch).  All of the event codes will look like “CYBLE_EVT_”
      2. A void pointer, that you will cast into a specific pointer based on the event code.

      Your event handler code will then be a big switch statement, where you will look at the events, and do something (or not).

      When you look in the PDL BLE Middleware documentation you can see the APIs and what events happen based on your API calls.  For example Cy_BLE_GAPP_StartAdvertisement tell the PSoC BLE Stack to start advertising.  You can see that it will generate 4 possible events i.e. CY_BLE_EVT_GAPP_START_STOP

      When you click on the event in the documentation it will tell you the meaning of the event, and what the eventParameter means (i.e. what you should cast it to in order to figure out the data passed to you)

      Build the project

      To build the project, first make a new PSoC 63 BLE project.  Then edit the schematic to have a BLE and a UART.

      PSoC 6 BLE Events Schematic

      Assign the UART pins to the KitProg UART bridge pins (aka P50/P51)

      PSoC 6 BLE Events Pin Assignment

      Configure the BLE to be a GAP Peripheral.

      PSoC 6 BLE Events Configuration

      Add a custom service to the project by loading the LED Service.  It doesn’t really matter what service you add for this project.  I just picked this one because I am using it for another project.  You could have just as easily picked one of the pre-existing definitions or made your own.

      PSoC 6 BLE Events Configuration

      This is what the LED Service looks like.

      PSoC 6 BLE Events - LED Service

      Configure the GAP settings.  Specifically name your device – in this case I named mine “mytest”

      PSoC 6 BLE Events GAP Configuration

      Edit the advertising packet to include the name and the service.

      PSoC 6 BLE Events Advertising Configuration

      Write the Firmware

      Remember the main event in this example project is the BLE Event Handler.  I created this event handler with the events that I normally used (i.e. CY_BLE_EVT_STACK_ON) and then kept adding events until I had them all defined.  The way that I knew an event was missing from the “switch” was by the default case printing out the event number.

      Now you need a task to run the BLE.  It just runs the Cy_BLE_ProcessEvents each time an event needs to be handled.

      Test the System

      Finally program the CY8CKIT-062-BLE and attach with it to CySmart or LightBlue.  There are three phases

      1. The stack turns on and starts advertising (CY_BLE_EVT_STACK_ON –> CY_BLE_EVT_GAPP_ADVERTISMENT)
      2. A connection is made and eventually disconnected (CY_BLE_EVT_CONNECT_IND –> CY_BLE_EVT_GAP_DEVICE_DISCONNECTED
      3. You start advertising again CY_BLE_EVT_GAPP_ADVERTISEMENT_START_STOP

      PSoC 6 BLE Events

       

      MBEDOS & BLE & PSoC 6 & CYW4343W

      Summary

      At the Embedded World Show in Germany in a couple of weeks I am going to be showing a crazy demo (more on this later) that uses MBED OS and BLE and WiFi and PSoC 6 and the 4343W.  Given how close things are and how new MBED OS is to me I figure that I had better get going sorting out the BLE interface.   This article and probably the next several are going to show my progress through the learning curve.

      It turns out that in MBED OS, instead of using the Cypress BLE Host Stack I will be using the ARM Cordio BLE host stack talking via HCI to the Cypress BLE Controller stack running on the 4343W (a Bluetooth, BLE and WiFi combo chip).  At this point all of my experience with BLE has been with Cypress stacks, either the PSoC 4/6 BLE stack or with the Cypress IoT stacks e.g. the CYW20719.  Lot’s of new learning.  Add in that all of the code is in C++ and it makes for an adventure.

      For this article I will show the steps to get an ARM BLE example going on the CY8CPROTO_062_4343W development kit.  This will involve.

      1. Importing the ARM MBEDOS BLE Examples
      2. Modifying them to support the Cypress Targets & Test
      3. Updating an example program in a few places to fix things that I don’t like.

      Import ARM MBED OS BLE Examples

      The first step is to make a clone of the ARM examples by running “mbed import mbed-os-example-ble”.  This will load a bunch of different example projects (as libraries)

      Then, when you look at what you have after all of that mess, you can see 14 example programs with promising names.

      When you look in the BLE_LED directory you will find a file “readme.md” which is a markdown formatted file.  You can view this file on the GitHub website for this example here.  The top of this one looks promising:

      Modify and Test

      I decide that the example called “BLE_LED” looks like a good place to start.  This example is a simple peripheral that advertises it name.  When you connect to it there is a Service with UUID “0xA000” (unfortunately a 16-bit UUID… bad demo code) that Service has one characteristic with UUID 0xA001 (another 16-UUID … that isn’t nice … come on people… haven’t you read the spec?).  When you write a “1” to that characteristic the LED2 is supposed to turn on, and when you write a 0 the LED2 is supposed to turn off.

      First, until the Cypress stuff is accepted into the main release, I need to update mbed-os to our targets) with “cd mbed-os ; mbed update master”.  To build this project Ill run “mbed compile -t GCC_ARM -m CY8CPROTO_062_4343W”.  When I program the the development kit, the LED starts blinking and I am able to see it using the GATT browser LightBlue Explorer.

      But when I try to write a 1 to the 0xA001 characteristic nothing happens.

      So, what gives? The answer is that on line 32 you can see that the authors as assuming that you have two LEDs (my development kit only has one.

      And on line 124 you can see a function that inverts the LED

      which is triggered on line 47 to be called every 500ms

      OK.  I am not loving this. I think that I should make some updates to this project.

      Update

      There are several things that I don’t like about this program or need to be fixed.

      1. Make the user LED2 be LED1 and fix the fact that it is active low.
      2. Change the UUIDs of the Service and Characteristic to be legal 128-bit UUIDs
      3. Make the stdio print out the status of the connection (instead of the blinking LED1)
      4. Make the baud rate of standard i/o be 115200 instead of 9600

      First, fix the LED2 to be LED1.  Do this by commenting out all of the _alive_led code and switching the _actuated_led to be LED1.  Also set the state of the LED1 to 1 (meaning off because it is active low)

      The author of the example code has a function called blink which is executed by the event queue every 500ms, comment out that function

      And don’t inject events into the queue to run the blink function

      The LED on my board is active low… so instead of writing the value write the opposite of the value.

      It is illegal in Bluetooth to use 16-bit UUIDs without first registering them with the Bluetooth SIG and having them be “Assigned numbers”.  The author of this example program violated the specification by assigning the LED service UUID of 0xA000 and the LED characteristic UUID of 0xA001.  This is super annoying and I am not willing to be a slob.  To fix this modify ledservice.h to declare the UUIDs as UUID type instead of uint16_ts

      Then initialize them in the main.cpp as 128-bit UUIDs using the const char * initializer.

      The original code has a blinking LED.  Which I dont really like.  Typically, I like to blink the LED when the device is advertising, and make it be solid when there is a connection.  However, as I only have one LED on my board, and I have allocated it to be the “_actuated_led”, I will use the UART to print out status changes.  To do this, I update the “onDisconnectionComplete” and “onConnectionComplete” events to print out that fact to stdio.

      In order to set the stdio to use 115200 instead of 9600 you can change the default rate of the UART in the mbed_app.json.

      Here is the final version of main.cpp

      And LEDService.h

       

      BLE Write Request, Write Command, Signed Write Command & Prepare Write

      Summary

      In my article entitled “PSoC4 BLE Central Custom Profile w/LED & CapSense” a reader named Doug posted a question which asked about BLE Writes and the events that are created in PSoC 4 BLE.  This article attempts to answer those questions.  The bottom line is that the BLE Spec specifies four ways for a GATT Client to write to a GATT Server.  Each of those write types either have a response or not.  Inside of the PSoC BLE Stack each of them generate a different event.

      Here is a summary of the BLE Write Events from my WICED BLE textbook chapter 4D.4

      Inside of the PSoC Stack it will generate the following events:

      Request Event PSoC 4 Response API
      Write Request CYBLE_EVT_GATTS_WRITE_REQ No Response
      Write Command CYBLE_EVT_GATTS_WRITE_CMD_REQ CyBle_GattsWriteRsp or CyBle_GattsErrorRsp
      Signed Write CYBLE_EVT_GATTS_DATA_SIGNED_CMD_REQ CyBle_GattsWriteRsp or CyBle_GattsErrorRsp
      Prepare Write CYBLE_EVT_GATTS_PREP_WRITE_REQ Out of scope for today
      Execute Write CYBLE_EVT_GATTS_EXEC_WRITE_REQ Out of scope for today

      Question(s)

      Here are the original question(s):

      Hi, I am having some problems understanding “write without response” setup.
      In the “capsenseled” server project “CYBLE_EVT_GATTS_WRITE_REQ” is used instead of “CYBLE_EVT_GATTS_WRITE_CMD_REQ” in the event handler, but “write without response” is selected in the component setup.
      According to this other project I am looking at ( https://www.digikey.com/eewiki/pages/viewpage.action?pageId=55574662 ) both are used with comments as follows

      case CYBLE_EVT_GATTS_WRITE_REQ: //Write with response
      case CYBLE_EVT_GATTS_WRITE_CMD_REQ: //Write without response

      Why is “CYBLE_EVT_GATTS_WRITE_CMD_REQ” NOT used in the capsenseled project, and does “CYBLE_EVT_GATTS_WRITE_REQ” still function in a write without response setup?
      Am I misunderstanding the definition of a response?
      Is the “response” referring to an event that occurs within the server device, or is a response defined as a reply from the client device?

      I am trying to set up a low power single button remote to report the state of the button, to be handled by the client which is connected to a larger power source and will possibly count edges, measure button press duration, or both, etc. Ideally the remote would be asleep except for when it needs to tell the client that the button has changed states, and would not spend any energy processing a response from the client.

      BLE Spec

      When you declare a Characteristic, you have a 1-byte bit field to specify the Characteristic Properties, that tells the GATT Client how it can write to the Characteristic.  Here is a screenshot from section 3.3.1 of the Bluetooth core spec:

      And the legal values for the Characteristic Properties are in section 3.3.1.1

      This table says that it is perfectly legal to perform a “Write without response” (which is really called “Write Command” in section 3.4.5.3) or a “Write” (which is really called “Write Request” in section 3.4.5.1) as long as you send a legal response (or none).  If you look at the project which is referenced in the Digikey article, you can see that the author did just that for the Characteristic “Number_Write”.

      Write Command a.k.a. Write Without Response”

      As I looked around at the spec for this article I discovered something which I did not previously know.  Specifically, a Write Command must fit in one packet… which means that the data written to the Characteristic must be no more than the ATT MTU – 3.  Here is the spec:

      Write Request

      A Write Request is a two sided request, meaning the GATT Server must either send a “Write Response” or an “Error Response”  Here is a screenshot from the spec.

      Write Response

      A Write Response is a stupid simple packet with just one possible value… 0x13 meaning that the write worked.  In the PSoC, you generate this packet by calling “CyBle_GattsWriteRsp” with the connection handle as the only parameter.

      Error Response

      The more interesting response is an error where you are allowed to send more information.  To generate an error response in PSoC you call CyBle_GattsErrorRsp with the connection handle and the error code.

      The spec gives a list of legal error codes.  Here is a snapshot from the spec with a FEW of them.

      The interesting thing about these error codes is that you are allowed to create you own “Application Errors” which will have your application semantics.

      PSoC Creator has an enumerated list for the error codes (here is a short section from the BLE Component Datasheet)

      Answers

      OK… so that leaves me with giving specific answers to his questions.  My answer are embedded in bold:

      Hi, I am having some problems understanding “write without response” setup.
      In the “capsenseled” server project “CYBLE_EVT_GATTS_WRITE_REQ” is used instead of “CYBLE_EVT_GATTS_WRITE_CMD_REQ” in the event handler, but “write without response” is selected in the component setup.
      According to this other project I am looking at ( https://www.digikey.com/eewiki/pages/viewpage.action?pageId=55574662 ) both are used with comments as follows

      case CYBLE_EVT_GATTS_WRITE_REQ: //Write with response
      case CYBLE_EVT_GATTS_WRITE_CMD_REQ: //Write without response

      Why is “CYBLE_EVT_GATTS_WRITE_CMD_REQ” NOT used in the capsenseled project,

      When I wrote that project originally I chose to only support no responses to writes.  There is no need to support both.  As the application developer you can choose to do either or both.

      and does “CYBLE_EVT_GATTS_WRITE_REQ” still function in a write without response setup?

      If the GATT Client sends you a CYBLE_EVT_GATTS_WRITE_REQ and you send a response it might turn out badly and you should not do that.
      Am I misunderstanding the definition of a response?
      Is the “response” referring to an event that occurs within the server device, or is a response defined as a reply from the client device?

      Well..  sounds like the answer was yes… but hopefully it is no now.

      I am trying to set up a low power single button remote to report the state of the button, to be handled by the client which is connected to a larger power source and will possibly count edges, measure button press duration, or both, etc. Ideally the remote would be asleep except for when it needs to tell the client that the button has changed states, and would not spend any energy processing a response from the client.

      Sounds like “Write without response” is perfect for your application.

      Mouser PSoC 6-WiFi-BT L8: Integrate WiFi and AWS Into the Game

      Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

      Summary

      In this lesson we will move the subscriber app functionality into the main GameBle project (now called GameBleAws).  In order to do this, you need to turn the subscriber into a thread, and fix it so that messages that are sent to the PADDLE topic get turned into messages that can be sent to the paddleQueue.

      To implement this lesson I will follow these steps:

      1. Create a New Project starting from L6GameBle
      2. Copy over subscriber.c and wifi_config_dct.h
      3. Update the Makefile
      4. Create subscriber.h
      5. Update main.c
      6. Update subscriber.c
      7. Test

      Create a New Project

      Copy and paste the L6GameBle project into a new project called L8GameBleAws using Copy/Paste

      Create a new Make target for the GameBleAws project

      Copy subscriber.c & wifi_config_dct.h

      Use copy/paste to make a copy of the subscriber application and paste it into the GameBleAws project.  Once done your folder should look like this:

      Update the Makefile

      Create subscriber.h

      In order for the main.c to know about the awsThread (which is the former application_start of subscriber.c) you should create a file called subscriber.h.  Then you should define the awsThread function to match the wiced_thread_t function prototype (just a function that takes a wiced_thread_arg and returns void).

      Update main.c

      To integrate the awsThread thread into your main project you need to add the “subscriber.h” to the includes:

      Add a new variable to hold the awsThreadHandle.

      Finally you should launch the AWS thread by creating it with wiced_rtos_create_thread.

      Update subscriber.c

      In order for subscriber.c to be useful you need to fix the includes, send the messages from the PADDLE topic to the game thread, and turn application_start into a thread.  Start by fixing the includes (just like we did in the BLE Example in Lesson 6)

      When you get a message to the PADDLE topic, you should parse it, then send a message to the game thread to move the paddle.  You do this exactly the same way as you did in the BLE project.  Notice that I protect the game thread by making sure it send a value less than 100.

      Test

      I don’t really have a good program (like the GoBle) to test moving the paddle live.  But you can see that when the game is over, you can still move the paddle using AWS console.  In the screen shot below you can see that I moved the paddle to position 0.  And you can see that the BLE started at the same time as AWS.  Score.

      Mouser PSoC 6-WiFi-BT L7 : Implement WiFi and AWS

      Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

      Summary

      In this lesson I am going to update one of the predefined application which we deliver as part of WICED Studio which knows how to connect to the AWS IoT Cloud to work on my network.  This will demonstrate WiFi and MQTT.  I will also fix the application so that it knows about a new MQTT Topic called “PADDLE” which will be used to send messages to move the game paddle.

      To implement this project I will:

      1. Copy the subscriber from demo/aws/iot/pub_sub/subscriber
      2. Setup a “thing” on AWS and download the certificates
      3. Update the certificates in the WICED installation
      4. Update the project with my AWS configuration
      5. Test
      6. Update the project to be compatible with the Game
      7. Test

      Copy Subscriber & Fix the Makefile

      The first thing that I will do is copy/paste the subscriber application which can be found at demo/aws/iot/pub_sub/subscriber into my folder.  I will also rename the project to L7subscriber. Once that is done it should look like this:

      Then you need to edit the Makefile to update the name of the project.

      Go to Amazon.com and Create a “thing”

      In order to connect to the AWS cloud you need to create a “thing”.  Go to the AWS console and click “Create”

      We are just going to create one thing.  So, click “Create a single thing”

      Give it a name, in this case Mouser.

      AWS has device level security which is implemented with RSA certificates for each device.  So,  you need to let AWS create a certificate for you.

      Once that is done download the device certificate and the two keys.  You need to 100% make sure you do this now, because you wont get another chance. I’m also going to activate the certificate once I have the certificate and keys.

      Now attach a policy to your thing.  I already have the “ww101_policy” setup.

      The policy looks like this.  Basically, things are wide open.

      Update the Certificates

      The last thing that you need is the most recent AWS certificate.  WICED expects that you use the RSA2048 bit key.

      Now that you have the four security documents., you need to integrate them into your WICED installation.  To do this, change directories to ~/Documents/WICED-Studio-6.2/43xxx_Wi-Fi/resources/apps/aws/iot  Then copy the files, and then make symbolic links.  If you are not on a Mac or Linux then just copy the files and rename them appropriately.

      Update the Project

      AWS creates a virtual machine and runs an MQTT server on that machine.  You can find out the DNS name of that machine on the settings screen.  Here you can see my endpoint.  You will need to configure the WICED project to talk to your server.

      You need to change the actual endpoint of your MQTT server in the AWS cloud on line 119

      In the file wifi_config_dct.h you will need to change the CLIENT_AP_SSID and CLIENT_AP_PASSPHRASE for your network

      Test

      In order to test the project you will need to create a make target and program your development kit.

      Once that is done you can go to the Amazon.com test console and send MQTT messages to the correct topic.

      Here you can see the project attached to my network.  And successfully received the LIGHT ON message.

      Update the Project for the Game

      We know that the game doesn’t care about the LIGHT topic so, let’s change it to PADDLE.

      And let’s assume that messages to the paddle topic are ASCII numbers <100.  So, we can parse the message and print it out.  Notice that I used sscanf to parse the message and we all know that is super dangerous.

      Test

      After making those updates let’s program the whole shooting match again.  Then test by sending some messages to the PADDLE topic.

      It’s good.  Things are working.

      Mouser PSoC6-WiFi-BT L6 : Integrate GoBle Bluetooth into the Game

      Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

      Summary

      At this point we have a working BLE Remote Control and a working Game.  In this lesson I’ll merge the two projects together so that the GoBle remote control will be able to control the game paddle.  It will do this by creating messages (just like the CapSense messages) and sending them to the Game thread via the paddleQueue.  And it will send “Button0” messages when “Button A” is pressed.

      To implement this lesson I will follow these steps:

      1. Copy everything into a new project
      2. Modify the Makefile
      3. Modify main.c
      4. Create a new make target
      5. Test it all to make sure things are still working
      6. Modify GoBleThread.c
      7. Program and Test

      Copy L4Game into a new project L6GameBle

      Use “copy” and “paste” to create a new project, when you paste give it the name “L6GameBle” (there is an error in the screenshot)

      Copy the files GoBle_db.c/h, GoBleThread.c/h, and wiced_bt_cfg.c from the GoBle project into your new GameBle project.  After that is done your project should look like this:

      Modify the Makefile

      1. Change the name of the App to “App_WStudio_L6GameBle”
      2. Add the new source files
      3. Add the BLE Library “libraries/drivers/bluetooth/low_energy”

      Modify main.c

      Add the include for the GeBleThread.

      In the application_start function add a call GoBleThread_start() to get the GoBle thread going

      Create a new make target

      Test it all to make sure things are still working

      Run the make target and make sure that the game still plays and that you can get remote control messages.

      Modify GoBleThread.c

      Add the includes for the GameThread (to get access to the game message structure) and SystemGlobal (to get access to the queue)

      I don’t need (or want) the button/slider printout information.  So I will delete the old button code from goble_event_handler. (delete this stuff)

      Now, update the code to send the slider and button information to the GameThread (via the paddleQueue).  You may have noticed that the slider on GoBle gives you 0->0xFF and the direction is the inverse from the game we setup.  So, I will scale the value to 100 and invert it so that the controller moves the paddle the right way on line 143.  The message format is exactly the same as what we setup for the CapSense.  This means the CapSense slider works at the same time as the GoBle controller.

      Program and Test

      Mouser PSoC6-WiFi-BT L4 : The Video Game

      Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

      Summary

      In this lesson I’ll finish the video game thread by adding the graphics etc. to play the game.  In addition I’ll fix up the CapSense thread so that it is connected to the game via an RTOS queue.

      There are three main things going on in this game.

      1. A state machine for the game screen (Splash, Start, Running, Over)
      2. A 20ms timer that updates the screen while the game is running (moves the Paddle and the Ball)
      3. A GUI queue where the rest of the system – CapSense,  Bluetooth and WiFi – can send Button and Paddle messages.

      To implement this project I will:

      1. Setup the project and makefile by copying L3CapSenseTft
      2. Update gamethread.h to define the GUI queue messages
      3. Fix main.c to create the queue
      4. Create SystemGlobal.h to give the rest of the files access to the gui queue
      5. Updating the CapSenseThread to send GUI messages
      6. Update the includes in GameThread.c
      7. Add some #define macros to define game parameters
      8. Add a State Machine for the game & define some paddle movement methods
      9. Make forward declarations for the thread functions
      10. Create some variables to maintain game state
      11. Add display functions for the score and the speed
      12. Add functions to start and end the game
      13. Add helper functions to calculate the top and bottom of the paddle
      14. Add a function to update and draw the paddle
      15. Add a function to update and draw the ball
      16. Add a function for the game timer to call
      17. Update the main game thread

      Setup the project and makefile by copying L3CapSenseTft

      Use copy/paste to copy the L3CapSenseTft project to a new folder name L4Game.   Change the name of the makefile to be L4Game.mk.

      Edit the makefile and change the name of the application.

      Create a make target for this project

      Update GameThread.h to Define the GUI Messages

      All of the threads in the system (CapSense, Bluetooth, and WiFi) will control the paddle and the button by sending messages to an RTOS queue.  In gameThread.h we will add a definition of that message.  The message is just a structure with two values – which GUI element and what value to send.

      Fix main.c to Create the Queue

      I typically believe that the RTOS primitives should be owned by the main.c.  To do this edit main.c and fix the includes.

      Then define the queue variable “paddleQueue” which I should have names “guiQueue” but it is way to late to fix it now — oh well.

      Create the queue

      Create SystemGlobal.h

      Each of the threads in the system need to have access to the paddleQueue.  In order to do that create a file called SystemGlobal.h and extern the variable to give them that access.

      Updating the CapSenseThread to send GUI messages

      Remember that when we setup the CapSenseThread originally, it just printed out the values.  Let’s fix it so send messages.  So, edit CapSenseThread.c.

      1. Add a message variable (line 8)
      2. Fix the button0 and button 1 to make and send RTOS messages (lines 20/21 and 26/27)
      3. Fix the slider to send the position (lines 33-35)

      Update the includes in GameThread.c

      Now let’s fix GameThread.c.  Start by editing the includes to add a new file called “SystemGlobal.h” which contains the global variable for the GUI queue.

      Add some #define macros in GameThread.c

      There are a number of constants which I use in the game.  In this section I use #define macros to define them.

      Add a State Machine for the Game & Define Paddle Movement

      Open up GameThread.c – all of the game control functions will go there.

      There will be four screens in the game.  A splash screen to display Cypress and Mouser, a Ready Player 1 Screen, the actual game screen and a game over screen.

      In addition the paddle can move a little bit at a time (increment) or jump directly to the position (absolute)

      Fix the gameState statemachine

      In the splash screen I need to set the state machine to GS_SPLASH

      In the start screen I need to set the state machine to GS_START

      Make Forward Declarations for Functions

      You should define the functions in advance of using them

      Create some variables to maintain game state

      The updateScreenTimer is used while the game is running to call the updateScreen every 20ms.  The rest of the variables are self explanatory.

      Add Display Functions for the Score & Speed

      These two functions print the speed and score at the top of the screen.

      Add Function to Start the Game

      When the game needs to start you:

      1. Reset the score
      2. Set the paddle position
      3. Move the ball to the middle of the paddle
      4. Set the ball to move to the right and down
      5. Clear the screen, display score and speed
      6. Start the game running

      Add Function to End the Game

      When the game is over you should:

      1. Move the game state to over
      2. Stop the timer
      3. Display game over
      4. Display press button 0 to start

      Add Helper Functions to Calculate Paddle Top & Bottom

      There are two places where you need to know the position of the Paddle.  Specifically:

      1. To draw the paddle
      2. To figure out if the ball hit the paddle or not.

      These two functions calculate the pixel position of the top and bottom of the paddle based on it current position

      Add a Function to Update & Draw the Paddle

      While the game is running you need the paddle to move.  There are two methods:

      1. Absolute just moves the current position immediately to the desired position.
      2. Incremental, which moves the paddle a little bit towards the desired position.

      Add a function to update and draw the ball

      You need a function to:

      1. Move the ball
      2. Figure out if it hit the right/left/top/bottom of the screen and do the right thing.

      When the ball hits one of those surfaces it needs to change direction to either plus or minus.

      Every time it hits the paddle the score should increase and possibly speed up.

      If it misses the paddle the game is over.

      Create a Function for the Game Timer

      An RTOS timer runs every 20ms.  That timer needs a function to move the paddle and move the ball.

      Update the Main Game Thread

      The main game thread needs to get messages out of the queue and then do the right thing based on the game state.

      Program and Test

      Now that it is all done… program and test it.

      GameThread.c

      Here is the whole thread is here so you can copy/paste it into your file.