Introduction: LED POVstick With Bluetooth Low Energy
This instructable shows you how to build a lightwriter stick with RGB LEDs which is controllable via BLE from your phone!
Now that the dark season starts and you need to take long exposure pictures: With this stick you can write your signature into the picture, or a motivational quote, or a declaration of love, a QR-code, a web-adresse, or many things else...
It covers several topics of development:
- building the hardware
- programming the Cypress BLE chipset with C
- make your own app to control it.
Step 1: Hardware for the BLE-LED-Stick
For the stick you need the following:
- A cypress BLE module ( CY8C4247LQI-BL583 )
- a WS2812b RGB-LED-Strip (64LEDs from a 144Led per meter strip)
- a Li-Ion battery with a suitable holder (18650)
- a pushbutton
- a piece of breadboard
The hardware of the stick itself is quite simple.
The Cypress BLE module is mounted on a piece of breadboard and the LEDs, the button and the power-supply are just connected to this breadboard.
Everything is mounted, glued or screwed to a small piece of wooden strip, which itself is partly inserted into a clear polyacryl tube. But this is not a must. I wanted to mount everything inside a tube, but I didn't found a suitable for the BLE-module and the battery which are quite big, compared to the LEDs. For a first shot you don't need the acryl-tube.
Step 2: Electronics Assembly
This step shows you how the BLE-module is mounted and which pins are used for which purpose.
As in several of my Instructables I used the Cypress BLE Development Kit.
CY8CKIT-042-BLE Quick Start Guide
If you want to operate the module on it's own, all you need to connect is the power sources and the used pins.
For our project we only use the pin 3.5 to drive the LED-Strip. But of course you can change that with the PSoC Creator.
As you can see in the picture of the PCB, I added pinheads in all corners of the chip but I skipped the VREF pin.
This way the module is mounted properly and it is impossible to misconnect the module.
Step 3: How to Generate the Fonts?
Well, I think this was one of the most interesting problems I solved during this project.
Of course one could just design a new font and write it in an array, but that is really much work!
So what did I do?
I knew that I needed some kind of ASCII to hex-bitmap conversion. And I was lucky, because I was not the first with this problem! :-)
The software "GLCD Font Generator" did just the right thing: https://www.mikroe.com/supporting-software/
Because I wanted to get the most out of the LED-stick, I imported the font in a rather big size (~32pixel). If you only use capital letters you don't have to care about ascenders, which will increase your visible font-size another few pixels. But I chose to use both capitals and minuscule letters. (https://en.wikipedia.org/wiki/Ascender_%28typography%29 )
Once you import a font into GLCD Font generator you can choose to export it in different formats.
I tried to export it directly into headers which was good, but not perfect. The resulting export is an array of shorts (16bit) with byte-hex-values for the columns for each character of the first 128-ascii character. Not quite what I wanted or needed...
So I imported the array into an open office calc worksheet. Then I removed the "0x" on three of four values and concatenated them into one 32bit long value. I also fixed the wrong endianess of the individual bytes.
The resulting array is a N*M array of 32bit values. M is the respective character and N are the columns that make up the display of this letter. In this first draft all characters have the same number of columns, that means all letters are equally wide, like in the well known Courier font. Small characters like "i" or "t" look like they are lost in space.
Therefore I added a new parameter in the beginning of each character to tell, how much columns this character has or how wide this character is. This saves memory and make the text look better!
Attachments
Step 4: BLE Control Software
The principle of the BLE-software is very easy:
- At the beginning it just does nothing.
- Via BLE you can set different animations or texts to be displayed.
- Once you press the button, the individual columns of the animation or the text is displayed.
- After the text is displayed, it continues to wait again.
Just import the cypress project to your PSoC-Creator and modify it if you like.
The PSoC-4 has not that much RAM and flash to be able to hold complete RGB-images of the fonts. Therefore I needed a way to generate the LED-content dynamically from the text. That is pretty straightforward, nothing special so far. From a text with many letters, the algorithm takes one letter and converts it into a black-white-bitmap array . Then it takes each column of this one-letter-bitmap and instead of white, it writes the current RGB-color to the LED-array. This way you can generate single-color texts or by an additional function change the color after each column, each letter or even after each pixel.
A "letter" can be stored in a single byte-variable while a black and white bitmap needs to be stored in some kind of an array.
The data-structure is this:
String: newtext = "Hello"; Font: uint32 characters = { FirstCharacter_ColumnCount, FirstCharacter_FirstColumn, FirstCharacter_SecondColumn, ... <br> SecondCharacter_ColumnCount, SecondCharacter_FirstColumn, ... ... LastCharacter_ColumnCount, ... LastCharacter_LastColumn }; Color: uint32 rgbcolor = 0xHHBBGGRR; // Brightness, Blue, Green, Red each as 8bit value
To convert a string for display we do the following:
getCharacter() : H ( 8bit) getColumn( int i ) : column (32bit) (i starts with the first column, runs to the last.) if( bit in column is 1 ) --> LED in Strip is set to color. LED-Strip Array is 64 LEDs with 32bit colors each! <br>
And if this column is displayed we continue with the next one.
It is this easy.
Attachments
Step 5: First Test
Now that the software runs, we are ready for the first tests.
The easiest way to test the embedded function is with an Bluetooth low energy test app. Like the Nordic or Cypress Apps.
Nordic: nRF Connect for Mobile
Cypress: CySmart
Start the Pov-Stick and observe how the demo-string will be displayed. Once this is finished it is time to start the app. Search the Povstick device and click on connect.
Once the connection is established the app automatically discover all defined services and characteristics.
Look for the first service (should start with 0000ccce...). Click on it to open it and display the first characteristic (starts with 0000ccc1). Then hit the write (or upload) button and write an 01 to this characteristic.
Once you hit send, the POVstick will start the Color-Knight-rider animation aka Larson Scanner with changing colors.
Gratulations you sent your first value via BLE!
Step 6: Select the Animations
In the software we defined an enum "e_Animation" with the following values:
typedef enum
{ Knightrider = 0, ColorKnightRider, Rainbowswirl, Valueswirl, WS_CandyCane, WS_CandyCane_2, WS_CandyCane_3, WS_Twinkle, WS_Icicle, WS_ColorWheel, RGB_Control, TextAnimation, Animation_Max } e_Animation ;
These are the values that are valid for the ccc1 characteristic. If you would like to see the CandyCane-Animation you have to write a 4, 5 or 6 to this characteristic. They differ in the colors.
Two special animations are the RGB_Control and the TextAnimation. If you chose to activate these, the stick will obviously show nothing at first. But it offers you additional options to control the stick with the other services.
Step 7: RGB Control
The RGB-Control can very easily be tested with the CySmart App because I used the same UUID for this characteristic as in the Cypress Demo.
Start the CySmart app and connect to the Povstick. First you have to write a "0x0A" to the ccc1 characteristic.
0x0A is the hex-value for 10, which is the RGB-Control animation in the enum.
Then you can switch to the RGB-LED Control Panel in the CySmart App. Maybe you have to restart the app to get to this screen. Then you can control the color of all LEDs with this RGB-diagram.
Of course you can also write the values directly into the characteristic.
Step 8: Text_Animation Service and Persistent Storage Service
These services are not so easy to test.
Technically you can also use the nordic app for this, but you need to know what values to write to which characteristic.
So if you want to test these, you should have a look at the PSoC project, which characteristic has which UUID.
An important on is the "Set-Speed" characteristic. With this characteristic you could control how fast the animations are.
With the "Set_Animation" characteristic of the PersistentStorageService you can control the fonts and the colors of the text string. The valid values are defined in "povanimation.h", two fonts "mono" and "serif" and single colored and rainbow-colored. The values 0 and 1 display the text with a fixed color, controllable via the RGB_Control characteristic. The values 2 and 3 change the color for each column and give the string a nice rainbow.
The "Write_Text_Service" is kind of different. You can write a new string to the device by writing individual characters to the "Set_Character" characteristic. On each write, you will get a notification back of the current length of the string.
To start a new string, write "true" to "Clear_String".
This is not the best implementation, but it works for any string up to 250 characters without changing the MTU size.
The display of a new string with start when the button on the Povstick is pressed.
Step 9: Start the Android App
This is an important step, but way beyond the scope of this instructable. Sorry for that!
Maybe I might upload my test-app to the play store, but it is not yet finished or releasable.
Step 10: Write Messages in Pictures
Well, this is why I build this povstick in the first place: To write messages in pictures.
You need a tripod, a camera with long-exposure function and some good location.
Set up the camera and adjust the exposure time to 10s for a first test.
Trigger the release and start walking through the picture, starting the text-display on the stick.
Et Voila there we are!
With the right combination of LED-brightness, aperture and exposure time it is even possible to take pictures at dawn.
The three pictures in this step show the complete spectrum of possibilities.
In the first, the LEDs are overexposed and create a magical glow. But that is why the reflections on the ground are visible and the background is rather good.
The second picture is exposed for the LEDs, but that leaves the background completely black.
And the third one shows rather dim LEDs shortly after sunset. The LEDs are as bright as in the other pictures, but the environment was so bright that I had to use a low apperture and a low ISO so that the LEDs appear rather dark.