This is a simple demonstration of persistence of vision (POV) using the Atmel ATmega8 microcontroller and eight LEDs to display ASCII-Strings.
I just wanted to try it out myself :-) (there are tons of projects like this online)
A few images of the final result:
The idea and large parts of the code are mainly taken from Chapter 3, povToy.c of the book Make: AVR Programming by Elliot Williams, who made his source code publicly available on github: AVR-Programming. The source code was originally written for the ATmega 168, which is also used in the popular Arduino, so a few very small changes were necessary to port it to the ATmega8. The awesome CMake toolchain file for AVR microcontrollers and the corresponding CMakeLists.txt are taken from Matthias Kleemann. The fonts are not directly included (see below for details why)
First, clone the project: git clone https://github.com/stfnw/pov-ascii
To build and flash the program onto the microcontroller run the following commands:
# first manually add a font file under pov-ascii/lib
cp <path-to-some-font.h> pov-ascii/lib/
mkdir pov-ascii/build
cd pov-ascii/build
cmake ../
make upload_pov-ascii
POV works, because the eye does not react instantaneously to stimulus and therefore a small flash of light leaves a short afterimage and is perceived for a longer time than the light is actually turned on. This optical illusion allows the drawing of seemingly floating shapes in the air, for example by turning LEDs on and off in a fast pattern and waving them around.
To display text, the different characters and symbols of the alphabet have to be translated to the corresponding blink-patterns for the LEDs. In C, this is usually done by saving the needed characters in a two-dimensional array in a separate header-file, where each inner array represents one character.
For example, to display the letter A
with five LEDs (ignoring the other three bits of one byte), one could use the following pattern (where each 1
represents one turned-on LED and each 0
represents one turned-off LED)
char A = {
0b00010000,
0b00001000,
0b00000100,
0b00000110,
0b00000101,
0b00000110,
0b00000100,
0b00001000,
0b00010000,
};
Written in hexadecimal this is a bit shorter, but unfortunately looks a bit more cryptic: char A = { 0x10, 0x08, 0x04, 0x06, 0x05, 0x06, 0x04, 0x08, 0x1F }
Without the 0
s the pattern itself looks like this: an A
rotated by 90 degrees
1
1
1
11
1 1
11
1
1
1
The fonts used for this project are truncated to represent a subset of ASCII characters, more specifically the range from 0x20
(SPACE) to 0x7F
(DEL).
They are not directly included, because I am not sure under which license - if any - they were published.
However, here are a few example links where I took some fonts from:
- https://www.mikrocontroller.net/topic/54860 (direct link to zip)
- https://github.com/radikalbytes/Arduino-POV-minimalist/blob/master/Arduino%20code/fonts.h
- http://jared.geek.nz/2014/jan/custom-fonts-for-microcontrollers (direct link to zip)
Manually building and editing POV-fonts is a quite tedious and time-consuming task. Fortunately there are ways to automate this and convert a TrueType font to a C-Array.
Usually this requires two steps:
-
converting the TrueType font (a vector font) to a bitmap font or a series of black-and-white bitmaps for each character a general discussion of this step can for example be found here:
- http://stackoverflow.com/questions/2672144/dump-characters-glyphs-from-truetype-font-ttf-into-bitmaps
- http://stackoverflow.com/questions/17142331/convert-truetype-glyphs-to-png-image
for a scripted approach of this step based on ImageMagick, see e.g. https://github.com/yukinoraru/ttf2png
-
converting each bitmap to the corresponding C-Array by iterating over it pixel for pixel
During my search for a solution, I came across someone way smarter than me (Jared Sanson), who already had taken a bit of his time and wrote a small python script based on the Python Imaging Library (PIL) to automate the whole process. With a bit of parameter tweaking (e.g. the right settings for character height and width) and a good pixel font as basis, the result can be quite remarkable.