Arduino Forum

Using Arduino => Programming Questions => Topic started by: travisr100 on Sep 09, 2019, 01:21 am

Title: IR tachometer, weird readings
Post by: travisr100 on Sep 09, 2019, 01:21 am
I'm working on a tachometer using an IR sensor.  It mostly works but I keep getting some peculiar readings.  Here is some serial output showing what I'm talking about...

currTime=1659791008 prevTime=1659664548 interval=126460 spindleRPM=474 rpmd=0
currTime=1659791008 prevTime=1659664548 interval=126460 spindleRPM=474 rpmd=0
currTime=1659917544 prevTime=1659791008 interval=126536 spindleRPM=474 rpmd=0
currTime=1660053264 prevTime=1660044076 interval=9188 spindleRPM=6530 rpmd=6056
currTime=1660053264 prevTime=1660044076 interval=9188 spindleRPM=6530 rpmd=0
currTime=1660170544 prevTime=1660053264 interval=117280 spindleRPM=511 rpmd=-6019
currTime=1660297076 prevTime=1660170544 interval=126532 spindleRPM=474 rpmd=-37
currTime=1660297076 prevTime=1660170544 interval=126532 spindleRPM=474 rpmd=0
currTime=1660423608 prevTime=1660297076 interval=126532 spindleRPM=474 rpmd=0
currTime=1660550084 prevTime=1660423608 interval=126476 spindleRPM=474 rpmd=0
currTime=1660550084 prevTime=1660423608 interval=126476 spindleRPM=474 rpmd=0


If the code helps, here it is...

Code: [Select]

// Screen dimensions
#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 128 

// You can use any (4 or) 5 pins
#define SCLK_PIN 13 //clk/sck
#define MOSI_PIN 3 //din
#define DC_PIN   4 //data command
#define CS_PIN   5
#define RST_PIN  6

// Color definitions
#define  BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0 
#define WHITE           0xFFFF

#define LED_PIN     2
#define LED_COUNT  24
#define BRIGHTNESS 20 //0 to 255

#include <Adafruit_GFX.h>
//#include <Adafruit_SSD1351.h>
#include <Adafruit_SSD1331.h>

#include <Adafruit_NeoPixel.h>
#include <SPI.h>
#include <Fonts/FreeMono9pt7b.h>
//#include <Fonts/FreeMono12pt7b.h>
#include <Fonts/FreeMono18pt7b.h>
//#include <Fonts/FreeMono24pt7b.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeMonoBold18pt7b.h>

//Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN);
Adafruit_SSD1331 tft = Adafruit_SSD1331(CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN);

Adafruit_NeoPixel ring(LED_COUNT, LED_PIN, NEO_RGBW + NEO_KHZ800);


int spindleRPM = 0;
int prevRpm = 0;
volatile unsigned long rpmArray[2] = {0,0}; //array to hold the latest microseconds and previous microseconds
unsigned long tempArray[2] = {60000000, 0};  //temporary array for copying the value of rpmArray so it can be worked on after interrupts started again
long interval = 0; //time between IR pulses
int rightDigits = 0; //stores the portion of the rpm value from 0 to 99 for the ring display
int rpmDifference = 0;  //difference between the current rpm reading and the previous reading
//long currTime = 0;
//long prevTime = 0;
byte mappedPixel = 0;  //the pixel to light up on the ring representing RPM from 0 to 99
int tailSize = 0;  //the size of the "tail" trailing the lighted pixel
byte rpmDigits[4] = {0,0,0,0};  //array to hold digits of the RPM.  Max RPM 9,999.
byte rpmDigitsPrev[4] = {0,0,0,0};  //array to hold previous value of rpmDigits for comparison purposes


void setup(){
  pinMode(21, INPUT_PULLUP);
  Serial.begin(9600);
  tft.begin();
  attachInterrupt(digitalPinToInterrupt(21), isr, FALLING); //Interrupts are called on Rise of Input
  ring.begin();           // Initialize NeoPixel ring object
  ring.show();            // Turn OFF all pixels ASAP
  ring.setBrightness(20); // Set brightness to about 1/5 (max = 255)
  tftPrintBackground();
}

 
void loop(){
  noInterrupts();
  memcpy(tempArray, rpmArray, sizeof tempArray);
  interrupts();
  interval = (tempArray[0] - tempArray[1]);
  spindleRPM = (60*1000000)/interval;
  if (spindleRPM < 0) spindleRPM = 0;  //prevent rpm from being negative from dividing by 0, issue on startup
  rpmDifference = (spindleRPM - prevRpm);
  rightDigits = (spindleRPM % 100);
  displayDigits();  //Displays the RPM digits on the display


 

  if (spindleRPM > 0 ) {
    tftPrintSpindleRPM();
    memcpy(rpmDigitsPrev, rpmDigits, sizeof rpmDigits);
    printx100(); //prints "x100" under RPM if the RPM is > 100
    displayPixel(ring.Color(255,   0,   0), rightDigits, rpmDifference);
    ring.show();
    prevRpm = spindleRPM;
    Serial.print("currTime=");
    Serial.print(tempArray[0]);
    Serial.print(" prevTime=");
    Serial.print(tempArray[1]);
    Serial.print(" interval=");
    Serial.print(interval);
    Serial.print(" spindleRPM=");
    Serial.print(spindleRPM);
    Serial.print(" rpmd=");
    Serial.println(rpmDifference);
    //prevTime = currTime;
  } 
}

