The Association of Model Submariners.

Would you like to react to this message? Create an account in a few clicks or log in to continue.

* THE FORUM FOR ALL THOSE INTERESTED IN BUILDING AND OPERATING MODEL SUBMARINES *



Join the AMS - Registered Forum users can become members of the AMS and it's free ...... To join send an email with your name , address and phone number to amstreasure@googlemail.com


For a guide to past events see the "Shows and Events" section.

Papplewick Pumping Station SUBMARINE Day. 31st March - 1st April 2024.

$$$

&&&

::::

Who is online?

In total there are 4 users online :: 0 Registered, 0 Hidden and 4 Guests

None


Most users ever online was 180 on Tue Nov 05, 2019 6:03 am

Latest topics

» Newbie needs advice!
Telemetry on openLRS EmptyFri Apr 26, 2024 1:58 pm by david f

» Modulated electric fields for submarine communication in a "heads up" from Harry!
Telemetry on openLRS EmptySun Apr 21, 2024 6:09 am by geofrancis

» 868/915 Mhz as a viable frequency for submarines.
Telemetry on openLRS EmptyWed Apr 10, 2024 5:48 am by tsenecal

» Laser cut Robbe U47 conversion
Telemetry on openLRS EmptyTue Apr 09, 2024 3:40 pm by david f

» ExpressLRS - 868/915 Mhz equipment
Telemetry on openLRS EmptyTue Apr 02, 2024 3:27 pm by tsenecal

» Information on camouflage patterns for German seahund
Telemetry on openLRS EmptyFri Mar 15, 2024 4:36 pm by david f

» WW2 mini sub build
Telemetry on openLRS EmptyTue Mar 12, 2024 1:56 pm by geofrancis

» Not the hobby I expected :)
Telemetry on openLRS EmptySun Mar 10, 2024 6:30 pm by cat

» Sheerline gasket material
Telemetry on openLRS EmptyMon Feb 19, 2024 9:24 pm by Michaelc

Statistics

Our users have posted a total of 12449 messages in 1981 subjects

We have 1010 registered users

The newest registered user is Chris Shelley

