Pages

Saturday, October 11, 2014

RFduino / BLED112 / DS18B20 Temperature Demo

This is another simple temperature monitor.  It uses a DS18B20 sensor which is connected to the RFduino over a 1-Wire bus.  It also adds red and blue LEDs that supply status. 

The red LED blinks unless an error is detected at which time it turns on solid.  The blue LED turns on when a connection is made to the temperature monitor and blinks 5 times if a new temperature is detected.

Below is a mock up of the breadboard temperature monitor and a circuit diagram produced using the fritzing package.

TemperatureDS18B20Project_bb

TemperatureDS18B20Project_schem

If you don’t already have the OneWire library information on it can be found here on the Arduino site which directs you to Paul Stofffregen’s site.  To install download the zip file and then copy to your RFduino libraries directory.  On my system this directory is located at C:\Program Files (x86)\arduino-1.5.7\hardware\arduino\RFduino\libraries.  On your system this will be dependent on where your Arduino IDE with RFduino support is located.

The files for the DS18B20 demo are located here.  This demo uses the same windows program as the TMP007 demo which can be found here in the dhRFduino repository on GitHub.

The LEDs are controlled by setting that are located in the RFduinoBLE_onConnect and RFduinoBLE_onDisconnect routines.  These routines are called when a connection is established to the RFduino and when that connection is terminated.

RFduino / BLED112 / TMP007 Temperature Demo

I decided to build on the temperature example by adding an external sensor to the RFduino.  In keeping with the temperature theme I used a TMP007 temperature sensor from Adafruit.

To read the temperature from the TMP007 I used the TMP007 library from Adafruit. 

Remember when installing libraries to use with the RFduino you need to get them put in the right place in the Arduino tree.  On my system this directory is located at C:\Program Files (x86)\arduino-1.5.7\hardware\arduino\RFduino\libraries.  On your system this will be dependent on where your Arduino IDE with RFduino support is located.

The files for the TMP007 demo are here on GitHub in the dhRFduino repository.

The hardware setup for this demo is very simple.  The TMP007 and the RFduino are connected to power and ground and the SCL and SDA lines on the TMP007 are connected to SCL labeled GPIO5 and SDA labeled GPIO6 on the RFduino.

If this demo is run in DEBUG mode and the serial console is attached to the RFduino status messages will be logged when a connection is made to the RFduino, when the connection is disconnected, the temperature each time the sensor is red and when a new temperature value is detected.

Sunday, September 7, 2014

Accessing an RFduino using BLE GUI

I was asked how you would access the RFduino using the BLE GUI.  Below are step by step instructions that worked for me.

RFduino Setup

Open the Temperature example sketch in the Arduino IDE and compile and load the sketch.

Reading a Value from the RFduino

Run the BLE GUI software.  This can be done via the icon on the desktop or through the program menu.

When the software runs it will display a windows as shown below.

image

The software should have the COM port that was installed listed as shown in the first red circle.  As long as the right COM port is showing the next step is to select the Attach button as shown in the second red circle.  I was able to use the default baud rate.

When you are successfully connected the Attach button should change to a Detach button and next to the button should be a green Connected as shown below.

image

After you successfully connect to the BLED112 you should select the Start button to start scanning.  The GUI should update and list your RFduino device as shown below.  I only have one BLE device so I am not sure how it would look if you had multiple devices that were all broadcasting.

image

The log window will also show results of the scan.

image

Next you should select the Connect button to connect to the RFduino.

image

Once you are connected the Connect button will change to Disconnect and you should select the GATT button.

image

When the GATT button is selected it will update the GUI including additional commands and a window where the results will be shared.  You should select the Descriptors Discover.

image

The GUI will update and show all the descriptors it found on the RFduino.

image

You can scroll down and select Handle 14.  By selecting the Read button you will read data from the RFduino.  In this case it will be the core temperature.

image

The GUI will update with the Raw value stored at Handle 14 and will also print the result in the log window.

image

You have now successfully read the RFduino via your BLED112.

You will want to select the Disconnect button to disconnect from the RFduino and the Detach button to disconnect the GUI from the BLED112.

