The finished product in all it's glory, surrounded by the corpses of failed attempts.
The "motor interchange board", aka the relay thingy.
The case that never was.
The printer's control board, hacked to integrate with my own control circuitry.
A work-in-progress shot from earlier on. Spot the voltage regular which caused me hours of "fun".
The USB-stick-voltage-regulator-heatsink. It did get toasty though.
My makeshift soldering station, aka an amazon box. It's okay, because the carpet didn't actually catch fire, despite all odds.
QUICK NOTE there are two videos in a playlist, because I have poor planning skills. And for some reason they seem to be in the wrong order. They're both good though, well imo anyway.
I was in need of a way to let even more people know that Haskell is my favourite language. This is the solution.
What it does
Basically a keyboard hooked up to a GHCi (the Haskell REPL) instance, which outputs to an Epson receipt printer and a 20x4 LCD display. You can type in a line of Haskell, just as you would in GHCi, and it will pass it to a GHCi process running in the background, then read the output back to write out onto the printer. When you type "quit", it will tear off your receipt so you can pull it out of the machine.
How I built it
I bought an Epson receipt printer a couple of weeks ago in preparation, as well as some relays (these will come in handy later.) First thing I did on the day was try to figure out how to reverse the paper feeding motor so I can pull the paper back in, allowing me to print output lines more compactly. This was FRUSTRATING to say the least, so I'll go into more detail in the next section but long story short it took me about 10 hours.
After that it was onto the Haskell evaluation code. Of course this was also more difficult than I expected but at least it was software so I was more in my comfort zone. I used Python for all the software running on the Pi. It's a bit hacky, but it works. When the program starts, I also create a GHCi process in the background, then when I need to evaluate some Haskell I send the input to the interpreter over stdin, and I read it back through stdout. You may wonder "what about stderr????" well I made a script to start up GHCi which automatically redirects all stderr into stdout so I don't have to worry about that.
The evaluation side also took longer than expected because I could not for the life of me get the prompt to not show on the first repl instance. To get around this, I just ignored the first line of the output regardless of what it says. Again, I told you this is hacky.
Finally I plugged the LCD in over an I2C interface which went relatively smoothly using some script I found on the internet, and then made a cardboard box into a nice carry case.
Challenges I ran into
So as mentioned, I spent about 10 hours trying to get the feed motor to reverse. The situation is this, we have a stepper motor attached to a gear chain which drives a roller which feeds paper through the system. Usually, this will only run one way in response to various ESC/POS commands, but I wanted to be able to feed the paper back into the system. My plan was, if I swap round the 4 wires going in, the motor will reverse. And how do I do this? Well get two relays, of course. But, I don't know much about electronics, and I especially didn't know much about electronics yesterday, so this had me scouring dozens of datasheets and websites and calculators trying to work out how to power these relays.
I initially came to the conclusion that the GPIO pins on my Pi won't be powerful enough to power the relays. I thought this because I plugged it in and it didn't want to power it. So, I decided to power these relays using MOSFETs, which should let me boost the voltage to a 24V supply from the printer (lots of sparks ensued.) This of course didn't work either because the Pi didn't have enough voltage to power the MOSFETs I bought :( So then, I tried to use a transistor to power the MOSFET to power the relays. Which also didn't work. Same reason. OR SO I THOUGHT. Turns out I misread the datasheet and I had my relays upside down. Yep. 10 hours wasted...... Still upset about that.
I plugged the relays in the CORRECT way round and they worked first try. Which I guess is good?
Second annoying problem was that the Pi would refuse to register all keyboard events. I was running headless and writing my code over SSH, so I couldn't just plug a keyboard in and it would work. I had to pipe my events from
/dev/tty1. This almost worked except, due to buffering, entire lines would just be skipped sometimes. Not ideal. This was another few hours down the drain and I still have no idea how I was supposed to fix it the proper way so I just found a python library to do it for me. They have everything don't they.
Also to name a few others, and in the name of hacky-ness: the motor wouldn't spin in reverse unless the lid was pressed down so I tied a LITERAL shoe string around the printer to hold it down. Some of my socket wires were too fat so I had to sand down the jumper connectors in order to fit them into the control board. I soldered up part of a USB stick I got as swag from last HackNotts to use as a heatsink. I went through 3 (three) raspberry pis in the making of this project. Don't ask how. I flip-flopped between using a voltage regulator and not using a voltage regulator about 5 times before breaking it which sort of made the decision for me.
Accomplishments that I'm proud of
This project is actually something I've been meaning to do for a while but just have not had the time due to coursework etc etc so this actually gave me the time to sit down and finish it, which was nice. Also, I now have a funny story to tell about my 10 hour relay delay >:(.
What I learned
I learned a lot about electronics, the analogue side mostly. In the past I've only really done digital logic so this was mostly new to me. I also learned about the ESC/POS command set which is how Epson receipt printers communicate with computers. It's really cool actually, it has commands for printing images, barcodes, and even QR codes! Finally, I learned quite a bit about inter-process communication because I'd never really done a whole lot of process communication over pipes before.
What's next for The Haskelltron 2000
I've got loads of ideas, hopefully when the hackspace opens up again after lockdown I can get this all done. Firstly I want to make a nice wooden case instead of the flimsy cardboard one (which I didn't even get to show in the demo but there's a photo). I'd also like to make it actually portable so I don't need to plug it into mains. I also want to integrate it with the Haskell diagrams library so I can write the code for an SVG graphic and have it render directly on the receipt. For now though I'm excited to be able to have the coolest computer in my Haskell lectures.