Skip to content

the-cave/servo-helmsman

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Servo Helmsman

What is it?

Servo Helmsman is an RC servo controller library built to last. With extreme portability, agnostic to platform and processor, and asynchronous non-blocking API.

Controlling an RC servo's would usually complicate project code considerably with the timing requirements, let alone controlling multiple servos.
Servo Helmsman abstracts away the complication and exposes more manageable intuitive interfaces with asynchronous API.

Porting?

No need, the code is hardware and platform agnostic. It will run everywhere as long as C language works. However, since the timing is critical to the servo controlling, the library would work well on a sufficiently fast processor.

The intuitive API

As an embedded system developer, one would want to simply call servo.set_position(angle), and everything else should be taken care of by the underlying library. And this library happens to provide the API described.

Usages

There are multiple methods exposed by the library, but the most interesting one as a library consumer is servo_helmsman__set_position(&config, &state, position). Every other method is for runtime supporting, but they are crucial for making the library functioning.

The library can be set up by declaring a Helmsman instance and implementing a GPIO signal output.

#define OFFSET 7

static void servo_output(bool state);
static const ServoHelmsman_Config servo_config = {
    .offset = OFFSET, // more info later
    .output = &servo_output,
};
static ServoHelmsman_State servo_state;
static void servo_output(bool state) {
  if (state) {
    GPIOC->ODR |= GPIO_ODR_ODR14;
    return;
  }
  GPIOC->ODR &= ~GPIO_ODR_ODR14;
}

Initialize the state on program starts.

servo_helmsman__init(&servo_state);

Calling cycle_sync every 20 milliseconds.

servo_helmsman__cycle_sync(&servo_config, &servo_state);

Calling step_poll periodically with less than 1 millisecond interval. (more info below)

servo_helmsman__step_poll(&servo_config, &servo_state);

Once setup, the library is now ready for use by consumers.

servo_helmsman__set_position(&servo_config, &servo_state, DESIRED_POSITION);

parameter explanations

Some parameters need to be known.

  • The interval to poll the step_poll method
  • The offset and position variables

They are unsurprisingly explained in the same section because they are interconnected.

Simply put, a pulse generated by an instance of Servo Helmsman has the width of offset + position. And the unit of the pulse width is controlled by the interval between each step_poll calling.

For example, if I wanted to generate 1.5 milliseconds pulse width, this is one way to do it:

  • calling step_poll every 100 microseconds
  • set offset to 10
  • set position to 5

There are infinitely many ways to achieve the same thing, but there are some boundaries.

Here are some of my observations

  • Most of the applications only require the servo horn to be in 2 positions.
  • Despite the above observation, the maximum number for the position can't usually be 1. (thus, the total positions of 2; 0 and 1) Because you will not be able to calibrate the offset variable anymore with the step_poll interval fixed to the roughest value possible.
  • Most servos don't respect the ideal control signal; you often can't determine the offset, position, and poll interval with the calculation method alone.
  • If you poll the step_poll too frequently, the overrun issue is likely to occur.
    For example, if you poll the method at the 10-microseconds interval, and the processor can execute 8 instructions per microsecond (8 MHz), your main loop would have theoretically 80 instruction budgets to run (and poll) everything or each loop would overlap.
  • On the other hand, if the interval is too high, you can't calibrate the offset value with reasonable precision, as mentioned.
  • If you want the servo to be able to be set at the center with symmetric steps, the maximum position number must be an even number.
  • This library uses uint8_t as a type of position; you can't use it for any higher precision requirements. In fact, I don't think you would even considering servo in the first place.
  • My personal approach to determining these 3 variables is by setting the position to 11 steps (0 to 10) and calibrate for another 2 variables with the actual hardware.
  • Don't calibrate the variables too hard; at the end of the day, you can always customize the servo's horn's angle when attached. Don't aim at the perfect center, because it does not really matter anyway.

Prerequisites

License

Servo Helmsman is released under the BSD 3-Clause License. 🎉