Controlling a washing machine motor with an Arduino
Reverse engineering the original setup
In the washing machine, the motor driver received mains power through a relay on the main control board. The motor driver was controlled by the main control board via a 5-pin cable. The pinout is shown in the image below: The main control board communicates with the motor driver using an SPI bus. Data is transmitted in bytes with the most-significant-bit first. On the rising edge of the clock signal, the main board updates the signal on the MOSI pin, and the motor driver updates the signal on the MISO pin. On the falling edge of the clock, both devices sample the signals from the other device. In contrast to most implementations, a 1 is actually represented by a low voltage (0V), and a 0 is represented by a high voltage (5V). Thus, the signal on the wire is actually the complement of the transmitted data. An example waveform can be seen in the image below: In the above image, the main board transmits11000110 00000000
, or C6 00
in hex, to the motor driver. Recall that the voltage on the wire is the complement of the transmitted signal.
The length of a clock pulse is around 0.5 ms, and the spacing between clock pulses for the same byte is 0.5 ms. The spacing between clock pulses in different bytes is 2.5 ms.
Reverse engineering the commands
To determine the commands that are needed to make the motor driver spin the motor, I connected an Arduino to the CLK, MISO, and MOSI pins and used a small sketch to listen on the SPI bus and communicate the intercepted data to my computer via the serial port. Then, I wrote a Python program to take the raw data from Arduino and extract the commands that are transmitted.Description of the reverse-engineered protocol
Idle pattern
When neither device is transmitting anything, the main board transmitsC6 00
repeatedly on the bus. Since the motor driver has no control over the clock signal, this is necessary to allow the motor driver to transmit anything on the bus. Normally, the motor driver will send 00
for every byte.
Transmission from the main board to the motor driver
The main board starts a transmission by transmitting AA
in place of the idle pattern. This is followed by one byte indicating the length of the packet, the actual contents of the packet, a CRC8 computed with polynomial 0x01
, and the complement of the CRC. For example, the full command to stop the motor is AA 06 11 00 00 0B 86 00 9A 65
. Note that neither the start byte, the length byte, the CRC, or its complement are included in the length of the packet.
While the main board is transmitting, the motor driver will be transmitting 00
. However, on the last byte (the complement of the CRC), the motor driver will respond with 0F
. Thus, for the previous example command, the motor driver will respond with 00 00 00 00 00 00 00 00 00 0F
.
Transmission from the motor driver to the main board
The motor driver starts a transmission by transmitting a non-zero value during the second byte of the idle pattern. This byte is the length of the packet the motor driver intends to transmit. The packet is followed by a CRC8 computed with polynomial 0x01
and a null byte, both of which are not included in the length of the packet.
The main board transmits 00
during the packet and 0F
during the final null byte.
Interrupted transmission
Sometimes the motor driver will interrupt a transmission from the main board. To do this, it transmitsFF
at any point during the main board's transmission. The main board returns to transmitting the idle pattern, at which point the motor driver is free to begin transmitting.
Commands and responses
In this section I will try to describe all of the commands, responses, and error messages I have encountered.Known commands
Bytes (start byte, length, and CRC omitted) | Description |
---|---|
11 00 00 0B 86 00 |
Stop motor |
11 01 74 00 00 80 |
Test the inverter by driving one of the coils only |
11 xx xx 02 54 00 |
Run the motor in reverse. x is the speed, given as a negative two's complement value, MSB first |
11 xx xx 01 2A 00 |
Run the motor forwards. x is the speed, MSB first |
44 8r dd dd dd dd dd dd dd dd |
Write configuration register r. Each register has 8 bytes of data (d). A total of 16 configuration registers are known, but their functions are not known. See "Configuring the motor driver" |
Unknown commands
Bytes (start byte, length, and CRC omitted) | Notes |
---|---|
33 ff ff |
Query error or status message? Transmitting this followed immediately by the "stop motor" command produces the response 88 80 00 00 14 00 00 |
55 |
In the original setup, this was transmitted about once per second. |
Status message
The motor driver can be configured to transmit a status message roughly three times per second. The status message takes the form82 xx xx yy yy
with the start, length, and CRC bytes omitted. X is the speed of the motor (MSB first) and Y is proportional to the torque or power of the motor (also MSB first). The most significant bit of the speed field is 1 when the motor has reached its target speed. The torque/power field can be seen to increase when the motor is loaded.
Configuring the motor driver
When the main board starts up, it transmits the following block of messages to the controller (again, with start byte, length, and CRC omitted):
44 80 00 7c 3e d5 03 7e 3e d5
44 81 01 7e 56 7c 18 70 00 30
44 82 27 a1 01 fb 71 00 0c 63
44 83 0c 64 09 99 0a 3b 09 f6
44 84 08 88 63 8d 72 eb 63 11
44 85 5b 24 18 31 01 4b 6d 8c
44 86 0b df 03 c7 0c cd 50 00
44 87 4b c9 79 b9 73 45 32 73
44 88 40 dd 79 14 7b f6 00 05
44 89 01 6c 7f f0 00 03 00 5a
44 8a 00 46 03 e8 00 05 01 6c
44 8b 7c 71 4c be 00 02 00 0f
44 8c 00 05 30 b8 ea 60 5d c0
44 8d ff ff 00 22 ff ff ff ff
44 8e ff ff ff ff ff ff ff ff
44 8f ff ff ff ff a0 86 00 95
Miscellaneous messages
Bytes (start byte, length, and CRC omitted) | Notes |
---|---|
BB 20 00 |
Produced when the motor driver turns off the relay through which the VFD is powered. When power is disconnected from the motor driver, the main capacitors will slowly discharge. When they are partially discharged, the VFD is powered off but the control circuit will continue running for a little while. |
BB 04 00 |
Produced when the motor driver enters a lockout mode (see Results section). |
BB 24 00 |
Produced when the relay is turned off and the motor driver is in lockout mode. This suggests that messages beginning with BB are actually some kind of status bitmask. The other bits in the bitmask are unknown. |
CC 4D 30 42 30 30 31 31 35 |
Transmitted once per second before the motor driver is configured (as described in Configuring the motor driver). |
88 xx xx uu vv yy zz |
Produced at several occasions to indicate the status of the drum. xx xx indicates the current speed and is interpreted like the speed field in the status message, as explained above. I do not know the interpretations for U, V, Y, and Z. Their values seem to vary based on whether the motor is currently at rest, accelerating, or braking. |
Results
When testing the motor driver with the Arduino, the motor driver would occasionally lock up, sometimes in response to an invalid command, but sometimes just randomly, and would unlock only after some time. Power-cycling the motor driver did not unlock the driver. When this occurred, the motor driver would transmitBB 04 00
. Since the main board of the washing machine is not working, I cannot determine which commands would have been used to unlock the motor or what error the main board would display in the event that this happens. I also do not know it the motor driver is fully functional or not, and I was not able to find any documentation for either the motor driver as a whole, or the control chip on the board.
Comments
Post a Comment