Millis() not function in header file

  • Placing serial print statements @9600 might not be the wisest thing to do when clocking data.

Did something similar a while back:


#include "IRremoteNEC.h"

//=============================================================================
//IR remote
//NEC - IR code
//By: LarryD, Huge thanks to Jack Christensen
//
//For the remote control, see:  http://goo.gl/nvDuhD
//
//"IRremoteNEC.cpp IRremoteNEC.h" 
// PERMISSION TO DISTRIBUTE
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
// and associated documentation files (the "Software"), to deal in the Software without restriction, 
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
// subject to the following conditions:
// LIMITATION OF LIABILITY
// The software is provided "as is", without warranty of any kind, express or implied, 
// including but not limited to the warranties of merchantability, fitness for a particular 
// purpose and noninfringement. In no event shall the authors or copyright holders be liable 
// for any claim, damages or other liability, whether in an action of contract, 
// tort or otherwise, arising from, out of or in connection with the software 
// or the use or other dealings in the software. 
//
//IRremoteNEC.cpp(.h) - A class to retrieve IR commands from 44/17 Button IR Remote
//Tested with Arduino IDE 1.06 on an UNO
//
// Rev 1.00   January 25, 2015 functional code
// Rev 1.01   February 1, 2015 created the library files IRremoteNEC.cpp and .h
//
//=============================================================================

//*****************************************************************************
void irISR(void);

//======== VARIABLES USED BY THE ISR -- Must be accessed atomically!
volatile byte irFlag;                 //a flag stating we have seen an edge
volatile unsigned long thisMicros;    //time the current edge happened

//======== LOCAL COPIES OF ISR VARIABLES ========
unsigned long thisMicrosLocal;
//
//*****************************************************************************

//              c l a s s   I R r e m o t e N E C
//*****************************************************************************
//Constructor
IRremoteNEC::IRremoteNEC(byte IRpin)
{
  IRpin_ = IRpin;

} // END of IRremoteNEC()

//********************************************************** 
//Initialization
void IRremoteNEC::beginIR()
{
  pinMode(IRpin_, INPUT_PULLUP);
  counter = 0;
  validStart = false;
  thisMicrosLocal = micros();

  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    thisMicros = thisMicrosLocal;
  }

  irFlag = 0;
  //We must convert the pin # to the interrupt # (i.e.  2-2=0 or 3-2=1)
  attachInterrupt (IRpin_ - 2, irISR, FALLING);  // attach IR interrupt handler using D2 or D3

} // END of beginIR()

//********************************************************** 
//Return the current state of the interrupt flag.
byte IRremoteNEC::getIRflag()
{
  return irFlag;

} // END of getIRflag()

//**********************************************************  
//Reset the state of the interrupt flag.
void IRremoteNEC::resetIRflag()
{
  irFlag = 0;

} // END of resetIRflag()

//**********************************************************  
//Handle falling edge detection, return IR code if a valid one exists.
//NOTE: IR remote "repeat" codes are ignored and not returned.
byte IRremoteNEC::checkCode()
{
  byte byteRecived = 0;   //returned variable to the CALLing code
  byte rxBit = 0;         //the value of the received bit

  //Calculate the time between the last two falling edges.
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    thisMicrosLocal = thisMicros;
  }
  unsigned long temp = thisMicrosLocal - lastMicros;

  //For the next iteration, save the edge time, which just happened.
  lastMicros = thisMicrosLocal;

  //Are we over the start bit upper limit of 13.8mS for the 44/17 button IR remote code?
  if (temp > 13800)
  {
    //There must have been quite some time since the last falling edge.
    //Save the current time (beginning time) as the starting edge for this message.
    startMillis = millis();
  }

  //One complete message is (measured 67.5mS) ~75mS long.
  //If we go over this, reset things i.e. get ready for the next message.
  //As a benefit this removes (ignores) any repeat codes that come in.
  else if(millis() - startMillis > 75)
  {
    //Too much time has elapsed since the first edge of the message. 
    //Start over.
    validStart = false;
  }

  //Are we inside the limit of the start bit: (measured 13480) 13200uS to 13800uS
  else if((validStart == false) && (temp > 13200))
  {
    //This is a valid start time
    counter = 0;
    validStart = true;

    //4 bytes are coming, initialize their storage.
    data[0] = 0;
    data[1] = 0;
    data[2] = 0;
    data[3] = 0;
  }

  //Are we into data bits: (measured 1130) 900 to 1300uS is a 0 bit,
  //(measured 2250), 2000 to 2500uS is a 1 bit.
  else if((validStart == true) && (temp > 900) && (temp < 2500))
  {
    //Is this bit a 1?
    if(temp > 2000)
    {
      rxBit = 1;
    }

    //Is this bit a 0?
    else if(temp < 1300)
    {
      rxBit = 0;
    }

    //Timing was not valid!
    else
    {
      //The bit width was not within the above range, start over.
      validStart = false;
      counter = 0;
    }

    //Put this bit in the correct position in the current byte.
    //example: let us say we are doing bit 19
    //         data[19/8 is byte 2] |= rxBit << (19%8 gives a shift of 3))
    //         data[2] = data[2] | rxBit << 3
    data[counter/8] |= (rxBit << (counter%8));

    //Have we received all the bits yet? (0-31 is 32 bits)
    if(counter >= 31) 
    {
      //This remote always sends: 0x00 as Address and  0xFF as ~Address
      //Example: 0x00  0xFF  0x04  0xFB would be a valid message
      //Was this a valid IR code?  i.e. Address = ~Address && Data = ~Data
      if((data[0] == (~data[1] & 0xFF)) && (data[2] == (~data[3] & 0xFF)))
      {
        //data[2] contains the valid IR button code
        byteRecived = data[2];
      }

      //We are now finished with this IR code, get ready for the next valid start.
      validStart = false;

    } //END of if(counter >= 31)

    //Get ready for the next bit.
    counter++;
  } //END of if(validStart == true && (temp > 900) && (temp < 2500))

  return byteRecived;  //If zero (0) there is no valid IR button code

} // END of checkCode()

//=============================================================================
//                      H E L P E R    F U N C T I O N S
//=============================================================================


//*****************************************************************************    
// Interrupt Service Routine (ISR)
void irISR()
{
  thisMicros = micros();     //record the time the edge happened
  irFlag = 1;                //Flag that we have seen a falling edge
} // END of irISR()
//*****************************************************************************