Showing posts with label Adafruit. Show all posts
Showing posts with label Adafruit. Show all posts

Sunday, September 27, 2015

BLE controlled Minecraft nightlight

A few months ago my daughter asked me to print something for her on my 3D printer. I asked her what she wanted and she said "something Minecraft". We started looking at designs on thingiverse and came across a design for a Mincraft ore block. I thought it might be cool to make a night light out of it using Adafruit Neopixel LED strips and an Adafruit Pro Trinket microcontroller to change the colors. I ended up having a bit of scope creep on this project and it took way longer than I expected but the end result was pretty neat and I learned some new things. Originally I was just going to program the Arduino to cycle through colors but then I came across the Adafruit Bluefruit LE breakout board and realized it would be fairly easy to add BLE control to the project. In the end this was the most involved Arduino coding project I've done so far. At the bottom of this post there are links to download the 3D models and Arduino code if you want to build one yourself.




3D Printing


The first step in this project was to 3D print the plastic parts. I printed the cube at 1.5 times the original size which made the final dimensions 105mm on each side. I had to print it with supports for the holes and a brim to minimize lifting from the print bed. It took almost 18 hours to print it. After it was done printing I realized there wasn't good way to attach a base to the cube (other than glue) so I used OpenSCAD to add recessed corner posts with screw holes and reprinted it.


I used FreeCAD to design an insert that fits inside the cube. The LED strips sit in the channels and the electronics go in the square opening on the bottom.






Diffuser panels


With the 3D printing done the next step was to make some diffuser panels to go on the inside of the cube so you don't see the individual LEDs. I considered 3D printing the diffusers out of natural filament but that would have taken several hours. I had some scrap plexiglass in the garage so I cut out pieces to fit the top and four sides. I sanded both sides of the plexi with 80 grit sandpaper to make them opaque. I tested the diffusers with the LED flash light on my iPhone and they seemed to work pretty well.





Assembling and wiring the insert


The first step in assembling the insert was to cut and solder the LED strips. Adafruit Neopixel LED strips can be cut with scissors. There are cut lines printed on the strip between each LED. I designed the insert to fit three LEDs on each side and five on top. To minimize the number of jump wires I would need to solder I cut three strips and bent them around the edges.


I used the tip of my soldering iron to melt holes for the wiring to pass through to the center of the insert. With the strips set in place I soldered jumper wires onto the end of the LED strips, passing the wires through the holes so the wires were on the inside of the insert and not getting in the way of the LEDs. Then I used hot glue to attach the LED strips to the insert. The Neopixels are addressed by numbers starting with zero for the first LED on the strip so they need to be wired back up as a continuous strip. The strips are also directional so you need to pay attention to the arrows on the strips, wiring them so the arrows all face the same direction. I put a female header on the end of the of the strip wiring so I could plug it into the circuit board.






Breadboarding the control circuit


I hooked up the circuit on a breadboard to test it out before soldering. Controlling the LEDs only requires one digital pin. The BLE breakout board communicates over SPI.


Once I had everything wired up I loaded the Adafruit_NeoPixel strandtest example code to make sure all my LEDs were working correctly.



Soldering the control board


The two main components of the control board are the Pro Trinket microcontroller and the Bluefruit BLE breakout board. I decided to use headers so the microcontroller and BLE chip can be easily replaced if needed. I started with a half-size Adafruit Perma-Proto broad. To make the control circuit as compact as possible I placed the Pro Trinket on one side and the BLE board on the other. To do this I needed to cut the traces for a few holes. I used an X-ACTO to cut and scrape the traces. I used my multimeter to verify there was no continuity.

Cutting the traces on the Perma-Proto board
After cutting the traces I soldered on the headers for the Pro Trinket and the BLE breakout.

Pro Trinket plugged into its headers
BLE board plugged into its header

I finished up the wiring between the microcontroller and BLE board and added some male headers for connecting the LEDs and power input. After that I used a Dremel to cut down the proto-board as small as possible.


Here is the finished control circuit.



Power switch and power input


On the back of the cube I added a barrel connector for power and a small toggle switch. The toggle switch controls the power to the microcontroller and the LEDs. The power cable is routed through a small hole in the white insert.




Assembling all the parts


The insert was secured to the cube with countersunk head 4-40 screws. I added some stick on rubber feet and stuffed the control board in the square opening.


