I use two OLIMEXINO 85 to implement a 2 channel remote control and control 2 digital servos. In general, it works already, but the servos are vibrating all the time.
A digital servo needs a pulse of 1.5 ms for neutral position. A shorter or longer pulse turns it left or right.
delayMicroseconds() is a blocking loop that is better than 0.5usec accurate, but it assumes no interrupts. SO if you code has plenty of them delayMicroseconds run out of sync.
If you want really accurate timing you must use the internal timers.
Finally your code contains a possible bug
adding time is no good idea as it might overflow causing unwanted effects
GoForSmoke:
Suppose you only send the servo a pulse when you want it to move?
If it has to be continuous, that's what PWM is for.
You are right, but I am afraid that the resolution is too low (1:255). I need pulses with HIGH levels from 1000...2000 microseconds and LOW levels 30000 microseconds. 30000 / 255 = 117, so I have only 8 possible values between 1000 and 2000.
I tried already "#include <Servo.h>" but compilation causes many errors. There are many "if"s in the source code depending on the hardware. Perhaps my OLIMEXINO 85 does not match.
UKHeliBob:
Please post an example program that exhibits the errors. It need only be about 10 lines long, if that.
It's not about my code, it is only a program with "#include <Servo.h>" and nothing else.
The result (directory path shortened):
...\libraries\Servo\src\avr\Servo.cpp: In function 'void __vector_3()':
...\libraries\Servo\src\avr\Servo.cpp:82:44: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint16_t* {aka volatile unsigned int*}' for argument '2' to 'void handle_interrupts(timer16_Sequence_t, volatile uint16_t*, volatile uint16_t*)'
handle_interrupts(_timer1, &TCNT1, &OCR1A);
^
...\libraries\Servo\src\avr\Servo.cpp: In function 'void initISR(timer16_Sequence_t)':
...\libraries\Servo\src\avr\Servo.cpp:128:5: error: 'TCCR1A' was not declared in this scope
TCCR1A = 0; // normal counting mode
^
...\libraries\Servo\src\avr\Servo.cpp:129:5: error: 'TCCR1B' was not declared in this scope
TCCR1B = _BV(CS11); // set prescaler of 8
^
...\libraries\Servo\src\avr\Servo.cpp:136:5: error: 'TIFR1' was not declared in this scope
TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
^
...\libraries\Servo\src\avr\Servo.cpp:137:5: error: 'TIMSK1' was not declared in this scope
TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
^
I've seen those kind of errors before, usually when I had my library files in the wrong folder.
Before writing to the servo you might want to check in the current value is even close to the previous, make a dead zone just wider than a wobble and have that only where the servo gets written to.
Some day I should get a cheap servo just to dink with it.
Plenz:
... can see on my oscilloscope that both pulses are jittering a little bit, roughly estimated +/- 5 micro seconds.
As Rob pointed out an interrupt will lengthen the delay. The timer 0 interrupt, the one that keeps the millis clock updated, takes roughly 5us to execute. It is invoked about once every millisecond.
You really need to use a timer that keeps ticking regardless of interrupts. Micros() does that but only has a 4us resolution. You haven't said how precise the delays need to be. But you're probably going to need to directly use a hardware timer.
One other possible approach is temporarily disabling timer 0 when calling delayMicros(). But whether you can get away with that depends on what else you're doing.
Tiny85 needs a different servo library (or a servo library that checks for the 'x5 series and adjusts accordingly), cause it's timers are wierd (it's timer1 isn't the normal 16-bit one, but a crazy one that can be clocked off the PLL)
GoForSmoke:
Before writing to the servo you might want to check in the current value is even close to the previous, make a dead zone just wider than a wobble and have that only where the servo gets written to.
It works theoretically if I create a pulse only if there is a change in the pulse width.
Unfortunately, if there are no pulses, the servo switches its power off. The things which the servo shall move may have forces which can turn the servo. So there is a constant stream of pulses necessary to keep the servo on its position.