Introduction: BLE-Controlled WS2801 LEDs

About: I like to explore new things and try out stuff. At the moment I'm in to electronics, BLE and LEDs.

This instructable shows how to use the Cypress BLE-Devboards for Bluetooth-Low-Energy projects. This BLE-board is powered by a Cortex-M0 and has a lot of resources and computing power left for own applications. And the best of all: It costs only 10€ and you don't need any other parts to operate it.

Bluetooth low energy aka "Bluetooth smart" aka "Bluetooth 4.0" is a nice thing. Unfortunately the BT-specification is something about 1000pages long. And to get you started you need to read the specifications of the chip-manufactures as well. And if you start with the wrong chip it might cost you another few weeks of reading and thinking...

That's why I want to share my BLE experience with you and show how you can get startet very quick.

My project was to control WS2801-LEDs via BLE.

I wanted to build a flash-cloud like this one: How to make a lightning cloud and I needed a WS2801-Controller anyway. And because I lately got this BLE-Devkit I thought why not?

Once you understand how this works, you could easily add features or modify the setup.

The BLE-hardware is a Cypress BLE-dev-kit board "CY8CKIT-042-BLE". You can find more informations on this here: Cypress CY8CKit-042-BLE

The dev-kit is around 50€, but the BLE-board itself has everything it needs and only costs 10€.This is less than a BLE-addon for the Arduino!

Step 1: The Cypress CY8CKit-042-BLE

I usually don't advertise, but this dev-kit really rocks!

The main features of the BLE-board (the small red one) are:

  • PSoC 4 with an ARM-Cortex M0 core (low-power 32bit uC) with 16kB RAM and 128kB Flash!!
  • a lot of additional analog and digital features (several PWMs, Counter, Timer, Op-Amps and much more!)
  • wide range of operation 1.8-5.5V !!
  • several predefined HW/SW-features like SPI, I2C, UART, LCD-driver...

Especially the wide range of operating voltage makes is ideal for makers! And the Cortex-M0 provides some ultra-low power modes, making it ideal for battery powered applications.

And finally there are a lot of examples and tutorials on the cypress website. I wish I found this chip earlier!

If you buy this dev-kit, you get the programmer board (big red) with Arduinio-compatible headers, a small red BLE-board, a small black BLE-board (with less analog features) and a BLE-Dongle for your computer.

Everything else you need is free of charge. The IDE, the Compiler and the documentation. So let's start!

Step 2: Setup of PSoC-Creator

The Cypress-IDE is a combination of schematic-drawing and software-development. And that is, because the chips are HW-configurable too!

The PSoC 4 on the tiny red BLE-board doesn't have fixed pins for UART, PWM or IOs, you can configure them on nearly every output pin of the chip. The BLE-funktionality is fixed but that is because the peripherals (like the antenna) are fixed too.

So get the current version of the PSoC-Creator and install it. Unfortunately it only runs under windows. But it works fine in Virtualbox 5.0 on a linux host. PSoC-Creator (under Download on the bottom).

Then you need CySmart (some kind of debug tool for BLE) and the Board-Package. (For some downloads you must login to the cypress website, you can create an account for this)

On the Cypress-website you can also find a lot of good examples. If you want to get an idea of what this instructable is all about, try one of the BLE examples. You can just open them with the PSoC-Creator and run them on the device.

Step 3: Make New Project

Open PSoC-Creator and start a new project.

Then open the Schematic-Editor by clicking "TopDesign.cysch" in the workspace explorer panel.

Then search the component catalog and add the following items:

  • BLE component (for the BLE-functionality)
  • SPI (SCB mode) [v3.0] (this is the SPI-master for the WS2801)
  • Two digital output pins [v2.10] (We will use them for the debug-Led on the board)
  • Timer [v2.70]
  • an Interrupt [v1.70]
  • a clock [v2.20]
  • a constant logic low "0" [v1.0]

Then your schematic might look like this.

In the next steps we will configure each component.

Step 4: Configure Clock and Timer

Just have a look at the screenshots I providedto see how the components should be configured.

For the Timer_clock I chose 24MHz instead of 48MHz, because the 48MHz caused timing-problems. And we only need this timer for a regular interrupt!

Step 5: Configure SPI

The SPI-component was in fact the most critical. Because I had no logical analyser I had to try and find out what works!

This is the selected values in the SPI Basic:

  • Mode - Master
  • sub-Mode - Motorola
  • sclk mode : CPHA = 1, CPOL = 0
  • Data rate - 4 Mbps
  • RX / TX data bits: 8
  • Transfer separation: Separated
  • check Remove MISO (otherwise you have to connect something to it!)

In the SPI Advanced you have to change this:

  • TX-Buffer-size : 255

Just look at the screenshots.

Step 6: Configure BLE GAP-Settings

For the BLE-functionality I started with a tutorial from Cypress.

There is an example where you can control the RGB-LED on the board via BLE.

If you start with this example, or at least use the same UUID, you can control you device with the Cypress-App.

First we have adjust the GAP-Setting.

Step 7: Configure BLE GATT Settings

The Gatt-Settings are adjusted in the profiles-page.

