dronecan / libcanard

MIT License
45 stars 52 forks source link

Raw Command Throttle Value Decoding not Standard Compliant #68

Open ampere-tobi opened 4 months ago

ampere-tobi commented 4 months ago

Hello, im trying to decode raw throttle commands without using libcanard. The specification shows a clear way how multiple values, in this case 14bit are meant to be packed into the message. https://dronecan.github.io/Specification/figures/bit_encoding.png However after some review of the actual traffic, there seems to be significant deviation. Only the first throttle value in a 4 channel single frame configuration is placed in compliance, to some extenend. The others are also packed, although needs shifting to fit together, in 14bit packages but have to be descattered by shifting bit pairs in an arbitrary pattern within said 14bit packets to retrieve the correct value. Can anyone shine some light into the issue and whats the magic behind this weird encoding pattern. Kind Regards Tobi

bnickodemus commented 1 month ago

Nobody explained it to me but it's not difficult to figure out.

e.g. TX 15:27:29.608994 NFD 1404067F 13 5B 05 5F F3 C7 5D D3 .[._..]. 127 uavcan.equipment.esc.RawCommand cmd: [5651, 5569, 4095, 7453] interpret 0x135B055FF3C75D in binary, drop tail byte: [00010011 010110] [11000001 010101] [11111111 001111] [00011101 011101] 5651 = 010110 00010011 5569 = 010101 11000001 4095 = 001111 11111111 7453 = 011101 00011101 The pattern should now be obvious.

//decode uint32_t bit_ofs = 0; uint8_t payload_head = frame.data; pool_counter = frame.data_len-1; // drop tail byte uint8_t payload = pool_counter 8 / 14; // bit_length is 14 for (int i = 0; i < payload; i++) // payload is 4 for a single frame transfer { memset(&storage, 0, sizeof(storage)); copyBitArray(&payload_head[0], bit_ofs, bit_length, (uint8_t*) &storage.bytes[0], 0); storage.bytes[14 / 8U] = (uint8_t)(storage.bytes[14 / 8U] >> ((8U - (14 % 8U)) & 7U)); if (i == PcSettings.DroneCanMotorId) { pwm_dronecan = storage.s16; break; } bit_ofs += 14; }

For multi frame transfers, you need to wait until all bytes are received before you can decode.

Read the transport layer: https://dronecan.github.io/Specification/4.1_CAN_bus_transport_layer/