void isr(){
  rpmArray[1] = rpmArray[0];
  rpmArray[0] = micros();
}

void displayDigits(){  //breaks out the digits of the RPM and puts them in an array for display.
  int myRPM = spindleRPM;
  if (spindleRPM > 99) myRPM /= 100;
  for (byte i = 0; i < 2; i++) {
    rpmDigits[i] = myRPM % 10;
    myRPM /= 10;
  }
}

void printx100(){
  if (spindleRPM >= 100 && prevRpm < 100) {
    tft.setCursor(5, 20);
    tft.setTextColor(RED); 
    tft.println("x100");
    tft.setFont();
  }
  else if (spindleRPM < 100 &&  prevRpm >= 100) {
    tft.setCursor(5, 20);
    tft.setTextColor(BLACK); 
    tft.println("x100");
    tft.setFont();
  }
}




void displayPixel(uint32_t color, byte rightDigits, int rpmDifference){
//  Serial.print("rpmd= ");
//  Serial.print(rpmDifference);
  rpmDifference = constrain(rpmDifference, -50, 50);  //limiting the acceleration value to 100 or less in either direction
//  Serial.print(" rpmdc= ");
//  Serial.print(rpmDifference);
 
  mappedPixel = map(rightDigits, 0, 99, 0, 23);
  tailSize = map(rpmDifference, -50, 50, -23, 23);
//  Serial.print(" tailsize= ");
//  Serial.println(tailSize);
  ring.clear();
  ring.setPixelColor(mappedPixel, color);         //  Set pixel's color (in RAM)
 
//  Serial.print("Mapped=");
//  Serial.println(mappedPixel);
 
  int m = mappedPixel;
  int brightness = 50;
  int x = 50;
  for (int i=mappedPixel-tailSize; i < mappedPixel; i++){
    uint32_t rgbcolor = ring.ColorHSV(65000, 255, 255);
    x += 10;
    m = i;
    if (m < 0) {
      m=m+24;
    }
//    Serial.println(m);
    ring.setPixelColor(m, rgbcolor);
  }
 
}




void tftPrintSpindleRPM(){
  tft.setFont(&FreeMono18pt7b);
  tft.setTextSize(1);

 //print previous spindleRPM in black to clear it
  tft.setCursor(50, 23);
  tft.setTextColor(BLACK);
 
  if (rpmDigits[1] != rpmDigitsPrev[1]){
    tft.print(rpmDigitsPrev[1]);
  }
  tft.setCursor(70, 23);
  if (rpmDigits[0] != rpmDigitsPrev[0]){
    tft.print(rpmDigitsPrev[0]);
  }
   
  //print the spindleRPM in white
  tft.setCursor(50, 23);
  tft.setTextColor(WHITE);
 
  if (rpmDigits[1] > 0 && rpmDigits[1] != rpmDigitsPrev[1]){
    tft.print(rpmDigits[1]);
  }
  tft.setCursor(70, 23);
  if (rpmDigits[0] != rpmDigitsPrev[0]){
    tft.print(rpmDigits[0]);
  }
  tft.setFont();
}
 

   





void tftPrintBackground() {
  tft.fillScreen(BLACK);

  tft.drawRect(0, 33, 96, 31, GREEN);
  tft.drawLine(31, 33, 31, 64, GREEN);
  tft.drawLine(62, 33, 62, 64, GREEN);

  tft.setFont(&FreeSans9pt7b);
  tft.setCursor(1, 13);
  tft.setTextColor(RED); 
  tft.println("RPM");
  tft.setFont();

  tft.setCursor(7, 38);
  tft.setTextColor(RED);
  tft.setTextSize(1);
  tft.println("MTR");

  tft.setCursor(3, 52);
  tft.setTextColor(WHITE);
  tft.setTextSize(1);
  tft.println("3600");
 
  tft.setCursor(38, 38);
  tft.setTextColor(RED);
  tft.setTextSize(1);
  tft.println("DRV");

  tft.setCursor(35, 52);
  tft.setTextColor(WHITE);
  tft.println("1350");
  tft.setFont();

  tft.setCursor(71, 38);
  tft.setTextColor(RED);
  tft.setTextSize(1);
  tft.println("FPR");

  tft.setCursor(64, 52);
  //tft.setCursor(60, 72);
  tft.setTextColor(WHITE);
  tft.println(".0209");
  tft.setFont();
}
Title: Re: IR tachometer, weird readings
Post by: noweare on Sep 09, 2019, 10:22 am
We don't know what doing.You need to give more information.
Like what are you expecting, other than the numbers look funny.

