Adding extra functions to MinimOSD

I have started to add functions to MinimOsd code.

At first i did it for myself only. Added many functions i thought i need. Then opened this thread.

after a while, Pedro and later Miguel came, and things started to happen fast. :D

They have optimised the code and added even more things to it.

They have worked hard on CT, and it became a great tool!

Thank you Bough! :)

By now MinimOSD-Extra got a pretty advanced OSD.

Here it is in action:

Added:

- Changeable unit measurement (US, metric)

- Airspeed

- Home alt

- Battery Percent

- Battery used mah

- Current Draw

- Time From Startup (cleared at takeoff to show exact flight time)

- OSD Menu

- Variometer

- Wind horizontal speed and direction, and also the average wind speed of the last few minutes. 

- OSD on/off

- Switchable secound screen

- WP distance

- WP heading

- Crosstrack error

- Warning messages for Lost GPS fix, Stall, Overspeed, battery volt, battery Percent, RSSI

- Efficiency, glide distance & thermic notifier. 3 in one panel

- OSD Brightness

- HAM Call Sign

- After flight summary

- Trip distance

- Temperature

- Smoothened horizon

- Real heading

- RSSI

- Vertical speed

This functions can be turned on and off, and placed on different screens now, by the Config. tool.

Also RSSI, switching mode and channel and unit measurement, Stall speed warning, Overspeed warning, Battery warning volt, Battery percent warning, RSSI warning,  can be set in new Config Tool.

We built in a new way of setting video standards. Now OSD does not guessing anymore :). You can set it fixed from CT. It is in "Video Mode" menu.

Here is how it looks: (This video is a bit outdated, sorry. I will make a new one soon.)

The MinimOSD-Extra project is here: Link

This project is the developing version of the official Arducam OSD located here: Link

The latest stable version is: 2.2

The latest version can be downloaded from here: MinimOSD-Extra R800

Username: MinimOSD_Extra

Password: Top_Secret

CT is included. (The FW for Plane, Copter, Character upload and the character file is in the "FW & Char" directory inside CT directory)

We are sharing it to see videos you make using it! :)

Enjoy

You need to be a member of diydrones to add comments!

Join diydrones

Email me when people reply –

