Servo operation with simple pluses, no library

Hopefully my commented code is self-explanatory.

I'm puzzled why using microseconds for the delays doesn't work?

/*
  Servo Motor Control — 50Hz pulse Generator
  A simple demo not using the Arduino library
  Intended to satisfy myself that the servo's position (angle)
  depends on the width of the high-going pulse

  The Frequency setting of a DMM conneceted to pin 9 will display
  50 Hz

  A 'scope shows the respective high and low sections

  Terry, 29 October 2019
*/

int servoPin = 9;

void setup()
{
  pinMode(servoPin, OUTPUT);
}
void loop()
{
  // Sends a 50Hz train of pulses, High for 2 ms
  // and Low for 18 ms.
  // Total duration = 20 ms ==> 50 Hz

  // This pair of code lines take the servo to its approximate
  // anti-clockwise extreme
  digitalWrite(9, HIGH);
  delay(2); // 2 ms HIGH
  digitalWrite(9, LOW);
  delay(18); // 18 ms LOW
  // Where it remains

  // Similarly, the following (commented out) code takes it roughly
  // to the other extreme
  //digitalWrite(9, HIGH);
  //delay(1); // 1 ms HIGH
  //digitalWrite(9, LOW);
  //delay(19); // 19 ms LOW

  // So I was surprised that if microseconds units like those
  // below are used instead, the servo 'sticks', buzzing, with
  // a heavy current consumption.
  //delayMicroseconds(1000);
  //delayMicroseconds(19000);

  // The several minor changes I tried to the values made
  // no difference
}

That is a little odd, and not my experience, i do know that delayMicroseconds(0); does cause strange behavior, but that is not what you've used. Anyway how have you fared using micros() ?

https://www.arduino.cc/reference/en/language/functions/time/delaymicroseconds/

Currently, the largest value that will produce an accurate delay is 16383. This could change in future Arduino releases. For delays longer than a few thousand microseconds, you should use delay() instead.

@Danois90: Thanks, that must be it, didn't spot that limitation. I tried this code and no sticking/buzzing. But with 16 ms for the LOW it meant 4 ms for the HIGH, to retain the required 50 Hz, which seems too long, so I'm sort of surprised it worked.

/*
  Servo Motor Control — 50Hz pulse Generator
  A simple demo not using the Arduino library
  Intended to satisfy myself that the servo's position (angle)
  depends on the width of the high-going pulse

  The Frequency setting of a DMM conneceted to pin 9 will display
  50 Hz

  A 'scope shows the respective high and low sections

  Terry, 29 October 2019
*/

int servoPin = 9;

void setup()
{
  pinMode(servoPin, OUTPUT);
}
void loop()
{
  // Sends a 50Hz train of pulses, High for 1 ms
  // and Low for 19 ms.
  // Total duration = 20 ms ==> 50 Hz

  // This pair of code lines take the servo to its approximate
  // anti-clockwise extreme
  digitalWrite(9, HIGH);
  delayMicroseconds(4000); // 4 ms high (Surely way too much?)
  digitalWrite(9, LOW);
  delayMicroseconds(16000); // 16 ms LOW
  // Where it remains

}

Yes 4ms is way too long but many servos will simply treat it as maximum pulse length and go to their limit. Other servos will do nothing because it's an invalid control signal.

BTW 50Hz isn't a given. Most servos work perfectly well up to around 100-120Hz. They just need a low that's considerably longer than the longest valid pulse length. 4-5ms is often enough for the low.

Steve

Thanks Steve.

Terry.

slipstick:
BTW 50Hz isn't a given. Most servos work perfectly well up to around 100-120Hz. They just need a low that's considerably longer than the longest valid pulse length. 4-5ms is often enough for the low.

or up to 20hz is fine, the frquency does not really not to be consistent either, it is a 'latch' so using a 'delayMicroseconds()' for the high and just 'delay(20)' for the low should work just fine.

Thanks @Deva_Rishi.

As an experienced electronics hobbyist but not a programmer I'm finding servo coding quite heavy going.

I'll write a new post expanding on this, as it would be OT in this thread.

Terry.

As an experienced electronics hobbyist but not a programmer I'm finding servo coding quite heavy going.

Why not just use the Servo library ?

untested!

 unsigned long pulseLen = 2300; // 544 ~ 2400
  digitalWrite(9, HIGH);
  delayMicroseconds(pulseLen); // 2.3 ms high (Surely way too much?)
  digitalWrite(9, LOW);
  delayMicroseconds(20000 - pulseLen); // 17.7 ms LOW
  // Where it remains

}

delayMicroseconds(20000 - pulseLen); // 17.7 ms LOWYou have obviously not read the whole thread particularly reply #2

UKHeliBob:
Why not just use the Servo library ?

It can be quite educational and fun to use hardware without a library :wink:

Currently I'm writing my own code for a BME280 sensor without using anything else than the spec sheet and the process is teaching me a lot about how the I2C bus is working.

UKHeliBob:
Why not just use the Servo library ?

If interrupts are going to be turned off at any time the Servo library is unreliable, i found that to be a pretty good reason, also since that happens when you make use of other (timer) interrupts. (or the library influences the other interrupts) By manually firing a pulse you can prevent this from happening.

@Deva_Rishi:
Yes, I KNEW that max delayMicroseconds() was 16383, guess I'm getting too forgetful, absent minded, senile or whatever. Time to switch to "lurk only". :confused: