Author Topic: Designing a simple "RC" controller  (Read 2116 times)

0 Members and 1 Guest are viewing this topic.

Offline joker1283Topic starter

  • Newbie
  • Posts: 4
  • Country: us
Designing a simple "RC" controller
« on: November 25, 2017, 11:23:09 pm »
When I used to fly RC helicopter, I can adjust a "curve" on my radio transmitter that relates the motion of the control stick (transmitter) to the motion of the servo at the receiving end. This curve was displayed on a screen and allows user to tune the sensitivity of servo movement at various points. For example, for lower sensitivity, one would have to move the control stick quite a bit for only a little bit of servo movement. This is useful for tasks like hovering where you don't want to overcompensate. For acrobatics, the reverse is true, you want quick response to any input at the control stick.

I want to design a similar device using a microcontroller (like Arduino), a LCD screen, and a motor (either stepper or servo) for output (analogous to the servo on the RC heli), and some kind of input (analogous to the control stick on the transmitter). For the input, the user shall move a linear rack and pinion system, with the pinion hooked to a rotary encoder.

Ideally, the user can push the rack back and forth, which controls the corresponding linear movement at the output. The user should be able to adjust the movement curve on the screen. Furthermore, there should be multiple curves (or mode) that the user can switch back and forth. Any mode switch would be done only when the servo and the rack are at their initial position (or when the system is in a "mode change" mode).

The input and output are at the same device so we don't have to worry about wireless transmission of signals like that of a real RC application.

Can someone give me a rough overview of what I need and how this can be implemented?
Thanks
 

Offline Nitrousoxide

  • Regular Contributor
  • *
  • Posts: 156
  • Country: au
Re: Designing a simple "RC" controller
« Reply #1 on: November 26, 2017, 01:52:59 pm »
What are the user requirements? You've stated roughly what it needs to do, but not any specific needs. (i.e. 5 hour battery life)

Whats the end goal, to produce a PCB or is it just going to be hacked together protoboards?

There are plenty of ways to tackle something like this. If it were me, I'd probably address it in sections:
- Power supply: Battery charging, DC-DC
- Processing: Any microcontroller, MSP432.
- Motor Driver: Depends on load.
- Display: Some generic SPI display(?)

Analog inputs would require appropriate filtering and protection.

Regardless of hardware requirements, it sounds like this is more of a software question that you're posing.

In this case, you can use something known as a "Look up Table", also known as a LUT. Look up tables allow you to map a linear input to a non-linear output, this method is used in a lot of applications (one example is LED brightness curves).

You can implement a LUT through the use of a precomputed array to save on processing time.

Again, not too sure what you are driving with the resulting signal and you may require a closed loop feedback system after the LUT.
« Last Edit: November 26, 2017, 01:56:31 pm by Nitrousoxide »
 

Offline Frankie1AbC

  • Newbie
  • Posts: 3
  • Country: mk
Re: Designing a simple "RC" controller
« Reply #2 on: November 26, 2017, 06:49:38 pm »
Maybe you should check out Arduino Mini and NRF24L01 modules
 

Offline joker1283Topic starter

  • Newbie
  • Posts: 4
  • Country: us
Re: Designing a simple "RC" controller
« Reply #3 on: November 29, 2017, 07:49:02 pm »
What are the user requirements? You've stated roughly what it needs to do, but not any specific needs. (i.e. 5 hour battery life)

Whats the end goal, to produce a PCB or is it just going to be hacked together protoboards?

There are plenty of ways to tackle something like this. If it were me, I'd probably address it in sections:
- Power supply: Battery charging, DC-DC
- Processing: Any microcontroller, MSP432.
- Motor Driver: Depends on load.
- Display: Some generic SPI display(?)

Analog inputs would require appropriate filtering and protection.

Regardless of hardware requirements, it sounds like this is more of a software question that you're posing.

In this case, you can use something known as a "Look up Table", also known as a LUT. Look up tables allow you to map a linear input to a non-linear output, this method is used in a lot of applications (one example is LED brightness curves).

You can implement a LUT through the use of a precomputed array to save on processing time.

