Intro: Display Colorful Message in Limited Resources
In many MCU projects, there are a big challenge on how to display a human readable message.
This Instructables demostrate how to use a very limited resources (1 KB ROM, 64 Bytes RAM and 60 LEDs) to display a colorful message.
Step 1: What I Have?
- 1 KB flash program memory
- 64 Bytes RAM
- 5 IO pins
1 M (60 LEDs) WS2812 strip
This is reuse from previous project:
Step 2: List Out the Challenge
In font size 8x6, if display 1 row 8 characters require 8x6x8 = 384 pixels
In U8glib, smallest font is 6x5, display 4 characters still require 6x5x4 = 120 pixels
But I want to try displaying message (HELLO WORLD!) use only 60 pixels.
Limited IO pins
Some LED matrix circuit require IO = width + height, but ATtiny13A only have 5 IO pins. Hopefully WS2812 strip only require 1 IO pin to drive it.
I have tried some Arduino WS2812 library, all example excess ATtiny13A 1 KB limit. light_ws2812 is the smallest one, Hopefully it have sample code direct compile with avr-gcc, it is much smaller!
And then font binary is another memory consumer, 8x6 font size for 97 ASCII characters use (8x6)/8x97 = 582 bytes!
In all WS2812 library, it require a full bitmap buffer as a parameter. 60 pixel RGB buffer require 60 x 3 = 180 bytes, but ATtiny13A only have 64 bytes RAM! It excess too much, I nearly give up!
Hopefully light_ws2812 library code is easy to read and I found I can store only a mono bitmap and dynamic return the color value by a function.
But it still another challenge, since the function call each time before sending 8 bits value to WS2812, so the function must not run over 50 us or it will treat as a new cycle. i.e. fail to send data to all 60 LEDs.
Display power consumption
According to the specification, each WS2812 can consume around 60 mA power, 60 pixels can draw 3.6 A; 384 pixels can draw over 20 A!
So in my example, the color value far lower than the maximum possible value (255), the maximum light value I use is 7 only. it can keep the platform only draw below 30 mA while powered by Lipo battery.
Step 3: Technique Used
Since we cannot indefinitely increase pixels while wanting display more characters, most common way is scrolling the message. Then how much display area it should have, I think it should at least can display 3-4 characters at the same time.
Halftone is actually the reprographic technique commonly used in press. Inspired from the concept of rotating the matrix 45 degree to improve the reprographic quality, it can help reduce 50% of pixel in this project!
Step 4: Design Font
Since there not yet have an halftone font, I have write a simple web page to design one. I have tried many combination, 5x6 (thanks to halftone, it become 5x3) font size is the least readable size. Each character use 5x3 = 15 bit, it can fit for 2 bytes data. Then 97 ASCII characters use 2x97 = 194 bytes, around 20% of program memory.
You may download the web page and design your own font here:
Step 5: Program
Program without Arduino is a little different and difficult.
- avr-gcc: http://www.nongnu.org/avr-libc/
- make: https://www.gnu.org/software/make/
- avrdude: http://www.nongnu.org/avrdude/
After download the code and install above software:
Simple run "make" in the "Examples/WS2812_Halftone_ATtiny13A" will program the ATtiny13A.
If it is too difficult for you and you have DigiSpark in hand, you may try another example in "Examples/WS2812_Halftone_DigiSpark".
Arduino example should coming soon. :)
ATtiny13A example: program 974 bytes, memory 22 bytes
Digispark example: program 1378 bytes, memory 203 bytes
Step 6: Patch the LED Strip
Cut the 1 M LED Strip to 5 parts, each have 12 LEDs.
Prepare a plastic around 5 cm x 22 cm in size, stick the strip on a plastic plate. the first LED (with wire connected) start at left top corner. The the second row start from right left and align around 8.3 mm left apart from first row; the third row start from left to right and align with the first row...
Solder the LED strip with wire, the connection is as same as what you cut.
Step 7: Connect
The connection is very simple:
ATtiny13A pin 2 -> LED strip signal pin
ATtiny13A pin 4 -> LED strip Vcc pin -> Lipo +ve
ATtiny13A pin 8 -> LED strip GND pin -> Lipo -ve
If you are trying Digispark or Arduino example, signal pin should connect to pin 6.
You may use a butter paper or an A4 paper to folder a light diffuser for better display result.
Step 8: HELLO WORLD!
If everything goes well, you can see "HELLO WORLD!" message scrolling.
Step 9: What's Next?
- 5x6 halftone font only have 80% readability, 8x6 halftone font (3 bytes@character) should have much better result
- "Hello World!" use 12 characters, I have tested the example code can display over 30 characters (half of available RAM)
- ATtiny13A still have another type of memory, EEPROM, if store and read the message from EEPROM, it can display 64 characters
- How about store the font in EEPROM? If you only require a subset of 97 ASCII characters, you can store the font binary in EEPROM; If you are using Digispark / ATtiny85 / other Arduino board, you are store full set of 8x6 halftone font (291 bytes) in EEPROM
- Design your own font
- Design your own color pattern