Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(telemetry): Add GPS Telemetry #18

Merged
merged 121 commits into from
Jul 26, 2023
Merged

feat(telemetry): Add GPS Telemetry #18

merged 121 commits into from
Jul 26, 2023

Conversation

ZZ-Cat
Copy link
Owner

@ZZ-Cat ZZ-Cat commented Apr 25, 2023

Overview

This Pull Request adds GPS telemetry, as per #15.
I have decided against providing my own hardware GPS driver for this because I don't see a need to reinvent the wheel.
Instead, I have made it so that you can bring your own GPS module & drivers & you can pass data from your GPS to CRSF for Arduino's GPS telemetry.

What's new

  • DMA.
    But... so far, it has decided to be a thorn in my side for using it to send telemetry. Until I can find a solution to this, I am reverting to using the the Arduino API function for sending telemetry out. DMA is still in use to receive CRSF packets on hardware that supports it. However, it's "receive only" for now.
  • GPS Telemetry!
    I finally have this finished & ready for you to use.
  • PlatformIO: GPS Telemetry example
    This example is enabled by default in PlatformIO. It demonstrates how GPS data can be passed into CRSF for Arduino for use as GPS telemetry.
  • Arduino IDE: GPS Telemetry example
    This is line-for-line identical to its PlatformIO version.

New API function

This Pull Request introduces a new API function: CRSFforArduino::telemetryWriteGPS().
This function takes six parameters:

  • latitude
    • Type: float
    • SI Unit: Decimal degrees
  • longitude
    • Type: float
    • SI Unit: Decimal degrees
  • altitude
    • Type: float
    • SI Unit: Centimetres (cm)
  • speed
    • Type: float
    • SI Unit: Centimetres per second (cm/s)
  • groundCourse
    • Type: float
    • SI Unit: Degrees.
  • satellites
    • Type: uint8_t

Telemetry is written out automatically when you call CRSFforArduino::update() in your main loop.

You can use CRSFforArduino::telemetryWriteGPS() in the same context as the code you use to poll-&-parse data from your GPS module.

#include "CRSFforArduino.h"

CRSFforArduino crsf = CRSFforArduino(&Serial1);

float gpsLatitude;
float gpsLongitude;
float gpsAltitude;
float gpsSpeed;
float gpsCourse;
float gpsSatellitesInView;

uint16_t rcChannels[16];

int main()
{
    for (uint8_t i = 0; i < 16; i++)
    {
        if (i == 3)
        {
            rcChannels[i] = 172;
        }

        else
        {
            rcChannels[i] = 992;
        }
    }

    while (1)
    {
        /* Get your GPS data.
        This function would be replaced with your own GPS driver & parsing code. */
        exampleGetMyGPSdata(&gpsLatitude, &gpsLongitude, &gpsAltitude, &gpsSpeed, &gpsCourse, &gpsSatellitesInView);

        /* Update telemetry. This can be either before or after CRSFforArduino::update(). */
        crsf.telemetryWriteGPS(gpsLatitude, gpsLongitude, gpsAltitude, gpsSpeed, gpsCourse, gpsSatellitesInView);

        /* Update CRSF for Arduino. */
        crsf.update();

        /* Get your RC channels. */
        rcChannels[RC_CHANNEL_ROLL] = crsf.getChannel(RC_CHANNEL_ROLL + 1);
        rcChannels[RC_CHANNEL_PITCH] = crsf.getChannel(RC_CHANNEL_PITCH + 1);
        rcChannels[RC_CHANNEL_THROTTLE] = crsf.getChannel(RC_CHANNEL_THROTTLE + 1);
        rcChannels[RC_CHANNEL_YAW] = crsf.getChannel(RC_CHANNEL_YAW + 1);
    }
}

Changes to RC channels

You no longer need to get your RC channels inside the call to CRSFforArduino::update().

#include "CRSFforArduino.h"

