Project: acquiring speed of a motor with SS49E hall sensor on shaft. 2 magnets on shaft, LM393 comparator to convert to square wave and sent to a 5V 16Mhz Promini.
Problem. 50% square wave from a signal generator is read just fine by the Promini, but not the one from the comparator. Some very strange results too. Changing the 3.65Vref on the comparator can significantly change the displayed reading, but not the comparator output viewed on the scope.
I'm using a sketch based on Nick Gammon's most helpful timers/counters page. (Thanks so much Nick for all your information, you've been such a great help over the years.)
I've tried other sketches and hardware like schmidt trigger inverter, but no success.
The attached pic shows the scope on the pin5 arduino input (1k pullup) showing a 26hz signal, while the Promini reports 1022hz. A laser tach shows 780 rpm, or 13hz, x2 magnets is 26hz verifying the scope reading.
Fairly sure this is some kind of electronics issue, impedence or stray currents but it remains even with all different hardware and circuits.
Anyone have any ideas?
Thanks very much.
#include <SSD1306_text.h>
//for rpi, had to add 'const' in front of the 'static' progmem statement in sshfont.h
//also changed the oled address to 0x3c in ssd1306_text.h
#include <Wire.h>
#define OLED_RESET 4
SSD1306_text display(OLED_RESET);
volatile unsigned long timerCounts;
volatile boolean counterReady;
// internal to counting routine
unsigned long overflowCount; //max 4,294,967,295
unsigned int timerTicks; //max 65535
unsigned int timerPeriod; //
void startCounting (unsigned int ms)
{
counterReady = false; // time not up yet
timerPeriod = ms; // how many 1 ms counts to do
timerTicks = 0; // reset interrupt counter
overflowCount = 0; // no overflows yet
// reset Timer 1 and Timer 2
TCCR1A = 0;
TCCR1B = 0;
TCCR2A = 0;
TCCR2B = 0;
// Timer 1 - counts events on pin D5
TIMSK1 = bit (TOIE1); // interrupt on Timer 1 overflow
// Timer 2 - gives us our 1 ms counting interval
// 16 MHz clock (62.5 ns per tick) - prescaled by 128
// counter increments every 8 µs.
// So we count 125 of them, giving exactly 1000 µs (1 ms)
TCCR2A = bit (WGM21) ; // CTC mode
OCR2A = 124; // count up to 125 (zero relative!!!!)
// Timer 2 - interrupt on match (ie. every 1 ms)
TIMSK2 = bit (OCIE2A); // enable Timer2 Interrupt
TCNT1 = 0; // Both counters to zero
TCNT2 = 0;
// Reset prescalers
GTCCR = bit (PSRASY); // reset prescaler now
// start Timer 2
TCCR2B = bit (CS20) | bit (CS22) ; // prescaler of 128
// start Timer 1
// External clock source on T1 pin (D5). Clock on rising edge.
TCCR1B = bit (CS10) | bit (CS11) | bit (CS12);
} // end of startCounting
ISR (TIMER1_OVF_vect)
{
++overflowCount; // count number of Counter1 overflows
} // end of TIMER1_OVF_vect
//******************************************************************
// Timer2 Interrupt Service is invoked by hardware Timer 2 every 1 ms = 1000 Hz
// 16Mhz / 128 / 125 = 1000 Hz
ISR (TIMER2_COMPA_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = TCNT1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;
// see if we have reached timing period
if (++timerTicks < timerPeriod)
return; // not yet
// if just missed an overflow
if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 256)
overflowCopy++;
// end of gate time, measurement ready
TCCR1A = 0; // stop timer 1
TCCR1B = 0;
TCCR2A = 0; // stop timer 2
TCCR2B = 0;
TIMSK1 = 0; // disable Timer1 Interrupt
TIMSK2 = 0; // disable Timer2 Interrupt
// calculate total count
timerCounts = (overflowCopy << 16) + timer1CounterValue; // each overflow is 65536 more
counterReady = true; // set global flag for end count period
} // end of TIMER2_COMPA_vect
void setup ()
{
display.init();
display.clear(); // clear screen
display.setCursor(0,0);
display.setTextSize(1,1);
display.write("Hello world!");
//float floatVal = 23.792;
//display.print(floatVal,3);
//display.writeInt(int i);
Serial.begin(115200);
Serial.println("Frequency Counter");
} // end of setup
void loop ()
{
// stop Timer 0 interrupts from throwing the count out
byte oldTCCR0A = TCCR0A;
byte oldTCCR0B = TCCR0B;
TCCR0A = 0; // stop timer 0
TCCR0B = 0;
startCounting (500); // how many ms to count for
while (!counterReady)
{ } // loop until count over
// adjust counts by counting interval to give frequency in Hz
float frq = (timerCounts * 1000.0) / timerPeriod;
Serial.print ("Frequency: ");
Serial.print ((unsigned long) frq);
Serial.println (" Hz.");
display.clear();
display.setTextSize(2,1);
display.setCursor(5,0);
display.print((unsigned long) frq);
display.print(" Hz");
// restart timer 0
TCCR0A = oldTCCR0A;
TCCR0B = oldTCCR0B;
// let serial stuff finish
delay(200);
} // end of loop