I am fairly new to the principle of timer interrupts, maybe someone can help me out! I am trying to program an Arduino that can read a PPM signal, check for some conditions, adapt the signal if necessary and generate a new PPM signal. So far I've been able to read the signal using an external interrupt (counting the channel widths using timer/counter1) and generating a signal using a timer interrupt in CTC mode, but in separate programs.
I am wondering if it is possible to combine these two programs, meaning that the reading interrupt is triggered on pin input CHANGE, while at the same time keep another timer counting for generating the signal. I tried using two timer/counter1 and timer/counter2 simultaneously but so far no good results.
I spend last day searching but can't find any similar projects, so any help would be greatly appreciated!
Sorry, and thanks for the tip! If you referring to code, below you can find the separate programs I use.
For generating PPM signal:
// declare constants
const int PPM_OUT = 5; // ppm out pin number
const int NUM_CHAN = 8; // number of channels
const int PPM_PULSE = 500; // set pulse length to 500 us
const int PPM_FRAME = 22500; // set frame length
// declare variables
int ppm_out[NUM_CHAN] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500};
// setup code running once
void setup() {
// initializing timer 1
cli(); // disable global interrupts
TCCR1A = 0; // set register to 0 (timer/counter control register)
TCCR1B = 0; // set register to 0
OCR1A = 0; // compare match register
TCCR1B |= (1 << WGM12); // enable CTC mode
TCCR1B |= (1 << CS11); // choose clock bits for prescaler
// TCCR1B |= (1 << CS10); // choose clock bits for prescaler (CS10 & CS12 for 1024, CS11 for 8, seet table AVR)
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt timer/counter interrupt mask register
sei(); // enable global interrupts
pinMode(PPM_OUT, OUTPUT); // set ppm output pin
Serial.begin(9600); // initialize serial communication
}
// main code for running repeatedly
void loop() {
}
//delay(60);
// interrupt service routine
ISR(TIMER1_COMPA_vect) {
static boolean state = true;
TCNT1 = 0;
if(state) { // check if pulse
digitalWrite(PPM_OUT, HIGH); // set output high
OCR1A = PPM_PULSE * 2; // set compare time
state = false; // change state
}
else {
static byte chan_cur; // current channel variable
static unsigned int total; // remaining frame length
state = true; // state
digitalWrite(PPM_OUT, LOW); // start low
if (chan_cur >= NUM_CHAN) { // check if new burst started
chan_cur = 0; // reset current channel number
total = total + PPM_PULSE; // add pulse to total time
OCR1A = (PPM_FRAME - total) * 2; // set compare match register to required synchro blank time
total = 0; // reset total time
}
else { // write pulse width
OCR1A = (ppm_out[chan_cur] - PPM_PULSE) * 2; // set compare match register to channel width
total = total + ppm_out[chan_cur]; // add to total time
chan_cur++; // increment channel
}
}
}
For reading PPM:
// declare constants
const int PPM_IN = 3; // ppm pin number (2 or 3 for interrupts)
const int NUM_CHAN = 8; // number of channels
// declare variables
int channel[NUM_CHAN]; // array to store interval lengths
int pulse; // array to store pulse lengths
// setup code running once
void setup() {
Serial.begin(9600); // open serial communication
pinMode(PPM_IN, INPUT); // set input pin
attachInterrupt(PPM_IN-2, read_ppm, CHANGE);
cli();
TCCR1A = 0; //reset timer1
TCCR1B = 0;
TCCR1B |= (1 << CS11); //set timer1 to increment every 0,5 us
sei();
}
// main code for running repeatedly
void loop() {
}
Serial.println("");
// delay(60);
}
void read_ppm() {
// static unsigned int pulse;
static unsigned long counter;
static byte k;
counter = TCNT1;
TCNT1 = 0;
// while(k<NUM_CHAN){
if(counter<1020) { // pulse
pulse = counter;
}
else if (counter > 3820) { // synchro
k = 0;
}
else { //
channel[k] = (counter + pulse)/2;
k++;
}
}
Thanks, this is really helpful. I've been able to combine timer/counter1 and timer/counter2 in one program and it seems to be working correctly. I am using the Arduino Duemilanove which only has three timers. Now I need an extra timer to build-in an ultrasonic sensor (NewPing library uses timer/counter2), but from what I understood it is not advisable to mess with timer/counter0, is that correct? Thanks again for the articles, they were really clearing things up for me!