Update: In the meantime I developed a user friendly Python program which does all the work with a single command line: SPEER – Samsung Printer EEprom Resetter for Raspberry Pi.
Lousy Business Practices
A little bit more than a year ago I bought a used Samsung CLP-510 color laser printer for a few bucks. It printed fine, but I suspected that the toner was probably almost empty. And with laser printers it’s almost as bad as with ink jets. New toner cartridges are more expensive than the value of the printer. It is even worse with color laser printers, since they need four cartridges. But I figured that I would try to refill the toner cartridges once the time comes. So I bought it. It turned out that the toner cartridges where not completely empty. I used the printer for almost a year. But eventually the printer informed me that it was empty. It contains three toner cartridges:
- CLP-510D7K/ELS – That’s the black color for 7000 pages.
- CLP-510D5C/ELS – That’s the cyan color for 5000 pages.
- CLP-510D5M/ELS – That’s the magenta color for 5000 pages.
- CLP-510D5Y/ELS – That’s the yellow color for 5000 pages.
The black one was the one which was empty first. So no problem, I thought. Let’s refill them with some new colorful powder. Only then I found out that the cartridges contain a build-in page counter – a little electronic circuit board – which stops you from using the cartridge even if it’s refilled. Well, those are really lousy business practices if you ask me. The manufacturer forces you to buy an expensive new cartridge, even though it would continue to work perfectly by refilling it. Luckily there are some solutions to that problem.
- You can replace the counter board inside the cartridge with a new one. You can buy those for a few bucks on eBay.
- You can reset the page counter by reprogramming the EEPROM of the toner counter board.
Solution 2 sounded really geeky. So I went for that.
There already exists a tool called SSBR – Sad Samsung EEPROM Backup/Restore Utility (cool name!). It runs on MS-DOS. And you have to fabricate a connector cable which connects the parallel port of a PC to the three contacts of the toner cartridge. There are however some problems with that.
- Nobody runs MS-DOS on a PC anymore.
- Almost no PC has a parallel port anymore. Also the parallel port has to be operated in standard mode. Not EPP or ECP which is standard nowadays.
The first problem was solved by creating a Flash Drive which boots straight into DOS. And luckily, I had an ancient PC with a parallel port collecting dust in the attic which was still working. Then I soldered together a cable and ran the tool. It worked at the first try. Sweet. The printer was alive again. I was happy. But then I got an even better idea.
Raspberry Pi FTW
When I was refilling the cartridge I took a look at the counter board. It only had a single chip on it. A ST Microelectronics 24C04WP. I googled for a data sheet. What do you know? It’s a 4 Kbit EEPROM programmable through a serial I²C bus.
Now it dawned on me. Doesn’t the Raspberry Pi have I²C capabilities? Some more goggling. Yes it does! Straight through its GPIO header. I thought it would be really cool to use my Pi to read from and maybe even write back to that EEPROM. That could be really useful. Because more people probably own a Raspberry Pi nowadays then a PC or laptop with a parallel port.
After fiddling around for a couple hours I was indeed able to access the EEPROM with the Raspberry Pi. I write down the steps here for anybody who wants to give it a shot as well:
1: Wiring the Cartridge to the Raspberry Pi
The I²C bus uses four pins. VCC (+3.3V), GND, a clock line (SCL) and a data line (SDA). The counter board has however only three contacts. I figure that they are creating the power rail internally by flattening the clock signal. So we only have to connect three pins:
- Raspberry Pi Pin 3 SDA –> left connector on toner (red wire)
- Raspberry Pi Pin 5 SCL –> right connector on toner (green wire)
- Raspberry Pi Pin 6 GND –> middle connector on toner (black wire)
Note that I have a Raspberry Pi model B+. But I think the pin layout is the same on the other models (make sure to check first). Here are some pictures of the pin layout and how I connected the Pi to the toner cartridge. I used some crocodile clips soldered to a 0.1″ female header connector:
2: Enabling I²C on the Raspberry Pi
I²C is not enabled by default in Raspbian. First, we need to add the i2c modules i2c-bcm2708 and i2c-dev to /etc/modules:
snd-bcm2835 i2c-bcm2708 i2c-dev
Now comment out the module in /etc/modprobe.d/raspi-blacklist.conf:
blacklist spi-bcm2708 #blacklist i2c-bcm2708
On newer Raspbian kernels it might also be necessary to enable I²C in raspi-config:
In Advanced Options select and enable I2C.
After a reboot, the modules should be loaded by default. You can check with lsmod.
Now we also install some tools in order to be able to fiddle with the i2c bus:
sudo apt-get install i2c-tools hexedit
The package i2c-tools contains a tool called i2cdetect, which can be used to probe the i2c bus. The i2c bus at the GPIO header of my Raspberry Pi correlates to the i2c device at bus 1. I am not sure if this is the same with all models. You can also try bus 0 if it doesn’t work:
sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- 56 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
If that works, all is good. Here we can see that there is something available on bus 1 at the addresses 0x56 and 0x57. It turns out that the EEPROM contains 512 bytes in two banks with each 256 bytes, which are addressed through those two i2c addresses.
3: Reading the EEPROM
There exists a handy little tool for Linux called eeprog which can read and program EEPROMs through i2c. However the official version doesn’t work with the 24C04 because of some timing issues. Luckily, there exists a modified version which does not have that problem. The source code can be downloaded here: eeprog-0.7.6-tear5.tar.gz. Extract the tar file and run make to compile the source.
Now we can finally try to read from the EEPROM:
sudo ./eeprog /dev/i2c-1 0x56 -8 -r 0x00:0x100 -f > dump1
eeprog 0.7.6-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x56, Mode: 8bit Operation: read 256 bytes from offset 0, Output file: <stdout> Reading 256 bytes from 0x0
Note that we use the device /dev/i2c-1, which is the i2c bus 1. And that we are reading 256 bytes through i2c address 0x56 in 8 bit mode. The dumped file should be exactly 256 bytes long. Like I mentioned above, there is a second bank of 256 bytes at address 0x57. But it’s empty, respectively it contains only bytes of value 0xff. So we can ignore that memory area and focus only on the 256 bytes at 0x56.
With hexdump we can display the content of the binary dump:
hexdump -Cv dump1
00000000 53 41 4d 53 55 4e 47 e3 ff ff ff ff ff ff ff ff |SAMSUNG.........| 00000010 ff ff ff ff ff ff ff ff 43 4c 50 35 31 30 ff ff |........CLP510..| 00000020 32 30 30 39 2e 31 30 ff 6b 2d 30 39 31 30 32 30 |2009.10.k-091020| 00000030 37 36 33 35 38 ff ff ff ff ff ff ff ff ff ff ff |76358...........| 00000040 ff ff ff ff ff ff ff ff ff ff ff ff 00 ff ff ff |................| 00000050 00 ff ff ff 01 ff ff ff 01 e7 a0 d0 ff ff ff ff |................| 00000060 ff ff ff ff ff ff ff ff 02 2e 10 38 ff ff ff ff |...........8....| 00000070 ff ff ff ff ff ff ff ff 02 8a 2b c0 ff ff ff ff |..........+.....| 00000080 ff ff ff ff ff ff ff ff 00 00 08 82 ff ff ff ff |................| 00000090 01 a9 23 2f ff ff ff ff aa bb ff ff ff ff ff ff |..#/............| 000000a0 30 32 34 37 38 ff ff ff ff ff ff ff ff ff ff ff |02478...........| 000000b0 ff ff ff ff ff ff ff ff 45 55 ff ff ff ff ff ff |........EU......| 000000c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000d0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000e0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000f0 53 41 4d 53 55 4e 47 e3 43 4c 50 35 31 30 ff ff |SAMSUNG.CLP510..| 00000100
We have a winner. It seems like it contains some ASCII strings describing the printer and toner model, as well as some other data. Somewhere in there is our page count.
4: Hacking the Counter
What I did next was to print a page and create another dump afterwards. Then I compared those two dumps:
hexdump -Cv dump1 > dump1.hex hexdump -Cv dump2 > dump2.hex diff dump1.hex dump2.hex
I highlighted the differences:
The four bytes at address 0x88 seem to be the page counter. Hex 0x882 equals to 2178 which is exactly what the printer tells me is the page count of the black color. The four bytes at 0x90 are also some sort of counter. Both are counting up. The bytes at 0xa0 are the ASCII representation of a number which is counting down. Maybe it’s the pages left. I am not sure.
Now we can use hexedit to manipulate the dump. After a bit experimentation I found out that only the bytes at 0x88 and 0x90 need to be changed. I did set them both to zero:
Now we can write the dump back to the EEPROM. We again access the memory bank at i2c address 0x56. And we write back the whole dump to memory address 0x00:
sudo ./eeprog /dev/i2c-1 0x56 -w 0x00 -f -t 5 < dump2
eeprog 0.7.6-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x56, Mode: 8bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 5 milliseconds Writing <stdin> starting at address 0x0 ................................................................................................................................................................................................................................................................
The parameter -t 5 is important. It causes eeprog to wait 5ms after every byte it writes. The parameter is not available in the original version of eeprog. And it does not work with the 24C04 otherwise (Input/output error). Once the image is written back to the chip you should read it again and check that the correct data was actually written to the EEPROM. If everything worked alright you can load the cartridge back into your printer. And it should now think that has been given a brand new toner cartridge.
Here is a comparison of the status page before and after the reset that I printed on my printer:
Now isn’t that nice? That saved me some money and I could finally use the hardware capabilities of my Raspberry Pi. I am sure there are other printer models out there which use the same or similar methods to store the page count on the toner cartridge. Let me know if you try that method as well on this printer or some other models.