Tuesday, February 17, 2026

Spinning fan with lights

 Another fun find while thrifting.  This time, it's a little battery-operated fan that shows messages with lights.





 So I got it, of course, mainly to see what makes it tick.

Disassembly 

 The back came off with a bit of prying.  Three AAA batteries power a DC motor that spins the fan.

The front has a dome over the plastic fan blade, and then the fan blade holder holds the PCB.  


The PCB has a little ribbon cable with 7 LEDs built into it.  That ribbon slots into the fan blade.


The dome is press-fit over the fan blades and onto the fan blade holder, which contains the PCB.  Then, that whole assembly is press-fit onto the motor shaft.  The trick is that there's a spring coming up from base, and the spring is connected to the battery.  As such, the DC power to the PCB is coming from the shaft and the spring.

PCB front


 PCB back


There is a little slot in the PCB back where power gets interrupted now and then.  

I think what's happening is that the DC power maintains a reasonable voltage in a capacitor somewhere and that fills up as the motor spins.  Periodically, there's a pulse generated that might kill circuit power, were it not for the cap.  The pulse that occurs is also input to the circuitry to know when the fan has hit a particular rotational point, so it has positional feedback.

The 24C08

The people who made this left me two good things.  

First, the EPROM chip's label was left visible. In other toys, they sometimes bury these chips in a potting substance, or grind the identifying information off of the top layer of the chip.


That's a HK 24C08 EPROM.  It can hold up to 8Kbits of memory, or 1 Kbyte.  It's addressable by I2C.  The pins on it are power, ground, SDA, SCL, Write Protect, and one meaningful Address line.  There are two NC pins.  

The address line allows you to have two of these EPROMs on the same I2C bus, if you want.  In this case, the pin is connected to GND, so that makes it address 0.

Note that there appears to be a little capacitor stuck between pins 7 and 8 on the device.  Pin 8 is Vcc, and pin 7 is /WC (Write Control).  One 24C08 datasheet says, "Write operations are disabled to the entire memory array when write control (/WC) is driven high.  Write operations are enabled when write control (/WC) is either driven low or left floating."

In this case, since there's a cap between Vcc and /WC, it would seem that it's "hard wired" as write-protected. 

I2C SDA/SCL connection

The next nice thing they did was that they built the device with a usable Micro USB port, whose data lines connect directly to the SDA and SCL lines of the 24C08.

While the device had a Micro USB port, you can't plug it directly into a computer USB port and expect it to do anything.  The USB interface doesn't work that way, i.e., it doesn't do direct I2C communications.

I took a Micro USB cable, chopped it, and separated the wires. 

 


Once the wire ends were stripped, I just toned out the connections with a DMM, checking for a connection from each wire to a pin on the 24C08.  In my case, the black and red connected properly to GND/Vss (4) and Vcc (8).  The green wire turned out to be my SDA (data) line (5), and the white one connected to SCL (clock) (6).

Arduino 

I fired up an old Kosmoduino board, which is an Arduino Nano, pre-wired to various controls and devices.  

My initial interest was to use the Kosmos buttons. I found that pin 7 would give me the Button 1 signal, and pin 8 would be Button 2.  I could check regularly in the main loop() function, and if either would go LOW, I could have the sketch do something in response, like read or write EPROM data.


 The green board shown here is just an easy way for me to connect pins.  There are screw-down terminals on the opposite side, so I didn't have to solder the USB cord's wires.

 

For the Arduino Nano, native I2C communications are done on pins A4 (SDA, yellow here connecting to green on the other end) and A5 (SCL, white here).

Arduino has an at24c08 library.  I'm using the one from Stefan Stromberg.  (This is one of many at24cxx libraries for eproms of different storage sizes.)  Its basic examples yielded quick results.

You start by managing the sketch libraries and installing the AT24C library.

Then, in the sketch, you have to include the library

 #include <at24c08.h>

and then you declare the eprom object and its address as a global.

 AT24C08 eprom(AT24C08_ADDRESS_0);

 From that point, you can simply call eprom.get() to read a byte from the device.  This is much easier than trying to figure out the addressing patterns manually.  If you read the datasheet for the 24C08, there's a little dance you have to do, sending a START, pretend-writing to and address, then sending another START, then reading a byte, then STOP.  All of that rigamarole is handled for you in the eprom AT24C library.

Read operations 

I made the main loop check button 1 for a LOW signal, and when that was seen, it would read.

Initially, I tried just reading a few specific bytes, but I progressed quickly to the point of having it report a page (256 bytes) of memory at a time in binary form (highest bit, mask 0x80, down to lowest bit, mask 0x01).  I then adjusted the output to be more legible, using "#" for 1 values, and "." for 0 values.

After a few test iterations, a pattern emerged.  As it turns out, if you read the values in descending address order, you can see the letters' pixels.  Example shown here is the "REDUCE USE 5-8PM" message:

104     ####.### F7
103     ...#.... 10
102     ...#.... 10
101     ...#.... 10
100     ####.### F7
99     ####.### F7
98     #..#...# 91
97     #..#...# 91
96     #..#...# 91
95     #......# 81
94     ####.### F7
93     #....... 80
92     #....... 80
91     #....... 80
90     #....... 80
89     ####.### F7
88     ...#...# 11
87     ...#...# 11
86     ...#...# 11
85     .....##. 06 <- above this, message "SMUD CAN HELP", 13 chars
84     ...#...# 11 <- rendering code
83     .#.....# 41 <- line count

