DottyMatrix: Printing to an actual printer

It seems the repairs to my venerable Epson MX-80 F/T III dot matrix printer did actually work because it’s now printing again! What’s more, it’s printing via the prototype of my DottyMatrix serial to Centronics parallel interface.

Time for a quick recap.

The DottyMatrix is based around an AVR ATMEGA328PB microcontroller. It takes input on a TTL-level serial connection and sends it, via a shift register, to a Centronics-compatible DB25 connector.

In addition to the data lines, I’ve also implemented nearly all the other signals, such as /STROBE, /INIT, /ACK and so on. There was one I hadn’t planned on using, but we’ll come to that soon.

I’ve also just finished changing capacitors in the Epson after it released unwholesome amounts of magic smoke. And I gave it a bit of a wash & brush-up.

Don’t she look pretty?

While the printer was still hors combat, I threw together an ATMEGA328P-based virtual printer to test how my DottyMatrix prototype would cope with signals coming back from the machine. But, of course, I couldn’t be absolutely sure I’d got everything right. It was time to hook up DottyMatrix to the real thing. I was in for a pleasant surprise and a valuable lesson.

Cable hunt

First, I needed a printer cable. Being a natural cable hoarder, I had high hopes there was one in a box somewhere.

I was in luck. I couldn’t have looked in more than three or four hundred boxes before I turned up a nice fat DB25 male to Centronics/Amphenol male cable. The last time I used this puppy must have been in the 1990s.

And when I say ‘fat’ I mean it. These days we’re accustomed to scrawny USB cables with tiny plugs. But this thing is a monster. Plugging it in felt like wrangling an anaconda.

Making connections

The next step was to connect up. The female DB25 connectors I have (with right-angle pins) won’t go in a stripboard. I think the pins are 0.1in spaced, but the rows are staggered. Instead, I took the direct approach, using jumper cables with DuPont headers to connect directly to the pins of the DB25 and the breadboard of my ATMEGA328DB prototyping rig. (You can also see one of the probes from my multimeter in the picture.)

So far, this has proven to be a surprisingly robust arrangement.

Sending text

The main purpose behind this project is to be able to send data programmatically from a Raspberry Pi. But as it simply uses a serial port, there are all kinds of ways one can transmit to the printer.

For the sake of these initial tests, I simply used an FTDI cable from my Mac to the DottyMatrix with a terminal program running on the computer.

I fired up the printer. It let out its habitual initialisation chatter. I fired up the DottyMatrix. The printer chattered again – a good sign as the DottyMatrix sends an initialisation pulse as part of its power-on sequence. Then I typed…

…and the printer printed!

The first attempts were rather faint. The printer ribbon was decades old. The fact that it printed anything at all was a miracle.

It just so happened that I had a couple of spare ribbons knocking about. I bought these some considerable time ago – perhaps as long as 10 years – when I last thought I might press the Epson back into service. That attempt involved a USB-to-parallel cable and what can only be described as ‘driver hell’. (This was on Linux.) I don’t think I managed to print a single character. Nonetheless, I still had two ribbons in their plastic packaging. The printing still wasn’t as dense as it might have been, but it’s legible.

No acknowledgement

Of course, I’m not saying that my hardware and software worked flawlessly right off the bat.

For one thing, I’d amended the software so that when the DottyMatrix interface sends a character, it doesn’t wait for an /ACK signal from the printer. It was actually quite common for this signal to be ignored. But when I tried enabling its use, the interface just timed out. I may have to tweak timings.

And while playing around, I came to realise that there’s a signal I had intended to ignore but which is actually quite useful. And it’s the SELECT signal.

This is an output from the printer. It goes high when the printer is online and ready. It goes low when you take the printer offline – for example, by hitting the ‘ON LINE’ button.

I figured it might actually be useful to know when the printer is simply offline, as opposed to being unavailable for another reason, such as a ‘paper end’ condition or some other error. Fortunately, I’d assigned a GPIO pin for this signal and a few lines of code had it enabled. I also added a 10kΩ pulldown resistor to the line on the interface so that if, for example, the printer is switched off, the line isn’t left floating – it will register as ‘offline’.

Here’s a code snippet showing a function I use to check the current printer state.

printer_state updatePrinterState()
    curr_state = READY; // let's assume the best
    if(!readPin(&INPUT_PORT, ERR_PIN)) curr_state = ERROR; // active low
    if(readPin(&INPUT_PORT, BUSY_PIN)) curr_state = BUSY; // active high
    if(!readPin(&INPUT_PORT, SELECT_PIN)) curr_state = OFFLINE;
    if(readPin(&INPUT_PORT, PE_PIN)) curr_state = PAPER_END; // active high - /ERROR and BUSY will also be set
    if(curr_state == READY) errorState = NO_ERR;
    return curr_state;

A lot of what you see there relies on defines and enums established elsewhere, but the key thing is the order.

Certain states, such as ‘paper end’, will also set a signal on the /ERROR line (and the BUSY line, for that matter). So the error line gets checked first and, if the state turns out to be something more specific, we update further down.

Further work

So, anyway, it’s working. I have some finessing to do with the /ACK thing, which will be a good excuse to fire up the oscilloscope. And I’m not convinced I’m getting maximum speed. But now we’re into the stage of adding functionality and optimising – and that’s where a lot of the real fun starts!

[ » Read the next post in which the secrets of /ACK are revealed! » ]

[ » All DottyMatrix posts » ]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.