CRSFforArduino crsf = CRSFforArduino(&Serial1);

uint16_t rcChannels[16];

int main()
{
    for (uint8_t i = 0; i < 16; i++)
    {
        if (i == 3)
        {
            rcChannels[i] = 172;
        }

        else
        {
            rcChannels[i] = 992;
        }
    }

    while (1)
    {
        if (crsf.update())
        {
            /* Getting your RC channels this way is no longer necessary. */
            rcChannels[RC_CHANNEL_ROLL] = crsf.getChannel(RC_CHANNEL_ROLL + 1);
            rcChannels[RC_CHANNEL_PITCH] = crsf.getChannel(RC_CHANNEL_PITCH + 1);
            rcChannels[RC_CHANNEL_THROTTLE] = crsf.getChannel(RC_CHANNEL_THROTTLE + 1);
            rcChannels[RC_CHANNEL_YAW] = crsf.getChannel(RC_CHANNEL_YAW + 1);
        }
    }
}

Now, you can do it this way...

#include "CRSFforArduino.h"

CRSFforArduino crsf = CRSFforArduino(&Serial1);

uint16_t rcChannels[16];

int main()
{
    for (uint8_t i = 0; i < 16; i++)
    {
        if (i == 3)
        {
            rcChannels[i] = 172;
        }

        else
        {
            rcChannels[i] = 992;
        }
    }

    while (1)
    {
        /* Polling the return value is optional & no longer necessary. */
        crsf.update();

        /* This is a better way. */
        rcChannels[RC_CHANNEL_ROLL] = crsf.getChannel(RC_CHANNEL_ROLL + 1);
        rcChannels[RC_CHANNEL_PITCH] = crsf.getChannel(RC_CHANNEL_PITCH + 1);
        rcChannels[RC_CHANNEL_THROTTLE] = crsf.getChannel(RC_CHANNEL_THROTTLE + 1);
        rcChannels[RC_CHANNEL_YAW] = crsf.getChannel(RC_CHANNEL_YAW + 1);
    }
}

Later on in the year, I will make it so the CRSFforArduino::getChannel() function returns a pre-set value when your RC receiver goes into fail-safe mode. When I come back from my hiatus, that is. =^/.~=

How to access GPS Telemetry from your controller

I am assuming that you are using the latest versions of EdgeTX & ExpressLRS. If you aren't, go & update your gear now. This is only applicable to EdgeTX & ExpressLRS (because this is what I have tested it on).

Here is what you need to do:

  1. In your Model Settings, pan over to your Telemetry tab.
  2. Tap (or click) on Discover new.
  3. All five GPS telemetry "sensors" should show up automatically.

By rights, you don't need to do any calibration here. However, it is a good idea to verify the accuracy of your telemetry.
How fast (or how slow) GPS telemetry is updated is dependent on what you have set your packet rate to on your ExpressLRS transmitter module (via the Lua Script).

Keep in mind that the default units on your controller may be slightly different to what units are used in CRSF for Arduino's source code, & you may need to convert the SI Units in the source code over to what you are seeing on your controller to verify the accuracy of your telemetry.
Another thing you need to keep in mind is that there are rounding errors in your controller, so don't be too surprised if your telemetry is off by about that 🤏 much.

Notes from yours truly

It has taken me a while to get around to working on this PR again. A lot has happened over the last few months in my personal life, which has meant that I have had to put all of my projects on hold between March 2023 through June 2023.
Also, the "clean commit" I did to this PR was a huge set-back for me & I let things such as "What's the f**kin' point anymore?" get to me & I let intrusive thoughts like that drive me to the point of nearly giving up on CRSF for Arduino.

To spite that... I am not giving up on CRSF for Arduino... ever! I started this project for a reason: To see it through to the end, no matter what. I was inspired to make this project by the wonderful team over at ExpressLRS, when one of their developers tested the RadioMaster Ranger to just over 100 kilometres. That is literally why CRSF for Arduino exists today. Because I want to bring that capability to the maker community via the Arduino ecosystem.

