STM32 for Arduino - Connecting an RC receiver via input capture mode
HTML-код
- Опубликовано: 30 сен 2017
- In this video I'm connecting a 6 channel RC receiver via the input capture mode. As always I will explain some background information about the STM32 timers and registers.
Another important step in creating a STM32 flight controller for quadcopters.
My website: www.brokking.net/
Video 1 - Getting started with the STM32 microcontroller - STM32F103C8T6 via Arduino:
• Getting started with t...
Video 2 - STM32 for Arduino - Connecting a RC receiver should be easy, right?:
• STM32 for Arduino - Co...
Video 3 - Improve your Arduino programming skills - The qualifier volatile explained:
• Improve your Arduino p...
The Arduino STM32 project on GitHub:
github.com/rogerclarkmelbourn...
I bought the STM32F103C8T6 here:
www.dx.com/p/stm32f103c8t6-arm...
And also the FTDI programmer:
www.dx.com/p/crius-ftdi-basic-...
You can download the Arduino code via this link:
www.brokking.net/RUclips/STM32...
Music:
www.bensound.com Наука
Seriously i have learnt more by following this video than taking some course, you make me love datasheets. These videos are the most information-dense videos ever.
Best explanation ever! Thank you so much!
First time I m very much confused after watching 3 to 4 times i got the idea.. good video. Keep on posting joop. It may increase my programming skills. Thank you, hope you see new date soon.
Thank You for creating this video series. It's so helpful.
The videos are so well explained but not in the proper queue. It becomes challenging for people like me( _who are new to this_ ) to navigate.
Brilliant stuff Joop! You are a real register 'detective' I think :-)
Also nice to point out the fine STM32 work by Roger Clark. Never new of this.
Now to find that STM32 board I bought a few months ago!
I'm starting to mess around with the stm32 arm microcontroller using the keil mdk and man this video is helpful xD Thanks!
Really cool way to explain an elegant solution. Thank you very much!
I didn't understand (as i am medical student), but your work is really awesome. Keep it up brother. You are born with extremely high IQ. Apple needs person like you (they don't have any after Steve Jobs).
your all videos are really helpful.....
In your algorithm to calculate the time duration, there may be two possible cases that make your method fail.
1. The counter has been cleared more than once.
2. The counter has been cleared but the value of the counter is greater than the start value.
I think it would be better if the counter reset flag can be monitored so that such two scenarios cannot happen.
Great explanation, thank you
Excellent videos! Thanks.
can you make a ppm reader tutorial or library? thankyou!
On this receiver you showed the rising edge is the same for all. I'd make the code interrupt for one channel going high and then switch to interrupts for all channels going low. But your code is more flexible, it will work for the non-aligned rises on the other receiver. It is a more generic handler.
Joop, I made an error in my sketch, I'm sorry. I love your effort in this. You have taught me a lot. Thanks again!
Great to hear that you found the problem yourself!
Great work 👍🏻
super informative!
Hey Joop, I just can't thank you enough for your contributions to community through your videos, you took the RUclips tutorials on embedded systems to next level.
Just want to give a small suggestion, in your new quadcopter flight controller, use one separate stm32 microcontroller for reading the gyro data, and transmitting it to main stm32, as you know there are tons of different IMUs available, and tons of different ways to extract and filter data, so, if a user decides to add a different IMU or modify the code for IMU to add functionalities such as Extended Kalman Filter, they will not have to tweek the main algorithm which will not only reduce the processing load on main processor but will give a lot of room(space) and processing power to users for better customization and flexibility of choosing their own IMUs and things like sensor fusion of other sensors such as Magnetometer.
I'm not sure if I will make a GPS quadcopter as it is a ton of work. But I will keep your comment in mind.
I'm not talking about GPS anyway, just saying that, additional STM32 just to handle the IMU will give users a lot of space and processing power to implement heavy duty filters for sensor.
sir we the viewers will really greatful to you ....if you add a camera or gps or magnetometer tonyour new flight controller
the STM32 already has a lot of processing power, hell you can run an autolevel code on an arduino mini pro at 400Hz. The calculations for orientation estimation and PID AND altitude hold can be done in less than 800us(optimized code on my github - github.com/naughtyStark/Altitude-Hold-Drone-Simple ) on an 8 bit 16MHz mini pro. given that the STM32 can be overclocked to 128MHz and is a 32 bit controller, its possible to do all those calculations in 50us(or worst case scenario 100us if you don't force everything to work in float). given that reading data from the mpu6050 takes about 290us, the total time required for the basic stuff is about 340us. adding the GPS doesn't actually add any time requirements because reading the serial port doesn't block the main code, reading the mag is a little tricky but can be done pretty quickly too, so you could do all the sensor communication in about 1ms and then do the calculations in 100-200us and you still have plenty of room(assuming you want a 400Hz update rate).
@@sidharthtalia Hello Friend,
I think it's a pity that you do not report much. Only through you and great people like Mr. Brokking makes RUclips fun. I appreciate your abilities and want more expertise from you. I particularly like the kind of simple and understandable programming series in Arduino IDE.
All the best.
Many Thanks so much for the detailed explanation on how the hardware and software works together. hope to see more.
Opmerking: volgens mij kan het veel simpeler, je hebt volgens mij maar 1 interrupt nodig die op 1 flank afgaat. Voor jouw ontvanger is dat de opgaande flank van een willekeurig kanaal. Je hebt vervolgens 1 capture register nodig om die ene opgaande flank te timen (immers ze komen allemaal te gelijk) en de overige capture registers gebruik je om de afgaande flank van elk kanaal te capturen. Als de interrupt afgaat, lees je alle capture registers uit en bepaal je de eind minus de vorige start waarde. Deze methode werkt volgens mij ook voor de far sky ontvanger (en mijn futaba R617FS), echter dan zet je de interrupt op de afgaande flank van de laatste te meten kanaal en dan zijn de pulse breedtes gelijk aan de onderlinge deltas.
Ik zal vanavond effe kijken of ik een proof of concept kan maken van het hierboven genoemde methode.
Inmiddels heb ik het bovengenoemde methode getest en inderdaad dat werkt, ik heb nu maar 1 interrupt die naar 1 flank kijkt. Zodra de interrupt afgaat bepaal ik alle kanaal waarden uit de onderlinge delta's van de capture registers (getest met de futaba R617FS).
hi, could you link the datasheet please, the only STM32F103C8T6 datasheet i can find is different to the one you show here. Thanks for the amazing videos
Hi, Joop, in this tutorial your explaining very good the PWM, but for your latest project YMFC32 autonomous you 're using the PPM solution.
In that program, I don't find where the signal detection mode changes from rising edge, to falling edge.
That "change" command is well present, but as a comment ...
Hello Joop, can you please explain how you changed the code from reading indevidual PWM signals to one PPM signal ? I cant find it in any video or text.
Hi Joop, as always a superb teaching! You are really a teaching hero :D but how fast/faster is it in the end when compared to the "attach interrupt" method? After all that's what all the work was for, right?
is this code applied to all the flysky 6 ch receivers?
Respect🌻.
Hi sir, firstly thank you. I have learnt so many things in your videos. I am trying to read 6 channel pwm or ppm with esp32 but I have problem about esp32 datasheet. Is it possible to help?
Thank you very very much for the thorough explanation! Quite frankly I am not a skilled programmer yet, But from what I can grasp from your explanation, I suppose it is possible to implement such approach in reading PPM signals? Can you make a tutorial about it? (If ever this is not way to much to ask.)
Where can one find the include file that contains, "Timer2.attachCompare1Interrupt(handler_channel_1);"? I want to generate an interrupt on timer 1 update event but can't find the syntax or any guidance on how to write the line of code. Thanks
your videos are very detailed nice work! Just one piece of feedback coming from someone that knows nothing about drones yet and is focused on learning more about the firmware implementation than building it. I have missed videos covering the source code basic functionality. It would be nice to see more videos like your "Altitude hold programming and implementation" video, where you show more code. But also explaining more about the code basics. For example, how the commands from the Remote Control are received, processed and forwarded to the right functions in charge of moving the drone? I actually am trying to find more related videos covering those things but seems like nobody that builds drones seems to cover too much of those subjects, mainly about communication and control with MAVlink and QGroundControl. I couldn't find a single video showing how MAVlink interfaces with the control movements of the drones in the firmware source code. I actually have a more specific taste because I am developing a open source framework that abstracts all communication between PC, Smartphone and embedded devices with embedded devices as well as hardware abstraction layers of the ESP32 and also STM32 cortex M0 and cortex M4, more specifically but portable to any embedded device. Is something far more advanced and wide than both MAVlink and QGroundControl and all other solutions together but I am trying to understand more about MAVlink and QGroundControl and drones as my framework will solve the same problems that those projects solve. I want to make sure that my framework will be at least much easier to use for developers than those solutions that are already in the market. So I am trying to understand how they interface with the embedded system to make sure my solution will be able better cover those integrations. Is a very generic framework, it covers basically everything, from drones and drone swarms - that not only can be unmanned but also talk and interact to each other or even control each other as the protocol allows - to smart factories and IoT devices, all through Ethernet, Wifi, Wireless radio mesh or RS485. To ensure it is going to be generic for drones I need to better understand the existing solutions for controlling and monitoring manned and unmanned flights and better understand drone users, that's why I decided to write this crazy long text to you. Maybe you will be able to give me some kind of feedback also and help me to understand drone users and developers. In my case I also started building my own drone, very low cost (and small) with an STM32F030C8T6 but I was making the firmware from scratch, all coded by me, so stopped on PWM the motors and communication protocol a long time ago due to lack of time to work on this project. Just made it lift and stopped there, something pretty simple as I was just testing the also generic board I developed for the STM32F030C8T6 MCU at that time.
Hello Joop,
In the previous video you showed the receiver output graph of that futaba receiver in which all the rising edges occur at the same time.. So in this example also all the timer interrupts will get triggered simultaneously, so won't that reduce the accuracy..?
No, the capture function functions will capture the timer value without any delay as it is hardware based.
Is this method causes any jitter on servo pulse if I use with servo? If so then How to correct it?
Do you have the code that reads ppm signal ?
Joop is there a way to do the same with software interrupts?
Hi, your videos are very helpful to me. Thanks for these videos. I have one suggestion for you. Why don't you consider using Keil for programming stm32f103c8t6. It gives you ability to debug the program using st link debugger which is very cheap. Also you get control of complete microcontroller. You don't need to dig up into stm32 libraries for arduino which are made by someone else. Also there is another software available known as stm studio which can be used for real-time data visualization which can be used instead of serial.Print of arduino. This software allows you to get the value of any variable being used in the microcontroller program without doing any modification in the program.
A lot of my viewers are Arduino starters. The Arduino IDE will help them to learn in an easy way as I did myself. Using Keil or similar will create a much steeper learning curve to the STM32 and a lot of creative minds might drop off.
Please remember that my videos are a starting point. My viewers have to explore their own creative road.
You might also consider using the bootloader by Roger Clark to avoid the extra serial USB converter on your breadboard. Thanks for the great videos btw.
Joop Brokking It's very great that you care about your audience. Then It's correct to use arduino.
it is pretty easy to do in STM32CubeMX + Keil uVision
hello everybody, I switched from using a voltage divider to logic level converter IC 5v to 3.3V but I still get the same results ??? would you please help us to overcome this matter
Hi Joop, SUPER JOB in your detailed description in this video. I've been trying to get a simple input capture to work on the STM32 (using the free CoCox IDE) for weeks (part time). I wanted to use the Arduino IDE but didn't know how to use the registers directly. Never got the interrupt to work (using CoCox or Arduino) until you came along - thanks so very much! Question: I wanted to change the PSC for a similar application and see the affect on the measured period, and found the PSC value made no difference. What could be the issue? Best Regards.
Hey- great video. What is the signal's high voltage out of a Futaba Rx (ie: is it 5v or 3.3v)? Is there an issue plugging a Futaba RX PWM channel into an ESP32 or a similar 3.3V MCU?
The output is most likely 3.3V. But it's always best to check it with an oscilloscope.
hey thanks but why you didn't do this with the flysky T6
hi! I just want to say that this is a wonderful video!
Just one question, why not use the PWM input mode in 1:16 ... ?
Good question - I'd not noticed the PWM input mode before.
However, it does appear that there's only one PWM input mode per timer (of which there are four timers - TIM1-TIM4) so it would not support the six channels of this RC receiver.
PWM input mode looks good for when you only have a smaller number of inputs, maybe at higher frequency, and want to measure both period and duty cycle.
is there any possible way to connect Sony PS2 Controller joystick to the stm32 blue pill ?
Hi, Very Nice explanation. I have utilised this Concept for the Measurement of the Pulse Width & Frequency. It works fine. But at low Frequency I need to change the Pre scalar Value . How to do this ?? Thanks in advance .
Ravi
Thank you Mr Joob for this valuable video. You used "ISR (PCINTO_VECT) " in YMFC-al based arduino-uno project. Plz can you give us its equivalent in STM32 board, best regards
@Joop Brokking, big fan btw, I am building a rocket and would like to self land it using jets and elevons, but I very little experience with self balancing, gps, etc. Where should I start? Do you have a tutorial that shows how to self pilot a drone?
Could I connect a raspberry pi or a esp8266 to control it with a mobile app?
I hope that this comment/question finds you well. I am going to be using your videos to build my own quadcopter, and 2 of my children will be building with me. I saw your video about why you are using the STM32F103C8T6 vs. an Arduino Uno, as the STM32 is faster. I found a faster unit and it's by Adafruit called Metro M4 and it uses the ATSAMD51J19 Chip, which is 120MHz vs the 72MHz -- I am having a hard time finding the Timer addressing. Do I want the TC or the TCC? Could you give me a general idea on how I would go about addressing properly for the program?
I know the method shown in the video might be more efficient, but can you use the arduino pulseIn() function?
this is my question as well... is pulseIN still usable with STM32?
In some previous videos you have said gyro angle drift over time .. is this problem is only with mpu 6050 or all gyro have same problem
All gyros have that problem. However the mpu 6050 also have a accelerometer which can fix the angle drift in vertical plane. rotating drift is not as bad as tilting so the mpu 6050 is enough for a drone by itself. If you don't want the rotating drift you can add a magnetometer as well
+1 And a compass is needed to compensate the drift for the yaw axis.
can you explain how to do it ? you are good at basic explanations of such theoretical issues
why you don't make an arduino library?
this code works with flysky t6 ? because i did but it doesn't work, it doesn't read the pulse, i have bind it and wire correctly. plz help me
Hello joop,
in your previous video solved the problem and you read the receiver signals correctly.
Since the signals are read correctly why it is used the input capture mode??
He has to do with the microcontroller or in this way the signals are read more correctly??
The previous method was very inefficient (code size) and slow. This method is more efficient in code size and is not influenced by other interrupts. This makes the input capture mode more accurate.
An clarification,this method(input capture mode) she is necessary for the particular microcontroller(stm32)??
For example we could this method to use it at arduino uno(quadcopter previous project) or to this microcontroller is not deemed necessary??
can this be done using pocketbeagle board?
at 11:46 , you set ccmr2 to zero while it is used as the block diagram shows , is it a mistake ? have you meant ccmr1 in the block diagram?
The block diagram is probably wrong. I have to look it up to be sure. But in the flight controller code you can find this:
TIMER2_BASE->CCMR1 = 0b100000001; //Register is set like this due to a bug in the define table (30-09-2017)
TIMER2_BASE->CCMR2 = 0b100000001; //Register is set like this due to a bug in the define table (30-09-2017)
As you can see both are set.
Did you test PWM to PPM using Arduino mini pro !???, I tried it but does't give the expected results , in the test mode when I choose "a" to read receiver signal , I get values between 99 and 180 and one channel give me 900 !??? Could you help me , by the way I test all the other staff and give me a good results 100/100 , still only the radio pulses and I finish the project.
How can I get the datasheet that u r using ?
how about attiney13 ?
When compiling this sketch I keep getting this error.
timer_setup:56:16: error: 'PWM' was not declared in this scope; did you mean 'PWR'?
'I2C_FAST_MODE' was not declared in this scope; did you mean 'IS_UART_MODE.
Any suggestions?
Hi mate. Big JB fan here from Argentina, watched all your videos (many many times) and used your code on several projects. There's a very nice plane that flies on your PID code, I should upload a video about it soon.
In regards to this particular vide for the capture interrupt, I'm noticing that the code you finally used on the source files does not match the video. Actually, in the handler_channel_1 source code I noticed that you don't change between raising and falling edges... but it works! So... why does it still work? I'm trying to adapt your code to a STM32F401 but can't figure it out. Any help will be much appreciated. Thanks,
Hi Joop
My receiver output signal is 5V and it doesn't work properly. What can be the solution?
What is the Block diagramming software that you use?
It's a powerPoint presentation.
what is the diferent if i use transmitter I6 instead of T6 ?! please help !! =((
👍👍👏👏
Hello,
I do not speak English and so a little bored, I do not understand why I get this line to check the controler "exit status 1 expected constructor, destructor, or conversion type before" ('token.
it appears the line: ISR (PCINTO_VECT) {
could you explain to me.
thank you
when i run your code, it says Hwire is not declared. Which library should i add for it?
Change Hardwire to:
TwoWire HWire (2, I2C_FAST_MODE); //Initiate I2C port 2 at 400kHz.
Thanks bro, yeah i sort it out. It worked. I have build the same design and the code works like a charm. You are a legend :)
Joop, great videos, as others I’ve learned a lot from watching them.
I do have a problem with converting my r6b receiver from PWM to PPM. I followed your instructions on building the Arduino pro mini for the PPM interface but I can’t get it to work.
I was able to run the STM32_ICM_1 program with the r6b receiver viewing channel 1 prior to adding the pro Mini and it worked as in your video. But when I add the pro mini with the additional channels and try running the STM32_ICM_2 program it doesn’t work.
A line of the serial monitor looks like this “1:99 2:99 3:0 4:0 5:11579 6:36127”. None of the values change when I move any of the joysticks.
I thought maybe the pro mini may be the issue so I also tried connecting an Arduino nano and loading the pwm_to_ppm_r6b program on it but I it gave me the same results.
Any guidance would be greatly appreciated.
Thank you and Happy New year :)
Hello. I'm having a hard time getting the code for this project can post it?
Does anybody know what software Joop uses for his schematics
For this video I used Microsoft Powerpoint.
What about the electrical schematic for the YMFC-AL, it looks very professional, and I'd like to use that software to draw stuff for my final year project.
Here's your video with the schematic I'm talking about: ruclips.net/video/DYpHB-LfloI/видео.html
its in "YMFC-AL.zip"
High quality explanation as usual
?
Wait for stm32 with motor blusless.
Great video, thanks for sharing.
I have a question. I connected my receiver with the 6 cables to the stm. 5 channels work perfect, but for some reason one the channels can get "stuck" or "slow"... As in, it doesn't seem to update instantly but somewhat postponed (but even then not with a regular delay but at some point - a 0.5 to 2 seconds later - it will update)... Had that with channel 2 initially. When I swap the cables of channel 1 & 2 everything was fine... Now at some point later channel 2 is working fine, but I channel 4 starting to behave like this... Using d8r-xp and turnigy-9xr. Any ideas anyone?
Update: Seems like declaring the six "int32_t channel_x;" variables at the top as volatile at least gets rid of the 0.5-2 sec delay.... Probably because it's being updated in an interrupt and the main-loop uses a cached value from a register instead of fetching the updated on from memory (slower) - still a bit weird it only happens to one channel. Also have a feeling the "weird" behaving channel is updating slightly slower, or in more discrete steps than the other channels - but that might just be me being oversensitive after chasing this ^^.
Note that there is a tiny copy & paste mistake in STM32_ICM_2.ino in the function handler_channel_3(...). The line reading "channel_3 = TIMER2_BASE->CCR3 - channel_1_start;" should be "channel_3 = TIMER2_BASE->CCR3 - channel_3_start;"
Also, if I may suggest - you could declare the channel_x_start as static inside each interrupt-handler - that limits the scope of the variable (less globals), which is generally a good thing.
Hello, I noticed the copy-paste error recently. I will try to upload the correct code as soon as possible.
Joop you could start a university-level course "Designing, Programming, Building and Flying a Quadcopter." It would have full-enrollment. :)
way not use ppm signal?
Check out my latest videos and you will see that I'm using PPM for the YMFC-32 autonomous.
why dont you use ESP32 it is faster, why is stm32 so special?
i am just confused , why haven't you used this ?
if(micros() - loop_timer > 4050)digitalWrite(12, HIGH); //Turn on the LED if the loop time exceeds 4050us.
//All the information for controlling the motor's is available.
//The refresh rate is 250Hz. That means the esc's need there pulse every 4ms.
while(micros() - loop_timer < 4000); //We wait until 4000us are passed.
loop_timer = micros(); //Set the timer for the next loop.
PORTD |= B11110000; //Set digital outputs 4,5,6 and 7 high.
timer_channel_1 = esc_1 + loop_timer; //Calculate the time of the faling edge of the esc-1 pulse.
timer_channel_2 = esc_2 + loop_timer; //Calculate the time of the faling edge of the esc-2 pulse.
timer_channel_3 = esc_3 + loop_timer; //Calculate the time of the faling edge of the esc-3 pulse.
timer_channel_4 = esc_4 + loop_timer; //Calculate the time of the faling edge of the esc-4 pulse.
It is used in the YMFC-32 flight controller code:
if (micros() - loop_timer > 4050)error = 5;
you may not have understood me , i mean why didnt you use the same method you used in ymfc-al in creating ESC pulses?
Ok, got it now :-)
The STM32 has free programmable timers that can be set and triggered at any frequency. This way it's possible to create the correct output pulse with the timers and I don't have to use the YMFC-AL method.
convincing ,despite that atmel328 has 3 timers also ^_^
Great video... One thing is still not clear though... You're telling (ruclips.net/video/JFSFbSg0l2M/видео.html) that reserved part of the register should not be changed and then your assignment like REG = (1
In the datasheet you can find the initial value of the registers like: "Reset value: 0x0000". And "Reserved, must be kept at reset value". So by keeping them on '0' it should work fine.
In this specific case, the reset value may be all zeros, but 'best practice' should be taught and Maciej is correct (and safe) in his explanation of setting and clearing bits.
Best practice is teaching someone a trick == bad practice. My goal is to explain the core problem so everybody can understand what is going on and decide what is needed to keep the reserved bits untouched. Same as with the qualifier volatile: ruclips.net/video/o3dcmo-hbQw/видео.html
It is not a trick! Read->Modify->Write is the SAFE method. If you are trying to show the core problem, then after you use one method, explain why this will not always be the best way and explain a better more robust and potentialy problem free method. That is teaching. I have been a software developer for 36 years and the number of times I've debugged my employees code and discovered this as the root cause is far too often. So please, show the method you use in the video, but show how it can be improved. ie a better practice. Only use = in a statrtup initialisation function. Everywhere else in you code use |= OR &=~ to modify just the bits you need to.
36 years? Wow...
sounds like to measure the length of the balls (pulse), mine is 6 inch in circumference, lol
joop i heard that stm32 is no longer in production because many users are going back to Atmega32. arduino is mostly used by liars because they can hide their program code within the bootloader