Again, not too sure what you are driving with the resulting signal and you may require a closed loop feedback system after the LUT.

Hi, thanks for the reply.

For the output, I plan to use a stepper motor, like the 28byj-48 motor. Power supply will be 4 NiMh AA batteries in series, and this will be used to power everything, including the motor, the microcontroller, etc.

I don't really have requirements on battery life. I'm sure the 4 AA batteries would last more than enough.

The end goal is to make a PCB, but for now, I'm going to try to use a breadboard first to make sure whatever design I use works. Size is not critical at this time.

I also don't plan to use any feedback mechanism. Positional accuracy is not critical.

The part that I need advice on is how to implement that "curve" and displaying it on a screen. You mentioned lookup table. As I understand, the lookup table stores the position information between the input and output correct? How do I actually code this up (I guess this is more of a software question) if I used a stepper motor without feedback? I believe one can only tell the stepper how many "steps" to take and at what speed. So maybe I need to take the derivative of the positions in the lookup table and use that as the stepping frequency?

thanks

 

Offline laneboysrc

  • Contributor
  • Posts: 28
  • Country: sg
    • LANE Boys RC - radio control related electronics
Re: Designing a simple "RC" controller
« Reply #4 on: November 30, 2017, 06:08:16 am »
There are open source RC transmitter projects that you may be able to use as starting point:
http://www.deviationtx.com/
http://www.open-tx.org/
to name a few. They are not based on Arduino, but the calculations are just math anyway.
The code you are looking for is usually part of the "mixer" functionality.

hope it helps, Werner
 

Offline xani

  • Frequent Contributor
  • **
  • Posts: 400
Re: Designing a simple "RC" controller
« Reply #5 on: November 30, 2017, 07:52:17 am »
As for curve, you generally have 2 approaches

One is to make an array that acts as lookup table between input and output value + give user way to tune that (say few pre-generated curves + ability to edit them like change slope/gain)

Advantage is that you can do anything and it is fast (just a memory lookup per event), disadvantage is RAM usage

Other is just to make it one of predefined, parametrized functions (conversely same functions can be used to generate lookup table in the first method) and just give user access to those parameters

As for driving the stepper, I'd just use resulting value as "steps per second" and feed it to loop responsible for driving the stepper motor.
 

Offline Nitrousoxide

  • Regular Contributor
  • *
  • Posts: 156
  • Country: au
Re: Designing a simple "RC" controller
« Reply #6 on: November 30, 2017, 10:12:39 am »
... Power supply will be 4 NiMh AA batteries in series, and this will be used to power everything, including the motor, the microcontroller, etc.

Cool, make sure you implement some form of protection and charge control. Inevitably you'd need to use some form of regulator, either linear or switching (dc-dc buck).

The part that I need advice on is how to implement that "curve" and displaying it on a screen. You mentioned lookup table. As I understand, the lookup table stores the position information between the input and output correct? How do I actually code this up (I guess this is more of a software question) if I used a stepper motor without feedback? I believe one can only tell the stepper how many "steps" to take and at what speed. So maybe I need to take the derivative of the positions in the lookup table and use that as the stepping frequency?

Yes, the LUT stores effectively a "mapping" between function input and output value.

Ideally, you want to precompute most of your data beforehand rather than calculating them in real time, now there are some scenarios where a real-time calculation is the only solution, but for most cases, there will be sufficient system memory to precompute.

As you have no feedback, there is no way to accurately detect the stepper/servo position. Taking the derivative won't help you. You can use a counter to measure how many steps have occurred and thus the total angle/distance displaced. However, If the motor slips then that can never be corrected for (in usual runtime operating, you can force the motor to an extreme/hardstop to trigger a switch to indicate a home position). So when you use the LUT, you'll just have to pray that the motor does not slip so you get a 1:1 mapping of your LUT function.

As per suggested prior, you can just use an array, ill walk through a basic example:

Say I want to create a log LUT for an LED. I would have a function that resembles:

Code: [Select]
ledLut[5] = {0, 0.69, 1.099, 1.39, 1.61};

void ledLutFn(int i) {
    return ledLut[i];
}

