New paper

I picked up 1000 sheets of continuous-feed paper on Amazon for
~$16. Works a bit better than manually feeding filler paper. I haven't
tested it with a long print run yet, so it's entirely possible I'll
have to build some guides for it.

New Arduinos

I also grabbed some Arduino Nano clones to replace some of my
"prototyping" Arduinos (I generally use Nanos/normal Arduinos with the
headers removed for permanent projects, but keep a couple around that
have breadboard pins precisely for this sort of
prototyping). Replacing the boards was simple, obviously, and allowed
me to close the device back up, so it now genuinely just looks like an
electric typewriter with a USB cord.

Motion control improvements

One issue I noticed immediately was that the stepper motor control in
the Arduinos was not the best. The driver was programmed to simply
either run the stepper at a certain speed or not run it at all. To
explain why that's not the best way to do it, here's a little about
how stepper motors work physics-wise.

Essentially, the assumption that my code was making was that the
stepper motion starts and stops instantly; the rotor is at angle x
and not rotating, you apply a step, and the rotor is now at angle
x+1 and not rotating. In reality, of course, that doesn't happen;
the rotor has mass and therefore rotational inertia. What is happening
is that the step applies a torque to the rotor, which needs to move it
far enough before the next step happens to allow the next pole to
'grab' the rotor; if you try to step too fast, the rotor can't keep up
and just sits in place and makes an annoying buzzing noise.

This limit to the rotor's angular acceleration restricts a naive
controller to the maximum speed that can be obtained with one step's
worth of acceleration. However, I know from my 3D printer experience
that that speed is far below the actual top speed of the motor. Once
the rotor is spinning, if you step slightly faster than is required
to maintain its speed, you can accelerate the rotor beyond its current
speed, and thereby reach a higher maximum velocity throughout the
move. The process can be repeated to decelerate the motor at the end
of the move.

I also at the same time decided to enhance the controls so that
multiple moves could be executed at the same time. Previously, the
carriage would advance, the wheel would spin, and the hammer would
fire one after another with every part coming to a complete stop
before the next move started. However, that wastes a lot of
time. Ideally, each motor in the typewriter would be running all the
time, and to achieve that I again looked at 3D printer controls. Most
3D printers use a 'motion planner', a subsystem entirely devoted to
answering the question of "what is the best way to get from the
machine's current position to the next vertex?", and I realized that
this machine can be seen as a weird sort of Cartesian robot: each
position can be represented as a triple (row, column, wheel
index). It's then obvious that the easiest way to get from one
character to the next is a diagonal move; i.e. moving both the
carriage and the wheel simultaneously.

The system I ended up using is pretty simple; each axis stores its
current position, its target position, and some auxiliary numbers
related to its acceleration state. A rather high-frequency timer
interrupt processes the movement queue and allows the main thread to
block on stepper moves. That system manages the movement to the point
where often the limiting factor in print speed is how fast the hammer
can actuate.

Linux ttyUSBx devices are weird

So everyone knows howdisclaimer: not everyone might actually know
how when you press ^S in the terminal it quits working
until you press ^Q; this is a commonality among most UNIX terminals
and is generally seen as a nuisance.

These control sequences are more properly known as Xon/DC1 for
^Q and Xoff/DC3 for ^S. Their origin lies in the days of slow
modems and teleprinters that, while they may have a 9600 baud (say)
connection to their computer, aren't actually capable of processing
1200 characters a second. The solution to this problem was something
called flow control. When the terminal device (or modem or printer
or whatever)'s internal recieve buffer was getting full, it would send
an Xoff back to the computer, which would then stop sending and
allow the device to drain its buffer until it sent an Xon instead.

Since this device is only capable of around 5-10 characters per second
(for now; more movement optimizations are coming Soontm),
it would obviously benefit from flow control. I set up some simple
code to send Xon/Xoff appropriately and discovered (eventually)
that Linux doesn't honor flow control on USB serial ports.

This just confuses me. There's flow control on my screen console /
terminal emulator, but not on a physical serial device. How strange.

My solution was simply to write a getty-like program that handled
flow control on its own and ran the serial line in raw mode. The
program runs a shell in a PTY and just copies the PTY output to the
serial line only when the flow control says it should. As far as I can
tell, the reason Linux doesn't do the flow control on ttyUSBx ports
is because the USB serial protocol has its own form of out-of-band
flow control for the USB connection (if the USB bandwidth is exceeded
it'll cause blocking reads/writes) and the maintainers figured nobody
is gonna try to hook up a device that only handles 10 cps in
2018. Once again, the universe invents a better idiot.

Next steps

The USB cable comes out the front right now. I'd like to put a
panel-mounted USB B port on it.

The hammer actuation has numerous issues. The motor has a worn-out
commutator (meaning that it's got a few positions that if it stops
in that position it can't start again), and a replacement remained
elusive even after 30 minutes of Googling part numbers.

The paper isn't going to track perfectly after a good few pages get
through, so I had ought to build a guide of some sort that uses the
tractor-feed holes in the paper.

The typewheel doesn't have all of ASCII, and it has a few non-ASCII
characters. I don't know if they made an ASCII-compatible typewheel
for this (probably not; all I can find are serif/script wheels) but
if there's any way to obtain/make one it should be done.

Both the ribbon and correction tape are out and I haven't bothered
to get more yet.