Is it possible to set event priority for these three peripherals?
I am using arduino nano to convert Sbus signal to PPM while also using wire communication as a slave. The timing of the Timer ISR (ISR(TIMER1_COMPA_vect)) is critical, so I need to set it at the highest priority. Is it possible? If so, how?
Thanks!
/*
* PPM generator originally written by David Hasko
* on https://code.google.com/p/generate-ppm-signal/
*/
#include <Wire.h>
#include "SBUS.h"
#include <SoftwareSerial.h>
SoftwareSerial mySerial(7, 8); // RX, TX
SBUS x8r(Serial);
uint16_t channels[16];
bool failSafe;
bool lostFrame;
//////////////////////CONFIGURATION///////////////////////////////
#define CHANNEL_NUMBER 8 //set the number of chanels
#define CHANNEL_DEFAULT_VALUE 1500 //set the default servo value
#define FRAME_LENGTH 22500 //set the PPM frame length in microseconds (1ms = 1000µs)
#define PULSE_LENGTH 300 //set the pulse length
#define onState 1 //set polarity of the pulses: 1 is positive, 0 is negative
#define sigPin 9 //set PPM signal output pin on the arduino
/*this array holds the servo values for the ppm signal
change theese values in your code (usually servo values move between 1000 and 2000)*/
int ppm[CHANNEL_NUMBER];
void setup(){
//initiallize default ppm values
for(int i=0; i<CHANNEL_NUMBER; i++){
ppm[i]= CHANNEL_DEFAULT_VALUE;
}
pinMode(sigPin, OUTPUT);
digitalWrite(sigPin, !onState); //set the PPM signal pin to the default state (off)
cli();
TCCR1A = 0; // set entire TCCR1 register to 0
TCCR1B = 0;
OCR1A = 100; // compare match register, change this
TCCR1B |= (1 << WGM12); // turn on CTC mode
TCCR1B |= (1 << CS11); // 8 prescaler: 0,5 microseconds at 16mhz
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
sei();
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
mySerial.begin(115200);
// begin the SBUS communication
x8r.begin();
Serial.begin(100000, SERIAL_8E2);
}
void loop(){
if(x8r.read(&channels[0], &failSafe, &lostFrame)){
ppm[0] = 0.625 * channels[0] + 880;
ppm[1] = 0.625 * channels[1] + 880;
ppm[2] = 0.625 * channels[2] + 880;
ppm[3] = 0.625 * channels[3] + 880;
ppm[4] = 0.625 * channels[4] + 880;
ppm[5] = 0.625 * channels[5] + 880;
}
}
ISR(TIMER1_COMPA_vect){ //leave this alone
static boolean state = true;
TCNT1 = 0;
if (state) { //start pulse
digitalWrite(sigPin, onState);
OCR1A = PULSE_LENGTH * 2;
state = false;
} else{ //end pulse and calculate when to start the next pulse
static byte cur_chan_numb;
static unsigned int calc_rest;
digitalWrite(sigPin, !onState);
state = true;
if(cur_chan_numb >= CHANNEL_NUMBER){
cur_chan_numb = 0;
calc_rest = calc_rest + PULSE_LENGTH;//
OCR1A = (FRAME_LENGTH - calc_rest) * 2;
calc_rest = 0;
}
else{
OCR1A = (ppm[cur_chan_numb] - PULSE_LENGTH) * 2;
calc_rest = calc_rest + ppm[cur_chan_numb];
cur_chan_numb++;
}
}
}
void receiveEvent(int howMany)
{
while( Wire.available()>0) // loop through all but the last
{
byte c = Wire.read(); // receive byte as a character
// mySerial.print(c); // print the character
}
// mySerial.println("");
}
mySerial.begin(115200);It is that you aren't using it at all, but at that speed SoftwareSerial it won't be much use, and it will interfere with you timer when you do use it (regardless of the speed) during TX and will be interfered with during RX.
endrew:
Thanks everyone!
So, I understand that priorities are pre-determined and cannot be changed?
If you wish you can keep the respective local interrupt enable switches at open conditions (interrupts are disabled but their occurrences are registered), and then serve the interrupting device of your choice through polling of the corresponding interrupt flag bit. This is a method called polled interrupt; whereas, the other one is called vectored interrupt.
GolamMostafa:
If you wish you can keep the respective local interrupt enable switches at open conditions (interrupts are disabled but their occurrences are registered), and then serve the interrupting device of your choice through polling of the corresponding interrupt flag bit. This is a method called polled interrupt; whereas, the other one is called vectored interrupt.
You mean to disable the mechanism that makes the program skip to the interrupt routine and poll the interrupt flag instead?
The avr interrupt priorities don’t really do much, anyway, since they don’t nest.
The hw priorities only come into play if two hardware events happen at exactly the same time.
westfw:
The avr interrupt priorities don’t really do much, anyway, since they don’t nest.
The hw priorities only come into play if two hardware events happen at exactly the same time.
And no, the priorities can’t be changed.
I am not familiar with the term "nest".
Do you mean that if a higher priority interrupt happen while the program is in another lower priority interrupt handler routine, it will not go to the higher interrupt routine immediately, but only when its done with the current interrupt? If so, is this true also for timer interrupts?
And yes, an interrupt routine needs to be finished before another interrupt can be serviced. You can work aroind that by selectively enabling a specific interrupt in the ISR (e.g. timer) and disabling all others, though I have never tried.
Inside interrupt handlers, you don't normally allow other interrupts to interrupt them. But sometimes it is desirable. You can enable interrupts if you wish. Then you must add extra code to be sure that you aren't interrupting yourself.
But in this case, the timing requirements are so tight you cannot do that. I suggest you switch to an Arduino with more hardware Serial. The Teensy 3.2 is a great alternative.
endrew:
I am not familiar with the term "nest".
Do you mean that if a higher priority interrupt happen while the program is in another lower priority interrupt handler routine, it will not go to the higher interrupt routine immediately, but only when its done with the current interrupt? If so, is this true also for timer interrupts?
This is a typical example of a 'nested interrupt' process. Here, the arrival of a higher priority interrupt always suspends the on-going process of the lower priority interrupt provided the global interrupt mechanism is enabled.