Direct port register addressing to control servo motor

Please tell me that is it possible to use direct port register addressing to control servo motor in Arduino?
For example, I used direct port register addressing to create running effect of 4 LEDs using DDRx and PORTx commands.
So in the same way, is it possible to control servo motor in Arduino UNO?
Please help.

What exact "servo motor'" are you talking about?

What code have you seen or written that controls it so far?

Why do you think direct port access is needed or desirable?

a7

Possible, but there is no obvious reason to do so.

I want to use SG90 small servo motor.
I never seen any such code yet, nor did I try any coding for it.
Just wondering, if at all, it is possible to control servo motor using direct port access.
Please guide if such controlling is possible.

Please give me some hint for it. So I will try.

Possible but you will be making way more work for yourself with absolutely no benefit.

SG90 servos can be controlled and made to do anything they are capable of on one pin using the servo library.

If using a library offends you, learn how to do it "by hand" - reading the servo library code might give you ideas, might make you change your mind.

I've come as close as I dare to saying that controlling an SG90 with direct port addressing is the dumbest thing I've read today.

a7

Use the servo library.

Ok.
Thanks for the reply and guidance.
Though this idea appears dumbest, but I will surely try working on servo library code.
Thanks for the hint.
I am thinking of following the trail of AVR coding in ATMega16 to drive servo motor using Timers, which I hope could be brought up in Arduino for direct port access.
Anyway, thanks again for the library code hint.

Are you familiar with the signal needed to control a servo?

Yes. Familiar quite well. It requires PWM signalling, series of repeating pulses of variable width of pulses.

Yes, this is certainly possible. The details will vary a great deal depending on how you want things to work. For example:

void loop() {
  uint16_t pos = map(analogRead(0), 0, 1023, 1000, 2000);  // map pot to servo us
  PORTD |= 0b100;          // Servo pulse positive
  delayMicroseconds(pos);  // pulse of 1 to 2ms determines servo position.
  PORTD &= ~0b100;         // Servo pulse off
  delay(20);               // 20ms till the next pulse.
}

Or, timer1 can be set up to output servo pulses continuously and atonomously.
Or a timer can be used to time the servo pulse, but not the inter-pulse time.
Or you could set up the WDT to interrupt for the inter-pulse time, and use a timer for the pulse.
And you'd want to consider whether you're driving one servo, several servos, or many servos.

1 Like

Wow! That's so helpful.
Thank you so much for explaining it in such a simple way.
Thanks again and again.

I made a simulation that does not use a library. Maybe this will suit your purpose?

2 Likes

I thought the servo library used the timer to generate the servo pulse, and then stepped to the next servo after an interrupt, allowing it to handle multiple servos on multiple pins.
A library that only does one servo is considerably less useful.

The simulation is really interesting.
Thank you so much for sharing.

It really works! :smile:
Thank you so much for the valuable guidance.
I have created the simulation here.

1 Like

… simulation. Thanks!

Pro tip - the slide fader available in the wokwi works much better for an analog input!

If you started from knowing how servos work, and knowledge of the pulses necessary, the inquiry amounts to just learning (or being shown) how to use direct port access, which... you also knew about. The only step you have been helped to make is to combine the two. Unless you've never used delay() or hadn't heard of delayMicroseconds()…

Your example works fine with pinMode() and digitalWrite(), so I hope that explains to you why I found your question to be odd.

I understand the advantages of using direct port manipulation. To the extent that it is necessary to decrease the time taken to change an output bit, you are doing better. But your solution must be then compared to how fast a servo library does the same thing.

But before you go to any trouble looking into that, the time for any method of changing an output pin can be totally accounted for in the context of creating a pulse of 1000 to 2000 microseconds every 20 milliseconds.

Your solution uses blocking techniques in the synthesis of output waveforms. This may make it far less useful in any real deployment.

added: please take a look at @xfpd's sim in #14. Non-blocking and able to provide a loop frequency of > 2.5 6 kHz.

a7

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.