What are you expecting from the numbers? 
What are you measuring the rpm of ( a motor spindle) ?
Is what ever your measuring constant speed.

I looks like there is gearing of some kind involved. 126 milliseconds is about 8 rpms but you have
474 rpms.

Your turning off interrupts to do a copy. Could you be missing interrupts in that period of time?
Whats your loop time ? If it is fast compared to the interrupts you don't have to turn off interrupts.

set a flag in the interrupt and in loop when the flag is 1 then do the copy or any other stuff that way
your not doing it more than once.

Title: Re: IR tachometer, weird readings
Post by: Gates on Sep 09, 2019, 10:50 am
You might want to look at the .h files for these include files.  This could help you see some pins have already defined.
Code: [Select]
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1331.h>
#include <Adafruit_NeoPixel.h>
#include <SPI.h>
#include <Fonts/FreeMono9pt7b.h>
#include <Fonts/FreeMono18pt7b.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeMonoBold18pt7b.h>
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 09, 2019, 02:23 pm
We don't know what doing.You need to give more information.
Like what are you expecting, other than the numbers look funny.

What are you expecting from the numbers? 
What are you measuring the rpm of ( a motor spindle) ?
Is what ever your measuring constant speed.

I looks like there is gearing of some kind involved. 126 milliseconds is about 8 rpms but you have
474 rpms.

Your turning off interrupts to do a copy. Could you be missing interrupts in that period of time?
Whats your loop time ? If it is fast compared to the interrupts you don't have to turn off interrupts.

set a flag in the interrupt and in loop when the flag is 1 then do the copy or any other stuff that way
your not doing it more than once.


Sorry for not giving more information.  There is a lot of code that I posted that doesn't have anything to do with the problem but I've seen people before get upset when the entire code isn't posted.

I've got an IR sensor that's looking at a piece of reflective tape on a rotating wheel. Each time it sees the tape the ISR is called.  When it's called it measures the time in microseconds into an array and moves the previous value stored to a second position in the array.  Each trip through the sketches main loop it is looking at these two times and calculating what the latest RPM is.

What I posted is the serial output I recorded on the console.  It is showing the two time values from the array (currTime and prevTime), the difference between these two times (interval), the calcluated RPM based on this interval, and the RPM difference from the previous time it was calculated. 

During the serial output I posted the motor is running at a near constant RPM of 474.  Even though the wheel is spinning at a constant RPM I will periodically get "noise."   You can see where the RPM jumps to approximately 6500 all of the sudden when in reality the wheel was running at a constant RPM. 

It's microseconds, not milliseconds I'm measuring thus the formula of 60*1000000/interval to come up with the RPM.  So no, no gearing involved. 

I am turning off interrupts to do a copy as that's what I've seen suggested in other posts.  Yes, I could be missing interrupts with each trip through the main loop of the sketch but it really shouldn't matter.  Or at least I don't believe it should.  It's obvious through the serial output I posted that the ISR is running at least more than once with each trip through the loop otherwise the prevtime value would always be equal to the previous currtime value.   

There are two approaches to calculating RPM.  One is to run the loop at some interval and count the number of pulses during that interval.  This proved to be very inaccurate and causes the RPM to jump by multiples of 60 which has been documented in lots of other posts.  The solution everyone offered was to calculate the time between pulses of the IR instead which is what I'm doing.  Seems to work fine except for the random odd numbers as I posted above.  Something is going on I just can't seem to figure out what.  It's almost like I'm making it through the loop twice before the ISR has had a chance to fire?
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 09, 2019, 03:10 pm
You might want to look at the .h files for these include files.  This could help you see some pins have already defined.

I looked at the libraries and don't see any pins defined in them that I'm trying to use.  I also just tried using a different IR sensor on a different pin.  Results don't change.
Title: Re: IR tachometer, weird readings
Post by: johnwasser on Sep 09, 2019, 03:18 pm
After removing the double-sampling (reporting the same 'curr' and 'prev' times twice):


currTime=1659791008 prevTime=1659664548 interval=126460 spindleRPM=474 rpmd=0
currTime=1659917544 prevTime=1659791008 interval=126536 spindleRPM=474 rpmd=0
Note: One rotation not reported. Next 'prevTime' is 126532 microseconds after previous 'currTime'
currTime=1660053264 prevTime=1660044076 interval=9188 spindleRPM=6530 rpmd=0
currTime=1660170544 prevTime=1660053264 interval=117280 spindleRPM=511 rpmd=-6019
currTime=1660297076 prevTime=1660170544 interval=126532 spindleRPM=474 rpmd=-37
currTime=1660423608 prevTime=1660297076 interval=126532 spindleRPM=474 rpmd=0
currTime=1660550084 prevTime=1660423608 interval=126476 spindleRPM=474 rpmd=0


