Wierd value when using Micros()?

I have a system that is counting the cycles of a square function. At times it has noise, so I am looking to not count any cycles that are too short (they must be atleast 1/3 the duration it should be).

I have a variable set to unsigned long to capture the micros() when a interrupt happens. If the time between the previous micros and the current micros is not longer than the 1/3 duration time, it doesnt count it. But, I am getting some odd values back. Note- My system is going a bit nuts due to what I think is noise in signals, but want to start here as this is straightforward. My system works well until the fan gets to 20,000 RPM or so, causing this interrupt to strike more often but is really nothing when it comes to signals. It performs reliably until 17,000 or so.

I attach the interrupt, delay 1000, then detach the interrupt. The interrupt code is:

void tickL() {
  if ((micros()-pmicros)>bouncetime){
    L=L+1;
  }else{
    Serial.print("Did not count cycle of: ");
    Serial.println(micros()-pmicros);
  }
  pmicros=micros();
}

It calculates a delta in the time that looks a lot like the max unsigned long value, but not sure why

22:16:01.096 -> Kicked out cycle of: 4294966608
22:16:01.129 -> Kicked out cycle of: 336
22:16:01.162 -> Kicked out cycle of: 4294966608
22:16:01.196 -> Kicked out cycle of: 336
22:16:01.196 -> Kicked out cycle of: 4294966608
22:16:01.229 -> Kicked out cycle of: 336
22:16:01.263 -> Kicked out cycle of: 4294966608
22:16:01.296 -> Kicked out cycle of: 336
22:16:01.329 -> Kicked out cycle of: 336

Please post a complete sketch so that the variable declarations can be seen

For instance, are pmicros and L declared as volatile as they should be. Not too that Serial.println() does not work properly in an ISR because it uses interrupts and they are disabled when in an ISR

So it that "not properly" or "not at all"? :thinking:

Attempting to use functions such as "Serial.println()" in an interrupt indicates complete ignorance of the purpose of interrupts and generally that interrupts should not be used in the first place. :roll_eyes:

I chose my words carefully to cover both possibilities

Try using one value of micros() instead of three:

void tickL() 
{
  unsigned long currentMicros = micros();
  if ((currentMicros-pmicros)>bouncetime){
    L=L+1;
  }else{
    Serial.print("Did not count cycle of: ");
    Serial.println(currentMicros-pmicros);
  }
  pmicros=currentMicros;
}

micros() uses the Timer0 count which continues counting even with interrupts disabled.

1 Like

I put it in quickly to see what was going on to troubleshoot, which it has successfully done in the interim

Full code below. Note- I have encountered what seems to be noise errata in this system, which has caused me to isolate the fans from the arduino (as it should). They are triggered through a mechanical relay board that provides isolation, and the power to flip the relays in the board is dedicated as well.

I have 3 supplies. A 12V supply that powers the fans, and the LED side of an optocoupler. The other side of the opto is the arduino circuit powered by a separate 12v supply. The opto is brought up/down by the hall effect sensor in the fan. The third supply is a 5V supply that powers the J-VCC on the relay board.

Creating this true electrical isolation solved my problems and got me to deploy this system. However, it still failed when I ran BOTH fans, even when one hall effect sensor was completely disconnected. Which made me think one fan, purely by running, is inducing noise in the other fans signal. However, I could read the signal at the arduino and it looked perfect (I debounced etc and nothing every got it reading correctly with both running). So, my system runs one fan, measures it, then runs the other, measures it. "Both running" would mean (to the arduino): two low signals to the relay board to close this circuits, the 5v then flips the relays which allows the 12v+ to power the fans. Both Optos recieving hall effect sensor signals (ground). I never made sense of this, but the system reacted similar as it does now with this new fan.

Anyways- running one fan at a time, the system has been working perfectly for 300+ tests. Now, I introduce the higher speed fan (which, does have some additional features internally- slow start etc, but the voltage/amperage and hall effect are the same). When the fan gets to 17,000+, the system goes bonkers as I saw before when circuits got noisy (may not be fact, hypothesizing). Readings go all over the place basically, even when before I could read the signal to the arduino is fine.

