|Terms of service|
|Let's keep it simple
YMFC-32 | Adding telemetry | The DIY Arduino - STM32 autonomous drone
This page contains the full script that I used for making this video.
Hello and welcome to another one of my YMFC-32 videos. In this video I will explain how I implemented the telemetry system that you see here.
Now you might ask yourself why is it important to have a telemetry system on a multicopter. Well, in the upcoming videos I will implement more sensors like a compass and a GPS to create an autonomous flying quadcopter.
This will increase the complexity of the code and its usage. Also, it makes flying more relaxing and there is a big chance that you fly further away and longer. The telemetry system allows you to check various parameters before and during flight.
For example, before every flight you want to know that your GPS has found enough satellites to get a reliable GPS-hold.
And for that reason I tried to make a simple telemetry system for the YMFC-32.
The basic components that I used are two APC220 transceivers. You can find links to all these parts on my website.
Now, I tested these transceivers on my octocopter and got a range of over 1200 meters during a very stressful flyaway. That was a bad day. But it showed me that these things really work.
Next you need an Arduino Uno and an LCD board like this. As you can see these things are really cheap when bought together. And finally a buzzer for sound effects and a switch.
Here you can see the connections to the YMFC-32 flight controller. For simplicity I will only send data to the ground station. That is why there are only three connections. This will keep the code as simple as possible.
The Schematic for the ground station looks like this. Again, very simple.
The switch is needed for uploading a program to the Arduino. You need to disconnect the transceiver during uploads as it will hold the serial port high and you get an error during upload.
Out of the box these APC220 transceivers will work as a serial air bridge with a baud rate of 9600 baud per second. Ok, very important. The STM32 is a 3.3V microcontroller and the input voltage on pin B0 must be limited to 3.3V. With the APC220 the voltage is regulated to approximately 3.3V as you can see on the oscilloscope. If you use other serial transceivers make sure that the voltage is limited to approximately 3.3V on pin B0. Otherwise you might destroy the output.
And now that the hardware is done we can start with the fun stuff, sending data.
In the YMFC-32 flight controller code there are several variables that hold valuable information about the quadcopter. Like battery voltage, flight mode, errors , number of satellites and much more. To show these variables on the LCD we need to transfer them from the quadcopter to the ground station.
To get a better understanding of how this data transfer works we need to know more about the serial communications protocol. First, the serial communication that is used for the YMFC-32 is time based. Meaning that after a received start a timer is needed to simulate a clock pulse. That is the reason that the baud rate on both devices must be the same.
A baud rate of 9600 means that the low or high state of the data line can change 9600 times per second.
With every data transfer, 8 bits are send to the receiver. And yes, 8 bits form one byte. And these bits can be anything. All zeros, all ones or a combination.
When the data line is not used it's pulled high. So when I now send 8 ones for example the receiver has now idea that anything has been send as the data line is never pulled low.
To overcome this problem a start indication is needed. This is the so called start bit that will pull the data line low to indicate a start.
As already explained this communication protocol is time based and the clocks of the transmitter and receiver might not run 100% accurate. This means that over time there will be a small time drift.
By using a stop bit the data line is pulled high so the receiver has a known synchronization point that is used to reset the clock of the receiver.
Here I have an example of one data transfer at 9600 bauds per second. This means that every bit is approximately 104 microseconds long. Because we have 1 start bit, 8 data bits and 1 stop bit the total data transfer takes 1041 microseconds.
Ok, this makes sense so far.
Now let's have a look at a variable of the YMFC-32 code that is used for storing the actual latitude of the quadcopter. As you can see it's called l_lat_gps. This variable is declared as a 32 bit signed integer. A 32 bit integer is needed because the latitude can run up to a 10 digit number.
So, how do we send a 32 bit integer when we can only send 8 bits at a time. Well, the answer is very simple, we need to use the bit shift operator.
Here I have my 32 bit latitude variable and my send byte variable declared as an 8 bit unsigned integer. When I now copy the latitude variable into the send_byte variable only the last 8,or least significant bits are copied.
With the bit shift operator it's possible to shift the latitude 8 places to the right and again copy the value to the send_byte variable.
This way the 9nth till 16th bit are copied.
This way it's possible to select 4 groups of 8 bits that can be send via the serial transceivers.
Now, it's not possible to send multiple bytes in every main program loop. This will simply take too long and the main program loop will exceed the 4000 microsecond maximum.
To overcome this problem only one byte is send every program loop.
If we have a look at the code you can see that every program loop this subroutine is executed. During the first two loops a signature is send so the ground station can detect the start of the data stream.
After that, during every loop a single byte is send.
As you can see here the battery voltage is send as a byte by multiplying it by 10. This way we don't have to use pointers to get the individual float bytes and we can keep the code simple and easy to understand.
And this goes on and on. Variables that hold more than one byte are first stored in a temporary variable. This is because in the next loop the variable can be changed and you get weird readings on the ground station.
And finally after 125 loops the counter is reset and the whole thing starts all over again. Because the main program loop runs at 250Hz the total refresh rate is 2 times per second. More than enough to get usable telemetry data.
Next thing is the output method. You might expect something like serial.print or serial.write. But this is not the case. One serial port is used for uploading the program. The other one is used for the GPS.
That is why I wrote a small piece of code that simulates a serial output. Look at it as the software serial library. Only smaller in code size. This way I can keep the transceiver connected and still be able to upload programs to the STM32. As you can see, every 104 microseconds a bit is send.
To make sure we get a valid data transfer an error check is done with the help of a check_byte. This check_byte is set to zero at the beginning of every data transmission. After sending each byte the XOR operator is used to change the check_byte based on the transmitted bytes.
The check_byte is send last so the ground station can do the same with the received bytes. After that it can check the XOR result with the received check_byte.
Ok, now that all the data is send we can have a look at the receiver side.
Receiving the individual bytes on the Arduino is done with the Serial function. As explained we first need to make sure that the baud rate is set at the same speed as the transmitter.
After that the bytes are received automatically in a rotating buffer via interrupts. We can check if there are new bytes available with the Serial.available function. After that we can read the received bytes with the with the Serial.read function.
The program will search for the start signature JB. When found it will increment the receive_start_detect variable. Between the two start signatures a complete data transfer can be found.
In this part of the code the check byte is calculated based on the received bytes. When the two check bytes match the received bytes are used to create the original variables that can be shown on the LCD.
The rest of the program is pretty straight forward.
The only thing that I like to explain are the key inputs. The keys are connected via resistors to one analog input. So when you press a key the voltage on the analog input changes. I created an interrupt that checks the keys every few microseconds.
This way it's possible to create a very responsive user interface.
Now let's have a look at how it works.
As you can see I connected the Arduino power supply to the battery of my transmitter. When I turn on the transmitter the telemetry system is also powered.
The receiver will now wait for a valid telemetry signal. When I now connect the flight battery and wait for the calibration sequence to finish, the quadcopter data is shown on the LCD.
I can now scroll through the pages with the up and down keys.
Here you can see that the maximum altitude is stored in the EEPROM of the Arduino. When I hold down a key for several seconds there is a notification sound and an option for erasing this value.
The same method is used for the total flight time.
There is always a possibility that the telemetry signal gets disturbed. When I disconnect the battery you will see and hear that the ground station outputs an alarm. I can now mute the alarm with a key press.
The last known dataset is in the memory and can be checked with the up and down keys. When the telemetry connection is restored the values will automatically show up on the LCD.
And that brings us to the end of this video. I hope that this video gives you a better understanding of the YMFC-32 telemetry system.
Thank you for watching and see you next time.