Go Down

Topic: rpm sensing with proximity sensor (Read 728 times) previous topic - next topic

Alimoestar_S_K

Hi,

i'm working on rpm sensing using a proximity sensor. when ever the sensor detects metal bolt on the motor axis it should blink BUILTIN LED. The time between blinks is used to calculate the rpm. thats the theory behind this project. but so far no luck....
any advise?

Code: [Select]
/* interrupt function testing
 *  created 30 may 2018 9:51
 *  by Alimoestar SK
 *  tested and improved till 6 june 2018
 *  work as follows. if a metal object is detected build in led is on
 *  the number led is on is counted and presented as "number of detections"
 *  RPM is measured using the number of detection and the time that has passed
 */


const byte interruptPin = 2;
volatile byte state = LOW;
float n = 0;
float RPM = 0;

unsigned long StartTime = millis();



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);
 
}
void loop() {
  digitalWrite(LED_BUILTIN, state);
 
}

void blink() {
  state = !state;
{ if(digitalRead(LED_BUILTIN  == HIGH))
{n++;
  Serial.print("number of detections:");
  Serial.println(n);
}
  unsigned long CurrentTime = millis();
 
    RPM = ((float) n / CurrentTime - StartTime);
    CurrentTime = StartTime;
      Serial.print("RPM:");
      Serial.println(RPM);
     
}}
 

bos1714

#1
Jun 07, 2018, 01:08 pm Last Edit: Jun 07, 2018, 01:09 pm by bos1714
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.
Time line? Time isn't made out of lines. It is made out of circles. That is why clocks are round.

PaulS

Code: [Select]
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, HIGH);
The valid modes are RISING, FALLING, CHANGE, and LOW. HIGH is nowhere in that list.
The art of getting good answers lies in asking good questions.

bos1714

#3
Jun 07, 2018, 05:47 pm Last Edit: Jun 07, 2018, 05:47 pm by bos1714
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?

Time line? Time isn't made out of lines. It is made out of circles. That is why clocks are round.

PaulS

Quote
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.
The art of getting good answers lies in asking good questions.

bos1714

I see. You say that HIGH is not a valid argument input, but yet is it on the reference snippet I posted. Any explanations?
Time line? Time isn't made out of lines. It is made out of circles. That is why clocks are round.

PaulS

I see. You say that HIGH is not a valid argument input, but yet is it on the reference snippet I posted. Any explanations?
Other than that it doesn't make sense? Why would you want to trigger an interrupt continually when a pin was HIGH or LOW?

Interrupts are to handle changes from outside the microcontroller.

(LOW has a valid use in waking from sleep mode)
The art of getting good answers lies in asking good questions.

cattledog

#7
Jun 08, 2018, 06:32 pm Last Edit: Jun 08, 2018, 06:50 pm by cattledog
Quote
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

Quote
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.

Alimoestar_S_K

dear all,

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.

Code: [Select]

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.

help please.

Alimoestar_S_K

dear all,

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

Code: [Select]


//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);

  }



any idea's???
thank you in advance

AWOL

#10
Aug 16, 2018, 12:25 am Last Edit: Aug 16, 2018, 12:26 am by AWOL
Don't do serial I/O in interrupt context.

Quote
keeps dropping till reaches zero
I don't know what that means.

Code: [Select]
digitalRead(LED_BUILTIN  == FALLING)Oops
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Alimoestar_S_K

dear awol,

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
Code: [Select]
currenttime = previoustime;
// it should be the other way around
previoustime = currenttime;


since fixing this, no more decreasing till zero

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?


Code: [Select]

//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);

  }

AWOL

Code: [Select]
if (digitalRead(LED_BUILTIN  == FALLING))Still oops.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

PaulS

Code: [Select]
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
That is a stupid name for the function to call. Nothing is blinking...

Code: [Select]
  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 art of getting good answers lies in asking good questions.

Alimoestar_S_K

#14
Aug 16, 2018, 02:57 pm Last Edit: Aug 16, 2018, 03:16 pm by Alimoestar_S_K
dear all,

i've taken all coments and advise into consideration. did some extra reading and came up with the following.

Code: [Select]

/* Alimoestar S.K.
 *  original code may 2018
 *  16 aug 2018 revised
 *  coments and advise from arduino forum toopic :rpm sensing with proximity sensor
 *
  */

const byte interruptPin = 2;
volatile long n=0;
volatile long RPM=0;
volatile boolean flag=0;
long RPMperiod;
unsigned long previoustime=0;


void setup()
{
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(interruptPin), sensor, FALLING);

}

void loop()
{
    if(flag)
  {
    RPM=(60000000UL/RPMperiod);   //One (1) signal per rotation.
    interrupts();
    Serial.print("RPM = ");
    Serial.println(RPM );
    flag=0;
  }
}

void sensor()
{unsigned long currenttime=micros();
  RPMperiod=float ( currenttime- previoustime);
  flag=1;
  previoustime = currenttime;

}

  
in the serial monitor i'm seeing my rpm value and a lot of other things.

Go Up