Thanks to Bluegiga and RFduino for their products and documentation.  If you find something that doesn’t work for you or you have questions please post them as comments and I will get back to you as soon as I can.

Saturday, September 6, 2014

My Take on the RFduino Temperature Example for Windows 7

One of the examples that comes with the RFduino is an example which reads the RFduino’s core temperature via BLE.  This is my take on that example running under Windows 7 using the BLED112 and BGLib.  The output is just text and not the nice graphics of the IOS RFduino example but it should get the idea across.

One change I made to the sketch running on the RFduino is to only update the temperature if it changes.  This allows the program running on the Windows PC to set the notify attribute and have the RFduino send a notification with the new temperature when it changes.

I found this program not a really good example of using notify because the core temperature doesn’t appear to change too often.  However, it shows all the steps necessary to utilize the notify BLE feature with the RFduino and BLED112.

The code for this example can be found on GitHub in the dhRFduino repository under digitalhack.

For a step by step example of getting this to run under windows see the post on RFduino and BLED112, Putting It All Together but substitute the TemperatureExample sketch and windows program for the ReadValueExample sketch and windows program.

This example uses a soft reset for the BLED112 and has timeouts implemented in a slightly different way than the ReadValueExample.

As always I hope you find this helpful and thanks to Bluegiga and RFduino because without their products none of this would be possible.

If you find something that doesn’t work for you or you have questions please post them as comments and I will get back to you as soon as I can.

Saturday, August 30, 2014

RFduino and BLED112, Putting It All Together

This tutorial is a very simple example to get started with setting data on the RFduino and reading it via a BLED112 on a PC running windows.

The code for this example can be found on GitHub in the dhRFduino repository under digitalhack.

This tutorial includes a sketch to run on the RFduino that will set various data values to be read from the RFduino and a program for Windows that uses the BLED112 to connect to the RFduino and read back the data.  To set different values the RFduino sketch has to have comments changed and then be recompiled.  I wasn’t looking for elegance that will come later.  I just wanted something simple.

This tutorial makes use of the following:

  1. A Windows PC
  2. Code:: Blocks 12.11 w/ MINGW
  3. Bluegiga’s BGLib SDK
  4. The Arduino IDE version 1.5.7 BETA
  5. The RFduino RFD22102 with an RFD22121 USB Shield for RFduino or another way to code to the RFduino.  In this post I describe a method using a Sparkfun FTDI 3.3V board.
  6. The RFduino library for the Arduino IDE.  This library can be found by starting at http://www.rfduino.com/product/rfd22102-rfduino-dip/ and then scrolling halfway down the page to DOWNLOAD, than selecting DOWNLOAD and finally selecting Download RFduino Zip.

Prior to starting you should review these documents:

  1. RFduino Quick  Start Guide for step by step instructions on how to install the RFduino library in the Arduino IDE.
  2. My Bluegiga BLED112 Setup on Windows 7 blog post.
  3. My Bluegiga’s BLED112, BGLib and Code::Blocks blog post.
  4. My It Worked For Me – RFduino blog post for information on downloading code to the RFduino using a Sparkfun FTDI 3.3V board.  Reviewing this document is optional and is only needed if you are using method described in the post.

RFduino Sketch

Below is the code for the RFduino to test initial connectivity between the RFduino and the BLED112.  This code should be copied into the Arduino IDE, compiled and downloaded to the RFduino.

#include <RFduinoBLE.h>

// This function is defined in the RFduino BLE library so it gets
// called anytime a connect is completed to the RFduino.
void RFduinoBLE_onConnect(){
  Serial.println("Connect");
}

// This function is defined in the RFduino BLE library so it gets
// called any time the RFduino is disconnected from.
void RFduinoBLE_onDisconnect(){
  Serial.println("Disconnect"); 
}

void setup() {
  Serial.begin(9600);
  Serial.println("Starting...");
  // this is the data we want to appear in the advertisement
  RFduinoBLE.advertisementData = "test01";

  // start the BLE stack
  RFduinoBLE.begin();
}