3 posters

    Telemetry on openLRS

    david f
    david f
    AMS Treasurer


    Posts : 2398
    Join date : 2010-11-10
    Age : 73
    Location : Cumbria

    Telemetry on openLRS Empty Telemetry on openLRS

    Post  david f Sat Feb 13, 2016 11:32 am

    Tim S has asked me to put his latest coding on here to keep it safe.

    For those of you following this, mostly on SubPirates, Tim is working on Telemetry for subs.

    I can testify to the the fact that (an early version of this ) is working very well on my subs. Giving temperature and current draw and battery voltage.

    This is the latest version (still under development by Tim) now incorporating a depth sensor. (And yes - it works!)

    Tim's code follows: (You need to use it with Arduino IDE version 1.6.7 or above and the FrSkyTelemetryLRS library installed)


    /*
     FrSky Telemetry library LRS test
     (c) Pawelsky 20150724.
     Not for commercial use

     FrSkyTelemetry library modified to deal with LRS format (TTL level serial instead of FrSky format...
     renamed to FrSkyTelemetryLRS

     modifications by tim senecal
    */

    #include "FrSkyTelemetryLRS.h"


    #define minraw    272.0
    #define maxraw    1015.0
    #define minreal   9.0
    #define maxreal   158.0
    //#define voltsdiv  84.81
    //#define voltsdiv  102.40
    #define voltsdiv  104.2839

    //explanation of some math...
    // arduino analog pins return values from 0 to 1023...
    // which represent voltages from 0 to 5
    // pressure transducer returns 0.5 to 4.5 volts,
    // for the 5psi model, 4.5 volts represents 11.5 feet, or 138 inches, or 350 cm, or 3500 mm
    // if 1023 = 5 volts, then 921 = 4.5 volts, then 921 = 3500 mm
    // however, we need to establish what "zero" is.
    // we start with 102, which should be 0.5 volts...
    // but because we converted our sensor to a sealed sensor, it might not be 102...
    // so we have some variables and math to handle that.
    #define maxP    921
    #define milli   3514.344
    #define centi   351.434
    #define inches  138.36

    FrSkyTelemetryLRS telemetry; // Create telemetry object

    const int analogTemp1 = A0;
    const int analogTemp2 = A1;
    const int analogAmp = A2;
    const int analogVolt = A3;
    const int analogPressure = A6;

    int mVperAmp = 66;    // use 185 for 5A, 100 for 20A, and 66 for 30A
    int ACSoffset = 2500; // offset to remove negative side of range
    int baseline = 102;   // this should be the zero psi baseline for 0.5 volts, but may not be
    int init_counter = 0;

    float calc_milli = 0;
    float calc_centi = 0;
    float calc_inches = 0;

    float amperes = 0;
    float voltage = 0;
    float actual_rpm = 0;
    float calc_speed = 0;
    float Temp1 = 0;
    float Temp2 = 0;
    float depth = 0;

    void setup()
    {
     // Configure the telemetry serial port
     telemetry.begin(SERIAL_1);

     Serial.begin(9600);
    }

    void loop()
    {
     actual_rpm = 3000;
     calc_speed = 2.258;

     amperes = calc_amperage_val();
     voltage = calc_voltage_val();

     telemetry.setFasData(amperes,   // Current consumption in amps
                          voltage);  // Battery voltage in volts

     depth = calc_pressure_val();

     telemetry.setFgsData(depth);  // Fuel level in percent -  unsigned int16 - any value between 0 and 65535

     // Set LiPo voltage sensor (FLVS) data (we use two sensors to simulate 8S battery
     // (set Voltage source to Cells in menu to use this data for battery voltage)
     float v1 = voltage/2;
     float v2 = voltage/2;
     telemetry.setFlvsData(v1, v2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);  // Cell voltages in volts (cells 1-8). Cells 9-12 are not used in this example

     // Set variometer sensor (FVAS) data
     telemetry.setFvasData(depth);  // Altitude in m (can be nevative)

     // Set GPS data
     float heading = 125.22;

     telemetry.setGpsData(39.847993, -105.104269,  // Latitude and longitude in degrees decimal (positive for N/E, negative for S/W)
                          depth,                   // Altitude in m (can be negative)
                          calc_speed,              // Speed in m/s
                          heading,                 // Course over ground in degrees
                          15, 2, 19,               // Date (year - 2000, month, day)
                          12, 00, 00);             // Time (hour, minute, second) - will be affected by timezone setings in your radio

     float accel_angle_x =  2.35;
     float accel_angle_y =  4.25;
     float accel_angle_z =  3.15;

     telemetry.setTasData(accel_angle_x,     // calculated x angle
                          accel_angle_y,     // calculated y angle
                          accel_angle_z);    // calculated z angle

     // Set temperature sensor (TEMS) data, two temperatures T1 & T2

       // Set temperature sensor (TEMS) data, two temperatures T1 & T2
     Temp1 = calc_temp_val(analogTemp1);
     Temp2 = calc_temp_val(analogTemp2);
     telemetry.setTemsData(Temp1,   // Temperature #1 in degrees Celsuis (can be negative)
                           Temp2);  // Temperature #2 in degrees Celsuis (can be negative)

     // Set RPM sensor (RPMS) data
     // (set number of blades to 2 in telemetry menu to get correct rpm value)
     telemetry.setRpmsData(actual_rpm);  // Rotations per minute

     // Send the telemetry data, note that the data will only be sent for sensors
     // that had their data set at least once. Also it will only be set in defined
     // time intervals, so not necessarily at every call to send() method.
     telemetry.send();

     delay(100);  //delay for 1/10 of a second
    }


    float fmap (float x, float in_min, float in_max, float out_min, float out_max) {
     return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    }

    float calc_temp_val(int analog_pin){
     uint16_t raw_val;
     float temp, raw_float;

     temp = 0;
     raw_val = analogRead(analog_pin);
    //  raw_val = 1023 - raw_val;
     raw_float = raw_val;
     temp = fmap(raw_val, minraw, maxraw, minreal, maxreal);

    //  Serial.print("raw temp: ");
    //  Serial.print(analog_pin);
    //  Serial.print(" ");
    //  Serial.println(raw_val);

     return temp;
    }

    float calc_voltage_val(){
     int RawValue = analogRead(analogVolt);
     voltage = RawValue;

    //  Serial.print("raw volt: ");
    //  Serial.println(RawValue);
     voltage = voltage / voltsdiv; // Gets you adjusted Volts

     return voltage;
    }

    float calc_amperage_val(){
     int RawValue = analogRead(analogAmp);
     Serial.print("raw amps: ");
     Serial.println(RawValue);

     float mVoltage = RawValue;
     mVoltage = mVoltage / 1024.0;
     mVoltage = mVoltage * 5000; // Gets you mV 5000 is VCC for 5v arduino
     Serial.print("mVolts: ");
     Serial.println(mVoltage);
     amperes = abs(((mVoltage - ACSoffset) / mVperAmp));
     Serial.print("amps: ");
     Serial.println(amperes);

     return amperes;
    }

    float calc_pressure_val(){
     // read the input on analog pin 0:
     int RawValue = analogRead(analogPressure);

     // here is code where we establish what the real zero baseline is
     // we read the sensor ten times in the first second of running,
     // and take the average of those ten readings as the baseline
     if (init_counter < 10)
     {
       baseline = baseline + RawValue;
       baseline = baseline / 2;

       init_counter = init_counter + 1;

       // we then calculate what each discrete value for an analog
       // result would need to be multiplied by to reach max depth at 921
       calc_milli = (maxP - baseline) / milli;
       calc_centi = (maxP - baseline) / centi;
       calc_inches = (maxP - baseline) / inches;
     }

     int fixed_sensor = RawValue - baseline;
     Serial.print("raw depth: ");
     Serial.println(fixed_sensor);

     if (fixed_sensor < 0)
     {
       fixed_sensor = 0;
     }
     //  float depth = fixed_sensor / calc_inches;
     //  float depth = fixed_sensor / calc_centi;
     float depth = fixed_sensor / calc_milli;

     Serial.print("calced depth: ");
     Serial.println(depth);

     return depth;
    }



    Later Edit: Good point, John. I will do it once I have worked out how to do it! We can't just store a zip file but we can include a link to SubPirates.

    Later Edit: Well, I have managed to lock myself out of SubPirates (I tried changing my password!)

    So I can't download the zip file!

    Perhaps (John or Tim or any other person signed on with SubPirates) you could download the zip and keep it safe.

    It is on this page:

    http://www.subpirates.com/showthread.php?5271-Custom-Frsky-Telemetry-Hub/page3

    The link is labelled:

    FrSkyTelemetryLRS.zip

    Later Later Edit: I have a copy of the library zip files now. (Retrieved from my waste paper basket!) Now to get a password working on SubPirates again.


    Last edited by david f on Tue Feb 16, 2016 2:48 pm; edited 7 times in total
    John Wrennall
    John Wrennall
    AMS member


    Posts : 157
    Join date : 2011-11-16
    Age : 77
    Location : Leyland

    Telemetry on openLRS Empty Re: Telemetry on openLRS

    Post  John Wrennall Sat Feb 13, 2016 4:14 pm

    Hi David.

    for completeness,I think you should include Tim's latest Zip file for the FrSkyTelemetryLRS library

    John
    david f
    david f
    AMS Treasurer


    Posts : 2398
    Join date : 2010-11-10
    Age : 73
    Location : Cumbria

    Telemetry on openLRS Empty Re: Telemetry on openLRS

    Post  david f Mon Apr 15, 2019 2:23 pm

    Hi All,

    I have been having some problems using Nano clones for Telemetry and it now seems to be solved.

    The problem was that the telemetry stopped working after a few power-ups in the model (not on the bench). The TX light stopped flashing and the Nano had to be re-programmed.

    It looked very much like a power supply problem. I'm using a separate BEC - linear not switch mode.

    After a bit of a web search, I tried a  100 ohm resistor in the Arduino power supply with a 5v zener across to earth plus in the TX line a 1k resistor in line with a 5v zener connected to earth.

    This seems to have done the trick following a Sunday sail at Barrow.

    David
    david f
    david f
    AMS Treasurer


    Posts : 2398
    Join date : 2010-11-10
    Age : 73
    Location : Cumbria

    Telemetry on openLRS Empty Re: Telemetry on openLRS

    Post  david f Mon Mar 23, 2020 1:21 pm

    This looks like a solution to the nano clone problem , I have been having.

    Despite my confident assertions in my last post this problem never went away and I had stopped using Telemetry on openLRS.

    A few days ago, I substituted my one genuine Nano for the clones i had been using and so far it is holding up well, with none of the input protection components I had been using. So it does seem to be something to do with the reliability of the clones.

    I have just put an order in for 3 genuine Nano Every to test the idea further.

    (The Nano Every is the updated Nano. However my order is going to northern Italy which is having deep problems at the moment with the virus so I don't know how long it will be for me to report back.)

    David
    david f
    david f
    AMS Treasurer


    Posts : 2398
    Join date : 2010-11-10
    Age : 73
    Location : Cumbria

    Telemetry on openLRS Empty Re: Telemetry on openLRS

    Post  david f Tue Apr 07, 2020 10:55 am

    The good news is that the genuine Nano is still working well in my sub on the bench despite all my switch-ons and other attempts to get it to fail.

    So I don't know what the problem is with the nano clones. It seems to be connected to the serial port.

    So I will always use a genuine Nano in future for the telemetry application and other "mission- critical" things such as the piston tank.

    The Nano Every arrived very promptly from Northern Italy, despite the virus problems. They are very reasonably priced but  it is really a whole new processor. Several of my Nano sketches don't work on them, including telemetry. They have many more choices for the serial ports which is maybe where the trouble lies. Maybe someone can explain this?

    I include the current telemetry sketches I am using "in clear"  (Slightly modified from Tim's original. I have adopted the "KISS" principle and only ask for battery voltage! I include Tim's original  FrSkyTelemetryLRS software for completeness.

    Please note that I am using this on my Futaba 9c TX with the (now unavailable) FRSky FLD-02 LCD display and the standard Hobbyking openLRS modules with TX module set to FRSky telemetry option. Tim tells me that the Taranis TXs have everything built in but I stocked up and bought three Futaba 9c and they are holding up only too well! Maybe someone could make me an offer on the 9Cs and I can update!?
    David

    Telemetry software:

    /*
      FrSkyTelemetry library modified to deal with LRS format (TTL level serial instead of FrSky format...
      renamed to FrSkyTelemetryLRS

      Modifications by Tim Senecal

      Using Arduino ide version 1.8.9
      Modified by RDF to just give battery voltage
      This works well with a genuine Nano. (The earlier problems listed below only seem to occur with clones.)
      Connections:
      arduino TX -> receiver  RX (4th pin down fom top - aerial on left)
      arduino GND -> receiver GND(1st pin down from top - aerial on left.)
      voltage input to pin A2 on arduino
      receiver +6v to Vin on arduino

      March 2020. Trying to solve problem of Nano being knocked out by stray voltages.(TX led stops flashing and chip has to be reloaded.)
      March 2020. Trying with 1k resistor in line with TX input followed by 0.01 uF cap going to earth.
      August 2019. Problems with low input voltage so 100 ohm resistor not used.
      April 2019. Some problems with nano being disabled after use in sub - voltage surges
     April 2019. So trying 100 ohm in power supply with 5v zener across to earth.
     April 2019.Plus transmitter line with 1k resistor in line with 5v zener connected to earth.
     April 2019. So far voltage clamping seems to be working.
     Feb 2019 - modifying this version 2.3 to only have voltage input.(For Pioneer)
     Feb 2019. RDF has added master reader for i2c to this telemetry software. Working quite well.
     This version is working for i2c compass input(separate Arduino), voltage and depth.
     Depth displays on altitude, compass heading to RPM, voltage to Temperature 1
     Voltage input tapped off as 1/3 rd of say, 12v battery. (5k and 10k resistors connected across reverse biased diode (to blow fuse if polarity switched.))
     Sept 2019-RDF - Maybe move to  input from divider set by 4.7kohms and 15k ohms for 12 v battery. Better for  3.3 v input.
     No i2c input freezes telemetry.
     FrSky Telemetry library LRS test
     (c) Pawelsky 20150724
     Not for commercial use

     FrSkyTelemetry library modified to deal with LRS format (TTL level serial instead of FrSky format...
     renamed to FrSkyTelemetryLRS

     modifications by tim senecal
    */

    #include "FrSkyTelemetryLRS.h"

    #include <SoftwareSerial.h>

    #include <Wire.h>
    //#include <LSM303.h>

    byte val = 0;

    FrSkyTelemetryLRS telemetry; // Create telemetry object

    float amperes = 0;
    float voltage = 0;
    float actual_rpm = 0;
    float calc_speed = 0;
    float Temp1;
    float Temp2;
    float depth;
    float heading;
    float voltsrdf;
    int iRXVal;

    //int  depthpin = 3;    // REMOVED the pin that the depth sensor is attached to
    int voltpin = 2;    // the pin that the voltage sensor is attached to

    //LSM303 compass;

    void setup()
    {
     //Test of i2c master writer. Uses code from here by Stevie to cope with values beyond 255.  https://forum.arduino.cc/index.php?topic=420056.0
     Wire.begin();                 // REMOVED join i2c bus (address optional for master)
     Wire.onRequest(requestEvent); // REMOVED register event
     // compass.init();
     //  compass.enableDefault();

     Serial.begin(9600);           // start serial for output


     // initialize the voltage pin as a input:
     int voltpin = 2;
     float voltsrdf = 0;   // Store in value

     // Configure the telemetry serial port
     telemetry.begin(SERIAL_1);
    }

    void loop() {


     Wire.beginTransmission(29);
     //start the transmission from the above address

     Wire.write(val);

     Wire.requestFrom(29, 1);
     heading = Wire.read();

     delay(100);

     //  compass.read();
     // heading = compass.heading();
     Serial.println(heading);
     delay(100);

     // iTestVal = heading;  // Test value

     telemetry.setFasData(amperes,   // Current consumption in amps
                          voltage);  // Battery voltage in volts


     // read input state
     // depth = analogRead (depthpin);
     // Adjust depth value
     depth = 3 * (depth - 84); // 84 to set zero
     Serial.println(depth);                 // Print the result.

     // read input state
     voltsrdf = analogRead (voltpin);
     Serial.println(voltsrdf);                 // Print the result.

     //actual_rpm = 2700;
     actual_rpm = heading;

     //depth = 160;
     amperes = 8.325;
     voltage = 12.50;

     telemetry.setFgsData(depth);  // Fuel level in percent -  unsigned int16 - any value between 0 and 65535

     // Set LiPo voltage sensor (FLVS) data (we use two sensors to simulate 8S battery
     // (set Voltage source to Cells in menu to use this data for battery voltage)
     float v1 = voltage / 2;
     float v2 = voltage / 2;
     telemetry.setFlvsData(v1, v2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);  // Cell voltages in volts (cells 1-8). Cells 9-12 are not used in this example

     // Set variometer sensor (FVAS) data
     telemetry.setFvasData(depth);  // Altitude in m (can be negative)

     // Set GPS data
     //float heading = 125.22;

     telemetry.setGpsData(39.847993, -105.104269,  // Latitude and longitude in degrees decimal (positive for N/E, negative for S/W)
                          depth,                   // Altitude in m (can be negative)
                          calc_speed,              // Speed in m/s
                          heading,                 // Course over ground in degrees
                          15, 2, 19,               // Date (year - 2000, month, day)
                          12, 00, 00);             // Time (hour, minute, second) - will be affected by timezone setings in your radio

     float accel_angle_x =  2.35;
     float accel_angle_y =  4.25;
     float accel_angle_z =  3.15;

     telemetry.setTasData(accel_angle_x,     // calculated x angle
                          accel_angle_y,     // calculated y angle
                          accel_angle_z);    // calculated z angle

     // Set temperature sensor (TEMS) data, two temperatures T1 & T2
     //float Temp1 = 12.0;
     float Temp1 = voltsrdf / 76; //  Fiddle factor of (originally 67) is calibration value from earlier software by RDF
     float Temp2 = 3;

     telemetry.setTemsData(Temp1,   // Temperature #1 in degrees Celsuis (can be negative)
                           Temp2);  // Temperature #2 in degrees Celsuis (can be negative)

     // Set RPM sensor (RPMS) data
     // (set number of blades to 2 in telemetry menu to get correct rpm value)
     telemetry.setRpmsData(actual_rpm);  // Rotations per minute

     // Send the telemetry data, note that the data will only be sent for sensors
     // that had their data set at least once. Also it will only be set in defined
     // time intervals, so not necessarily at every call to send() method.
     telemetry.send();
     delay(100);

     // Master reader part
     Wire.requestFrom(8, 2);    // request 2 bytes from slave device #8

     // Receive the 'int' from I2C and print it:-
     if (Wire.available() >= 2)                  // Make sure there are two bytes.
     {
       int iRXVal;
       for (int i = 0; i < 2; i++)             // Receive and rebuild the 'int'.
         iRXVal += Wire.read() << (i * 8);   //    "     "     "     "    "
       Serial.println(iRXVal);                 // Print the result.
       heading = iRXVal;
       Serial.println(heading);

     }

     delay(100);


    }

    // function that executes whenever data is requested by master
    // this function is registered as an event, see setup()
    void requestEvent()
    {
     int heading;
     // Wire.write("David123456"); // respond with message of 6 bytes
     // Wire.write((byte*)&iTestVal, 2);  // Transmit the 'int', one byte at a time.
     // as expected by master
    }


    FrSkyTelemetryLRS software:



    /*
     FrSky Telemetry for Teensy 3.x and 328P based boards (e.g. Pro Mini, Nano, Uno)
     (c) Pawelsky 20150730
     Not for commercial use
    */

    #include "FrSkyTelemetryLRS.h"

    FrSkyTelemetryLRS::FrSkyTelemetryLRS() : enabledSensors(SENSOR_NONE), cellIdx(0), frame1Time(0), frame2Time(0), frame3Time(0) {}

    void FrSkyTelemetryLRS::begin(uint16_t id)
    {
     //enable serial port for OpenLRSng data transfer
     if(id == SERIAL_HW)
     {
       port = &Serial;
       Serial.begin(9600);
     }

     if(id == SERIAL_1)
     {
    #if defined(SERIAL_PORT_HARDWARE1)
       port = &Serial1;
       Serial1.begin(9600);
    #else
       port = &Serial;
       Serial.begin(9600);
    #endif
     }

     if(id == SERIAL_2)
     {
    #if defined(SERIAL_PORT_HARDWARE2)
       port = &Serial2;
       Serial2.begin(9600);
    #else
       port = &Serial;
       Serial.begin(9600);
    #endif
     }
     
     if(id == SERIAL_3)
     {
    #if defined(SERIAL_PORT_HARDWARE3)
       port = &Serial3;
       Serial3.begin(9600);
    #else
       port = &Serial;
       Serial.begin(9600);
    #endif
     }
     if (softSerial != NULL)
     {
       delete softSerial;
       softSerial = NULL;
     }

    #ifdef SOFT_SERIAL_PIN_2
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_3
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_4
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_5
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_6
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_7
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_8
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_9
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_10
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_11
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    #ifdef SOFT_SERIAL_PIN_12
     if(id == SOFT_SERIAL_PIN_2)
     {
       softSerial = new SoftwareSerial(SOFT_SERIAL_PIN_2, SOFT_SERIAL_PIN_2, false);
       port = softSerial;
       softSerial->begin(9600);
       pinMode(SOFT_SERIAL_PIN_2, OUTPUT);
     }
    #endif
    }

    void FrSkyTelemetryLRS::setFgsData(float fuel)
    {
     enabledSensors |= SENSOR_FGS;
     FrSkyTelemetryLRS::fuel = (uint16_t)round(fuel);
    }

    void FrSkyTelemetryLRS::setFlvsData(float cell1, float cell2, float cell3, float cell4, float cell5, float cell6,
                                    float cell7, float cell8, float cell9, float cell10, float cell11, float cell12)
    {
     enabledSensors |= SENSOR_FLVS;
     // DEVIATION FROM SPEC: in reality cells are numbered from 0 not from 1 like in the FrSky protocol spec
     FrSkyTelemetryLRS::cell[0] = 0x0000 | (uint16_t)round(cell1 * 500.0);
     FrSkyTelemetryLRS::cell[1]  = 0x0000;
     FrSkyTelemetryLRS::cell[2]  = 0x0000;
     FrSkyTelemetryLRS::cell[3]  = 0x0000;
     FrSkyTelemetryLRS::cell[4]  = 0x0000;
     FrSkyTelemetryLRS::cell[5]  = 0x0000;
     FrSkyTelemetryLRS::cell[6]  = 0x0000;
     FrSkyTelemetryLRS::cell[7]  = 0x0000;
     FrSkyTelemetryLRS::cell[8]  = 0x0000;
     FrSkyTelemetryLRS::cell[9]  = 0x0000;
     FrSkyTelemetryLRS::cell[10]  = 0x0000;
     FrSkyTelemetryLRS::cell[11]  = 0x0000;
     
     if(cell2  != 0) FrSkyTelemetryLRS::cell[1]  = 0x1000 | (uint16_t)round(cell2  * 500.0);
     if(cell3  != 0) FrSkyTelemetryLRS::cell[2]  = 0x2000 | (uint16_t)round(cell3  * 500.0);
     if(cell4  != 0) FrSkyTelemetryLRS::cell[3] = 0x3000 | (uint16_t)round(cell4  * 500.0);
     if(cell5  != 0) FrSkyTelemetryLRS::cell[4]  = 0x4000 | (uint16_t)round(cell5  * 500.0);
     if(cell6  != 0) FrSkyTelemetryLRS::cell[5]  = 0x5000 | (uint16_t)round(cell6  * 500.0);
     if(cell7  != 0) FrSkyTelemetryLRS::cell[6]  = 0x6000 | (uint16_t)round(cell7  * 500.0);
     if(cell8  != 0) FrSkyTelemetryLRS::cell[7]  = 0x7000 | (uint16_t)round(cell8  * 500.0);
     if(cell9  != 0) FrSkyTelemetryLRS::cell[8]  = 0x8000 | (uint16_t)round(cell9  * 500.0);
     if(cell10 != 0) FrSkyTelemetryLRS::cell[9]  = 0x9000 | (uint16_t)round(cell10 * 500.0);
     if(cell11 != 0) FrSkyTelemetryLRS::cell[10] = 0xA000 | (uint16_t)round(cell11 * 500.0);
     if(cell12 != 0) FrSkyTelemetryLRS::cell[11] = 0xB000 | (uint16_t)round(cell12 * 500.0);
    }

    void FrSkyTelemetryLRS::setFasData(float current, float voltage)
    {
     enabledSensors |= SENSOR_FAS;
     // DEVIATION FROM SPEC: FrSky protocol spec suggests 0.5 ratio, but in reality this ratio is 0.5238 (based on the information from internet).
     voltage *= 0.5238;
     FrSkyTelemetryLRS::voltageBD = (uint16_t)voltage;
     FrSkyTelemetryLRS::voltageAD = (uint16_t)round((voltage - voltageBD) * 10.0);
     FrSkyTelemetryLRS::current = (uint16_t)round(current * 10.0);
    }

    void FrSkyTelemetryLRS::setFvasData(float alt)
    {
     enabledSensors |= SENSOR_FVAS;
     FrSkyTelemetryLRS::altBD = (int16_t)alt;
     FrSkyTelemetryLRS::altAD = abs((int16_t)round((alt - FrSkyTelemetryLRS::altBD) * 100.0));
    }

    void FrSkyTelemetryLRS::setGpsData(float lat, float lon, float alt, float speed, float cog, uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
    {
     enabledSensors |= SENSOR_GPS;
     FrSkyTelemetryLRS::latNS = (uint16_t)(lat < 0 ? 'S' : 'N'); if(lat < 0) lat = -lat;
     FrSkyTelemetryLRS::latBD = (uint16_t)lat;
     lat = (lat - (float)FrSkyTelemetryLRS::latBD) * 60.0;
     FrSkyTelemetryLRS::latBD = FrSkyTelemetryLRS::latBD * 100 + (uint16_t)lat;
     FrSkyTelemetryLRS::latAD = (uint16_t)round((lat - (uint16_t)lat) * 10000.0);
     FrSkyTelemetryLRS::lonEW = (uint16_t)(lon < 0 ? 'W' : 'E');  if(lon < 0) lon = -lon;
     FrSkyTelemetryLRS::lonBD = (uint16_t)lon;
     lon = (lon - (float)FrSkyTelemetryLRS::lonBD) * 60.0;
     FrSkyTelemetryLRS::lonBD = FrSkyTelemetryLRS::lonBD * 100 + (uint16_t)lon;
     FrSkyTelemetryLRS::lonAD = (uint16_t)round((lon - (uint16_t)lon) * 10000.0);
     FrSkyTelemetryLRS::altBD = (int16_t)alt;
     FrSkyTelemetryLRS::altAD = abs((int16_t)round((alt - FrSkyTelemetryLRS::altBD) * 100.0));
     speed *= 1.94384; // Convert m/s to knots
     FrSkyTelemetryLRS::speedBD = (uint16_t)speed;
     FrSkyTelemetryLRS::speedAD = (uint16_t)round((speed - FrSkyTelemetryLRS::speedBD) * 100.0);
     FrSkyTelemetryLRS::cogBD = (uint16_t)cog;
     FrSkyTelemetryLRS::cogAD = (uint16_t)round((cog - FrSkyTelemetryLRS::cogBD) * 100.0);
     FrSkyTelemetryLRS::year  = (uint16_t)(year);
     FrSkyTelemetryLRS::dayMonth = (uint16_t)day; FrSkyTelemetryLRS::dayMonth <<= 8; FrSkyTelemetryLRS::dayMonth |= (uint16_t)month;
     FrSkyTelemetryLRS::hourMinute = (uint16_t)hour; FrSkyTelemetryLRS::hourMinute <<= 8; FrSkyTelemetryLRS::hourMinute |= (uint16_t)minute;
     FrSkyTelemetryLRS::second = (uint16_t)second;
    }

    void FrSkyTelemetryLRS::setTasData(float accX, float accY, float accZ)
    {
     enabledSensors |= SENSOR_TAS;
     FrSkyTelemetryLRS::accX = (int16_t)round(accX * 1000.0);
     FrSkyTelemetryLRS::accY = (int16_t)round(accY * 1000.0);
     FrSkyTelemetryLRS::accZ = (int16_t)round(accZ * 1000.0);
    }

    void FrSkyTelemetryLRS::setTemsData(float t1, float t2)
    {
     enabledSensors |= SENSOR_TEMS;
     FrSkyTelemetryLRS::t1 = (int16_t)round(t1);
     FrSkyTelemetryLRS::t2 = (int16_t)round(t2);
    }

    void FrSkyTelemetryLRS::setRpmsData(float rpm)
    {
     enabledSensors |= SENSOR_RPMS;
     FrSkyTelemetryLRS::rpm = (uint16_t)round(rpm / 30.0);
    }

    void FrSkyTelemetryLRS::sendSeparator()
    {
     if(port != NULL)
     {
       port->write(0x5E);
     }
    }

    void FrSkyTelemetryLRS::sendByte(uint8_t byte)
    {
     if(port != NULL)
     {
       if(byte == 0x5E) // use 5D 3E sequence instead of 5E to distinguish between separator character and real data
       {
         port->write(0x5D);
         port->write(0x3E);
       }
       else if(byte == 0x5D) // use 5D 3D sequence instead of 5D to distinguish between stuffing character and real data
       {
         port->write(0x5D);
         port->write(0x3D);
       }
       else
       {
         port->write(byte);
       }
       if(port != NULL) port->flush();
     }
     else
     {
       Serial.println("no serial port defined");
     }
    }

    void FrSkyTelemetryLRS::sendData(uint8_t dataId, uint16_t data, bool bigEndian)
    {
     sendSeparator();
     sendByte(dataId);
     uint8_t *bytes = (uint8_t*)&data;
     if(bigEndian == false)
     {
       sendByte(bytes[0]);
       sendByte(bytes[1]);
     }
     else
     {
       sendByte(bytes[1]);
       sendByte(bytes[0]);
     }
     if(port != NULL) port->flush();
    }

    bool FrSkyTelemetryLRS::sendFasData()
    {
     bool enabled = enabledSensors & SENSOR_FAS;
     if(enabled == true)
     {
       sendData(0x28, current);
       sendData(0x3A, voltageBD);
       sendData(0x3B, voltageAD);
     }
     return enabled;
    }

    bool FrSkyTelemetryLRS::sendFgsData()
    {
     bool enabled = enabledSensors & SENSOR_FGS;
     if(enabled == true)
     {
       sendData(0x04, fuel);
     }
     return enabled;
    }

    bool FrSkyTelemetryLRS::sendFlvsData()
    {
     bool enabled = enabledSensors & SENSOR_FLVS;
     if(enabled == true)
     {
       // Only send one cell at a time
       if((cell[cellIdx] == 0) || (cellIdx == 12)) cellIdx = 0;
       sendData(0x06, cell[cellIdx], true);  
       cellIdx++;
     }
     return enabled;
    }

    bool FrSkyTelemetryLRS::sendFvasData()
    {
     bool enabled = enabledSensors & SENSOR_FVAS;
     if(enabled == true)
     {
       sendData(0x10, altBD);  
       sendData(0x21, altAD);  
     }
     return enabled;
    }

    bool FrSkyTelemetryLRS::sendGpsData()
    {
     bool enabled = enabledSensors & SENSOR_GPS;
     if(enabled == true)
     {
       sendData(0x01, gpsAltBD);  
       sendData(0x09, gpsAltAD);  
       sendData(0x11, speedBD);  
       sendData(0x19, speedAD);  
       sendData(0x12, lonBD); // DEVIATION FROM SPEC: FrSky protocol spec says lat shall be sent as big endian, but it reality little endian is expected
       sendData(0x1A, lonAD); // DEVIATION FROM SPEC: FrSky protocol spec says lat shall be sent as big endian, but it reality little endian is expected
       sendData(0x22, lonEW); // DEVIATION FROM SPEC: FrSky protocol spec says lon shall be sent as big endian, but it reality little endian is expected
       sendData(0x13, latBD); // DEVIATION FROM SPEC: FrSky protocol spec says lon shall be sent as big endian, but it reality little endian is expected
       sendData(0x1B, latAD);  
       sendData(0x23, latNS);  
       sendData(0x14, cogBD);  
       sendData(0x1C, cogAD);  
     }
     return enabled;
    }

    bool FrSkyTelemetryLRS::sendDateTimeData()
    {
     bool enabled = enabledSensors & SENSOR_GPS;
     if(enabled == true)
     {
       sendData(0x15, dayMonth, true);  
       sendData(0x16, year);  
       sendData(0x17, hourMinute, true);  
       sendData(0x18, second);  
     }
     return enabled;
    }

    bool FrSkyTelemetryLRS::sendTasData()
    {
     bool enabled = enabledSensors & SENSOR_TAS;
     if(enabled == true)
     {
       sendData(0x24, accX);  
       sendData(0x25, accY);  
       sendData(0x26, accZ);  
     }
     return enabled;
    }

    bool FrSkyTelemetryLRS::sendTemsData()
    {
     bool enabled = enabledSensors & SENSOR_TEMS;
     if(enabled == true)
     {
       sendData(0x02, t1);  
       sendData(0x05, t2);
     }
     return enabled;
    }
     
    bool FrSkyTelemetryLRS::sendRpmsData()
    {
     bool enabled = enabledSensors & SENSOR_RPMS;
     if(enabled == true)
     {
       sendData(0x03, rpm);
     }
     return enabled;
    }

    void FrSkyTelemetryLRS::sendFrame1()
    {
     bool result = false;
     result  = sendFasData();
     result |= sendFlvsData();
     result |= sendFvasData();
     result |= sendTasData();
     result |= sendTemsData();
     result |= sendRpmsData();
     if (result == true) sendSeparator();
    }

    void FrSkyTelemetryLRS::sendFrame2()
    {
     bool result = false;
     result  = sendFgsData();
     result |= sendGpsData();
     if (result == true) sendSeparator();
    }

    void FrSkyTelemetryLRS::sendFrame3()
    {
     bool result = false;
     result = sendDateTimeData();
     if (result == true) sendSeparator();
    }

    void FrSkyTelemetryLRS::send()
    {
     uint32_t currentTime = millis();
     if(currentTime > frame3Time) // Sent every 5s (5000ms)
     {
       frame3Time = currentTime + 5000;
       frame2Time = currentTime + 200; // Postpone frame 2 to next cycle
       frame1Time = currentTime + 200; // Postpone frame 1 to next cycle
       sendFrame3();
     }
     else if(currentTime > frame2Time) // Sent every 1s (1000ms)
     {
       frame2Time = currentTime + 2000;
       frame1Time = currentTime + 200; // Postpone frame 1 to next cycle
       sendFrame2();
     }
     else if(currentTime > frame1Time) // Sent every 200ms
     {
       frame1Time = currentTime + 200;
       sendFrame1();
     }
    }
    avatar
    tsenecal
    Guest


    Posts : 311
    Join date : 2015-04-01

    Telemetry on openLRS Empty Re: Telemetry on openLRS

    Post  tsenecal Fri Apr 10, 2020 7:20 am

    David,

    there might be some weird new constants in use...

    backup your existing FrSkyTelemetryLRS.h, then open it with a text editor.

    replace the following section of code in the FrSkyTelemetryLRS.h library:

    if(id == SERIAL_1)
    {
    #if defined(SERIAL_PORT_HARDWARE1)
    port = &Serial1;
    Serial1.begin(9600);
    #else
    port = &Serial;
    Serial.begin(9600);
    #endif
    }

    with this:

    if(id == SERIAL_1)
    {
    port = &Serial1;
    Serial1.begin(9600);
    }

    recompile the code and see if that makes any difference.


    this forces the Serial1 RX and TX pins to be used, which is correct for the Nano Every.
    david f
    david f
    AMS Treasurer


    Posts : 2398
    Join date : 2010-11-10
    Age : 73
    Location : Cumbria

    Telemetry on openLRS Empty Re: Telemetry on openLRS

    Post  david f Sat Apr 11, 2020 12:47 pm

    Hi Tim,

    That modification works very well. Telemetry coming through fine. Thank you!

    It is a shame that they didn't call the Nano Every something else - it is quite different from the Nano.

    Good price and easy to solder though. Also available without pins so smaller (Unlike the genuine Nano.)

    I will put the Nano Every on long term test but I am sure that it will be more reliable than the Nano clones. (I wonder if the "clone kludge" of using  a cheap CH340 driver is at the heart of the problem?)

    Thanks again and keep well!

    David

      Current date/time is Mon Apr 29, 2024 11:02 am