/* * Inductance & Frequency Meter * frequency counter library based on the theremin by Martin Nawrath */ #include /* * Pin defs are for the Arduino Pro Mini I used * FreqCounter library wants input on pin 5; * all other pin choices are arbitrary */ //library to run the 16-char by 2-line display #include LiquidCrystal lcd(A5, A4, A3, A2, A1, A0); //pins for (rs, enable, d4, d5, d6, d7) #define FreqInput 5 //button goes high to set zero point #define ZeroButton 9 //set high to measure (FreqEnable must be low) #define InductEnable 8 //set high to measure (InductEnable must be low) #define FreqEnable 7 //switch is low to measure F, high to measure L #define FLswitch 4 //oscillator effective capacitance, 350 pF //determined empirically by best-fit comparisons with known inductors #define TankCapacitance 0.00000000035 const float sqrt_C = sqrt(TankCapacitance); unsigned long frq; float fadj; float zero_calibration = 11; //initial guess for 10 uH series coil + strays void setup() { pinMode(ZeroButton, INPUT); pinMode(FLswitch, INPUT_PULLUP); pinMode(InductEnable, OUTPUT); pinMode(FreqEnable, OUTPUT); lcd.begin(16, 2); lcd.clear(); lcd.print("starting up"); delay(1000); //milliseconds } void loop() { if (digitalRead(FLswitch) == LOW) { digitalWrite(InductEnable, LOW); digitalWrite(FreqEnable, HIGH); measure_freq(); } else { digitalWrite(InductEnable, HIGH); digitalWrite(FreqEnable, LOW); if (digitalRead(ZeroButton) == HIGH) { calibrate(); } else { measure_induct(); } } delay(500); } void measure_freq() { //ZeroButton has no effect here //lcd.clear(); lcd.setCursor(0, 0); lcd.print("Frequency: "); FreqCounter::f_comp = 10; // calibration value, empirically determined FreqCounter::start(250); // Gate time in mSec while (FreqCounter::f_ready == 0) { frq = FreqCounter::f_freq; } lcd.setCursor(0, 1); lcd.print(4 * frq); //we measured for 1/4 second lcd.print(" Hz "); } void measure_induct() { float adjusted_inductance; float measured_inductance; float displayed_inductance; float denominator; FreqCounter::f_comp = 10; FreqCounter::start(250); // Gate time in mSec while (FreqCounter::f_ready == 0) { frq = FreqCounter::f_freq; } lcd.setCursor(0, 0); lcd.print(" "); lcd.setCursor(0, 0); // lcd.print("Inductance: "); lcd.print("f_raw = "); lcd.print(frq); lcd.setCursor(0, 1); if (frq == 0) { lcd.print("-------- "); } else { denominator = 2 * PI * 4 * frq * sqrt_C; //f-counter runs for 1/4 sec measured_inductance = 1000000 / (denominator * denominator); //in uH adjusted_inductance = measured_inductance - zero_calibration; if(abs(adjusted_inductance) < 1) { lcd.print("< 1 uH "); } else { /* * tweak displayed value with a fudge factor; * formulas are determined by best fit with known inductors */ if (adjusted_inductance < 1000) { // y = 0.0002x2 + 0.8314x + 0.0225 displayed_inductance = 0.0002*adjusted_inductance*adjusted_inductance + 0.8314*adjusted_inductance + 0.0225; } else if (adjusted_inductance < 10000) { // y = 0.0006x2 - 0.8191x + 1407.2 displayed_inductance = 0.0006*adjusted_inductance*adjusted_inductance - 0.8191*adjusted_inductance + 1407.2; } else { // y = 3.9459x - 6884.4 displayed_inductance = 3.9459*adjusted_inductance - 6884.4; } lcd.print(long(displayed_inductance)); //must cast to long; could exceed the range of integer type lcd.print(" uH "); } } } void calibrate() { float adjusted_inductance; float measured_inductance; float denominator; FreqCounter::f_comp = 10; FreqCounter::start(250); // Gate time in mSec while (FreqCounter::f_ready == 0) { frq = FreqCounter::f_freq; } lcd.setCursor(0, 0); lcd.print(" "); lcd.setCursor(0, 0); lcd.print("Calibrating..."); // lcd.print("C f = "); // lcd.print(frq); lcd.setCursor(0, 1); if (frq == 0) { lcd.print("-------- "); } else { denominator = 2 * PI * 4 * frq * sqrt_C; //f-counter runs for 1/4 second zero_calibration = 1000000 / (denominator * denominator); //in uH lcd.print(zero_calibration); lcd.print(" uH "); } }