// In loop we send either a byte, float of integer by uncommenting the appropriate line.
// As the code is setup now the RFduino will send an uppercase A when it is queried for data

void loop() {
  uint8_t temp = 'A';
  Serial.println("Setting value");
  RFduinoBLE.sendByte(temp);
  //RFduinoBLE.sendFloat(99.1);
  //RFduinoBLE.sendInt(32766);
  while (true) {
  }
}

Windows Program

Below is the code that is used in main.c.  To compile this code you will need to have the following files in the source directory and you will need to make sure they are all included in your Code::Blocks project definition.  This is most easily done using the process described in the Bluegiga’s BLED112, BGLib and Code::Blocks blog post.

  1. cmd_def.c
  2. commands.c – this file will need to be modified to comment out the stubs of the ble functions that are setup in main.c.  This is
    1. ble_evt_connection_status
    2. ble_evt_attclient_attribute_value
    3. ble_evt_connection_disconnected
    4. ble_rsp_gap_connect_direct
  3. apitypes.h – this file will need to be modified as described in the Bluegiga’s BLED112, BGLib and Code::Blocks blog post
  4. cmd_def.h – this file will need to be modified as described in the Bluegiga’s BLED112, BGLib and Code::Blocks blog post

In main.c there are two defines that will need to be updated. 

  1. BLEADDRESS which needs to be the address of your RFduino.
  2. COMPORT needs to be the COM port that is defined for your BLED112

If you uncomment the #define DEBUG the program will print out a number of status messages that should be useful for debugging.

Once you have the Code::Blocks project setup, and have made all the necessary changes you should build the project.

#include <stdio.h>
#include <windows.h>
#include "cmd_def.h"

//#define DEBUG
#define BLEADDRESS "d6:3e:7a:bd:b5:7d" // substitute your RFduinos address
#define COMPORT "COM8" // substitute the COM port for your BLED112
//#define COMPORT "\\\\.\\COM10" // use this notation for com ports > 9.

typedef enum {
  state_disconnected,
  state_connecting,
  state_connected,
  state_requesting_value,
  state_value_returned,
  state_finish,
} states;
states state = state_disconnected;

bd_addr btle_dev;
uint8 btle_connection;
volatile HANDLE comm_port_h;

void dump_packet(char *rxtx, int len0, unsigned char *data0, int len1, unsigned char *data1) {
  printf("%s Packet: ", rxtx);
  int i;
  for (i = 0; i < len0; i++) {
    printf("%02x ", data0[i]);
  }

  for (i = 0; i < len1; i++) {
    printf("%02x ", data1[i]);
  }
  printf("\n");
}

void change_state(states new_state) {
  state = new_state;
}

void btle_send(uint8 len1, uint8* data1, uint16 len2, uint8* data2) {
  DWORD bytes_sent;

#ifdef DEBUG
  dump_packet("TX", len1, data1, len2, data2);
#endif

  if(!WriteFile (comm_port_h, data1, len1, &bytes_sent, NULL)) {
    printf("ERROR: Writing data. %d\n",(int)GetLastError());
    exit(-1);
  }

  if(!WriteFile (comm_port_h, data2, len2, &bytes_sent, NULL)) {
    printf("ERROR: Writing data. %d\n",(int)GetLastError());
    exit(-1);
  }
}

int btle_read() {
  DWORD bytes_read;
  const struct ble_msg *btle_msg;
  struct ble_header btle_msg_hdr;
  unsigned char buf[128];

#ifdef DEBUG
  printf("above first read\n");
#endif

  if(!ReadFile(comm_port_h, (unsigned char*)&btle_msg_hdr, 4, &bytes_read, NULL)) {
    return GetLastError();
  }
  // Error if 4 bytes were not read.  This means a timeout occurred.
  if (bytes_read != 4) return -1;

  if(btle_msg_hdr.lolen) {

#ifdef DEBUG
    printf("above second read\n");
#endif

    if(!ReadFile(comm_port_h, buf, btle_msg_hdr.lolen, &bytes_read, NULL)) {
      return GetLastError();
    }
  }

#ifdef DEBUG
  dump_packet("RX", sizeof(btle_msg_hdr), (unsigned char *)&btle_msg_hdr, btle_msg_hdr.lolen, buf);
#endif

  btle_msg=ble_get_msg_hdr(btle_msg_hdr);
  if(!btle_msg) {
    printf("ERROR: Message not found:%d:%d\n",(int)btle_msg_hdr.cls,(int)btle_msg_hdr.command);
    return -1;
  }

#ifdef DEBUG
  printf("dispatching event / response\n");
#endif

  btle_msg->handler(buf);

#ifdef DEBUG
  printf("below dispatch\n");
#endif

  return 0;
}