So, I put in this debounce thinking it was reading way too many cycles. Which it doesnt appear to, but since I put this in, the system locks up- Continues to Serial.print, but it seems functions outside of the Interrupt are not working. Note this may be 100% caused by putting serial.print in the interrupt, and if so is NOT the root cause but more errata I have caused by trying to troubleshoot.

One piece of info- when it locks up, and I power the whole system down while plugged into the USB (so fans shut off, optos get no LED power), the system catches back up to itself/un-locks up. So the 12v+ from the fans and the hall effect somehow are causing it to lock up. This would stop the interrupts, and if the serial.print is causing this issue, would explain it. But, not explain why the system gets terrible readings when the fan speeds up.

When the fan is sped up, the system is in delay(1000), with interrupt on only L=L+1 for interrupt. The loop its performing was working perfectly for the first 12 seconds and perfectly for slower moving fans, so its 100% related to the fan speeding up and whatever electrical (likely) fallout that is causing. Turning on/off fans doesnt cause any issues in the system.

Simplified circuit below (does not show the relay board, or any of the buttons/screens running purely off the arduino). Some value resistors etc have changed but you get the idea.

///SCREEN STUFF
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int lstart=1;// 25; //Where to start drawing updated RPM
int rstart=65;//95; 
int yRPM=33;//18;  //row where RPM info is

unsigned long timestamp;

String PN;
int ftime;
String PN1="9HV_08"; //14,900
int fan1min=14400;
int fan1max=15400;
int ftime1=9;
String PN0="9HVA08"; //16,100
int fan0min= 15600;
int fan0max= 16600;
int ftime0=9;
String PN2="9HVB08"; //18,3009HVB0812P1G001
int fan2min= 17800;
int fan2max= 18800;
int ftime2=16;

bool lpass=true;
bool rpass=true;
bool failure=false;

int min;
int max;



int lsensorpin = 2;
int rsensorpin= 3;
int rgled=4;
int rrled=5;
int gbut=7;
int rbut=6;
int lgled=8;
int lrled=9;
int lrelaypin= 10;
int rrelaypin=11;
int flippin1=12; //Guessing
int flippin2=15; //A1
int debugout=16; //A2
bool redexit=false;
int x=0;
int flipvalue=3;
bool flipchange=false;

unsigned long pmicros;
int bouncetime=500; //(debounce time in Micros)

bool TS=false;

volatile unsigned long L=0;
volatile unsigned long R=0;
unsigned long lRPM=0;
unsigned long rRPM=0;

void setup() {
  pinMode(lsensorpin, INPUT);//_PULLUP); //2
  pinMode(rsensorpin, INPUT);//_PULLUP); //3
  pinMode(rgled, OUTPUT); //4
  pinMode(rrled, OUTPUT); //5
  pinMode(gbut, INPUT_PULLUP); //6
  pinMode(rbut, INPUT_PULLUP); //7
  pinMode(lgled, OUTPUT); //8
  pinMode(lrled, OUTPUT); //9
  pinMode(lrelaypin, OUTPUT); //10 
  pinMode(rrelaypin, OUTPUT); //11
  pinMode(flippin1, INPUT_PULLUP); //15
  pinMode(flippin2, INPUT_PULLUP); //15
  pinMode(debugout, OUTPUT);
  //SDA18
  //SCL19
  


        // IDK WHy but screen needs this
      if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
        //Serial.println(F("SSD1306 allocation failed"));
        for(;;); // Don't proceed, loop forever
      }

      display.display(); //Show Adafruit logo 2 seconds
      delay(500); // Pause for 2 seconds
      display.clearDisplay();
      //setupscreen(1); will be done under setflipper
  
  setflipper(); 
  fanson(0);
  lightdemo();
  Serial.begin(9600);
  Serial.println("FInish Setup");
}

//void loop(){};