What this does is effectively index an array and returns a value. As you may deduce, this only works for integer inputs.
This LUT could either contain speed or position information, it's up to you.

As for displaying to a screen, that is a task that can be solved through many methods. I'd suggest looking at the u8g2lib. https://github.com/olikraus/u8g2/wiki
« Last Edit: November 30, 2017, 10:22:20 am by Nitrousoxide »
 

Offline paulca

  • Super Contributor
  • ***
  • Posts: 4247
  • Country: gb
Re: Designing a simple "RC" controller
« Reply #7 on: November 30, 2017, 10:28:56 am »
If you look at the RC controller settings it more or less explains the formula you need to alter the rates.

Expo, Limits and offsets.

I would create a basic function which takes the parameters:

getOutput( inputValue, expo, upperLimit, lowerLimit, offset ) {
    // Some exponential multiplier within the upper/lower limits
   // Add the offset
    return outputValue
}

This gives you the curve within the limits with the centre offset by the offset value.

Granted higher end radios do allow for multi-point curves which will require more mathematics.

I am not entirely familiar with the microcontrollers, but you might run into issues if it does not support floating point mathematics.  If that is the case, you would need to look up "fixed point" mathematics.
"What could possibly go wrong?"
Current Open Projects:  STM32F411RE+ESP32+TFT for home IoT (NoT) projects.  Child's advent xmas countdown toy.  Digital audio routing board.
 

Offline joker1283Topic starter

  • Newbie
  • Posts: 4
  • Country: us
Re: Designing a simple "RC" controller
« Reply #8 on: December 01, 2017, 01:39:33 am »


Code: [Select]
ledLut[5] = {0, 0.69, 1.099, 1.39, 1.61};

void ledLutFn(int i) {
    return ledLut[i];
}

What this does is effectively index an array and returns a value. As you may deduce, this only works for integer inputs.
This LUT could either contain speed or position information, it's up to you.


Thanks. I understand the idea of an LUT. I just need help on how to actually use it. Let's say the LUT contains position information (my preferred approach), and let's say the LUT looks something like this:

input position      output position
0                         0
1                         1
2                         4
3                         9
4                         16
... and so forth.

The input position is given by how much the rotary encoder ans turned. The output position is given by how much the stepper motor has turned. Let's ignore scaling and the transformation between linear and rotational motion for now.

Initially both the input and output position are at "0". Suppose at time T1, the input position is at 1, the system will look at the LUT and realizes the output needs to be at 1 also. Does my code quickly turn the stepper motor and stops once it has turned enough steps corresponding to position 1 (at the output)?  Then quickly after, the input position is at 2. According to the LUT, the output position needs to be at 4. If my stepper motor rotational speed (step/second) is the same, then it'll take longer to reach 4, so I would need to step faster to reach 4 if I don't want the output to "fall behind" the input too much. So maybe in my code I would need to periodically calculate the difference between the current output position and the desired output position and set my step speed accordingly?

So I guess the output will always lag the input right? As you can see, there are a lot of details that needs to be worked out given that I have a LUT, and this is the part I hope I can get some advice on.

Thanks. I appreciate it.
 

Offline Nitrousoxide

  • Regular Contributor
  • *
  • Posts: 156
  • Country: au
Re: Designing a simple "RC" controller
« Reply #9 on: December 01, 2017, 03:54:22 am »
If my stepper motor rotational speed (step/second) is the same, then it'll take longer to reach 4, so I would need to step faster to reach 4 if I don't want the output to "fall behind" the input too much.

So I guess the output will always lag the input right?

Yes, the motor would take longer to arrive at the destination if the displacement is large enough, and thus you would need to delay any other system that relies upon the motor position after that delay has been completed.

It depends on the rate that you are sending position commands to the motor driver/output, the delay would also depend on the mechanical inertia of the motor, say for different loads your motor might take less/more time to displace.

Note: Be careful when you drive stepper motors too fast as they may skip steps.

So maybe in my code I would need to periodically calculate the difference between the current output position and the desired output position and set my step speed accordingly?