void ble_evt_connection_status(const struct ble_msg_connection_status_evt_t *msg) {
  if (msg->flags &connection_connected) {
    change_state(state_connected);

#ifdef DEBUG
    printf("Connected\n");
#endif
  }
}

void ble_evt_attclient_attribute_value(const struct ble_msg_attclient_attribute_value_evt_t *msg) {
  union {
    float f;
    int i;
    uint8 b[4];
  } value;

  value.b[0] = msg->value.data[0];
  value.b[1] = msg->value.data[1];
  value.b[2] = msg->value.data[2];
  value.b[3] = msg->value.data[3];

  printf("----> value: (int) %d (float) %f (byte) %c\n", value.i, value.f, value.b[0]);

  if (state == state_requesting_value) change_state(state_value_returned);
}

void ble_evt_connection_disconnected(const struct ble_msg_connection_disconnected_evt_t *msg) {
  change_state(state_disconnected);

#ifdef DEBUG
  printf("Connection terminated\n");
#endif
}

void ble_rsp_gap_connect_direct(const struct ble_msg_gap_connect_direct_rsp_t *msg) {

#ifdef DEBUG
  printf("from ble_rsp_gap_connect_direct - result: %d, connection_handle: %d\n",
         msg->result, msg->connection_handle);
#endif

  btle_connection = msg->connection_handle;
}

int main(int argc, char *argv[]) {
  COMMTIMEOUTS cto;
  char *comm_port = COMPORT;
  unsigned int b[5];
  int n;

     n = sscanf(BLEADDRESS, "%X:%X:%X:%X:%X:%X", &b[5], &b[4], &b[3], &b[2], &b[1], &b[0]);
     if (n == 6 && (b[0] | b[1] | b[2] | b[3] | b[4] | b[5]) < 256) {
    for(n=0; n<6; n++)
           btle_dev.addr[n] = b[n];
     } else {
         printf("bad bluetooth address");
         return -1;
     }

  bglib_output = btle_send;

  comm_port_h = CreateFile(comm_port, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
                              NULL, OPEN_EXISTING, 0, NULL);


  if (comm_port_h == INVALID_HANDLE_VALUE) {
    printf("Error opening %s: %d\n",comm_port,(int)GetLastError());
    return -1;
  }

  // Reset dongle to get it into known state
  ble_cmd_system_reset(0);
  CloseHandle(comm_port_h);

  do {
    Sleep (500); // 0.5s
    comm_port_h = CreateFile(comm_port, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
                                NULL, OPEN_EXISTING, 0, NULL);
  } while (comm_port_h == INVALID_HANDLE_VALUE);

  // Set 10 second timeout for reads.
  cto.ReadIntervalTimeout = 0;
  cto.ReadTotalTimeoutMultiplier = 0;
  cto.ReadTotalTimeoutConstant = 10000;
  cto.WriteTotalTimeoutMultiplier = 0;
  cto.WriteTotalTimeoutConstant = 0;

  if (!SetCommTimeouts(comm_port_h, &cto)) {
    printf("Error setting port timeouts: %d\n",(int)GetLastError());
    return -1;
  }

#ifdef DEBUG
  printf("ReadIntervalTimeout: %ld, ReadTotalTimeoutConstant: %ld, ReadTotalTimeoutMultiplier %ld\n",
         cto.ReadIntervalTimeout, cto.ReadTotalTimeoutConstant, cto.ReadTotalTimeoutMultiplier);
#endif

  change_state(state_connecting);
  ble_cmd_gap_connect_direct(&btle_dev, gap_address_type_random, 40, 60, 100,0);
  while (state != state_connected) {
    if (btle_read() != 0) break;
  }

  change_state(state_requesting_value);
  ble_cmd_attclient_read_by_handle(btle_connection, 0x000e);
  while (state != state_value_returned) {
    if (btle_read() != 0) break;
  }

  ble_cmd_connection_disconnect(btle_connection);
  while (state != state_disconnected) {
    if (btle_read() != 0) break;
  }

  CloseHandle(comm_port_h);
  return 0;
}

