Skip to main content
Tweeted twitter.com/#!/StackArduino/status/506629986380689408
New tags.
Link
Post Migrated Here from electronics.stackexchange.com (revisions)
Source Link

Arduino Hardware timer and interrupts issue

I recently started programming with Arduino and and currently I'm making a project to read RPM and Speed of my car using Arduino Uno. So far I got everything working but the speed value does not show properly. I have used one hardware counter and two interrupts in this project.

  1. Timer 1 on pin 5 - Count pulses from car's ECU to calculate speed.
  2. Int0 on pin 2 - Read ignition pulse to calculate RPM.
  3. int1 on pin 3 - 5v in from headlight switch to control the brightness of the display (MAX729 7 seg 8 digit).

I can get the proper reading from RPM and also the brightness control is working properly. Here is my codes below.

    #include <LedControl.h>

// inputs: DIN pin, CLK pin, LOAD pin. number of chips
LedControl display = LedControl(12, 10, 11, 1);

//SPEEDO-----------------------------------------------------------
const int hardwareCounterPin = 5;
const int samplePeriod = 1000; //in milliseconds
const float pulsesPerMile = 4000; // this is pulses per mile for Toyota. Other cars are different.
const float convertMph = pulsesPerMile/3600;
unsigned int count;
float mph;
int kph;
int roundedKph;
int previousKph;
int prevCount;
//----------------------------------------------------------------

//RPM-------------------------------------------------------------
//Configuration for the Tachometer variables
const int sensorPin = 2;
const int sensorInterrupt = 0;
const int timeoutValue = 5;
volatile unsigned long lastPulseTime;
volatile unsigned long interval = 0;
volatile int timeoutCounter;
int rpm;
int rpmlast = 3000;
int rpm_interval = 3000;
//---------------------------------------------------------------

//Brightness control---------------------------------------------
int brightnessIndicator = 13;  //Light pin 13 led to show that brightness control is in action.
int brightnessIn = 3;  //Sensor in from headlight positive wire to control the brightness.
//---------------------------------------------------------------

void setup(void) {
  //Serial.begin(9600);
  
  display.shutdown(0, false);  // turns on display
  display.setIntensity(0, 10); // 15 = brightest
  printTrueno(); //Print my car's name
  delay(3000);
  initToZero(); //Print all zeros before going to the loop
  
  TCCR1A = 0; //Configure hardware counter 
  TCNT1 = 0;  // Reset hardware counter to zero
  
  //Config for the Tach
  pinMode(sensorPin, INPUT);
  attachInterrupt(sensorInterrupt, &sensorIsr, RISING);
  lastPulseTime = 0;
  timeoutCounter = 0;
  
  //Config for brightness control
  pinMode(brightnessIndicator, OUTPUT);  //LED output
  pinMode(brightnessIn,INPUT);  //Sensor in
  attachInterrupt(1, changeBrightness, CHANGE);  //Attach the 2nd interrupt
  changeBrightness();  //Check for head lights on or not.
}
 
void loop() {
  //SPEEDO-----------------------------------------------------------
  // This uses the hardware pulse counter on the Arduino.
  // Currently it collects samples for one second.
  bitSet(TCCR1B, CS12); // start counting pulses
  bitSet(TCCR1B, CS11); // Clock on rising edge
  delay(samplePeriod); // Allow pulse counter to collect for samplePeriod
  TCCR1B = 0; // stop counting
  count = TCNT1; // Store the hardware counter in a variable
  TCNT1 = 0;     // Reset hardware counter to zero
  mph = (count/convertMph)*10; // Convert pulse count into mph. 10x allows retaining 10th of mph resolution.
  kph = ((unsigned int) mph)*1.6; // Convert to kph and cast to integer. 
 
  int x = kph / 10;
  int y = kph % 10;
  
  // Round to whole mile per hour
  if(y >= 5){
    roundedKph = x + 1;
  }
  else {
    roundedKph = x;
  }
  
  //If kph is less than 1 kph just show 0kph.
  //Readings of 0.9kph or lower are some what erratic and can
  //occasionally be triggered by electrical noise.
  //if(x == 0){
  if(x < 2){  // 1 was triggered by some noise signal.
    roundedKph = 0;
  }
  
  // Don't display kph readings that are more than 50 kph higher than the previous reading because it is probably a spurious reading.
  if(roundedKph < 181){
    if((roundedKph - previousKph) > 50) {
      Serial.println(previousKph);
      printNumber(previousKph, 0);
    }
    else {
      Serial.println(roundedKph);
      printNumber(roundedKph, 0);
    }
  }
  
  previousKph = roundedKph; // Set previousMph for use in next loop.
  //-----------------------------------------------------------------
  
  //RPM--------------------------------------------------------------
  if(rpm >= 0) {  //Remove the minus values   
    
    //Let's keep this RPMr value under control, between 0 and 9999
    rpm = constrain (rpm, 0, 9999);

    //If the engine is not running, print 0
    if ((micros() - lastPulseTime) < 5e6 ) {
      rpm = rpm;
    }
    else {
      rpm = 0;
    }
    
    if (rpm < 250)
      rpm = 0;
    //Serial.println(rpm);
    printNumber(rpm, 1);
  }
  //-----------------------------------------------------------------
}

//Each time the interrupt receives a rising tach signal, it'll run this subroutine
void sensorIsr() {
  unsigned long now = micros();
  interval = now - lastPulseTime;
  if (interval > 5000){
     rpm = 61000000UL/(interval * 2);
     lastPulseTime = now;
  }
}

void changeBrightness() {
  int val = digitalRead(brightnessIn);  //Read the sensor value
  
  if(val == 1){  //If the headlights are on, pin goes HIGH.
    digitalWrite(brightnessIndicator, HIGH);   //turn the LED on
    display.setIntensity(0, 6); //Reduce the brightness.
  }
  else {
    digitalWrite(brightnessIndicator, LOW);    //turn the LED off
    display.setIntensity(0, 14);  //increase the brightness.
  }
}

void printNumber(int v, int flag) {
    int ones;
    int tens;
    int hundreds;
    int thousands;
    
    if (flag==0){
      ones = v%10;
      v = v/10;
      tens = v%10;
      v= v/10;
      hundreds = v;

      //Now print the number digit by digit
      if (hundreds>0)
        display.setDigit(0,0,(byte)hundreds,false);
      else
        display.setChar(0,0,' ',false);
        
      display.setDigit(0,1,(byte)tens,false);       
      display.setDigit(0,2,(byte)ones,false);
    }
    else if (flag=1) {
      ones = v%10;
      v = v/10;
      tens = v%10;
      v = v/10;
      hundreds = v%10;
      v = v/10;
      thousands = v%10;

      //Now print the number digit by digit
      display.setDigit(0,4,(byte)thousands,false);
      display.setDigit(0,5,(byte)hundreds,false);
      display.setDigit(0,6,(byte)tens,false);
      display.setDigit(0,7,(byte)ones,false);
    }
}

I think the problem is between Timer1 and first interrupt. Can someone please help me to solve this?

Thank you very much.