One mistake I made was using too much hot glue to attach the LED wiring inside the square hole of the insert. The extra glue caused the control board to protrude a couple millimeters. Not a huge deal but I would have liked the bottom to be completely flat. I had planned to put a cover on the bottom so I just designed it to account for the protrusion. I fired up FreeCAD again and whipped something up.


The cover was attached with pan head 4-40 screws.




Writing the code


For the Arduino code I started with Adafruit's nRF8001 echoDemo example. It basically does serial communication between the Arduino and an iPhone app.


Adafruit also provides a demo iPhone app called Bluefruit LE Connect. The app lets you interact with the BLE breakout board without having to do any iOS development.


After playing around with the color picker in the iOS app I saw it was sending RGB values formatted like this: !C180255
The exclamation point indicates a command, the next character indicates what kind of command, followed by red/green/blue values. This seemed like a good format for all of the commands I planned to send to the cube. I started planning out all the commands on my whiteboard.


One thing I hadn't worked with before on Arduino boards was EEPROM memory. I understood basically how it worked but hadn't actually used it in a project yet. Turn out to be very straight forward. On the Atmega328P chip there are 1024 possible EEPROM memory locations and you can store one byte of info in each location.

Here are the major features of my Arduino code on the cube:
  • Set the whole cube to a single color
  • Set the color of each side individually
  • Activate animations (Pulse, Rainbow, and Cycle)
  • Set a new BLE name on the cube and save it to EEPROM
  • Save the current colors and animation settings to EEPROM
  • Read settings from EEPROM on start up
  • Set base values in EEPROM for new boards
  • Flash green to confirm commands

I won't go into great detail about the code itself. You can read through it here if you would like. I tried to comment it well. I'm sure it can be improved quite a bit so feel free to send suggestions or pull requests.


Demo

Here is a (long) video showing most of the functions of the cube





Download links

As promised here are links to download everything if you want to make one of these yourself. The Fritzing diagram lists all the parts needed.










Sunday, February 1, 2015

CAN Bus to UART using an Adafruit Pro Trinket

I have been fighting with the onboard CAN controller on my BeagleBone Black trying to
get it to work properly for months. In the process I learned about pin muxing, bone-capemgr and compiling overlays. I was able to bring up the can0 interface and receive can messages with candump but the interface was unstable. It would randomly hang and stop receiving messages. If I tried to send anything with cansend I would get a kernel stack traces in dmesg and the can0 interface would hang.  I tried Angstrom, Ubuntu and the latest Debian images all with the same results. Maybe my BBB board has a hardware problem. It is one of the early Rev B boards. Or maybe I'm running into some sort of kernel driver bug. Whatever the issue I am done trying to figure out what the eff is wrong with it and I just want to move forward with my project. (and yes I was using a transceiver). I considered bypassing the onboard can controller and talking to a MCP2515 over SPI but that gets into compiling a custom kernel for the BBB and I don't want to use up a SPI port. I mention all of this because I know someone out there will say "why didn't you just use the onboard can controller". I tried and I am done fighting with it.

My attempt at using the CAN controller on
the BBB with an MCP2562 transceiver

What now?

Once I decided I wasn't going to get the onboard BBB can controller to work I started thinking about options. My first attempt at a workaround was an Arduino Uno with a Seeed CAN Bus shield connected to the BBB with a USB cable. I read the data from the serial port created over the USB connection. While this worked it was a bit bulky and fragile. The USB cable is much too big, the Uno with a shield is big and the Uno would reset when serial communication started (though there is a workaround for this).

I took a break from this project for a while and in the meantime I ordered a few Adafruit Trinkets and Pro Trinkets just to play around with. The Pro Trinket has the same microcontroller as the Uno but the board is much, much smaller.

Size comparison between Uno, Pro Trinket and Trinket.
(Photo credit: Adafruit)

Pro Trinket CAN to UART Converter

The Pro Trinket has SPI and UART plus a bunch of digital and analog pins. After playing around with the Trinket I realized I could build a CAN Bus to UART converter that would be able to push CAN data into the BBB over a UART. The BeagleBone is a 3.3volt device so I used the 3volt version of the Pro Trinket so I didn't have to use any level shifters. For the CAN Bus controller I used an MCP2515 and for the CAN transceiver I used an MCP2562. The MCP2515 connects to the Arduino using a SPI connection. Here is the circuit I came up with:



Here is a Fritzing breadboard diagram of the circuit:

The UART serial connection between the Arduino and the BeagleBone runs at 115,200 bps so you might drop a few packets on a very busy CAN bus running at 500kbps. My Digital Dashboard project is only going to have a few devices broadcasting CAN packets so the UART speed will be more than enough for my purposes. The current version only transmits CAN data to the BBB. It should be fairly trivial to connect the BBB UART1 TX to the RX on the Arduino. It would also need a bit of code to parse the message received on the UART and write it to the CAN bus. I'm planning on adding the functionality soon and I'll write up another post when I have that done. I'm planning on changing the Arduino code to use an External Interrupt so the Trinket can perform a few other functions instead of just polling for incoming messages.

The Arduino Code

The way this works is the MCP2515 has an INT (interrupt) pin that signals when a CAN message has been received. The INT pin drives Pin3 on the Arduino low and triggers it to read messages from the MCP2515 buffer. Once a message has been read from the MCP2515 buffer it is formatted into a NMEA-ish string that is written to the serial port and transmitted to the BBB on UART1.

Screenshot of CAN data coming in on UART1

 Here is the Arduino code:



Setting up the BeagleBone

The pins on the BeagleBone need to be configured to be used as a UART. I used Adafruit's python IO library to do this. When you install their library it will create the overlays needed to configure the pins. Follow the instructions on their learn site here: https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black. Here is the code to receive the CAN messages on BBB UART1:


Costs

The price for these parts wasn't bad at all

Adafruit Pro Trinket 3v - $9.95
16Mhz Crystal - $1.12
Two 22pF ceramic capacitors - $0.66
MCP2515 CAN controller - $2.18
MCP2562 CAN transceiver - $1.12

Total: $15.03


Well that's it for now. Next I'm going to work on modifying the code to use External Interrupts and then see if I can get it setup to receive messages over the UART. I also need to get this thing moved from the breadboard and soldered on to some protoboard.




Resources
http://www.embedded-things.com/bbb/enable-canbus-on-the-beaglebone-black/
http://www.adafruit.com/product/2010
https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/uart
http://ww1.microchip.com/downloads/en/DeviceDoc/21801d.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/25167B.pdf

Sunday, October 5, 2014

Speed up screen redraws with a BeagleBone Black and Adafruit TFT

In a previous post I wrote about experimenting with the BeagleBone Black and an Adafruit 2.2" TFT screen. The TFT screen communicates over SPI using a userspace library. Being a userspace library it is expected it will be slower than driver that is compiled into the kernel but something in the code seemed to be causing redraws to be unnecessarily slow.

Adafruit 2.2" TFT with a BeagleBone Black
To measure how long the screen draws were taking I modified the example image.py script to read the time right before and right after the screen draw function call. I also wrapped a while loop around it so it would redraw the screen repeatedly to give me an average of how long it took.

Code to measure screen redraw time

Depending on how much of the screen was being redrawn and the load on the BBB it would take between 0.7 seconds to 0.9 seconds to execute the disp.display(image) function. The following output is for the example image.py that draws the cat.jpg file to the screen:

Output measuring screen redraw time

One of the commenters on my previous post tracked down the slowness to one specific function named 'image_to_data' in the file ILI9341.py. He also supplied a modification that reduced his screen redraw time dramatically by using NumPy. I tried it out and it reduced my screen redraw times dramatically. Screen redraws went from 0.85 seconds to 0.17 seconds. That is an 80% improvement!

Screen redraw times when using NumPy

If you want to make this modification yourself here is what you need to do:

1. Install PyNum. This is easy to install as it is available as a pkg.

Install the python-numpy package


2. Edit the file Adafruit_Python_ILI9341/Adafruit_ILI9341/ILI9341.py

First add the import statement at the top

Add import statement for numpy

Next modify the image_to_data function. Here is the original function

Original image_to_data function

and here is the function after being modified to use NumPy

Modified image_to_data function

3. Save the file and then re-run the installation script.



If you don't want to manually make these modifications you can use my forked version of the library: https://github.com/matt448/Adafruit_Python_ILI9341

I have submitted a pull request to Adafruit for this change so maybe in the future this will be included there. [UPDATE: Adafruit has pulled these changes into the master branch of their library. If you download the latest version here https://github.com/adafruit/Adafruit_Python_ILI9341 you will get the improved screen drawing speed.]


Here are videos before and after I made the change. It's quite noticeable when making quick changes. Before making the code changes the display would lag behind when adjustments were made to the pot.
BEFOREAFTER



[Updated 2014-10-08: Added before and after videos.]
[Updated 2015-03-11: Added note about my pull request being included in the main library.]