What you just described is a closed loop control system :P
You're monitoring the current, measured value and comparing it to the desired value which produces a known "error". This "error" value can be then fed through a compensator so find the optimum output value to correct for this "error".

A closed loop control system will address the speed and displacement errors, both in transient and steady state. I'm fairly confident most motor systems are closed loop.

To implement this properly, you would need a sensor on the motor output. You would not be able to implement this technique by just "counting" the motor steps in software (which is effectively just guessing) and subtracting it from the set value.
 

Offline paulca

  • Super Contributor
  • ***
  • Posts: 4247
  • Country: gb
Re: Designing a simple "RC" controller
« Reply #10 on: December 01, 2017, 07:44:30 am »
In RC the transmittor sends the required position to the servo (via the receiver) as PWM pulses.  The server moves using a control feedback loop to the position it knows represents that pulse width.  This is why (usually cheap) servo's often buzz as they get caught between two positions and oscillate.   The advantage is, if you grab the servo and try and move it out of that position it will fight you to get back to it.

They use a highly geared motor and a position sensor rather than a stepper motor per-sae.  Depending on your application you need to consider the output motor needs to apply torque to achieve it's goal of moving something with sizeable force.

I suppose in the line of thought of this thread the servo needs to know it's position, so it needs feedback within itself which I believe is done electronically and not digitally but the controller and receiver do not.  They trust the servo goes where they tell it.  Thus the when you look at the servo positions in an RC transmitter they are not telling you the position of the servo they are just telling you the commanded position and trusting the servo went were it was told.
"What could possibly go wrong?"
Current Open Projects:  STM32F411RE+ESP32+TFT for home IoT (NoT) projects.  Child's advent xmas countdown toy.  Digital audio routing board.
 

Offline macboy

  • Super Contributor
  • ***
  • Posts: 2287
  • Country: ca
Re: Designing a simple "RC" controller
« Reply #11 on: December 01, 2017, 02:40:28 pm »
When I used to fly RC helicopter, I can adjust a "curve" on my radio transmitter that relates the motion of the control stick (transmitter) to the motion of the servo at the receiving end. This curve was displayed on a screen and allows user to tune the sensitivity of servo movement at various points. For example, for lower sensitivity, one would have to move the control stick quite a bit for only a little bit of servo movement. This is useful for tasks like hovering where you don't want to overcompensate. For acrobatics, the reverse is true, you want quick response to any input at the control stick.

I want to design a similar device using a microcontroller (like Arduino), a LCD screen, and a motor (either stepper or servo) for output (analogous to the servo on the RC heli), and some kind of input (analogous to the control stick on the transmitter). For the input, the user shall move a linear rack and pinion system, with the pinion hooked to a rotary encoder.

Ideally, the user can push the rack back and forth, which controls the corresponding linear movement at the output. The user should be able to adjust the movement curve on the screen. Furthermore, there should be multiple curves (or mode) that the user can switch back and forth. Any mode switch would be done only when the servo and the rack are at their initial position (or when the system is in a "mode change" mode).

The input and output are at the same device so we don't have to worry about wireless transmission of signals like that of a real RC application.

Can someone give me a rough overview of what I need and how this can be implemented?
Thanks

A rotary encoder is a bad idea for the input. The problem is with missed codes. What happens when it is turned too fast (or too slowly) to capture the movement accurately? In the normal usage scenario for a rotary encoder, this doesn't matter, as it has no absolute position. But you are confining it to a specific amount of rotation with the linear slider and rack and pinion apparatus, so you must know the absolute position. A rotary encoder is intended to be a "speed and direction of rotation" type sensor, not an absolute position sensor. Instead, use either a normal potentiometer with your rack and pinion, or get a linear/slide type potentiometer, which is much simpler still. Use the pot as a voltage divider to feed and A/D of the micro, and you will very easily know the absolute position of the slider.

A servo is the easiest output device. That is because all of the motion control smarts are contained within the servo itself. All that you need to do to command it to move to a specific position is to supply a pulse of (nominally) between 1 ms and 2 ms width/duration. 1 ms is full left, 2 ms is full right, and 1.5 ms is the mid-point. Usually the pulse is sent at a rate of roughly 50 times per second. Different servos may accept more or less frequent updates than that, but 50 Hz is the norm.

