×

Notice

The forum is in read only mode.

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.
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
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.
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.
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.
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.
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.
  • 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.
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.
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.
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.
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();
	   }
        }
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!!!
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)
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.
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.
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.
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.
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.
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
Time to create page: 0.522 seconds
Powered by Kunena Forum