Replies

  • I like to have the time of day in my symbology to make it easier to match up recording with flights. The time data on the MAVLink used to be limited to time since the APM was booted, but given that we have a GPS available I used to add code to Arducopter/Arduplane to fix this. At some point GPS time was added to the MAVLink data stream, so in principle no need to make those mods any more. However, the data is scaled in microseconds since start of Unix epoch, so goes over 32 bits. The data is therefore transferred in a 64 bit unsigned word. First thing that needs to happen in the MinimOSD, therefore, is to divide by 1000000 to get time in seconds. Unfortunately, using a 64 bit divide seems to call in a library that increases code size by about 10k, so forget that. I therefore adapted some general multi-word divide code and hardcoded it for 64 bit divided by 32 bit. It now adds about 1.3k. Still needed to disable a few panels to make it fit, but that wasn't a big problem for me. I expect that the size could be reduced further by reworking the divide routine to work on 32 bit words rather than 16 bit words, but that is for another day.

    The time of day is displayed in the panTime() function in the line immediately below, and aligned with the time since start. This means that you need to make sure to leave blank space when you lay out your symbology.

    You need to set your timezone in a define statement.

    Required mods are as shown below.

    Andrew

    //---
    //
    // Add this variable declaration to OSD_Vars.h
    static uint64_t osd_gps_time; // time from GPS AJF

    //--

    //

    // Add these declarations to OSD_Config.h, and set your timezone appropriately

    #define TIME_TIMEZONE -4   // Offset from UTC to local time in hours. For eastern North America it should be -4 for summer, -5 for winter
    #define TIME_MAX_SECONDS 86400 // seconds in one day (60*60*24) 

    //---
    //
    // Add the section with "case MAVLINK_MSG_ID_SYSTEM_TIME:" to MAVLink.ino
    //
    case MAVLINK_MSG_ID_SCALED_PRESSURE:
    {
    temperature = mavlink_msg_scaled_pressure_get_temperature(&msg);
    }
    break;
    case MAVLINK_MSG_ID_SYSTEM_TIME:
    {
    osd_gps_time = mavlink_msg_system_time_get_time_unix_usec(&msg);
    }
    break;
    default:
    //Do nothing
    break;


    //---
    //
    // Use this new version of "panTime" in OSD_Panels.ino
    //
    //
    /* **************************************************************** */
    // Panel : panTime
    // Needs : X, Y locations
    // Output : Time from start with symbols
    // Size : 2 x 8 (rows x chars) //AJF
    // Staus : done

    void panTime(int first_col, int first_line)
    {
    osd.setPanel(first_col, first_line);
    osd.openPanel();

    // The data is scaled in usec, and stored as a 64 bit value. We therefore need to divide by 1,000,000 to get to seconds.
    // Using the standard library 64 bit divide adds about 10kB to the code size and doesn't fit in the 328. Using this routine only
    // adds about 1.3kB, and does fit (at least for this version of MinimOSD with a few panels disabled).
    uint32_t local_osd_gps_time = Divide_1000000(osd_gps_time);

    start_Time = (millis() / 1000) - FTime;

    uint32_t local_time = (local_osd_gps_time + TIME_MAX_SECONDS + TIME_TIMEZONE * 3600) % TIME_MAX_SECONDS;

    int t_sec = local_time % 60;
    local_time /= 60;
    int t_min = local_time % 60;
    local_time /= 60;
    int t_hr = local_time % 24;

    osd.printf(" %c%2i%c%02i|", 0x08, ((int)start_Time / 60) % 60, 0x3A, (int)start_Time % 60);
    if(local_osd_gps_time != 0) osd.printf("%02i%c%02i%c%02i", t_hr, 0x3A, t_min, 0x3A, t_sec);
    osd.closePanel();
    }


    //---
    //
    // Add the following routines to OSD_Panels.ino
    //
    //
    //
    // q[0], r[0], u[0], and v[0] contain the LEAST significant halfwords. (The sequence is in little-endian order).
    // This first version is a fairly precise implementation of Knuth's Algorithm D, for a binary computer with base b = 2**16.
    // The caller supplies
    // 1. Space q for the quotient, m - n + 1 halfwords (at least one).
    // 2. Space r for the remainder (optional), n halfwords.
    // 3. The dividend u, m halfwords, m >= 1.
    // 4. The divisor v, n halfwords, n >= 2.
    // The most significant digit of the divisor, v[n-1], must be nonzero. The dividend u may have leading zeros; this just makes
    // the algorithm take longer and makes the quotient contain more leading zeros. A value of NULL may be given for the address
    // of the remainder to signify that the caller does not want the remainder. The program does not alter the input parameters u and v.
    // The quotient and remainder returned may have leading zeros. The function itself returns a value of 0 for success and 1 for
    // invalid parameters (e.g., division by 0) . For now, we must have m >= n. Knuth's Algorithm D also requires that the dividend
    // be at least as long as the divisor. (In his terms, m >= 0 (unstated). Therefore m+n >= n.)
    //
    // Adapted from code at <http://www.hackersdelight.org/hdcodetxt/divmnu.c.txt&gt; to make a 64 bit divided by 32 bit version
    //

    union U64_32_16 {
    uint16_t u16_4[4];
    uint32_t u32_2[2];
    uint64_t u64_1;
    };

    union U32_16 {
    uint16_t u16_2[2];
    uint32_t u32_1;
    };

    uint32_t Divide_1000000(uint64_t x)
    {
    uint32_t returnValue;
    U64_32_16 dividend, quotient;
    U32_16 divisor;

    dividend.u64_1 = x;
    divisor.u32_1 = 1000000;

    div_64_32(quotient.u16_4, dividend.u16_4, divisor.u16_2);

    return quotient.u32_2[0];
    }

    uint16_t nlz(uint32_t x)
    {
    uint16_t n;
    if (x == 0) {
    return (32);
    }
    n = 0;
    if (x <= 0x0000FFFF) {
    n = n + 16;
    x = x << 16;
    }
    if (x <= 0x00FFFFFF) {
    n = n + 8;
    x = x << 8;
    }
    if (x <= 0x0FFFFFFF) {
    n = n + 4;
    x = x << 4;
    }
    if (x <= 0x3FFFFFFF) {
    n = n + 2;
    x = x << 2;
    }
    if (x <= 0x7FFFFFFF) {
    n = n + 1;
    }
    return n;
    }

    int div_64_32(uint16_t q[4], const uint16_t u[4], const uint16_t v[2])
    {
    const uint32_t b = 65536; // Number base (16 bits).
    uint32_t qhat; // Estimated quotient digit.
    uint32_t rhat; // A remainder.
    uint32_t p; // Product of two digits.
    int32_t s, i, j, t, k;
    uint16_t vn[2];
    uint16_t un[5];

    // Normalize by shifting v left just enough so that
    // its high-order bit is on, and shift u left the
    // same amount. We may have to append a high-order
    // digit on the dividend; we do that unconditionally.

    s = nlz(v[1]) - 16; // 0 <= s <= 15.
    vn[1] = (v[1] << s) | (v[0] >> 16 - s);
    vn[0] = v[0] << s;

    un[4] = u[3] >> 16 - s;
    for (i = 3; i > 0; i--) {
    un[i] = (u[i] << s) | (u[i - 1] >> 16 - s);
    }
    un[0] = u[0] << s;

    for (j = 2; j >= 0; j--) { // Main loop.
    // Compute estimate qhat of q[j].
    qhat = (un[j + 2] * b + un[j + 1]) / vn[1];
    rhat = (un[j + 2] * b + un[j + 1]) - qhat * vn[1];
    again:
    if (qhat >= b || qhat * vn[0] > b * rhat + un[j]) {
    qhat = qhat - 1;
    rhat = rhat + vn[1];
    if (rhat < b) {
    goto again;
    }
    }
    // Multiply and subtract.
    k = 0;
    for (i = 0; i < 2; i++) {
    p = qhat * vn[i];
    t = un[i + j] - k - (p & 0xFFFF);
    un[i + j] = t;
    k = (p >> 16) - (t >> 16);
    }
    t = un[j + 2] - k;
    un[j + 2] = t;
    q[j] = qhat; // Store quotient digit.
    if (t < 0) { // If we subtracted too
    q[j] = q[j] - 1; // much, add back.
    k = 0;
    for (i = 0; i < 2; i++) {
    t = un[i + j] + vn[i] + k;
    un[i + j] = t;
    k = t >> 16;
    }
    un[j + 2] = un[j + 2] + k;
    }
    } // End j.

    return 0;
    }

    • Hey Andrew. I was able to move everything into the appropriate spot except the routines you added at the end. It seems that it's not happy with these lines:

      if (x <= 0x00FFFFFF) {
      n = n + 8;
      x = x 8;
      }

      Specifically, x = x 8; . Any hints on what's supposed to be in the middle? 

      EDIT1: I guessed that you meant to have a multiplier in there, so I changed it to x=x*8. After that, though, I got an error on these lines:

      vn[1] = (v[1] s) | (v[0] >> 16 - s);
      vn[0] = v[0] s;

      Again, I'm not sure what v[0] s means. Maybe another multiplier?

    • This is awesome Andrew! and exactly what I've been recently looking for. Do you have your code available in Git that I could get some help me to compile into a release of Minim OSD Extra? I apologize if I'm not using the correct terms. I'm not a programmer. Thanks!

  • What are the preffered sr nr's with a pixhawk, I can imagine that with more process power of the pixhawk we can get more updates from mavlink?

This reply was deleted.

Activity