OK,.. I'm not an expert,.. I always consider my self a learner,... but I am really baffled as to what is going on with my code and why it will not reading the fan speed on INT1, on the 2560. INT0 counting works fine and I get lots of clock pulses in order to calculate RPM,.. however INT1 does not want to seem to play ball, even though I have verified the clock signal is present on Pin3,.. there just does not seem to be enough counts going in,.. I wondered if it was the INT0 was taking priority,.. but not the case,.. as I have left INT0 disabled and INT1 counts are still way too low....
Have included snippets of code,.. and attached full listing a full code is too big.
The essence of the code is it counts pulse ( from fan ) for a cycle ( approx 22seconds ) the calculates the speed from the number of pulses / by time..
Am I missing the obvious,.. any suggestions gratefully received:-
thanks for looking
Code as follows
volatile unsigned long rpmCHcount = 0;//see http://arduino.cc/en/Reference/Volatile
volatile unsigned long SwitchRPMcounter = 0;
//float rpmCH0 = 0;
//float rpmSW1 = 0;
volatile unsigned long lastmillisCH0 = 0;
volatile unsigned long lastmillisSW1 = 0;
float FanRPM[3];
int FanSpeed[3] = {0, 0, 0 };
int PercentSpeed[3];
// ----------------------------
void CHrpm(){ /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
rpmCHcount++;
}
void SwitchRPM(){ /* this code will be executed every time the interrupt 1 (pin3) gets low.*/
SwitchRPMcounter++;
}
------------------------------------
// Fan Setup ---------------
pinMode(2, INPUT); // Pin 2 is input to which a switch is connected = INT0
pinMode(3, INPUT);
attachInterrupt(0, CHrpm, RISING); // enable the interrupt
attachInterrupt(1, SwitchRPM, RISING); // enable the interrupt
---------------------------------------
void GetFanFrequency(byte ISRindx)
{
float MillsTime;
Serial.print("CH RPM >");
Serial.println(rpmCHcount);
Serial.print("SW RPM >");
Serial.println(SwitchRPMcounter);
if ( ISRindx == 0 )
{
if (millis() - lastmillisCH0 > 1000)
{ /*Uptade every one second, this will be equal to reading frecuency (Hz).*/
detachInterrupt(0); //Disable interrupt when calculating
MillsTime = millis() - lastmillisCH0;
FanRPM[0] = ( rpmCHcount / ( MillsTime / 1000 ) ) * 30; /* Convert frecuency to RPM, note: this works for one
// interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
rpmCHcount = 0; // Restart the RPM counter
lastmillisCH0 = millis(); // Update lasmillis
attachInterrupt(0, CHrpm, FALLING); //enable interrupt
}
}
// -------------------------------------
if ( ISRindx == 1 )
{
if (millis() - lastmillisSW1 > 1000)
{ /*Update every one second, this will be equal to reading frecuency (Hz).*/
detachInterrupt(1); //Disable interrupt when calculating
Serial.print("Mills >");
Serial.println(millis());
Serial.print("Last Mills >");
Serial.println(lastmillisSW1);
MillsTime = millis() - lastmillisSW1;
Serial.print("Millis() - Last Mills >");
Serial.println(MillsTime);
Serial.print("rpm SW Count >");
Serial.println(SwitchRPMcounter);
FanRPM[1] = ( SwitchRPMcounter / ( MillsTime / 1000 ) ) * 30; /* Convert frecuency to RPM, note: this works for one
// interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
SwitchRPMcounter = 0; // Restart the RPM counter
lastmillisSW1 = millis(); // Update lasmillis
attachInterrupt(1, SwitchRPM, FALLING); //enable interrupt
}
}
Serial.print("Stored 0 RPM >");
Serial.println(FanRPM[0]);
Serial.print("Stored 1 RPM >");
Serial.println(FanRPM[1]);
}
Tx Guys,.. I have set all the attachInterrupt calls to use RISING,.. and set the function millis() to write to an unsigned long,... Although it was working in the INT0 function,... but point taken, what I had was wrong. Anyway,.. disabling ALL interrupts with CLI SEI etc,.. during one part of routine,.. would prevent interrupts on the other fan being counted,... as far as I can work out in my way of thinking,.. ( but this is limited Arduino knowledge I have to say ).
Printing during the function,.. is purely for debug,... once counting is correct I plan to remove it... once I find out where all my clock pulses have gone on INT1.
Your point about comments,... do they get complied into the code,.. I assumed they are stripped at compile, before downloading the exe?
disabling ALL interrupts with CLI SEI etc,.. during one part of routine,.. would prevent interrupts on the other fan being counted,.
That's not what PaulS meant.
If (and its a biginners error to think that you do) you really do need to turn off an interrupt then you do it just for that interrupt not for the whole M/C.
You can set/clear the right bit in the interrupt control register or use a flag in the ISR its self.
You can set/clear the right bit in the interrupt control register or use a flag in the ISR its self.
Ah sorry,.. understand what you are saying... is this quicker than attachInterrupt/detachInterrupt routine then??
Anyway further work on test rig seems to show that INT1 is pulled LOW,..... if I disconnect my input signal from the fan,.. there's lots of nice pulses.... Connect lead to pin3 on Ardiuno board... and its like tying into a short,....
Do I need
pinMode(2, INPUT);
pinMode(3, INPUT);
Don't know why INT1 seems to be pulled Low,.. as daughter board does not appear to have short....
I have tried the following (cut-down) program on both an UNO and a Mega2560,.. and the apparent short to ground is the same.
the daughter board does not ring out for any shorts... unless I'm missing the obvious...
volatile unsigned long rpmCHcount = 0;//see http://arduino.cc/en/Reference/Volatile
volatile unsigned long SwitchRPMcounter = 0;
volatile unsigned long lastmillisCH0 = 0;
volatile unsigned long lastmillisSW1 = 0;
unsigned long MillsTime;
float FanRPM[3];
void CHrpm() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
rpmCHcount++;
}
void SwitchRPM() { /* this code will be executed every time the interrupt 1 (pin3) gets low.*/
SwitchRPMcounter++;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(38400); // Used to type in characters
pinMode(2, INPUT);
pinMode(3, INPUT);
Serial.println("Setting Fan speeds");
analogWrite( 5 , 15);
analogWrite( 9 , 15);
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
Serial.println("Running Loop");
// GetFanFrequency(0);
GetFanFrequency(1);
Serial.print("\n\n\n");
}
void GetFanFrequency(byte ISRindx)
{
Serial.print("CH RPM >");
Serial.println(rpmCHcount);
Serial.print("SW RPM >");
Serial.println(SwitchRPMcounter);
if ( ISRindx == 0 )
{
if (millis() - lastmillisCH0 > 1000)
{ /*Uptade every one second, this will be equal to reading frecuency (Hz).*/
detachInterrupt(0); //Disable interrupt when calculating
MillsTime = millis() - lastmillisCH0;
FanRPM[0] = ( rpmCHcount / ( MillsTime / 1000 ) ) * 30; /* Convert frecuency to RPM, note: this works for one
// interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
rpmCHcount = 0; // Restart the RPM counter
lastmillisCH0 = millis(); // Update lasmillis
attachInterrupt(0, CHrpm, RISING); //enable interrupt
}
}
// -------------------------------------
if ( ISRindx == 1 )
{
if (millis() - lastmillisSW1 > 1000)
{ /*Update every one second, this will be equal to reading frecuency (Hz).*/
detachInterrupt(1); //Disable interrupt when calculating
Serial.print("Mills >");
Serial.println(millis());
Serial.print("Last Mills >");
Serial.println(lastmillisSW1);
MillsTime = millis() - lastmillisSW1;
Serial.print("Millis() - Last Mills >");
Serial.println(MillsTime);
Serial.print("rpm SW Count >");
Serial.println(SwitchRPMcounter);
FanRPM[1] = ( SwitchRPMcounter / ( MillsTime / 1000 ) ) * 30; /* Convert frecuency to RPM, note: this works for one
// interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
SwitchRPMcounter = 0; // Restart the RPM counter
lastmillisSW1 = millis(); // Update lasmillis
attachInterrupt(1, SwitchRPM, RISING); //enable interrupt
}
}
Serial.print("Stored 0 RPM >");
Serial.println(FanRPM[0]);
Serial.print("Stored 1 RPM >");
Serial.println(FanRPM[1]);
}
To the setup portion of the code and that does not appear to make any difference... ( INT0) was and still is working,.. ) but this would not be the first funny. But point taken I need to attach the interrupt handlers during setup.
have not tried pull-ups as yet as my clk signal drives high and low,.. ie it is not open collector... Drive signal is derived from a 74AC14,.. schmitt trigger.. and as far as I can tell the data sheet shows output is driven high and low,.. so I don't believe I need pull-ups, and my signal goes more or less between the rails,.. ( less than 100mv off ).
No, not yet,.... but the hex schmitt drives a good signal which I can see on a scope,.. when I attach it to Pin3 ( INT1 ) it basically pulls it to ground, ( well within a few milli-Volts ). and INT0 works perfectly...
Tried a 5K6 pull-up... no change... hummmm back to the drawing board
Have not tried swapping signals around but the output from the 7414 is good on both channels,.. its just when I connect the one to INT1 aka pin3 on the 2560 it gets pulled to ground,.. and the 7414 starts to get warm as the power is dissipated....
I have tried running the blink prog,... and toggling the state of pin2 and 3,.. and without a load it certainly changes state,.. I was concerned is was shorted internally to ground,..
So in my small uneducated Arduino world,.. something is configuring Pin3 to ground, is this possible.
Am I right in using INT (Zero) and INT (ONE),... as pins 2 and 3 respectively on the mega2560?
Am I right in using INT (Zero) and INT (ONE),... as pins 2 and 3 respectively on the mega2560?
From the Mega page:
External Interrupts: 2 (interrupt 0), 3 (interrupt 1), 18 (interrupt 5), 19 (interrupt 4), 20 (interrupt 3), and 21 (interrupt 2). These pins can be configured to trigger an interrupt on a low level, a rising or falling edge, or a change in level. See the attachInterrupt() function for details.
Think I might have discovered the problem,.... when my daughter board is plugged in to the Arduino ( either Mega or UNO ),... there seems to be a 10R load to ground from the sense pin on the plug/pin I use for the fan input...
When the daughter board is not plugged in, the connection is completely open,.. so hence my assumption,... that all was fine with board.
Need some more time to get to the bottom of this....
but thanks for input though,... was sort of getting a little baffled
During my playing on a previous iteration at the breadboard stage,.. it would seem I swapped the connection wires for Gnd and sense return,.... so although the daughter board itself was fine,.. when I connected all my connecting cables up,.. ( to the fan driver board ),.. then the problem occurred....
Connecting cable sorted,.. things seem to be behaving themselves...
thanks again,. for input,.. I have tidied up some s/w things that I had wrong, and not quite correct...