- Posts: 3333
DSM Telemetry support
- vlad_vy
- Offline
PhracturedBlue wrote: I reworked the state-machine again. Now it does read both frames of telemetry and it does work with >= 8 channels. However, for unknown reasons only every other telemetry packet is received correctly. I have no idea why that is, but I never get the expected 'end of packet' bit on every other read.
of course, it needs testing to see what else I broke.
Maybe telemetry module change something at every transmission? CRC coding or anything else? What telemetry packet is correct? First or second? Does it has place at both 6/7 and 8/9 channel modes?
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
www.helifreak.com/showthread.php?t=320846
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
That is useful to know, but I need to know how many pulses Spektrum expects per revolution. Since I don't have a Spektrum radio, there doesn't appear to beany way for me to figure this out.vlad_vy wrote: PB, you can check RPM sensor telemetry without real RPM sensor:
www.helifreak.com/showthread.php?t=320846
It is probably easier for someone with the proper sensor (and a known RPM to just tell me what is reported.
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
1) AR8000 + TM1000 telemetry module. TM1000 doesn't bind at 6 and 7 channel mode, but bind at 8 and 9 channel mode (bind LED solid).
2) AR6210 + TM1000 telemetry module. TM1000 doesn't bind at 6 and 7 channel mode, and it seems doesn't bind at 8 and 9 channel mode, but TM1000 bind LED fast blink and telemetry really work.
It seems that with DSMX protocol the telemetry works only at 8/9 channel mode. With DSM2 protocol the telemetry works at any channels mode. What is the difference?
Also,
1) Will be better assign internal Rx voltage to Telemetry.volt[1] as for Walkera telemetry.
2) Telemetry temperature data (packet[6] and packet[7]) need to check for 0xFFFF if temperature sensor is disconnected.
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
PhracturedBlue wrote: I reworked the state-machine again. Now it does read both frames of telemetry and it does work with >= 8 channels. However, for unknown reasons only every other telemetry packet is received correctly. I have no idea why that is, but I never get the expected 'end of packet' bit on every other read.
of course, it needs testing to see what else I broke.
PB, if I right understand RW9UAO, with DSMX protocol (unlike dsm2) the telemetry packet transmit only once at second half of 22ms. Can you check it?
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
Please Log in or Create an account to join the conversation.
- RW9UAO
- Offline
- Posts: 25
some rework code for DSM telemetry. i think it more usable. DEVO telemetry screen as is.
check for //RW9UAO comments. don`t know how to make diff patch.
https://docs.google.com/file/d/0B1Bo-wTTor5LZDZWM3UzZHZCSUE/edit?usp=sharing
p.s. found small bug: PhracturedBlue-deviation-b1b5bcecde6b\src\target\common_devo\protocol\cyrf6936.c
u8 CYRF_ReadRSSI(u32 dodummyread){
return (result & 0x0F);
return (result & 0x1F);//rssi has 5 bits, not 4
Please Log in or Create an account to join the conversation.
- rbe2012
- Offline
- So much to do, so little time...
- Posts: 1433
with "patch -p1 < filename.patch".
For the bug you have found you should file an issue on bitbucket.
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
Data structure:
0[00] 22(0x16)
1[01] 00
2[02] Altitude LSB
3[03] Altitude MSB
4[04] 1/100th of a degree second latitude (Decimal)
5[05] degree seconds latitude (Decimal)
6[06] degree minutes latitude (Decimal)
7[07] degrees latitude (Decimal)
8[08] 1/100th of a degree second longitude (Decimal)
9[09] degree seconds longitude (Decimal)
10[0A] degree minutes longitude (Decimal)
11[0B] degrees longitude (Decimal)
12[0C] Heading LSB (Decimal)
13[0D] Heading MSB (Decimal) Divide by 10 for Degrees
14[0E] Unknown
15[0F] Unknown
0[00] 23(0x17)
1[01] 00
2[02] Speed LSB (Decimal)
3[03] Speed MSB (Decimal) Divide by 10 for Knots. Multiply by 0.185 for Kph and 0.115 for Mph
4[04] UTC Time LSB 1/10th sec.
5[05] UTC Time
6[06] UTC Time
7[07] UTC Time MSB
8[08] Number of Sats (Decimal)
9[09] 00
10[0A]-15[0F] Unused (But contains Data left in buffer)
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
if(Model.protocol == PROTOCOL_DSMX)
packet[12] = num_channels < 8 ? 0xb2 : 0xb2;
else
packet[12] = num_channels < 8 ? 0x01 : 0x02;
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
static void parse_telemetry_packet()
{
if(packet[0] == 0x7f || packet[0] == 0xff) { //TM1000 or TM1100 Flight log
//Telemetry.FadesA = ((s32)packet[2] << 8) | packet[3];
//Telemetry.FadesB = ((s32)packet[4] << 8) | packet[5];
//Telemetry.FadesL = ((s32)packet[6] << 8) | packet[7];
//Telemetry.FadesR = ((s32)packet[8] << 8) | packet[9];
//Telemetry.FrameLoss = ((s32)packet[10] << 8) | packet[11];
//Telemetry.Holds = ((s32)packet[12] << 8) | packet[13];
Telemetry.volt[1] = ((((s32)packet[14] << 8) | packet[15]) + 5) / 10; //In 1/10 of Volts
Telemetry.time[0] = CLOCK_getms();
Telemetry.time[1] = Telemetry.time[0];
} else if (packet[0] == 0x7e || packet[0] == 0xfe) { //TM1000 or TM1100
Telemetry.rpm[0] = ((packet[2] << 8) | packet[3]); //In RPM
if (Telemetry.rpm[0] == 0xffff)
Telemetry.rpm[0] = 0;
Telemetry.volt[0] = ((((s32)packet[4] << 8) | packet[5]) + 5) / 10; //In 1/10 of Volts
Telemetry.temp[0] = packet[7] == 0xff ? 0 : (packet[7] - 32) * 5 / 9; //In degrees-C (16Bit signed integer !!!)
//Telemetry.temp[0] = ((((s16)packet[6] << 8) | packet[7]) - 32) * 5 / 9; //(16Bit signed integer)
//if (Telemetry.temp[0] > 500 || Telemetry.temp[0] < -100)
// Telemetry.temp[0] = 0;
Telemetry.time[0] = CLOCK_getms();
Telemetry.time[1] = Telemetry.time[0];
} else if (packet[0] == 0x03) { //High Current sensor
//Telemetry.current = (((s32)packet[2] << 8) | packet[3]) * 1967 / 1000; //In 1/10 of Amps (16bit value, 1 unit is 0.1967A)
//Telemetry.time[x1] = CLOCK_getms();
} else if (packet[0] == 0x0a) { //Powerbox sensor
//Telemetry.pwb.volt1 = (((s32)packet[2] << 8) | packet[3] + 5) /10; //In 1/10 of Volts
//Telemetry.pwb.volt1 = (((s32)packet[4] << 8) | packet[5] + 5) /10; //In 1/10 of Volts
//Telemetry.pwb.capacity1 = (((s32)packet[6] << 8) | packet[7] + 5); //In mAh
//Telemetry.pwb.capacity2 = (((s32)packet[8] << 8) | packet[9] + 5); //In mAh
//Telemetry.pwb.alarm_v1 = packet[15] & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_v2 = (packet[15] >> 1) & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_c1 = (packet[15] >> 2) & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_c2 = (packet[15] >> 3) & 0x01; //0 = disable, 1 = enable
//Telemetry.time[x2] = CLOCK_getms();
} else if (packet[0] == 0x11) { //AirSpeed sensor
//Telemetry.airspeed = ((s32)packet[2] << 8) | packet[3]; //In km/h (16Bit value, 1 unit is 1 km/h)
//Telemetry.time[x3] = CLOCK_getms();
} else if (packet[0] == 0x12) { //Altimeter sensor
//Telemetry.altitude = (((s16)packet[2] << 8) | packet[3]) /10; //In meters (16Bit signed integer, 1 unit is 0.1m)
//Telemetry.time[x4] = CLOCK_getms();
} else if (packet[0] == 0x14) { //G-Force sensor
//Telemetry.gforce.x = ((s16)packet[2] << 8) | packet[3]; //In 0.01g (16Bit signed integers, unit is 0.01g)
//Telemetry.gforce.y = ((s16)packet[4] << 8) | packet[5];
//Telemetry.gforce.z = ((s16)packet[6] << 8) | packet[7];
//Telemetry.gforce.xmax = ((s16)packet[8] << 8) | packet[9];
//Telemetry.gforce.ymax = ((s16)packet[10] << 8) | packet[11];
//Telemetry.gforce.zmax = ((s16)packet[12] << 8) | packet[13];
//Telemetry.gforce.zmin = ((s16)packet[14] << 8) | packet[15];
//Telemetry.time[x5] = CLOCK_getms();
} else if (packet[0] == 0x15) { //JetCat sensor
} else if (packet[0] == 0x16) { //GPS sensor
Telemetry.gps.altitude = (((packet[3] >> 4) * 10 + (packet[3] & 0x0f)) * 100 //(16Bit decimal, 1 unit is 0.1m)
+ ((packet[2] >> 4) * 10 + (packet[2] & 0x0f))) * 100; //In meters * 1000
Telemetry.gps.latitude = ((packet[7] >> 4) * 10 + (packet[7] & 0x0f)) * 3600000
+ ((packet[6] >> 4) * 10 + (packet[6] & 0x0f)) * 60000
+ ((packet[5] >> 4) * 10 + (packet[5] & 0x0f)) * 600
+ ((packet[4] >> 4) * 10 + (packet[4] & 0x0f)) * 6;
Telemetry.gps.longitude = ((packet[11] >> 4) * 10 + (packet[11] & 0x0f)) * 3600000
+ ((packet[10] >> 4) * 10 + (packet[10] & 0x0f)) * 60000
+ ((packet[9] >> 4) * 10 + (packet[9] & 0x0f)) * 600
+ ((packet[8] >> 4) * 10 + (packet[8] & 0x0f)) * 6;
// Telemetry.gps.heading = ((packet[13] >> 4) * 10 + (packet[13] & 0x0f)) * 10 //(16Bit decimal, 1 unit is 0.1 degree)
// + ((packet[12] >> 4) * 10 + (packet[12] & 0x0f)) / 10; //In degrees
Telemetry.time[2] = CLOCK_getms();
} else if (packet[0] == 0x17) { //GPS sensor
Telemetry.gps.velocity = (((packet[3] >> 4) * 10 + (packet[3] & 0x0f)) * 100
+ ((packet[2] >> 4) * 10 + (packet[2] & 0x0f))) * 5556 / 108; //In m/s * 1000
//u32 utc_time = ((packet[7] >> 4) * 10 + (packet[7] & 0x0f)) * 1000000
//+ ((packet[6] >> 4) * 10 + (packet[6] & 0x0f)) * 10000
//+ ((packet[5] >> 4) * 10 + (packet[5] & 0x0f)) * 100
//+ ((packet[4] >> 4) * 10 + (packet[4] & 0x0f));
Telemetry.gps.time = 0; //Not calculated yet
// Telemetry.gps.sats = ((packet[8] >> 4) * 10 + (packet[8] & 0x0f));
Telemetry.time[2] = CLOCK_getms();
}
}
GPS sensor tested and works fine, with except:
1) I cann't calculate date/time from UTC time
2) I cann't test Heading and number of sats without screen output
3) I don't know how telemetry transmit lattitude N and S, and four longitude sectors (0-90) for +0~+180 and -0~-180. Now it works only for lattitude +0~+90 degree and longitude +0~+90 degree. Possible this info contained at 14 and 15 bytes of GPS(0x16) packet.
What I can test:
1) GPS Sensor
2) High Current Sensor
3) AirSpeed Sensor
4) G-Force Sensor
5) Brushless RPM Sensor
6) Magnetic RPM Sensor (Eagle Tree, waiting connectors)
7) Altimeter Sensor (will get it soon)
Please Log in or Create an account to join the conversation.
- RW9UAO
- Offline
- Posts: 25
one more adding:
_telemtest_page.c
void PAGE_TelemtestEvent() {
time_count ++;
//if (time_count < 10) // 100ms x10 = 2seconds, to slow down the refresh rate to once per 2s
// return;
time_count = 0;
int i;
u32 time = CLOCK_getms();
//RW9UAO
if (Telemetry.RSSI != tp.telem.RSSI) {
if (OBJ_IS_USED(&gui1->RSSI))
GUI_Redraw(&gui1->RSSI);
tp.telem.RSSI = Telemetry.RSSI;
}
if (Telemetry.A != tp.telem.A) {
if (OBJ_IS_USED(&gui1->A))
GUI_Redraw(&gui1->A);
tp.telem.A = Telemetry.A;
}
if (Telemetry.B != tp.telem.B) {
if (OBJ_IS_USED(&gui1->B))
GUI_Redraw(&gui1->B);
tp.telem.B = Telemetry.B;
}
if (Telemetry.L != tp.telem.L) {
if (OBJ_IS_USED(&gui1->L))
GUI_Redraw(&gui1->L);
tp.telem.L = Telemetry.L;
}
if (Telemetry.R != tp.telem.R) {
if (OBJ_IS_USED(&gui1->R))
GUI_Redraw(&gui1->R);
tp.telem.R = Telemetry.R;
}
if (Telemetry.F != tp.telem.F) {
if (OBJ_IS_USED(&gui1->F))
GUI_Redraw(&gui1->F);
tp.telem.F = Telemetry.F;
}
if (Telemetry.H != tp.telem.H) {
if (OBJ_IS_USED(&gui1->H))
GUI_Redraw(&gui1->H);
tp.telem.H = Telemetry.H;
}
if (Telemetry.current != tp.telem.current) {
if (OBJ_IS_USED(&gui1->current))
GUI_Redraw(&gui1->current);
tp.telem.current = Telemetry.current;
}
//RW9UAO
for(i = 0; i < 3; i++) {
if (Telemetry.volt[i] != tp.telem.volt[i]) {
if (OBJ_IS_USED(&gui1->volt[i])) // in devo10, the item objects are drawn in different pages, so some of them might not exist in a page
GUI_Redraw(&gui1->volt[i]);
tp.telem.volt[i] = Telemetry.volt[i];
}
}
dsm2.c
//Read telemetry if needed
if(CYRF_ReadRegister(0x07) & 0x02) {
//RW9UAO
Telemetry.RSSI = CYRF_ReadRegister(0x13) & 0x1F;
CYRF_ReadDataPacket(packet);
if(CYRF_ReadRegister(0x09) == 0x10){//rx count
parse_telemetry_packet();
}
}
Please Log in or Create an account to join the conversation.
- RW9UAO
- Offline
- Posts: 25
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
vlad_vy wrote: Draft version of telemetry parser
3) I don't know how telemetry transmit lattitude N and S, and four longitude sectors (0-90) for +0~+180 and -0~-180. Now it works only for lattitude +0~+90 degree and longitude +0~+90 degree. Possible this info contained at 14 and 15 bytes of GPS(0x16) packet.
Byte 15 of GPS(0x16) packet:
First bit is lattitude sign 1=N(+), 0=S(-),
second bit is longitude sign 1=E(+), 0=W(-),
third bit is longitude over 100 degree, 1=(+-100 degree)
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
vlad_vy wrote: Draft version of telemetry parser
1) I cann't calculate date/time from UTC time
Spektrum UTC time is simple time in decimal format HH:MM:SS.SS
New draft version of telemetry parser, with full GPS code
static void parse_telemetry_packet()
{
if(packet[0] == 0x7f || packet[0] == 0xff) { //TM1000 or TM1100 Flight log
//Telemetry.FadesA = ((s32)packet[2] << 8) | packet[3];
//Telemetry.FadesB = ((s32)packet[4] << 8) | packet[5];
//Telemetry.FadesL = ((s32)packet[6] << 8) | packet[7];
//Telemetry.FadesR = ((s32)packet[8] << 8) | packet[9];
//Telemetry.FrameLoss = ((s32)packet[10] << 8) | packet[11];
//Telemetry.Holds = ((s32)packet[12] << 8) | packet[13];
Telemetry.volt[1] = ((((s32)packet[14] << 8) | packet[15]) + 5) / 10; //In 1/10 of Volts
Telemetry.time[0] = CLOCK_getms();
Telemetry.time[1] = Telemetry.time[0];
} else if (packet[0] == 0x7e || packet[0] == 0xfe) { //TM1000 or TM1100
Telemetry.rpm[0] = ((packet[2] << 8) | packet[3]); //In RPM
if (Telemetry.rpm[0] == 0xffff)
Telemetry.rpm[0] = 0;
Telemetry.volt[0] = ((((s32)packet[4] << 8) | packet[5]) + 5) / 10; //In 1/10 of Volts
Telemetry.temp[0] = packet[7] == 0xff ? 0 : (packet[7] - 32) * 5 / 9; //In degrees-C (16Bit signed integer !!!)
//Telemetry.temp[0] = ((((s16)packet[6] << 8) | packet[7]) - 32) * 5 / 9; //(16Bit signed integer)
//if (Telemetry.temp[0] > 500 || Telemetry.temp[0] < -100)
// Telemetry.temp[0] = 0;
Telemetry.time[0] = CLOCK_getms();
Telemetry.time[1] = Telemetry.time[0];
} else if (packet[0] == 0x03) { //High Current sensor
//Telemetry.current = (((s32)packet[2] << 8) | packet[3]) * 1967 / 1000; //In 1/10 of Amps (16bit value, 1 unit is 0.1967A)
//Telemetry.time[x1] = CLOCK_getms();
} else if (packet[0] == 0x0a) { //Powerbox sensor
//Telemetry.pwb.volt1 = (((s32)packet[2] << 8) | packet[3] + 5) /10; //In 1/10 of Volts
//Telemetry.pwb.volt1 = (((s32)packet[4] << 8) | packet[5] + 5) /10; //In 1/10 of Volts
//Telemetry.pwb.capacity1 = (((s32)packet[6] << 8) | packet[7] + 5); //In mAh
//Telemetry.pwb.capacity2 = (((s32)packet[8] << 8) | packet[9] + 5); //In mAh
//Telemetry.pwb.alarm_v1 = packet[15] & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_v2 = (packet[15] >> 1) & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_c1 = (packet[15] >> 2) & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_c2 = (packet[15] >> 3) & 0x01; //0 = disable, 1 = enable
//Telemetry.time[x2] = CLOCK_getms();
} else if (packet[0] == 0x11) { //AirSpeed sensor
//Telemetry.airspeed = ((s32)packet[2] << 8) | packet[3]; //In km/h (16Bit value, 1 unit is 1 km/h)
//Telemetry.time[x3] = CLOCK_getms();
} else if (packet[0] == 0x12) { //Altimeter sensor
//Telemetry.altitude = (((s16)packet[2] << 8) | packet[3]) /10; //In meters (16Bit signed integer, 1 unit is 0.1m)
//Telemetry.time[x4] = CLOCK_getms();
} else if (packet[0] == 0x14) { //G-Force sensor
//Telemetry.gforce.x = ((s16)packet[2] << 8) | packet[3]; //In 0.01g (16Bit signed integers, unit is 0.01g)
//Telemetry.gforce.y = ((s16)packet[4] << 8) | packet[5];
//Telemetry.gforce.z = ((s16)packet[6] << 8) | packet[7];
//Telemetry.gforce.xmax = ((s16)packet[8] << 8) | packet[9];
//Telemetry.gforce.ymax = ((s16)packet[10] << 8) | packet[11];
//Telemetry.gforce.zmax = ((s16)packet[12] << 8) | packet[13];
//Telemetry.gforce.zmin = ((s16)packet[14] << 8) | packet[15];
//Telemetry.time[x5] = CLOCK_getms();
} else if (packet[0] == 0x15) { //JetCat sensor
} else if (packet[0] == 0x16) { //GPS sensor
Telemetry.gps.altitude = (((packet[3] >> 4) * 10 + (packet[3] & 0x0f)) * 100 //(16Bit decimal, 1 unit is 0.1m)
+ ((packet[2] >> 4) * 10 + (packet[2] & 0x0f))) * 100; //In meters * 1000
Telemetry.gps.latitude = ((packet[7] >> 4) * 10 + (packet[7] & 0x0f)) * 3600000
+ ((packet[6] >> 4) * 10 + (packet[6] & 0x0f)) * 60000
+ ((packet[5] >> 4) * 10 + (packet[5] & 0x0f)) * 600
+ ((packet[4] >> 4) * 10 + (packet[4] & 0x0f)) * 6;
if ((packet[15] & 0x01) == 0)
Telemetry.gps.latitude *= -1;
Telemetry.gps.longitude = ((packet[11] >> 4) * 10 + (packet[11] & 0x0f)) * 3600000
+ ((packet[10] >> 4) * 10 + (packet[10] & 0x0f)) * 60000
+ ((packet[9] >> 4) * 10 + (packet[9] & 0x0f)) * 600
+ ((packet[8] >> 4) * 10 + (packet[8] & 0x0f)) * 6;
if ((packet[15] & 0x04) == 4)
Telemetry.gps.longitude += 360000000;
if ((packet[15] & 0x02) == 0)
Telemetry.gps.longitude *= -1;
// Telemetry.gps.heading = ((packet[13] >> 4) * 10 + (packet[13] & 0x0f)) * 10 //(16Bit decimal, 1 unit is 0.1 degree)
// + ((packet[12] >> 4) * 10 + (packet[12] & 0x0f)) / 10; //In degrees
Telemetry.time[2] = CLOCK_getms();
} else if (packet[0] == 0x17) { //GPS sensor
Telemetry.gps.velocity = (((packet[3] >> 4) * 10 + (packet[3] & 0x0f)) * 100
+ ((packet[2] >> 4) * 10 + (packet[2] & 0x0f))) * 5556 / 108; //In m/s * 1000
u8 hour = (packet[7] >> 4) * 10 + (packet[7] & 0x0f);
u8 min = (packet[6] >> 4) * 10 + (packet[6] & 0x0f);
u8 sec = (packet[5] >> 4) * 10 + (packet[5] & 0x0f);
//u8 ssec = (packet[4] >> 4) * 10 + (packet[4] & 0x0f);
u8 day = 0;
u8 month = 0;
u8 year = 0; // + 2000
Telemetry.gps.time = ((year & 0x3F) << 26)
| ((month & 0x0F) << 22)
| ((day & 0x1F) << 17)
| ((hour & 0x1F) << 12)
| ((min & 0x3F) << 6)
| ((sec & 0x3F) << 0);
// Telemetry.gps.sats = ((packet[8] >> 4) * 10 + (packet[8] & 0x0f));
Telemetry.time[2] = CLOCK_getms();
}
}
Data type = 0x16 GPS Sensor
0[00] 22(0x16)
1[01] 00
2[02] Altitude LSB (Decimal) //In 0.1m
3[03] Altitude MSB (Decimal)
4[04] 1/100th of a degree second latitude (Decimal) (DD MM.SSSS)
5[05] degree seconds latitude (Decimal)
6[06] degree minutes latitude (Decimal)
7[07] degrees latitude (Decimal)
8[08] 1/100th of a degree second longitude (Decimal) (DD MM.SSSS)
9[09] degree seconds longitude (Decimal)
10[0A] degree minutes longitude (Decimal)
11[0B] degrees longitude (Decimal)
12[0C] Heading LSB (Decimal) Divide by 10 for Degrees
13[0D] Heading MSB (Decimal)
14[0E] Unknown
15[0F] First bit for latitude: 1=N(+), 0=S(-);
Second bit for longitude: 1=E(+), 0=W(-);
Third bit for longitude over 100 degree: 1=+-100 degrees
Data type = 0x17 GPS Sensor
0[00] 23(0x17)
1[01] 00
2[02] Speed LSB (Decimal) Divide by 10 for Knots. Multiply by 0.185 for Kph and 0.115 for Mph
3[03] Speed MSB (Decimal)
4[04] UTC Time LSB (Decimal) 1/100th sec. (HH:MM:SS.SS)
5[05] UTC Time (Decimal) = SS
6[06] UTC Time (Decimal) = MM
7[07] UTC Time MSB (Decimal) = HH
8[08] Number of Sats (Decimal)
9[09] 00
10[0A]-15[0F] Unused (But contains Data left in buffer)
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
RW9UAO wrote: too much "if", use switch/case =)
static void parse_telemetry_packet()
{
switch(packet[0]) {
case 0x7f: //TM1000 Flight log
case 0xff: //TM1100 Flight log
//Telemetry.fadesA = ((s32)packet[2] << 8) | packet[3];
//Telemetry.fadesB = ((s32)packet[4] << 8) | packet[5];
//Telemetry.fadesL = ((s32)packet[6] << 8) | packet[7];
//Telemetry.fadesR = ((s32)packet[8] << 8) | packet[9];
//Telemetry.frameloss = ((s32)packet[10] << 8) | packet[11];
//Telemetry.holds = ((s32)packet[12] << 8) | packet[13];
Telemetry.volt[1] = ((((s32)packet[14] << 8) | packet[15]) + 5) / 10; //In 1/10 of Volts
Telemetry.time[0] = CLOCK_getms();
Telemetry.time[1] = Telemetry.time[0];
break;
case 0x7e: //TM1000
case 0xfe: //TM1100
Telemetry.rpm[0] = ((packet[2] << 8) | packet[3]); //In RPM
if (Telemetry.rpm[0] == 0xffff)
Telemetry.rpm[0] = 0;
Telemetry.volt[0] = ((((s32)packet[4] << 8) | packet[5]) + 5) / 10; //In 1/10 of Volts
Telemetry.temp[0] = packet[7] == 0xff ? 0 : (packet[7] - 32) * 5 / 9; //In degrees-C (16Bit signed integer !!!)
//Telemetry.temp[0] = ((((s16)packet[6] << 8) | packet[7]) - 32) * 5 / 9; //(16Bit signed integer)
//if (Telemetry.temp[0] > 500 || Telemetry.temp[0] < -100)
// Telemetry.temp[0] = 0;
Telemetry.time[0] = CLOCK_getms();
Telemetry.time[1] = Telemetry.time[0];
break;
case 0x03: //High Current sensor
//Telemetry.current = (((s32)packet[2] << 8) | packet[3]) * 1967 / 1000; //In 1/10 of Amps (16bit value, 1 unit is 0.1967A)
//Telemetry.time[x1] = CLOCK_getms();
break;
case 0x0a: //Powerbox sensor
//Telemetry.pwb.volt1 = (((s32)packet[2] << 8) | packet[3] + 5) /10; //In 1/10 of Volts
//Telemetry.pwb.volt1 = (((s32)packet[4] << 8) | packet[5] + 5) /10; //In 1/10 of Volts
//Telemetry.pwb.capacity1 = (((s32)packet[6] << 8) | packet[7] + 5); //In mAh
//Telemetry.pwb.capacity2 = (((s32)packet[8] << 8) | packet[9] + 5); //In mAh
//Telemetry.pwb.alarm_v1 = packet[15] & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_v2 = (packet[15] >> 1) & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_c1 = (packet[15] >> 2) & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_c2 = (packet[15] >> 3) & 0x01; //0 = disable, 1 = enable
//Telemetry.time[x2] = CLOCK_getms();
break;
case 0x11: //AirSpeed sensor
//Telemetry.airspeed = ((s32)packet[2] << 8) | packet[3]; //In km/h (16Bit value, 1 unit is 1 km/h)
//Telemetry.time[x3] = CLOCK_getms();
break;
case 0x12: //Altimeter sensor
//Telemetry.altitude = (((s16)packet[2] << 8) | packet[3]) /10; //In meters (16Bit signed integer, 1 unit is 0.1m)
//Telemetry.time[x4] = CLOCK_getms();
break;
case 0x14: //G-Force sensor
//Telemetry.gforce.x = ((s16)packet[2] << 8) | packet[3]; //In 0.01g (16Bit signed integers, unit is 0.01g)
//Telemetry.gforce.y = ((s16)packet[4] << 8) | packet[5];
//Telemetry.gforce.z = ((s16)packet[6] << 8) | packet[7];
//Telemetry.gforce.xmax = ((s16)packet[8] << 8) | packet[9];
//Telemetry.gforce.ymax = ((s16)packet[10] << 8) | packet[11];
//Telemetry.gforce.zmax = ((s16)packet[12] << 8) | packet[13];
//Telemetry.gforce.zmin = ((s16)packet[14] << 8) | packet[15];
//Telemetry.time[x5] = CLOCK_getms();
break;
case 0x15: //JetCat sensor
//No data yet
break;
case 0x16: //GPS sensor
Telemetry.gps.altitude = (((packet[3] >> 4) * 10 + (packet[3] & 0x0f)) * 100 //(16Bit decimal, 1 unit is 0.1m)
+ ((packet[2] >> 4) * 10 + (packet[2] & 0x0f))) * 100; //In meters * 1000
Telemetry.gps.latitude = ((packet[7] >> 4) * 10 + (packet[7] & 0x0f)) * 3600000
+ ((packet[6] >> 4) * 10 + (packet[6] & 0x0f)) * 60000
+ ((packet[5] >> 4) * 10 + (packet[5] & 0x0f)) * 600
+ ((packet[4] >> 4) * 10 + (packet[4] & 0x0f)) * 6;
if ((packet[15] & 0x01) == 0)
Telemetry.gps.latitude *= -1;
Telemetry.gps.longitude = ((packet[11] >> 4) * 10 + (packet[11] & 0x0f)) * 3600000
+ ((packet[10] >> 4) * 10 + (packet[10] & 0x0f)) * 60000
+ ((packet[9] >> 4) * 10 + (packet[9] & 0x0f)) * 600
+ ((packet[8] >> 4) * 10 + (packet[8] & 0x0f)) * 6;
if ((packet[15] & 0x04) == 4)
Telemetry.gps.longitude += 360000000;
if ((packet[15] & 0x02) == 0)
Telemetry.gps.longitude *= -1;
// Telemetry.gps.heading = ((packet[13] >> 4) * 10 + (packet[13] & 0x0f)) * 10 //(16Bit decimal, 1 unit is 0.1 degree)
// + ((packet[12] >> 4) * 10 + (packet[12] & 0x0f)) / 10; //In degrees
Telemetry.time[2] = CLOCK_getms();
break;
case 0x17: //GPS sensor
Telemetry.gps.velocity = (((packet[3] >> 4) * 10 + (packet[3] & 0x0f)) * 100
+ ((packet[2] >> 4) * 10 + (packet[2] & 0x0f))) * 5556 / 108; //In m/s * 1000
u8 hour = (packet[7] >> 4) * 10 + (packet[7] & 0x0f);
u8 min = (packet[6] >> 4) * 10 + (packet[6] & 0x0f);
u8 sec = (packet[5] >> 4) * 10 + (packet[5] & 0x0f);
//u8 ssec = (packet[4] >> 4) * 10 + (packet[4] & 0x0f);
u8 day = 0;
u8 month = 0;
u8 year = 0; // + 2000
Telemetry.gps.time = ((year & 0x3F) << 26)
| ((month & 0x0F) << 22)
| ((day & 0x1F) << 17)
| ((hour & 0x1F) << 12)
| ((min & 0x3F) << 6)
| ((sec & 0x3F) << 0);
// Telemetry.gps.sats = ((packet[8] >> 4) * 10 + (packet[8] & 0x0f));
Telemetry.time[2] = CLOCK_getms();
break;
}
}
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
Telemetry.rpm[0] = (packet[2] << 8) | packet[3];
if ((Telemetry.rpm[0] == 0xffff) || (Telemetry.rpm[0] < 200))
Telemetry.rpm[0] = 0;
else
Telemetry.rpm[0] = 120000000 / 2 / Telemetry.rpm[0]; //In RPM (2 = number of poles)
//Telemetry.rpm[0] = 120000000 / number_of_poles(2, 4, ... 32) / gear_ratio(0.01 - 30.99) / Telemetry.rpm[0]; //In RPM
//by default number_of_poles = 2, gear_ratio = 1.00
The most common equation will be:
Telemetry.rpm[0] = 120000000 / number_of_poles(2, 4, ... 32) / gear_ratio(0.01 - 30.99) / Telemetry.rpm[0]; //In RPM
By default number_of_poles equal to 2, gear_ratio = 1.00
New draft version of telemetry parser, with corrected RPM calculation
static void parse_telemetry_packet()
{
switch(packet[0]) {
case 0x7f: //TM1000 Flight log
case 0xff: //TM1100 Flight log
//Telemetry.fadesA = ((s32)packet[2] << 8) | packet[3];
//Telemetry.fadesB = ((s32)packet[4] << 8) | packet[5];
//Telemetry.fadesL = ((s32)packet[6] << 8) | packet[7];
//Telemetry.fadesR = ((s32)packet[8] << 8) | packet[9];
//Telemetry.frameloss = ((s32)packet[10] << 8) | packet[11];
//Telemetry.holds = ((s32)packet[12] << 8) | packet[13];
Telemetry.volt[1] = ((((s32)packet[14] << 8) | packet[15]) + 5) / 10; //In 1/10 of Volts
Telemetry.time[0] = CLOCK_getms();
Telemetry.time[1] = Telemetry.time[0];
break;
case 0x7e: //TM1000
case 0xfe: //TM1100
Telemetry.rpm[0] = (packet[2] << 8) | packet[3];
if ((Telemetry.rpm[0] == 0xffff) || (Telemetry.rpm[0] < 200))
Telemetry.rpm[0] = 0;
else
Telemetry.rpm[0] = 120000000 / 2 / Telemetry.rpm[0]; //In RPM (2 = number of poles)
//Telemetry.rpm[0] = 120000000 / number_of_poles(2, 4, ... 32) / gear_ratio(0.01 - 30.99) / Telemetry.rpm[0];
//by default number_of_poles = 2, gear_ratio = 1.00
Telemetry.volt[0] = ((((s32)packet[4] << 8) | packet[5]) + 5) / 10; //In 1/10 of Volts
Telemetry.temp[0] = packet[7] == 0xff ? 0 : (packet[7] - 32) * 5 / 9; //In degrees-C (16Bit signed integer !!!)
//Telemetry.temp[0] = ((((s16)packet[6] << 8) | packet[7]) - 32) * 5 / 9; //(16Bit signed integer)
//if (Telemetry.temp[0] > 500 || Telemetry.temp[0] < -100)
// Telemetry.temp[0] = 0;
Telemetry.time[0] = CLOCK_getms();
Telemetry.time[1] = Telemetry.time[0];
break;
case 0x03: //High Current sensor
//Telemetry.current = (((s32)packet[2] << 8) | packet[3]) * 1967 / 1000; //In 1/10 of Amps (16bit value, 1 unit is 0.1967A)
//Telemetry.time[x1] = CLOCK_getms();
break;
case 0x0a: //Powerbox sensor
//Telemetry.pwb.volt1 = (((s32)packet[2] << 8) | packet[3] + 5) /10; //In 1/10 of Volts
//Telemetry.pwb.volt1 = (((s32)packet[4] << 8) | packet[5] + 5) /10; //In 1/10 of Volts
//Telemetry.pwb.capacity1 = (((s32)packet[6] << 8) | packet[7] + 5); //In mAh
//Telemetry.pwb.capacity2 = (((s32)packet[8] << 8) | packet[9] + 5); //In mAh
//Telemetry.pwb.alarm_v1 = packet[15] & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_v2 = (packet[15] >> 1) & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_c1 = (packet[15] >> 2) & 0x01; //0 = disable, 1 = enable
//Telemetry.pwb.alarm_c2 = (packet[15] >> 3) & 0x01; //0 = disable, 1 = enable
//Telemetry.time[x2] = CLOCK_getms();
break;
case 0x11: //AirSpeed sensor
//Telemetry.airspeed = ((s32)packet[2] << 8) | packet[3]; //In km/h (16Bit value, 1 unit is 1 km/h)
//Telemetry.time[x3] = CLOCK_getms();
break;
case 0x12: //Altimeter sensor
//Telemetry.altitude = (((s16)packet[2] << 8) | packet[3]) /10; //In meters (16Bit signed integer, 1 unit is 0.1m)
//Telemetry.time[x4] = CLOCK_getms();
break;
case 0x14: //G-Force sensor
//Telemetry.gforce.x = ((s16)packet[2] << 8) | packet[3]; //In 0.01g (16Bit signed integers, unit is 0.01g)
//Telemetry.gforce.y = ((s16)packet[4] << 8) | packet[5];
//Telemetry.gforce.z = ((s16)packet[6] << 8) | packet[7];
//Telemetry.gforce.xmax = ((s16)packet[8] << 8) | packet[9];
//Telemetry.gforce.ymax = ((s16)packet[10] << 8) | packet[11];
//Telemetry.gforce.zmax = ((s16)packet[12] << 8) | packet[13];
//Telemetry.gforce.zmin = ((s16)packet[14] << 8) | packet[15];
//Telemetry.time[x5] = CLOCK_getms();
break;
case 0x15: //JetCat sensor
//No data yet
break;
case 0x16: //GPS sensor
Telemetry.gps.altitude = (((packet[3] >> 4) * 10 + (packet[3] & 0x0f)) * 100 //(16Bit decimal, 1 unit is 0.1m)
+ ((packet[2] >> 4) * 10 + (packet[2] & 0x0f))) * 100; //In meters * 1000
Telemetry.gps.latitude = ((packet[7] >> 4) * 10 + (packet[7] & 0x0f)) * 3600000
+ ((packet[6] >> 4) * 10 + (packet[6] & 0x0f)) * 60000
+ ((packet[5] >> 4) * 10 + (packet[5] & 0x0f)) * 600
+ ((packet[4] >> 4) * 10 + (packet[4] & 0x0f)) * 6;
if ((packet[15] & 0x01) == 0)
Telemetry.gps.latitude *= -1;
Telemetry.gps.longitude = ((packet[11] >> 4) * 10 + (packet[11] & 0x0f)) * 3600000
+ ((packet[10] >> 4) * 10 + (packet[10] & 0x0f)) * 60000
+ ((packet[9] >> 4) * 10 + (packet[9] & 0x0f)) * 600
+ ((packet[8] >> 4) * 10 + (packet[8] & 0x0f)) * 6;
if ((packet[15] & 0x04) == 4)
Telemetry.gps.longitude += 360000000;
if ((packet[15] & 0x02) == 0)
Telemetry.gps.longitude *= -1;
// Telemetry.gps.heading = ((packet[13] >> 4) * 10 + (packet[13] & 0x0f)) * 10 //(16Bit decimal, 1 unit is 0.1 degree)
// + ((packet[12] >> 4) * 10 + (packet[12] & 0x0f)) / 10; //In degrees
Telemetry.time[2] = CLOCK_getms();
break;
case 0x17: //GPS sensor
Telemetry.gps.velocity = (((packet[3] >> 4) * 10 + (packet[3] & 0x0f)) * 100
+ ((packet[2] >> 4) * 10 + (packet[2] & 0x0f))) * 5556 / 108; //In m/s * 1000
u8 hour = (packet[7] >> 4) * 10 + (packet[7] & 0x0f);
u8 min = (packet[6] >> 4) * 10 + (packet[6] & 0x0f);
u8 sec = (packet[5] >> 4) * 10 + (packet[5] & 0x0f);
//u8 ssec = (packet[4] >> 4) * 10 + (packet[4] & 0x0f);
u8 day = 0;
u8 month = 0;
u8 year = 0; // + 2000
Telemetry.gps.time = ((year & 0x3F) << 26)
| ((month & 0x0F) << 22)
| ((day & 0x1F) << 17)
| ((hour & 0x1F) << 12)
| ((min & 0x3F) << 6)
| ((sec & 0x3F) << 0);
// Telemetry.gps.sats = ((packet[8] >> 4) * 10 + (packet[8] & 0x0f));
Telemetry.time[2] = CLOCK_getms();
break;
}
}
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
Please Log in or Create an account to join the conversation.
- Home
- Forum
- Development
- Protocol Development
- DSM Telemetry support