This program is based on the Bluegiga demo programs. 

The program starts by attempting to open the designated COM port.  If the open is successful it issues a reset to the BLED112 device to get it into a known state and closes the COM port.  It then attempts to open the COM port.  This open will not succeed until the BLED112 completes resetting.  When the BLED112 resets it will disconnect and reconnect from the USB.

Next the program sets up a read timeout so that it will not lock up forever if the BLED112 stops sending data.  In this example that is unlikely to happen.

After the read timeout is setup the program instructs the BLED112 to connect to the RFduino.  When the connection completes the ble_evt_connection_status callback function is called.

After the connection is established the program instructs the BLED112 to read data from the RFduino based on the data handle..  When the data is read the ble_evt_attclient_attribute_value callback function is called which prints out the data.

Finally the program instructs the BLED112 to disconnect from the RFduino.

The ble_evt_attclient_attribute_value callback function is setup to print the data out in three of the data types that the RFduino can send: byte, float, and integer.  This allows you to see on the console the value set on the RFduino.

Getting It All To Work Together

The sequence of events that I use is to get the RFduino up and running with a Serial Monitor session going so I can see the status outputs.  Then I run the windows program which takes a couple of seconds to run and prints the value.

You can test different data types by switching the comments around in the RFduino sketch.  When you do this don’t forget to compile and download the modified code to the RFduino.

If everything is working the program should print the following line after about 6 seconds:

----> value: (int) 131481153 (float) 0.000000 (byte) A

If you change the RFduino sketch to send an integer or a float or a different character your output will obviously look slightly different.

Hope you find this helpful. My thanks to Bluegiga and RFduino because without their products none of this would be possible.

If you find something that doesn’t work for you or you have questions please post them as comments and I will get back to you as soon as I can.

Friday, August 29, 2014

Bluegiga’s BLED112, BGLib and Code::Blocks

There is a lot of good documentation on BGLib and the BGAPI on Bluegiga’s website.  I found the first couple of slides in the BGAPI BGLib Overview presentation very helpful for a high-level understanding.

Along with the sdk source two examples are installed.  Reviewing these examples provides additional information on how to use the sdk.

After you successfully install the Bluegiga SDK you will end up with a ble-1.2.2-100 folder (assuming you install version 1.2.2 of the sdk) under the install directory.  I let the install proceed with defaults so on my system it ended up on C:\Bluegiga.  The sdk is in the src directory.

image

The sdk consists of two c files and two header files.

image

  • apitypes.h consists of a number of type definitions.
  • cmd_def.h defines a number of constants and data structures.
  • cmd_def.c sets up the data structure that is used to dispatch events based on the packets received.
  • commands.c defines the default functions that get called when an event is dispatched.  These functions have no executable statements and therefore when called just return.  In your program you will need to define those functions you wish to use and comment them out or remove them from commands.c

In the examples commands.c has been renamed to stubs.c.  The examples also contain a Makefile for building them.  The Makefile contains logic for MINGW under Windows but as was planning to  use Code::Blocks I didn’t test them.

In using BGLib with MINGW in Code::Blocks 12.11 I found that the apitypes.h and cmd_def.h files had to be modified.  The modifications were necessary to get the PACKSTRUCT macro defined properly.  The problem is that PACKED is defined in windef.h for MINGW without gcc_struct which causes incorrect packing of data.

