Note: BGScript is no longer supported since SDK 2.4.x. We encourage all customers still using BGScript to migrate their applications to C since GCC support was also added in 2.4.x.
This example demonstrates how to access the BMA280 accelerometer chip that is mounted on the expansion board that is delivered with the BGM111 development kit (SLWSTK6101A). The example is a BGScript application that uses just basic GPIO read/write operations (bit-banging) to implement the SPI transactions. The source files are included as one zip file at the end of this article.
The example will allow you to experiment with the accelerometer that is included in the kit. It also serves as an example on how to implement some simple serial interface protocols using bit-banging. At the time of writing this document, the SPI peripheral support is not yet included in the BGM111 SDK (v 0.9.2-446). This example does not require HW SPI support so it is not dependent on the SDK version.
A picture of the BGM111 development board with the expansion board attached is shown below.
To run this example, you need:
The accelerometer samples are printed via UART to the terminal program. The same values are also exposed through a simple GATT service using nofitications. You can use some generic BLE test application to read the accelerometer samples using a smartphone or tablet.
At boot, the script enables advertising and starts a soft timer that is running continuously. Most of the functionality is inside the timer handler.
First the program does an SPI self-test to check that the SPI interface between BGM111 and the sensor (BMA280) works as expected. The self-test writes some generic purpose registers in the sensor and reads the same values back to compare that the values match. The self-test will fail if for example the expansion board is not attached to the main board.
After the self-test is completed, the program will simply just read the accelerometer samples once per timer event. Three samples are read, one per each axis (X, Y, Z). The three accelerometer samples are printed in the terminal using hex notation.
If a remote client is connected then the accelerometer data is also pushed to client using notifications. (Note that to receive the notifications client must subscribe to the notifications by writing to the corresponding client characteristic configuration.)
The program also blinks a LED on the board (LED0) to indicate connection status. When the module is advertising and no connection is active then the LED is blinking slowly with a “heart beat” pattern, about once per second. If connection is open the LED will blink faster with a 50/50 duty cycle.
Running the demo
The following screenshot illustrates how the debug output will look like in a terminal program when the program is running. Debug output is handled using the on-board USB-to-UART converter in the development kit. When you connect the kit to your PC it will be visible as a virtual COM port and the name is “COMx: JLink CDC UART Port”.
The following screenshot is made using an Android phone and a 3rd party utility called BLE Tool. After enabling notifications the three accelerometer samples will be updated continuously.
If you change the orientation of the development kit or move it you can observe how the accelerometer data changes.
The project consists of following files:
This is a typical organization of a BGScript project. The *.bgproj file defines what files are included in the project and what is the target device. Application is in accm_bgscript.bgs. The procedures that implement SPI write and read are separated into spi_bitbang.bgs.
The HW configuration is in file accm_hardware.xml. This file configures the GPIO pins needed for SPI and LED output and also the UART interface.
The GATT is defined in accm_gatt.xml. This project implements a custom GATT service so that remote client can access the accelerometer data by subscribing to notifications. The accelerometer data is visible through a custom characteristic with UUID ed3d929d-aaa7-4bf7-b222-bcff617d272d. Data length is three bytes, one byte for each sample (axis).
SPI interface details
To access the BMA280 accelerometer we need to support read and write operations. The details are described in the BMA280 manual that is available online.
For both write and read, the basic structure is the same. The SPI frame consists of 16 bits and the first bit is a read/write selector (1=read, 0 = write). The R/W bit is followed by a 7-bit address field.
The lower 8 bits are used for data. In case of write operation, the data is written by host (i.e. BGM111). In case of read, the data is written by the sensor (BMA280).
SPI uses separate lines for write and read and in principle it is possible to both send and receive data simultaneously. However, in this case the interface is such that data is transferred only in one direction at a time.
The SPI bitbang used in this project is accessible through two procedures:
* procedure spi_write(address, value)
* procedure spi_read(address)
When calling SPI write, the register address and value are simply passed as parameters. The SPI write procedure is in this project used only for the self-test part.
When calling spi_read() the register address is given as argument. The read result is stored in a global variable named spi_data_in (declared in file spi_bitbang.bgs). This variable is declared with the “export” keyword so that it is also accessible from the main program.
The logic analyzer screenshot below illustrates a single SPI transaction (read operation). The duration of one clock cycle is 280 microseconds which corresponds to 3,6 kHz. One 16-bit transaction takes about 4.6 milliseconds to complete. This means that the maximum number of samples that can be read with this implementation is in the order of 200 samples per second.
To get the raw sensor values from BMA280 it is enough just to read three registers at addresses 0x03, 0x05 and 0x07. For details, see the register map in BMA280 manual. These three registers actually contain just the most significant part of the acceleration values. The samples are 14-bit wide but this demo only reads the most significant 8 bits for simplicity.
The source files are included in one archive named accm_slave.zip, see download link below.
and I thought bit-banging was a thing of the past
I'm using this example and it works fine with a PC terminal, but it doesn't work with BLE tool in android. The app in this example doesn't even find BGM111. I tried different BLE tool app which finds BGM111, but it doesn't reach accelerometer data, just writes this code 0x7FB2 and nothing else.
Can you tell me please, what am i doing wrong?
Can you check the markings in the shield of your BGM111 module, does the module revision info end with "V1.1" ? If this is the case, then you need to modify the hardware configuration file (accm_hardware.xml) and comment out or delete the following line:
<ctune value="0" />
This setting is needed only for BGM111 V1 modules (the first engineering samples). For V1.1 and later you should leave it empty.
Thank you for fast reply. The module revision end with "V1". I tried to delete that line anyway, but nothing has changed...
I flashed my BLE on this project and I can't read the data in Tera term ( see figure)
Would you know solve this problem.
@Arsimik do you have the small extension board connected (as shown in the picture in the beginning of this article)?
Are you trying this on BGM111 kit or perhaps some other radio board like BGM113 ?
Thank you for your reply .Yes , I have a small extension board connected and I trying this on BGM111.
I would like to know please what is variable nibble in the procedure print_nibble.Because when I want to see the value in the register 0x75 , The console show me 00.
# print a nibble procedure print_nibble(nibble) n = nibble if n < $a then n = n + $30 else n = n + $37 end if call endpoint_send(endpoint_uart1, 1, n) end
The print_nibble procedure prints one nibble into the UART. Nibble is a group of for bits (or a half byte). See https://en.wikipedia.org/wiki/Nibble
print_nibble is used by the other helper function in the BGScript:
# print hex values (range 0..255 -> output 0x00..0xFF) procedure print_hex(hex) call print_nibble(hex/16) call print_nibble(hex&$f) end
If you call for example print_hex($75) the procedure will call:
What the print_nibble function really does is takes a 4-bit value as input (range 0...F in hex) and then converts the numeric value into ASCII character.
>> I want to see the value in the register 0x75 ,
This knowledgebase article is about accessing BMA280 accelerometer. That chip does not have any register at offset 0x75. I assume you are referring to the MPU-6500 sensor that you mentioned in another context. Please be more specific in your questions. If you have some trouble accessing the MPU-6500 then maybe better to create a new thread for that?
Sorry, I make reference exactly to sensor MPU6500.
I don't know how to create a new thread for that .Do you have an example ( program) please.