I note that 117280 + 9188 = 126468 so it looks like there was one spurious interrupt part way through a rotation.  Perhaps a flash of light or some electrical noise triggered the interrupt.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 09, 2019, 03:25 pm
After removing the double-sampling (reporting the same 'curr' and 'prev' times twice):


currTime=1659791008 prevTime=1659664548 interval=126460 spindleRPM=474 rpmd=0
currTime=1659917544 prevTime=1659791008 interval=126536 spindleRPM=474 rpmd=0
Note: One rotation not reported. Next 'prevTime' is 126532 microseconds after previous 'currTime'
currTime=1660053264 prevTime=1660044076 interval=9188 spindleRPM=6530 rpmd=0
currTime=1660170544 prevTime=1660053264 interval=117280 spindleRPM=511 rpmd=-6019
currTime=1660297076 prevTime=1660170544 interval=126532 spindleRPM=474 rpmd=-37
currTime=1660423608 prevTime=1660297076 interval=126532 spindleRPM=474 rpmd=0
currTime=1660550084 prevTime=1660423608 interval=126476 spindleRPM=474 rpmd=0


I note that 117280 + 9188 = 126468 so it looks like there was one spurious interrupt part way through a rotation.  Perhaps a flash of light or some electrical noise triggered the interrupt.
I too have been thinking this is some kind of "noise" or spurious interrupt.  Perhaps the IR sensor when it sees the reflective tape is quickly rising and falling twice or something.  In order to make this more understandable I stripped out all the other code and tried to simplify it for understanding it here.  With the other code stripped out, here's what I have...

Code: [Select]


int spindleRPM = 0;
int prevRpm = 0;
volatile unsigned long rpmArray[2] = {0,0}; //array to hold the latest microseconds and previous microseconds
unsigned long tempArray[2] = {60000000, 0};  //temporary array for copying the value of rpmArray so it can be worked on after interrupts started again
long interval = 0; //time between IR pulses
int rpmDifference = 0;  //difference between the current rpm reading and the previous reading



void setup(){
  pinMode(21, INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(20), isr, FALLING); //Interrupts are called on Rise of Input
 
}

 
void loop(){
  noInterrupts();
  memcpy(tempArray, rpmArray, sizeof tempArray);
  interrupts();
  interval = (tempArray[0] - tempArray[1]);
  spindleRPM = (60*1000000)/interval;
  if (spindleRPM < 0) spindleRPM = 0;  //prevent rpm from being negative from dividing by 0, issue on startup
  rpmDifference = (spindleRPM - prevRpm);
 


 

  if (spindleRPM > 0 ) {
   
    prevRpm = spindleRPM;
    Serial.print("currTime=");
    Serial.print(tempArray[0]);
    Serial.print(" prevTime=");
    Serial.print(tempArray[1]);
    Serial.print(" interval=");
    Serial.print(interval);
    Serial.print(" spindleRPM=");
    Serial.print(spindleRPM);
    Serial.print(" rpmd=");
    Serial.println(rpmDifference);
  } 
}

void isr(){
  rpmArray[1] = rpmArray[0];
  rpmArray[0] = micros();
}



I decided to go ahead and run it to verify I didn't remove anything that should have been left in.  What's interesting is that now that I stripped everything else out, the problem goes away.  I can sit and watch the serial monitor and don't see the problem ever occur where as with all the other code in there the problem seems to occur at least once every 15 seconds or so.  Now I'm really stumped.  I didn't figure stripping out all the other code would make a difference.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 09, 2019, 03:33 pm
I spoke to soon.  I let it run for about 5 minutes and never observed the problem then suddenly saw it again.  But now it seems to only occur once every 5 to 7 minutes where with the other code it was happening every 10 to 15 seconds.

I'm almost to the point of trying to set this up with a hall sensor instead to see if I observe the same problem.  But seems way too much of a coincidence that with the other code taken out it almost never occurs.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 09, 2019, 03:45 pm
And of course now I'm running it with all the other code and almost can't get it to occur.  Ran for 10 minutes without seeing it.

John, I went back and read your post again.  Interesting observation you had about the sum of those two numbers.  I'm thinking you may be right.  During my latest run I only got it to happen once in 5 minutes but when it did, the two numbers added up to close to all the other intervals that were being measured.  I wonder if it's not stray light triggering the sensor.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 09, 2019, 03:52 pm
After removing the double-sampling (reporting the same 'curr' and 'prev' times twice):


