DSM Telemetry support

More
24 Dec 2012 04:26 - 24 Dec 2012 05:11 #4242 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support

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?
Last edit: 24 Dec 2012 05:11 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
24 Dec 2012 14:52 #4249 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support
PB, you can check RPM sensor telemetry without real RPM sensor:

www.helifreak.com/showthread.php?t=320846

Please Log in or Create an account to join the conversation.

More
24 Dec 2012 21:40 - 24 Dec 2012 21:40 #4256 by PhracturedBlue
Replied by PhracturedBlue on topic DSM Telemetry support

vlad_vy wrote: PB, you can check RPM sensor telemetry without real RPM sensor:

www.helifreak.com/showthread.php?t=320846

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.


It is probably easier for someone with the proper sensor (and a known RPM to just tell me what is reported.
Last edit: 24 Dec 2012 21:40 by PhracturedBlue.

Please Log in or Create an account to join the conversation.

More
01 Jan 2013 08:16 - 01 Jan 2013 12:29 #4460 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support
I have notice that with DSMX protocol:
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.
Last edit: 01 Jan 2013 12:29 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
09 Feb 2013 11:31 - 09 Feb 2013 12:34 #6164 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support

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?
Last edit: 09 Feb 2013 12:34 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
09 Feb 2013 14:58 #6169 by PhracturedBlue
Replied by PhracturedBlue on topic DSM Telemetry support
I believe he's right, but it doesn't really matter to my code.

Please Log in or Create an account to join the conversation.

More
03 Mar 2013 11:21 - 03 Mar 2013 11:30 #7278 by RW9UAO
Replied by RW9UAO on topic DSM Telemetry support

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
Last edit: 03 Mar 2013 11:30 by RW9UAO.

Please Log in or Create an account to join the conversation.

  • rbe2012
  • rbe2012's Avatar
  • Offline
  • So much to do, so little time...
More
03 Mar 2013 13:20 #7283 by rbe2012
Replied by rbe2012 on topic DSM Telemetry support
You can run "hg diff > filename.patch". The result is a file you can use as input
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.

More
07 Mar 2013 14:34 - 07 Mar 2013 14:39 #7492 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support
PB, if you have a time, I can test telemetry for Spektrum GPS sensor.

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)
Last edit: 07 Mar 2013 14:39 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
07 Mar 2013 18:00 - 07 Mar 2013 18:22 #7494 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support
If Tx at DSMX mode always transmit, in time of binding, capability byte 0xB2, telemetry works fine with any number of channels (6, 7, 8 or 9 channels).

if(Model.protocol == PROTOCOL_DSMX)
packet[12] = num_channels < 8 ? 0xb2 : 0xb2;
else
packet[12] = num_channels < 8 ? 0x01 : 0x02;
Last edit: 07 Mar 2013 18:22 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
13 Mar 2013 16:40 - 17 Mar 2013 12:45 #7694 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support
Draft version of telemetry parser
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)
Last edit: 17 Mar 2013 12:45 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
14 Mar 2013 06:38 #7737 by RW9UAO
Replied by RW9UAO on topic DSM Telemetry support
too much "if", use switch/case =)
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];
        }
    }
this fix blinking values
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.

More
14 Mar 2013 06:40 #7738 by RW9UAO
Replied by RW9UAO on topic DSM Telemetry support
ok. next we need add more screens for telemetry. please!!!

Please Log in or Create an account to join the conversation.

More
14 Mar 2013 17:44 #7757 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support

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.

More
14 Mar 2013 18:15 - 15 Mar 2013 09:23 #7758 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support
deleted
Last edit: 15 Mar 2013 09:23 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
15 Mar 2013 04:09 - 17 Mar 2013 12:46 #7771 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support

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)
Last edit: 17 Mar 2013 12:46 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
16 Mar 2013 06:42 - 17 Mar 2013 12:47 #7798 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support

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;
    }
}
Last edit: 17 Mar 2013 12:47 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
16 Mar 2013 12:06 - 17 Mar 2013 12:48 #7804 by vlad_vy
Replied by vlad_vy on topic DSM Telemetry support
Tested telemetry with Magnetic RPM sensor. Current calculation is incorrect. Correctly will be:
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;
    }
}
Last edit: 17 Mar 2013 12:48 by vlad_vy.

Please Log in or Create an account to join the conversation.

More
16 Mar 2013 14:20 #7807 by PhracturedBlue
Replied by PhracturedBlue on topic DSM Telemetry support
Thanks for the hard work. I will get this included soon.

Please Log in or Create an account to join the conversation.

More
16 Mar 2013 16:03 #7819 by PhracturedBlue
Replied by PhracturedBlue on topic DSM Telemetry support
It seems to be ok, but is too big to fit inside the devo7e. I need to figure out how to reduce the size of the dsm code so that this can fit. Maybe I need to break up the dsm2 and dsmx protocols into different modules, though it won't save me all that much

Please Log in or Create an account to join the conversation.

Time to create page: 0.088 seconds
Powered by Kunena Forum