The other reason is traditional PWM receivers are notoriously janky, when it comes to implementing them in an Arduino project.
The receivers themselves are either difficult to find, expensive, or are of questionable quality. The CRSF protocol is far more robust than using traditional PWM RC receivers, & CRSF for Arduino brings that robustness & reliability to the Arduino ecosystem.

@ZZ-Cat ZZ-Cat linked an issue Apr 25, 2023 that may be closed by this pull request
@ZZ-Cat ZZ-Cat self-assigned this Apr 25, 2023
@ZZ-Cat ZZ-Cat added the ✨️ Enhancement ✨️ New feature or request label Apr 25, 2023
@ZZ-Cat ZZ-Cat added this to the Version 0.4.0 milestone Apr 25, 2023
ZZ-Cat added 24 commits May 31, 2023 10:39
This is a part of an ongoing test to see if CI will verify CRSF for Arduino on supported Arduino IDE platforms
…ndency

This is a part of an ongoing test to see if CI will verify CRSF for Arduino on supported Arduino IDE platforms
…fruit Zero DMA Library`

This is a part of an ongoing test to see if CI will verify CRSF for Arduino on supported Arduino IDE platforms
This CI workflow builds CRSF for Arduino using PlatformIO. The name should reflect this.
This CI workflow builds CRSF for Arduino using the Arduino IDE. The name should reflect this.
Conventional Commits tag sits between the two CI tags & the Releases & License tags
ZZ-Cat added 11 commits July 25, 2023 21:24
Latitude, Longitude, Altitude, Speed, Course, & Satellites values are now available for use as GPS Telemetry.
Don't mind me. I am griping over the fact that I forgot to format my code prior to my previous commit.
CRSF for Arduino is fully compatible with the Seeed Studio XIAO SAMD21 development board.

PlatformIO users can select this board in the `project.ini` file as `seeed_xiao`.
Arduino IDE users can select this board from the Boards Manager (provided support for this has been added to the Arduino IDE ahead of time).
@ZZ-Cat ZZ-Cat removed the ⤴️ Rebase Needed ⤴️ This needs to be rebased. label Jul 25, 2023
ZZ-Cat added 14 commits July 26, 2023 09:56
This function is only called when CRSF for Arduino is compiled with `USE_DMA` commented out.
**CAVEATS:** For the time being, `_serial->write()` is sending telemetry instead of DMA. Currently, DMA is only handling the reception of incoming CRSF packets, _not_ sending them out. For some reason, DMA stops working when I try to use it to write out data. For now, this is how I am giving you all telemetry. It will have to do, until I can find a solution to the DMA woes that I am experiencing, later on.
…vertently compiled in PlatformIO

PlatformIO users must use main_rc.cpp in `src/src` directory instead.
Arduino IDE users now have their own version of the GPS Telemetry example
…advertently compiled in the Arduino IDE

Arduino IDE users must use the channels.ino file located in the examples folder.
…ample is inadvertently compiled in the Arduino IDE

Arduino IDE users must use the gps_telemetry.ino file located in the examples folder.
…mple files

The Arduino IDE likes to include these files - despite these files being specific to PlatformIO - into its compilation & this error causes a false positive.

If both the GPS Telemetry & RC example files are built & flashed onto hardware via the Arduino IDE, these examples _will_ be non-functional.
@ZZ-Cat ZZ-Cat marked this pull request as ready for review July 26, 2023 22:31
@ZZ-Cat ZZ-Cat merged commit 7c70fb1 into Main-Trunk Jul 26, 2023
@ZZ-Cat ZZ-Cat deleted the ZZ-Cat/issue15 branch July 26, 2023 22:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨️ Enhancement ✨️ New feature or request
Projects
Status: Done
Status: 📋 Backlog
Development

Successfully merging this pull request may close these issues.

GPS telemetry
1 participant