All posts by nouyang

diary: somehow i’m graduating; and misc. arts and crafts

guess i’m graduating in two months? if i get my work done? but i feel so burnt out about it, which is confusing. i think i should feel happy and productive. i’m not sure what’s going on. i guess i don’t have anything to look forward to, really, after ward. no happy post doc, job, vacation, etc. awaits me. (but shouldn’t i find happiness where i am?)

have you ever picked up serial crafts to avoid thinking about work, because

embroidered cat brooch

first i tried embroidery, there’s a ~$16 embroider-patch-cat kit online. i liked it a lot actually! it has a video of the full process (20 mins) on youtube and on amazon.

how does it turn into a brooch?

after embroidering, you cut it and the back piece out. then you sew / glue on the pin to the back piece. then hem the two together (watch the video — turns out you use a running stitch to get the two pieces aligned, then go back with a x2 thread to hem so it looks neater). (I left a little gap and put in some stuffing to make it plush).

lessons learned:

  • where to place stitches? i imagine where i’d make a line if i was coloring it in with a gel pen, to mimic the direction of the cat’s fur
  • watch very carefully at the beginning that pull the thread all the way through — i could make a snarl in 10 seconds / two pulls through the cloth, that would take 5 mins to undo. frustration
  • Re the hem of the cat: “hemming is easy right, just keep looping it back and forth a lot” “wait i should fill in this spot” “wait now the threads are crossed” “mother of pearl wtf happened”
  • to separate the embroidery floss, which has 6 strands, into individual strands (most of it is done with a single strand, looped around the needle so it’s two strands going through the fabric) — can start separating from the center and pull through
  • can use wax (or soap) to make separating earlier / get some of the loose fuzz gone

so much regret, so quickly (thread tangles)

then i tried cross stitch

there’s a ~$10 pusheen kit online

it’s oddly addicting. just filling it in one square at a time.

with a side of paint-by-numbers

you get the wood frames, which have a bit of gold, and have outlines milled out. and one brush (I supplemented my own). and all the colors, and some instructions.

how to get circuitpython working on the $17 waveshare rp2040 LCD board (bonus: add unicode characters to a BDF font file for more c a t _ฅ^•ﻌ•^ฅ_ )

friend gave me a waveshare LCD, it’s got IMU + rp2040 microcontroller + lipo 1S charger + 1.28” LCD screen (full color!), and usb-C connector to boot, for $17. Jeez. What has this world come to XD; anyhow, so finally got around to playing around with it 😀

This is their demo (you plug in to power and get this)

And this is my “Hello World” 😀

(Ignore red circle for now, I’ll explain later)

And the code is really straightforward:

   def main_menu(self, sleep_time=0.05):
        self.fill(self.color('purple'))
        self.draw_text("banner_text", 20, 100, "Hello World!",
                       self.color('white'),
                       self.font)

        self.draw_text("banner_text", 50, 150, "_ฅ^•ﻌ•^ฅ_",
                        self.color('white'),
                        self.font)
        # self.draw_text("banner_text", 60, 200, "ฅ",
 
        while True:
            self.update() 

Here are the steps I took.

get board to show up as usb drive

(This is starting just from the board out of the box!)

First, I had a frustrating 30 mins where I couldn’t get the board to show up no matter what buttons I held down. Turns out it was just a flaky USB-C cable. ^^; The board has two buttons, boot and reset.

So lessons: To boot into USB drive: what is universal for rp2040 boards (as opposed to specific to e.g. adafruit boards) is to hold BOOT, power on (plug in), then press and release SELECT. The board should up as USB drive then. (rpi something, I forget). (After pressing SELECT, you can release BOOT, or wait for the board to show up before releasing BOOT, shouldn’t matter).

Install Circuitpython

To load circuitpython (should be one-time, unless you f*k up your program or something, which I’ve done)
Copy UF2 (compiled python) file to the board.

https://circuitpython.org/board/waveshare_rp2040_lcd_1_28/

It will have a name such as:
adafruit-circuitpython-waveshare_rp2040_lcd_1_28-en_US-8.1.0.uf2

Board will then disappear and then reappear with name “CircuitPython” and the file “code.py”. Now you’re in business!

Then, the waveshare demo file uses micropython instead of circuitpython.
(Circuitpython is a fork of micropython with some sensible defaults).
So I used this code from a reddit user which is written in circuitpython.

https://www.reddit.com/r/circuitpython/comments/11fmwcq/waveshare_rp2040lcd128_example_code/

Copy the file into code.py

However when I ran, got error due to missing libraries. (See Debugging section for more info).

Install libraries

Circuitpython has a bunch of common libraries. Looking at the import statements of the internet demo file,

https://circuitpython.org/libraries

I needed the folders

adafruit_gfx
adafruit_bitmap_font
adafruit_display_text

Therefore, unzip. Make a ‘lib’ folder in your rp2040. Put folders in.
e.g. On a Mac, this structure would look like

├── code.py
└── lib
├── adafruit_bitmap_font
├── adafruit_display_text
└── adafruit_gfx

Additionally, I needed a “gc9a01” library which was not in the circuitpython library bundle.

I copied the contents of this file.
https://github.com/tylercrumpton/CircuitPython_GC9A01

Into a file on the root folder of the rp2040.

.
├── code.py
├── gc9a01.py
└── lib

fonts: Glyph Bitmap Distribution Format (BDF)

Finally, I did not have the font. mfbold.bdf
I elected to change the font used in the code, since I didn’t have that file anyway. I used Spleen, and the font size 16 width by 32 height pixels.

https://github.com/fcambus/spleen

https://raw.githubusercontent.com/fcambus/spleen/master/spleen-16×32.bdf

