Go Down

Topic: Using IR sensor and IR receiver to measure the speed of the shaft (Read 226 times) previous topic - next topic

nghtitus

Jun 22, 2018, 10:50 am Last Edit: Jun 22, 2018, 10:52 am by nghtitus Reason: File was not attached.
Hi,
my code is
Code: [Select]
float value=0;
float rev=0;  
int rpm;
int oldtime=0;
int time;

#include<SD.h>

void isr() //interrupt service routine
{
rev++; //Each rotation, this interrupt function is run twice, so
//take this into consideration
//when calculating ROC Disk Speed
//update count
}
void setup()
{
SD.begin(); //initialise the SD
Serial.begin(9600); //initialise the serial communication
attachInterrupt(0,isr,FALLING);  //attaching the interrupt
//Interrupt 0 is digital pin 2, so that is where the IR detector is connected
//Triggers on FALLING (change from HIGH to LOW)
}

void loop()
{
  delay (1000);                 //Do not process interruptions during calculations

detachInterrupt(0);           //detaches the interrupt
millis();
time=millis()-oldtime;        //finds the time
rpm=(rev/time)*60000;      //calculates rpm
oldtime=millis();             //saves the current time
rev=0;                        //reset the revolutions counted
Serial.print("ROC BD    " );
Serial.print(rpm);
Serial.println(" RPM");
attachInterrupt(0,isr,FALLING); //restart the interrupt processing
}


The circuit diagram is attached. Two variations from the attached circuit are:
(a) Instead of using the OLED screen, I am trying to log the data in the SD card.
(b) I have no switch on my circuit.

I am only getting values around 3000rpm even for a speed that should be for less than 100rpm.

Please advice, I am a novice in this area. I need the tachometer for my postgraduate project.

Thanks.

wvmarle

Please do an autoformat before posting, makes your code a lot more readable. Formatting is a mess.

You don't need to detach and then attach the interrupt. That's very bad practice. The normal way is to disable interrupts, copy the value to another variable, and re-enable interrupts:

Code: [Select]

noInterrupts();
int revCount = rev;
rev = 0;
interrupts();


Then the rpm calculation is probably going wrong as you're using 16-bit integers, and 60,000 is awfully close to the 65,535 limit of an unsigned int. As you're doing a division you probably best make the whole thing floating point:

Code: [Select]

rpm=(rev/time)*60000.0;      //calculates rpm


Otherwise, making that 60,000 an unsigned long should also do the job forcing the compiler to use a big enough variable:

Code: [Select]

rpm=(rev/time)*60000ul;      //calculates rpm
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

wvmarle

Oh, and rev of course has to be declared volatile. Forgot that one. That may be another source of problems.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

nghtitus

Thank you for the response. I will incorporate your comments in my code and see what happens.

Go Up