82     ######## FF
81     ...#...# 11
80     ..##...# 31
79     .#.#...# 51
78     #...###. 8E
77     ######## FF
76     #..#...# 91
75     #..#...# 91
74     #..#...# 91
73     #......# 81
72     ######## FF
71     #......# 81
70     #......# 81
69     .#....#. 42
68     ..####.. 3C
67     .####### 7F
66     #....... 80
65     #....... 80
64     #....... 80
63     .####### 7F
62     .######. 7E
61     #......# 81
60     #......# 81
59     #......# 81
58     .#....#. 42
57     ######## FF
56     #..#...# 91
55     #..#...# 91
54     #..#...# 91
53     #......# 81
52     ........ 00
51     ........ 00
50     ........ 00
49     ........ 00
48     ........ 00
47     .####### 7F
46     #....... 80
45     #....... 80
44     #....... 80
43     .####### 7F
42     #...###. 8E
41     #..#...# 91
40     #..#...# 91
39     #..#...# 91
38     .##....# 61
37     ######## FF
36     #..#...# 91
35     #..#...# 91
34     #..#...# 91
33     #......# 81
32     ........ 00
31     ........ 00
30     ........ 00
29     ........ 00
28     ........ 00
27     #..##### 9F
26     #..#...# 91
25     #..#...# 91
24     #..#...# 91
23     .##....# 61
22     ...#.... 10
21     ...#.... 10
20     ...#.... 10
19     ...#.... 10
18     ...#.... 10
17     .##.###. 6E
16     #..#...# 91
15     #..#...# 91
14     #..#...# 91
13     .##.###. 6E
12     ######## FF
11     ...#...# 11
10     ...#...# 11
9     ...#...# 11
8     ....###. 0E
7     ######## FF
6     ......#. 02
5     ...###.. 1C
4     ......#. 02 
3     ######## FF <- above this, message "REDUCE USE 5-8PM", 16 chars
2     ...#...# 11 <- rendering code
1     .#.#.... 50 <- column count (80)

0     ......#. 02

 

Write operations

I made the sketch look for a button 2 LOW signal.  When seen, it would to trigger a Write operation.   I fully expected this to fail, because of the capacitor tying Vcc to /WC.  But, for whatever reason, I was able to write to the EPROM without error!  Maybe the cap has failed, or it wasn't installed correctly.  I thought I would have to de-solder it or otherwise kill it, but I was able to write!

So, I started writing values to various lines to change the message and do other experiments.  

Changing pixels was pretty easy.

Preamble byte 1: column count

Preceding each message phrase, there was additional information.  For each, you would see two bytes.  And, there was also a value in address 0 that didn't fit the pattern.

It turns out that for each message, the first byte is a "column count".  Each letter is rendered as 5 columns of 7 pixels.  So for a 16-char message, there are 80 "columns".  Thus, for the message "REDUCE USE 5-8PM" in addresses 3..82 (80 bytes), the count in address 1 is 0x50 (80 decimal).

There's an upper limit to this value.  You can't render more than 0x5a columns (90 decimal columns, 18 characters).  If you try to set this value to something that is too large, or doesn't divide by 5 properly, the message rendering will fail overall.

Preamble byte 2: rendering code 

The second byte is a rendering code.  For example, Address 2 contained 00010001.  In fact, for the fan I got, it used values 00010001 for all six of the message rendering codes.  The default behavior was to draw the message gradually, left-to-right, wait, and then erase gradually, right-to-left.

With some experimentation, I found that the nibble codes for these rendering code bytes act as follows:

       Draw  Clear
bits   Hi    Lo
0000   LR    RL (same behavior as 0001)
0001   LR    RL
0010   RL    LR
0011   OI    IO
0100   IO    OI
0101   C-LR  LR-C
0110   R-LC  C-LR
0111   Inst  Inst

LR = left to right

RL = right to left

IO = inside to outside

OI = outside to inside

C-LR = Center to Left and Right

LR-C = Left and Right to Center

Inst = show the whole message in one instant without slowly drawing

A rendering code byte has two nibbles (high and low).  As an example, if the high nibble is 0110, and the low nibble is 0011, it will draw the message from the Right and Left edges in to the Center, and then erase from the inner ring to the outer ring.

Message count 

The only thing left to figure out was byte 0.  It was set to 6 initially, and that simply meant "there are 6 messages to display".

7 bits, not 8

The fan has only 7 LEDs going around, not 8.   That didn't really make sense, given the letter patterns in the EPROM made use of all eight bits.  After some experimentation with bit values, I found that the bit at position 0x08 actually is ignored during rendering.  For example, the value 0b11110111 renders the same as 0b11111111.

Below are examples where I've changed the word HELP to other values, just to test.



Easier control

I modified my Arduino sketch to use the Serial port as an input mechanism, rather than using the buttons.

The sketch reads text from Serial into a character buffer.  As I do command text processing, I read from that buffer instead of reading directly from Serial.

There are two main operations: R and W.  The commands are as follows:

Command: R0

Read page 0 (255..0) and report EPROM byte contents in the form address, binary value, hex value.

Command: R1

Same as R0, but page 1 (511..256)

