I've been meaning to keep a blog about this project. I've been working on it (on and off) since early this year, and it was meant to be ready for Berlin Makerfaire 2020, but it was cancelled. But I'm going to finish the project anyway for that date.
What is this project? Print your own adventure game with a thermal printer, Raspberry Pi, arcade buttons and CircuitPython.
Why am I doing this? Part of my job as Maker Advocate (Dublin Maker) to extend my knowledge in this area, always a fan and huge awareness, but always more of a spectator and supporter than active Maker of physical projects. Plus it's fun to try new things.
Well, I can say I am rusty as heck, but I needed the coding to while away the time. My goal was to complete my Maker project that was meant for Berlin Makerfaire in the next couple of weeks, but that has been cancelled due to COVID-19.
So I mustered my energy, blew the dust off the coding side of my brain and pulled out all my electronics bits and latest code from my repo. It was a working prototype on a given sample of a dummy data for the thermal printer to print out your text based adventure game.
So it was shock, horror and no surprise when I went to refactor the code, I was thinking... "What was I doing?!? Omgerd!"
The next part of the project was pretty straight forward, fix up the JSON to be read into the code so printer will work. With this new code, I'm no-where having it connected up with the electronics (I already know it worked from last time I was prototyping).
So to get this JSON file, I want to have a way I can add stories, so into a spreadsheet it goes, I export it to CSV file and this CSV file gets read in by the new CSV to JSON convertor I wrote in Python. Now it's a library I can use for my main project, yippee.
💡 Found this story/prompt generator handy for what I'm doing as I can't seem to think of anything story to write: https://www.plot-generator.org.uk/
I took it for granted. I spent a whole day wrangling code and ended up going to bed late as I was so close to what I wanted. I was going to try using Pandas instead of the general csv, itertools and groupby. Turns out when I got up the next morning, I was overthinking the problem and refactored (again). Didn't have to use Pandas (now I know a little about it), normal plain Python in-built tools was a-okay. 🙌
Also wrote tests (using PyTest) to make sure the data and JSON format is correct, and tested a sample run through of a game. Well, that was easier than expected and it worked. 🙌🙌
This is the project by the way, an early prototype (with Pi-top 3, I have a Raspberry Pi 3 in it) is pictured below...
👉 I'll be putting up pics and vids to my Flickr album: https://www.flickr.com/photos/whykay/albums/72157713817366118
My yellow and blue arcade buttons works!
Successful run of a sample game playthrough
Whoops, something went wrong, the image was too big, had to scale down the size and try again. It also made dreadful, distressing noises while printing this! 😱
Printing the Dublin Maker logo - take 2 - success! 🎉
Getting the case for the mini-thermal printer printed on our Prusa 3D printer at home
Anyway, now I have to refactor the main code that does the actual interaction with the hardware. Just have to remember to commit the latest code first! Learnt from last time. 😅
So after connecting up to a Pi-Top 4 (which is a Raspberry Pi 4), checked all the connections.
- ☑️ Power light going on and off on thermal printer - yay, it's powered!
- ☑️ Thermal printer is connected to ground and TX GPIO
- ☑️ Yellow, Blue and Black buttons all connected to its ground and GPIO pins
Then I tried a bit of code to start talking to the thermal printer via Python REPL.
❌ Well, that didn't work. It was hanging. It was trying to use
/dev/serial0, so I had a look and sure as anything, it's not there, just
/dev/serial1. I vaguely remember having this problem before.
Did a quick search on "Where is /dev/serial0 on Raspberry Pi?" and got the answer.
- Select option 5 (Interfacing options)
- Select option P6 (Serial)
This part is important:-
Save the configuration and exit rasp-config.
Reboot the Raspberry Pi.
Now when you check,
/dev/serial0 is available.
So I ran through setting up the thermal printer via Python REPL and by jammy dodgers it worked. I was able to print out a quick "Maker Advocate". 🎉
This is all set up ready for the next phase: Operation get it all to work again
It's the small wins that keeps me going. Like a couple of refactors of the aforementioned code for importing CSV and converting to JSON so I can use it for this project.
I found that it was working but crapping out sometimes, and after a few goes, I realised it was the content from the JSON file, it had unicode characters that was throwing the thermal printer library off. So I removed these odd characters, mainly converted to apostrophes. This is the reason for not to copy and paste willy nilly. 😭
It was all going well until I tried to print an image on the thermal printer and it didn't recognise the command
printer.image(Image.open("thepic.png")). I double-checked that I installed PIL (via Pillow) and checked the printer object with the Python REPL. Still no dice... 🤔
Did a quick search and sure enough, there's another library for the thermal printer: https://thermalprinter.readthedocs.io/en/latest/index.html. And it has the call to print an image, yay! 🙌
pip install thermalprinter and the following:
>>> from PIL import Image >>> from ThermalPrinter import * >>> printer = ThermalPrinter(port="/dev/serial0") >>> printer.image(Image.open("thepic.png"))
And it worked! 🙌🙌
Now I had to go through the code and update the calls as it's slightly different, but easier and nicer to use. I tried to have the image called at the bottom, but it came out all mangled and lost some of my text. So I put it at the top and it worked a treat. So the image is staying at the top. 😜
Here's the video of a playthrough:
And the finished printout from the playthough:
Finally, it's also colour blind-friendly colour buttons:
- Circuit Python and Arduino support for thermal printer
- Circuit Python for thermal printer (alternate and works better espec with image handling)
- Mu Editor
- Python 3