currTime=1659791008 prevTime=1659664548 interval=126460 spindleRPM=474 rpmd=0
currTime=1659917544 prevTime=1659791008 interval=126536 spindleRPM=474 rpmd=0
Note: One rotation not reported. Next 'prevTime' is 126532 microseconds after previous 'currTime'
currTime=1660053264 prevTime=1660044076 interval=9188 spindleRPM=6530 rpmd=0
currTime=1660170544 prevTime=1660053264 interval=117280 spindleRPM=511 rpmd=-6019
currTime=1660297076 prevTime=1660170544 interval=126532 spindleRPM=474 rpmd=-37
currTime=1660423608 prevTime=1660297076 interval=126532 spindleRPM=474 rpmd=0
currTime=1660550084 prevTime=1660423608 interval=126476 spindleRPM=474 rpmd=0


I note that 117280 + 9188 = 126468 so it looks like there was one spurious interrupt part way through a rotation.  Perhaps a flash of light or some electrical noise triggered the interrupt.
John, I think you nailed it.  I've been sitting here watching it run and looking at each instance where it occurs.  So far each time it happens if you add the two up they come out to right at what the interval should have been.  It must be seeing some stray light that's somehow triggering it part way through a rotation.
Title: Re: IR tachometer, weird readings
Post by: TomGeorge on Sep 10, 2019, 02:01 pm
HI,
Just out of curiosity, you have an IR sensor, reflective tape.
What is your source of IR energy to reflect off the tape?
Is the tape specified for IR reflection?

Tom... :)
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 10, 2019, 03:23 pm
I'm using these emitter/sensors:

FTCBlock 10PCS IR Infrared Obstacle Avoidance Sensor Module for Arduino Smart Car Robot https://www.amazon.com/dp/B07H2TH8BH/ref=cm_sw_r_cp_tai_dj6DDb8HJ0KGM

The tape is tape that came with a handheld IR tachometer so I assume so.

From what I'm observing it doesn't seem to have any problem sensing the tape.  It seems like it's sensing an extra pulse during a revolution.
Title: Re: IR tachometer, weird readings
Post by: johnwasser on Sep 10, 2019, 03:29 pm
From what I'm observing it doesn't seem to have any problem sensing the tape.  It seems like it's sensing an extra pulse during a revolution.
Does the extra pulse usually come around the same place in the revolution?  If so you might just have a shiny spot.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 10, 2019, 03:35 pm
Not in front of the setup at the moment to check that.  But I'll give it a look when I can.  That is possible.  Seems to be awfully intermittent though.  It can run over 1000 revolutions without the problem happening.  I've got a hall sensor on order and going to see if that fixes the problem although I wanted to stay away from using any magnets.
Title: Re: IR tachometer, weird readings
Post by: KrisKasprzak on Sep 10, 2019, 08:33 pm
Travisr100.

Did you get this issue fixed? I have the same exact problem using these sensors. I suspect my issue is stray light, but not sure--I feel my setup is well hidden from light.

I've implemented software and hardware debouncers, and that seemed to help but not totally fixed my issue. Hoping you have the magic sauce :)

Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 10, 2019, 09:30 pm
Not yet. Stray light could be my problem as well. Going to try shielding it as best I can and see what the results are. I believe these sensors are extremely sensitive.

Debouncing in code would be difficult for me because of the range of rpm I'm measuring. Most values I would exclude with denounce code would be acceptable values at other RPM's. What I could do is check for a percentage variance from the last reading and discard it if it was higher than x% difference. Even then however I have to take acceleration into account.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 11, 2019, 12:59 am
Well, it's not stray light.  Hall sensor came in today and got it hooked up.  I'm still seeing the same problem.  Here's another copy of some console output...

currTime=302183396 prevTime=302083416 interval=99980 spindleRPM=600 rpmd=0
currTime=302283356 prevTime=302183396 interval=99960 spindleRPM=600 rpmd=0
currTime=302383316 prevTime=302283356 interval=99960 spindleRPM=600 rpmd=0
currTime=302483308 prevTime=302383316 interval=99992 spindleRPM=600 rpmd=0
currTime=302483308 prevTime=302383316 interval=99992 spindleRPM=600 rpmd=0
currTime=302583328 prevTime=302483308 interval=100020 spindleRPM=599 rpmd=-1
currTime=302683328 prevTime=302583328 interval=100000 spindleRPM=600 rpmd=1
currTime=302783284 prevTime=302683328 interval=99956 spindleRPM=600 rpmd=0
currTime=302883220 prevTime=302783284 interval=99936 spindleRPM=600 rpmd=0
currTime=302886808 prevTime=302883220 interval=3588 spindleRPM=16722 rpmd=16122
currTime=302983180 prevTime=302886808 interval=96372 spindleRPM=622 rpmd=-16100
currTime=303083176 prevTime=302983180 interval=99996 spindleRPM=600 rpmd=-22
currTime=303183220 prevTime=303083176 interval=100044 spindleRPM=599 rpmd=-1
currTime=303283256 prevTime=303183220 interval=100036 spindleRPM=599 rpmd=0
currTime=303283256 prevTime=303183220 interval=100036 spindleRPM=599 rpmd=0
currTime=303383236 prevTime=303283256 interval=99980 spindleRPM=600 rpmd=1
currTime=303483140 prevTime=303383236 interval=99904 spindleRPM=600 rpmd=0
currTime=303583056 prevTime=303483140 interval=99916 spindleRPM=600 rpmd=0
currTime=303683028 prevTime=303583056 interval=99972 spindleRPM=600 rpmd=0
currTime=303683028 prevTime=303583056 interval=99972 spindleRPM=600 rpmd=0
currTime=303783068 prevTime=303683028 interval=100040 spindleRPM=599 rpmd=-1
currTime=303883140 prevTime=303783068 interval=100072 spindleRPM=599 rpmd=0
currTime=303983188 prevTime=303883140 interval=100048 spindleRPM=599 rpmd=0