The device does not appear to use pages 2 or 3 of the data for messages.  Those pages can be read, and I'm not sure if they're important (e.g., operational code, or other configuration settings I don't know about).

Command: W decimalAddr binary7

This command lets you write a byte to a decimal address.  If the binary value only has 7 digits, it's assumed to be part of a letter, and split accordingly, inserting a 0 in the 0x08 bit position.  For example, if you say W 24 1010111, it will turn the binary value into 1010 0111 (0xA7) and write that to address 24.  This 7-bit format makes is easier to visualize the character bits that will actually appear. 

Command: W decimalAddr binary8

In the case where you have to write a full 8-bit value (e.g., rendering control codes, or column count information), you enter the binary value with all 8 bits, and it use them as provided without inserting the 0x08 bit.

For example, W 24 10100111 is equivalent to the 7-bit variant W 24 1010111.

Coding trickiness

A few notes on coding.

Debouncing

Since I started by using buttons for input, I added delay() calls as a cheap way to prevent re-reading the button too soon after I'd seen a LOW signal the first time.

Datatype: byte vs int

In early revs, I was calling eprom.put(addr,val) with an int datatype for val.  This would write two bytes, not one.  And, because I was writing bytes in reverse address order, it caused an overwrite of 0 in certain positions.

For example, if you use an int type and do:

eprom.put(80,1);
eprom.put(79,1);
eprom.put(78,1); 

then it would do something odd, like put 0 into positions 80 and 79, and 1 into 78, because it was actually writing two bytes each time.

The way to prevent the 0-overwrite behavior is to use the right data type, or do an explicit case, like this:

eprom.put(80,(byte)1);
eprom.put(79,(byte)1);
eprom.put(78,(byte)1); 

Serial read buffering

As with any character buffer management, be careful with buffer overflow possibilities.  Far too many examples are provided out there, where someone in Arduino land provides an example of char buf[32] and then lets people write off the end of it.  That will wreck up your sketch behavior, and it also teaches bad security coding practices to young programmers.

While none of my commands will expect more than 32 bytes, I keep a running count of characters read per line, and prevent buffering if the count goes too high. 

Next Steps

  • Come up with some clever messages of my own.
  • Communicate with the Arduino Serial interface using something other than Serial Monitor, and pipe a whole set of messages (including message count at Addr 0, line counts, rendering codes, and message pixel columns) as a compiled bundle. 
  • Find more of these devices, because they're fun! 

Final notes

 As it turns out, I didn't really need to do any disassembly of the device.  The Micro USB port is externally available, underneath the fan blade that doesn't have the LEDs.  At this point, I can connect the fan to the Arduino (hacked USB cable), run Write and Read commands using Arduino's Serial Monitor, do Read operations to verify that the data got written, unplug, and test.

If, however, the /WC line were preventing me from proceeding, I would have had to de-solder the capacitor between pins 7 and 8.  (For some devices, I may have also had to bodge wire pin 7 to GND/Vss pin 4 in order to write.

I have not found ways to do any of the following:

  • Change the rendering speed
  • Render around the entire circle
  • Avoid the whitespace breaks between characters
  • Render any other nice things found in other spinners (e.g., the date/time/temperature). 

Tuesday, February 3, 2026

Tandy DMP-203 dot matrix printer

 I came across a very old printer at the thrift store, and got it for a good enough price that it could serve as a distraction so that I wouldn't buy anything else for a few days.



 

It's a Tandy DMP-203 dot matrix printer.  It was pretty dirty, but seemed somewhat well boxed (not original).  It had an attached power cord.  Initial power-on testing at the store showed it to be quite dead.  The ink cartridge was still there.

I was interested in reviving this one.  Initial removal of the cartridge was easy enough.  

My first concern was seeing why it wasn't powering on.  To determine that, I'd have to get inside.

Disassembly

Main cover removal 

Warning: panel removal on this device exposes high power circuitry that is potentially lethal.  Do not do this if you are not aware of electrical safety.  The power board also has high power capacitors that slowly discharge, so do not open the panel until you have had the device unplugged for about a minute.

There is one obvious external screw at the top, rear.  This is removed first.


 After that's been removed, there are two visible "tabs" that are press-fit / snap-on latches, the tabs attached to the bottom frame.  If you press those gently inward, and/or pry the upper case away, each gently lifts up.  I used a flathead screwdriver (first picture) to push the tab inward.

Then, I found there were three more case screws.  All three are just behind the front "vent" lines on the upper frame.



As it turns out, most of the case screws are the same.

With the screws removed, I pried the front and sides up.  Thankfully, the case did not have additional plastic press-fit clips around the sides or front.  But it took additional force to pull up.  I'll show why later.



 This is the kind of edge connection that's going on inside the front and sides.  No clips visible, but there is a little slot in the reinforcement tab.



After doing more prying, the top part popped off with a bit of a snap, and this is why.  There is one more press-fit clip underneath the left, middle of the top part.  It's about 4.5" away from the left side.  In the future, it's probably better to lift up the edge, look inside with a flashlight, stick a screwdriver in the gap, and push that clip a bit to release it.

There may be another way to push on this clip to get it to release.  Behind the clip, near the print head area, there is a narrow slot.  It may be doable to push something through that, maybe something like a tongue depressor.  Oddly, I have something that might work.  It's the arm of a pair of macetech programmable glasses.  That fits well, and has to reach about 1.5" (38mm) into through the slot in order to press against the tab.  

A chunk of one-sided FR-1 PCB board also fits through the slot.  You need something long, thin, and strong for this. 

The top was off, but not fully disconnected yet, because there's a little control panel board screwed to the top.  Remove that and set the screws aside.  Note its position.


Interestingly, the top panel has slots that would allow for a larger control board.  There's room for three more buttons, and maybe a few LED indicators.  The board, itself, has room for another button, and appears to have unused pads.


This is what it looked like when I had the top flipped over, and the control panel was not yet disconnected.


With the control panel removed, you can see there's room for another button and indicator light.  To avoid losing them, I put the screws back into where they originated in the top panel.


Power board removal 

Now that the top panel was removed, I could see the power supply board (beige) and a part of the main PCB (green).  Both were pretty dirty.  The power board has four screws holding it down.  Two were blackened somehow, perhaps by corrosion or stray ink.


I removed the four screws holding the power board down.  

Then, to remove the power board from the case, it turns out that you have to pry upwards where the on/off switch is.  There's a cutout in the plastic of the case that otherwise would appear to be cracked plastic.  But, it's there to let the switch clear the case as it's inserted.




Connected to the mains is a fuse.  I removed it and tested it, and it's still ok.  But if your board isn't powering on, this could be the cause (and could indicate a bigger problem further inside).

This is what it looked like with the power board loosened.

The main power cord is held by small clips on the right side of the printer.  

The cord goes under the platen roller knob.  That knob, as it turns out, is press-fit onto its rod.  It has a cut-out that goes around a tough pin that then goes through the rod.  You can just wiggle the knob firmly to pull it away to the right.



You can then gently loosen the main power line around its case clips, and snake it around the rod and pin, and then loosen the piece on the back to provides strain relief.

With the power cord released from its clips, I could now see the underside of the power board.  It was really messy, but it seemed like there weren't any clear burn marks or bad solder joints.


The power board was connected to the PCB with a 5-wire ribbon and a shrouded connector.  (The ribbon also isn't color coded in any way.  You kind of have to trust that the bend of the ribbon will help you remember how to put it back together again.)  The connector shroud was clipped pretty firmly in place.  This is old school stuff, and seems designed to prevent removal.  That makes sense, given it's a rattling device.

After some prying with a very small, flathead screwdriver, the shroud popped off like this.  The trick is to get the screw under one corner of the shroud and pop it upward.  This really only can be done if you have room to get to it, which is why it was necessary to pull the power board away from the bottom frame.


The ribbon wires then are held down with "biting" connectors.  You can't just pull them up at this point, and since there are multiple of them, it'd strain things to try to pull them out individually.

To disconnect these wires, I simply used five pointed toothpicks.  I pushed those in alongside the original wires, effectively releasing the biting metal pieces.  You can kind of feel when you've pushed the toothpick in enough to release each wire.

Once the toothpicks were in place, I could remove the ribbon's wires.

Not shown here, but... now you have toothpicks that are stuck.  What do you do?  Use a small, flathead screwdriver and push each socket tooth.  The toothpick will come out, and the socket tooth won't bite into the screwdriver, so it can come out, too.

Power board

Now for a bit of power board inspection.  Just as they say on the internet, it looked like there was capacitor leakage.  It looked bad and actually smelled a bit like rotten fish.

Here you can see one of the electrolytic capacitors leaked badly...

and another one did, too.

There are a few other electrolytics that look ok, but I'll replace them anyway just because of age.


I took plenty of pictures to try to remember the orientation.  But it turns out that the board has good markings on it, showing capacitor polarity.




Off to de-solder.  Here are the caps that were removed.

And here are the printed specs and rough measurements.

C11 (smallest blueish)

  • 4.7 uF
  • 6.3V
  • 5.16mm diameter
  • 11.63mm height
  • 5mm lead spacing

C9 (small blackish)

  • 330 uF
  • 10V ELNA (M) (20%)
  • 8.18mm diameter
  • 12.36mm height
  • 5mm lead spacing

C2 (Nichicon, blue)

  • 220 uF 
  • 200V
  • 18.4mm diameter
  • 40mm height
  • 7.4mm lead spacing (but also can take 10mm!)

C13 (Nichicon, brown/black)

  • 4700 uF (4.7F) 
  • 25V
  • 18.3mm diameter
  • 34.5mm height
  • 7.5mm lead spacing 

Armed with that info, I found replacements at both Mouser and Digikey.

One nice surprise on the board is that the board design for C2 could accept either the original through-hole leads at 7.5mm lead spacing, or a snap-in style capacitor with 10mm lead spacing (and 1.5mm-wide, stubby leads).  The original PCB had solder flatly laid over the larger holes seen here, since they were disused.


To remove the bad capacitors, I had to cut through a bit of the leaked gunk, and then de-solder.  After de-soldering, I did some overall board cleaning.  Here are the before and after shots.

At this point, I researched and ordered replacement caps.  In the case of C2, I opted to get a similar replacement with 7.5mm lead spacing, only because that's what Digikey was serving up.  I'd looked at Mouser earlier, and found that they could have provided snap-in form-factor capacitors only, and at a cheaper price.  I went with Digikey in the end, just so I could have all the parts on a single list there.

Frozen print head 

Onward with diagnosing the (seemingly) immovable print head.

I tried moving the platen roller, and it rolled as expected, if begrudgingly.  However, I couldn't move the printer head side to side (along the X axis) without a lot of force.

I figured the next best thing to do would be to remove the print carriage assembly from the PCB to take a closer look at it.  I thought maybe by de-tensioning the belt, and removing the X axis motor, I could rule out motor issues and avoid pressure on the motor pinion gear.

Print carriage assembly and main board removal 

The print carriage assembly was held in place by four plastic clips in the lower frame.  I thought that a tensioning pin also was getting in the way, but that's actually part of the print carriage assembly and could have been removed later.


To release these pins, I used a flathead screwdriver, and gently pushed each one away from the center, while lifting the carriage from a corner point initially, or from the center subsequently.

After that has come up, the carriage assembly is still entangled by the ribbon cable (be very careful with that), a four-wire ribbon cable, and the two 6-pin motor wire harnesses.

There is a DIP switch panel that I should have removed first.  With the print carriage assembly in its original place, you can slide the panel left, up, and out.  This untraps the print head ribbon cable and makes subsequent moves strain that ribbon less.  This is the view from below.


 The four-wire pin assembly is another of those that has a hard-to-remove shroud, and has socket points that "bite" into each wire.  I'm not wholly sure what those do.  Note that for this one, there is a color coding on one side, so mind that as you reassemble later on.

Here again I used the toothpick trick.



I also marked the header to remember where the gray wire would go.



The print head ribbon cable remained firmly in place.  I have not found a way to remove that, so you have to work around it and be very careful to avoid breaking or pinching it.

The six-wire harness to the control panel can also be removed from the PCB using the toothpick trick.  The bends in the cable help remember how to put it back in later on.  Unclip shroud first.

Exposing teeth. 


 Toothpicks and removal.


 

The 6-wire motor harnesses each have their own header, and those can be pried up gently with a small, flathead screwdriver.  This is just a picture for color orientation purposes.

 The red header came off first (Y axis, or roller axis).  I just used a normal screwdriver to twist-pry it up.


Then, the white one (X axis, or print head axis).


It's nice that the headers and sockets are matched by color so I can remember which goes where.

This is a close-up of the print head ribbon connection on the PCB end.  I don't see an obvious way to detach it.  More modern ribbon connectors have a disconnect mechanism.  At some point above, I gained access to, and removed the screws holding the PCB to the lower frame.  This allowed me a lot more freedom of movement, and helped avoid messing up the print head ribbon cable.  At least, I think it did.  I won't know until I reassemble and test.


I wonder now if I the ribbon is held in by the same "biting" tooth mechanism as the others.  Those work, because they're used tinned, stranded wire that metal tabs can hold onto.  Once presented with something more solid, like a screwdriver tip, the teeth can't bite.

Ribbon cable ends would be soft copper.  If I were to be able to slide a thin, metal edge into there (perhaps a trimmed aluminum can?) maybe the "teeth" would release from the ribbon.

Here's where things stood at this point.  The PCB and carriage assembly are out of the lower frame.  In this picture, they're upside-down.  The two are held together by the print head ribbon cable.  The print head still doesn't move cleanly along the X axis.

In order to remove the PCB, I had to unscrew the screws that were holding it to the lower frame.  I also took off the screws that were holding the parallel port (Centronics?) clips, and associated outer flange.  I went further than needed, removing the inner mounting brackets.  All those parts are seen at the top, right.


X-axis Motor de-tensioning and removal 

The next part of the disassembly was to take off the X axis stepper motor.  It's seen here, mounted to a metal plate.  The plate slides and tension is provided by the spring.  In that way, on the opposite side, the motor gear talks to a drive gear that pulls the belt that moves the print head.

The motor is labeled 42SIN-15D6YA, but if you search for that on the internet, you'll likely end up looking at NEMA 17 stepper motors.  This is not that.  This is a pancake, unipolar, 6-wire stepper.  I'm not sure what voltage it runs at and I don't have any other specs on it.

I removed the spring, and the two screws holding the motor in place.  I also removed a tensioning wire on the side of the carriage.  With that, the motor came out, and the belt was left loose.


At this point, with the motor completely out, I should have been able to slide the print head freely from side to side, barring there being any "parking" mechanisms.  But the print head was still very tough to move.  I could move it a bit with quite a bit of force.

I tried adding some sewing machine oil to the X axis rod, and that didn't really help.

So, I started thinking that the X axis could have a sleeve bearing that was frozen, so I started looking at ways to remove the rod entirely from the frame.

This is the blue lever mechanism on the right side of the rod.  Looking at it closely, it didn't provide any clues as to how I could remove it.


Looking at it from the inside didn't provide clues, either.  I tried unclipping the blue lever away from the frame so it could rotate beyond its normal detente range.  I hoped that would get it to a point where it would be released, but it didn't come free, and it felt like I was putting too much strain on it.

Sprocket feed roller removal 

So, I started to remove more from the back of the assembly.  This is the rearmost assembly that holds the sprockets for tractor-feed paper.  I removed it by first taking off the C clip and then sliding off the associated gear.  With those off, I could slide the rod to the right, allowing the left end of the rod to come off.  Then, I could pull the rod out of the frame, inward from the right end.

Gearing and roller removal 

The next task was careful and organized removal of the gears.  Some are held in by screws.









 

With the first set of screws removed, I could slide the beige handle outward from the frame, but could not remove it.


 

Once the handle has been moved away from the frame, it can rotate and dangle.  On reassembly, remember to rotate it back upward.


I tried to remove the pin that is used for the roller knob, but that wasn't a good move.  (I was able to move it almost halfway out, and then got stuck, so I had to cleverly use a C clamp to gently get it back to where it came from without bending it.)

The next nylon gear was accessible, now that the beige lever was out of the way.  This one has a beveled top, and behind it there is a washer and spring, pushing the gear away from the frame.  The non-beveled part of this gear (the larger diameter portion) can engage its teeth with the sprocket axle's gear.  When the beige gear's "c" arm rotates over the beveled gear, it pushes the gear inward, compressing the spring, and causing the larger diameter gear to disengage from the sprocket axle gear.  Here, I remove the beveled gear, washer, and spring.






Going back to the roller axle, right side, there's a C clip holding a gear in place.  I removed that.



And now I could slide that gear away from the frame.


That revealed another of those through-the-rod pins, like the one seen under the roller knob.  The thing to note here is that the white gear has slots that line up with the pin, so it's important to align that when reassembling.

This is a close-up of one of those through-the-rod pins (photo through loupe).  It looks like maybe some kind of spring metal, crimped, and then inserted.   If I were to take it out, I might not get it back in again.

In general, I think the through-rod pin mechanism was a cheap way to avoid using set screws.  In some ways, given the environment, it may have also been more reliable than set screws.

I still had not freed up the roller from the frame.

It took me a while to figure this part out.  It turns out that there are white bushings that have levers on each end of the roller.  But, if you look closely, there's a tiny kind of stiff glue holding each lever bushing in place.



The blue stuff is a glue, and its purpose it to keep the lever from rotating around the axle.  I used an X-acto knife to cut off the blue and scrape it a bit.


 

But even with that glue removed, the lever would rotate.  It turns out that the lever also has a nib that sets into a hidden hole in the frame. You have to pry the lever tip away from the frame a little in order to release the nib, and then then lever can rotate (assuming you got the glue out).

On the left side of the roller axis, the lever bushing holds the axle in place.  Behind it, there's a washer and spring under tension, so those can pop out.

I got the levers away and rotated them to a vertical position.  As you do this, you can see that the inner part of the levered bushing has flats on the edges, allowing it to slide upward once in position.

Even with the levers set up properly, the roller wasn't completely free, because of the position of the print head.  I forced the print head all the way to the right.


 

Finally, I could get the roller and lever bushings off.  (And, pop! the spring and washer came loose on the left side.)

 


Here's the right side of the roller assembly.  If you look closely, you can see the nib on the lever.

 Root cause of frozen print head

Finally with the roller assembly out, I could move the print head along the X axis, and it moved pretty smoothly.  But, why?  If it was moving cleanly, that meant that the problem was not some kind of frozen bushing, or dirtiness of the X axis rod, though it certainly could use cleaning and oiling.

That's when I finally saw this:

I noticed that the print head was prone to tipping forward and backward as I moved it left and right along the rod.  It should have been more rigid.

As it turns out, there's little L-shaped clip on the front of the print head carriage, and it was riding on top of  the plastic rail at the front of the carriage frame.


 

That meant that the print head was tipped inward and binding against the roller.

There was no adjustment mechanism for this, so I just pushed that part of the frame inward a bit, and that allowed the L to pop over into its proper position.

Once that was done, I could slide the print head left and right with light finger pressure.


 

So as it turns out, much of the disassembly done earlier wasn't really necessary, and put the print head ribbon at risk.  It did allow me access to a lot more of the machinery, which I could clean.

Reassembly 

After that, I could put it all back together again.

A few points on reassembly:

  1. Be super careful to avoid damaging the print head ribbon.  That might be impossible to replace. 
  2. Remember to align the roller's right side gear with the pin.
  3. It seems like it shouldn't really be necessary to glue the levers in place, but maybe I'll do it.
  4. The beige lever on the right side has to be rotated upward so that it engages the beveled gear correctly.
  5. The four-wire ribbon can get trapped in the wrong place under the carriage, preventing proper carriage landing.
  6. Be sure that the print head ribbon is pulled through the DIP switch panel hole before dropping the carriage in place. 
  7. Before setting the carriage down, there's a lever at its front.  That lever has to be held up before the carriage goes down.  The lever is part of the X axis homing switch assembly.  If the lever isn't moving properly, the print head probably will move left as it tries to home, and will crash into the rigid lever, and might break it.  So, make sure it's properly oriented before dropping the carriage back in place, and test manually afterward to make sure you can hear it clicking the tactile switch underneath.
  8. After the carriage is in place, you should be able to put the DIP switch panel back on.  Double check to make sure the print head ribbon is positioned properly before putting the panel on. 
  9. Probably, it's best to keep the motors disconnected (i.e., don't reconnect the red and white connectors to their headers) as much as possible.  You don't really want motor movement to provide some kind of flyback current to the board. 

With this all reassembled, but with motors still disconnected, there are few other interesting things to note.

  1. The X axis does move properly it takes more pressure than just a finger push.  That makes sense, because the belt is now under tension, and you're pushing against the gearing and the stepper motor.  But, it moves without an extraordinary amount of force.
  2. As the print head moves, you'll see that a gearing mechanism rotates the gears and pin that would drive belt movement.  I don't quite understand how that works.  As well, it moves them bidirectionally, suggesting it'll keep hitting the same section of the ribbon over and over again, unless something else controls the ribbon drive gear.

Now that all that is done, I'm awaiting the replacement caps so I can get the power board working.  I'm hoping that will provide insight into the normal motor voltages.  I could try to drive them independently using some kind of microcontroller (Arduino, Polulu motor boards, e.g.) but can't really safely do that without knowing the typical voltage.

Power board repair

(05-FEB-2026)
 
Sad.  The caps arrived from Digikey today and I got them soldered on securely.  Power-on shows very little voltage on the pins.  I doubt, given the age, that this board had any kind of signaling to negotiate voltage, or even a low voltage "on" line like you'd see in ATX power supplies.

I think if I'm reading the traces correctly, pins 1 and 2 on the header are tied; pins 3 and 4 are tied; and pin 5 is separate.  I'm getting 1.9v on pin 5, and nothing on pins 3 and 4.

Disconnected, when I tone it out, pins 1, 2, 3, and 4 all produce tone against each other.  That's rather unexpected.  I guess that suggests (perhaps) some kind of switch that turns on when truly powered.

I checked the traces (using DMM) and they all seem intact.  

I'll have to dig deeper into the circuit diagram to try to make sense of what it's doing, and may start detaching components to see if I can figure out if some important transistor, etc., is dead.

Power board voltage (and short circuit) insights 

(07-FEB-2026)

A few more insights!

First of all, I took a closer look at the circuit board to see if it would provide clues about voltage on different header pins, and indeed the screen printing did show it!

Front side


 It wasn't totally clear where those pins went, so I also looked, and the traces on the back also showed voltages (and you could more clearly see where they went).


 It's a little clearer with some Photoshopping and contrast enhancement.


 So if both front and back markings are to be trusted, the board is likely set up with the following.  The pins for CN1 (connector 1) are number 5 to 1, reading left to right, on top of the board and with the connector at the top.  When flipped over, then, the pin solder points are 1 to 5, reading left to right.

Pin 1 = Pin 2 = 24V 

Pin 3 = Pin 4 = Ground

Pin 5 = 5V

The other thing I did was check the diodes on the board.  I was lazy and didn't disassemble each component.  But one of them, ZD2, looked pretty corroded.

As it turns out, all the diodes show some forward voltage drop, except ZD2.  That one was showing a short.  I de-soldered it and tested it in isolation, and it still shows that it's bad.

The diode appears to be marked 27B, suggesting it's a 27V, +/-5% diode.  The diode is 2.7mm thick, and about 4mm long (for the body) with 10mm bent lead spacing.  The leads are about 0.8mm thick.  The dimensions 2.7mm and 4mm suggest it's a "DO-41" or "DO-41-2" or "DO-41G" case form factor.  Some also say "SOD66" form factor.  All but one of these listed on Digikey is rated at 1w, and sadly all but one are currently tariffed in the US.  Buying a single one from Digikey costs $0.13 for the item, and $6.99 for shipping.

For just over double that price ($15), I picked up a used, apparently working Panasonic KX-P1091i dot matrix printer, and it had two kinds of DB25-to-Centronics types of cables with it.  It powers on and didn't require extensive cleaning.  So I'm less inclined to spend money on a 27v Zener diode at this point.

I got to thinking: ok, so what does this diode do?  It's connected directly between the marked 24v trace and the GND trace in an orientation where the black band is on the GND side.  That suggests to me that they're not taking advantage of the reverse bias behavior of a Zener, really.  And if it's just there to face a minimal forward voltage drop, maybe its presence drains off some current so it doesn't all go to the 1,2 pins?  I don't really understand it.

But, given that I didn't think it'd do anything significant (in my opinion at this point -- need to talk to my EE friends) to the circuit, I thought I'd try powering the board (in isolation, not hooked up to the printer) to see what would happen.

And there you go.  

 Between GND and 24V, I'm seeing about 24.8 to 25.2V.  

Between GND and 5V (pin 5, conveniently), I'm seeing around 7.6V.  The 5V line is dangerously high, but the diode that I removed shouldn't really have anything to do with that.

Why is the 5V line so high?  It could potentially damage other circuitry, unless the PCB has some kind of power limiting management on it.  I don't see any obvious adjustment knobs (potentiometers) on the power board.  AI reports back what I suspected.  It's not safe, and it could be because of a failed voltage regulator.

At this point, I'm tempted to circumvent the whole power board and put in something that I know is generating 24v and 5v safely.  I won't know current draw requirements.  The label on the bottom of the printer says 120 VAC, 60 Hz, 0.7A.

It's quite possible that the circuit downstream from the power supply is already damaged, in which case I can try even more severe experiments (drive the motors myself, and then figure out how to fire the dot matrix pins myself).

One thing I can do is trace back from some known chip on the PCB to see where its 5v power line goes, and whether it connects directly to the power board pin 5.  One such is the TC51832SPL-12 chip.  That appears to be a RAM chip with Vdd at pin 28 (top, rightmost), and GND at the opposite corner at pin 14.

Indeed, pin 14 connects to PCB screw ground, and pin 28 touches power board pin 5 directly.  So, yeah, it's possible the power board failed and could have taken some of the PCB chips down.  My only safe way to find out, short of diagnosing the 5v line failure on the original board, is to spin up my own power supply.

Alternate power supply 

I figured I would try to set up my own 24v power supply and 5v power supply with common ground.  I had just received a bench power supply which would fit the bill quite nicely. 

I already had an LM2596 DC-DC buck converter.

With some quick wiring, I got the power supply and buck converter talking to each other.  A precision pot on the buck converter let me dial its output voltage down to 5v. 

Then, with some 22ga patch wire and some quick-connects, I got everything connected to the power ribbon.  Again, looking at power wires from left to right, they're numbered 5..1.  5 = 5V.  4,3 = GND.  2,1 = 24V.  

I triple-checked all the connections, and also checked again to make sure that the carriage return limit switch was working properly.  The moment of truth! I powered it up, the print head homed to the left and hit the limit switch as intended, and the light came on.  I could press the "line feed" button and it would move the roller.  A press-hold of the "line feed" button caused the roller to scroll the page out.

Not all is perfect with it.  If I start with the carriage a few inches from the left margin, it makes an awful grinding noise, and doesn't move the carriage.  I think it's quite possible that there's a problem with a bend or a bad tooth in the belt. 

Parallel port programming

DMP-203 parallel port timing 

I still don't have a DMP-203 manual, so I'm making some close guesses based on a timing diagram seen in a DMP-105 manual.

The back interface for the printer is a Centronics that talks to a DB-25 connector.

There are resources online that translate the pin numbering.

The timing diagram shows that I have to

1.  Set up D1..D8 data pins with some value

2.  No wait time is required

3.  Bring /STROBE low for at least 1.5 usec.

4.  Read BUSY.  It should be high for at least 500 usec.

5.  /ACK will also go low when BUSY goes high.

6.  Wait for BUSY to go low and /ACK to go high

7.  Again, no wait time is needed before sending the next character D1..D8.

If desired, I can also pay attention to PAPER OUT and FAULT__ signals.  Generated pins from the printer are biased high to +5V with a 2.2kOhm resistor.   Signal lines sent to the printer are supposed to be biased high with a 1 kOhm resistor as well.

Comparison with Panasonic KP-P1091i interface

The timing for the Panasonic has different wait times.

2.  Wait at least 0.5 usec before setting /STROBE low.

3.  Keep STROBE low for at last 1.0 usec 

4.  BUSY signal goes low when /STROBE goes low, whereas for DMP-203, BUSY goes low after /STROBE goes high.

5.  BUSY time high ranges, depending on buffer state.

6.  When BUSY drops back to low, /ACK drops to low.  In general, like with DMP-203, wait for both BUSY low and /ACK high to know printer is ready for the next set of data.  /ACK is designated as going low for max 5 usec.

7.  With BUSY low, and /ACK rising edge, the next data can be sent.

Significant pins (for my purposes)

All pin numbering shown here is based on a Centronics 36-pin parallel port.  There are resources elsewhere with mappings of these to a DB-25 connector.  On the DMP-105 documentation, six additional lines are marked NC (Not Connected); three more are marked as 0V without being twisted pair returns; one (pin 13) is the logical opposite of BUSY; and one (pin 17) is CHASSIS GROUND.  That adds up to eleven pins that are effectively irrelevant, leaving the other 25 to be usable within a DB-25 connector. 

/STROBE (pin 1)

DATA 1..DATA 8 (pins 2..9)

/ACK (pin 10)

BUSY (pin 11) 

On both, pins 19..30 are connected to Signal Ground and are set up a twisted pair lines for each corresponding line in pins 1..11.  

The chassis ground is on pin 17, and is distinct from the term "0V".  This does not appear to have a mapping to the DB25 pins.

On the Panasonic, the +5V line (pin 18) is documented as "...for evaluation only.  It should not be used to supply power for external equipment."  On the DMP-105, +5 is documented as "80 mA Maximum".

Optional pins

PO (paper out) (pin 12)

/ERROR (pin 32)

/AUTOFEEDXT (pin 14, Panasonic only)

/PRIME (pin 31, Panasonic only)

DB25 pin association

Centronics 1..14 match DB25 1..14

/FAULT = Centronics 32 = DB25 15

NC on DMP-203, PRIME__ on Panasonic,  Centronics 31 = DB25 16

NC Centronics 36 = DB25 17

NC on DMP-203, SG (signal ground) on Panasonic, Centronics 33 = DB25 18

Return /STROBE Centronics 19 = DB25 19

Return 2 Centronics 21 = DB25 20

Return 4 Centronics 23 = DB25 21

Return 6 Centronics 25 = DB25 22

Return 8 Centronics 27 = DB25 23

Return 10 Centronics 29 = DB25 24

Return 11 Centronics 30 = DB25 25

Since not all return lines are represented in the DB25, how are they connected to ground?  Perhaps there are different styles of DB25-to-Centronics cables.  The one I tested is one that came with the Panasonic.  That document says, for the SG pin, "The twisted pair return wires (pins 19-30) are connected to signal ground."  When the cable is disconnected from the printer, there is no connectivity on those wires. But when the Centronics end of the cable is plugged into the Panasonic, indeed DB25 pins 20..25 all show connectivity to DB25 pin 18.  

The same is seen when the Centronics end is plugged into the DMP-203. 

Reference: https://en.wikipedia.org/wiki/Parallel_port

Communications circuit

For communication, I can actually use the same board I was using for driving an LED cube.  That design was based on having a couple of 74HC595 chips in series so I could shift out 16 bits of data at once.  It wasn't really suited to the task of the LED cube because the pin current draw was really too high.

In this case, I'm just driving logic signals, so it's fine.

What I might want, though, is my own set of pull-up resistors or pull-down resistors, depending on the task.  The DMP-105 manual indicates that you should use 1kOhm pull-ups for printer inputs, and that printer outputs already are pulled up via a 2.2kOhm resistor to +5v.

Better, though, might be to use just one 8-bit shift register for the data byte.  That might save me the complexity of setting up pull-ups or pull-downs on those lines.  Really, they don't get read until the /STROBE fires.

So, I'm thinking that STROBE should be pulled high on an output pin.  

I can set up a 74HC595N with these pins.

- /OE biased low

- RCLK output low

- /SRCLR biased high

- SRCLK output low

- SER biased low

I "clock out" the serial data on the SER pin, toggling SRCLK with each bit.  Toggle RCLK to push all eight bits to output pins, which connect to DATA1..8 on the parallel port.

Delay (0.5 usec or 0 usec) 

Toggle STROBE low (1 usec or 1.5 usec) then high.

While BUSY high and ACK low, wait.  (Or, handle that in state machine fashion. Do not send data while BUSY high or ACK low.)

So one way to do this might be:

main loop(): 

check for serial in and buffer

if buffer has a character and not (BUSY_11 or !ACK_10)
  set up D1_2..D8_9

  delay, if needed 

  toggle STROBE_1 for appropriate amount of time

continue in main loop

A trickier way to do this might entail setting an interrupt on the ACK rising edge.  The problem there is that we don't get a rising edge on the initial state (first character read from serial in) and we do get an ACK on power-up.

An ACK interrupt might say, "If there's a character in the buffer, emit it.  On buffer empty, turn off interrupt."

The initial state would say, "If there's a character in the buffer, and the interrupt isn't set, and BUSY is low, turn on the interrupt function and call it right away."

There probably is some kind of timing conflict in here, where data read into the Serial buffer has to occur while the printer is busy.  And, we don't want interrupts to cause buffer management (add char, remove char) timing conflicts.

 DMP-203 Graphics Mode

I'm hoping the DMP-203 still honors the "graphics mode" mechanism available in the DMP-105.  It allows you to specify a "number of dot columns" character style (27, 20 for condensed), go into graphics mode (18), position the head to that column (27, 16, n1, n2; n1 == int(xpos/256); n2 == xpos mod 256) and then top-to-bottom dots (output 0x80 OR (1,2,4,8,16,32,64)).

With the DMP-203, though, I think there must be a different code for printing, because it boasts having 24 dot matrix pins, not just 7. 

When done, command 30 exits graphics mode.

 ESC/P and ESC/P2?

There is a standard of the era, Epson ESC/P and ESC/P2 format, that correspond to the commands listed above in the DMP-105 manual.

27,20 is "ESC DC4" (device control 4). But, ESC/P used a plain DC4 to mean "cancel double-width printing (one line)".

AI says the Tandy DMP-202 emulates the IBM Proprinter X24 or Epson LQ-850/LQ-570.

So what do those do?

In the Epson LQ manual, it says that 24-pin control is referred to as "triple density" and thus needs 3 bytes of information for each column it prints.  The top pin is 0x80 and the bottom pin is 0x01.  The output sequence is ESC * m n1 n2 data.

Reference https://files.support.epson.com/pdf/lq850_/lq850_u1.pdf