Looking at the internet code,

bitmap_font.load_font("font/mfbold.bdf")

it expects the font in the folder “font” on the root folder (you can actually put the BDF anywhere you want). So I created a “font” folder and put the Spleen bdf file in there. Finally I changed the “load_font” in the internet code.

bitmap_font.load_font("font/spleen-16x32.bdf")

final folder structure


owls@owls:/Volumes/CIRCUITPY$ tree -L 2
├── code.py
├── font
│   └── spleen-16x32.bdf
├── gc9a01.py
├── internet_copy.py
└── lib
├── adafruit_bitmap_font
├── adafruit_display_text
└── adafruit_gfx

Hurray!

Note: on linux the filepath is under “media”, e.g.

/media/owls/CIRCUITPY$

final code

I stripped out the IMU code, since I’m not interested in it for a hello world. Therefore my final code file:

(See link to zip file at the bottom)

hexadecimal font fun: more unicode cats _ฅ^•ﻌ•^ฅ_

The font file does not contain ALL the unicode ever, since microcontrollers are short on space. (The spleen is already a huge 238kb).

Therefore when I tried to display the unicode cat “_ฅ^•ﻌ•^ฅ” the microcontroller skipped the ฅ and the ﻌ characters.

Fortunately The BDF file format is straightforward ! So we can just manually add one or two characters.

Literally it is 1s and 0s. Here’s an example. (I’ll explain how I got this picture in a moment)


The first row is all 0’s. So it would look like
0 0 0 0

This happens for several rows.

Now let’s look at the row I highlighted in red.

If you read off the pixels, it’s

[0 0 0 0] [0 1 1 0] [0 0 1 1] [0 0 0 0]

Now in decimal that’s

0 (4+2) (2+1) 0
0 6 3 0

And that’s one row in the BDF file! done 🙂

hexadecimal

There’s just one trick, which is that there are 16 possible combinations, so we use hexadecimal instead. So if we look at the orange row, we have

[0001] [1110] [0010] [0100]

Which is in decimal

1 (8+4+2) 2 4
1 14 2 4

Now we need to turn the 14 into a single character, a.k.a. in hexadecimal. So we have 0 to 9, then we know that 10 = A, and 16 = F. So we have

1 D 2 4

for this row.
Anyway, so at the end, we have a cat’s paw 🙂

Oh, and finally, for the BDF to work properly we also need the unicode number (?).
So you’ll see the in the BDF file lines like this:

STARTCHAR LATIN CAPITAL LETTER A
ENCODING 65

This corresponds to ASCII.

STARTCHAR LATIN CAPITAL LETTER B
ENCODING 66

The Spleen font goes pretty far down the unicode, but didn’t have these characters. So then I looked up the number using python’s ord() function. Looking up the codepoint using the ord function (can e.g. be used to look up ascii table)

ord('A')
65
ord('B')
66

ord('ฅ')
3589
ord('ﻌ')
65228

Hurray! All done.

example of error

if you look at the 8… I originally had a 9 there. So …


… my cat ended up with a nostril !

How to set up GIMP

Well, you simply type the character into GIMP, set an approximate font size, and then do a 4×1 grid to help. (I also used a “y” character to roughly line up the character vertically, fortunately it’s very easy to shift characters up and down — just add or subtract lines of 0s.

Also, turn off anti-aliasing.


Go to View -> Show Grid. Also, go to Image -> Configure Grid. You want a 4×1 pixel grid to easily read off the hexadecimal

(Note: you can click the lock/link icon below the spacing, so that you can adjust the height without adjusting the width).

Debugging

Debugging is fun!

On Mac,

$ brew install minicom
$ minicom -D /dev/tty.usbmodem101

Linux:


$ apt install minicom
$ minicom -D /dev/ttyACM0 

(You can check the port with $ ls /dev/tty*)

Your rp2040 will be running your code. So then to get to a prompt (REPL), hit ctrl-C, and you should see:


Adafruit CircuitPython 8.1.0 on 2023-05-22; Waveshare RP2040-LCD-1.28 with rp2040
>> print('hi')
hi

Now if you hit ctrl-c again, it will reboot and try to run your code again, but this time you can see the error messages also.


0;🐍Done | 8.1.0soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
0;🐍code.py | 8.1.0Traceback (most recent call last):
File "code.py", line 1, in
ImportError: no module named 'machine'
0;🐍1@code.py ImportError | 8.1.0
Code done running.

Traceback (most recent call last):
File "code.py", line 1207, in
File "code.py", line 1193, in main_menu
File "code.py", line 1047, in banner_demo
File "adafruit_bitmap_font/bitmap_font.py", line 47, in load_font
OSError: [Errno 2] No such file/directory: font/mfbold.bdf
0;🐍47@adafruit_bitmap_font/bitmap_font OSError | 8.1.0

The funny/awesome thing is that with an LCD screen you can also see the error displayed:


0;🐍Done | 8.1.0soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. code.py output: 0;🐍code.py | 8.1.0Traceback (most recent call last): File "code.py", line 1, in ImportError: no module named 'machine' 0;🐍1@code.py ImportError | 8.1.0 Code done running.

Traceback (most recent call last): File "code.py", line 1207, in File "code.py", line 1193, in main_menu File "code.py", line 1047, in banner_demo File "adafruit_bitmap_font/bitmap_font.py", line 47, in load_font OSError: [Errno 2] No such file/directory: font/mfbold.bdf 0;🐍47@adafruit_bitmap_font/bitmap_font OSError | 8.1.0

The funny/awesome thing is that with an LCD screen you can also see the error displayed:

reference: here are the files as a 173kb zip

these would go onto the CIRCUITPY usb drive