johnwasser still seems to be on to something.  If you look at the two oddball intervals above, 3588 and 96372, they add up to 99,960 which would be right in line with the other intervals.  I'm stumped as to what may be causing this.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 11, 2019, 01:13 am
I'm having an even harder time explaining these...

currTime=166339132 prevTime=166289152 interval=49980 spindleRPM=1200 rpmd=-1
currTime=166439184 prevTime=166389140 interval=50044 spindleRPM=1198 rpmd=-2
currTime=166539364 prevTime=166489260 interval=50104 spindleRPM=1197 rpmd=-1
currTime=166589480 prevTime=166539364 interval=50116 spindleRPM=1197 rpmd=0
currTime=166689708 prevTime=166639596 interval=50112 spindleRPM=1197 rpmd=0
currTime=166789832 prevTime=166739792 interval=50040 spindleRPM=1199 rpmd=2
currTime=166839816 prevTime=166791540 interval=48276 spindleRPM=1242 rpmd=43
currTime=166939668 prevTime=166889764 interval=49904 spindleRPM=1202 rpmd=-40
currTime=166989556 prevTime=166939668 interval=49888 spindleRPM=1202 rpmd=0
currTime=167089352 prevTime=167039448 interval=49904 spindleRPM=1202 rpmd=0
currTime=167189236 prevTime=167139276 interval=49960 spindleRPM=1200 rpmd=-2
currTime=167239228 prevTime=167189236 interval=49992 spindleRPM=1200 rpmd=0
currTime=167339328 prevTime=167289260 interval=50068 spindleRPM=1198 rpmd=-2
Title: Re: IR tachometer, weird readings
Post by: KrisKasprzak on Sep 11, 2019, 05:20 am
my units have a sensitivity pot, maybe you can adjust it's sensitivity?
Title: Re: IR tachometer, weird readings
Post by: Gates on Sep 11, 2019, 12:05 pm
maybe buy an oscilloscope to test your signal speed/s.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 11, 2019, 02:17 pm
my units have a sensitivity pot, maybe you can adjust it's sensitivity?
Mine do as well.  I currently have them set to the minimum sensitivity.  Thing is, the problem occurs with the hall/proximity sensor as well.
Title: Re: IR tachometer, weird readings
Post by: TomGeorge on Sep 11, 2019, 02:31 pm
Hi,
Time to get serious. :)

Can you please post some pictures of your project so we can see your component layout?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Please not a fritzy picture circuit...

Thanks.. Tom.. :)
Title: Re: IR tachometer, weird readings
Post by: TomGeorge on Sep 11, 2019, 02:37 pm
Hi,
This is your sensor, it is not physically designed for tacho application, you need shrouds over both the emitter and sensor.
They will be sensitive to not just straight ahead range, but sideways as well.
(https://forum.arduino.cc/index.php?action=dlattach;topic=635291.0;attach=324016)

Tom.. :)
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 11, 2019, 02:51 pm
Hi Tom, you are correct. That's the sensor I'm using. I've also tried this one...

Twidec/10mm Hall Effect Proximity Sensor Inductive Switch NPN NO(Normally Open) with Magnet DC5-30V NJK-5002C https://www.amazon.com/dp/B07P1GKQRM/ref=cm_sw_r_cp_api_i_C1oEDbTBHRNA7

I'm not in front of the setup at the moment but will be happy to post a picture later when I can.

I'm not sure what software I'd use to create the circuit diagram.

And I do have a scope but haven't broken it out and hooked it up on this yet.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 11, 2019, 02:57 pm
You said that IR sensor is not designed for a tach application. If you can point me to one that is I'll be happy to order one.
Title: Re: IR tachometer, weird readings
Post by: Gates on Sep 13, 2019, 04:27 pm
Hi Tom, you are correct. That's the sensor I'm using. I've also tried this one...

Twidec/10mm Hall Effect Proximity Sensor Inductive Switch NPN NO(Normally Open) with Magnet DC5-30V NJK-5002C https://www.amazon.com/dp/B07P1GKQRM/ref=cm_sw_r_cp_api_i_C1oEDbTBHRNA7

