If you've done other CircuitPython projects involving text and displays, you've probably used a custom font file. That's a great way to get a nice custom look to project read outs. But you may have noticed - this project has no font file.
So how did we get those nice bold text readouts? Let's talk about that a bit. It's a trick that could be useful for other projects. We'll mainly focus on the way the CO2 reading was done.
Sprite Sheet Instead of Font File
At the heart of the CircuitPython displayio library is the concept of TileGrids. This lets you carve up a source bitmap into multiple sections (tiles) and then layout one or more of them (grid). You can do this with any bitmap, but here we use one that contains the numbers 0-9. It was created by hand in GIMP:
The max value the SCD30 can report is 10000 ppm. Ignoring that upper limit, every other reading is at most 4 digits wide. The LED matrix we use is 32 pixels wide. Mathy McMathy says "32 / 4 = 8" so we make each digit be 8 pixels wide. We chose 10 pixels for the height as a "meh, that looks about right" value.
Loading the source Bitmap into our code is just one line of code:
digits_bmp, digits_pal = adafruit_imageload.load("/bmps/digits.bmp")
Setting up our TileGrid that will use this source Bitmap is also a single line of code, but there are numerous parameters that get used:
co2_value = displayio.TileGrid( digits_bmp, pixel_shader=digits_pal, x=0, y=51, width=4, height=1, tile_width=8, tile_height=10, )
We tell it to use digits_bmp
, and its associate color palette digits_pal
, as our source Bitmap. We also go ahead and set our location on the matrix with x
and y
. Now for the more important ones to understand. With width
and height
we are setting the size of the resulting TileGrid in terms of number of tiles. The similarly named tile_width
and tile_height
are what actually set the individual tile size - and how the source bitmap is carved up. The result looks something like this:
The co2_value
TileGrid is 4 x 1 tiles. Each of these tiles can "point" to any of the possible source tiles, 0 - 10, from the source Bitmap digits_bmp
. The syntax for doing that would look like:
co2_value[1] = 4
to set the second digit (index 1) to 4 as an example.
By creating our source bitmap with the digits arranged as they are, the indices correspond to the actual digits, 3=3, 7=7, etc. That lets us use the digits from the actual CO2 reading to set each tile. That's what this bit of code does:
# CO2 value # clear it for i in range(4): co2_value[i] = 10 # update it i = 3 while value: co2_value[i] = value % 10 value = int(value / 10) i -= 1
So it looks like we are printing text using a blocky font, but we are not. It's all done with a bitmap file. Pretty neat trick, huh?
Why Do That?
So why do this TileGrid / Bitmap file approach vs. just using a font file and formatted prints? Mainly for precise control of the resulting output. Like pixel-by-pixel control. The LED matrix is physically large but is pretty low resolution - only 64 x 32. And our CO2 value readout uses only 8x10 pixel digits. Getting a font to render exactly like you want at that low of a resolution can sometimes be tricky. And since we only needed digits, not a full alphabet, we just felt we could get there quicker with this approach.
TileGrids can be a bit tricky to wrap your head around at first. Hopefully this example not only helps illustrate how they work, but also maybe a neat way you can use them in your projects. Be sure to checkout the Displayio Learn Guide for more details.
Changing The Text Labels
The text readouts are done with the four English words GOOD, POOR, WARN, and DANG. This was also done using a TileGrid / Bitmap combo. Here's the source bitmap:
It's simpler than the CO2 value read out. It's just a single tile which points to one of the 32x16 pixel words. If you wanted to change the text, you could do so by editing the source bitmap. Since it's a bitmap, you can make it be whatever you want. No need to find a font that supports a specific language.
So they could also be changed if you wanted by simply editing each of the sub 32x32 pixel icons.
Text editor powered by tinymce.