|
| 1 | +/** |
| 2 | + * PRDC_TMAESC.cpp - T-Motor ALPHA ESC Telemetry Protocol Arduino library |
| 3 | + * Author: Veljko Petrovic <[email protected]> |
| 4 | + * PR-DC, Republic of Serbia |
| 5 | + |
| 6 | + * |
| 7 | + * -------------------- |
| 8 | + * Copyright (C) 2021 PR-DC <[email protected]> |
| 9 | + * |
| 10 | + * This file is part of PRDC_TMAESC. |
| 11 | + * |
| 12 | + * PRDC_TMAESC is free software: you can redistribute it and/or modify |
| 13 | + * it under the terms of the GNU Lesser General Public License as |
| 14 | + * published by the Free Software Foundation, either version 3 of the |
| 15 | + * License, or (at your option) any later version. |
| 16 | + * |
| 17 | + * PRDC_TMAESC is distributed in the hope that it will be useful, |
| 18 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 19 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 20 | + * GNU Lesser General Public License for more details. |
| 21 | + * |
| 22 | + * You should have received a copy of the GNU Lesser General Public License |
| 23 | + * along with PRDC_TMAESC. If not, see <https://www.gnu.org/licenses/>. |
| 24 | + * |
| 25 | + */ |
| 26 | + |
| 27 | +#include "PRDC_TMAESC.h" |
| 28 | + |
| 29 | +// init() |
| 30 | +// initalizes communication |
| 31 | +// -------------------- |
| 32 | +void PRDC_TMAESC::init(Stream& stream) { |
| 33 | + _serial = &stream; |
| 34 | +} |
| 35 | + |
| 36 | +void PRDC_TMAESC::init(HardwareSerial& serial){ |
| 37 | + serial.begin(PRDC_TMAESC_BAUD); |
| 38 | + init((Stream&)serial); |
| 39 | +} |
| 40 | + |
| 41 | +// update() |
| 42 | +// reads and parses a packet if available |
| 43 | +// -------------------- |
| 44 | +bool PRDC_TMAESC::update() { |
| 45 | + uint32_t n = _serial->available(); |
| 46 | + if(n == 0) { |
| 47 | + return false; |
| 48 | + } |
| 49 | + while(n--) { |
| 50 | + uint8_t b = _serial->read(); |
| 51 | + if(len == 0 && b != PRDC_TMAESC_B1) { |
| 52 | + continue; |
| 53 | + } |
| 54 | + if(len == 1 && b != PRDC_TMAESC_B2) { |
| 55 | + continue; |
| 56 | + } |
| 57 | + data_buffer[len++] = b; |
| 58 | + if(len == PRDC_TMAESC_PACKET_SIZE) { |
| 59 | + len = 0; |
| 60 | + if(parse_packet()){ |
| 61 | + return true; |
| 62 | + } |
| 63 | + } |
| 64 | + } |
| 65 | + return false; |
| 66 | +} |
| 67 | + |
| 68 | +// parse_packet() |
| 69 | +// parses a raw data packet |
| 70 | +// -------------------- |
| 71 | +bool PRDC_TMAESC::parse_packet(void) { |
| 72 | + // check packet integrity |
| 73 | + uint16_t checksum_received = (data_buffer[23] << 8) | data_buffer[22]; |
| 74 | + uint16_t checksum_calculated = calc_checksum(data_buffer, PRDC_TMAESC_PACKET_SIZE-2); |
| 75 | + if(checksum_received == checksum_calculated) { |
| 76 | + data.time = millis(); |
| 77 | + // pack raw data |
| 78 | + data_raw.counter = (data_buffer[4] << 8) | data_buffer[5]; |
| 79 | + data_raw.throttle_rx = (data_buffer[6] << 8) | data_buffer[7]; |
| 80 | + data_raw.throttle_out = (data_buffer[8] << 8) | data_buffer[9]; |
| 81 | + data_raw.rpm = (data_buffer[10] << 8) | data_buffer[11]; |
| 82 | + data_raw.voltage_bus = (data_buffer[12] << 8) | data_buffer[13]; |
| 83 | + data_raw.current_bus = (data_buffer[14] << 8) | data_buffer[15]; |
| 84 | + data_raw.current_phase = (data_buffer[16] << 8) | data_buffer[17]; |
| 85 | + data_raw.temperature_mos = data_buffer[18]; |
| 86 | + data_raw.temperature_cap = data_buffer[19]; |
| 87 | + data_raw.status = (data_buffer[20] << 8) | data_buffer[21]; |
| 88 | + // process raw data |
| 89 | + data.counter = data_raw.counter; |
| 90 | + data.throttle_rx = (float)data_raw.throttle_rx*100.0/1024.0; |
| 91 | + data.throttle_out = (float)data_raw.throttle_out*100.0/1024.0; |
| 92 | + data.rpm = data_raw.rpm*10.0/(3.0*poles); |
| 93 | + data.voltage_bus = (float)data_raw.voltage_bus/10.0; |
| 94 | + data.current_bus = (float)data_raw.current_bus/64.0; |
| 95 | + data.current_phase = (float)data_raw.current_phase/64.0; |
| 96 | + data.temperature_mos = temperature_decode(data_raw.temperature_mos); |
| 97 | + data.temperature_cap = temperature_decode(data_raw.temperature_cap); |
| 98 | + data.status = data_raw.status; |
| 99 | + data.fault = (data.status != 0x00); |
| 100 | + return true; |
| 101 | + } |
| 102 | + else { |
| 103 | + return false; |
| 104 | + } |
| 105 | +} |
| 106 | + |
| 107 | +// set_poles() |
| 108 | +// sets BLDC motor pole number |
| 109 | +// -------------------- |
| 110 | +void PRDC_TMAESC::set_poles(uint8_t p) { |
| 111 | + poles = p; |
| 112 | +} |
| 113 | + |
| 114 | +// calc_checksum() |
| 115 | +// calculates checksum by summing message bytes |
| 116 | +// -------------------- |
| 117 | +uint16_t PRDC_TMAESC::calc_checksum(uint8_t* data, uint16_t n) { |
| 118 | + uint16_t checksum = 0; |
| 119 | + while(n--) { |
| 120 | + checksum += data[n]; |
| 121 | + } |
| 122 | + return checksum; |
| 123 | +} |
| 124 | + |
| 125 | +// temperature decoding table |
| 126 | +static const struct { |
| 127 | + uint8_t temp_reading; |
| 128 | + uint8_t temp_value; |
| 129 | +} temp_table[] = { |
| 130 | + {241, 0}, {240, 1}, {239, 2}, {238, 3}, {237, 4}, {236, 5}, {235, 6}, {234, 7}, {233, 8}, {232, 9}, |
| 131 | + {231, 10}, {230, 11}, {229, 12}, {228, 13}, {227, 14}, {226, 15}, {224, 16}, {223, 17}, {222, 18}, {220, 19}, |
| 132 | + {219, 20}, {217, 21}, {216, 22}, {214, 23}, {213, 24}, {211, 25}, {209, 26}, {208, 27}, {206, 28}, {204, 29}, |
| 133 | + {202, 30}, {201, 31}, {199, 32}, {197, 33}, {195, 34}, {193, 35}, {191, 36}, {189, 37}, {187, 38}, {185, 39}, |
| 134 | + {183, 40}, {181, 41}, {179, 42}, {177, 43}, {174, 44}, {172, 45}, {170, 46}, {168, 47}, {166, 48}, {164, 49}, |
| 135 | + {161, 50}, {159, 51}, {157, 52}, {154, 53}, {152, 54}, {150, 55}, {148, 56}, {146, 57}, {143, 58}, {141, 59}, |
| 136 | + {139, 60}, {136, 61}, {134, 62}, {132, 63}, {130, 64}, {128, 65}, {125, 66}, {123, 67}, {121, 68}, {119, 69}, |
| 137 | + {117, 70}, {115, 71}, {113, 72}, {111, 73}, {109, 74}, {106, 75}, {105, 76}, {103, 77}, {101, 78}, {99, 79}, |
| 138 | + {97, 80}, {95, 81}, {93, 82}, {91, 83}, {90, 84}, {88, 85}, {85, 86}, {84, 87}, {82, 88}, {81, 89}, |
| 139 | + {79, 90}, {77, 91}, {76, 92}, {74, 93}, {73, 94}, {72, 95}, {69, 96}, {68, 97}, {66, 98}, {65, 99}, |
| 140 | + {64, 100}, {62, 101}, {62, 102}, {61, 103}, {59, 104}, {58, 105}, {56, 106}, {54, 107}, {54, 108}, {53, 109}, |
| 141 | + {51, 110}, {51, 111}, {50, 112}, {48, 113}, {48, 114}, {46, 115}, {46, 116}, {44, 117}, {43, 118}, {43, 119}, |
| 142 | + {41, 120}, {41, 121}, {39, 122}, {39, 123}, {39, 124}, {37, 125}, {37, 126}, {35, 127}, {35, 128}, {33, 129}, |
| 143 | +}; |
| 144 | + |
| 145 | +// temperature_decode() |
| 146 | +// decodes raw temperature reading |
| 147 | +// -------------------- |
| 148 | +uint8_t PRDC_TMAESC::temperature_decode(uint8_t temp_raw) { |
| 149 | + for (uint8_t i=0; i<130; i++) { |
| 150 | + if (temp_table[i].temp_reading <= temp_raw) { |
| 151 | + return temp_table[i].temp_value; |
| 152 | + } |
| 153 | + } |
| 154 | + return 130U; |
| 155 | +} |
0 commit comments