optocoupler for arduino uno , help!... tachometer adjust.

Hi everyone, I 'm going to measure bldc rpm . I have issue with the opto sensor .

I bought a Groove Opto Coupler for Arduino which states ‘LOW’ when IR led lights on the phototransistor .

Everywhere I find sensor which states ‘HIGH’ when IR led lights on TR .

What is true code about rpm calculating ?

the program :

unsigned int rpm;
float iin=0.0;
float iout=0.0;
int current=0;
float vout = 0.0;
float vin = 0.0;
float R1 = 100000.0;                              
float R2 = 10000.0;                         
int value = 0;
const byte pinStopBTN = A0; 
const byte pinStartBTN = A1; 
const byte LED1 = 9; 
const byte LED2 = 8; 

volatile int rpmcount = 0; 
unsigned long timeold = 0; 

byte startFlag = LOW;  
byte StopBTN = LOW;  
byte StartBTN = HIGH;  


void rpm_func() 
{
 rpmcount++; 
}

void setup(){
 pinMode(analogInput, INPUT);
 pinMode(currentInput, INPUT);
 pinMode(PWMPin,OUTPUT);
 pinMode(digitalPin, INPUT);
 pinMode(digitalPin2, INPUT);
 pinMode(analogPin, INPUT);
 attachInterrupt(0, rpm_func, FALLING);
 pinMode(pinStartBTN,INPUT); 
 pinMode(pinStopBTN,INPUT); 
 pinMode(LED1,OUTPUT);
 pinMode(LED2,OUTPUT); 


 
 lcd.begin(16, 2);
 
}

void loop(){
 if (!StartBTN) { 
   digitalWrite(LED1,LOW); 
   digitalWrite(LED2,HIGH);
   startFlag = HIGH;

}
 if (!StopBTN) { 
   digitalWrite(LED1,HIGH); 
   digitalWrite(LED2,LOW); 
   startFlag = LOW; 
   
}
 

    StartBTN = digitalRead(pinStartBTN); 
 StopBTN = digitalRead(pinStopBTN); 

  { 
 inputValue = analogRead(inputPin);
 inputValue = map(inputValue,0,1023,128 ,255);
 analogWrite(PWMPin,inputValue);  
 
 if (!startFlag) { 
   analogWrite(PWMPin,0); 
if (rpmcount >= 12) { 
  
   detachInterrupt(0);
 
  rpm = (rpmcount * 60000)/(millis() - timeold);     Here I might change something

  timeold = millis();
  rpmcount = 0;
   attachInterrupt(0, rpm_func, FALLING); 
}
 
 if (millis() - timeold > 1500) { 
   rpm = 0; 
 }
 value = analogRead(analogInput); 
current=analogRead(currentInput);
iout=(current*5)/1024.0; 
iin=((iout/10)/0.03);  
  vout = (value * 5.0) / 1024.0; 
  vin = vout / (R2/(R1+R2)); 

 if (vin<0.09) {
  vin=0.0;
 }
lcd.setCursor(0,0 ); 
lcd.print("I= ");
lcd.print(iin);
lcd.setCursor(0, 1);
lcd.print("V= ");
lcd.print(vin);
lcd.setCursor(8, 0);
lcd.print("RPM=");
lcd.print(rpm);
delay(500); // 
} 
}

Thank you in advance:)

Where is the rest of the program ?

Everything works fine . Bldc reaches approx. 10000tr/min , but the calculated rpm are more than 50000,60000 :o . I don't know the exactly code , cause groove opto coupler works the opposite way compared with simple IRled and pTR .

 rpm = (rpmcount * 60000)/(millis() - timeold);     Here I might change something

Try declaring rpm as unsigned long and using 60000UL. If that doesn't work, declare rpmcount as volatile unsigned long as well.

rpmcount*60000 is overflowing

Whether the optocoupler goes high or low at the slot is not important. You will still see one interrupt per revolution.

You do have only one open slot in the encoder wheel?

Yes , i have only one slot in the wheel.

Swapped rpm = (60000ULrpmcounter)/(millis()-timeold); with (10000ULrpmcounter)/(millis()-timeold); , as well unsigned long rpm , volatile unsigned long rpmcount . Approximately equal rpm but unstable , example: 1117 or 9874 and vice versa.

Everyone can help me?

Please go back and modify your first sketch so that the code is posted using the code tags </> icon from the tool bar so that you see the words code in brackets. Your code is posted between the words so that it looks like what I post below.

Try running this simple tachometer code below and report back the results. Your use of detachInterrupt() and attachInterrupt() can create problems, and the resetting of rpm ever 1500ms also looks like it could create a discontinuity.

volatile unsigned long  count = 0;

unsigned long copyCount = 0;
unsigned int rpm = 0;

unsigned long lastRead = 0;

unsigned long interval = 1000;

void setup()
{
  Serial.begin(115200);
  Serial.println("start...");

  attachInterrupt(0, isrCount, FALLING);//interupt signal to pin 2

}

void loop()
{
  if (millis() - lastRead >= interval) //read interrupt count every second
  {
    lastRead  += interval; //millis();
    // disable interrupts,make copy of count,reenable interrupts
    noInterrupts();
    copyCount = count;
    count = 0;
    interrupts();

    rpm = copyCount * 60;
    Serial.println(rpm);
    Serial.println(copyCount);
  }
}

void isrCount()
{
  count++;
}

EDIT: TYPO in ISR count + >> count++;

Works:) thank you !

Stable rpm without fluctuation . rpm = copyCount * 60; changed 60 with 10 . I have to explore this type of rpm metering code , the previous my code was frustrating . If speed falls below 1000rpm , it shows me 9000rpm ,and wide variations of rpm (200,300,400,500) . I measure speed of BLDC with Aerocontroller ,there can not be any variations.

Congrats @cattledog ! You are pro member:)