The first "Generic Access" and "Generic Attribute" doesn't need to be changed.

If you started with the example you might already have RGB-Service. If not, add a new custom service with "Add" and name it RGB_LED_Service or something else. It is Important to give this custom service the 16-bit UUID CBBB. This way the Cypress App recognizes this service an can handle it appropriately. First change the UUID for this service from 128-bit to 16-bit and enter CBBB.

You can also rename the service itself by right-clicking the new service an choosing "rename".

Then you have to change the custom characteristic and rename it. Enter the name and the type of the fields and choose read and write from properties.

Then you best delete the custom descriptor and add a new "characteristic user descriptor" by right-clicking and selecting "add Descriptor". This sets the right UUID and Fields for the descriptor. You can enter anything in the User-Descriptor Field.

Step 8: Adjust the Pins

doubleclick the file with *.cydwr to open the pin-assignment-editor.

For the SPI the pins are more or less preselected. You can only choose between two or three. The digital output pins may be routed to any pin. But as we want to use the built-in RGB-LED for debugging, we have to chose those pins. P3[6] for the green one and P2[6] for the red one.

Step 9: Connect the WS2801-LEDs

This is the most easy part of the whole thing.

You can connect the LEDs while the BLE-Board still is in the programmer, or you can use the BLE board without the programmer. Then you have to apply the +5V too! Of course!. :-)

It is really simple.

Step 10: Now for the Software - Initialize

From the main menu select "Build" and "generate Application". This validates the setup and generates the hardware-design to be uploaded and additionally it generates all the headers for the software.

The most important functions are:

CyBle_Start( CustomEventHandler );

This function starts the BLE and tells the stack which function handles the callback if there is any: The CustomEventHandler! This function is implemented in the file BLE_Process.c.

Timer_Init(); and Timer_Enable(); initiates the timer-component and generates an Interrupt every 30ms.

And finally the SPIMASTER_Start(); Which starts the SPI-Component.

You might have recognized that the function has the same name as the component. If you named you component different then also your function to start it is different. Just start typing and the IDE will suggest the best functions.

Step 11: Timer Interupt

This is the Interrupt-Service Routine that handles the BLE-callbacks. In the example this is in the endless-for-loop in the main()-function. But I wanted to do something else and handle BLE only if it is necessary.

If your device shall run on batteries, then you might think about sending the CPU to a sleep-mode.

CY_ISR(Time_BLE_Helper_ISR)<br>{
    isr_1_Disable();
    // bearbeite BLE-Events
    
    RED_Write(0);
    CyBle_ProcessEvents();
    RED_Write(0xFF);
    
    isr_1_ClearPending();
    isr_1_Enable();    
    Timer_Enable();
    
}

Step 12: The CustomEventHandler (for BLE)

This is THE function for BLE. everything is handled here.

Connect, disconnect, write, and adverstising events.

In the BLE_Process.h I defined some shortcuts to replace the generated defines because they are very long, you don't have to if you don't want:

#define RGB_LED_CHAR_HANDLE                (CYBLE_RGB_LED_SERVICE_RGB_LED_CHARACTERISTIC_CHAR_HANDLE)

The right side is the system define and the left side the shortcut.

Once there is a write-event you have to check which characteristic of which service shall be written. This is done by this:

if(wrReqParam->handleValPair.attrHandle == cyBle_customs[RGB_LED_SERVICE_INDEX].\<br>                                                        customServiceInfo[RGB_LED_CHAR_INDEX].\
                                                        customServiceCharHandle)
            {
               

This code extracts the data that shall be written and updates the RGB-LED finally.

 		/* Extract the value of the attribute from the handle-value 
                 * pair database. */
                RGBledData[RED_INDEX] = wrReqParam->handleValPair.value.val[RED_INDEX];
                RGBledData[GREEN_INDEX] = wrReqParam->handleValPair.value.val[GREEN_INDEX];
                RGBledData[BLUE_INDEX] = wrReqParam->handleValPair.value.val[BLUE_INDEX];
                RGBledData[INTENSITY_INDEX] = wrReqParam->handleValPair.value.val[INTENSITY_INDEX];
                
                /* Update the PrISM components and the attribute for RGB LED read 
                 * characteristics */
                UpdateRGBled();
            }

If you named your service different, the defines are also different. Just check it out, it is not so difficult.

Step 13: Animations.c

This file contains all the functions to write Colors to the WS2801 via SPI.

The function used for this is :

void SPIMASTER_SpiUartPutArray(const uint8 wrBuf[], uint32 count)

Therefore I have defined a global char-buffer and fill it dynamically with different values and then write it to SPI.

Step 14: Connect to Your New Device

Programm and power up the board and use the BLE-USB-Dongle or the CySmart-App to connect to your new device.

You can find the App here: https://play.google.com/store/apps/details?id=com.cypress.cysmart

You can use the Gatt DB to write new values to your new service!

Or you use the RGB-Service that is already installed in the CySmart-App.

Currently I'm working on a custom Android-App to control my device, but that is much more complicated than the device itself!!

Make It Glow! Contest

Participated in the
Make It Glow! Contest

Tech Contest

Participated in the
Tech Contest