Alimoestar_S_K:
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, HIGH);
/* CHANGE to trigger the interrupt whenever the pin changes value
LOW to trigger the interrupt whenever the pin is low,
RISING to trigger when the pin goes from low to high,
FALLING for when the pin goes from high to low.The Due, Zero and MKR1000 boards allows also:
HIGH to trigger the interrupt whenever the pin is high.
*/
Serial.begin(9600);
}
Hello there!
The first thing that strikes me as odd is that you have the interrupt pin set as INPUT_PULLUP, which leads me to believe that your sensor pulls the pin low when it sees the metal bolt. Your interrupt is set to run the ISR when the pin is high. Since the pin is set at INPUT_PULLUP, the ISR is going to continuously run when the sensor does not see the bolt, seeing as how the pin is always high (except for the metal bolt). Try changing the interrupt event so that it triggers the ISR during a FALLING edge, instead of HIGH.
PaulS:
The valid modes are RISING, FALLING, CHANGE, and LOW. HIGH is nowhere in that list.
Here is a snippet from the Arduino Reference page for attachInterrupt(). It clearly says that HIGH is on the list. Additionally, if HIGH wasn't allowed, wouldn't the compiler throw an error?
Additionally, if HIGH wasn't allowed, wouldn't the compiler throw an error?
The compiler would throw an error if you tried to use "SamIsAnIdiot" as the argument. You are free to use values of the correct type, but not that the function expects, and the compiler will let you.
Here is a snippet from the Arduino Reference page for attachInterrupt(). It clearly says that HIGH is on the list.
You are correct about this, but there is more to consider. Did you see this line about the Due, Zero, and MKR1000 boards right before the listing of HIGH
The Due, Zero and MKR1000 boards allows also:
HIGH: to trigger the interrupt whenever the pin is HIGH
What Arduino do you have?
In the AT328 Arduinos the external interrupt mode HIGH is actually treated the same as CHANGE.
Arduino.h defines HIGH as 1 and LOW as 0. It also defines CHANGE as 1, FALLING as 2 and RISING as 3.
The attachInterrupt() function (defined in WInterrupts.c) just does an entry of that value into the External Interrupt Control Register A (EICRA) for interrupt sense control. The only values which fit into the two control bits of that register are 0 through 3.
Table 12-1. Interrupt 1 Sense Control
ISC11 ISC10 Description
0 0 The low level of INT1 generates an interrupt request.
0 1 Any logical change on INT1 generates an interrupt request.
1 0 The falling edge of INT1 generates an interrupt request.
1 1 The rising edge of INT1 generates an interrupt request.
Please elaborate on what your program is doing. "no luck" is not a very good problem statement.
i have changed the code a little. the idea is now to measure the time between 2 pulses (1 bolt passes the sensr twice, thus 1 full rotation of the axis) and calculate the rpm. measurements happens in microseconds.
const byte interruptPin = 2;
volatile byte state = LOW;
float n=0;
float RPM = 0;
unsigned long previoustime = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
/* CHANGE to trigger the interrupt whenever the pin changes value
LOW to trigger the interrupt whenever the pin is low,
RISING to trigger when the pin goes from low to high,
FALLING for when the pin goes from high to low.The Due, Zero and MKR1000 boards allows also:
HIGH to trigger the interrupt whenever the pin is high.
*/
}
void loop() {
digitalWrite(LED_BUILTIN, state);
}
void blink() {
state = !state;
if (digitalRead(LED_BUILTIN == FALLING))
{n++;
}
Serial.print("number of detections : ");
Serial.print(n);
if (n == 2){
unsigned long currenttime = micros();
RPM = (((float) 1.00 / (float)(currenttime - previoustime)) * (float) 60000000.00);
currenttime = previoustime;
n=0;
}
Serial.print(" RPM : ");
Serial.println(RPM);
}
but what happens in serial monitor is that the rpm value keeps dropping till reaches zero.But motor speed is constant.
im working with a inductive proximity sensor and want to measure the time between 2 interupts of this sensor.
this is my code, which for some reason keeps dropping till reaches zero
//15 augustus 2018
// Alimoestar S.K.
const byte interruptPin = 2;
volatile byte state = LOW;
float n=0;
float Time = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
/* CHANGE to trigger the interrupt whenever the pin changes value
LOW to trigger the interrupt whenever the pin is low,
RISING to trigger when the pin goes from low to high,
FALLING for when the pin goes from high to low.The Due, Zero and MKR1000 boards allows also:
HIGH to trigger the interrupt whenever the pin is high.
*/
}
void loop() {
digitalWrite(LED_BUILTIN, state);
}
void blink() {
state = !state;
if (digitalRead(LED_BUILTIN == FALLING))
{unsigned long previoustime= micros();
n++;
Serial.print("number of detections : ");
Serial.print(n);
if (n == 2){
unsigned long currenttime = micros();
Time=(float)(currenttime - previoustime);
currenttime = previoustime;
n=1;
}
}
Serial.print(" RPM : ");
Serial.println(RPM);
}
when i say keep dropping till reaches zero, i meant that the value printed on the serial monitor was decreasing till it reached zero.
i've recently found out that i made an error in
currenttime = previoustime;
// it should be the other way around
previoustime = currenttime;
since fixing this, no more decreasing till zero
AWOL:
Don't do serial I/O in interrupt context.
should i put this in the loop, like this? or do you suggest a different way?
//15 augustus 2018
// Alimoestar S.K.
const byte interruptPin = 2;
volatile byte state = LOW;
float n=0;
float Time = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
/* CHANGE to trigger the interrupt whenever the pin changes value
LOW to trigger the interrupt whenever the pin is low,
RISING to trigger when the pin goes from low to high,
FALLING for when the pin goes from high to low.The Due, Zero and MKR1000 boards allows also:
HIGH to trigger the interrupt whenever the pin is high.
*/
}
void blink() {
state = !state;
if (digitalRead(LED_BUILTIN == FALLING))
{unsigned long previoustime= micros();
n++;
Serial.print("number of detections : ");
Serial.print(n);
if (n == 2){
unsigned long currenttime = micros();
Time=(float)(currenttime - previoustime);
previoustime = currenttime;
n=1;
}
}
}
void loop() {
digitalWrite(LED_BUILTIN, state);
Serial.print(" RPM : ");
Serial.println(RPM);
}
That is a stupid name for the function to call. Nothing is blinking...
if (digitalRead(LED_BUILTIN == FALLING))
Work out, on paper, EXACTLY which pin you are reading from. It is NOT the pin you want to read from.
There is NO need to read the state of an output pin. Keep track of the state you set it to.
Regardless, the state of the LED pin has NOTHING to do with the time that the sensor (assuming that it is indeed connected to pin 2) triggered the interrupt.
Your code is, as currently written, complete nonsense.
the pin i am reading from is pin 2 on the arduino uno R3, which has interrupts for pin 2 and 3.
With this code,
if (digitalRead(LED_BUILTIN == FALLING))
You are comparing LED_BUILTIN to FALLING, which returns true or false. Which of those values do you think is 2? Neither one is. That code is reading from pin true or pin false. Hardly a reasonable thing to do.
Even if you fix that to
if (digitalRead(LED_BUILTIN) == FALLING)
so that you are reading from the LED_BUILTIN pin, you are comparing HIGH or LOW to FALLING. Never will match...
after consideration of all your comments and some extra reading and testing, i came up with the following code:
/* RPM sensing using a arduino uno
and inductive proximity sensor
Alimoestar S.K.
original code may 2018
revised 20 aug 2018
revised 27 aug 2018
revised 1 sep 2018
*/
//---------------------------- declaration -------------------------------
const byte interruptPin = 2;
int n = 0;
volatile long RPM = 0;
volatile long RPMsum = 0; // sum of 20 RPM measurements
volatile long RPMav = 0; // average of 20 RPM measurements
float F = 0.000; // frequency
volatile boolean flag = 0;
unsigned long DeltaT; // time between two interupts
unsigned long previoustime = 0;
//---------------------------- setup --------------------------------------
void setup()
{
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(interruptPin), sensor, FALLING);
}
//---------------------------- ISR sensor --------------------------------
void sensor()
{ flag = 1;
}
//----------------------------- loop --------------------------------------
void loop()
{ //-----------------------------------------------------------------------rpm measurement
if (flag)
{ noInterrupts(); // disables interrupt, because the folloing is time sensitive
n++;
unsigned long currenttime = micros(); // measure the current time
DeltaT = (currenttime - previoustime); // calculate the time difference
previoustime = currenttime; // set previoustime = currenttime
if (DeltaT >= 32000) { // deltaT 32000 => rpm= +-1800 (debouncing)
RPM = float(60000000UL / DeltaT); // calculate the rpm (One (1) signal per rotation)
Serial.print("delta T =\t");
Serial.print(DeltaT);
Serial.print("\t rpm =\t");
Serial.println(RPM );
//}
//---------------------------------------------- frequency calculation
F = (RPMav / 2) * 60.00;
flag = 0;
interrupts();
}
// Average RPM value of 200 measurements
RPMsum = RPMsum + RPM; // sum of 200 measurements
if (n == 20) {
RPMav = (RPMsum / 20); // averge of 200 measurement
//---------------------------------------------- print to serial screen
Serial.print(" RPM = ");
Serial.print(RPM );
Serial.print(" RPMav = ");
Serial.print(RPMav );
Serial.print(" Freq = ");
Serial.println(F );
RPMsum = 0;
n = 0;
}
}
}//-------------------------------- end loop -----------------------------------------
//--------------------------------- end code -----------------------------------------
this seemed to work at first, but after some time gave some nonsense reading.
any thoughts or coments???
but after some time gave some nonsense reading.
any thoughts or coments
Yes. You ABSOLUTELY MUST understand what you can, and can not do, with interrupts disabled.
The ONLY thing you should be doing, while interrupts are disabled, is copying and resetting the values of the variables that the interrupt service routine(s) use.
This is similar to my project. These comments make little sense. Watch this little video; If you can understand this simple sketch, the solution will become obvious. (use a Hall detector, not the photo module in the video. I have since learned that RPM is usually done with a Hall effect detector)