0
Offline
Full Member
Karma: 1
Posts: 137
|
 |
« on: July 28, 2012, 12:56:31 am » |
Hi , I used a Arduino Duemilanove to generate a 5V trigger signal to be measured by itself through an interrupt (So the microcontroller feeds the trigger is the same as the one measuring it). This is my code int pin = 13; volatile int state = LOW; const int ledPin = 12; // the number of the LED pin int ledState = LOW; // ledState used to set the LED long previousMillis = 0; // will store last time LED was updated long interval = 100; // interval at which to blink (milliseconds)
int trigger = 13; // Trigger Ausgnag unsigned long microshigh1; //Microsekunden wenn der Trigger auf HIGH geht- vorheriger Trigger unsigned long microshigh2; //Microsekunden wenn der Trigger auf HIGH geht- aktueller Trigger unsigned long deltamicros; //Abstand zweier high Flanken
void setup() { //Wie werden die Arduino ÜPins benutzt? Serial.begin(115200); pinMode(pin, OUTPUT); attachInterrupt(0, ignite, CHANGE); //put interrupt on pin 2---> Triggereingang pinMode(ledPin, OUTPUT);// Virtueller trigger
} void loop() { unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) { // save the last time you blinked the LED previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa: if (ledState == LOW) ledState = HIGH; else ledState = LOW;
// set the LED with the ledState of the variable: digitalWrite(ledPin, ledState); } }
void ignite() { state = !state; digitalWrite(pin, state); digitalWrite(10, LOW); microshigh2 = micros();
deltamicros= microshigh2-microshigh1; Serial.println(deltamicros); microshigh1= microshigh2; }
The result is the following received by the serial out: Measured time Variation 101396 101376 -20 100352 -1024 101376 1024 101372 -4 100356 -1016 101372 1016 101384 12 100344 -1040 101380 1036 100356 -1024 101372 1016 As you see there is pretty much of a variation although I used and interrupt. is that normal and I should not expect a better result?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Dallas
Online
Shannon Member
Karma: 118
Posts: 10147
|
 |
« Reply #1 on: July 28, 2012, 01:14:35 am » |
Wrong datatypes; they are supposed to be unsigned long...
unsigned long previousMillis = 0; // will store last time LED was updated unsigned long interval = 100; // interval at which to blink (milliseconds)
attachInterrupt(0, ignite, CHANGE); //put interrupt on pin 2---> Triggereingang +
void ignite() { Serial.println(deltamicros); }
=
Bad idea.
|
|
|
|
« Last Edit: July 28, 2012, 02:01:37 am by Coding Badly »
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 1
Posts: 137
|
 |
« Reply #2 on: July 28, 2012, 01:29:21 am » |
You're right. I changed it. Is that the root cause of the timing variation...?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Dallas
Online
Shannon Member
Karma: 118
Posts: 10147
|
 |
« Reply #3 on: July 28, 2012, 02:01:19 am » |
Very likely.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 1
Posts: 137
|
 |
« Reply #4 on: July 28, 2012, 03:51:58 am » |
Tried the changed code. Is the modification what you have meant? First the results in microseconds: 101372 100356 -1016 101372 1016 101380 8 100348 -1032 101380 1032 101372 -8 100356 -1016 101372 1016 100352 -1020 101376 1024 101380 4 100352 -1028 101376 1024 101372 -4 100352 -1020 101376 1024 101380 4 101372 -8 This is the code int pin = 13; volatile int state = LOW; const int ledPin = 12; // the number of the LED pin int ledState = LOW; // ledState used to set the LED unsigned long previousMillis = 0; // will store last time LED was updated unsigned long interval = 100; // interval at which to blink (milliseconds)
int trigger = 13; // Trigger Ausgnag unsigned long microshigh1; //Microsekunden wenn der Trigger auf HIGH geht- vorheriger Trigger unsigned long microshigh2; //Microsekunden wenn der Trigger auf HIGH geht- aktueller Trigger unsigned long deltamicros; //Abstand zweier high Flanken
void setup() { //Wie werden die Arduino ÜPins benutzt? Serial.begin(115200); pinMode(pin, OUTPUT); attachInterrupt(0, ignite, CHANGE); //put interrupt on pin 2---> Triggereingang pinMode(ledPin, OUTPUT);// Virtueller trigger
} void loop() { unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) { // save the last time you blinked the LED previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa: if (ledState == LOW) ledState = HIGH; else ledState = LOW;
// set the LED with the ledState of the variable: digitalWrite(ledPin, ledState); } }
void ignite() { state = !state; digitalWrite(pin, state); digitalWrite(10, LOW); microshigh2 = micros(); deltamicros= microshigh2-microshigh1; Serial.println(deltamicros); microshigh1= microshigh2; }
This wasn't the root cause. I tried to put the microshigh1 and 2 into volatile memory state improving speed...no success as well
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 71
Posts: 6611
Arduino rocks
|
 |
« Reply #5 on: July 28, 2012, 04:33:45 am » |
Don't do serial I/O in an interrupt routine - its takes forever, keep interrupt routine lean as its blocking other interrupts until it returns.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 1
Posts: 137
|
 |
« Reply #6 on: July 28, 2012, 06:02:26 am » |
MarkT, in general I do agree, but - I need to know if the interrupt is working with a minimum (or at least a defined) delay - the code shows an intervall of 100mS at 115200baud which should be quick enough to submit the data - the serial data submission is after the interrupt work...shouldn't lead to a delay
But anyhow I do agree that this is not optimum, but I do not know any other way to control function accuracy and I do not have a oscilloscope
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #7 on: July 28, 2012, 06:28:15 am » |
This wasn't the root cause. I tried to put the microshigh1 and 2 into volatile memory state improving speed...no success as well
Volatile memory?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #8 on: July 28, 2012, 06:29:10 am » |
MarkT, in general I do agree, but
Don't do Serial.print inside your ISR. Then get back to us about your problems.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 1
Posts: 137
|
 |
« Reply #9 on: July 28, 2012, 07:16:08 am » |
Ahh- I misunderstood all of you not using SerialPrint at all. Sorry! Now I changed the code and put the command in the loop void loop() { unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) { // save the last time you blinked the LED previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa: if (ledState == LOW) ledState = HIGH; else ledState = LOW;
// set the LED with the ledState of the variable: digitalWrite(ledPin, ledState); Serial.println(deltamicros); } }
I decreased the speed of blinking to give more time for SerialPrintThe result remains unchanged. Still 1mS variation: 1001504 1001468 1000448 1001476 100 0448 1001468 100 0448 1001472 100 0448
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35483
Seattle, WA USA
|
 |
« Reply #10 on: July 28, 2012, 09:07:00 am » |
Now I changed the code And posted only part of it...
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 1
Posts: 137
|
 |
« Reply #11 on: July 28, 2012, 09:31:49 am » |
int pin = 13; volatile int state = LOW; const int ledPin = 12; // the number of the LED pin int ledState = LOW; // ledState used to set the LED unsigned long previousMillis = 0; // will store last time LED was updated unsigned long interval = 1000; // interval at which to blink (milliseconds)
int trigger = 13; // Trigger Ausgnag unsigned long microshigh1; //Microsekunden wenn der Trigger auf HIGH geht- vorheriger Trigger unsigned long microshigh2; //Microsekunden wenn der Trigger auf HIGH geht- aktueller Trigger unsigned long deltamicros; //Abstand zweier high Flanken
void setup() { //Wie werden die Arduino ÜPins benutzt? Serial.begin(115200); pinMode(pin, OUTPUT); attachInterrupt(0, ignite, CHANGE); //put interrupt on pin 2---> Triggereingang pinMode(ledPin, OUTPUT);// Virtueller trigger
} void loop() { unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) { // save the last time you blinked the LED previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa: if (ledState == LOW) ledState = HIGH; else ledState = LOW;
// set the LED with the ledState of the variable: digitalWrite(ledPin, ledState); Serial.println(deltamicros); } }
void ignite() { digitalWrite(pin, state); digitalWrite(10, LOW); microshigh2 = micros(); deltamicros= microshigh2-microshigh1; microshigh1= microshigh2; state = !state; }
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35483
Seattle, WA USA
|
 |
« Reply #12 on: July 28, 2012, 09:49:47 am » |
unsigned long deltamicros; //Abstand zweier high Flanken Used by loop() and the ISR. Should, therefore, by volatile. The deltamicros variable takes time to convert to a string, and to shift the bytes to the serial port. An interrupt can occur while that is happening. You need to copy the valuable to another location, and output the copy. Even during a copy operation, while 4 bytes are copied, an interrupt can occur. So, you need to disable interrupts before the copy starts. and then enable them again as soon as the copy completes. What is generating the external interrupt? Are you sure that it is consistently happening exactly one second apart?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 1
Posts: 137
|
 |
« Reply #13 on: July 28, 2012, 02:23:25 pm » |
Dear all, I have found the issue. The code for blinking the trigger is based on mS and the ISR is based on microseconds. So I changed the code to the following: int pin = 13; volatile int state = LOW; const int ledPin = 12; // the number of the LED pin int ledState = LOW; // ledState used to set the LED unsigned long previousMillis = 0; // will store last time LED was updated unsigned long interval = 1000; // interval at which to blink (milliseconds)
int trigger = 13; // Trigger Ausgnag volatile unsigned long microshigh1; //Microsekunden wenn der Trigger auf HIGH geht- vorheriger Trigger volatile unsigned long microshigh2; //Microsekunden wenn der Trigger auf HIGH geht- aktueller Trigger volatile unsigned long deltamicros; //Abstand zweier high Flanken
void setup() { //Wie werden die Arduino ÜPins benutzt? Serial.begin(115200); pinMode(pin, OUTPUT); attachInterrupt(0, ignite, CHANGE); //put interrupt on pin 2---> Triggereingang pinMode(ledPin, OUTPUT);// Virtueller trigger
} void loop() { unsigned long currentMillis = micros();
if(currentMillis - previousMillis > interval) { // save the last time you blinked the LED previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa: if (ledState == LOW) ledState = HIGH; else ledState = LOW;
// set the LED with the ledState of the variable: digitalWrite(ledPin, ledState); Serial.println(deltamicros); } }
void ignite() { digitalWrite(pin, state); digitalWrite(10, LOW); microshigh2 = micros(); deltamicros= microshigh2-microshigh1; microshigh1= microshigh2; state = !state; } And the result with 1000microseconds is reasonable good including SerialPrint: Deltamicros Difference 100000 100012 12 100004 -8 100000 -4 100012 12 100004 -8 100012 8 100000 -12 100004 4 100012 8 100000 -12 100004 4 100012 8 100004 -8 100004 0 100008 4 100000 -8 100008 8 100008 0 100012 4 Thank you all for your support!
|
|
|
|
|
Logged
|
|
|
|
|
|