For the "curve", you have a lot of options. You could provide say 10 points of adjustment, and allow the user to move the input/output point away from the straight line. Then you must interpolate between points, either linearly or using some type of best-fit curve algorithm. Or you could do it with something like a power-law deviation, very similar to the "gamma" curve used for TVs and computer monitors.

I'd suggest implementing a minimum first: the input (reading the pot's position), calculating some curve (that you define at compile time), and commanding the servo. Play with different curves/algorithms. Notice how using only 8 bits for the input and output will result in a "dead zone" near zero, but increasing to much greater resolution (especially for the output) will improve that. After you have that sorted these fundamentals, then move on to create some kind of user interface to allow a run-time modification of the curve.
 

Offline paulca

  • Super Contributor
  • ***
  • Posts: 4247
  • Country: gb
"What could possibly go wrong?"
Current Open Projects:  STM32F411RE+ESP32+TFT for home IoT (NoT) projects.  Child's advent xmas countdown toy.  Digital audio routing board.
 

Offline joker1283Topic starter

  • Newbie
  • Posts: 4
  • Country: us
Re: Designing a simple "RC" controller
« Reply #13 on: December 04, 2017, 02:18:13 am »
A rotary encoder is a bad idea for the input. The problem is with missed codes. What happens when it is turned too fast (or too slowly) to capture the movement accurately? In the normal usage scenario for a rotary encoder, this doesn't matter, as it has no absolute position. But you are confining it to a specific amount of rotation with the linear slider and rack and pinion apparatus, so you must know the absolute position. A rotary encoder is intended to be a "speed and direction of rotation" type sensor, not an absolute position sensor. Instead, use either a normal potentiometer with your rack and pinion, or get a linear/slide type potentiometer, which is much simpler still. Use the pot as a voltage divider to feed and A/D of the micro, and you will very easily know the absolute position of the slider.

Let me get this straight. I thought the rotary encoder will tell you the pulses that corresponds to a certain degree of rotation and also the direction of rotation. Therefore, if you have a "home" position in your code, then you can count the number of pulses along with their directions to calculate an relative position right? For example, the user lines up the rack and pinion in a certain way, and calls this "home", he might even press a button to the micro controller to make this home, and the pulse count will be set to 0.  Then we can know the relative position by simply keeping track of the pulses from the rotary encoder right? (assuming there are no missed code)


A servo is the easiest output device. That is because all of the motion control smarts are contained within the servo itself. All that you need to do to command it to move to a specific position is to supply a pulse of (nominally) between 1 ms and 2 ms width/duration. 1 ms is full left, 2 ms is full right, and 1.5 ms is the mid-point. Usually the pulse is sent at a rate of roughly 50 times per second. Different servos may accept more or less frequent updates than that, but 50 Hz is the norm.

I'm learning about servos now. So basically, you control a stepper by specifying the frequency of steps (each control signal corresponds to a "step", and you can specify how fast it steps, like by changing the delay between each step). So you only get to control the rotational velocity.

But you can control the servo by specifying a position? In another word, the input signal will corresponds to a position and the servo will move there quickly without you having to worry about the velocity?


For the "curve", you have a lot of options. You could provide say 10 points of adjustment, and allow the user to move the input/output point away from the straight line. Then you must interpolate between points, either linearly or using some type of best-fit curve algorithm.


That's what I had in plan.

Thanks
« Last Edit: December 04, 2017, 02:27:46 am by joker1283 »
 

Offline paulca

  • Super Contributor
  • ***
  • Posts: 4247
  • Country: gb
Re: Designing a simple "RC" controller
« Reply #14 on: December 04, 2017, 09:36:49 am »
But you can control the servo by specifying a position? In another word, the input signal will corresponds to a position and the servo will move there quickly without you having to worry about the velocity?

