Hi ¡¡ ... I'm new to Arduino and i'm having probles trying to measure speed and cadence of a bicycle using the respective sensors ( wheel & crank ) and interrupts ( on a MEGA )
Here is the code i´m using
volatile unsigned long start1=0;
volatile unsigned long end1=0;
volatile unsigned int vel1=0;
volatile unsigned int vel2=0;
volatile unsigned long const=60000;
volatile float factor = 0.0006;
volatile unsigned int const perimeter = 209; // [cm]
volatile unsigned long start2=0;
volatile unsigned long end2=0;
volatile unsigned int rpm1=0;
volatile unsigned int rpm2=0;
void setup() {
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), rpm, RISING);
attachInterrupt(digitalPinToInterrupt(3), vel, RISING);
}
void loop() {
if(vel1 != vel2){
Serial.println(vel1);
vel2=vel1;}
if(rpm1 != rpm2){
Serial.print("\t");
Serial.print("\t");
Serial.println(rpm1);
rpm2=rpm1;}
}
void vel() {
start1 = millis();
if((start1 - end1) >140) {
vel1 = perimeter *(factor/(start1 - end1))* const;
end1 = start1; }
}
void rpm() {
start2 = millis();
if((start2 - end2) >300) {
rpm1=const/(start2-fin2);
end2 = start2; }
}
Basicaly i´m printing speed and cadence everytime it changes; and the Interrupts only measure the difference of time between the current and last time triggered .... make the calculations .... save the value ( the "if" part is a debounce thing dependent on the maximun speed and rpm )
Now, void rpm() and void vel() works fine separately, but together they do this ...
vel rpm
2
15
4
33
6
7
42
69 <--------- error,
140 <--------- error
8
48
46
47
48
49
50
52
9
10
57
58
186 <--------- error
90 <--------- error
59
58
59
62
11
10
60
61
62
61
60
9 <--------- stop pedaling, wheel inertia
8
7
6
5
5 <--------- error, cero cadence
36 <--------- error, cero cadence
4
3
2
5 <--------- pedaling backwards, wheel doesn´t move, only crank
62
68
69
71
70
72
70
68
0
67
66
4 <--------- error, wheel doesn´t move
70
69
The problem seems to be a kind interference between the Interrupts, i´ve try to use detachInterrupt() on the code whit no results ( the code stop working sometimes ) ... maybe i´m using it wrong ... don´t know
Can anyone tell me whats happening ? I feel like something is missing....
Your code doesn't compile. const is a keyword and can't be used as a variable name. fin2 isn't declared and it doesn't make sense to use it there anyway. It should presumably be end2.
Pete
Oh and in the code that you have noy posted which does compile it's println that is giving the problem.
Mark
What type of sensor are you using which is providing input to pin 2 and 3?
el_supremo:
Your code doesn't compile. const is a keyword and can't be used as a variable name. fin2 isn't declared and it doesn't make sense to use it there anyway. It should presumably be end2.
Pete
Yes; should say constant and end2 .. sorry
i copy the code from another place .... this is the one corresponding to the data
volatile unsigned long start1=0;
volatile unsigned long end1=0;
volatile unsigned int vel1=0;
volatile unsigned int vel2=0;
volatile unsigned long constant=60000;
volatile float factor = 0.0006;
volatile unsigned int const perimeter = 209; // [cm]
volatile unsigned long start2=0;
volatile unsigned long end2=0;
volatile unsigned int rpm1=0;
volatile unsigned int rpm2=0;
void setup() {
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), rpm, RISING);
attachInterrupt(digitalPinToInterrupt(3), vel, RISING);
}
void loop() {
if(vel1 != vel2){
Serial.println(vel1);
vel2=vel1;
//EIFR = (1 << INTF0);
//EIFR = bit (INTF0);
//EIFR = 0x01;
//attachInterrupt(digitalPinToInterrupt(3), rpm, RISING);}
}
if(rpm1 != rpm2){
Serial.print("\t");
Serial.print("\t");
Serial.println(rpm1);
rpm2=rpm1;
//EIFR = (1 << INTF0);
//EIFR = bit (INTF0);
//EIFR = 0x01;
//attachInterrupt(digitalPinToInterrupt(2), rpm, RISING);}
}
}
void vel() {
start1 = millis();
if((start1 - end1) >140) {
vel1 = perimeter *(factor/(start1 - end1))* constant;
end1 = start1;
//detachInterrupt(digitalPinToInterrupt(3));
}
}
void rpm() {
start2 = millis();
if((start2 - end2) >300) {
rpm1=constant/(start2-end2);
end2 = start2;
//detachInterrupt(digitalPinToInterrupt(2));
}
}
the annotations ( detachs / clear flag ) it's what I've try
i´m using reed sensors ( is what cycling computers use, i think)
and your is of println is still your error
Mark
Can you provide a quick sketch of how you have the reed switch wired to the arduno and to power or ground. Is the reed switch opened or closed by the magnet? I think the input to the arduino may be floating when the reed switch is open depending on how it is wired.
Always explicitly declare your pin modes. Even though every pin defaults to INPUT on startup, it's not good practice to rely on that. (And it's pretty rare not to use INPUT_PULLUP.)
You also never take a local copy of the volatile variables. What if vel2!=vel1 when you checked it but later on (a few microsecond later) vel1 changes? Then you save that changed value to vel2, without ever looking at it. At the top of the loop, call noInterrupts()
grab a stable copy of the volatiles and then re-enable interrupts with interrupts()
. This way you get a consistent set of values.
The worst case when you don't use clean local copies is the interrupt can change the value between the main program reading the first and second byte of the 2-byte integer. That gets weird random results that look totally crazy.
MorganS:
Always explicitly declare your pin modes. Even though every pin defaults to INPUT on startup, it's not good practice to rely on that. (And it's pretty rare not to use INPUT_PULLUP.)
You also never take a local copy of the volatile variables. What if vel2!=vel1 when you checked it but later on (a few microsecond later) vel1 changes? Then you save that changed value to vel2, without ever looking at it. At the top of the loop, call noInterrupts()
grab a stable copy of the volatiles and then re-enable interrupts with interrupts()
. This way you get a consistent set of values.
The worst case when you don't use clean local copies is the interrupt can change the value between the main program reading the first and second byte of the 2-byte integer. That gets weird random results that look totally crazy.
i´ll give it a try to se what happen .... also im going to upload the sketch later, if it's of any help.