Hello
I'm using a UNO to measure the period time between two rising edges. I'm using micros() to get a "timestamp" to calculate elapsed time. Then converting it to ms with 3 decimal points
But when I'm testing I get some strange results, when the frequency of the input signal gets lower the reading gets more inaccurate. Also the calculated time is faster then the frequency of the signal.
Test Results:
| Frequency | Calculatedtime(ms) |
|---|---|
| 200Hz | 4,992-4,996 |
| 100Hz | 9,984-9,988 |
| 50Hz | 19,968-19,972 |
| 25Hz | 39,940-39,944 |
| 10Hz | 99,860-99,866 |
The code:
#include <BigCrystal.h>
#include <BigFont.h>
#include <LiquidCrystal.h>
/************************************
Title:
Created: 2018-04-03
Author: Martin Augustsson
----------------------------
************************************/
/************************************
Pin mapping
************************************/
const byte interruptPin = 2;
const byte resetBtnPin = 11;
const byte ledPin = 12;
const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
/************************************
Global variables
************************************/
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
BigCrystal bigCrystal(&lcd);
unsigned long elapsedTime = 0;
volatile unsigned long timeMicros = 0;
volatile bool newPulse = false;
unsigned long time1 = 0;
unsigned long time2 = 0;
int ResetBtnState = 0;
int counter = 0; // Count how many pulses we have recived
bool hasPrintedResult = false; // Keep track if we printed the result (avoids multiple writes to LCD)
bool isReady = false;
bool printedReady = false;
float distanceCM = 2.52; // Distance traveled between pulses in centimeters
float speedKPH = 0; // Speed in kilometers per hour
float speedMPH = 0; // Speed in miles per hour
/************************************
Setup
Runs once at startup
************************************/
void setup() {
Serial.begin(9600);
pinMode(interruptPin, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(resetBtnPin, INPUT);
bigCrystal.begin(20, 4);
//attachInterrupt to right pin and function
attachInterrupt(digitalPinToInterrupt(interruptPin), ISR1, RISING);
isReady = true;
}
/************************************
Main loop
Runs until powered off
***********************************/
void loop() {
ResetBtnState = digitalRead(resetBtnPin);
// Show that box is ready, LED? Text?
if ( counter == 0 && isReady) {
digitalWrite(ledPin, HIGH);
if (!printedReady) {
lcd.print("Ready!");
printedReady = true;
}
} else {
digitalWrite(ledPin, LOW);
}
//Reset for a new reading
if (ResetBtnState == HIGH) {
resetValues();
lcd.clear();
}
// If there is a new pulse, store timestamp and update counter and pulse flag
if (newPulse) {
if (counter == 0) {
time1 = timeMicros;
} else if (counter == 1) {
time2 = timeMicros;
}
counter++;
newPulse = false;
hasPrintedResult = false;
}
// Wait until we got two pulses to calculate durnation
if ( (counter != 0) && (counter == 2) && !hasPrintedResult) {
elapsedTime = time2 - time1;
printTime(elapsedTime);
// calculateSpeed(); // Not used right now, period time most important
hasPrintedResult = true;
}
}
/************************************
Functions
***********************************/
// Interrupt Service Routine, get timestamp and signal that we got a new pulse
void ISR1() {
timeMicros = micros();
newPulse = true;
}
// Prints out the time in microseconds to the LCD
void printTime(unsigned long x) {
lcd.clear();
float ms = float(x) / 1000;
char charBuff[20];
dtostrf(ms, 5, 3, charBuff);
Serial.println(x);
Serial.println(charBuff);
int i = 0;
byte w = 0;
bool secondRow = false;
while (charBuff[i] != '\0') {
if ( 20 < (w + bigCrystal.widthBig(charBuff[i])) ) {
secondRow = true;
w = 0;
}
if (secondRow) {
bigCrystal.writeBig(charBuff[i], w, 2);
} else {
bigCrystal.writeBig(charBuff[i], w, 0);
}
w += bigCrystal.widthBig(charBuff[i]);
i++;
}
}
// Reset Values for a new reading
void resetValues() {
counter = 0;
printedReady = false;
hasPrintedResult = false;
isReady = true;
newPulse = false;
}