Showing posts with label BeagleBone Black. Show all posts
Showing posts with label BeagleBone Black. Show all posts

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.]


Friday, September 5, 2014

Experimenting with BeagleBone Black and a userspace TFT library

This post is part of a series of posts I have done about the Adafruit 2.2" TFT display. You can check out those previous posts here and here. In those previous posts I was using this display with an Arduino and ran into issues with the refresh rate. To get a decent refresh rate I had to do some extra coding to determine what data needed updating and then only redraw the sections of the screen that actually needed to change. In this post I am going to take a look at using this display with the BeagleBone Black single board computer. My hope going into this is that the CPU horsepower of the BBB will allow quicker screen redraws which would eliminate the need to selectively redraw sections of the screen.

Since the BBB is a full computer there is a Linux operating system sitting between the code and the hardware. This quite a bit different from an Arduino where you have direct access to the hardware. My BBB came with Angstrom Linux on it but I am more familiar with Ubuntu and the Adafruit tutorials were written assuming you have Ubuntu installed. So I swapped the OS to Ubuntu 14.04 following Adafruit's tutorial. To control the TFT display with a BBB Adafruit created a user space library in Python. To install the library and wire up the display I followed the instructions on learn.adafruit.com. The instructions were written for the 2.8 inch display but they worked just fine for my 2.2 inch display. I think these instructions would probably work for most ILI9341 based TFT displays.

The wiring for the 2.2" display is slightly different than the 2.8" display. Here is how I wired it up.

  • BeagleBone Black SCLK pin P9_22 to TFT SCK.
  • BeagleBone Black MOSI pin P9_18 to TFT MOSI.
  • BeagleBone Black CE0 pin P9_17 to TFT CS.
  • BeagleBone Black pin P9_12 to TFT RST.
  • BeagleBone Black pin P9_15 to TFT D/C.
  • BeagleBone Black 3.3V power pin P9_3 to TFT Vin.
  • BeagleBone Black ground pin P9_2 to TFT GND.

Then I ran the sample image.py application to make sure everything worked correctly



Now that we have all that stuff out of the way let's get to the real point of this post, how fast can the BBB update this display! To test it I took one of Adafruit's example scripts that came with the library and modified it so it read the value of an analog pin (P9_40) and then display that value on the TFT screen with a custom font. I connected a 10k pot to the analog pin so I could adjust the value.

The first time I ran the test script I ran into problem with the bottom the text being clipped off. Turns out it was a bug with a Python library. I detailed the fix for that here.

In the script I also recorded a time stamp before drawing the TFT screen and immediately after to measure how long it took to actually draw the screen.

Here is a video of the testing



If you made it to the end of the video you saw that it was taking approximately 0.6 seconds for the draw command to complete but the screen itself appears to update nearly instantly. This is a huge improvement compared to when I tested this display with an Arduino. On the Arduino you could see the screen slowly painting the image onto the screen.

Here is a video of the same exact test with an Arduino:



I'm not sure what is taking 0.6 seconds with the BBB. The screen redraws seem to happen faster than that. Maybe it's the data transfer over SPI plus the screen redraw (Update: See this post to learn how to speed up the redraws). In any case I am quite pleased with it. Another advantage of using the BBB is I'm able to use any TrueType font to display text. The library on the Arduino only had one font which became very blocky when using large characters. As you saw in the first video I used an Arial font which looked very smooth.

I originally wanted to use this TFT display for my speedometer project but abandoned it for a 7 segment display because the refresh rate was so slow with the Arduino. Based on these BBB results I think I'm going to make a v2.0 digital speedometer using both an Arduino and a BBB. The BBB isn't great at doing real time things like counting pulses so I think I will continue to use the Arduino to count the VSS pulses and then feed the speed data into the BBB over I2C or CAN. I'm already brainstorming other data to display on the screen...

Oh here is the python code I used to test this display if you are interested:





Helpful Links

https://learn.adafruit.com/user-space-spi-tft-python-library-ili9341-2-8/
https://learn.adafruit.com/beaglebone-black-installing-operating-systems
http://elinux.org/Beagleboard:Ubuntu_On_BeagleBone_Black


[Updated 2014-09-05]
This is in reference to my statement about about the BBB not being great at real time tasks. I've been doing some reading and the BBB does have a hardware counter on it but it looks like you have to be a NASA engineer to get it to work. This post discusses the PRU on the BBB. When he started talking about having to write Assembly code I tuned out. I'll just use an Arduino to do the accurate pulse counting, thanks.

[Updated 2014-10-04]
Added Fritzing wiring diagram and pin outs.

[Updated 2014-10-08]
Added link to post that shows how to speed up display redraws.



Monday, August 25, 2014

Font issues with BeagleBone Black and ILI9341 TFT display

In my continuing quest to build a really cool digital speedometer for my car I have been experimenting with an Adafruit 2.2" color TFT display. This past weekend I loaded up Ubuntu 14.04 on my BeagleBone Black and wired up the TFT display to it. Adafruit has a python library that works on both the BeagleBone Black and a Raspberry Pi. After trying out the example code I decided I wanted to try using a nicer font than the default one in the example code. The first font I tried seemed to look fine but the second font I tried had the bottom third of the characters not displayed. To figure out which fonts were affected I wrote a python script that cycled through displaying a bunch of fonts on the screen. Here is a video of the results:


As you can see some fonts are affected more than others. A few have over half the line cut off. I started digging into the code that displays the text. I figured out the code is determining the height and width of the text and then turning the text into an image to be displayed on the screen. This is done so text can easily be rotated on the display.

Line number 17 in this snippet of code is where the height and width is determined before making the image.
The Adafruit library is using PIL (Python Image Library) to create an image from the text. Ubuntu 14.04 actually uses a fork of PIL called Pillow. I did some google searches and discovered that the textsize function has a bug that does not account for the font offsets which causes the clipping on some fonts. The Ubuntu 14.04 I installed on my BBB came with Pillow 2.3.0 which was broken. I updated it to latest available package which was Pillow 2.5.3 and it was still broken. I looked at the bug fix on the master branch of Pillow and it was just a small change to one file, PIL/ImageFont.py, so I decided to apply that change to my 2.5.3 install of Pillow.

Here is how I fixed it.

cd /usr/local/lib/python2.7/dist-packages/PIL
sudo vi ImageFont.py

At about line 142 look for the getsize function. Here is what it looked like before the change.




And here it is after the change.


Save the file and then you need to compile it into python byte-code.
sudo pycompile ImageFont.py

This creates an ImageFont.pyc file. Now to test it again.



All fixed! I'm sure that fix to getsize will be pushed out soon so this won't be a problem in the future but until then this will let me continue my experimentation.