Pretty much yes.  It will also try and remain there as long as you keep sending the pulse width.  You can try and move the servo away from that position and it will do whatever it can to remain or move back to that exact position.  If you stop sending the signal (most) will go limp and might even go random and jittery.  There are a few with memory which will still hold their last position even when you remove the input signal.
"What could possibly go wrong?"
Current Open Projects:  STM32F411RE+ESP32+TFT for home IoT (NoT) projects.  Child's advent xmas countdown toy.  Digital audio routing board.
 

Offline macboy

  • Super Contributor
  • ***
  • Posts: 2287
  • Country: ca
Re: Designing a simple "RC" controller
« Reply #15 on: December 05, 2017, 04:18:54 pm »
A rotary encoder is a bad idea for the input. The problem is with missed codes. What happens when it is turned too fast (or too slowly) to capture the movement accurately? In the normal usage scenario for a rotary encoder, this doesn't matter, as it has no absolute position. But you are confining it to a specific amount of rotation with the linear slider and rack and pinion apparatus, so you must know the absolute position. A rotary encoder is intended to be a "speed and direction of rotation" type sensor, not an absolute position sensor. Instead, use either a normal potentiometer with your rack and pinion, or get a linear/slide type potentiometer, which is much simpler still. Use the pot as a voltage divider to feed and A/D of the micro, and you will very easily know the absolute position of the slider.

Let me get this straight. I thought the rotary encoder will tell you the pulses that corresponds to a certain degree of rotation and also the direction of rotation. Therefore, if you have a "home" position in your code, then you can count the number of pulses along with their directions to calculate an relative position right? For example, the user lines up the rack and pinion in a certain way, and calls this "home", he might even press a button to the micro controller to make this home, and the pulse count will be set to 0.  Then we can know the relative position by simply keeping track of the pulses from the rotary encoder right? (assuming there are no missed code)

Again the problem is missed codes, either from going too quickly or too slowly.
Try an experiment: Find something with a rotary encoder, say the cursors position control of a digital oscilloscope, or the volume control of some home theatre receiver. Put the cursor (or volume) at some level. Mark the position of the knob against the faceplate with some tape. Now spin it back and forth multiple times at various speeds, fast and slow. Return to original marked position. Is the cursor (volume) now set exactly where it was when you started?

Quote

A servo is the easiest output device. That is because all of the motion control smarts are contained within the servo itself. All that you need to do to command it to move to a specific position is to supply a pulse of (nominally) between 1 ms and 2 ms width/duration. 1 ms is full left, 2 ms is full right, and 1.5 ms is the mid-point. Usually the pulse is sent at a rate of roughly 50 times per second. Different servos may accept more or less frequent updates than that, but 50 Hz is the norm.

I'm learning about servos now. So basically, you control a stepper by specifying the frequency of steps (each control signal corresponds to a "step", and you can specify how fast it steps, like by changing the delay between each step). So you only get to control the rotational velocity.

But you can control the servo by specifying a position? In another word, the input signal will corresponds to a position and the servo will move there quickly without you having to worry about the velocity?
Yes. You move a stepper in steps. The speed is determined by the speed of stepping it, but the position is (hopefully) determined by the actual count of the steps. If you go 100 one way then 100 the other, no matter the speed, you should end up at the original position. If the motor is loaded down too much or you try to step too fast, it might miss some steps then you have a similar situation to the rotary encoder.

A hobby servo has a geared-down motor, a position sensor (potentiometer), and control logic to move it to the desired spot. It will move to the new position as fast as possible. They have a speed rating which is in seconds per 60 degrees of rotation, and a torque rating. You control it by telling it the desired position, encoded as a pulse length as described above. There are many resources to learn more, as these are increasingly common on robotics in addition to R/C applications. As paulca mentioned, most will stop powering the motor (go limp) if/when the control signal pulses stop coming in. Others might self-center or poorly designed ones might go hard CW or CCW.

Servos are very easy to control with a microcontroller. You just set up a PWM output to give a repeating pulse at the desired width. Of course there are many Arduino libraries out there, and examples for probably any other architecture. There are also ICs which control multiple servos without the contant work from the micro, you just send commands over I2C and it takes care of generating the pulse train for each servo. (search evilbay for "arduino 16 channel servo" for example).
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf