I'm using an Arduino Leonardo and need to perform two time-sensitive tasks like this:
// Task 1 - Gets executed once a second (1Hz)
// Execution of task needs approx 70ms
task1(); //Sending a message via Serial
// Task 2 - Gets executed 50 times a second (50Hz)
// Execution of task need a few micros
task2(); //digitalWrite
As you can see, the problem is, that task one needs very long for execution and therefore task2 is executed too late to send a 50Hz signal. I'm not sure how, but I think there must be a way to give task 1 higher priority to interrupt task 2?
Thanks in advance! :)
Just for completion, here is my (not so clean) code:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(7, 6); //232_TX,232_
int triggerFreq = 10;
unsigned long timestamp_pps;
unsigned long timestamp;
unsigned long triggerStartTime;
const unsigned long dt_pps = 1000000; //micros
const unsigned long dt_trig = 1000000/triggerFreq; //micros
unsigned long ts_pps_high;
unsigned long ts_pps_low;
unsigned long ts_msg_high;
unsigned long ts_msg_low;
unsigned long i_pps = 0;
unsigned long i_trig = 0;
int hh = 04;
int mm = 51;
int ss = 00;
unsigned int pos = 2307;
bool msg;
bool trigMsgSent;
void setup() {
// put your setup code here, to run once:
pinMode(11, OUTPUT); // PPS
pinMode(12, OUTPUT); // Indicator of msg_sent
pinMode(13, OUTPUT); // FPS
Serial.begin(9600);
mySerial.begin(9600);
triggerStartTime = micros();
}
void loop() {
// ================== Part for the GPS Simulation ==================
timestamp_pps = micros()-triggerStartTime;
if (timestamp_pps>= dt_pps*i_pps+350000)
{
pos += 1;
digitalWrite(12,HIGH);
i_pps +=1;
if (ss == 59)
{
ss=0;
if (mm==59)
{
mm=0;
hh+=1;
}
else mm+=1;
}
else ss+=1;
ts_msg_high = micros();
mySerial.print("$GPRMC,");
if (hh<10) mySerial.print(F("0"));
mySerial.print(hh);
if (mm<10) mySerial.print(F("0"));
mySerial.print(mm);
if (ss<10) mySerial.print(F("0"));
mySerial.print(ss);
mySerial.print(".000,A,3015.");
mySerial.print(pos);
mySerial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");
// Print Debug Messages
digitalWrite(12,LOW);
ts_msg_low=micros();
Serial.print("PPS at: ");
Serial.print(ts_pps_high);
Serial.print("\t PPS low after: ");
Serial.print(ts_pps_low-ts_pps_high);
Serial.print("\t MSG high after: ");
Serial.print(ts_msg_high-ts_pps_high);
Serial.print("\t MSG low after: ");
Serial.print(ts_msg_low-ts_pps_high);
Serial.print("$GPRMC,");
if (hh<10) Serial.print(F("0"));
Serial.print(hh);
if (mm<10) Serial.print(F("0"));
Serial.print(mm);
if (ss<10) Serial.print(F("0"));
Serial.print(ss);
Serial.print(".000,A,3015.");
Serial.print(pos);
Serial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");
}
else if (timestamp_pps>=dt_pps*i_pps+100000)
{
digitalWrite(11,LOW);
if (msg==true)
{
msg = false;
ts_pps_low = micros();
}
}
else if (timestamp_pps>=dt_pps*i_pps)
{
digitalWrite(11,HIGH);
if (msg==false)
{
msg = true;
ts_pps_high = micros();
}
}
// ================== Part for the FPS Trigger ==================
timestamp = micros()-triggerStartTime;
if (timestamp>= dt_trig*i_trig+2000)
{
digitalWrite(13,LOW);
i_trig +=1;
trigMsgSent = false;
}
else if (timestamp >=dt_trig*i_trig)
{
digitalWrite(13,HIGH);
if (trigMsgSent == false)
{
Serial.print("FPS at: ");
Serial.println(micros());
trigMsgSent = true;
}
}
}
Update: So i implemented it with an interrupt according to this example. I just programmed the interrupt for the 50Hz signal, because that one must be accurate. The code is at the end. However, I'm still experiencing the 50Hz signal to be late when the serial is sent. It's now in the dimensions of half a millisecond, but that's not negligible in my project (Sensor fusion computer vision). The output of my post-processing-tool shows:
Trigger Nr. 25 is 646.912us late!
Trigger Nr. 28 is 434.176us late!
Trigger Nr. 75 is 653.056us late!
Trigger Nr. 78 is 429.056us late!
Trigger Nr. 125 is 646.912us late!
Trigger Nr. 128 is 434.944us late!
Trigger Nr. 175 is 646.912us late!
Trigger Nr. 178 is 439.04us late!
Trigger Nr. 225 is 646.912us late!
Trigger Nr. 228 is 440.064us late!
Trigger Nr. 275 is 647.168us late!
Trigger Nr. 278 is 434.944us late!
Trigger Nr. 325 is 611.84us late!
Trigger Nr. 328 is 462.08us late!
Trigger Nr. 375 is 612.864us late!
Trigger Nr. 378 is 475.136us late!
Trigger Nr. 425 is 619.008us late!
Trigger Nr. 428 is 473.856us late!
Trigger Nr. 475 is 613.888us late!
Trigger Nr. 478 is 467.968us late!
Trigger Nr. 525 is 612.864us late!
Trigger Nr. 528 is 474.88us late!
Trigger Nr. 575 is 613.12us late!
Does anyone know how I could improve my code?
Code:
//GPS DEFINITIONS
#include <SoftwareSerial.h>
SoftwareSerial mySerial(7, 6); //232_TX,232_
int triggerFreq = 50;
unsigned long timestamp_pps;
//unsigned long timestamp;
unsigned long triggerStartTime;
const unsigned long dt_pps = 1000000; //micros
//const unsigned long dt_trig = 1000000/triggerFreq; //micros
unsigned long ts_pps_high;
unsigned long ts_pps_low;
unsigned long ts_msg_high;
unsigned long ts_msg_low;
unsigned long i_pps = 0;
//unsigned long i_trig = 0;
int hh = 04;
int mm = 51;
int ss = 00;
unsigned int pos = 2307;
bool msg;
bool trigMsgSent;
void setup() {
cli();//stop interrupts
//set timer1 interrupt at 1Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
//OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
OCR1A = 19999; // = (16*10^6) / (100 * 8) -1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
// GPS SETUP
pinMode(11, OUTPUT); // PPS
pinMode(12, OUTPUT); // Indicator of msg_sent
pinMode(13, OUTPUT); // FPS
Serial.begin(9600);
mySerial.begin(9600);
triggerStartTime = micros();
}
ISR(TIMER1_COMPA_vect){ //change the 0 to 1 for timer1 and 2 for timer2
//interrupt commands here
digitalWrite(13,!digitalRead(13));
}
void loop() {
// ================== Part for the GPS Simulation ==================
timestamp_pps = micros()-triggerStartTime;
if (timestamp_pps>= dt_pps*i_pps+350000)
{
pos += 1;
digitalWrite(12,HIGH);
i_pps +=1;
if (ss == 59)
{
ss=0;
if (mm==59)
{
mm=0;
hh+=1;
}
else mm+=1;
}
else ss+=1;
ts_msg_high = micros();
mySerial.print("$GPRMC,");
if (hh<10) mySerial.print(F("0"));
mySerial.print(hh);
if (mm<10) mySerial.print(F("0"));
mySerial.print(mm);
if (ss<10) mySerial.print(F("0"));
mySerial.print(ss);
mySerial.print(".000,A,3015.");
mySerial.print(pos);
mySerial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");
// Print Debug Messages
digitalWrite(12,LOW);
ts_msg_low=micros();
Serial.print("PPS at: ");
Serial.print(ts_pps_high);
Serial.print("\t PPS low after: ");
Serial.print(ts_pps_low-ts_pps_high);
Serial.print("\t MSG high after: ");
Serial.print(ts_msg_high-ts_pps_high);
Serial.print("\t MSG low after: ");
Serial.print(ts_msg_low-ts_pps_high);
Serial.print("$GPRMC,");
if (hh<10) Serial.print(F("0"));
Serial.print(hh);
if (mm<10) Serial.print(F("0"));
Serial.print(mm);
if (ss<10) Serial.print(F("0"));
Serial.print(ss);
Serial.print(".000,A,3015.");
Serial.print(pos);
Serial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");
}
else if (timestamp_pps>=dt_pps*i_pps+100000)
{
digitalWrite(11,LOW);
if (msg==true)
{
msg = false;
ts_pps_low = micros();
}
}
else if (timestamp_pps>=dt_pps*i_pps)
{
digitalWrite(11,HIGH);
if (msg==false)
{
msg = true;
ts_pps_high = micros();
}
}
}