Optical Tachometer on Pro Micro clone - code not working

Hi there! Completely new to Arduino.

I am building an optical tachometer using an IR sensor. The tacho works on an Arduino R3 board but I would like to use a pro-micro clone instead, the version I have is 5V 16MHz:

The code is based on the code from James Rovere's Easy Peasy Tachometer project (thanks very much) and works fine on an Arduino R3 using pin 2 as the sensor input. Here is the code:

// optical_tacho2 for Arduino R3
//delay turned to 1000ms
#include <Wire.h>
#include  <Adafruit_SSD1306.h>// You may have to edit library for 128x64,
//  default is  128 x 32.

#define OLED_WIDTH 128
#define OLED_HEIGHT 64

#define  OLED_ADDR   0x3C // A very common address for these displays.

Adafruit_SSD1306  display(OLED_WIDTH, OLED_HEIGHT);


float value=0;
float rev=0;
int  rpm;
int oldtime=0;        
int time;

void isr()          //interrupt  service routine
{
rev++;
}

void setup()
{
 display.begin(SSD1306_SWITCHCAPVCC,  OLED_ADDR);
 display.clearDisplay();
   
digitalWrite(2 ,HIGH);// Instead  of using a pull up resistor. Use pin 2 on arduino R3 board
attachInterrupt(0,isr,RISING);  //attaching the interrupt

}

void  loop()
{
delay(1000);// 1 second delay
detachInterrupt(0);           //detaches  the interrupt while calculating
time=millis()-oldtime;        //finds the time  
rpm=(rev/time)*60000;         //calculates rpm
oldtime=millis();             //saves  the current time
rev=0;

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);// Vertical, Horizontal.
  display.println("RPM:");
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,25);
  display.println(rpm); 
  display.display();
  

  attachInterrupt(0,isr,RISING);


}

For the Pro-micro clone I have changed the IR sensor input pin to 4:

/*
 optical_tacho3_for cheap board.
 Caution!! Use 5V 16MHz settings, else board gets bricked. Use the Arduino bookmarks folder to un-brick devices
 This is the tacho for the cheap pro-micro clone
 on COM22 (may change ports)
//delay turned to 1000ms
// digitalwrite pin changed to 4
*/

#include <Wire.h>
#include  <Adafruit_SSD1306.h>// You may have to edit library for 128x64,
//  default is  128 x 32.

#define OLED_WIDTH 128
#define OLED_HEIGHT 64

#define  OLED_ADDR   0x3C // A very common address for these displays.

Adafruit_SSD1306  display(OLED_WIDTH, OLED_HEIGHT);

float value=0;
float rev=0;
int  rpm;
int oldtime=0;        
int time;
int sensor = 4;

void isr()          //interrupt  service routine
{
rev++;
}

void setup()
{
display.begin(SSD1306_SWITCHCAPVCC,  OLED_ADDR);
display.clearDisplay();
digitalWrite(4 ,HIGH);// Instead  of using a pull up resistor. Use pin 4 on clone


attachInterrupt(0,isr,RISING);  //attaching the interrupt

}

void  loop()
{
delay(1000);// 1 second delay
detachInterrupt(0);           //detaches  the interrupt while calculating
time=millis()-oldtime;        //finds the time  
rpm=(rev/time)*60000;         //calculates rpm
oldtime=millis();             //saves  the current time
rev=0;

display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);// Vertical, Horizontal.
display.println("RPM:");
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,25);
display.println(rpm); 
display.display();
  

attachInterrupt(0,isr,RISING);
}

However, when I upload the code to the pro-micro clone, I get a fixed value on the OLED of RPM: 57

