Philips AC2887 Air Purifier

Ressources, reverse engineering and mods on this device. It's a nice appliance!

Last updated: 06/2023



Official documentation

[User manual]

Teardown / Photos

The teardown is intuitive. There are only two types of screw (Philips head, ofc :), one short and one long, without mixing at the same teardown stage. No flimsy flex cable nor stuff to guitar pick out. Materials are solid, and conception is sound. See inside in the [Teardown gallery]

Identified Bill of material

Firmware dumps

For the main board

Here are binary dump of the flash, option bytes and eeprom for the main control board, as well as a lightly commented dissassembly of the firmware flash. The read out protection (ROP, option byte 0) is not set.

If I can get the stm8 IDA plugin to build, a decompiled and more heavily commented version of the FW might follow.

For the PM-meter board

Dump of the PM meter board was not attempted at this time

For the interface board

Dump of the interface board was not attempted at this time

Pinout for the various cables

Motor control not reversed. Board can be safely powered when disconnected from the appliance using the debug hearder with 3.3V or 5V.

Protocol between the main and the PM2.5 meter board

The PM2.5 DATA line is a 1 Hz period signal whose duty cycle at the low voltage value is the measured PM2.5 value (relative), from 0% at 0 PM2.5 to 100% at a score of 249 on the display interface (unclear what it means in actual unit).

Protocol between the main and interface board

General structure

The protocol is of particular relevance, as all function of the device as accessible by a serie of interface button emulation. The protocol is bog standard i2c at 50 kHz. Of note, the protocol is design so the panel MCU can be as simple as possible - for instance, the digits are sent as which seven segment to light up, not as integer.

The main board initiate with a start condition, addressing a write to adress 0x5A that acknowledges. Follow 5 bytes, which are acknowledged: LED for the status of the top panel LEDs, D2 for the central digit of the top panel display, D1 for the first digit, D2 for the last digit, and CKSUM a pseudo-checkum which is the sum of the 4 preceding byte XOR'd with 0xFF.

After a repeated start condition, the main board reads to adress 0x5B, which is acknowledged. Four bytes follow: one for the status of the button (BUTTON), one 0x00, two repeated check byte that are (BUTTON XOR 0xFF), which not acknoledged. A stop condition finishes the transmission. The next transmission, under the same protocol, will happen about 10 millisecond after the start of the current one.

Panel led control

The LED byte is a concatenation of single bit flags for the 4 LEDs on the front panel. Here is a list of the LED byte value seen during operation, and the meaning of each bit, and what the LEDs are.

p  = big PM 2.5 heading on
F  = small factory icon on
A  = small allergen icon on
V  = virus icon on
-  = not set

(none)      0x00  0b00000000
pFAV        0xA7  0b10100111
p           0x84  0b10000100
 F          0x02  0b00000010
  A         0x20  0b00100000
   V        0x01  0b00000001
pF          0x86  0b10000110
p A         0xA4  0b10100100
p  V        0x85  0b10000101
                    p-A--pFV  <- which bits control what

Digit encoding

The LED digits are sent as which 7-segment display to light up. This allows display of some "letters" too. Here are collected message on the wire, and deduced mapping of each bit to a segment. The "d" bit is apparently duplicated.


Display segment nomenclature:
  _  a
b| | c
  - d
e| | f
  _ g

0x00: off
0xFF full on as seen on the wire.

0x24 = 0b00100100 is 1 (    c     f  )  
0xF9 = 0b11111001 is 2 (a   c d e   g)
0x7D = 0b01111101 is 3 (a   c d   f g)
0x76 = 0b01110110 is 4 (  b c d   f  )
0x5F = 0b01011111 is 5 (a b   d   f g)
0xDF = 0b11011111 is 6 (a b   d e f g)
0xFF = 0b11111111 is 8 (a b c d e f g)
0x7F = 0b01111111 is 9 (a b c d   f g)
0xF7 = 0b11110111 is A (a b c d e f  )
0xDA = 0b11011010 is t (  b   d e   g)
0xD6 = 0b11010110 is h (  b   d e f  )
       edcdgfba        <- which bits control which segment
       Note: d is duplicated    

Button press encoding

The button press are sent as single bit flags on a byte, followed by 0x00 and two time a pseudo checksum which seems to be (BUTTON XOR 0xFF). The message is sent as long as the button is pressed - the panel MCU is truly simple. I have unfortunately forgotten to test two (and more) simultaneous button press, but I believe bitwise OR for the BUTTON byte makes sense. There are operation requiring button to be held for a time (the reset operation for the prefilter cleanup warning), and operation that require holding 2 buttons (HEPA and charcoal filter replacement timer warning). Both of these have associated messages on the 7-segment display so it is not require to know for how long to sent this message - just wait for the correct code to appear.

As seen on the wire:

no button pressed 
00 00 FF FF
first button pressed (ON/OFF) -> A bit
04 00 FB FB
second button pressed (lightbulb) -> B bit
02 00 FD FD
third button pressed (circled arrow A) -> C bit
01 00 FE FE
fourth button pressed (fan) -> D bit
20 00 DF DF
fifth button pressed (clock) -> E bit
10 00 EF EF
sixth button pressed (back arrow) -> F bit
08 00 F7 F7

Hence probably 0b00DEFABC.

Issues and solutions

Fan slightly noisy: Dissassemble everything up to removing the fan from the driving rod. Bend the fan wheel a bit to restore flatness the best you can. Reassemble while torquing everything to resistance. Solved it for me at least.

Recommended mods

Shut-up-machine mod

Desolder buzzer from main board to make the appliance silent. Does not impact functionality.

Wifi mod

By tapping the interface i2c with a MCU of our own that will relay message, but also insert our own, we can control both the function of the appliance and what is displayed on top. I choose to make an external tap (picrelated), but WiFi connection from within the plastic body is probably workable nonetheless. The FW for the mode is not written yet.

TODO

Take an exhaustive reading of voltage at every contact on the board, to help diagnosing issue by knowing what should appear where. Maybe also resistance reading and PCB trace reversing. Lots of time needed for this though - I don't have a computer-linked multimeter setup for easier data entry.

Firmware reversing: some practice on stm8 reversing would be helpful since that seems prevalent in appliances. Not as good tooling as stm32...