void loop() {
  setflipper();

  if ((failure==true) && (digitalRead(rbut)==false)){  //There was a failure and pressing red button to reset.  If not pressing red it will go on to checking GO
    setlights(0,0,0,0);
    failure=false;
    //SOMETHING RESETTING SCREEN BACK TO DISPLAYING MIN MAX

  }

 
  if ((failure==false) && (digitalRead(gbut)==false) && (TS==false)){ //No previous failure and Green is go
    setupscreen(1);
    setlights(0,0,0,0);
    L=0;
    R=0;

    lRPM=0;
    rRPM=0;
    initiateandmonitor(1); 
    //Serial.print("Got out of initiate with redexit=");
    //Serial.println(redexit);
    
    if (redexit==false){ //Spun up without red button
      //setupscreen(40); //"Left"
      //attachl();
      initiateandmonitor(2);
      if (redexit==false){
        //measure right
        //shut down and measure/displauy
        fanson(0);
        lpass= (lRPM<max && lRPM>min);
        rpass= (rRPM<max && rRPM>min);
        
          if (lpass==true && rpass==true){
            failure=false;
            setlights(1,0,1,0);
          }else if (lpass==true && rpass==false){
            failure=true;
            setlights(1,0,0,1);
          }else if (lpass==false && rpass==true){
            failure=true;
            setlights(0,1,1,0);
          }else{
            failure=true;
            setlights(0,1,0,1);
          }
        setupscreen(2);
        }
    }
  }
}

void setflipper(){
  flipchange=false;
  if (digitalRead(flippin1)==false) { 
    if (flipvalue!=1){ //value has changed
      TS=false;
      flipchange=true;
      flipvalue=1;
      PN=PN1;
      ftime=ftime1;
      min=fan1min;
      max=fan1max;
    }
  }else if(digitalRead(flippin2)==false){
     if (flipvalue!=2){ //value has changed
        TS=false;
        flipchange=true;
        flipvalue=2;
        ftime=ftime2;
        PN=PN2;
        min=fan2min;
        max=fan2max;
     }
  }else{
     if (flipvalue!=0){ //value has changed
      if(digitalRead(rbut)==false){
          TS=true;
          flipchange=true;
          flipvalue=0;
          ftime=60;
          PN="TShoot";
          min=0;
          max=0;
        }else {
        TS=false;
        flipchange=true;
        flipvalue=0;
        ftime=ftime0;
        PN=PN0;
        min=fan0min;
        max=fan0max;
        }
    }
  }
  if(flipchange==true){setupscreen(1);}

}

void tickL() {
  if ((micros()-pmicros)>bouncetime){
    L=L+1;
  }else{
    Serial.print("Did not count cycle of: ");
    Serial.println(micros()-pmicros);
  }
  pmicros=micros();
}

void tickR() {
  if ((micros()-pmicros)>bouncetime){
    R=R+1;
  }else{
    Serial.print("Did not count cycle of: ");
    Serial.println(micros()-pmicros);
  }
  pmicros=micros();
}

void setlights(bool lg, bool lr, bool rg, bool rr) {
digitalWrite(lgled, lg);
digitalWrite(lrled, lr);
digitalWrite(rgled, rg);
digitalWrite(rrled, rr);
}

void lightdemo() {
setlights(1,0,1,0);
delay(1000);
setlights(0,1,0,1);
delay(1000);
setlights(0,0,0,0);
}

void fanson(int fan) {
  if(fan==1){ //LEFT
    digitalWrite(lrelaypin, false);
    digitalWrite(rrelaypin, true);
  }else if(fan==2){
    digitalWrite(lrelaypin, true);
    digitalWrite(rrelaypin, false);
  }else if (fan==0){
    digitalWrite(lrelaypin, true);
    digitalWrite(rrelaypin, true);
  }
}

void attachl(){
    attachInterrupt(digitalPinToInterrupt(lsensorpin), tickL, RISING);
}

void detachl(){
    detachInterrupt(digitalPinToInterrupt(lsensorpin));
}
void attachr(){
    attachInterrupt(digitalPinToInterrupt(rsensorpin), tickR, RISING);
}

void detachr(){
    detachInterrupt(digitalPinToInterrupt(rsensorpin));
}