Diagnosis so far:

  • Works fine on R3 board with the IR sensor connected to pin 2
  • Changing the Pro Micro board in IDE to Sparkfun Pro Micro, Adafruit 32U4 Breakout or Arduino Micro has no effect
  • Changing delay(1000) to delay(2000) halves the number displayed to RPM: 29
  • Changing attachInterrupt(0,isr,RISING); detachInterrupt(0); attachInterrupt(0,isr,RISING); to attachInterrupt(4,isr,RISING); detachInterrupt(4); attachInterrupt(4,isr,RISING); displays a fixed RPM: 0 on the OLED

Circuit diagram:

  • Red wire is VCC
  • Black wire is GND
  • Orange wire is SDA (pin 2)
  • Yellow Wire is SCL (pin 3)
  • Brown wire is IR sensor input to board (pin 4)

Many thanks for any help :grinning:

From the Pro Micro schematic, pin 4 equals PD4

image

Based on the datasheet, PD4 is not the INT0 pin.

image

Hi sterretje

Brilliant, thankyou. On the above schematic it looks like pin 3 is INT0. Am I correct?

So how would I have to modify the code to account for this? Apologies, very new to programming...

Is a way to attach the interrupt that might be "easy peasy" but is error-prone
No comments about which IO-pins are interrupt-capable
and as a fixed number you the user must take care of which IO-pin relates to interrupt 0

it is better to use

to attach the correct interrupt

best regards Stefan

1 Like

You have a few options; start by consulting the datasheet of the 32U4 microcontroller if you haven't done so yet.

Next look at the microprocessor pins. There are 5 pins that can be used as external interrupt
PD0..PD3 and PE6. All those pins are broken out on the Pro Micro

Processor    Pro Micro

PD0/SCL      D3/SCL
PD1/SDA      D2/SDA
PD2/RXD1     D0/RX
PD3/TXD2     D1/TX
PE6/AIN0     D7

So make your choice of the ones that are still available and attach the correct interrupt number. Follow @StefanL38's advice for that.

@StefanL38 @sterretje

Thanks very much for your information and help with understanding the functions and pinout above. I will take a look this evening and let you know if i manage to get it working :grinning:

Do you know this funky coverversion of The Monster Mash ?

@StefanL38 brilliant :grinning:

Apologies guys, we have had a big storm here so I've been repairing fences all day. I will report back tomorrow with my tacho findings.

@sterretje @StefanL38

Thanks very much; problem solved!

I started by reloading the program onto my R3 with the following amendments as suggested:

digitalWrite(2 ,HIGH); //Instead  of using a pull up resistor. Use pin 2 on arduino R3 board

attachInterrupt(digitalPinToInterrupt(2),isr,RISING);  //attaching the interrupt

}

void  loop()
{
delay(1000);// 1 second delay
detachInterrupt(digitalPinToInterrupt(2));           //detaches  the interrupt while calculating
time=millis()-oldtime;        //finds the time  
rpm=(rev/time)*60000;         //calculates rpm
oldtime=millis();             //saves  the current time
rev=0;

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);// Vertical, Horizontal.
  display.println("RPM:");
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,25);
  display.println(rpm); 
  display.display();
  

  attachInterrupt(digitalPinToInterrupt(2),isr,RISING);


}

This worked fine, so I then used D7 on the micro clone:

attachInterrupt(digitalPinToInterrupt(2),isr,RISING);

As above, and success :grinning:. Now all I need is 4 wheels and reheat. Cheers all!

I'm surprised :wink: I suspect that that should have been

attachInterrupt(digitalPinToInterrupt(7),isr,RISING);

And that digitalWrite(2 ,HIGH) should have been digitalWrite(7 ,HIGH).

With that said, you should not use magic numbers for pins but rather use names as shown below.

const uint8_t interruptPin = 7;
...
...
digitalWrite(interruptPin ,HIGH)
...
...
attachInterrupt(digitalPinToInterrupt(interruptPin),isr,RISING);

That way you only have to change the pin number once and there is no chance that you forgot to change it somewhere.

@sterretje

Haha! Yes I meant that I changed it to pin 7.

Thanks for your help with the code grammar. I will experiment with assigning as you have described above. Cheers!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.