Projects

    Publish
     
      • How to create your own BLE Mobile App in 10 minutes

        Juan Benavides | 01/29/2018 | 05:43 PM

        Hackathon Project by Juan Benavides

         

         

        Introduction

        Have you ever wanted to get into mobile apps development but didn't have the time to learn other programming languages?

        In this blog I will show you how to create your own mobile app that connects to your Bluetooth Low Energy device.

        As part of a Hackathon project, I was interested in creating my own mobile app to connect to a Zigbee-based Light that doubles as a BLE Device. In other words, it is a Light that supports two protocols; Zigbee and BLE over the same radio.

        I wanted to support Android and iOS and I only had a background in Embedded Systems and a couple of days to get it done. So, after a quick Google search I was lucky to find a solution that only takes 10 minutes to develop (that's including the time spent installing the tools).

        The solution is called Evothings Studio and it offers a way to develop your mobile app using familiar web technologies such as HTML, CSS and JavaScript.

        One of the most amazing things is that the mobile app runs live on mobile devices while you develop and you can instantly see code changes on your apps.

        The process of developing the mobile app can be summarized as follows:

        1. Get a Bluetooth Device running.
        2. Install Evothings Tools in your PC and your phone.
        3. Select an example from the Evothings list of examples.
        4. Modify the example by using the UUIDs from your BLE Device. 
        5. Connect your phone to your BLE Device to control it.

         

         

        Step-by-step guide to reproduce the project

         

        Getting a Bluetooth Device running

        If you already have a BLE Device running, then the only thing you need to do in this step is make note of the following Unique Identifiers (UUID):

        • BLE Unique Service Indentifier: this is the UUID of the BLE Device Service you want to control (e.g. bae55b96-7d19-458d-970c-50613d801bc9).
        • BLE Characteristic Unique Identifier: this is the UUID of the BLE Device Characteristic you want to control (e.g. 76e137ac-b15f-49d7-9c4c-e278e6492ad9).

        If you don't have your BLE Device ready to go, then you can use the same one that I used from the Dynamic Multiprotocol (DMP) Light/Switch Demo. Click here and follow steps 1-5 to get it running.

        Once you get it running, open the Light Project in Simplicity Studio, open the file DynamicMultiprotocolDemoLightSoc.isc, select the Bluetooth GATT tab and make note of the BLE Unique Service Identifier and the BLE Characteristic Unique Identifier as illustrated in the image below:

        Figure 1
        Finding your BLE Device's UUIDs in Simplicity Studio

         

         

        Installing the Evothings Tools

        In this step you need to install both, the Evothings Studio application in your PC and the Evothings Mobile App in your phone. Click here to install the Evothings tools and verify that everything is operational by running their Hello World example.

         

         

        Select a Mobile App BLE example as a starting point

        Once you verified that you can run their Hello World example, locate the example Arduino101 LED On/Off BLE and click the button Copy as shown in Figure 2:

        Figure 2
        Selecting one of the BLE Examples as a starting point

         

         

        A window will be displayed for you to edit the project's name. You can call it dmp-light as shown in the following image:

        Figure 3
        Customizing the example with your own project name

         

         

        Modifying the Mobile App BLE example with your own UUIDs

        The next step is to edit the code. Select the tab MyApps in Evothings Studio to display your newly created example and click the button Edit and your text editor will open the folder where your example is located.

        First edit the file evothings.json and replace the property uuid with your own BLE Device Service UUID as shown in Figure 4:

        Figure 4
        Customizing the example with your own BLE device's service UUID

         

         

        Similarly, open the file index.html and replace the uuids in the functions to turn the LED On and Off, with your own BLE Device Characteristic UUID as shown in the image below:

        Figure 5
        Customizing the example with your own BLE device's characteristic UUID

         

         

        Finally, find out what's the advertised name of your BLE Device by scanning all the BLE devices within range from your phone as shown in Figure 6:

        Figure 6
        Scanning BLE devices within range from your phone

         

         

        Open the file index.html, locate the function app.connect and replace the advertised name of the BLE device with your own name as illustrated in Figure 7:

        Figure 7
        Customizing the example with your own BLE device name

         

         

        Connecting your new mobile app to your BLE device

        To connect to your BLE device you need to follow the same steps you made when trying their Hello World example; Start Evothings Workbench and under the Connect tab paste your Cloud Token and get a connect key using the GET KEY button. Launch Evothings Viewer on your phone, enter the connect key to hook up with your Workbench. On your computer, click the RUN button on your new DMP Light example in the Workbench.

        Now you can turn the Light On/Off from your phone as shown in the image below:

        Figure 8
        Your new mobile app

         

         

         

        Conclusion

        The Evothings Studio platform is a fast and easy way to develop mobile applications for Android and iOS while supporting one single code base through the use of the three most basic web technologies (HTML, JavaScript and CSS).

        For more information on how to deploy your mobile app to an app store check the following page: https://evothings.com/doc/build/build-overview.html

        For more information on how to get started developing your own Bluetooth Low Energy devices visit our website at: https://www.silabs.com/products/wireless/bluetooth

         

      • How to control a Zigbee-based Light with an Occupancy Sensor, Alexa and your Phone

        Juan Benavides | 01/22/2018 | 03:05 PM

        Hackathon project by Manasa Rao, Stephen To and Juan Benavides

         

         

        Introduction

        Would you like to learn an easy way to control a Zigbee-based Light with Alexa voice commands?

        Or how about controlling a Zigbee-based Light automatically with an Occupancy Sensor?

        Furthermore, how would you like to learn how to easily create your own Bluetooth mobile application to control a Zigbee-based Light and access the Internet?

        In this Hackathon project we demonstrate how to easily accomplish all of these cool features.

        Figure 1
        Project Presentation

         

         

        Background

        Silicon Labs released on November 2017 the new Dynamic Multiprotocol Software (DMP) for our Wireless Geckos. In summary, the DMP software enables the simultaneous operation of Zigbee and Bluetooh Low Energy (BLE) on a single radio chip.

        The best example to showcase this technology is by controlling and monitoring a Zigbee-based Light directly over Bluetooth with a smartphone mobile application. This example is actually available with the DMP SDK and our Hackathon project is based on it. 

         

         

         

        Project Overview

        The following image illustrates the scope of this blog:

        Project Overview
        Figure 2
        Project Block Diagram

         

        The Demo featured in this blog is based on the official DMP Light/Switch Demo that consists of two devices:

        Light: it runs Micrium OS to switch between Zigbee and Bluetooth on a single radio. 

        Switch: it supports Zigbee to provide wireless control of the Light.

        Click here to get started with this demo.

        In the original demo, users press a push button on the wireless Switch device, which in turn, sends a Zigbee Light Link (ZLL) command to toggle the Light On or Off.

        The Light device runs Micrium OS to switch between Zigbee and Bluetooth while sharing the same radio. This allows a mobile application to connect to the Light via Bluetooth.

        Users tap the mobile application to toggle the Light On/Off. 
        The Light device receives the Bluetooth notification and not only toggles the Light On/Off  but also updates the corresponding ZLL Cluster Attribute so the Switch remains in sync.

        This blog shows you how to add an Occupancy Sensor to the Switch device by connecting the Silicon Labs Optical Sensor Expansion Board (Si1133/Si1153) to the Switch's EXP Header (I2C).

        The Optical Sensor Expansion Board has a series of optical sensors to detect the presence of a person in the room. The occupancy sensor is used by the embedded application to control the light automatically. 

        Click here to see Stephen's blog on how to add this occupancy sensor to the DMP Light/Switch Demo.

        This blog is also going to show you how to control the Light with Alexa Voice Commands.

        To enable Alexa Voice Commands, we are also going to show you an easy way to create your own Bluetooth Mobile Application. This mobile application will use the smartphone as a gateway to access the Internet.

        Click here to see Juan's blog on how to create your own BLE mobile app to control the DMP Light/Switch Demo.

        Users will get to control the Light with Voice Commands and this blog will describe how to setup the system in Amazon Web Services (AWS).

        Click here to see Manasa's blog on how to add Alexa capabilities to the DMP Light/Switch Demo.

         

         

         

        Useful Links

         

         

         

      • Thunderboard Sense Battery Life

        Nick_W | 10/289/2017 | 11:43 PM
        I’ve been playing with this great new board for a few days now. One issue I have run into is that the battery life is very poor. I’m only getting a couple of days out of a coin cell.

        I’ve dug into the code, and a couple of things become clear. First, when running rom battery, when you connect to the board, all the sensors switch on, and stay on, until you disconnect.

        Second, when you read the sensor values, you aren’t reading the sensors directly, you are reading a cached copy of the values, which are updated every 3 seconds, continuously while you are connected - irrespective of how often you actually read the values out.

        Thirdly, on USB power, sensors are powered on all the time (OK, not a big deal).

        The conclusion is that if you connect, stay connected, and read the sensors once per minute, the sensors are live all the time, and the battery dies quickly. In fact, I’m not sure the device sleeps at all when connected.

        If you connect, read, then disconnect, you have the problem that the device times out after 30 seconds (ie goes into deep sleep, and can only be woken with a button push).

        I have changed this timeout to 1 hour, reduced the advertising cycle to 500ms (from 100ms) and reduced the led flashes (during advertising) to 20ms every 10 seconds, but the battery life is still poor when connecting, reading, disconnecting once every minute. I’m just reading the environmental sensors.

        It seems that although the sensors are off when not connected, the device does not sleep at all when advertising. (Although debug output does say BLE sleep mode enabled).

        Does anyone have any suggestions on how to reduce battery drain? Make the device sleep between advertisements? Or any other way to extend the battery life beyond a few days?

        Thanks.
      • Simple WGM110 programming fixture

        madsci | 10/289/2017 | 11:29 AM

        This project isn't really an end in itself, just a simple tool for working with the WGM110 Wi-Fi module, but it was suggested that I share it here, so I'm re-posting.

         

        Sometimes it's useful to be able to pre-program modules before they're installed on a board, particularly if your board doesn't have space for a SWD header.  The earliest versions of the WGM110 also had a defective DFU bootloader (stop bits were 1/2 bit time) that wouldn't work with some hosts, which made in-circuit programming difficult without SWD.

         

        To address this I made a quick and dirty programming fixture for about $15.  The components are a Mill-Max 854-22-010-40-001101 0.050" pitch 10-position pogo pin header to connect to the WGM110, a Samtec SFSD-10-28-H-05.00-SR cable with 20-pin 0.050" pitch plug for the JTAG side, some heat shrink tubing, and a 3D printed holder that I whipped up in Alibre.

         

        This is not really the right JTAG connector - its polarity key is in the wrong place and it's latching - but it's the closest thing that Digi-Key happened to have in stock that had discrete wires.  It fits on the dev board as is, and it'll fit on a P&E Cyclone's shrouded header if you snip off the key.

         

        In the orientation shown in the top view photo, the pogo pins are wired to the following JTAG pins:

         

         

        • 3 (ground)
        • (nc) 
        • 1 (VDD) 
        • 10 (Reset) 
        • (nc)
        • 2 (SWDIO)
        • 4 (SWCLK)
        • (nc)
        • (nc)
        • (nc)

         

        If I was going to be using this much I'd have machined mine from Delrin or anti-static ABS, but for only doing a few dozen units at most it didn't seem worth firing up a milling machine.

         

        Without the holder piece, I can use the pogo pin plug to re-flash modules in circuit that have been bricked by DFU failures.  This depends on having the PCB lands extend far enough beyond the periphery of the module to make contact.  If you followed the recommended layout in the datasheet, it ought to work. I wouldn't want to have to do many boards this way without an alignment jig to hold it in place, but it works fine to just hold it in place if you're just fixing an occasional mistake and not doing production quantities.

         

        Top view:

         

        2017-10-14 12.34.07.jpg

        Bottom view, with wiring to pogo pins:

        2017-10-14 12.34.19.jpg

        The STL file and original model in Alibre format are attached.  Keep in mind that I set the dimensions to make it work with my own 3D printer and the fit may require tweaking on yours.

         

        It's no substitute for a proper in-circuit programming setup for production, but it's handy for prototyping and I figured I'd share it here in case anyone else needs such a gadget.

         

        Scott

      • Setting BLE characteristic values – a Thunderboard Sense practical approach

        m_dobrea | 07/191/2017 | 02:45 AM

             Few months ago, I received a Thunderboard Sense kit from Silicon Labs Company. Analyzing the market for applications capable of working with this device, I noticed the existence of many applications capable of running on operating systems such as iOS, Android or Linux. But, I have not found a professional application, developed in Windows, able to work with this device. As a result, I decide to develop one - BLE SensorTags application.

             Right now, the BLE (Bluetooth Low Energy) SensorTag application – BlessTags (BLE SensorTags) can work with 2 different sensor tags from Silicon Labs Company: Thunderboard React and Thunderboard Sense.

             The BlessTags (BLE SensorTags) application has the following functionalities:

        1. To set, communicate, use and display (in graphic and numerical form) the information from all the sensors included on the SensorTags presented above. The supported sensor’s characteristics are:
          • For ThunderBoard React: accelerometer, orientation, temperature, humidity, light (ambient & UV), keys and output LEDs. 
          • For ThunderBoard Sense: accelerometer, orientation, barometer, temperature, humidity, air quality (CO2 & TVOC), light (ambient & UV), sound level, keys and output LEDs (2 x low power LEDs & 4 x power LEDs).
        2. In the developer mode the software provides the user with lots of messages obtained from the communication process with a specific SensorTag - these messages enable the user to identify the communication/configuration setbacks and some other problems.
        3. The software also gives the possibility to interrogate different types of unknown BLE devices - to be able to obtain the complete GATT attribute table for the unknown BLE device. At this link is presented the entire procedure used by me to obtain the complete GATT table for Thunderboard Sense and in the end a pdf file containing all the obtained results.
        4. To obtain and tune the optimal Kalman filter parameters;
        5. ... and the most exciting features: the gadgets. The gadgets are several practical applications that use one or more sensors from the SensorTag to achieve a concrete, fully functional and useful application. For instance, using the two buttons placed on Thunderboard React or Thunderboard Sense, these SensorTags are turning into wireless presenters for PowerPoint.

             For the development of the application I used: (a) intensively the documentation provided by Microsoft and (b) the source code (BluetoothLowEnergy.cpp) developed by Donald Ness and publicly offered at this address: https://gist.github.com/programmarchy/c9d02e22d58bfab3f8bb.

             The following code sequence, developed entirely by me, will complete the program provided by Mr. Donald Ness. With this code addition, we will not only be able to read data from the descriptors of a characteristic, but we will be able also to write characteristic values - in this way we can influence the state of the SensorTag.

             To exemplify the concepts of writing to a characteristic of a sensor, I will customize the code to be presented for the Profile User Interface service; service with the UUID: FCB89C40-C600-59F3-7DC3-5ECE444A401B. All the characteristics of this service (Profile User Interface service) are presented in the figure below. We, in this presentation, will focus only on the 0xC603 characteristic – UUID: FCB89C40-C603-59F3-7DC3-5ECE444A401B. This characteristic allow us to control the intensity and the color of the high brightness RGB LEDs placed on the SensorTag.

         

        Serviciu_C600.jpg

         

             In order to work correctly, the code below must be inserted after the code sequence from the Step 3, presented in ConnectBLEDevice() function, from the BluetoothLowEnergy.cpp file.  At this point and for the 0xC600 service pCharBuffer is a buffer with 4 elements. Each element stores a data structure related with one of the each of the 4 characteristics presented in the table above (UUID1: FCB89C40-C601-59F3-7DC3-5ECE444A401B, UUID2: FCB89C40-C602-59F3-7DC3-5ECE444A401B, UUID3: FCB89C40-C603-59F3-7DC3-5ECE444A401B and UUID4: FCB89C40-C604-59F3-7DC3-5ECE444A401B).

         

        PBTH_LE_GATT_CHARACTERISTIC pCharBuffer   = NULL;
        PBTH_LE_GATT_CHARACTERISTIC currGattCharTB;
        
        ……..
        
        if (pCharBuffer == NULL)	//step A				
        	{
        	free(pServiceBuffer);	pServiceBuffer = NULL; 		//free the service buffer
        	CloseHandle (hLEDevice); 				//close the BLE device handle
        	return -4;
        	}
        
        if (numChars > 4)		//step B				
        	{				//error we have more than 4 characteristics
        	free (pCharBuffer);	pCharBuffer = NULL; 		//free the characteristics buffer
        	free (pServiceBuffer); 	pServiceBuffer = NULL;		//free the service buffer
        	CloseHandle (hLEDevice); 				//close the BLE device handle
        	return -5;
        	}	
        
        //Get the specific characteristic from where the high brightness RGB LEDs can be controlled.
        //Here only the first 48 bits were checked - FCB89C40-C603-59F3-7DC3-5ECE444A401B – in
        //   order to identify this specific characteristic.
        currGattCharTB = NULL;		//step C
        for (i = 0; i< numChars; i++)
        	if (pCharBuffer[i].CharacteristicUuid.IsShortUuid == 0)
        		if (pCharBuffer[i].CharacteristicUuid.Value.LongUuid.Data1 == 0xFCB89C40 &&
        		     pCharBuffer[i].CharacteristicUuid.Value.LongUuid.Data2 == 0xC603)
        		    {
        currGattCharTB = &pCharBuffer[i]; break; } if (currGattCharTB == NULL) //step D { // if no such characteristic can be found: free all the data structures and return free (pCharBuffer); pCharBuffer = NULL; free(pServiceBuffer); pServiceBuffer = NULL; CloseHandle (hLEDevice); return -6; } typedef union //step E { BTH_LE_GATT_CHARACTERISTIC_VALUE newValue; struct { ULONG DataSize; UCHAR Data[4]; } myValue; } rezolvare; //step F rezolvare newValue_base; RtlZeroMemory(&newValue_base.newValue, ( sizeof(rezolvare) )); //step G //fill the structure with the required data newValue_base.newValue.DataSize = sizeof (UCHAR)*4; newValue_base.myValue.Data[0] = comLED; //which LEDs will be on newValue_base.myValue.Data[1] = valR; //red level [0, 255] newValue_base.myValue.Data[2] = valG; //green level [0, 255] newValue_base.myValue.Data[3] = valB; //blue level [0, 255] //step H hr = BluetoothGATTSetCharacteristicValue( hLEDevice, currGattCharTB, &newValue_base.newValue, 0, BLUETOOTH_GATT_FLAG_NONE); //step I if (S_OK != hr) { if (dbgMode) { InsertTextBoxLine (panelHandleDbg, PANEL_Dbg_TEXTBOX, -1, "Error at: BluetoothGATTSetDescriptorValue - impossible to set the I/O lines (LEDs) !"); HRESULTtoErrTxt (hr, buffErr); sprintf (buffDeAfisat, " - %s", buffErr); InsertTextBoxLine (panelHandleDbg, PANEL_Dbg_TEXTBOX, -1, buffDeAfisat); } free (pCharBuffer); pCharBuffer = NULL; free (pServiceBuffer); pServiceBuffer = NULL; CloseHandle (hLEDevice); return -4; } //step J //all is OK now and release all resources previously used free (pCharBuffer); pCharBuffer = NULL; free (pServiceBuffer); pServiceBuffer = NULL; CloseHandle (hLEDevice);

             The first 2 “if” instances (steps A and B) check the correctness of the service data in accordance with our previous knowledge related to this service. If everything is correct, we go to identifying the specific characteristic capable to influences the state of the LEDs – step C, this is done in the “for” loop.

             In D step, the software check if this specific characteristic (0xC603) was found. If this last test is passed, now we can dispatch data to the SensorTag via BluetoothGATTSetCharacteristicValue function - step H. But to do this a new data structure is defined, step E, a new variable (of this data specific type) is declared and initialized with 0, on the step F, and, in the end, the variable is initialized with the required data – step G.

             Analyzing steps E, F, G and H, one could say that a simpler approach can be easily found.  Yes, it is true, but this approach is perfectly functional for a compiler that would support a development in C++ (like Visual Studio). The BlessTags application has been fully developed in LabVindows/CVI, which has a compiler that only supports ANSI C. And for this compiler this was the only functional solution found up to now.

             Going further, if errors occur in the SensorTag communication process, they are treated in step I. At the end, all data structures used are released, step J.

             For the correct operation of the previous code, make sure the device is powered from the USB port, otherwise the RGB LEDS will be disabled by the Thunderboard Sense to conserve the power from the coin cell battery.

             And now a video to show BlessTags main functions:

         

         

             This application, BlessTags (BLE SensorTags) application, can be downloaded from the Windows Store Apps: https://www.microsoft.com/store/apps/9p054xsjjr1n. For more information, demo, practical applications, examples etc. please visit the following blog: https://ble-sensortag.blogspot.ro.

         

      • Sensor node network with Thunderboard Sense and MicroPython

        ThomasFK | 04/92/2017 | 04:04 PM

        I am a member of NUTS, the NTNU Student Test Satellite. The main goal is to create a CubeSat, a tiny satellite that piggybacks on the launch of a larger satellite.

         

        Another goal of NUTS is trying to promote aerospace/STEM topics among other students. Last fall we participated in "Researchers Night" at NTNU, which is used to promote STEM education among high school students. A lot of institutes and organizations show up at Researchers Night with really flashy displays, such as flamethrowers or slightly violent chemical reactions.

         

        At our disposal we had a vacuum chamber, a DC-motor, space-grade and regular solar panels, and several Thunderboard Senses. Showing off how marshmallows behave in vacuum, and how the DC motor behaves when connected to the different solar panels might be interesting enough in and of itself. However we decided to add some Thunderboards to spice it up a bit.

        Using a budding implementation of MicroPython for Thunderboard Sense (which will be released soon), we brainstormed and programmed a small sensor network for our stand, simulating logging telemetry data from our satellite. The Thunderboards were utilized as follows:

        • Glued to the DC motor, transmitting gyroscope data from the IMU.
        • Inside the vacuum chamber transmitting pressure.
        • Transmitting the light-level with the light-sensor.
        • Sampling the sound-level with the microphone.
        • A master that could tune into transmissions from either of the other Thunderboards, logging the output to screen and also showing how much the slave deviated from "normal" status by using the  RGB LEDs.

        I have embedded two video. The first one gives a short overview over the entire project, while the second shows the setup in action, logging data from the vacuum chamber.

         

        Our stand was a great success! Robot Very Happy We got several people standing around for up to half an hour discussing intricacies of satellite development as well as giving us an opportunity to talk more about the satellite radio link.

         

        At last I want to brag a bit about how neat this code turned out with MicroPython, and how MicroPython really was ideal for bringing up a project like this in such a short time.  The code for reading data from the IMU and transmitting it ended under 40 LOC.

        from tbsense import *
        from radio import *
        from math import sqrt
        
        rdio = Rail()
        i = IMU(gyro_scale = IMU.GYRO_SCALE_2000DPS, gyro_bw = IMU.GYRO_BW_12100HZ)
        
        def float_to_pkt(flt):
            integer = int(flt)
            decimal = round(flt, 3) - integer
            decimal = int(decimal*1000)
            ret = bytearray(6)
            ret[0] = (integer >> 24) & 0xFF
            ret[1] = (integer >> 16) & 0xFF
            ret[2] = (integer >> 8)  & 0xFF
            ret[3] = integer & 0xFF
            ret[4] = (decimal >> 8) & 0xFF
            ret[5] = decimal & 0xFF
            return ret
        
        def loop():
            meas = i.gyro_measurement()
            meas = sqrt((meas[0]**2)+(meas[1]**2)+(meas[2]**2))
            pkt = float_to_pkt(meas)
            rdio.tx(pkt)
            delay(200)
            
        def init():
            rdio.init()
            rdio.channel(MODE_IMU)
            i.init()
        
        delay(2000)
        init()
        while True:
            loop()

         

         

      • Thunderboard Sense with Raspberry Pi and Python

        DDB | 03/67/2017 | 08:16 PM

        The goal of this project was to make a very simple python script that runs on a Raspberry Pi and collects data from one or more Thunderboard Sense devices, using the same Google Firebase backend and web application that the official app uses.

         

        To get started, go to https://github.com/siliconlabs/thundercloud, and clone the repository. Follow the instructions and set up a firebase account and project, replacing the database name in src/main.js as instructed. For this example, I have not yet gotten authentication working, so change the database.rules.json for now to allow anyone to write (basically replacing "auth.uid === 'YsGcsiI8hkwjImSrr25uZdqlNw3Qkgi8vUWx9MU6'": with "true")

         

        {
          "rules": {
            ".read": false,
            ".write": false,
            "thunderboard":{
              ".read": true,
              ".write": true
            },
            "topCharts":{
              ".read": true,
              ".write": true
            },
            "sessions":{
              ".write": true,
              ".indexOn": ["startTime", "contactInfo/deviceName"],
              "$session":{//2592000000 is 30 days
                ".read": "data.child('startTime').val() > (now - 2992000000)",
                ".write":  true
              }
            }
          }
        }

         

        Now, deploy the app to Firebase using the firebase tools

         

         

        sudo npm install -g firebase
        firebase login
        firebase deploy --project <your firebase project id>

         

        In the Firebase console you should now see your deployed rules, as well as the application url. Following the URL should bring you to the default page:

        Screenshot 2017-03-09 01.35.43.png

        Now the next step is to log onto the Raspberry Pi, and install the necessary tools. The script uses bluepy to communicate with the sensor, and python-firebase to push data to the cloud. I did have some trouble installing python-firebase because of the specific version of the requests library, but eventually got it installed.

         

        Remember to put in your own database URL in the thundercloud.py script:

        from firebase import firebase
        import uuid
        import time
        
        class Thundercloud:
        
           def __init__(self):
        
              self.addr     = 'https://-- Your database URL --.firebaseio.com/'
              self.firebase = firebase.FirebaseApplication(self.addr, None)

         

        The tbsense_scan.py script continuously looks for advertising thunderboards, and automatically connects to the board if a new one is discovered.

         

        $ sudo python3 tbsense_scan.py 
        No Thunderboard Sense devices found!
        No Thunderboard Sense devices found!
        Starting thread <Thread(Thread-1, initial)> for 37020
        
        Thunder Sense #37020
        Ambient Light:	0.25 Lux
        Sound Level:	37.83
        tVOC:		0
        Humidity:	28.25 %RH
        Temperature:	29.86 C
        Pressure:	951.586
        UV Index:	0
        eCO2:		0
        

        When a Thunderboard Sense has been discovered and connected to, the script will print out the read data periodically. Take note of the number in "Thunder Sense #37020". We will need to give the number to the web application.

         

        The script generates a session ID for each board connected, and then continuously generates json strings for the data read from the Thunderboard Sense. The json string is then inserted into the appropriate location in the database. Firebase has a useful live database view that shows us that our data is indeed being pushed into the cloud:

        Screenshot 2017-03-09 01.20.16.png

        Finally if you go to the app url and append your Thunderboard Sense id, you should see the data being displayed https://<project id>.firebaseapp.com/#/37020

        Screenshot 2017-03-09 01.19.34.png

         Screenshot 2017-03-09 01.19.47.png

         tbsense.py simply discovers and sets up handles to the different characteristics. It also contains functions to read these characteristics:

         

         

        from bluepy.btle import *
        import struct
        from time import sleep
        
        class Thunderboard:
        
           def __init__(self, dev):
              self.dev  = dev
              self.char = dict()
              self.name = ''
              self.session = ''
              self.coinCell = False
        
              # Get device name and characteristics
        
              scanData = dev.getScanData()
        
              for (adtype, desc, value) in scanData:
                 if (desc == 'Complete Local Name'):
                    self.name = value
        
              ble_service = Peripheral()
              ble_service.connect(dev.addr, dev.addrType)
              characteristics = ble_service.getCharacteristics()
        
              for k in characteristics:
                 if k.uuid == '2a6e':
                    self.char['temperature'] = k
                    
                 elif k.uuid == '2a6f':
                    self.char['humidity'] = k
                    
                 elif k.uuid == '2a76':
                    self.char['uvIndex'] = k
                    
                 elif k.uuid == '2a6d':
                    self.char['pressure'] = k
                    
                 elif k.uuid == 'c8546913-bfd9-45eb-8dde-9f8754f4a32e':
                    self.char['ambientLight'] = k
        
                 elif k.uuid == 'c8546913-bf02-45eb-8dde-9f8754f4a32e':
                    self.char['sound'] = k
        
                 elif k.uuid == 'efd658ae-c401-ef33-76e7-91b00019103b':
                    self.char['co2'] = k
        
                 elif k.uuid == 'efd658ae-c402-ef33-76e7-91b00019103b':
                    self.char['voc'] = k
        
                 elif k.uuid == 'ec61a454-ed01-a5e8-b8f9-de9ec026ec51':
                    self.char['power_source_type'] = k
        
           
           def readTemperature(self):
              value = self.char['temperature'].read()
              value = struct.unpack('<H', value)
              value = value[0] / 100
              return value
        
           def readHumidity(self):
              value = self.char['humidity'].read()
              value = struct.unpack('<H', value)
              value = value[0] / 100
              return value
        
           def readAmbientLight(self):
              value = self.char['ambientLight'].read()
              value = struct.unpack('<L', value)
              value = value[0] / 100
              return value
        
           def readUvIndex(self):
              value = self.char['uvIndex'].read()
              value = ord(value)
              return value
        
           def readCo2(self):
              value = self.char['co2'].read()
              value = struct.unpack('<h', value)
              value = value[0]
              return value
        
           def readVoc(self):
              value = self.char['voc'].read()
              value = struct.unpack('<h', value)
              value = value[0]
              return value
        
           def readSound(self):
              value = self.char['sound'].read()
              value = struct.unpack('<h', value)
              value = value[0] / 100
              return value
        
           def readPressure(self):
              value = self.char['pressure'].read()
              value = struct.unpack('<L', value)
              value = value[0] / 1000
              return value
        

         

         

        thundercloud.py handles the connection to the Firebase database. getSession() generates a new session ID and is called once for every new Thunderboard Sense connection. putEnvironmentData() inserts the data and updates the timestamps:

         

         

        from firebase import firebase
        import uuid
        import time
        
        class Thundercloud:
        
           def __init__(self):
        
              self.addr     = 'https://'-- Firebase Database Name --'.firebaseio.com/'
              self.firebase = firebase.FirebaseApplication(self.addr, None)
        
           def getSession(self, deviceId):
        
              timestamp = int(time.time() * 1000)
              guid = str(uuid.uuid1())
        
              url = 'thunderboard/{}/sessions'.format(deviceId)
              self.firebase.put(url, timestamp, guid)
        
              
              d = {
                    "startTime" : timestamp,
                    "endTime" : timestamp,
                    "shortURL": '',
                    "contactInfo" : {
                         "fullName":"First and last name",
                         "phoneNumber":"12345678",
                         "emailAddress":"name@example.com",
                         "title":"",
                         "deviceName": 'Thunderboard #{}'.format(deviceId)
                     },
                     "temperatureUnits" : 0,
                     "measurementUnits" : 0,
                 }
        
              url = 'sessions'
              self.firebase.put(url, guid, d)
        
              return guid
        
           def putEnvironmentData(self, guid, data):
        
              timestamp = int(time.time() * 1000)
              url = 'sessions/{}/environment/data'.format(guid)
              self.firebase.put(url, timestamp, data)
        
              url = 'sessions/{}'.format(guid)
              self.firebase.put(url, 'endTime', timestamp)
        

         

        Finally, tbsense_scan.py continuously searches for new Thunderboard Sense devices, and spawns a new thread for each one successfully connected to:

         

        from bluepy.btle import *
        import struct
        from time import sleep
        from tbsense import Thunderboard
        from thundercloud import Thundercloud
        import threading
        
        def getThunderboards():
            scanner = Scanner(0)
            devices = scanner.scan(3)
            tbsense = dict()
            for dev in devices:
                scanData = dev.getScanData()
                for (adtype, desc, value) in scanData:
                    if desc == 'Complete Local Name':
                        if 'Thunder Sense #' in value:
                            deviceId = int(value.split('#')[-1])
                            tbsense[deviceId] = Thunderboard(dev)
        
            return tbsense
        
        def sensorLoop(fb, tb, devId):
        
            session = fb.getSession(devId)
            tb.session = session
            
            value = tb.char['power_source_type'].read()
            if ord(value) == 0x04:
                tb.coinCell = True
        
            while True:
        
                text = ''
        
                text += '\n' + tb.name + '\n'
                data = dict()
        
                try:
        
                    for key in tb.char.keys():
                        if key == 'temperature':
                                data['temperature'] = tb.readTemperature()
                                text += 'Temperature:\t{} C\n'.format(data['temperature'])
        
                        elif key == 'humidity':
                            data['humidity'] = tb.readHumidity()
                            text += 'Humidity:\t{} %RH\n'.format(data['humidity'])
        
                        elif key == 'ambientLight':
                            data['ambientLight'] = tb.readAmbientLight()
                            text += 'Ambient Light:\t{} Lux\n'.format(data['ambientLight'])
        
                        elif key == 'uvIndex':
                            data['uvIndex'] = tb.readUvIndex()
                            text += 'UV Index:\t{}\n'.format(data['uvIndex'])
        
                        elif key == 'co2' and tb.coinCell == False:
                            data['co2'] = tb.readCo2()
                            text += 'eCO2:\t\t{}\n'.format(data['co2'])
        
                        elif key == 'voc' and tb.coinCell == False:
                            data['voc'] = tb.readVoc()
                            text += 'tVOC:\t\t{}\n'.format(data['voc'])
        
                        elif key == 'sound':
                            data['sound'] = tb.readSound()
                            text += 'Sound Level:\t{}\n'.format(data['sound'])
        
                        elif key == 'pressure':
                            data['pressure'] = tb.readPressure()
                            text += 'Pressure:\t{}\n'.format(data['pressure'])
        
                except:
                    return
        
                print(text)
                fb.putEnvironmentData(session, data)
                sleep(1)
        
        
        def dataLoop(fb, thunderboards):
            threads = []
            for devId, tb in thunderboards.items():
                t = threading.Thread(target=sensorLoop, args=(fb, tb, devId))
                threads.append(t)
                print('Starting thread {} for {}'.format(t, devId))
                t.start()
        
        
        if __name__ == '__main__':
            
            fb = Thundercloud()
        
            while True:
                thunderboards = getThunderboards()
                if len(thunderboards) == 0:
                    print("No Thunderboard Sense devices found!")
                else:
                    dataLoop(fb, thunderboards)
        

         

      • Big red button on Thunderboard Sense and Samsung Artik 5

        DanilBorchevkin | 01/31/2017 | 07:19 PM

        As a weekend project, I decided to select an implementation of a big red button based on Thunderboard Sense and Samsung Artik 5. Why a big red button? Because everybody likes red buttons. About it even make films (The Box, 2009).

         

        Sorry for any possible mistakes - I am not a native English speaker/writer. By the way this article there is in russian language.

         

        What is needed for the project

         

        1. Big red button - for this all was conceived. The button should to be normally open
        2. Thunderboard Sense Kit
        3. Samsung Artik 5
        4. Seeed Studio Arduino Base Shield
        5. Seeed Studio Grove Buzzer

         

         

        Setup Thunderboard Sense

         

        Fortunately, we do not need to change anything in the code of the Thunderboard Sense, otherwise it would become a headache - Bluetooth SDK to this device requires an IAR ARM 7.80 compiler, that for many would be a big problem.

         

        As an actuator will act SW1 button - on this button will be tied up all logic of own project.

         

         

        Default firmware do not need any changes because it have following logic:

        1. Board sleep in inactive state and can't accept incoming connections. For change it mode to connectable mode need to push SW1.
        2. After push on SW1 green led start blink there is a possibility for connect to it.
        3. When disconnect is happened Thunderboard Sense again going to sleep.

        Thunderboard Sense provides various BLE services and characteristics (full list available in Android App repository). For us interested only one characteristic - CHARACTERISTIC_PUSH_BUTTONS, which have UUID fcb89c40-c601-59f3-7dc3-5ece444a401b and constist from one value uint8_t, with following states:

        1. Zero (=0) if no buttons was pressed;
        2. One (=1) if SW1 was pressed;
        3. Two (=2) if SW2 was pressed;
        4. Three (=3) if was pressed both SW1 and SW2;

        It is noteworthy that this characteristic has only read property which leads us to the solution of a periodic value reading.

         

        Setup Artik 5

        If it a first-time work with Artik 5 then you need to basic setup according to Quick Start Guide. For start developing you should upgrade to latest firmware and setup internet connection.

         

        Pre-installed packet manager for OS Fedora on Artik is dnf so all following instructions will be for it.

         

        First install all software needed for Bluetooth:

         

        dnf install bluez bluez-libs bluez-libs-devel

        Besides install Git:

        dnf install git

        Futher install Node.JS and npm:

        dnf install nodejs npm

        After this we need to install main module for work with BLE - noble - this module allows to serve BLE connections in case when controller have to do a central role.(for inverse situation there is the bleno module):

        npm install noble

        Now we ready for coding!

         

        Pairing

         

        For pairing devices we need to use the interactive util bluetoothctl. First start it:

         

        bluetoothctl

        After starting we need to switch on a pairing possibility:

         

        pairable on

        Then we should activate Thunderboard sense by pressing on SW1 and start scanning:

         

        scan on

        Target device we can determine by friendly name or by address.

         

         

        When the needed device is finding we should stop the scanning:

        scan off

        The most important for us - remember the address of own Thunderboard Sense and execute following commands:

        pair 00:0B:57:36:71:82
        trust 00:0B:57:36:71:82
        connect 00:0B:57:36:71:82

        At this stage we get message "Connection successful" and now we can request information about connected device:

        info 00:0B:57:36:71:82

        Output will be similar to my:

         

         

        Now input:

        exit

        and ... we ready to write code on Node.JS!

         

        Work with Bluetooth on Artik 5

         

        noble allows develop code for central device. So we have to implement following logic for work with Thunderboard Sense:

        1. Scanning for finding connectable Thunderboard Sense.
        2. Connect to device with a known address.
        3. Gettings lists of services and characteristics.
        4. Read the buttons characteristic's value.

        If you need only working code - go to https://bitbucket.org/sithings/app_thunderboardtoartik

         

        For start scanning we must make sure that Bluetooth controller is power up and only after that we can start scanning:

        /* Event of the state change of the BLE controller on board */
        noble.on('stateChange', function(state) {
        	if (state === "poweredOn") {
        		/*
        		 * If BLE normally started start scanning with duplicates with any UUIDs services
        		 */
        		console.log("\x1b[36m", "\nBLE is poweredOn. Start scanning", "\x1b[0m");
        		noble.startScanning([], false);
        	} else {
        		console.log("\nStopScanning. Status is %s", state);
        		noble.stopScanning();
        	}
        });

        After start scanning we must push SW1 on the Thunderboard Sense for wake up it. Once the device will be available script will be attempt connect to it:

        noble.on("discover", function(peripheral) {
        	
                ...
        
        	/* If founded device is own big red button */
        	if(config.bigRedButton.deviceAddress === peripheral.address) {
        		peripheral.connect( function(error) {
                        
                        ...
        
        		});
        	}
        });

        After successful connect we need to get all services and characteristics:

        peripheral.connect( function(error) {
        	peripheral.discoverAllServicesAndCharacteristics(function(error, services, characteristics) {
        		...
        	});

        In my code I define the desired characteristic by enumeration method:

         

        for(i = 0; i < characteristics.length; i++) {
        	/* If we find characteristic with button state when color it */
        	if (characteristics[i].uuid === config.bigRedButton.characteristicUUID) {
        		buttonStateChar = characteristics[i];
        	}
        	...

        Desired characteristic which contaits value with button state have only one property - read. For acquiring button states we need implement peridical reading of desired value. Afrter define the desired characteristic we need to set a polling interval.

         

        readingInterval = setInterval(readButtonCallback, config.bigRedButton.pollingInterval);

        Listing of the callback:

         

        /* Button callback started by setInterval */
        function readButtonCallback() {
        	buttonStateChar.read(function(error, data) {
        		buf = data[0];
        		console.log("\nData: %d", buf);
        		if (buf === 1) {
        			console.log("SW1 was pressed");
        			/* Enable buzzer */
        			config.buzzer.set();
        		}
        		else if (buf === 2) {
        			console.log("SW2 was pressed");
        		}
        		else if (buf === 0) {
        			console.log("No button pressed");
        			/* Disable buzzer */
        			config.buzzer.clear();
        		} 
        	});
        }

         

        Make buzz

         

        Unfortunately, I could not get to work with GPIO over artik-sdk module and I decided work with GPIO over sysfs. Grove Buzzer in my solution connected over Seeed Studio Base shield to pin gpio121 (2 pin of Arduino expansion).

         

        After starting the script a desired pin must to init as "out":

         

        exec("echo 121 > /sys/class/gpio/export");
        exec('echo "out" > /sys/class/gpio/gpio121/direction');

        To buzzer squeaked the pin must be pulled up:

         

        exec('echo "1" > /sys/class/gpio/gpio121/value');

        To silence buzzer the pin must be pulled down:

         

        exec('echo "0" > /sys/class/gpio/gpio121/value');

        Then exiting the script the buzzer's pins must be released:

         

        exec("121 > /sys/class/gpio/unexport");

        All of this was implemented in config.js of the project. Link to repository.

         

        Connect big red button to Thunderboard Sense.

         

        I have this kind of the button:

         

         

        Interesting fact - the button is more expensive than Thunderboard Sense Kit.

         

        Connect the button by soldering as described on a following scheme:

         

         

        In my case, it looks like this:

         

         

        Testing

         

        Video with test:

         

         

         

         

        But it isn't serous because buzzer too weak. I change the buzzer to relay with signal lamp:

         

         

         

         

        Now the big red button is really cool!

         

        Results

         

        It works. Repository with project - https://bitbucket.org/sithings/app_thunderboardtoartik

         

        Links

         

      • Thunderboard Sense - a review and some experiments

        hlipka | 01/24/2017 | 05:25 PM

        Thanks to the generous folks at Silicon labs, two months ago I found a package containing a Thunderboard Sense at my doorstep. Many thanks for giving me the chance to review this board! (And a big sorry I didn't finish this review sooner)

         

        Small Introduction
        This wasn't the first board from Silabs that I got to see, but it was the first one to come in a different package size. My first thought was "**bleep**, that thing is small!"
        Nice touch: this was the first Silabs (or Energy Micro) board that came in a smaller packaging, which makes sense since it really is just the size of 2 CR2032 cells (OK, just a little bit bigger). Although the parcel it came in was way too big as usual Robot Sad

        I applied for this review since when I saw this board I had immediately three different applications in mind:

        • run this as a small weather station on top of our house
        • use this as head-impact monitor during skiing
        • monitor the heating system for our house for function and gas leakage

        Given the number of sensors on this board it seams quite natural to use it to monitor environmental conditions. It would be quite interesting to add a large battery and a solar panel and then mount it on the top of our house (there is already a satellite antenna beam there) so I get my own weather station. It would need a clear side wall to measure ambient light, and some holes so it can measure humidity. Most sensible would be the usage of a radiation shield (such as these). But since its winter here in Europe this doesn't look like an inviting project at the moment...


        Skiing is more interesting. Two years ago I create the "Skier impact monitor" (SkiMon for short) for an Element14 challenge. SkiMon was designed so I could track the effects to the head whenever my son (who started downhill skiing back then) would tumble or hit something.
        The Sense Board would add a Gyro sensor to the mix, and have them together with the acceleration monitor and the BLE chip on one small board. This means it could be even smaller than my original solution. I had this in mind for the Thunderboard React board already, but this doesn't come with programming capabilities on board, so it was difficult there. For this project you really need to program the BLE chip, since you need to gather data with a high frequency (about 1000 samples per second) to aggregate them together and calculate the effects of any impact (see this posting about the Head Injury Criterion). Unfortunately there are two road blocks for this project: First I need to change the firmware to do all the calculations, and development requires an IAR embedded workbench license (more to that further down). Second the acceleration sensor must be able to handle high impact forces (a hard impact can easily reach 100g for some short moments). And  the ICM-20648 can only handle 16g. Bummer Robot Sad (I still do know only about three chips from Analog Devices which can handle such forces - back then I used the ADXL375).


        This leaves the heating system monitor project. The idea for this also came from a skiing vacation - some years ago the heating system went down while we were skiing. And since there were -20°C outside the house was just above the freezing point when we came back. Since then I have a mbed board running which pushes the current temperature of one room to the cloud so I can look for problems. It would be nice to have a solution in place which is much smaller, and also alerts me (by short message or email). Since I already have an OpenHAB server running, this would be a perfect integration. And the air quality sensors can tell me when something else is wrong. So I went out to see how well the Sense board works as environmental sensor.

         

        Having a deeper look
        As I said already - the Thunderboard Sense is much smaller than the other Silabs (or EnergyMicro) boards (apart from its sibling, the Thunderboard React). Both are about 45x30mm - as a comparison you could fit two CR2032 cells on them.
        While the React board comes just with a motion sensor (acceleration and rotation) and a temperature+humidity+light sensor, the Sense kit (as the name implies) packs much more sensors to the board:

        • acceleration and rotation
        • humidity and temperature
        • ambient light (and UV index)
        • air pressure
        • audio (MEMS microphone)
        • indoor air quality
        • (there is a hall-effect sensor mentioned, but its not populated on my board)


        All of these do fit on such a small board, together with

         

        • a CR2032 cell
        • a Bluetooth LE SoC with antenna
        • a debugging interface (JLink - how did they manage to fit that on this board too?)
        • 4 RGB LEDs
        • and two push buttons


        This is quite a powerful package! Unfortunately it also means the board is so densely packaged that there is no real silk screen designating the components (the are no numbers for the IC on board). Fortunately all of the sensors are accompanied by small images showing their function (although it took me a while to discover this - the gold-coloured silk screen is quite unobtrusive).

        So after inspecting the board, the first step was to download the Thunderboard app. Since I have a set of devices, I tested on a range of them. I used my iPad Air for iOS, and my Nexus 5 for Android. Since I was not able to connect the Thunderboard React to the Nexus 5 when I played with this board, I also took my old Samsung S4 mini from its archiving box (just to be see whether it fared better). Download was easy, and I was able to connect with all three devices. So the next step is playing around with the app and taking measurements.

         

        The Thunderboard app comes with multiple pages which can be select from the start screen (after connecting to the board). The Motion page shows the accelerometer / gyro data (even in 3D Robot Happy, the Environment page all the sensor data, and IO allows to control the LEDs on the board. When looking at the sensor data, its possible to stream all data to the cloud (Thundercloud, that is) so you can get historical data and nice graphs.

         

        Time for some measurements
        The temperature seemed to be a bit on the high side - it showed 28.5°C where my other thermometers show only 27° (and they agree mostly). But it settled down after while, so maybe this was me handling the board. (The Sense board itself was in my room for several hours before testing so it should be settled). So this seems to be fine (and probably still within spec of all sensors involved).

        Since I was in my study, I looked at workplace lighting (hey, there is a ambient light sensor in this thing, why shouldn't I use it?). After finding out how to orient the board properly (look for the small silk screen symbols for the sensors) it showed that my work desk has about 740 Lux, and with an additional direct light it goes up to 1200 Lux. According to this report this is more than sufficient. But OTOH the air in my room is too dry (its a typical winter problem).

        Next test was looking at the microphone. I originally ignored this sensor, but the Thunderboard app uses it to show the ambient noise level. And since I have a 3D printer right beneath my desk, it was interesting to see how loud it really gets. The app showed between 43 and 50db when the printer was idle (this is due to the fans), and depended a little bit on the orientation of the board. So I put it in a fixed spot right at the printers base plate (its mounted on a wooden board). When running, the noise goes up to 60db with spikes up to 67db. Interestingly the noise level didn't account for mechanical vibrations at lower frequencies which (at least to my subjective feeling) are even louder. Either the microphone cannot handle them or they are filtered by the boards firmware somehow. As a comparison: the noise floor in my study is at about 38db with just my (nearly silent) PC running and the windows closed. This is quite OK, and the printer seems to be at an acceptable level.

        While doing these test prints I also looked at the air quality. I'm printing with PLA so there shouldn't be a problem, but its always better to verify Robot Happy The air quality sensor needs some start-up time, even though it shows up in the app after about 30 seconds or so. Carbon Dioxide level was at 400ppm when I started (which is nearly outside air quality - I was venting the room before), and the VOC level was at 0ppb (which seemed strange). During printing the VOC rose to 3ppb, and CO2 stayed constant. Unfortunately I did not find any actual data which VOCs the sensors measures. And all the documents I found about air quality differed in the recommended threshold levels because they looked at different kinds of VOCs. But 3ppb should fine according to all of them...

        For acceleration and rotation I did not make tests since I looked at them with the React board already (although I need to write the review for that too, shame on me). The biggest drawback I see here is that there are not enough measurements sent from the board to the app, so any graphs you make are not fine enough in their time resolution.

        And I also did not look at the air pressure - I have nothing to compare it to, and on its own it is not really interesting. I just assume that it will work properly, like the rest of the board does.

        I did experiment with the LEDs a little bit, and can confirm that you can indeed control them from the app (provided that you power the board from USB and not via the coin cell).

        Unfortunately I did not have time to measure power consumption. One would either need a connector with 1.25mm pin pitch, or need to solder to the expansion connectors. But the Sense board uses an elaborate scheme to power all the sensors only when they are needed. This way it should keep the overall power consumption quite low, especially when the sensors are needed only once in a while.

         

        How to monitor a heating system
        My next test was to see how well I can use the Thunderboard Sense (together with the app) to monitor my heating system. Its a gas heater (nearly 20 years old, but quite efficient for that time, and its build robust). I placed the board about 50 cm away and powered it by an USB supply. I also powered the S4 mini via USB (and disabled any standby function so it would run until disabled). Then I connected the board to the app, enabled cloud streaming (so I would get nice graphs) and went to work. Unfortunately I found out that the app stopped sending any data after about an hour and said it got disconnected from the board. When repeating this experiment, the app disconnected after 30 minutes. That's not nice! When I tested with my Nexus 5, it got disconnected even faster. I then tested again with the React board - it could not connect to that one either (as before). Then I switched to my iPad Air, and lo and behold, it was able to stream data to the cloud for as long as wanted it to (or at least could abstain from using it...). So it seems either Android has a general problem with BLE (which I cannot confirm from my own work with it) or its the Thunderboard Android app.

        So here is the graph I got from my experiments:

        environmental_data_heater

        Thundercloud allows you to download the captured data. For that I did send the link to the last data set from the app via email, opened it with m,y browser and from there one can the navigate and download. The CSV files can be opened with LibreOffice, and then I create a diagram showing what I need.

        Its interesting to see that the temperature curve is nearly flat. Even though the heating is configured to lower the temperature during the day by several degrees, the room with the heater stays at the same temperature. And the board was far away enough to not capture the heat from the actual flame.
        The VOC levels are interesting - I started my measurements in the morning, right after the heater was running for longer periods to get the water hot and the rooms warm. So there were plenty of VOCs around, but their level fell over the day (since the heater is running less frequently - its doesn't need to keep the water and the rooms that warm). The same can be seen with carbon dioxide, just not as pronounced. In the afternoon the heating started again, because its configured to heat up the rooms before we are back at home.

         

        Its interesting that there are large spikes of VOC and CO2 levels. Either the heater sometimes really produces these levels, or something peculiar happens with the air quality sensor. Unfortunately I was not able to find any data sheet for the CCS881 sensor, so I cannot dive deeper into that. (Its similar for the ICM-20648 - there is a data sheet but you need to sign an NDA for it...)

         

        Most surprising for me was that the microphone was a really good indicator whether the heater is running or not. The flame is loud enough to be picked up well enough that one can see the heating periods, and even the longer runs in the afternoon. I found that interesting, and would try to incorporate that into a monitoring solution.

        I later did run a test with the board nearer to the heater and the flame, and then the heating periods were more visible, but still not that much. It seems one needs a thermocouple really close, or an IR / thermopile sensor for that.

        So after all these tests I can say that the Thunderboard sense really is a nice board and very capable. The application support for Android seems to be sub-optimal for the moment, unfortunately. To create a real monitoring solution (or a weather station), one probably needs a BLE app running on a PC (or maybe a RaspBerry PI), and a customized firmware on the Sense board.

         

        Firmware development
        And this is then my last topic for this review: firmware development. In the past I did several projects and experiments with the EFM32 MCUs, and was quite spoiled by Simplicity Studio and all the support. I always found development easy and well-supported. This is especially true since I'm a long-time Linux used and do all my work there whenever possible. And Energy Micro, and also Silabs later on supported that well. But when I looked into the documentation for BLE development, the picture was completely different. For BLE development one needs an IAR embedded workbench license, since the precompiled BLE stack library only work with that. I can understand that the BLE stack is delivered as library (regulatory reasons most probably), but requiring a separate tool for working with it? IAR only runs on Windows, and they do not even state prices on their web site (but from what I found it seems to be several thousands of Euros).

        Fortunately after some swearing and spending time with Google I found two ways around that:
        First, there is work underway to  have the BLE stack compile with GCC (and so it should work with Simplicity Studio again). Its not officially released, but a preview is available from the knowledge base (and also see the discussion). Maybe in some months this can be a stable solution.

        The second solution is to use BGScript. I always thought that this is intended for the BlueGiga modules only, but the developers guide explains how to use it for other EFR32 chips too. You just need to know the correct EFR32 part number, and hand this to the BGScript compiler. So I tested this with one of the example BGScript firmwares (which converts implements the temperature sensor BLE profile), compiled it and uploaded it to the Sense board (via the "Flash Programmer" tool), and it appeared as a different BLE device now (and needs a different app). Evewn though I could connect fine to the board, the app could not read the temperature. The reason: its doesn't know about the power and interrupt controller of the Sense board, so the sensor is still disabled. So the biggest problem with using BGScript is that you cannot re-use the Sense board demo firmware to talk to all the sensors, but need to implement anything from scratch. And since for some of them no data sheets are available, this seems difficult.
        So it seems I should wait for the GCC BLE stack to be officially supported.
         

        Aftermath

        After playing around with programming I wanted to re-install the original firmware (to get some screenshots of the app for this review). It is only available when BLE stack 2.0.1 is installed (which is not  the newest version), and can be selected from the "Getting started" section of Studio. Unfortunately after doing only the S4 mini would find the board in the Thunderboard app. I suspect that the board initially came with a newer firmware which is not available in the BLE SDK (see the forum discussion). So it seems I really need to look into the development setup...

         

        Outlook

        So what's my verdict for this review? Thunderboard sense surely is a fine board, but the software support (especially for Android) needs some more work. Also, currently BLE development is only feasible right now if you are willing to invest some real money (at least for hobbyists and small companies) or willing to work with beta and preview versions (BGScript doesn't seems capable enough more my needs right now, but I need to have a deeper look into it).

        I surely will experiment with, and follow the state of the BLE stack GCC support. When it reaches a usable state I will come back and look at how to implement my own firmware. Only then I will decide whether it will end up on my roof or near the heater Robot Happy

         

      • Threading Christmas - Thunderboard Sense on Steroids

        Alf | 01/03/2017 | 07:16 AM

        This project is an upgrade of my previous project so not too much code will be included here. What I wanted to do was to take the Thunderboard Sense and create wireless Christmas tree lights. Luckily enough we have some silicone balls around here that fits a Thunderboard Sense and a double-A battery holder which is perfect for the purpose of creating electronic Christmas baubles. You can see the boards, the battery holders and the silicone balls in this workshop picture, taken on Christmas Eve:

        Thread - Workshop

         

        And here's a couple more workshop pictures:

        Thread - Christmas lights

        My dad installing the wires for holding the baubles on the tree (obligatory white shirt on Christmas Eve).

         

        Thread - W

        Several units getting finished soldering.

         

        Thread - Workshop

        Installing the electronics in the silicon cases.

         

        Thread - Christmas tree lights

        All the baubles ready for the tree.

         

        Thread - Christmas tree lights

        Getting help with putting them up.

         

        Thread - Christmas tree lights

        And the last two baubles. Of course they need to go on the exact same branch.

         

        The program have been updated slightly, the clients now poll at a one second interval instead of 10 which is done with this line of code:

        #define REPORT_PERIOD_MS (1 * MILLISECOND_TICKS_PER_SECOND)

         

        The server was also ported to a Thunderboard Sense so I can have a more sexy remote. It is now also possible to turn the lights off by pressing both buttons simultaneously, so the new halButtonIsr looks like this:

        void halButtonIsr(uint8_t button, uint8_t state)
        {
          // button: BUTTON0 BUTTON1
          // state:  BUTTTON_RELEASED BUTTON_PRESSED
          if(button == BUTTON0)
            buttonsPressed = (buttonsPressed & ~0x1) | (state << 0x0);
          else if(button == BUTTON1)
            buttonsPressed = (buttonsPressed & ~0x2) | (state << 0x1);
        
          if(buttonsPressed == 0x3)
          {
        	colorOff   = 0x1;
        	colorStep  = 0;
        	colorFixed = 0x1;
        	colorStepped = 0;
          }
          else if((button == BUTTON0) && (state == BUTTON_PRESSED))
          {
        	  colorOff   = 0;
        	  colorStep  = 0;
        	  colorFixed = 0x1;
          	  incrementColorIndex();
          }
          else if((button == BUTTON1) && (state == BUTTON_PRESSED))
          {
        	colorOff   = 0;
        	colorStep++;
        	colorFixed = 0;
        	colorStepped = 0;
          }
        
          //Setting server led
          if(!colorOff)
          {
            BOARD_rgbledEnable( true, 0xf );
            BOARD_rgbledSetColor(colorTableSine[colorIndex][0],
            					 colorTableSine[colorIndex][1],
            					 colorTableSine[colorIndex][2]);
            ledOn = 0x1;
          }
          else
          {
        	BOARD_rgbledEnable( true, 0xf );
        	BOARD_rgbledSetColor(0x80,
        	   					 0x80,
        	   					 0x80);
        	ledOn = 0x1;
          }
          colorHold = 0;
        }

         

        You can also see that the LED's of the server is lit up according to the new color. They are turned off again in the handler for GET-requests:

        void clientGetHandler(const EmberCoapMessage *request)
        {
          // Requests from clients are sent as CoAP GET requests to the "client/get"
          // URI.
        
          EmberCoapCode responseCode;
        
          if (state != ADVERTISE) {
            responseCode = EMBER_COAP_CODE_503_SERVICE_UNAVAILABLE;
          } else {
        	if (!colorFixed)
        	  incrementColorIndex();
        	else if (colorHold <= 5)
        	  colorHold++;
        
        	// Disabling server LED after a while
            if (ledOn && colorHold > 5)
        	{
        	  BOARD_rgbledEnable( false, 0xf );
        	  ledOn = 0x0;
        	}
        
        	coapmessage[0] = colorOff ? 0x0 : colorTableSine[colorIndex][0];
        	coapmessage[1] = colorOff ? 0x0 : colorTableSine[colorIndex][1];
        	coapmessage[2] = colorOff ? 0x0 : colorTableSine[colorIndex][2];
        
        	emberAfCorePrint("Sending %ld %ld %ld to client at ", coapmessage[0], coapmessage[1], coapmessage[2]);
            emberAfCoreDebugExec(emberAfPrintIpv6Address(&request->remoteAddress));
            emberAfCorePrintln("");
            responseCode = EMBER_COAP_CODE_205_CONTENT;
          }
        
          if (emberCoapIsSuccessResponse(responseCode)
              || request->localAddress.bytes[0] != 0xFF) { // not multicast
            emberCoapRespond(responseCode, coapmessage, 3); // Payload
          }
        }

        And that's it! Here's a video demonstrating the new features on our Christmas tree: