Direct Frsky telemtry data from MW FC
Direct Frsky telemtry data from MW FC
Hi,
I was asking myself if there's an implementation for direct data output from the Multiwii-FC to the digital side port of Frsky telemetry receivers.
This way no additional sensors must be used to display height, position or whatever on your Tx.
Frame Protocol of FrSky Telemetry Hub System:
http://www.frsky-rc.com/uploadfile/2011 ... 301692.pdf
Thanks in advance
I was asking myself if there's an implementation for direct data output from the Multiwii-FC to the digital side port of Frsky telemetry receivers.
This way no additional sensors must be used to display height, position or whatever on your Tx.
Frame Protocol of FrSky Telemetry Hub System:
http://www.frsky-rc.com/uploadfile/2011 ... 301692.pdf
Thanks in advance
Re: Direct Frsky telemtry data from MW FC
Lapino wrote:Hi,
I was asking myself if there's an implementation for direct data output from the Multiwii-FC to the digital side port of Frsky telemetry receivers.
This way no additional sensors must be used to display height, position or whatever on your Tx.
Frame Protocol of FrSky Telemetry Hub System:
http://www.frsky-rc.com/uploadfile/2011 ... 301692.pdf
Thanks in advance
Well, not yet anyway
But I like the idea. Instead of using the Sensor Hub you could frame the sensor data with MultiWii and send it to the FrSky Rx directly.
You'd have to convert the signal to RS232 levels, however, and it would probably eat up quite some flash memory.
Re: Direct Frsky telemtry data from MW FC
I've a Flyduino Mega (2560) so flash isn't a problem...free connections either
Maybe some of the great coders could help?
I'm relative new to arduino and interrupt handling(if needed).
Maybe some of the great coders could help?
I'm relative new to arduino and interrupt handling(if needed).
Re: Direct Frsky telemtry data from MW FC
I've played with this idea some time ago and did some testing. It's possible and it's not too hard, but the following code fragments are just for testing propose and not cleany coded nor complete. You have been warned .
These code segments are meant for MW 2.0. To test this you need a Mega, a level converter and a telemetry capable FrSky reciever/transmitter combination. I've used a small lever converter from Ebay and a flashed 9x to display the data, but i'm not certain that the FrSky implementation from the er9x branch is complete and error-free.
The FrSky hub sends 3 different packets:
Frame 1 is send each 200ms. Basically some voltage, temperature and altitude information.
Frame 2 is send each second. I think the most interesting stuff: GPS, Speed, Fuel.
Frame 3 is send each 5s and only consists date and time information. Not very useful.
The example code only transmits the current GPS position. The rest is static demo data from the FrSky Frame Protocal datasheet.
config.h - somewhere around line 347
MultiWii_2_0.ino - line 113
MultiWii_2_0.ino - line 350 - at the end of annexCode() function
LCD.ino - at the end
I currently have only two STM32 and a 328 copter, hence I've suspended the project at the moment, but maybe someone could use some bits and pieces.
These code segments are meant for MW 2.0. To test this you need a Mega, a level converter and a telemetry capable FrSky reciever/transmitter combination. I've used a small lever converter from Ebay and a flashed 9x to display the data, but i'm not certain that the FrSky implementation from the er9x branch is complete and error-free.
The FrSky hub sends 3 different packets:
Frame 1 is send each 200ms. Basically some voltage, temperature and altitude information.
Frame 2 is send each second. I think the most interesting stuff: GPS, Speed, Fuel.
Frame 3 is send each 5s and only consists date and time information. Not very useful.
The example code only transmits the current GPS position. The rest is static demo data from the FrSky Frame Protocal datasheet.
config.h - somewhere around line 347
Code: Select all
/* Frsky Telemetry Output */
#define TELEMETRY_FRSKY
#define TELEMETRY_FRSKY_SERIAL 3
MultiWii_2_0.ino - line 113
Code: Select all
#if defined(TELEMETRY_FRSKY)
static uint32_t telemetryFrskyTimeFrame1 = 0, telemetryFrskyTimeFrame2 = 0, telemetryFrskyTimeFrame3 = 0;
#endif
MultiWii_2_0.ino - line 350 - at the end of annexCode() function
Code: Select all
#if defined(TELEMETRY_FRSKY)
telemetry_frsky();
#endif
LCD.ino - at the end
Code: Select all
#if defined(TELEMETRY_FRSKY)
void send_frsky_frame(byte* data, int len )
{
uint8_t bytestuff = 0;
for (uint8_t i=0;i<len;i++)
{
if ( ( data[i] == 0x5E || data[i] == 0x5e ) && bytestuff > 0 && bytestuff < 4 )
{
SerialWrite(TELEMETRY_FRSKY_SERIAL, 0x5D );
SerialWrite(TELEMETRY_FRSKY_SERIAL, 0x3E );
bytestuff++;
}
else if ( data[i] == 0x5D || data[i] == 0x5d )
{
SerialWrite(TELEMETRY_FRSKY_SERIAL, 0x5D );
SerialWrite(TELEMETRY_FRSKY_SERIAL, 0x3D );
bytestuff++;
}
else
{
SerialWrite(TELEMETRY_FRSKY_SERIAL, data[i] );
if ( data[i] == 0x5E || data[i] == 0x5e )
{
bytestuff=1;
}
else
{
bytestuff++;
}
}
}
}
// convert dd.ddddd format into ddmm
uint16_t GPS_degrees_to_ddmm(uint32_t i) {
return (int)( ( ( ( i - ( (int)( i / 100000 ) * 100000 ) ) * 0.6 ) + ( (int)( i / 100000 ) * 100000 ) ) / 1000 );
}
// convert dd.ddddd format into mmmm
uint16_t GPS_degrees_to_mmmm(uint32_t i) {
uint32_t n = ( i - ( (int)( i / 100000 ) * 100000 ) ) * 6;
return ( n - ( (int)( n / 10000 ) * 10000 ) );
}
void telemetry_frsky() {
// Frame 1: Three-axis Acceleration Values, Altitude (variometer-0.01m), Temperature1, Temperature2, Voltage, Current & Voltage (Ampere Sensor) , RPM
if (currentTime > telemetryFrskyTimeFrame1 + 200000 ) { // 200ms
uint16_t rpm = 0;
for (uint8_t i=0;i<NUMBER_MOTOR;i++)
{
rpm=rpm+motor[i];
}
rpm=rpm/NUMBER_MOTOR/30;
byte data[49] = {0x5E, 0x24, 0x00, 0x04, // Three-axis Acceleration Values x
0x5E, 0x25, 0x80, 0xFF, // Three-axis Acceleration Values y
0x5E, 0x26, 0xE0, 0xFE, // Three-axis Acceleration Values z
0x5E, 0x10, 0x3C, 0x00, // Altitude
0x5E, 0x21, 0x3C, 0x00, // Altitude
0x5E, 0x02, 0xEF, 0xFF, // Temperature1
0x5E, 0x05, 0xE9, 0xFF, // Temperature2
0x5E, 0x06, 0x18, 0x34, // Volt
0x5E, 0x28, 0x02, 0x00, // Current & Voltage (Ampere Sensor) Current
0x5E, 0x3A, 0x0a, 0x00, // Current & Voltage (Ampere Sensor) Voltage
0x5E, 0x3B, 0x05, 0x00, // Current & Voltage (Ampere Sensor) Voltage
0x5E, 0x03, rpm, rpm>>8, // RPM
0x5E};
send_frsky_frame(data, 49);
telemetryFrskyTimeFrame1 = currentTime;
}
// Frame 2: Course, Latitude, Longitude, Speed, Altitude (GPS), Fuel Level
if ( currentTime > telemetryFrskyTimeFrame2 + 1000000 ) { // 1s
uint16_t lat_ddmm = GPS_degrees_to_ddmm(GPS_latitude);
uint16_t lat_mmmm = GPS_degrees_to_mmmm(GPS_latitude);
uint16_t lon_ddmm = GPS_degrees_to_ddmm(GPS_longitude);
uint16_t lon_mmmm = GPS_degrees_to_mmmm(GPS_longitude);
byte data[53] = {0x5E,0x14,0x2c,0x00, // Course
0x5E,0x1c,0x03,0x00, // Course
0x5E,0x13,lat_ddmm, lat_ddmm>>8, // Latitude
0x5E,0x1b,lat_mmmm, lat_mmmm>>8, // Latitude
0x5E,0x23,0x4E,0x00, // N/S [4E|53]
0x5E,0x12,lon_ddmm, lon_ddmm>>8, // Longitude
0x5E,0x1a,lon_mmmm, lon_mmmm>>8, // Longitude
0x5E,0x22,0x45,0x00, // E/W [45|57]
0x5E,0x11,0x00,0x00, // Speed (GPS)
0x5E,0x19,0x93,0x00, // Speed (GPS)
0x5E,0x01,0x02,0x00, // Altitude (GPS)
0x5E,0x09,0x00,0x00, // Altitude (GPS)
0x5E,0x04,0x64,0x00, // Fuel Level
0x5E};
send_frsky_frame(data, 53);
telemetryFrskyTimeFrame2 = currentTime;
}
// Frame 3: Date, Time
if (currentTime > telemetryFrskyTimeFrame3 + 5000000 ) { // 5s
byte data[17] = {0x5E, 0x15, 0x0F, 0x07, // Date/Month
0x5E, 0x16, 0x0B, 0x00, // Year
0x5E, 0x17, 0x06, 0x12, // Hour/Minute
0x5E, 0x18, 0x32, 0x00, // Second
0x5E };
send_frsky_frame(data,17);
telemetryFrskyTimeFrame3 = currentTime;
}
}
#endif //TELEMETRY_FRSKY
I currently have only two STM32 and a 328 copter, hence I've suspended the project at the moment, but maybe someone could use some bits and pieces.
-
- Posts: 2261
- Joined: Sat Feb 19, 2011 8:30 pm
Re: Direct Frsky telemtry data from MW FC
Very interesting, question, what is the maximum range of the Frsky telemetry unit? Reason I ask, Bluetooth range is about 100 feet or there about.
Re: Direct Frsky telemtry data from MW FC
copterrichie wrote:Very interesting, question, what is the maximum range of the Frsky telemetry unit? Reason I ask, Bluetooth range is about 100 feet or there about.
Same range as the receiver (i.e. 1.5 km).
100 feet sounds a bit optimistic for Bluetooth.
Re: Direct Frsky telemtry data from MW FC
just ordered the required TTL level converter...will test it as soon as it arrives
-
- Posts: 2261
- Joined: Sat Feb 19, 2011 8:30 pm
Re: Direct Frsky telemtry data from MW FC
This would be really nice to get working, we could dump the On-board OSD and handle all of the telemetry on the ground.
-
- Posts: 1630
- Joined: Wed Jan 19, 2011 9:07 pm
Re: Direct Frsky telemtry data from MW FC
My dream would be a uplink telemetry based on frsky without impacting the 8 first RC channels.
Re: Direct Frsky telemtry data from MW FC
The Frsky transmitter and the receiver have both a RX/TX port combo, but does it actually have an separate up-link channel?
Re: Direct Frsky telemtry data from MW FC
copterrichie wrote:This would be really nice to get working, we could dump the On-board OSD and handle all of the telemetry on the ground.
You can already do this by sending telemetry encoded + fec over audio channel. Infact I think some commercial systems do this.
I also do not understand why anyone uses "OSD" which generates characters over fuzzy crap video and then transmits it back, when it would make 100x more sense to transmit the required data over sideband and then render it in any resolution and with any kind of on-screen setup on the ground. I guess people just don't like progress.
Re: Direct Frsky telemtry data from MW FC
No Sir !
People do not have skills (except a few)
I have Apache OSD - http://www.aeorc.com/english/?product-387.html
Manufacturer claim it will be implemented in future but looks like nothing is going on.
Anyway I was thinking (no skills) to try to use audio channel to send data.
Looking for protocol I found thishttp://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1270645507
What in Your opinion will be easiest way to try (on both TX & RX sides
Regards
Tom
People do not have skills (except a few)
I have Apache OSD - http://www.aeorc.com/english/?product-387.html
Manufacturer claim it will be implemented in future but looks like nothing is going on.
Anyway I was thinking (no skills) to try to use audio channel to send data.
Looking for protocol I found thishttp://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1270645507
What in Your opinion will be easiest way to try (on both TX & RX sides
Regards
Tom
-
- Posts: 2261
- Joined: Sat Feb 19, 2011 8:30 pm
Re: Direct Frsky telemtry data from MW FC
My understanding at present, there are problems sending telemetry data over the audio channel, one of the biggest problem, the audio will crap out long before the video will. A few guys over on RCG are now working on what they termed a video Modem to send data on the video.
http://www.rcgroups.com/forums/showthread.php?t=1672628
http://www.rcgroups.com/forums/showthread.php?t=1672628
Re: Direct Frsky telemtry data from MW FC
Old fashion 300 baud telephone modems was effective over very narrow freqency telephony audio.
Anyway if I find right protocol I will try it this weekend.
Tom
P.S. Long time ago I play with pocket radio (data over FM audio channel @ 2meters 144 Mhz) during very rare aurora condition I have 400 km contact (144Mhz have 50+km range) with totally distorted audio but packet radio modem was decoding it without any problem.
Anyway if I find right protocol I will try it this weekend.
Tom
P.S. Long time ago I play with pocket radio (data over FM audio channel @ 2meters 144 Mhz) during very rare aurora condition I have 400 km contact (144Mhz have 50+km range) with totally distorted audio but packet radio modem was decoding it without any problem.
Re: Direct Frsky telemtry data from MW FC
I have an Flyduino Mega and a complete FrSky set with telemetry, and want to give this a try.
Do you have any info on the level adapte you use?
I have this one [urlhttp://www.hobbyking.com/hobbyking/store/__16672__FrSky_Telemetry_Reciever_upgrade_USB_Serial_lead_interface.html][/url]
Mvh
Øyvind
Do you have any info on the level adapte you use?
I have this one [urlhttp://www.hobbyking.com/hobbyking/store/__16672__FrSky_Telemetry_Reciever_upgrade_USB_Serial_lead_interface.html][/url]
Mvh
Øyvind
Re: Direct Frsky telemtry data from MW FC
naze32 / stm32 port of multiwii supports telemetry output to FrSky without hub.
currently it outputs accelerometer data / battery voltage / baro pressure / gyro temperature / system up time (for the clock) / I think GPS data also , but that hasn't been tested.
code: http://code.google.com/p/afrodevices/so ... elemetry.c (needs output fix for 0x5E inside data stream)
since it's just tx out, a simple level shifter is used:
currently it outputs accelerometer data / battery voltage / baro pressure / gyro temperature / system up time (for the clock) / I think GPS data also , but that hasn't been tested.
code: http://code.google.com/p/afrodevices/so ... elemetry.c (needs output fix for 0x5E inside data stream)
since it's just tx out, a simple level shifter is used:
Re: Direct Frsky telemtry data from MW FC
I don't have much experience with the MultiWii code. But I think, there will be a Problem with the cycle time in both codes in this thread, if we send about 100 byte with 9600 baud, isnt' it?
-
- Posts: 2261
- Joined: Sat Feb 19, 2011 8:30 pm
Re: Direct Frsky telemtry data from MW FC
tobi86 wrote:I don't have much experience with the MultiWii code. But I think, there will be a Problem with the cycle time in both codes in this thread, if we send about 100 byte with 9600 baud, isnt' it?
This is where a good housekeeping (Slave Processor) would really come in handy.
Re: Direct Frsky telemtry data from MW FC
This is where a good housekeeping (Slave Processor) would really come in handy.
I agree. All my MWC models have a Pro Mini and I didn't want to give up the GUI's serial port. With that in mind, I'm finishing up my FrSky interface and it involves a slave processor that acts as a I2C bridge. That is to say, the FrSky FAS-100 current sensor and telemetry R/C Rx plug into the bridge. Then the MCW flight controller communicates with the bridge via the I2C port. The MWC manages the telemetry data that is sent (using a new sketch file that is added to the V2.1 release).
The code impact on the MWC is about 1500 bytes, but could be less depending on the telemetry data that is needed. At the moment I'm sending FAS-100 voltage/current, GPS coordinates, GPS course, GPS altitude, GPS ground speed, satellite count, satellite Fix status, stick position for six channels, baro altitude, temperature, and MWC cycle-time. Some of this data has a high frame rate. For example, I send baro altitude at 5Hz and GPS coordinates are 3Hz.
BTW, in my installation the GPS telmetry data is from the popular I2C_GPS_NAV board method. But the bridge could use other GPS sources too; Just about any data known to the MWC FC can be sent through the bridge to the telemetry Rx.
But I think, there will be a Problem with the cycle time in both codes in this thread, if we send about 100 byte with 9600 baud, isnt' it?
For sure, the soft serial method will not be an option. But interrupt driven 9600 baud serial code should be fine, even on the Pro Mini.
In my case the I2C bridge speed is 100KHz. There's about 150 bytes/sec that are sent to the FrSky telemetry Rx. In my observations I see very little impact to the cycle time due to FrSky telemetry. Given that, I expect a hardware 9600 baud serial port solution would be fine too.
- Thomas
Re: Direct Frsky telemtry data from MW FC
Software serial could be an option if the frame rate is reduced to sending only one byte each cycle. That would add one millisecond to those cycles ... I have these kind of increases with extensive logging enabled and the copter is still flyable.
Re: Direct Frsky telemtry data from MW FC
mr.rc-cam wrote:I agree. All my MWC models have a Pro Mini and I didn't want to give up the GUI's serial port. With that in mind, I'm finishing up my FrSky interface and it involves a slave processor that acts as a I2C bridge. That is to say, the FrSky FAS-100 current sensor and telemetry R/C Rx plug into the bridge. Then the MCW flight controller communicates with the bridge via the I2C port. The MWC manages the telemetry data that is sent (using a new sketch file that is added to the V2.1 release).
Could you share your code on this?
Also which tools you are going to use as (offline) map tracker and logger?
I found these:
- https://play.google.com/store/apps/deta ... rch_result - good but only online
- http://www.xcsoar.org/ and https://play.google.com/store/apps/deta ... soar&hl=en - great! but it's required nmea data on input (possible to do with software converter)
my thread on this here http://forum.rcdesign.ru/f90/thread287324.html
thx-
Alex
Re: Direct Frsky telemtry data from MW FC
Could you share your code on this?
I plan on publishing the code by the end of the month, or so I hope. The FrSky/Multicopter Telemetry Project blog will have the technical details when they become available:
http://www.rc-cam.com/forum/index.php?/ ... interface/
Also which tools you are going to use as (offline) map tracker and logger?
I don't have any immediate plans to use map tracking. So I don't have any recommendations to offer.
- Thomas
Re: Direct Frsky telemtry data from MW FC
I've integrated telemetry today and it seems to work (MultiWii 2.1). I've a Atmega2560 (Flyduino MEGA) so I can use serial Port 3 and don't need a soft RS232. I work with interrupts, so the totale cycle time increased only about 2 ms. To invert the TX-signal I used a single Schmitt-trigger Inverter (74LVC1G14), which I've directly integrated in my FrSky-receiver. To make the import and change in further MultiWii versions easyer I generated a new *.ino file with the FrSky code. Additionaly these changes are necessary:
config.h - around line 705
MultiWii_2_1.ino - somewhere in void setup() around line 570
MultiWii_2_1.ino - somewhere in void annexCode() around line 460
FrSky_telemetry.ino (New file)
In the next days I will add the possibility to integrate a FLVS-01 single-cell-voltage modul with a FAS100 Ampere sensor which I will connect to the RX Pin of the serial Port3. If someone interested in this code I can post it here too.
Improvements and feedback is welcome.
config.h - around line 705
Code: Select all
/**************************************************************************************/
/*********************** FrSky telemetry **************************/
/**************************************************************************************/
#define TELEMETRY_FRSKY //new
MultiWii_2_1.ino - somewhere in void setup() around line 570
Code: Select all
#if defined(TELEMETRY_FRSKY) //new FrSky
configure_FrSky();
#endif
MultiWii_2_1.ino - somewhere in void annexCode() around line 460
Code: Select all
#if defined(TELEMETRY_FRSKY) // new
telemetry_frsky();
#endif
FrSky_telemetry.ino (New file)
Code: Select all
// **********************
// FrSky telemetry
// **********************
#if defined(TELEMETRY_FRSKY)
// Serial config datas
#define TELEMETRY_FRSKY_SERIAL 3
#define TELEMETRY_FRSKY_BAUD 9600
// Interrupt
#define ISR_FRSKY ISR(USART3_UDRE_vect)
// Ringbuffer
#define FRSKY_BUFFER_SIZE 150
static uint8_t bufFrSky[FRSKY_BUFFER_SIZE];
static volatile uint8_t headTXFrSky;
static volatile uint8_t tailTXFrSky;
// Timing
#define Time_telemetry_send 125000
static uint8_t cycleCounter = 0;
static uint32_t FrSkyTime = 0;
// Frame protocol
#define Protocol_Header 0x5E
#define Protocol_Tail 0x5E
// Data Ids (bp = before point; af = after point)
// Official data IDs
#define ID_GPS_altidute_bp 0x01
#define ID_GPS_altidute_ap 0x09
#define ID_Temprature1 0x02
#define ID_RPM 0x03
#define ID_Fuel_level 0x04
#define ID_Temprature2 0x05
#define ID_Volt 0x06
#define ID_Altitude_bp 0x10
#define ID_Altitude_ap 0x21
#define ID_GPS_speed_bp 0x11
#define ID_GPS_speed_ap 0x19
#define ID_Longitude_bp 0x12
#define ID_Longitude_ap 0x1A
#define ID_E_W 0x22
#define ID_Latitude_bp 0x13
#define ID_Latitude_ap 0x1B
#define ID_N_S 0x23
#define ID_Course_bp 0x14
#define ID_Course_ap 0x24
#define ID_Date_Month 0x15
#define ID_Year 0x16
#define ID_Hour_Minute 0x17
#define ID_Second 0x18
#define ID_Acc_X 0x24
#define ID_Acc_Y 0x25
#define ID_Acc_Z 0x26
#define ID_Voltage_Amp_bp 0x3A
#define ID_Voltage_Amp_ap 0x3B
#define ID_Current 0x28
// User defined data IDs
#define ID_Gyro_X 0x40
#define ID_Gyro_Y 0x41
#define ID_Gyro_Z 0x42
void configure_FrSky()
{
SerialOpen(TELEMETRY_FRSKY_SERIAL,TELEMETRY_FRSKY_BAUD);
}
// Interrupt
ISR_FRSKY
{
uint8_t Tail = tailTXFrSky;
if (headTXFrSky != Tail)
{
if (++Tail >= FRSKY_BUFFER_SIZE)
{
Tail = 0;
}
tailTXFrSky = Tail;
UDR3 = bufFrSky[Tail]; // Transmit next byte in the ring
}
if (Tail == headTXFrSky) UCSR3B &= ~(1<<UDRIE3); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
}
// Main function FrSky telemetry
void telemetry_frsky()
{
if (currentTime > FrSkyTime ) //
{
FrSkyTime = currentTime + Time_telemetry_send;
cycleCounter++;
// Datas sent every 125 ms
send_Accel();
sendDataTail();
if ((cycleCounter % 4) == 0)
{
// Datas sent every 500ms
send_Altitude();
send_RPM();
send_Course();
send_GPS_speed();
send_Cell_volt();
sendDataTail();
}
if ((cycleCounter % 8) == 0)
{
// Datas sent every 1s
send_Time();
send_GPS_position();
send_GPS_altitude();
send_Temperature2(); // Distance_to_home
send_Fuel_level();
send_Voltage_ampere();
sendDataTail();
}
if (cycleCounter == 40)
{
// Datas sent every 5s
send_Temperature1(); // num of Sats
sendDataTail();
cycleCounter = 0;
}
}
}
void write_FrSky8(uint8_t Data)
{
uint8_t Head = headTXFrSky;
if (++Head >= FRSKY_BUFFER_SIZE) Head = 0;
bufFrSky[Head] = Data;
headTXFrSky = Head;
UCSR3B |= (1<<UDRIE3); // Enable Interrupt
}
void write_FrSky16(uint16_t Data)
{
uint8_t Data_send;
Data_send = Data;
write_FrSky8(Data_send);
Data_send = Data >> 8 & 0xff;
write_FrSky8(Data_send);
}
static void sendDataHead(uint8_t Data_id)
{
write_FrSky8(Protocol_Header);
write_FrSky8(Data_id);
}
static void sendDataTail(void)
{
write_FrSky8(Protocol_Tail);
}
//*********************************************************************************
//----------------- Telemetrie Datas ------------------------------------------
//*********************************************************************************
// GPS altitude
void send_GPS_altitude(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
int16_t Datas_GPS_altidute_bp;
uint16_t Datas_GPS_altidute_ap;
Datas_GPS_altidute_bp = GPS_altitude;
Datas_GPS_altidute_ap = 0;
sendDataHead(ID_GPS_altidute_bp);
write_FrSky16(Datas_GPS_altidute_bp);
sendDataHead(ID_GPS_altidute_ap);
write_FrSky16(Datas_GPS_altidute_ap);
}
}
// Temperature
void send_Temperature1(void)
{
int16_t Datas_Temprature1;
Datas_Temprature1 = GPS_numSat; // Number of Satalits alias Temp1
sendDataHead(ID_Temprature1);
write_FrSky16(Datas_Temprature1);
}
// RPM
void send_RPM(void)
{
uint16_t Datas_RPM = 0;
for (uint8_t i=0;i<NUMBER_MOTOR;i++)
{
Datas_RPM += motor[i];
}
Datas_RPM = (Datas_RPM / NUMBER_MOTOR) / 30; // RPM
sendDataHead(ID_RPM);
write_FrSky16(Datas_RPM);
}
// Fuel level
void send_Fuel_level(void)
{
uint16_t Datas_Fuel_level;
Datas_Fuel_level = 0;
sendDataHead(ID_Fuel_level);
write_FrSky16(Datas_Fuel_level);
}
// Temperature 2
void send_Temperature2(void)
{
if (f.GPS_FIX_HOME)
{
int16_t Datas_Temprature2;
Datas_Temprature2 = GPS_distanceToHome; // Distance to home alias Temp2
sendDataHead(ID_Temprature2);
write_FrSky16(Datas_Temprature2);
}
}
// Cell voltage
void send_Cell_volt(void)
{
uint16_t Datas_Volt;
Datas_Volt = 0; // 0.01v / 0 ~ 4.2v
sendDataHead(ID_Volt);
write_FrSky16(Datas_Volt);
}
// Altitude
void send_Altitude(void)
{
uint16_t Datas_altitude_bp;
uint16_t Datas_altitude_ap;
static uint16_t Start_altitude;
if (!f.ARMED)
{
Start_altitude = EstAlt / 100;
}
Datas_altitude_bp = (EstAlt / 100) - Start_altitude;
Datas_altitude_ap = (EstAlt % 100);
sendDataHead(ID_Altitude_bp);
write_FrSky16(Datas_altitude_bp);
sendDataHead(ID_Altitude_ap);
write_FrSky16(Datas_altitude_ap);
}
// GPS speed
void send_GPS_speed(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
uint16_t Datas_GPS_speed_bp;
uint16_t Datas_GPS_speed_ap;
Datas_GPS_speed_bp = GPS_speed * 0.036;
Datas_GPS_speed_ap = 0;
sendDataHead(ID_GPS_speed_bp);
write_FrSky16(Datas_GPS_speed_bp);
sendDataHead(ID_GPS_speed_ap);
write_FrSky16(Datas_GPS_speed_ap);
}
}
// GPS position
void send_GPS_position(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
uint16_t Datas_Longitude_bp;
uint16_t Datas_Longitude_ap;
uint16_t Datas_E_W;
uint16_t Datas_Latitude_bp;
uint16_t Datas_Latitude_ap;
uint16_t Datas_N_S;
Datas_Longitude_bp = abs(GPS_coord[LON]) / 100000;
Datas_Longitude_ap = abs((GPS_coord[LON])/10) % 10000;
Datas_E_W = GPS_coord[LON] < 0 ? 'W' : 'E';
Datas_Latitude_bp = abs(GPS_coord[LAT]) / 100000;
Datas_Latitude_ap = abs((GPS_coord[LAT])/10) % 10000;
Datas_N_S = GPS_coord[LAT] < 0 ? 'S' : 'N';
sendDataHead(ID_Longitude_bp);
write_FrSky16(Datas_Longitude_bp);
sendDataHead(ID_Longitude_ap);
write_FrSky16(Datas_Longitude_ap);
sendDataHead(ID_E_W);
write_FrSky16(Datas_E_W);
sendDataHead(ID_Latitude_bp);
write_FrSky16(Datas_Latitude_bp);
sendDataHead(ID_Latitude_ap);
write_FrSky16(Datas_Latitude_ap);
sendDataHead(ID_N_S);
write_FrSky16(Datas_N_S);
}
}
// Course
void send_Course(void)
{
uint16_t Datas_Course_bp;
uint16_t Datas_Course_ap;
Datas_Course_bp = heading;
Datas_Course_ap = 0;
sendDataHead(ID_Course_bp);
write_FrSky16(Datas_Course_bp);
sendDataHead(ID_Course_ap);
write_FrSky16(Datas_Course_ap);
}
// Time
void send_Time(void)
{
uint32_t seconds_since_start = millis() / 1000;
uint16_t Datas_Date_month;
uint16_t Datas_Year;
uint16_t Datas_Minutes_hours;
uint16_t Datas_seconds;
Datas_Date_month = 0;
Datas_Year = 12;
Datas_Minutes_hours = (seconds_since_start / 60) % 60;
Datas_seconds = seconds_since_start % 60;
sendDataHead(ID_Hour_Minute);
write_FrSky16(Datas_Minutes_hours);
sendDataHead(ID_Second);
write_FrSky16(Datas_seconds);
}
// ACC
void send_Accel(void)
{
int16_t Datas_Acc_X;
int16_t Datas_Acc_Y;
int16_t Datas_Acc_Z;
Datas_Acc_X = ((float)accSmooth[0] / acc_1G) * 1000;
Datas_Acc_Y = ((float)accSmooth[1] / acc_1G) * 1000;
Datas_Acc_Z = ((float)accSmooth[2] / acc_1G) * 1000;
sendDataHead(ID_Acc_X);
write_FrSky16(Datas_Acc_X);
sendDataHead(ID_Acc_Y);
write_FrSky16(Datas_Acc_Y);
sendDataHead(ID_Acc_Z);
write_FrSky16(Datas_Acc_Z);
}
// Voltage (Ampere Sensor)
void send_Voltage_ampere(void)
{
uint16_t Datas_Voltage_Amp_bp;
uint16_t Datas_Voltage_Amp_ap;
uint16_t Datas_Current;
Datas_Voltage_Amp_bp = 0;
Datas_Voltage_Amp_ap = 0;
Datas_Current = 0;
sendDataHead(ID_Voltage_Amp_bp);
write_FrSky16(Datas_Voltage_Amp_bp);
sendDataHead(ID_Voltage_Amp_ap);
write_FrSky16(Datas_Voltage_Amp_ap);
sendDataHead(ID_Current);
write_FrSky16(Datas_Current);
}
#endif
In the next days I will add the possibility to integrate a FLVS-01 single-cell-voltage modul with a FAS100 Ampere sensor which I will connect to the RX Pin of the serial Port3. If someone interested in this code I can post it here too.
Improvements and feedback is welcome.
Last edited by tobi86 on Thu Aug 09, 2012 10:25 pm, edited 2 times in total.
Re: Direct Frsky telemtry data from MW FC
Wow! Great job! Thanks a lot!
It seems we are in sync with our investigation!
Actually last night i have soldered an inverter (tranzistor + 3 resistors) and used the code base of this thread (but not yours yet ). I have played with "ALL IN ONE PRO Flight Controller v1.0" based on mega2560 (and also serial port 3), then checked the passed telemetry on turnigy+er9x...
So i have found out that cycleTime increases for 2-3ms when you are sending packets about 8-16 bytes, so I have success with transferring of GPS lon/lat/speed/alt, Baro ALT by using SerialWrite() function from mwii_2.1 code... BUT in case of trying to send all data which are supported in FrSky HUB protocol, it has a jumps in cycleTime more than 10ms
So i hope your implementation of write_FrSky8() function based on separated interrupt will resolve this issue... I will let you know soon
p.s. I suppose you have used some code base from dongs post viewtopic.php?f=7&t=1929&start=10#p19309 ?
There is an issue with calculation of the GPS lon/lat. I will post tested code (at least on turnigy+er9x) from home (at work now)...
Also are you planning to use some kind of map tracking and logging based on received telemetry?
And one more question In case of you are using the D8R-II plus receiver, have you tried to upgrade this to D8R-XP to get RSSI (e.g. for OSD) and CPPM output?
http://www.rcgroups.com/forums/showthre ... st22166908
thx-
Alex
It seems we are in sync with our investigation!
Actually last night i have soldered an inverter (tranzistor + 3 resistors) and used the code base of this thread (but not yours yet ). I have played with "ALL IN ONE PRO Flight Controller v1.0" based on mega2560 (and also serial port 3), then checked the passed telemetry on turnigy+er9x...
So i have found out that cycleTime increases for 2-3ms when you are sending packets about 8-16 bytes, so I have success with transferring of GPS lon/lat/speed/alt, Baro ALT by using SerialWrite() function from mwii_2.1 code... BUT in case of trying to send all data which are supported in FrSky HUB protocol, it has a jumps in cycleTime more than 10ms
So i hope your implementation of write_FrSky8() function based on separated interrupt will resolve this issue... I will let you know soon
p.s. I suppose you have used some code base from dongs post viewtopic.php?f=7&t=1929&start=10#p19309 ?
There is an issue with calculation of the GPS lon/lat. I will post tested code (at least on turnigy+er9x) from home (at work now)...
Also are you planning to use some kind of map tracking and logging based on received telemetry?
And one more question In case of you are using the D8R-II plus receiver, have you tried to upgrade this to D8R-XP to get RSSI (e.g. for OSD) and CPPM output?
http://www.rcgroups.com/forums/showthre ... st22166908
thx-
Alex
Re: Direct Frsky telemtry data from MW FC
mahowik wrote:So i have found out that cycleTime increases for 2-3ms when you are sending packets about 8-16 bytes, so I have success with transferring of GPS lon/lat/speed/alt, Baro ALT by using SerialWrite() function from mwii_2.1 code... BUT in case of trying to send all data which are supported in FrSky HUB protocol, it has a jumps in cycleTime more than 10ms
It must take much more than 10ms if you don't use interrupts and transfer datas with 9600 baud!
1 Bit takes 104 us
--> 1 Byte (8 bit + 1 start bit + 1 stop bit) = 1 ms
--> One Value (1 * Header, 1 * Data ID, 2 * Data) 4 Byte = 4 ms
--> only GPS Datas with 10 Data IDs (Position 6, speed 2, alt 2) = 10 * 4 ms = 40 ms!!! (Data frame tail, and RS232 waittime not included)
I checked it with my oscilloscope and measured 43ms.
mahowik wrote:p.s. I suppose you have used some code base from dongs post viewtopic.php?f=7&t=1929&start=10#p19309 ?
There is an issue with calculation of the GPS lon/lat. I will post tested code (at least on turnigy+er9x) from home (at work now)...
I don't have a GPS receiver at the moment. Can you please test the following code changes?
Code: Select all
Datas_Longitude_bp = abs(GPS_coord[LON]) / 100000;
Datas_Longitude_ap = abs((GPS_coord[LON])/10) % 10000;
Datas_E_W = GPS_coord[LON] < 0 ? 'W' : 'E';
Datas_Latitude_bp = abs(GPS_coord[LAT]) / 100000;
Datas_Latitude_ap = abs((GPS_coord[LAT])/10) % 10000;
Datas_N_S = GPS_coord[LAT] < 0 ? 'S' : 'N';
mahowik wrote:Also are you planning to use some kind of map tracking and logging based on received telemetry?
In the future I will log the Datas. Perhaps I will integrate in my transmitter bluetooth and a uC which receives all datas and simulate a FC. Then I connect a PC and can use MultiWiiConf or any other MultiWii Gui for reading the datas. But these are only rough ideas.
mahowik wrote:And one more question In case of you are using the D8R-II plus receiver, have you tried to upgrade this to D8R-XP to get RSSI (e.g. for OSD) and CPPM output?
I've a D8RSP with RSSI and CPPM
Re: Direct Frsky telemtry data from MW FC
tobi86 wrote:It must take much more than 10ms if you don't use interrupts and transfer datas with 9600 baud!
1 Bit takes 104 us
--> 1 Byte (8 bit + 1 start bit + 1 stop bit) = 1 ms
--> One Value (1 * Header, 1 * Data ID, 2 * Data) 4 Byte = 4 ms
--> only GPS Datas with 10 Data IDs (Position 6, speed 2, alt 2) = 10 * 4 ms = 40 ms!!! (Data frame tail, and RS232 waittime not included)
I checked it with my oscilloscope and measured 43ms.
I'm not expert in microcontrollers programming but actually as i see SerialWrite() also based on interrupt... So what is the advantage of your implementation? Because you have "separate" interrupt only for serial port 3?
Code: Select all
void SerialWrite(uint8_t port,uint8_t c){
switch (port) {
case 0: serialize8(c);UartSendData(); break; // Serial0 TX is driven via a buffer and a background intterupt
#if defined(MEGA) || defined(PROMICRO)
case 1: while (!(UCSR1A & (1 << UDRE1))) ; UDR1 = c; break; // Serial1 Serial2 and Serial3 TX are not driven via interrupts
#endif
#if defined(MEGA)
case 2: while (!(UCSR2A & (1 << UDRE2))) ; UDR2 = c; break;
case 3: while (!(UCSR3A & (1 << UDRE3))) ; UDR3 = c; break;
#endif
}
}
tobi86 wrote:I don't have a GPS receiver at the moment. Can you please test the following code changes?
Yes, this what i got last night, i.e. it's correct.
tobi86 wrote:In the future I will log the Datas. Perhaps I will integrate in my transmitter bluetooth and a uC which receives all datas and simulate a FC. Then I connect a PC and can use MultiWiiConf or any other MultiWii Gui for reading the datas. But these are only rough ideas.
I have similar ideas Here is details if you can read russian http://forum.rcdesign.ru/f90/thread287324.html In other case google helps!
thx-
Alex
Re: Direct Frsky telemtry data from MW FC
Thanks for testing the GPS part. I've changed the code in the post.
In the original MultiWii code only Serial Port0 (the port used for programming and config with the FTDI) is driven via interrupts. I configured serial3 in FrSky_telemetry.ino like serial port0 of the original Multiwii version. I don't use SerialWrite(). I use instead write_FrSky8() and at the end of this function I activate the interrupt.
mahowik wrote:I'm not expert in microcontrollers programming but actually as i see SerialWrite() also based on interrupt... So what is the advantage of your implementation? Because you have "separate" interrupt only for serial port 3?
In the original MultiWii code only Serial Port0 (the port used for programming and config with the FTDI) is driven via interrupts. I configured serial3 in FrSky_telemetry.ino like serial port0 of the original Multiwii version. I don't use SerialWrite(). I use instead write_FrSky8() and at the end of this function I activate the interrupt.
Re: Direct Frsky telemtry data from MW FC
You guys write about using a simple inverter for the TTL to RS232 (why Frsky, why?!?!) conversion. Does that really work? I mean you'd normaly need negative voltage for a 1 ... don't you? I bought a level converter that is really big, so I am interested in shrinking its size (and use your code for telemetry).
I already fitted my TX with a bluetooth dongle to transmit the received telemetry to an android phone. There are two apps in Google Play, but both are rather crude ... but they do their job. Having more data than just the voltage and rssi would be really helpful
I already fitted my TX with a bluetooth dongle to transmit the received telemetry to an android phone. There are two apps in Google Play, but both are rather crude ... but they do their job. Having more data than just the voltage and rssi would be really helpful
Re: Direct Frsky telemtry data from MW FC
tobi86 wrote:In the original MultiWii code only Serial Port0 (the port used for programming and config with the FTDI) is driven via interrupts. I configured serial3 in FrSky_telemetry.ino like serial port0 of the original Multiwii version. I don't use SerialWrite(). I use instead write_FrSky8() and at the end of this function I activate the interrupt.
Thank a lot for your solution! I will try it tonight and will back with results here.
Alex
Re: Direct Frsky telemtry data from MW FC
Sebbi wrote:You guys write about using a simple inverter for the TTL to RS232 (why Frsky, why?!?!) conversion. Does that really work? I mean you'd normaly need negative voltage for a 1 ... don't you? I bought a level converter that is really big, so I am interested in shrinking its size (and use your code for telemetry).
frsky can recognize normal TTL but inverted
http://9xforums.com/forum/viewtopic.php?f=5&t=632
logic inverter:
http://code.google.com/p/gruvin9x/wiki/ ... _Interface
you need only FrSky RX part of that...
Re: Direct Frsky telemtry data from MW FC
So I tested this and can say that is works fine (take no more than 2-3ms in jumps!), but have not checked this in real flight though...
I made some changes according to V2.0 of "Frame Protocol of FrSky Telemetry Hub System" http://www.frsky-rc.com/uploadfile/2012 ... 254960.pdf
- e.g. it doesn't make sense to send GPS_speed and Course every 500ms because frsky receiver will send it every 1 sec.
and also taking into account er9x-frsky firmware:
- it doesn't need to send E/W and N/S for GPS position, as it's not displayed with er9x-frsky. Instead of that it's possible not remove the sign for values before point and sign will be displayed before '=' ...
- Temperature1 was used for "Distance_to_home" because it's displayed by default with er9x-frsky (custom screen is not stored to eeprom unfortunaly... i have er9x-r767 version)
- Start_altitude don't need with er9x-frsky because it's possible do the same by pressing 'Menu' button and it takes an offset to know zero point
other:
- also removed unnecessary data send, e.g. zero values after point
- as for me more usefull to have rcCommand[THROTTLE] as RPM, e.g. to know the real hover point to set MID throttle expo...
I made some changes according to V2.0 of "Frame Protocol of FrSky Telemetry Hub System" http://www.frsky-rc.com/uploadfile/2012 ... 254960.pdf
- e.g. it doesn't make sense to send GPS_speed and Course every 500ms because frsky receiver will send it every 1 sec.
and also taking into account er9x-frsky firmware:
- it doesn't need to send E/W and N/S for GPS position, as it's not displayed with er9x-frsky. Instead of that it's possible not remove the sign for values before point and sign will be displayed before '=' ...
- Temperature1 was used for "Distance_to_home" because it's displayed by default with er9x-frsky (custom screen is not stored to eeprom unfortunaly... i have er9x-r767 version)
- Start_altitude don't need with er9x-frsky because it's possible do the same by pressing 'Menu' button and it takes an offset to know zero point
other:
- also removed unnecessary data send, e.g. zero values after point
- as for me more usefull to have rcCommand[THROTTLE] as RPM, e.g. to know the real hover point to set MID throttle expo...
Code: Select all
// **********************
// FrSky telemetry
// **********************
#if defined(TELEMETRY_FRSKY)
// Serial config datas
#define TELEMETRY_FRSKY_SERIAL 3
#define TELEMETRY_FRSKY_BAUD 9600
// Interrupt
#define ISR_FRSKY ISR(USART3_UDRE_vect)
// Ringbuffer
#define FRSKY_BUFFER_SIZE 150
static uint8_t bufFrSky[FRSKY_BUFFER_SIZE];
static volatile uint8_t headTXFrSky;
static volatile uint8_t tailTXFrSky;
// Timing
#define Time_telemetry_send 125000
static uint8_t cycleCounter = 0;
static uint32_t FrSkyTime = 0;
// Frame protocol
#define Protocol_Header 0x5E
#define Protocol_Tail 0x5E
// Data Ids (bp = before point; af = after point)
// Official data IDs
#define ID_GPS_altidute_bp 0x01
#define ID_GPS_altidute_ap 0x09
#define ID_Temprature1 0x02
#define ID_RPM 0x03
#define ID_Fuel_level 0x04
#define ID_Temprature2 0x05
#define ID_Volt 0x06
#define ID_Altitude_bp 0x10
#define ID_Altitude_ap 0x21
#define ID_GPS_speed_bp 0x11
#define ID_GPS_speed_ap 0x19
#define ID_Longitude_bp 0x12
#define ID_Longitude_ap 0x1A
#define ID_E_W 0x22
#define ID_Latitude_bp 0x13
#define ID_Latitude_ap 0x1B
#define ID_N_S 0x23
#define ID_Course_bp 0x14
#define ID_Course_ap 0x24
#define ID_Date_Month 0x15
#define ID_Year 0x16
#define ID_Hour_Minute 0x17
#define ID_Second 0x18
#define ID_Acc_X 0x24
#define ID_Acc_Y 0x25
#define ID_Acc_Z 0x26
#define ID_Voltage_Amp_bp 0x3A
#define ID_Voltage_Amp_ap 0x3B
#define ID_Current 0x28
// User defined data IDs
#define ID_Gyro_X 0x40
#define ID_Gyro_Y 0x41
#define ID_Gyro_Z 0x42
void configure_FrSky()
{
SerialOpen(TELEMETRY_FRSKY_SERIAL,TELEMETRY_FRSKY_BAUD);
}
// Interrupt
ISR_FRSKY
{
uint8_t Tail = tailTXFrSky;
if (headTXFrSky != Tail)
{
if (++Tail >= FRSKY_BUFFER_SIZE)
{
Tail = 0;
}
tailTXFrSky = Tail;
UDR3 = bufFrSky[Tail]; // Transmit next byte in the ring
}
if (Tail == headTXFrSky) UCSR3B &= ~(1<<UDRIE3); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
}
// Main function FrSky telemetry
void telemetry_frsky()
{
if (currentTime > FrSkyTime ) //
{
FrSkyTime = currentTime + Time_telemetry_send;
cycleCounter++;
// Datas sent every 125 ms
//send_Accel();
//sendDataTail();
if ((cycleCounter % 4) == 0)
{
// Datas sent every 500ms
send_Altitude();
send_RPM();
//send_Cell_volt();
sendDataTail();
}
if ((cycleCounter % 8) == 0)
{
// Datas sent every 1s
//send_Time();
//send_Course();
send_GPS_speed();
send_GPS_position();
send_GPS_altitude();
send_Temperature1(); // Distance_to_home
//send_Fuel_level();
// send_Voltage_ampere();
sendDataTail();
}
if (cycleCounter == 40)
{
// Datas sent every 5s
send_Temperature2(); // num of Sats
sendDataTail();
cycleCounter = 0;
}
}
}
void write_FrSky8(uint8_t Data)
{
uint8_t Head = headTXFrSky;
if (++Head >= FRSKY_BUFFER_SIZE) Head = 0;
bufFrSky[Head] = Data;
headTXFrSky = Head;
UCSR3B |= (1<<UDRIE3); // Enable Interrupt
}
void write_FrSky16(uint16_t Data)
{
uint8_t Data_send;
Data_send = Data;
write_FrSky8(Data_send);
Data_send = Data >> 8 & 0xff;
write_FrSky8(Data_send);
}
static void sendDataHead(uint8_t Data_id)
{
write_FrSky8(Protocol_Header);
write_FrSky8(Data_id);
}
static void sendDataTail(void)
{
write_FrSky8(Protocol_Tail);
}
//*********************************************************************************
//----------------- Telemetrie Datas ------------------------------------------
//*********************************************************************************
// GPS altitude
void send_GPS_altitude(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
int16_t Datas_GPS_altidute_bp;
//uint16_t Datas_GPS_altidute_ap;
Datas_GPS_altidute_bp = GPS_altitude;
//Datas_GPS_altidute_ap = 0;
sendDataHead(ID_GPS_altidute_bp);
write_FrSky16(Datas_GPS_altidute_bp);
//sendDataHead(ID_GPS_altidute_ap);
//write_FrSky16(Datas_GPS_altidute_ap);
}
}
// Temperature
void send_Temperature2(void)
{
int16_t Datas_Temprature2;
Datas_Temprature2 = GPS_numSat; // Number of Satalits alias Temp2
sendDataHead(ID_Temprature2);
write_FrSky16(Datas_Temprature2);
}
// RPM
void send_RPM(void)
{
uint16_t Datas_RPM = 0;
/*for (uint8_t i=0;i<NUMBER_MOTOR;i++)
{
Datas_RPM += motor[i];
}
Datas_RPM = (Datas_RPM / NUMBER_MOTOR) / 30; // RPM
*/
Datas_RPM = rcCommand[THROTTLE] / 3;
sendDataHead(ID_RPM);
write_FrSky16(Datas_RPM);
}
// Fuel level
void send_Fuel_level(void)
{
uint16_t Datas_Fuel_level;
Datas_Fuel_level = 0;
sendDataHead(ID_Fuel_level);
write_FrSky16(Datas_Fuel_level);
}
// Temperature 1
void send_Temperature1(void)
{
if (f.GPS_FIX_HOME)
{
int16_t Datas_Temprature1;
Datas_Temprature1 = GPS_distanceToHome; // Distance to home alias Temp1
sendDataHead(ID_Temprature1);
write_FrSky16(Datas_Temprature1);
}
}
// Cell voltage
void send_Cell_volt(void)
{
uint16_t Datas_Volt;
Datas_Volt = 0; // 0.01v / 0 ~ 4.2v
sendDataHead(ID_Volt);
write_FrSky16(Datas_Volt);
}
// Altitude
void send_Altitude(void)
{
uint16_t Datas_altitude_bp;
//uint16_t Datas_altitude_ap;
/*static uint16_t Start_altitude;
if (!f.ARMED)
{
Start_altitude = EstAlt / 100;
}
Datas_altitude_bp = (EstAlt / 100) - Start_altitude;
Datas_altitude_ap = (EstAlt % 100);*/
Datas_altitude_bp = (EstAlt / 100);
sendDataHead(ID_Altitude_bp);
write_FrSky16(Datas_altitude_bp);
//sendDataHead(ID_Altitude_ap);
//write_FrSky16(Datas_altitude_ap);
}
// GPS speed
void send_GPS_speed(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
uint16_t Datas_GPS_speed_bp;
//uint16_t Datas_GPS_speed_ap;
Datas_GPS_speed_bp = GPS_speed * 0.036;
//Datas_GPS_speed_ap = 0;
sendDataHead(ID_GPS_speed_bp);
write_FrSky16(Datas_GPS_speed_bp);
//sendDataHead(ID_GPS_speed_ap);
//write_FrSky16(Datas_GPS_speed_ap);
}
}
// GPS position
void send_GPS_position(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
uint16_t Datas_Longitude_bp;
uint16_t Datas_Longitude_ap;
//uint16_t Datas_E_W;
uint16_t Datas_Latitude_bp;
uint16_t Datas_Latitude_ap;
//uint16_t Datas_N_S;
Datas_Longitude_bp = (GPS_coord[LON]) / 100000;
Datas_Longitude_ap = abs((GPS_coord[LON])/10) % 10000;
//Datas_E_W = GPS_coord[LON] < 0 ? 'W' : 'E';
Datas_Latitude_bp = (GPS_coord[LAT]) / 100000;
Datas_Latitude_ap = abs((GPS_coord[LAT])/10) % 10000;
//Datas_N_S = GPS_coord[LAT] < 0 ? 'S' : 'N';
sendDataHead(ID_Longitude_bp);
write_FrSky16(Datas_Longitude_bp);
sendDataHead(ID_Longitude_ap);
write_FrSky16(Datas_Longitude_ap);
//sendDataHead(ID_E_W);
//write_FrSky16(Datas_E_W);
sendDataHead(ID_Latitude_bp);
write_FrSky16(Datas_Latitude_bp);
sendDataHead(ID_Latitude_ap);
write_FrSky16(Datas_Latitude_ap);
//sendDataHead(ID_N_S);
//write_FrSky16(Datas_N_S);
}
}
// Course
void send_Course(void)
{
uint16_t Datas_Course_bp;
uint16_t Datas_Course_ap;
Datas_Course_bp = heading;
Datas_Course_ap = 0;
sendDataHead(ID_Course_bp);
write_FrSky16(Datas_Course_bp);
sendDataHead(ID_Course_ap);
write_FrSky16(Datas_Course_ap);
}
// Time
void send_Time(void)
{
uint32_t seconds_since_start = millis() / 1000;
uint16_t Datas_Date_month;
uint16_t Datas_Year;
uint16_t Datas_Minutes_hours;
uint16_t Datas_seconds;
Datas_Date_month = 0;
Datas_Year = 12;
Datas_Minutes_hours = (seconds_since_start / 60) % 60;
Datas_seconds = seconds_since_start % 60;
sendDataHead(ID_Hour_Minute);
write_FrSky16(Datas_Minutes_hours);
sendDataHead(ID_Second);
write_FrSky16(Datas_seconds);
}
// ACC
void send_Accel(void)
{
int16_t Datas_Acc_X;
int16_t Datas_Acc_Y;
int16_t Datas_Acc_Z;
Datas_Acc_X = ((float)accSmooth[0] / acc_1G) * 1000;
Datas_Acc_Y = ((float)accSmooth[1] / acc_1G) * 1000;
Datas_Acc_Z = ((float)accSmooth[2] / acc_1G) * 1000;
sendDataHead(ID_Acc_X);
write_FrSky16(Datas_Acc_X);
sendDataHead(ID_Acc_Y);
write_FrSky16(Datas_Acc_Y);
sendDataHead(ID_Acc_Z);
write_FrSky16(Datas_Acc_Z);
}
// Voltage (Ampere Sensor)
void send_Voltage_ampere(void)
{
uint16_t Datas_Voltage_Amp_bp;
uint16_t Datas_Voltage_Amp_ap;
uint16_t Datas_Current;
Datas_Voltage_Amp_bp = 0;
Datas_Voltage_Amp_ap = 0;
Datas_Current = 0;
sendDataHead(ID_Voltage_Amp_bp);
write_FrSky16(Datas_Voltage_Amp_bp);
sendDataHead(ID_Voltage_Amp_ap);
write_FrSky16(Datas_Voltage_Amp_ap);
sendDataHead(ID_Current);
write_FrSky16(Datas_Current);
}
#endif
Re: Direct Frsky telemtry data from MW FC
mahowik wrote:- e.g. it doesn't make sense to send GPS_speed and Course every 500ms because frsky receiver will send it every 1 sec.
No, YOU can decide how often the Datas will be send. Only if you use the FrSky sensor hub, the Datas will be send as defined in the source code of this hub. If you copy GPS speed for example in the section 125 ms it will of course be send every 125ms.
Re: Direct Frsky telemtry data from MW FC
tobi86 wrote:mahowik wrote:- e.g. it doesn't make sense to send GPS_speed and Course every 500ms because frsky receiver will send it every 1 sec.
No, YOU can decide how often the Datas will be send. Only if you use the FrSky sensor hub, the Datas will be send as defined in the source code of this hub. If you copy GPS speed for example in the section 125 ms it will of course be send every 125ms.
We can simple check this practically but i suppose that frsky send the frames (1, 2, 3) according to hub protocol timeouts because as I remember it has only 1200 baud downlink with transmitter, but not 9600 which is used for communication with receiver...
Re: Direct Frsky telemtry data from MW FC
mahowik - there's a bug in the baseflight implementation of frsky tele and yours - you need to do xor-stuffing when the output sequence has 0x5e in it - check the pDF and er9x implementation for example. Ive been meaning to fix this in my code, not often occuring condition but still needs to be taken care of.
Re: Direct Frsky telemtry data from MW FC
dongs wrote:mahowik - there's a bug in the baseflight implementation of frsky tele and yours - you need to do xor-stuffing when the output sequence has 0x5e in it - check the pDF and er9x implementation for example. Ive been meaning to fix this in my code, not often occuring condition but still needs to be taken care of.
hi dongs,
yes, you are right! thanks, we need to take this into account... from "Frame Protocol of FrSky Telemetry Hub System (V2.0)" doc:
2. Byte stuffing method:
2.1 Output:
Byte in frame has value 0x5E is changed into 2 bytes: 0x5D 0x3E
Byte in frame has value 0x5D is changed into 2 bytes: 0x5D 0x3D
2.2 Input:
When byte 0x5D is received, discard this byte, and the next byte is XORed with 0x60.
Re: Direct Frsky telemtry data from MW FC
@tobi86: you was right... frsky receiver not so clever as I supposed before I have success with passing GPS speed every 125ms...
Re: Direct Frsky telemtry data from MW FC
Hi.
First of all.... thanks all for yet another improvement to the MultiWii code
I have a Flyduino Mega and a FrSky equipped 9x with ER9X firmware. My receiver is a D8R-II
I went ahead and made a small transistor based inverter.
It gets 5V from the Flyduino, and I took the GND from the D8R-II, because that way, I could use a normal 3wire servo lead on the Flyduino. The Flyduino and the receiver share the GND already through the PPM lead.
I soldered the transistor and the two resistors straight together, inline in a servo cable. Isolated all with some heatshrink. All working fine. (just need to label one side, so you know which side goes where next time you disconnect everything).
Just came back from a flight.... some observations
GPS data shows fine.
Distance from home(T1) also seems correct (units shown are probably in meters)
Ground speed show what I think is Km/h. The units on the GPS screen show as kts, even though I set it to metric.
ALT does receive data, but it seems there's a mixup between units in the ER9X firmware (r767).
Alt on the GPS lat/lon page is different from Alt or Galt on the custom screen. Alt on the custom screen seems to represent meters, but it does not start from zero (mine started at -39 (meters?).
I guess this is ER9X related.... The Alt on the custom screen seems to behave correctly, and show meters. It just does not reset to zero on start.
<EDIT> After a look in the code, it seems the Alt is the altitude from the Baro. Galt = GPS altitude....<END EDIT>
The RPM are shown as a 5 digit number, which represent throttle stick microseconds. It does not show baro PID adjustments. The version from tobi86 showed it as a 4 digit number, which seemed to represent motor speed. I liked tobi's version better (also because its only 4 digits, so 'fits' better on the screen), but that just my opinion....
Having this live data stream coming back from the copter, also proved what I was suspecting already for some time.....
My GPS seems to loose lock quite often, or may suddenly jump a lot..... On a few occasions, the location moved by nearly a 100 meters.... when RTH, it would move to somewere else.... Wherever it went to, once it arrived there, the distance to home was indeed 0...so it assumed that was home....
This all seems GPS related.... the FrSky telemetry just made it possible to actually see what was going on all the time.
Regarding the ER9X code..... the custom screen is nice.... just a shame in the current version it is not stored in eprom...
Some thoughts for possible improvements:
- there are 6 voltage reported (V1..V6). I guess they are cell voltages. Could we put the battery voltage, as measured by the multiwii on one of them (from the Vbat code) ? I'm also using the A2 input for the battery voltage, but why not show both.
- Could we show the powermeter reading as Mah2 (or 'fuel'). I assume, the amp sensor, once implemented, will show up on Mah1 ?
<EDIT> made some small modification to do just that..... seems to work, I get the powermeter sum in the fuel....
I also put vbat in amps.... could not get it working in one of the voltages, but hey.... it works for me <END EDIT>
Let's hope Alex will include this in the next release
Thanks again for this great code !
First of all.... thanks all for yet another improvement to the MultiWii code
I have a Flyduino Mega and a FrSky equipped 9x with ER9X firmware. My receiver is a D8R-II
I went ahead and made a small transistor based inverter.
It gets 5V from the Flyduino, and I took the GND from the D8R-II, because that way, I could use a normal 3wire servo lead on the Flyduino. The Flyduino and the receiver share the GND already through the PPM lead.
I soldered the transistor and the two resistors straight together, inline in a servo cable. Isolated all with some heatshrink. All working fine. (just need to label one side, so you know which side goes where next time you disconnect everything).
Just came back from a flight.... some observations
GPS data shows fine.
Distance from home(T1) also seems correct (units shown are probably in meters)
Ground speed show what I think is Km/h. The units on the GPS screen show as kts, even though I set it to metric.
ALT does receive data, but it seems there's a mixup between units in the ER9X firmware (r767).
Alt on the GPS lat/lon page is different from Alt or Galt on the custom screen. Alt on the custom screen seems to represent meters, but it does not start from zero (mine started at -39 (meters?).
I guess this is ER9X related.... The Alt on the custom screen seems to behave correctly, and show meters. It just does not reset to zero on start.
<EDIT> After a look in the code, it seems the Alt is the altitude from the Baro. Galt = GPS altitude....<END EDIT>
The RPM are shown as a 5 digit number, which represent throttle stick microseconds. It does not show baro PID adjustments. The version from tobi86 showed it as a 4 digit number, which seemed to represent motor speed. I liked tobi's version better (also because its only 4 digits, so 'fits' better on the screen), but that just my opinion....
Having this live data stream coming back from the copter, also proved what I was suspecting already for some time.....
My GPS seems to loose lock quite often, or may suddenly jump a lot..... On a few occasions, the location moved by nearly a 100 meters.... when RTH, it would move to somewere else.... Wherever it went to, once it arrived there, the distance to home was indeed 0...so it assumed that was home....
This all seems GPS related.... the FrSky telemetry just made it possible to actually see what was going on all the time.
Regarding the ER9X code..... the custom screen is nice.... just a shame in the current version it is not stored in eprom...
Some thoughts for possible improvements:
- there are 6 voltage reported (V1..V6). I guess they are cell voltages. Could we put the battery voltage, as measured by the multiwii on one of them (from the Vbat code) ? I'm also using the A2 input for the battery voltage, but why not show both.
- Could we show the powermeter reading as Mah2 (or 'fuel'). I assume, the amp sensor, once implemented, will show up on Mah1 ?
<EDIT> made some small modification to do just that..... seems to work, I get the powermeter sum in the fuel....
I also put vbat in amps.... could not get it working in one of the voltages, but hey.... it works for me <END EDIT>
Let's hope Alex will include this in the next release
Thanks again for this great code !
Re: Direct Frsky telemtry data from MW FC
wilco1967 wrote:Regarding the ER9X code..... the custom screen is nice.... just a shame in the current version it is not stored in eprom...
Yes, this is a problem of er9x, actually I switched to open9x because it stores the datas in eeprom and you have more possibilities with FrSky telemetry, for example telemetry bars or more values like the actual course of the magnometer.
wilco1967 wrote:- there are 6 voltage reported (V1..V6). I guess they are cell voltages. Could we put the battery voltage, as measured by the multiwii on one of them (from the Vbat code) ? I'm also using the A2 input for the battery voltage, but why not show both.
The six voltages are the datas of the FLVS-01. I will integate the possibilty to connect this sensor and/or the FAS100 current sensor to the FC that these values will also send down to the transmitter.
Re: Direct Frsky telemtry data from MW FC
i hope in r769 it stores the datas in eeprom already... last changes:
http://code.google.com/p/er9x/source/br ... /frsky.cpp
FAS100 fixes,Voice on A1/A2
fixes,Inactivity alarm fix,TelemetrEZ
support, flash saving
but need to try to make sure though...
Actually open9x in most cases the same or it's fully another firmware (features, gui etc.)?
http://code.google.com/p/er9x/source/br ... /frsky.cpp
FAS100 fixes,Voice on A1/A2
fixes,Inactivity alarm fix,TelemetrEZ
support, flash saving
but need to try to make sure though...
Actually open9x in most cases the same or it's fully another firmware (features, gui etc.)?
Re: Direct Frsky telemtry data from MW FC
dongs wrote:mahowik - there's a bug in the baseflight implementation of frsky tele and yours - you need to do xor-stuffing when the output sequence has 0x5e in it - check the pDF and er9x implementation for example. Ive been meaning to fix this in my code, not often occuring condition but still needs to be taken care of.
I'm not sure, if I understood the byte stuffing method correctly, if not, can anyone explain me how it works??? I implementated it in the following code version V0.2 of frSky_telemetry.ino (the other changes as explained in my post on page 2 are also still necessary). I also added the possibility to send the vbat value to the transmitter (Data ID 0x3A FAS100). I will do the implementation of FrSky voltage sensor FLVS01 and current sensor FAS100 the next days .
Code: Select all
// ****************************************************************
// FrSky telemetry
// Version: 0.2
// Date: 14/08/2012
// Changes: V0.2: - Byte stuffing added
// - vBat will be send, if "#define FAS_100" is comment out
// V0.1: - First release
// ****************************************************************
#if defined(TELEMETRY_FRSKY)
// user defines
//#define FAS_100 //if commment out, MultiWii vBat voltage will be send instead of FrSky FAS 100 voltage
// Serial config datas
#define TELEMETRY_FRSKY_SERIAL 3
#define TELEMETRY_FRSKY_BAUD 9600
// Interrupt
#define ISR_FRSKY ISR(USART3_UDRE_vect)
// Ringbuffer
#define FRSKY_BUFFER_SIZE 150
static uint8_t bufFrSky[FRSKY_BUFFER_SIZE];
static volatile uint8_t headTXFrSky;
static volatile uint8_t tailTXFrSky;
// Timing
#define Time_telemetry_send 125000
static uint8_t cycleCounter = 0;
static uint32_t FrSkyTime = 0;
// Frame protocol
#define Protocol_Header 0x5E
#define Protocol_Tail 0x5E
// Data Ids (bp = before point; af = after point)
// Official data IDs
#define ID_GPS_altidute_bp 0x01
#define ID_GPS_altidute_ap 0x09
#define ID_Temprature1 0x02
#define ID_RPM 0x03
#define ID_Fuel_level 0x04
#define ID_Temprature2 0x05
#define ID_Volt 0x06
#define ID_Altitude_bp 0x10
#define ID_Altitude_ap 0x21
#define ID_GPS_speed_bp 0x11
#define ID_GPS_speed_ap 0x19
#define ID_Longitude_bp 0x12
#define ID_Longitude_ap 0x1A
#define ID_E_W 0x22
#define ID_Latitude_bp 0x13
#define ID_Latitude_ap 0x1B
#define ID_N_S 0x23
#define ID_Course_bp 0x14
#define ID_Course_ap 0x24
#define ID_Date_Month 0x15
#define ID_Year 0x16
#define ID_Hour_Minute 0x17
#define ID_Second 0x18
#define ID_Acc_X 0x24
#define ID_Acc_Y 0x25
#define ID_Acc_Z 0x26
#define ID_Voltage_Amp_bp 0x3A
#define ID_Voltage_Amp_ap 0x3B
#define ID_Current 0x28
// User defined data IDs
#define ID_Gyro_X 0x40
#define ID_Gyro_Y 0x41
#define ID_Gyro_Z 0x42
void configure_FrSky()
{
SerialOpen(TELEMETRY_FRSKY_SERIAL,TELEMETRY_FRSKY_BAUD);
}
// Interrupt
ISR_FRSKY
{
uint8_t Tail = tailTXFrSky;
if (headTXFrSky != Tail)
{
if (++Tail >= FRSKY_BUFFER_SIZE)
{
Tail = 0;
}
tailTXFrSky = Tail;
UDR3 = bufFrSky[Tail]; // Transmit next byte in the ring
}
if (Tail == headTXFrSky) UCSR3B &= ~(1<<UDRIE3); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
}
// Main function FrSky telemetry
void telemetry_frsky()
{
if (currentTime > FrSkyTime ) //
{
FrSkyTime = currentTime + Time_telemetry_send;
cycleCounter++;
// Datas sent every 125 ms
send_Accel();
sendDataTail();
if ((cycleCounter % 4) == 0)
{
// Datas sent every 500ms
send_Altitude();
send_RPM();
send_Course();
send_GPS_speed();
//send_Cell_volt(); todo
sendDataTail();
}
if ((cycleCounter % 8) == 0)
{
// Datas sent every 1s
//send_Time();
send_GPS_position();
send_GPS_altitude();
send_Temperature2(); // Distance_to_home
//send_Fuel_level();
send_Voltage_ampere();
send_Temperature1(); // num of Sats
sendDataTail();
}
if (cycleCounter == 40)
{
// Datas sent every 5s
cycleCounter = 0;
}
}
}
void write_FrSky8(uint8_t Data)
{
uint8_t Head = headTXFrSky;
if (++Head >= FRSKY_BUFFER_SIZE) Head = 0;
bufFrSky[Head] = Data;
headTXFrSky = Head;
UCSR3B |= (1<<UDRIE3); // Enable Interrupt
}
void write_FrSky16(uint16_t Data)
{
uint8_t Data_send;
Data_send = Data;
check_FrSky_stuffing(Data_send);
Data_send = Data >> 8 & 0xff;
check_FrSky_stuffing(Data_send);
}
void check_FrSky_stuffing(uint8_t Data) //byte stuffing
{
if (Data == 0x5E)
{
write_FrSky8(0x5D);
write_FrSky8(0x3E);
}
else if (Data == 0x5D)
{
write_FrSky8(0x5D);
write_FrSky8(0x3D);
}
else
{
write_FrSky8(Data);
}
}
static void sendDataHead(uint8_t Data_id)
{
write_FrSky8(Protocol_Header);
write_FrSky8(Data_id);
}
static void sendDataTail(void)
{
write_FrSky8(Protocol_Tail);
}
//*********************************************************************************
//----------------- Telemetrie Datas ------------------------------------------
//*********************************************************************************
// GPS altitude
void send_GPS_altitude(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
int16_t Datas_GPS_altidute_bp;
uint16_t Datas_GPS_altidute_ap;
Datas_GPS_altidute_bp = GPS_altitude;
Datas_GPS_altidute_ap = 0;
sendDataHead(ID_GPS_altidute_bp);
write_FrSky16(Datas_GPS_altidute_bp);
sendDataHead(ID_GPS_altidute_ap);
write_FrSky16(Datas_GPS_altidute_ap);
}
}
// Temperature
void send_Temperature1(void)
{
int16_t Datas_Temprature1;
Datas_Temprature1 = GPS_numSat; // Number of Satalits alias Temp1
sendDataHead(ID_Temprature1);
write_FrSky16(Datas_Temprature1);
}
// RPM
void send_RPM(void)
{
uint16_t Datas_RPM = 0;
for (uint8_t i=0;i<NUMBER_MOTOR;i++)
{
Datas_RPM += motor[i];
}
Datas_RPM = (Datas_RPM / NUMBER_MOTOR) / 30; // RPM
sendDataHead(ID_RPM);
write_FrSky16(Datas_RPM);
}
// Fuel level
void send_Fuel_level(void)
{
uint16_t Datas_Fuel_level;
Datas_Fuel_level = 0;
sendDataHead(ID_Fuel_level);
write_FrSky16(Datas_Fuel_level);
}
// Temperature 2
void send_Temperature2(void)
{
if (f.GPS_FIX_HOME)
{
int16_t Datas_Temprature2;
Datas_Temprature2 = GPS_distanceToHome; // Distance to home alias Temp2
sendDataHead(ID_Temprature2);
write_FrSky16(Datas_Temprature2);
}
}
// Cell voltage todo !!!!!!!!!!!!!!!!!!
void send_Cell_volt(void) // Datas FrSky FLVS-01 voltage sensor
{
uint16_t Datas_Volt;
uint8_t number_of_cells = 0; // LiPo 3S = 3; LiPo 4S = 4 ...
static uint8_t cell = 0;
if (cell >= number_of_cells); cell = 0;
Datas_Volt = 0; // 0.01v / 0 ~ 4.2v
sendDataHead(ID_Volt);
write_FrSky16(Datas_Volt);
}
// Altitude
void send_Altitude(void)
{
uint16_t Datas_altitude_bp;
uint16_t Datas_altitude_ap;
static uint16_t Start_altitude;
if (!f.ARMED)
{
Start_altitude = EstAlt / 100;
}
Datas_altitude_bp = (EstAlt / 100) - Start_altitude;
Datas_altitude_ap = (EstAlt % 100);
sendDataHead(ID_Altitude_bp);
write_FrSky16(Datas_altitude_bp);
sendDataHead(ID_Altitude_ap);
write_FrSky16(Datas_altitude_ap);
}
// GPS speed
void send_GPS_speed(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
uint16_t Datas_GPS_speed_bp;
uint16_t Datas_GPS_speed_ap;
Datas_GPS_speed_bp = GPS_speed * 0.036;
Datas_GPS_speed_ap = 0;
sendDataHead(ID_GPS_speed_bp);
write_FrSky16(Datas_GPS_speed_bp);
sendDataHead(ID_GPS_speed_ap);
write_FrSky16(Datas_GPS_speed_ap);
}
}
// GPS position
void send_GPS_position(void)
{
uint16_t Datas_Longitude_bp;
uint16_t Datas_Longitude_ap;
uint16_t Datas_E_W;
uint16_t Datas_Latitude_bp;
uint16_t Datas_Latitude_ap;
uint16_t Datas_N_S;
Datas_Longitude_bp = abs(GPS_coord[LON]) / 100000;
Datas_Longitude_ap = abs((GPS_coord[LON])/10) % 10000;
Datas_E_W = GPS_coord[LON] < 0 ? 'W' : 'E';
Datas_Latitude_bp = abs(GPS_coord[LAT]) / 100000;
Datas_Latitude_ap = abs((GPS_coord[LAT])/10) % 10000;
Datas_N_S = GPS_coord[LAT] < 0 ? 'S' : 'N';
sendDataHead(ID_Longitude_bp);
write_FrSky16(Datas_Longitude_bp);
sendDataHead(ID_Longitude_ap);
write_FrSky16(Datas_Longitude_ap);
sendDataHead(ID_E_W);
write_FrSky16(Datas_E_W);
sendDataHead(ID_Latitude_bp);
write_FrSky16(Datas_Latitude_bp);
sendDataHead(ID_Latitude_ap);
write_FrSky16(Datas_Latitude_ap);
sendDataHead(ID_N_S);
write_FrSky16(Datas_N_S);
}
// Course
void send_Course(void)
{
uint16_t Datas_Course_bp;
uint16_t Datas_Course_ap;
Datas_Course_bp = heading;
Datas_Course_ap = 0;
sendDataHead(ID_Course_bp);
write_FrSky16(Datas_Course_bp);
sendDataHead(ID_Course_ap);
write_FrSky16(Datas_Course_ap);
}
// Time
void send_Time(void)
{
uint32_t seconds_since_start = millis() / 1000;
uint16_t Datas_Date_month;
uint16_t Datas_Year;
uint16_t Datas_Minutes_hours;
uint16_t Datas_seconds;
Datas_Date_month = 0;
Datas_Year = 12;
Datas_Minutes_hours = (seconds_since_start / 60) % 60;
Datas_seconds = seconds_since_start % 60;
sendDataHead(ID_Hour_Minute);
write_FrSky16(Datas_Minutes_hours);
sendDataHead(ID_Second);
write_FrSky16(Datas_seconds);
}
// ACC
void send_Accel(void)
{
int16_t Datas_Acc_X;
int16_t Datas_Acc_Y;
int16_t Datas_Acc_Z;
Datas_Acc_X = ((float)accSmooth[0] / acc_1G) * 1000;
Datas_Acc_Y = ((float)accSmooth[1] / acc_1G) * 1000;
Datas_Acc_Z = ((float)accSmooth[2] / acc_1G) * 1000;
sendDataHead(ID_Acc_X);
write_FrSky16(Datas_Acc_X);
sendDataHead(ID_Acc_Y);
write_FrSky16(Datas_Acc_Y);
sendDataHead(ID_Acc_Z);
write_FrSky16(Datas_Acc_Z);
}
// Voltage (Ampere Sensor)
void send_Voltage_ampere(void)
{
#if defined (FAS_100) // todo !!!!!!!!!!!!!!!!!
{
uint16_t Datas_Voltage_Amp_bp;
uint16_t Datas_Voltage_Amp_ap;
uint16_t Datas_Current;
Datas_Voltage_Amp_bp = 0;
Datas_Voltage_Amp_ap = 0;
Datas_Current = 0;
sendDataHead(ID_Voltage_Amp_bp);
write_FrSky16(Datas_Voltage_Amp_bp);
sendDataHead(ID_Voltage_Amp_ap);
write_FrSky16(Datas_Voltage_Amp_ap);
sendDataHead(ID_Current);
write_FrSky16(Datas_Current);
}
#else // use vBat
{
uint16_t Datas_Voltage_vBat_bp;
uint16_t Datas_Voltage_vBat_ap;
uint16_t voltage;
voltage = (vbat * 110) / 21;
Datas_Voltage_vBat_bp = voltage / 100;
Datas_Voltage_vBat_ap = ((voltage % 100) + 5) / 10;
sendDataHead(ID_Voltage_Amp_bp);
write_FrSky16(Datas_Voltage_vBat_bp);
sendDataHead(ID_Voltage_Amp_ap);
write_FrSky16(Datas_Voltage_vBat_ap);
}
#endif
}
#endif
Re: Direct Frsky telemtry data from MW FC
tobi86 wrote:I'm not sure, if I understood the byte stuffing method correctly, if not, can anyone explain me how it works???
Yes, it's correct. It gives possibility:
1) to pass 0x5E as data (not as header) with replacing it to 0x5D 0x3E
2) to pass 0x5D as data (with replacing it to 0x5D 0x3D) because 0x5D discarded/ignored on RX side...
Where on RX side second byte is decoded via XORing with 0x60:
1) 0x3E XOR 0x60 = 0x5E
2) 0x3D XOR 0x60 = 0x5D
thx-
Alex
Re: Direct Frsky telemtry data from MW FC
Alexinparis wrote:My dream would be a uplink telemetry based on frsky without impacting the 8 first RC channels.
Dreams are closer than we think they are:
OpenLRS tx- rx semi-duplex transmitter- receiver sistem based on RFM22B transciever is an arduino open source project witch allows to customize the data frame for bi-directional communication over RC link. The latest implementation on 433/470 Mhz (thanks to Thunded) has more than 4 Km ground range tested by many users .
Implementing RFM22B on a mega board (already did it Melih from flytron) would boost the potential of multiwii autonomous flight with waypoint navi.
ps.
price of RFM22B transciever is about 4 USD
links to OLRS http://flytron.com/16-openlrs
Re: Direct Frsky telemtry data from MW FC
Please can someone clear me the inverter type what buy thanks
Re: Direct Frsky telemtry data from MW FC
OK will be this code in Multiwii ? looking to 2.1 and no code is there. Thanks
Re: Direct Frsky telemtry data from MW FC
janekx wrote:Please can someone clear me the inverter type what buy thanks
You can make a simple inverter with a ordinary NPN transistor and 2 resistors..... see my post on the previous page....
If you don't want to order a 0.05 $ transistor, and pay 5 $ for postage, you could probably find a working transistor if you open up some old electronic device, and do a bit of googling on the type numbers to find one that is a NPN transistor.....
see this link for some explanation (bottom of the page)
http://www.kpsec.freeuk.com/trancirc.htm
The code is not (yet ?) contained in 2.1.... but you can simply add it yourselve, as explained earlier in this thread.
Re: Direct Frsky telemtry data from MW FC
Thanks I ordered a few days ago Serial Port Mini RS232 to TTL Converter Adaptor Module Board MAX3232 115200bps http://www.ebay.com/itm/251103811631?ss ... 1439.l2649
Is the code still compatible with 2.1?
Yes is I looked at first page there is 2_0 and 3th page shows 2_1, why is not this realtivly simple addon in main trunk?
Is the code still compatible with 2.1?
Yes is I looked at first page there is 2_0 and 3th page shows 2_1, why is not this realtivly simple addon in main trunk?
Re: Direct Frsky telemtry data from MW FC
It's not 2.1 compatible ... or at least not compatible with the current _shared branch. I haven't tested it yet, but my changes so the code compiles again were:
FrSkyTelemtry.ino (write_FrSky8 just uses SerialWrite() now):
Init isn't needed anymore, but you need to place this somewhere in the annexCode() function:
Last, but not least in config.h ... add/change:
That's it ... most of the functions in FrSkyTelemetry.ino don't send useful information yet. Feel free to change that ... I'd like to see a more complete version of this included in MultiWii
FrSkyTelemtry.ino (write_FrSky8 just uses SerialWrite() now):
Code: Select all
// ****************************************************************
// FrSky telemetry
// Version: 0.2.1
// Date 20/09/2012
// Changes: V0.2.1: - make it work with 2.1 (shared dev)
// Date: 14/08/2012
// Changes: V0.2: - Byte stuffing added
// - vBat will be send, if "#define FAS_100" is comment out
// V0.1: - First release
// ****************************************************************
#if defined(TELEMETRY_FRSKY)
// user defines
//#define FAS_100 //if commment out, MultiWii vBat voltage will be send instead of FrSky FAS 100 voltage
// Serial config datas
#define TELEMETRY_FRSKY_SERIAL 1
#define TELEMETRY_FRSKY_BAUD 9600
// Timing
#define Time_telemetry_send 125000
static uint8_t cycleCounter = 0;
static uint32_t FrSkyTime = 0;
// Frame protocol
#define Protocol_Header 0x5E
#define Protocol_Tail 0x5E
// Data Ids (bp = before point; af = after point)
// Official data IDs
#define ID_GPS_altidute_bp 0x01
#define ID_GPS_altidute_ap 0x09
#define ID_Temprature1 0x02
#define ID_RPM 0x03
#define ID_Fuel_level 0x04
#define ID_Temprature2 0x05
#define ID_Volt 0x06
#define ID_Altitude_bp 0x10
#define ID_Altitude_ap 0x21
#define ID_GPS_speed_bp 0x11
#define ID_GPS_speed_ap 0x19
#define ID_Longitude_bp 0x12
#define ID_Longitude_ap 0x1A
#define ID_E_W 0x22
#define ID_Latitude_bp 0x13
#define ID_Latitude_ap 0x1B
#define ID_N_S 0x23
#define ID_Course_bp 0x14
#define ID_Course_ap 0x24
#define ID_Date_Month 0x15
#define ID_Year 0x16
#define ID_Hour_Minute 0x17
#define ID_Second 0x18
#define ID_Acc_X 0x24
#define ID_Acc_Y 0x25
#define ID_Acc_Z 0x26
#define ID_Voltage_Amp_bp 0x3A
#define ID_Voltage_Amp_ap 0x3B
#define ID_Current 0x28
// User defined data IDs
#define ID_Gyro_X 0x40
#define ID_Gyro_Y 0x41
#define ID_Gyro_Z 0x42
// Main function FrSky telemetry
void telemetry_frsky()
{
if (currentTime > FrSkyTime ) //
{
FrSkyTime = currentTime + Time_telemetry_send;
cycleCounter++;
// Datas sent every 125 ms
send_Accel();
sendDataTail();
if ((cycleCounter % 4) == 0)
{
// Datas sent every 500ms
send_Altitude();
send_RPM();
send_Course();
send_GPS_speed();
//send_Cell_volt(); todo
sendDataTail();
}
if ((cycleCounter % 8) == 0)
{
// Datas sent every 1s
//send_Time();
send_GPS_position();
send_GPS_altitude();
send_Temperature2(); // Distance_to_home
//send_Fuel_level();
send_Voltage_ampere();
send_Temperature1(); // num of Sats
sendDataTail();
}
if (cycleCounter == 40)
{
// Datas sent every 5s
cycleCounter = 0;
}
}
}
void write_FrSky8(uint8_t Data)
{
SerialWrite(TELEMETRY_FRSKY_SERIAL, Data);
}
void write_FrSky16(uint16_t Data)
{
uint8_t Data_send;
Data_send = Data;
check_FrSky_stuffing(Data_send);
Data_send = Data >> 8 & 0xff;
check_FrSky_stuffing(Data_send);
}
void check_FrSky_stuffing(uint8_t Data) //byte stuffing
{
if (Data == 0x5E)
{
write_FrSky8(0x5D);
write_FrSky8(0x3E);
}
else if (Data == 0x5D)
{
write_FrSky8(0x5D);
write_FrSky8(0x3D);
}
else
{
write_FrSky8(Data);
}
}
static void sendDataHead(uint8_t Data_id)
{
write_FrSky8(Protocol_Header);
write_FrSky8(Data_id);
}
static void sendDataTail(void)
{
write_FrSky8(Protocol_Tail);
}
//*********************************************************************************
//----------------- Telemetrie Datas ------------------------------------------
//*********************************************************************************
// GPS altitude
void send_GPS_altitude(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
int16_t Datas_GPS_altidute_bp;
uint16_t Datas_GPS_altidute_ap;
Datas_GPS_altidute_bp = GPS_altitude;
Datas_GPS_altidute_ap = 0;
sendDataHead(ID_GPS_altidute_bp);
write_FrSky16(Datas_GPS_altidute_bp);
sendDataHead(ID_GPS_altidute_ap);
write_FrSky16(Datas_GPS_altidute_ap);
}
}
// Temperature
void send_Temperature1(void)
{
int16_t Datas_Temprature1;
Datas_Temprature1 = GPS_numSat; // Number of Satalits alias Temp1
sendDataHead(ID_Temprature1);
write_FrSky16(Datas_Temprature1);
}
// RPM
void send_RPM(void)
{
uint16_t Datas_RPM = 0;
for (uint8_t i=0;i<NUMBER_MOTOR;i++)
{
Datas_RPM += motor[i];
}
Datas_RPM = (Datas_RPM / NUMBER_MOTOR) / 30; // RPM
sendDataHead(ID_RPM);
write_FrSky16(Datas_RPM);
}
// Fuel level
void send_Fuel_level(void)
{
uint16_t Datas_Fuel_level;
Datas_Fuel_level = 0;
sendDataHead(ID_Fuel_level);
write_FrSky16(Datas_Fuel_level);
}
// Temperature 2
void send_Temperature2(void)
{
if (f.GPS_FIX_HOME)
{
int16_t Datas_Temprature2;
Datas_Temprature2 = GPS_distanceToHome; // Distance to home alias Temp2
sendDataHead(ID_Temprature2);
write_FrSky16(Datas_Temprature2);
}
}
// Cell voltage todo !!!!!!!!!!!!!!!!!!
void send_Cell_volt(void) // Datas FrSky FLVS-01 voltage sensor
{
uint16_t Datas_Volt;
uint8_t number_of_cells = 0; // LiPo 3S = 3; LiPo 4S = 4 ...
static uint8_t cell = 0;
if (cell >= number_of_cells); cell = 0;
Datas_Volt = 0; // 0.01v / 0 ~ 4.2v
sendDataHead(ID_Volt);
write_FrSky16(Datas_Volt);
}
// Altitude
void send_Altitude(void)
{
uint16_t Datas_altitude_bp;
uint16_t Datas_altitude_ap;
static uint16_t Start_altitude;
if (!f.ARMED)
{
Start_altitude = EstAlt / 100;
}
Datas_altitude_bp = (EstAlt / 100) - Start_altitude;
Datas_altitude_ap = (EstAlt % 100);
sendDataHead(ID_Altitude_bp);
write_FrSky16(Datas_altitude_bp);
sendDataHead(ID_Altitude_ap);
write_FrSky16(Datas_altitude_ap);
}
// GPS speed
void send_GPS_speed(void)
{
if (f.GPS_FIX && GPS_numSat >= 4)
{
uint16_t Datas_GPS_speed_bp;
uint16_t Datas_GPS_speed_ap;
Datas_GPS_speed_bp = GPS_speed * 0.036;
Datas_GPS_speed_ap = 0;
sendDataHead(ID_GPS_speed_bp);
write_FrSky16(Datas_GPS_speed_bp);
sendDataHead(ID_GPS_speed_ap);
write_FrSky16(Datas_GPS_speed_ap);
}
}
// GPS position
void send_GPS_position(void)
{
uint16_t Datas_Longitude_bp;
uint16_t Datas_Longitude_ap;
uint16_t Datas_E_W;
uint16_t Datas_Latitude_bp;
uint16_t Datas_Latitude_ap;
uint16_t Datas_N_S;
Datas_Longitude_bp = abs(GPS_coord[LON]) / 100000;
Datas_Longitude_ap = abs((GPS_coord[LON])/10) % 10000;
Datas_E_W = GPS_coord[LON] < 0 ? 'W' : 'E';
Datas_Latitude_bp = abs(GPS_coord[LAT]) / 100000;
Datas_Latitude_ap = abs((GPS_coord[LAT])/10) % 10000;
Datas_N_S = GPS_coord[LAT] < 0 ? 'S' : 'N';
sendDataHead(ID_Longitude_bp);
write_FrSky16(Datas_Longitude_bp);
sendDataHead(ID_Longitude_ap);
write_FrSky16(Datas_Longitude_ap);
sendDataHead(ID_E_W);
write_FrSky16(Datas_E_W);
sendDataHead(ID_Latitude_bp);
write_FrSky16(Datas_Latitude_bp);
sendDataHead(ID_Latitude_ap);
write_FrSky16(Datas_Latitude_ap);
sendDataHead(ID_N_S);
write_FrSky16(Datas_N_S);
}
// Course
void send_Course(void)
{
uint16_t Datas_Course_bp;
uint16_t Datas_Course_ap;
Datas_Course_bp = heading;
Datas_Course_ap = 0;
sendDataHead(ID_Course_bp);
write_FrSky16(Datas_Course_bp);
sendDataHead(ID_Course_ap);
write_FrSky16(Datas_Course_ap);
}
// Time
void send_Time(void)
{
uint32_t seconds_since_start = millis() / 1000;
uint16_t Datas_Date_month;
uint16_t Datas_Year;
uint16_t Datas_Minutes_hours;
uint16_t Datas_seconds;
Datas_Date_month = 0;
Datas_Year = 12;
Datas_Minutes_hours = (seconds_since_start / 60) % 60;
Datas_seconds = seconds_since_start % 60;
sendDataHead(ID_Hour_Minute);
write_FrSky16(Datas_Minutes_hours);
sendDataHead(ID_Second);
write_FrSky16(Datas_seconds);
}
// ACC
void send_Accel(void)
{
int16_t Datas_Acc_X;
int16_t Datas_Acc_Y;
int16_t Datas_Acc_Z;
Datas_Acc_X = ((float)accSmooth[0] / acc_1G) * 1000;
Datas_Acc_Y = ((float)accSmooth[1] / acc_1G) * 1000;
Datas_Acc_Z = ((float)accSmooth[2] / acc_1G) * 1000;
sendDataHead(ID_Acc_X);
write_FrSky16(Datas_Acc_X);
sendDataHead(ID_Acc_Y);
write_FrSky16(Datas_Acc_Y);
sendDataHead(ID_Acc_Z);
write_FrSky16(Datas_Acc_Z);
}
// Voltage (Ampere Sensor)
void send_Voltage_ampere(void)
{
#if defined (FAS_100) // todo !!!!!!!!!!!!!!!!!
{
uint16_t Datas_Voltage_Amp_bp;
uint16_t Datas_Voltage_Amp_ap;
uint16_t Datas_Current;
Datas_Voltage_Amp_bp = 0;
Datas_Voltage_Amp_ap = 0;
Datas_Current = 0;
sendDataHead(ID_Voltage_Amp_bp);
write_FrSky16(Datas_Voltage_Amp_bp);
sendDataHead(ID_Voltage_Amp_ap);
write_FrSky16(Datas_Voltage_Amp_ap);
sendDataHead(ID_Current);
write_FrSky16(Datas_Current);
}
#else // use vBat
{
uint16_t Datas_Voltage_vBat_bp;
uint16_t Datas_Voltage_vBat_ap;
uint16_t voltage;
voltage = (vbat * 110) / 21;
Datas_Voltage_vBat_bp = voltage / 100;
Datas_Voltage_vBat_ap = ((voltage % 100) + 5) / 10;
sendDataHead(ID_Voltage_Amp_bp);
write_FrSky16(Datas_Voltage_vBat_bp);
sendDataHead(ID_Voltage_Amp_ap);
write_FrSky16(Datas_Voltage_vBat_ap);
}
#endif
}
#endif
Init isn't needed anymore, but you need to place this somewhere in the annexCode() function:
Code: Select all
#if defined(TELEMETRY_FRSKY) // new
telemetry_frsky();
#endif
Last, but not least in config.h ... add/change:
Code: Select all
#define TELEMETRY_FRSKY
#define SERIAL0_COM_SPEED 115200
#define SERIAL1_COM_SPEED 9600 // it's on serial 1 for me ... so set this to 9600 baud
#define SERIAL2_COM_SPEED 115200
#define SERIAL3_COM_SPEED 115200
That's it ... most of the functions in FrSkyTelemetry.ino don't send useful information yet. Feel free to change that ... I'd like to see a more complete version of this included in MultiWii
Re: Direct Frsky telemtry data from MW FC
Thanks I am affraid will be able make some changes I program more then 10y ago in C++ and only basics.
Re: Direct Frsky telemtry data from MW FC
Hi all,
Although it is probably slightly slower, Software serial might be an interresting option:
[*] Since Arduino 1.0 software serial supports inverted signaling (info http://arduino.cc/en/Reference/SoftwareSerial)
[*] Since we are only writing but not reading, we can probably save some extra time.
Has anybody tried this?
Some other thoughts for non-mega boards: we could add a co-processor reading interface data from the serial port and translating it to the Frsky module.
What are your opinions?
Cheers
Although it is probably slightly slower, Software serial might be an interresting option:
[*] Since Arduino 1.0 software serial supports inverted signaling (info http://arduino.cc/en/Reference/SoftwareSerial)
[*] Since we are only writing but not reading, we can probably save some extra time.
Has anybody tried this?
Some other thoughts for non-mega boards: we could add a co-processor reading interface data from the serial port and translating it to the Frsky module.
What are your opinions?
Cheers
Re: Direct Frsky telemtry data from MW FC
I have it all working fine with a promini.
What I've done is to change the code to only send the FrSky data when the FC is armed. That way I avoid using a software port and I keep
the serial port for Mwc configuration when disarmed.
Only drawback is that Mwc serial had to be slowed down to 9600 but I'll change that as well.
What I've done is to change the code to only send the FrSky data when the FC is armed. That way I avoid using a software port and I keep
the serial port for Mwc configuration when disarmed.
Only drawback is that Mwc serial had to be slowed down to 9600 but I'll change that as well.