I'm not in front of the setup at the moment but will be happy to post a picture later when I can.

I'm not sure what software I'd use to create the circuit diagram.

And I do have a scope but haven't broken it out and hooked it up on this yet.
Brake it out dude... lol
Title: Re: IR tachometer, weird readings
Post by: TomGeorge on Sep 13, 2019, 04:43 pm
Hi,

Quote
I'm not sure what software I'd use to create the circuit diagram.
A picture of a hand drawn circuit in jpg, png?


Thanks.. Tom.. :)
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 13, 2019, 09:37 pm
Sorry Tom, I've been busy and haven't had a chance.  Will get to it however.  This thing isn't even on a breadboard.  The sensor is connected directly to the arduino, 5v, gnd, and signal.  That's it.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 18, 2019, 01:52 am
Sorry this has taken me so long to get to.  I got busy with some other stuff and also wanted to boil this down to basics to eliminate any other possibilities.  Here is a pic...

Tach Circuit (https://www.dropbox.com/s/m1kqd0nlu8r64rk/tach.jpg?dl=0)

This should suffice for a circuit diagram as well.  As I said it's extremely basic.  Signal pin from hall sensor to pin 2 on the nano.  Other than that just power and ground.  I got rid of the display and other components to get it down to basics.  This is also a new board I'm trying it with.  I previously had it on a Mega.  Still getting the same results. 

Here's some more console output...

 period0=69216    rpm=866    rpmd=0    srpm=866
 period0=69196    rpm=867    rpmd=1    srpm=866
 period0=69200    rpm=867    rpmd=0    srpm=867
 period0=69208    rpm=866    rpmd=1    srpm=867
 period0=69184    rpm=867    rpmd=1    srpm=867
 period0=69188    rpm=867    rpmd=0    srpm=867
discard period0=37648    rpm=1593    rpmd=726    srpm=978
discard period0=31532    rpm=1902    rpmd=309    srpm=1156
discard period0=69168    rpm=867    rpmd=1035    srpm=1191
 period0=69152    rpm=867    rpmd=0    srpm=867
 period0=69160    rpm=867    rpmd=0    srpm=867
 period0=69168    rpm=867    rpmd=0    srpm=867
 period0=69144    rpm=867    rpmd=0    srpm=867
 period0=69156    rpm=867    rpmd=0    srpm=867
 period0=69168    rpm=867    rpmd=0    srpm=867
 period0=69156    rpm=867    rpmd=0    srpm=867
 period0=69160    rpm=867    rpmd=0    srpm=867

Ther period0 line is the period between pulses.  You can see the motor is running at a stead 867 RPM or approximately 69,160 microseconds between pulses.  You'll see when the anomaly occurs it's like it's registering a pulse half way around the wheel.  The two outlier pulses of 37,648 and 31,532 add up to 69,180 which is very close to all the normal pulse values. 

I've tried this with the hall sensor, two different IR sensors, and two different arduino boards.  It seems to be pretty consistent. 
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 18, 2019, 02:34 am
As I was reading my last post I was asking myself what other variables I had not tried changing.  I figured it couldn't possibly make any difference but I went looking for a different USB cable.  The one I've been using is about 5' long allowing the arduino to sit on my desk in front of my keyboard while the computer is on a shelf above.  The only other cable I had was a little 6" cable.  I tried that cable and the problem disappeared.  In using the 6" cable I had to move the arduino right up next to the computer on the shelf.

This confuses me.  I'm not sure if the difference is the cable or the fact that the arduino moved from the desk up next to the computer.  i don't have a bunch of other electronic gear near the arduino that could be generating any interference I don't think.  Although my keyboard and mouse next to the arduino are wireless. 

I'll also mention that I tapped onto the signal wire and hooked it up to my scope.  I know virtually nothing about using a scope.  I was able to trigger on the signal from the hall and as I increased or decreased the motor speed I could see the pulse width changing on the scope.  What I did not see were any sudden jumps in the pulse width on the scope like what I'm seeing in the output of the serial console.  But it may be that it's happening so quickly that it's not really visible to the eye.  I don't know enough to generate a single shot capture when the pulse width changes above or below a certain threshold.  But what I'm seeing leads me to believe the pulse width isn't actually changing. 

Very much scratching my head here. 
Title: Re: IR tachometer, weird readings
Post by: SteveMann on Sep 18, 2019, 03:54 am
I know this is a Band-Aid, but could you accept throwing out readings that aren't within, say 20% of the prior reading?

But, I am reluctant to do Band-Aids in my projects without knowing what is really happening.
Title: Re: IR tachometer, weird readings
Post by: TomGeorge on Sep 18, 2019, 08:18 am
Hi,
Thanks. OPs pic/circuit.
(https://forum.arduino.cc/index.php?action=dlattach;topic=635291.0;attach=324844)
Tom. :)
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 18, 2019, 02:25 pm
Tom, how did you get that image inline on the post?  When I click the insert image button it's asking me for a URL.  Doing it as an attachment?

Steve, I have considered throwing out the readings based on some criteria.  You can see my console output says "discard" before several of the readings which is just me debugging to determine what to throw away.  As you said, I hate doing that without knowing what's going on.  In addition, kind of difficult to know what to throw away with this particular problem.  My "discard" is looking  at the length of the current period compared to last period and throwing it away if it's more than 2000.  This won't catch it every time however.  In addition there's the situation of acceleration.  If I share this code someone else's motor parameters may be completely different than mine and what I use as a means to discard readings may not work for someone else's situation.
Title: Re: IR tachometer, weird readings
Post by: travisr100 on Sep 19, 2019, 03:13 am
For any of you that want to see what the final code looks like here it is.  Feel free to criticize at will. 

Code: [Select]



volatile unsigned long period = 0; //time between pulses
volatile unsigned long prevTime = 0; //the last micros() we measured
volatile bool newMeasurementAvailable = 0;
unsigned long stablePeriod = 0; //
byte pointer = 0; //pointer to keep track of next position in array to store value
byte numPrevReadings = 0; //the number of readings to smooth, can be from 1 to 10, always starts at 1, dynamically changed based on period/RPM

unsigned long matrix[4][10] = {  //initialize the array with zeros
                              {0,0,0,0,0,0,0,0,0,0}, //stores the pulse period
                              {0,0,0,0,0,0,0,0,0,0}, //stores raw rpm
                              {0,0,0,0,0,0,0,0,0,0}, //stores smoothed rpm of current reading and numPrevReadingss
                              {0,0,0,0,0,0,0,0,0,0}  //not used just haven't decided if I'm going to or not
                              };

unsigned long total = 0;



void setup(){
  pinMode(21, INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(2), isr, FALLING); //Interrupts are called on Rise of Input
  Serial.println("Begin");
}

 
void loop(){
  if (newMeasurementAvailable) {
    noInterrupts();
    stablePeriod = period;
    interrupts();

    storeAndProcess();
    newMeasurementAvailable = 0;
   
    int rpmd = getRPM(0) - getRPM(1);  // rpm delta from the previous reading
    Serial.print(" period0=");
    Serial.print(getPeriod(0));
    Serial.print("\t rpm=");
    Serial.print(getRPM(0));
    Serial.print("\t rpmd=");
    Serial.print(abs(rpmd));
    Serial.print("\t srpm=");
    Serial.println(getSmoothedRPM(0));


  }
}

void storeAndProcess() {
  matrix[0][pointer] = stablePeriod;  //store the period
  matrix[1][pointer] = (60 * 1000000) / matrix[0][pointer];  //store the raw RPM

  //The next line determines the number of previous periods to use to calculate the average. As speed increases, number of previous readings will increase to a maximum of 9.
  //Using 125000 as a value below is a period of 1/8 of a second (1,000,000/125,000).  This equates to 480 RPM.  So up to 480 RPM it uses one reading.  At every multiple
  //of 480 RPM the number of values used for smoothing will increase by 1 up to 4800 RPM.  With an array of 10 elements as defined in this sketch that only gives us a max
  //of the current value plus the 9 previous values.  The array could be defined with more than 10 elements if you wanted to change this.  Additionally instead of using
  //simple division as I've done you could use the map function to define the range of potential RPM's at which you want smoothing done.
  numPrevReadings = 125000 / stablePeriod;
  numPrevReadings = constrain(numPrevReadings, 0, 9);
  total = stablePeriod;  //start with the period we just measured
  if (numPrevReadings != 0) {
    for (int i = 0; i < numPrevReadings; i++) {  //add numPrevReadings previous periods
      total += getPeriod(i);
    }
   }
  matrix[2][pointer] = ((numPrevReadings + 1) * (60 * 1000000)) / total;  //store the smoothed RPM
  if (pointer++ >= 9) pointer = 0;  //increment the pointer to the position to store the next reading
 
}

unsigned long getPeriod(byte position) {
  //position  = 0 returns the last recorded value
  //position = 1 returns next oldest and so on
  int positionToGet = (pointer - 1 - position);
  if (positionToGet < 0) positionToGet += 10;
  unsigned long value = matrix[0][positionToGet];
  return value;
}

unsigned long getRPM(byte position) {
  int positionToGet = (pointer - 1 - position);
  if (positionToGet < 0) positionToGet += 10;
  unsigned long value = matrix[1][positionToGet];
  return value;
}

unsigned long getSmoothedRPM(byte position) {
  int positionToGet = (pointer - 1 - position);
  if (positionToGet < 0) positionToGet += 10;
  unsigned long value = matrix[2][positionToGet];
  return value;
}

void isr(){
  newMeasurementAvailable = 1;
  period = micros() - prevTime;
  prevTime = micros();
}