This library looks great, thanks. I think I understand ServoIn and ServoOut examples ok, but I don'y know how to tie the two together, ie get a value with ServoIn and simply echo out to ServoOut. Ideally, I only need one channel, but I want to grab an input value when it changes, half the period, then output it with ServoOut at a fixed frequency. So, the output just runs at a fixed frequency and the output pulse width changes whenever the input pulse wodth changes, but at half the width. You huessed, I want to make a 1520uS to 760uS adapter :). Any hints appreciated, thanks.
G
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The first parameter passed to the constructor of ServoIn is an array which will contain the incoming signals in microseconds. The values in this array will be updated every time you call the update function. (see the ServoIn example)
The second parameter of the ServoOut constructor is an array that contains the outgoing signals in microseconds. You'll need to fill this array with (modified) values based on the array used by ServoIn. After that, call the update function on ServoOut.
Initialize everything in the setup function (set up timer, interrupts pin modes and start both g_servoIn and g_servoOut.
And your loop function will look something like this:
void loop() {
g_servoIn.update();
for ( uint8_t i = 0; i < SERVOS; ++i )
g_valuesOut[i] = g_valuesIn[i]; // perform extra processing here
g_servoOut.update();
}
Don't forget to copy the ISR function from the servoIn example or the code won't register incoming signals.
Good luck!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
That's great, many thanks for such a quick and comprehensive reply. I assume the output does run at some fairly constant frquency, am I right in thinking I need to call ServoOut::setPauseLength() in setup() to set the frequency?
G
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think the default length between two pulses (pause length) is 10000 microseconds by default, so that means 100 pulses per second on each output pin. Set it to 20000 to get 50 Hz or 5000 to get 200 Hz for example.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for that. I've started with a straight output = input test, but I'm getting no output at all. Is the library OK on a Nano or are some Nano pins different?. Thanks.
G
#include<ServoIn.h>#include<Timer1.h>#include<ServoOut.h>#define SERVOS 4uint16_tg_valuesIn[SERVOS];uint16_tg_valuesOut[SERVOS];uint8_tg_workIn[SERVOIN_WORK_SIZE(SERVOS)];uint8_tg_workOut[SERVOOUT_WORK_SIZE(SERVOS)];uint8_tg_pinsOut[SERVOS]={2,3,4,5};uint8_tg_pinsIn[SERVOS]={8,9,10,11};staticuint8_tlastB=0;rc::ServoIng_ServoIn(g_valuesIn,g_workIn,SERVOS);rc::ServoOutg_ServoOut(g_pinsOut,g_valuesOut,g_workOut,SERVOS);voidsetup(){// Initialize timer1, this is required for all features // that use Timer1 (PPMIn/PPMOut/ServoIn/ServoOut)rc::Timer1::init();for(uint8_ti=0;i<SERVOS;++i){pinMode(g_pinsIn[i],INPUT);// set up input pins pinMode(g_pinsOut[i],OUTPUT);// set up output pinsdigitalWrite(g_pinsOut[i],LOW);// put them low}// only allow pin change interrupts // for PB0-3 (digital pins 8-11)PCMSK0=(1<<PCINT0)|(1<<PCINT1)|(1<<PCINT2)|(1<<PCINT3);// enable pin change interrupt 0PCICR=(1<<PCIE0);g_ServoIn.start();g_ServoOut.start();}voidloop(){// update incoming valuesg_ServoIn.update();// Half the incoming pulse width, ie 1000..2000 becomes 500..1000// We have 760uS at 200Hz. OK for tail servos.for(uint8_ti=0;i<SERVOS;++i)g_valuesOut[i]=g_valuesIn[i];// tell ServoOut there are new values available in the input bufferg_ServoOut.update();}// Pin change port 0 interruptISR(PCINT0_vect){// we need to call the ServoIn ISR here, keep code in the ISR to a minimum!uint8_tnewB=PINB;uint8_tchgB=newB^lastB;// bitwise XOR will set all bits that have changedlastB=newB;// has any of the pins changed?if(chgB){// find out which pin has changedif(chgB&_BV(0)){g_ServoIn.pinChanged(0,newB&_BV(0));}if(chgB&_BV(1)){g_ServoIn.pinChanged(1,newB&_BV(1));}if(chgB&_BV(2)){g_ServoIn.pinChanged(2,newB&_BV(2));}if(chgB&_BV(3)){g_ServoIn.pinChanged(3,newB&_BV(3));}}}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The library was written for and tested on both Uno and Nano (Atmega 168/328). I'd start with putting a few Serial.println here and there, see if you get some input (set the serial speed to as high as possible to reduce the risk of messed up interrupts). Then check the output pins with either a scope or some LEDs (with current limiting resistor of course) to see if you get any output at all. This kind of problem can be hard to test, the best way is to start at the input stage and work your way to the output stage.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, I should have said that Serial debugging showed no output. The cause of that was reading the nano pinout upside down and wiring the input and out reversed :). Having corrected that, I now have input, varying correctly as I vary the input pulse width, but I do not have output. I'm setting g_valuesOut[0,1,2,3] to g_valuesIn[0,1,2,3], calling g_ServoOut.update() in the loop, and getting no output. Serial print of input value, output value before out update, and output value after out update all show the same correct value, but the physical outputs get nothing, it just sits near ground voltage. Am I ok to put serial debug writes amongst ServoOut.cpp please ?
Output pins 2, 3, 4, 5 are port D on the Nano and input pins 8,9,10,11 are port B. Is that definitely ok please?.
G
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
That's weird, update(true) only needs to be called when you've changed the pins. It recalculates the port and bit for each pin. Oh well, if it works... :)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, it works, but the servo is very noisy and has a lot of jitter. There's definitely a fait bit more jitter at the output of nano than at the input, so something still isn't right. I did the updat(true) because I could see it was used after the pins changed. In my naiveity, I thought it was the input pins but it actually refers to the output pins, so I have no idea what is going on. Debugging inside interrupts sucks :(
G
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The jitter may be due to multiple interrupts interfering with each other. Should the timer1 interrupt (which is used by ServoOut) occur while a different interrupt (pin change (used by ServoIn), or timer 0 (used for micro/millisecond timing by some of the standard Arduino functions)) is being handled, the timer 1 interrupt will be queued and handled at a later time, messing up the ServoOut timing.
The timer 0 overflow happens nearly 1000 times per second, the pin change interrupt depends on the frequency of your input signal and number of pins you're monitoring.
You could try disabling Timer0 interrupts (TIMSK0 = 0;), see if that makes the output a bit more stable. This breaks delay(), delayMicros() and other time related functions though. ServoIn and ServoOut use Timer 1 so that should remain functioning.
Another thing you can try is outputting the values of ServoIn to the console (and not using ServoOut) to see if it's reading stable values. Finally you could try using ServoOut with constant values (and disable ServoIn) to see if that gives any jitter. This may help you pinpoint the cause of the jitter.
And yes, debugging interrupts sucks, but still easier than debugging an ATtiny without serial output ;)
Last edit: dvdouden 2015-08-21
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I've been implementing a pwm mixer using ServoIn and ServoOut in the last day.
I did run exactly at the same problem of noisy due to (supposedly) manny interrupts.
I'm currently reading 10 channels, and writing 6. When I don't read anything, and just output 6 fixed values (set in the code) using the ServoOut I still get almost the same noise.
I did desable Timer0 and Timer2, and also left the ISR(PCINT0_vect) empty (the one that handles 6 of the 10 channels, I implemented another one to handle PCINT2_vect), still got the same noisy.
Have you guys figured this out?
By the way, I only got the output working calling g_ServoOut.update(true) too.
p.s.: Great work! The library is awesome! =)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry, never got around to investigate this further :/
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
Anonymous
-
2019-02-21
Hi,
How can I get hold of your code of the Esky transmitter? I want to use the input ppm signal from the transmitter main pcb and send it with the nrf24l01 module to my Esky receiver.
M
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
This library looks great, thanks. I think I understand ServoIn and ServoOut examples ok, but I don'y know how to tie the two together, ie get a value with ServoIn and simply echo out to ServoOut. Ideally, I only need one channel, but I want to grab an input value when it changes, half the period, then output it with ServoOut at a fixed frequency. So, the output just runs at a fixed frequency and the output pulse width changes whenever the input pulse wodth changes, but at half the width. You huessed, I want to make a 1520uS to 760uS adapter :). Any hints appreciated, thanks.
G
View and moderate all "Features" comments posted by this user
Mark all as spam, and block user from posting to "Discussion"
Hi Git,
The first parameter passed to the constructor of ServoIn is an array which will contain the incoming signals in microseconds. The values in this array will be updated every time you call the update function. (see the ServoIn example)
The second parameter of the ServoOut constructor is an array that contains the outgoing signals in microseconds. You'll need to fill this array with (modified) values based on the array used by ServoIn. After that, call the update function on ServoOut.
You'll need a few arrays:
call the constructors with the right parameters
Initialize everything in the setup function (set up timer, interrupts pin modes and start both g_servoIn and g_servoOut.
And your loop function will look something like this:
Don't forget to copy the ISR function from the servoIn example or the code won't register incoming signals.
Good luck!
That's great, many thanks for such a quick and comprehensive reply. I assume the output does run at some fairly constant frquency, am I right in thinking I need to call ServoOut::setPauseLength() in setup() to set the frequency?
G
I think the default length between two pulses (pause length) is 10000 microseconds by default, so that means 100 pulses per second on each output pin. Set it to 20000 to get 50 Hz or 5000 to get 200 Hz for example.
Thanks for that. I've started with a straight output = input test, but I'm getting no output at all. Is the library OK on a Nano or are some Nano pins different?. Thanks.
G
The library was written for and tested on both Uno and Nano (Atmega 168/328). I'd start with putting a few Serial.println here and there, see if you get some input (set the serial speed to as high as possible to reduce the risk of messed up interrupts). Then check the output pins with either a scope or some LEDs (with current limiting resistor of course) to see if you get any output at all. This kind of problem can be hard to test, the best way is to start at the input stage and work your way to the output stage.
Yes, I should have said that Serial debugging showed no output. The cause of that was reading the nano pinout upside down and wiring the input and out reversed :). Having corrected that, I now have input, varying correctly as I vary the input pulse width, but I do not have output. I'm setting g_valuesOut[0,1,2,3] to g_valuesIn[0,1,2,3], calling g_ServoOut.update() in the loop, and getting no output. Serial print of input value, output value before out update, and output value after out update all show the same correct value, but the physical outputs get nothing, it just sits near ground voltage. Am I ok to put serial debug writes amongst ServoOut.cpp please ?
Output pins 2, 3, 4, 5 are port D on the Nano and input pins 8,9,10,11 are port B. Is that definitely ok please?.
G
AHA!.
g_ServoOut.update();
should be :
g_ServoOut.update(true);
Working ok now, thanks for all your help. I'll posts the final code when it's done.
G
That's weird, update(true) only needs to be called when you've changed the pins. It recalculates the port and bit for each pin. Oh well, if it works... :)
Yes, it works, but the servo is very noisy and has a lot of jitter. There's definitely a fait bit more jitter at the output of nano than at the input, so something still isn't right. I did the updat(true) because I could see it was used after the pins changed. In my naiveity, I thought it was the input pins but it actually refers to the output pins, so I have no idea what is going on. Debugging inside interrupts sucks :(
G
The jitter may be due to multiple interrupts interfering with each other. Should the timer1 interrupt (which is used by ServoOut) occur while a different interrupt (pin change (used by ServoIn), or timer 0 (used for micro/millisecond timing by some of the standard Arduino functions)) is being handled, the timer 1 interrupt will be queued and handled at a later time, messing up the ServoOut timing.
The timer 0 overflow happens nearly 1000 times per second, the pin change interrupt depends on the frequency of your input signal and number of pins you're monitoring.
You could try disabling Timer0 interrupts (TIMSK0 = 0;), see if that makes the output a bit more stable. This breaks delay(), delayMicros() and other time related functions though. ServoIn and ServoOut use Timer 1 so that should remain functioning.
Another thing you can try is outputting the values of ServoIn to the console (and not using ServoOut) to see if it's reading stable values. Finally you could try using ServoOut with constant values (and disable ServoIn) to see if that gives any jitter. This may help you pinpoint the cause of the jitter.
And yes, debugging interrupts sucks, but still easier than debugging an ATtiny without serial output ;)
Last edit: dvdouden 2015-08-21
View and moderate all "Features" comments posted by this user
Mark all as spam, and block user from posting to "Discussion"
Hi! =)
I've been implementing a pwm mixer using ServoIn and ServoOut in the last day.
I did run exactly at the same problem of noisy due to (supposedly) manny interrupts.
I'm currently reading 10 channels, and writing 6. When I don't read anything, and just output 6 fixed values (set in the code) using the ServoOut I still get almost the same noise.
I did desable Timer0 and Timer2, and also left the ISR(PCINT0_vect) empty (the one that handles 6 of the 10 channels, I implemented another one to handle PCINT2_vect), still got the same noisy.
Have you guys figured this out?
By the way, I only got the output working calling g_ServoOut.update(true) too.
p.s.: Great work! The library is awesome! =)
Sorry, never got around to investigate this further :/
Hi,
How can I get hold of your code of the Esky transmitter? I want to use the input ppm signal from the transmitter main pcb and send it with the nrf24l01 module to my Esky receiver.
M
I don't seem to have that code anymore; looks like I lost it when my previous laptop died :(