The USB programming cable and Bluetooth adapter both will speak CAN bus to the Metacycle's controller and expose a serial protocol. This allows you to program the vehicle to perform differently. Limit the max RPMs, provide a power assist when you are pushing it, enable cruise control, and configuring the throttle are all done using this serial protocol.
Looking to write your own software? Bartek Banachewicz has made his notes public for a different controller, but it might speak the same protocol and could provide insight to the frames being sent. Also, another user has a packet dump and analysis that will help you decipher what's going across the wire. There's also a post decoding the serial protocol and an Android app post also has extra details.
The following is a very low-level dive into the controller's message format. It's here to help provide a reference for what the USB to CAN bus adapter provides to the EM_V3-40 software (and all derivatives).
Each section shows a sample message in hex. All hex values are shown as code. Messages are all 24 bytes long, including the envelope. Each section talks about specific values, which will be in bold to help locate them in the sample message.
Two-byte numbers are stored with the most significant byte first. 00 24 is 36 in decimal.
All decimals are transmitted as fixed position, so 1.2 is transmitted as the decimal value 12, which is 0c.
Negative numbers are saved as two's complement. ff is -1, fe is -2, fd is -3. To convert to a two-byte negative number, take the first overflow value (256 for one byte, 65536 for two bytes) and add the negative number. 65535 + (-2) is 65534, which is ff fe. Convert back from hex by checking if the high bit is set. If so, take the number and subtract the overflow value; ff fe is is 65534, then 65534 - 65536 is -2.
Message Envelope Structure - Applies to all messages, incoming and outgoing.
Each message, both to and from the controller, is 24 bytes long. This is a sample "LDGET" request. The first two and last two bytes (both are bolded) are the envelope.
c9 14 02 4c 44 47 45 54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 81 0d
c9 - The first byte is c9 if it is being sent to the controller, c0 if it is a response from the controller.
14 - The next byte is the payload size. Hex 14 is equal to decimal 20. There's 20 bytes in all payloads.
After those two bytes, the next 20 bytes is the payload.
81 - The second from the last is an XOR of all previous bytes (the payload and the first two bytes of the message envelope).
0d - The last byte is always 0d.
LDGET Request - Get current controller settings
c9 14 02 4c 44 47 45 54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 81 0d
The first two bytes are the envelope.
02 - Unknown.
4c 44 47 45 54 - "LDGET"
The rest of the payload are NULLs.
The last two bytes are the envelope.
LDGET Response Header - 7 responses are provided to the LDGET request.
c0 14 05 52 07 3a c7 0f df 52 14 00 00 00 00 00 00 00 00 00 00 00 ef 0d
The first two bytes are the envelope.
05 - Response packet
52 - "R" Read
07 - The response number, from 1 to 7.
The middle 17 bytes are the section of configuration settings. See "Config Settings 1" through "Config Settings 7" for explanations.
The last two bytes are the envelope.
P Request - Program the controller
c9 14 02 50 01 14 02 03 5c 02 3a 0a 00 78 26 e8 02 26 05 d2 00 51 e1 0d
The first two bytes are the envelope.
02 - Request packet
50 - "P" to Program
01 - The settings page number, from 1 to 7.
The middle 17 bytes are the section of configuration settings. See "Config Settings 1" through "Config Settings 7" for explanations.
The last two bytes are the envelope.
P Response - Controller settings were updated; sent after all 7 configuration settings were sent to the controller.
c0 14 0d 50 4e 03 4d ff f8 00 00 00 00 00 00 00 41 3e 00 00 49 00 b8 0d
The first two bytes are the envelope.
0d - Response packet.
50 - "P" for Program.
The next 18 bytes are unknown.
The last two bytes are the envelope.
Init Response - Controller was initialized
c0 14 0d fe ef 55 aa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 37 0d
The first two bytes are the envelope.
0d - Response packet.
fe - Init
The next 18 bytes are NULL.
The last two bytes are the envelope.
RESET Request - Restarts the controller. After writing configuration, the controller needs to reboot and this is one way to do that.
c9 14 02 52 45 53 45 54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8a 0d
The first two bytes are the envelope.
02 - Request packet.
52 45 53 45 54 - "RESET".
The next 14 bytes are NULL.
The last two bytes are the envelope.
CLERR Request - Resets the USB adapter, which is what the CLR DTC button does in the advanced debug panel.
c9 14 02 43 4c 45 52 52 00 00 00 00 00 00 00 00 00 00 00 00 00 00 95 0d
The first two bytes are the envelope.
02 - Request packet.
43 4c 45 52 52 - "CLERR".
The next 14 bytes are NULL.
The last two bytes are the envelope.
RESTT Request - Resets the debugging line.
c9 14 02 52 45 53 54 54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9b 0d
The first two bytes are the envelope.
02 - Request packet.
52 45 53 54 54 - "RESTT".
The next 14 bytes are NULL.
The last two bytes are the envelope.
RESTT Responses - Debug line was reset. After this is received, an AT command (AT+PIN7539) is received from the device, possibly programming a Bluetooth adapter to use the pin 7539.
c0 14 0d fe ef 55 aa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 37 0d
41 54 2b 50 49 4e 37 35 33 39 0d 0a
The first two bytes are the envelope.
0d - Response packet.
fe ef 55 aa - Unknown.
The next 15 bytes are NULL.
The last two bytes are the envelope.
SHOW Request
c9 14 02 53 48 4f 57 00 00 00 00 00 aa 00 00 00 0a aa 05 d2 00 51 50 0d
The first two bytes are the envelope.
02 - Request packet.
53 48 4f 57 - "SHOW".
4f indicates using CAN ID 3ff (channel A). This value changes when using different CAN IDs. The controller is 3fe. If you forget to reset the channel back, it is unfortunately saved to the registry and will need to be reset manually. Search for keys named "EM_V3" and delete them.
50 is CAN ID 3fd ( channel B)
51 is 3fb (channel C)
52 is 3f9 (channel D)
53 is 3f7 (channel E)
54 is 3f5 (channel F)
55 is 3f3 (channel G)
56 is 3f1 (channel H)
57 changes to 59 when the "CAN" advanced debug checkbox is enabled. It allows switching to different CAN IDs.
00 00 00 00 00 - Unknown, NULL.
aa - Local or remote. aa = local, 55 = remote.
00 00 - Throttle remote. Divide by 5945 (unverified through capture) to get throttle voltage.
00 - Bitmask
Bits 01 and 02: Set gear for remote mode.
0 = Low gear
1 = Mid gear
2 = High gear
3 = Sport mode.
Bit 04: Unknown.
Bit 08: Show D-axis and Q-axis amperage instead of battery voltage and battery amperage.
Bit 10: Show D-axis and Q-axis voltage instead of battery voltage and battery amperage.
Bit 20: Indicate "lock" in remote mode.
Bit 40: Indicates reverse gear in remote mode.
Bit 80: Indicate the brake is engaged in remote mode.
0a - Weak flux calibration, from Config Settings 2.
aa - Unknown.
05 d2 - Voltage calibration. 05d2 is 1490. This is the same value as what's from Config Settings 1. If this is incorrect, the controller could output the fault code for undervoltage or overvoltage in the response.
00 51 - Current calibration. 0051 is 81. This is the same value as what's from Config Settings 1.
The last two bytes are the envelope.
SHOW Response - Multiple types of responses are possible. It depends on the SHOW request send. There is no method to differentiate which type of request was sent from just the response.
c0 14 0d 59 42 03 46 ff f8 01 00 00 00 00 02 b8 5d 4b 22 d6 80 03 01 0d
The first two bytes are the envelope.
0d 59 42 - Unknown.
03 46 - First requested value. This changes based on the SHOW request.
When requesting battery info, this is fixed-point battery voltage. 0346 = 838, which is 83.8 V.
When requesting axis voltage, this is fixed-point Q-axis voltage. 0004 = 4, which is 0.4 V.
When requesting axis amperage, this is fixed-point Q-axis amperage. ffff = -1, which is -0.1 A.
ff f8 - Second requested value. This changes based on the SHOW request.
When requesting battery info, this is fixed-point battery current. fff8 is -8, which is -0.8 A.
When requesting axis voltage, this is fixed-point D-axis voltage. fff1 is -15, which is -1.5 V
When requesting axis amperage, this is fixed-point D-axis amperage. fff8 is -8, which is -0.8 A.
01 - Unknown.
00 00 00 00 - Fault code bitmask. See table at top of page for fault code bits.
02 b8 - RPM.
5d - Controller temp + 50. 5d = 93, minus 50 = 43° C.
4b - External temp + 50. 4b = 75, minus 50 = 25° C.
22 d6 - Temperature coefficient. 22d6 = 8918.
80 - Bitmask.
Bits 01, 02: Current gear. 0 is low, 1 is medium, 2 is high, 3 is sport.
Bit 04: Reverse.
Bit 08: Parked.
Bit 10: Brake
Bit 20: Lock (anti-theft)
Bit 40: Side stand
Bit 80: Regen
03 - Controller status. 0 = idle, 1 = init, 2 = start, 3 = run, 4 = stop, 5 = brake, 6 = wait, 7 = fault.
The last two bytes are the envelope.
Config Settings 1 - Explanation of data fields in LDGET or P
c0 14 05 52 01 14 02 03 5c 02 3a 0a 00 78 22 60 02 26 05 d2 00 51 61 0d
14 - Model type. Read-only.
05 = EM-30S
0A = EM50S
14 = EM-100S
1E = EM150S
28 = EM-200S
02 - High nibble (0) is the brand name, low nibble (2) is the voltage.
High nibble: brand name
0* = common
1* = lvyuan
2* = lima
3* = lvjia
4* = lvjia-1
5* = guangyang
6* through f* = reserved
Low nibble: voltage
*0 = 48 V
*1 = 60 V
*2 = 72 V
*3 = 84 V
*4 = 96 V
*5 through *f = reserved
03 5c - Overvoltage as fixed-point decimal, high byte first. 035c is 860 decimal, so 86.0 V is the overvoltage threshold.
02 3a - Soft undervoltage as a fixed-point decimal, high byte first. 023a is 570, so 57.0 V is the soft undervoltage threshold.
0a - Undervoltage variation as a fixed-point decimal. 0a is 10, so 1.0 V is the variation.
00 78 - Regen current as a decimal. 0078 is 120 A.
22 60 - Phase current. 2260 is 8800 A.
02 26 - Undervoltage as a fixed-point decimal. 0226 is 550, so 55.0 V.
05 d2 - Voltage calibration. 05d2 is 1490.
00 51 - Current calibration. 0051 is 81.
Config Settings 2 - Explanation of data fields in LDGET or P
c0 14 05 52 02 00 dc 50 4b 64 0b b8 2e e0 17 70 04 25 08 78 1e 0a 7d 0d
00 dc - Bus current limit. 00dc = 20 A.
50 - Low gear RPM %. 50 = 80%.
4b - Mid gear RPM %. 4b = 75%.
64 - High gear RPM %. 64 = 100%.
0b b8 - Flux weakening, weak magnetic value. 0bb8 = 3000.
2e e0 - High flux weakening value (KP). 2ee0 = 12000.
17 70 - Mid flux weakening value, start phase. 1770 = 6000.
04 - Bitmask. Unless otherwise specified, turning on the bit turns on the feature.
Bit 01: Speed limiter.
Bit 02, 04, 08: Default gear. 02 = high, 04 = mid, 08 = low.
Bit 10: Motor type. 00 = surface, 10 = v-type.
Bit 20: Gear changing. 00 = button, 20 = switch.
Bit 40: Noise reduction (low brake).
Bit 80: Soft start.
25 - Speed limit percent. 25 = 37%.
08 - Soft start grade. Values can range from 1 to 16. 08 = 8.
78 - Sport mode auto disable timer. 78 is 120 seconds.
1e - Sport mode recovery timer: 1e is 30 seconds.
0a - Maximum torque per ampere (flux-weakening compensation). 0a = 10.
Config Settings 3 - Explanation of data fields in LDGET or P
c0 14 05 52 03 00 78 8c af b4 00 69 24 54 24 d4 0a 70 10 19 e8 71 6c 0d
00 78 - Hall shift angle. Signed integer. Positive numbers are normal. Negative numbers are stored as 65536 - N. 0078 = 120°. ff88 would be -120°.
8c - Controller high temp threshold. 8c = 140° C.
af - Controller over temp (second protection phase). af = 175° C.
b4 - Max temperature limit. b4 = 180°C.
00 69 - TC1: engine phase when temp limit occurs. 0069 = 105° C.
24 54 - TC2: traction control or dampening. 2454 = 9300.
24 d4 - One-LIN speed compensate (real speed from GPS / one-LIN) * 64 * 256. 24d4 = 9428.
0a - Reverse max RPM. 0a = 10%.
70 - Bitmask. Unless otherwise specified, turning on the bit turns on the feature.
Bits 01, 02, 04: Unknown.
Bit 08: Hill hold control.
Bit 10: Exchange phase wire blue-green.
Bit 20: Exchange hall wire yellow-blue.
Bit 40: Sport mode auto disable.
Bit 80: Motor rotation changing. 00 = forward, 80 = reverse.
10 - Number of pole pairs. 10 = 16 pole pairs.
19 - EBS %. Enables regenerative braking and determines how much regenerative braking is applied. 19 = 25%.
e8 - Software version stored as a fixed precision integer. e8 = 232, which is version 2.32.
71 - Hardware version stored as a fixed precision integer. 71 = 113, which is version 1.13.
Config Settings 4 - Explanation of data fields in LDGET or P
c0 14 05 52 04 04 0c cc 03 e8 04 b0 51 44 14 01 2c 13 88 00 28 03 80 0d
04 - Bitmask. Unless otherwise specified, turning on the bit turns on the feature.
Bit 01: Moving vehicle booster (MBC).
Bit 02: Hill descent control (HDC), maximum RPM limiter.
Bit 04: Speedometer output. 00 = hall speedometer, 04 = one-LIN.
Bit 08: Enable cruise control.
Bit 10: Double voltage detection.
Bit 20: Double voltage low/high. 00 = low, 20 = high.
Bit 40: Secure boot.
Bit 80: Unknown / reserved.
0c cc - Moving vehicle booster amount as a percent of the motor base speed. 0ccc = 3276. Divide this by 327 to get ~10%.
03 e8 - Moving vehicle booster torque. 03e8 = 1000.
04 b0 - Hill descent control, max RPM of motor. 04b0 = 1200 RPM.
51 - Low gear percentage of amps. 51 = 81%.
44 - Mid gear percentage of amps. 44 = 68%.
14 - High gear's overrating speed (KD). 14 = 20% over maximum.
01 2c - Flux weakening value (KI). 012c = 300.
13 88 - Max phase current limit. 1388 = 5000.
00 28 - Max phase limit time. 0028 = 40 seconds.
03 - Weak flux calibration. 03 = 3.
Config Settings 5 - Explanation of data fields in LDGET or P
c0 14 05 52 05 c0 00 c0 00 c8 80 c0 0b c0 25 c3 11 c0 00 58 00 0a a0 0d
c0 00 - PD0 - see Port Settings.
c0 00 - JTCK - see Port Settings.
c8 80 - SWD - - see Port Settings.
c0 0b - PA11 - see Port Settings.
c0 25 - PB3 - see Port Settings.
c3 11 - PD1 - see Port Settings.
c0 00 - PA12 - see Port Settings.
58 00 - PC15 - see Port Settings.
0a - Unknown / reserved. Suspected to be a random byte from memory.
Config Settings 6 - Explanation of data fields in LDGET or P
c0 14 05 52 06 c0 00 c0 0f c0 8a c2 09 c1 10 c2 07 c0 00 cb 92 20 a6 0d
c0 00 - PA0 - see Port Settings.
c0 0f - PB9 - see Port Settings.
c0 8a - PB4 - see Port Settings.
c2 09 - PA15 - see Port Settings.
c1 10 - PB2 - see Port Settings.
c2 07 - PC14 - see Port Settings.
c0 00 - PB5 - see Port Settings.
cb 92 - PD15 - see Port Settings.
20 - Unknown / reserved. Suspected to be a random byte from memory.
Config Settings 7 - Explanation of data fields in LDGET or P
c0 14 05 52 07 3a c7 0f df 52 14 00 00 00 00 00 00 00 00 00 00 00 ef 0d
3a - Throttle begin voltage. 3a = 58, which converts to 1.27 on screen. Due to the resolution, not all decimal values can be saved perfectly; 1.26 and 1.27 both code to 3a. To convert the saved value to voltage, add 1, multiply by 5.5, then divide by 255, and finally drop digits after the second decimal. 3a is 58, add 1 to get 59, then becomes 324.5 after multiplication, divides to 1.27155, then with digits dropped it is 1.27. To convert voltage to the saved value, multiply by 255, divide by 5.5, then drop the decimal portion. 1.26 times 255 is 321.3. Divide it by 5.5 to get ~58.42. Remove the decimal portion to get 58. Convert 58 to hex, resulting in 3a.
c7 - Throttle end voltage. c7 = 199, which converts to 4.31. See the earlier throttle conversion explanation.
0f - Throttle low protect. 0f = 15, which converts to 0.34. See the earlier throttle conversion explanation.
df - Throttle high protect voltage. df = 223, which converts to 4.82. See the earlier throttle conversion explanation.
52 - Rate of decline. 52 = 82.
14 - Rate of acceleration. 14 = 20.
00 00 - Starting torque.
00 00 - Torque smoothing factor.
00 00 00 00 00 00 00 - Unused / reserved. Sometimes has values that appear to come from other config settings. When written as INI files, these could also have random data even if the controller's settings do not change.
Port Settings - These are the checkboxes, radios, and drop-down lists to describe what's attached to the controller ports. This will be a two byte value from Config Settings 5 and Config Settings 6.
c3 - F/U/D mode and checkboxes.
Bit 01 if SW checked.
Bit 02 if U mode, bit 04 if D mode, neither bit is F mode.
Bit 08 if LA checked.
Bits 10, 20, 40, 80 are unknown. Typically this value is c in hex, meaning 40 and 80 are set. For one port it is 5 in hex, meaning 10 and 40 are set.
11 - Bit flag and program.
Bit 80 if IO is checked.
Program values are from 00 to 7f (1 to 128). They are detailed in the interactive spreadsheet near the top of this page.
Port Settings - These are the checkboxes, radios, and drop-down lists to describe what's attached to the controller ports. This will be a two byte value from Config Settings 5 and Config Settings 6.
c3 - F/U/D mode and checkboxes.
Bit 01 if SW checked.
Bit 02 if U mode, bit 04 if D mode, neither bit is F mode.
Bit 08 if LA checked.
Bits 10, 20, 40, 80 are unknown. Typically this value is c in hex, meaning 40 and 80 are set. For one port it is 5 in hex, meaning 10 and 40 are set.
11 - Bit flag and program.
Bit 80 if IO is checked.
Program values are from 00 to 7f (1 to 128). They are detailed in the interactive spreadsheet near the top of this page.