In apitypes.h I commented out the lines beginning with #ifdef __GNUC__ and ending with the corresponding #endif.  In cmd_def.h I commented out the lines starting with #ifdef PACKED down to the corresponding #else and then the corresponding #endif several lines below.

apitypes.h modifications:

image

cmd_def.h modifications:

image

To setup the scan_demo example in Code::Blocks I suggest the following steps:

Execute Code::Blocks and under File select New and create a Console project for C.

image

Enter scan_demo as the project title.  Code::Blocks will create new project folder in your projects folder.

image

The new project will have a main.c file and a scan_demo.cbp Code::Blocks project file.

image

Close Code:: Blocks and go to the folder with the Bluegiga scan_demo in it and copy all the apitypes.h, cmd_def.c, cmd)def.h, main.c and stubs.c and paste these into the Code::Blocks project folder.  You will get a warning about main.c as it already exists in the Code::Blocks project folder.  Answer that you want to replace the existing file with the copied file.

image

Execute Code::Blocks and open your scan_demo project.  Select the scan_demo project in the left side window and the select Project from the menu bar and Add Files…  Select the new files you added to your project from the example directory.

image

Using the gear icon build the project.

image

As the scan_demo program requires the COM port of the BLED112 as a parameter you will need to open a console window and navigate to the executable in your scan_demo project directory.  In this case I built a Debug copy so it was in the bin\Debug directory.

Run the scan_demo program with the appropriate COM port.  In my case this was com8:

scan_demo com8

As long as you have a BLE device that is advertising you will see its address along with the RSSI power value in the console window.

image

You should now be ready to move on to compiling an example that receives data from your BLE device.  In my case that is an RFduino which is the subject of my next post.

Hope you find this helpful.  My thanks to Bluegiga for their sdk and the documentation on their website and to the folks responsible for Code::Blocks.

If you find something that doesn’t work for you or you have questions please post them as comments and I will get back to you as soon as I can.

Thursday, August 28, 2014

Bluegiga BLED112 Setup on Windows 7

To use the Bluegiga BLED112 dongle and sdk with Windows 7 you will should follow the steps below.

Download and Install the Software

Go to the Bluegiga site and download the appropriate software.  It is recommended that you want to make sure that you download the sdk for the version of software that is loaded on your BLED112. 

I was not able to figure how to determine which version of software is running on the usb dongle without downloading the software and installing it.  Fortunately, I guessed right.  At the time that I did the the BLED112 dongle I received was running v1.2.2-100. 

To download the software you will need to register on the Bluegiga site.  Once you are registered go to this URL to download the software.

https://www.bluegiga.com/en-US/products/bluetooth-4.0-modules/bled112-bluetooth-smart-dongle/documentation/

When you get to the website you will want to select Software Releases which should expand the section to list the software versions available for download.

image

Plug in the BLED112

Once the software has installed plug in your BLED112 and wait for the drivers to install.

Access the BLED112 using the BLE GUI Software

Once the BLED112 has completed its install you should execute the BLE GUI software that was downloaded.  This can be done via the icon on the desktop or through the program menu.

When the software runs it will display a windows as shown below.

image

The software should have the COM port that was installed listed as shown in the first red circle.  As long as the right COM port is showing the next step is to select the Attach button as shown in the second red circle.  I was able to use the default baud rate.

When you are successfully connected the Attach button should change to a Detach button and next to the button should be a green Connected as shown below.

image

The next step is to select Commands from the menu bar and then select the Info command.

image

This should result in the BLED112 reporting back its version as shown below.

image

This means that the BLED112 dongle is successfully installed.

Using Device Manager to Find Your COM Port

If you run into problems with what COM port the BLED112 is connected to you can open a command window and enter devmgmt.msc which will bring up the Windows 7 device manager.  Then scroll down to Ports (COM & LPT).  Click on the triangle / arrow to expand the port listing and you should see a COM port that lists Bluegiga Bluetooth Low Energy (COMx) where COMx is the COM port that is connected to the BLED112.

image

In my next post I will discuss walking through the sdk and some changes that I had to make to get the sdk to work correctly with Code::Blocks 12.11 and MINGW.