void initiateandmonitor(int fan){
    fanson(fan);
    //delay(500);
    redexit=false;
    for(x = ftime; x>0; x--){
      if(digitalRead(rbut)==false){
        redexit=true;
        fanson(0);
        Serial.println("Breaking the fans");
        setlights(0,1,0,1);
        setupscreen(3);
        break;
      }else{
        if (fan==1){
            L=0;
            pmicros=micros();
            attachl();
            delay(1000);
            detachl();
            lRPM=L*30;
        }else if(fan==2){
            R=0;
            pmicros=micros();
            attachr();
            delay(1000);
            detachr();
            rRPM=R*30;
        }
      setupscreen(2);  
      }    
    }

    if(x=0) Serial.println("Spun up with no red button");
}


//SCREENSTUFFFFFFF

void setupscreen(int y) {  //y=1 for showing PN being tested.  y=2 to display results, y=3 for count down
        display.clearDisplay();
        display.setTextSize(2); // Draw 2X-scale text
        display.setTextColor(SSD1306_WHITE);

        if (y==1){
        //Lines
        display.drawLine(0, 15, display.width()-1, 15, SSD1306_WHITE);
        display.drawLine(0, 16, display.width()-1, 16, SSD1306_WHITE);
        display.drawLine(62, 15, 62, 55, SSD1306_WHITE);
          
          //Header

          display.setCursor(0, 0);
          display.print("PN:");
          display.setCursor(50, 0);
          display.print(PN);
          
          //RPM HEaders
          display.setTextSize(1);
          display.setCursor(0, 18);
          display.print("MIN:");
          display.setCursor(70, 18);
          display.print("MAX:");
          display.setCursor(0, 48);
          display.print("SPINUP:");

          //Print Min Max
          display.setCursor(lstart, yRPM);
          display.print(min);
          display.setCursor(rstart, yRPM);
          display.print(max);
          display.setCursor(45, 48);
          display.print(ftime);
        }else if (y==2){
          //Lines
          display.drawLine(0, 15, display.width()-1, 15, SSD1306_WHITE);
          display.drawLine(0, 16, display.width()-1, 16, SSD1306_WHITE);
          display.drawLine(62, 15, 62, 55, SSD1306_WHITE);
          
          //Header
          display.setCursor(0, 0);
          display.print("Left");
          display.setCursor(68, 0);
          display.print("Right");
          
          //RPM HEaders
          display.setTextSize(1);
          display.setCursor(0, 18);
          //display.print("RPM:");
          if(x>0){
            display.print("RPM: T:");
            display.setCursor(50, 18);
            display.print(x);
          } else{
             display.print("RPM:");;            
          }
          display.setCursor(65,18);
          display.print("RPM:");

          //PN at bottom when printing RPM
          display.setCursor(0,55);
          display.print(String(PN));
          display.setCursor(65,48);
          display.print(min);
          display.setCursor(65,55);
          display.print(max);
          //Serial.println("Part is " + PN);

          //Print RPM's
          display.setTextSize(2);
          display.setCursor(lstart, yRPM);
          display.print(lRPM);
          display.setCursor(rstart, yRPM);
          display.print(rRPM);
        }else if (y==3){ //fans spinning
          if (redexit==true){
            display.setTextSize(3);
            display.setCursor(5,24);
            display.print("STOP");
          }else{
            //Lines
            display.drawLine(0, 15, display.width()-1, 15, SSD1306_WHITE);
            display.drawLine(0, 16, display.width()-1, 16, SSD1306_WHITE);
            
            //Header
            display.setCursor(0, 0);
            display.print("SPIN UP");

            //Countdown
            display.setTextSize(3);
            display.setCursor(50,20);
            display.print(x);
          }
        }else if (y==40){ //LEft
          //Lines
          display.drawLine(0, 15, display.width()-1, 15, SSD1306_WHITE);
          display.drawLine(0, 16, display.width()-1, 16, SSD1306_WHITE);  
          //Header
          display.setCursor(0, 0);
          display.print("Measure");
          //Countdown
          display.setTextSize(3);
          display.setCursor(20,20);
          display.print("Left");
        }else if (y==41){ //Right
          //Lines
          display.drawLine(0, 15, display.width()-1, 15, SSD1306_WHITE);
          display.drawLine(0, 16, display.width()-1, 16, SSD1306_WHITE);  
          //Header
          display.setCursor(0, 0);
          display.print("Measure");
          //Countdown
          display.setTextSize(3);
          display.setCursor(30,20);
          display.print("Right");
        }
        display.display();

}

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