For those wanting the code, here it is. I will likely make a few mistakes in this post and edit it if there is any mistakes or things are not clear. When you try this code, please post a response about your experience.
A2 Input from where timer connects to coil (note resistor connects to D13)
A7 Input to measure power 6-12 VDC (R1 ~10 Kohm A7 to ground, R2 20-30 Kohm to input power)
D7 Output to Solid State Switch (MOSFET) to connect where timer connects to coil
D13 Output Cap Charge Pin (connect to A2 with a resistor 300-500+ Kohms)
Code: Select all
/* The Ford Arduino Coil Tester ('FACT'), a prog to test Model T 'buzz coils'
Released under the GNU General Public Licence (https://www.gnu.org/licenses/gpl-3.0.html)
-----------------------------------------------------------------------------
Version 0.7 written by Luke P and Robert R, Christchurch, New Zealand, 17th December 2019.
(1) turn on Model T coil for [interval] milliseconds (typically 4-5 msec)
(2) measure the current max value
(3) measure time from 0 to max val (rise/ramp time)
(4) measure time from max val to min val (decay time)
(5) calc and present results via USB serial
Makes use of fast ADC read (set presecale to 16, giving read times of ~ 24 us)
Leading on from initial proof of concept to usable code
-----------------------------------------------------------------------------
Version 0.8 (Luke P), 28th Dec 2019
Collect data much as for 0.7, tidy code, sep into functions for:
(a) Multi-firing of coil as if running in vehicle at specific RPM
This in order to check consistency between firings and present results
(b) Single fire as before (and present results)
Utilise switch press longevity for multi-fire or single-fire tests
-----------------------------------------------------------------------------
Version 0.81 (Luke P), 29th Dec 2019
Bugfix - need to reset results array at start of multi-test otherwise it only outputted every 2nd trial
Alter calculation of rpmdelay to incorporate interval time at start
-----------------------------------------------------------------------------
Version 0.88 (Luke P), 29th Dec 2019
Calculate some stats on results (incl affect on degrees of rotation) and display
Bugfix where using rpmdelay to calc degree variation (should be rpm)
Intro discard variable to discard first few results from multi-fire test that are often higher
than following results. Prob due to coil 'warming up from rest' these could skew stat calcs
-----------------------------------------------------------------------------
Version 0.89 (Luke P), 30th Dec 2019
Ability to use CT or ACS712 for current reading
Some changes to stats calcs / display
-----------------------------------------------------------------------------
Version 0.89.1 (Luke P), 2 Jan 2020
Bugfix - multiple 60000/rpm by 2 for rpm delay, not divide!
-----------------------------------------------------------------------------
Version 0.9 (Luke P), 2 Jan 2020
Include LCD setup and output data to LCD
This uses a lot more memory so begin on some code optimisation to reduce
Set missfire variable
RPM to global and std at 900RPM
-----------------------------------------------------------------------------
Version 0.9.1 (Luke P), 3 Jan 2020
Bugfixes incl testnum after multi-fire, memory optimisation contd
-----------------------------------------------------------------------------
Version 0.92 (Luke P), 3 Jan 2020
Include capacitor test and leakage / tracking resistance check
* *
-----------------------------------------------------------------------------
Version 0.93 (Luke P), 13 Jan 2020
Shorted turns (ringing) test via 0,47uF, reactance test.
-----------------------------------------------------------------------------
Version 0.94 (Luke P), 15 Jan 2020
ESR test for capacitors (check able to deliver requisite current)
-----------------------------------------------------------------------------
Version 0.95 (Luke P), 20 Jan 2020
Remove short/ESR tests as probably unnecessary and complicated
Add input voltage reading - eventually use to track & ID correct firing time
per given input voltage
Version 0.96 (Matt), 27 May 2020
Added code for .96" OLED. This code also is set up for graphing current. Set numReadings = 150 (170 caused trouble).
Pin Connections
Arduino device
Ground OLED ground
+5VDC Vcc
A0 Input for data read from current sensor (5 VDC limit)
A1 Input for RPM_Set control potentiometer (0-5 VDC)
A2 Input from where timer connects to coil (note resistor connects to D13)
A3
A4 To OLED/LCD SDA (if no SDA pin)
A5 To OLED/LCD SCL (if not SCL pin)
A6
A7 Input to measure power 6-12 VDC (R1 ~10 Kohm A7 to ground, R2 20-30 Kohm to input power)
D1
D2
D3
D4
D5 Input Cap Test switch (other side connected to GND)
D6
D7 Output to Solid State Switch (MOSFET) to connect where timer connects to coil
D8 Input Run Test Pushbutton (other side connected to GND)
D9
D10
D11
D12
D13 Output Cap Charge Pin (connect to A2 with a resistor 300-500+ Kohms)
PLEASE NOTE: This code does multiple and single fire test with the oscilloscope.
The goal is to get a matching set of coils with a time to fire of; 3.5ms at 6V, and 2ms at 12V,
*/
#define ver 0.96
// Include any required libraries
// Uncomment following for LCD *******************************************************************************************
//#include <LiquidCrystal_I2C.h> // presently utilising the library from https://github.com/johnrickman/LiquidCrystal_I2C
// #define LCD=1; //define to correctly select correct code
//Initialise the LCD
//LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // set the address, columns and line
// END LCD
// Uncomment following for OLED ******************************************************************************************
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
#define SCREEN_WIDTH 128 //OLED Width
#define SCREEN_HEIGHT 32 //OLED Height
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// END OLED **************************************************************************************************************
#define cap_swPin 5 // input pin for cap/coil test switch. Low for cap
#define outPin 7 //output pin to ss relay for coil
#define swPin 8 //input pin for switch, normally high
#define cap_chg_pin 13 //for capacitor test
//setup for fast ADC read
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define numReadings 120 //max number of values in array, 150 = approx 3ms (112 limit of display)
#define numTests 50 //number of test cycles in multi test
#define interval 4000 // interval at which to turn on (microseconds)
//#define source_volts 1010 // source voltage for cap test (should check this at start)
#define source_volts 1023 // source voltage for cap test (should check this at start)
//setup for switch reading
#define short_in 60
#define meduim_in 600
#define long_in 2000
// voltmeter + resistor divider details
//#define R1 32400.0 // resistor to ground
//#define R2 120000.0 // resistor to input supply
#define R1 10000.0 // resistor to ground
#define R2 20000.0 // resistor to input supply
//setup for switch reading
unsigned long swTimer = 0;
unsigned long RPM_time_new = 0;
unsigned long RPM_time_old = 0;
boolean swPrevState = HIGH;
boolean swPresentState;
boolean cap_swPinState;
int ttf; // time to fire
// voltmeter + resistor divider details
float input_voltage = 0.0;
float interim_val = 0.0;
// Set global variables etc
unsigned long time_now = 0; // use long in case micros count gets big
unsigned long time_gone = 0;
//byte testnum = 0; // use byte for mem reduce, assume testnum < 255
float mVolts = 0.0;
float amps = 0.0;
int rpm = 900; // set desired 'rpm' for multitest - facsimile of single coil running at this speed
int A0_max = 512; // set to zero current
//set variables for collect_data function array
unsigned int analogVals[numReadings][2]; // array name & columns
unsigned int x = 0; // initialise array input
//set variables for multi_test function array
unsigned int resultVals[numTests][2]; // array name
unsigned int y = 0; // initialise array input
/*
//create the omega symbol to print to LCD
// ohm sign
byte omega[8] =
{
B00000,
B01110,
B10001,
B10001,
B10001,
B01010,
B11011,
B00000
}; // creating the omega (ohms) symbol, thanks to https://www.hackmeister.dk/2010/08/custom-lcd-characters-with-arduino/
*/
//begin setup for program proper
void setup()
{
pinMode(swPin, INPUT_PULLUP); // set the switch pin as input and apply resistor to +5
pinMode(outPin, OUTPUT);// define output pin
pinMode(cap_chg_pin, OUTPUT);// define output pin
pinMode (cap_swPin, INPUT_PULLUP);
sbi(ADCSRA, ADPS2); //more stuff for fast ADC read
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);
Serial.begin(115200); // open the serial port
//Serial.println (F("Setup 15")); //For testing ***************************************************************************************************
// let's get the input voltage to display
int a7val = analogRead(A7);
interim_val = (a7val * 5.0) / 1024.0;
input_voltage = interim_val / (R1 / (R1 + R2));
//read potentiometer and set rpm
rpm = analogRead(A1) / 50 * 100 + 500; // perform a read to clear register (comment out if no Potentiometer) units 100 rpm
// begin display detail
/* // The following for OLED comment if not used
lcd.init(); // setup the LCD for printing
lcd.backlight(); // turn on LCD backlight
lcd.print (F("FACT v")); // initial text on lcd display at startup
lcd.print (ver); // prints version number from define
lcd.print (F(" LP_20")); // build number
lcd.setCursor (0, 1);
lcd.print (F("Test @"));
lcd.print (input_volts, 1); // print voltage to 1 decimal place
lcd.print (F(" volts"));
lcd.blink();
lcd.createChar(0, omega);
*/
// The following for OLED comment if not used
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(WHITE, BLACK); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.println(F("Ford Arduino Coil Tst"));
display.setTextSize(2); // Draw 2X-scale text
//display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
display.print(F("FACT v")); display.println (ver);
display.setTextSize(1); // Normal 1:1 pixel scale
display.print(F("Vin= ")); display.print (input_voltage); display.println(F(" volts")); // display input voltage
//display.println(F(".96 OLED OSCILLOSCOPE"));
display.display();
}
//--- Function to fire coil once and collect data ---//
void single_fire_data()
{
//int A0_max = 512; // set to zero current
A0_max = 512; // set to zero current
int A0_new = 0;
mVolts = 0.0;
ttf = 0;
analogRead(A0); // perform a read to clear register
digitalWrite(outPin, HIGH); //set outPin high to power coil for time interval
time_now = micros();
for (byte i = 0; i < numReadings; i++) // test only for the number in the array
{
analogVals[i][0] = analogRead(A0); // read pin 0 volts (which is actually current from CT) and input value to array col 1
analogVals[i][1] = (micros() - time_now); // time since start of loop (thus sample time), input to array col 2
if (input_voltage > 9) // for 12 volts (for 9-12 volts)
{
analogVals[i][0] = (analogVals[i][0] + analogRead(A0)) / 2; //take a second reading and average the two (this helps fit on OLED screen)
}
else // for 6 volts (for less than 9 volts)
{
analogVals[i][0] = (analogVals[i][0] + analogRead(A0)); //take a third reading and average the three (this helps fit on OLED screen)
analogVals[i][0] = (analogVals[i][0] + analogRead(A0)) / 3;
}
A0_new = analogVals[i][0];
if (A0_new > A0_max && (A0_new > 580)) //detect current increasing and write to 'maxval'
{
A0_max = A0_new;
ttf = analogVals[i][1];
}
}
digitalWrite(outPin, LOW); // reset outPin to low and turn off power to coil
/*
// uncomment two lines for ACS712
mVolts = (A0_max / 1024.0) * 5000.0; // raw analog read val to millvolts
//amps = ((mVolts - 2500.0)/185.0); // millivolts to amps (utilise scale factor for ACS sensor range 5A chip
amps = ((mVolts - 2500.0) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
//amps = ((mVolts - 2500.0)/66.0); // millivolts to amps (utilise scale factor for ACS sensor range 30A chip
*/
}
void single_test()
{
single_fire_data();
// uncomment two lines for ACS712
mVolts = (A0_max / 1024.0) * 5000.0; // raw analog read val to millvolts
//amps = ((mVolts - 2500.0)/185.0); // millivolts to amps (utilise scale factor for ACS sensor range 5A chip
amps = ((mVolts - 2500.0) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
//amps = ((mVolts - 2500.0)/66.0); // millivolts to amps (utilise scale factor for ACS sensor range 30A chip
// write results to OLED
display.clearDisplay();
for (x = 1; x < numReadings; x++) {
// digital value of max current in =660; 5= digital values of current range/#lines = 150/32 = 4.68
display.drawLine(x + 10 , ((660 - analogVals[x - 1][0])) / 4.68, x + 10 , (660 - (analogVals[x][0])) / 4.68, WHITE);
}
// draw the axis, lables and tick marks
for (int y = 0; y < 5; y++) {
display.drawFastHLine(7, y * (32) / 7 + 9, 3, WHITE);
}
for (int x = 0; x < 6; x++) {
display.drawFastVLine(x * 23 + 10, 29, 3, WHITE);
}
display.setTextColor(WHITE, BLACK);
display.setTextSize(1);
display.setCursor(0, 24);
display.println("0");
display.setCursor(0, 8);
display.println("5");
//Yellow text at top
//display.fillRect(0, 0, 127 , 14, WHITE);
display.setTextColor(WHITE, BLACK);
display.drawFastHLine(10, 31, 128 - 10, WHITE);
display.drawFastVLine(10, 8, 32, WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("TTF=");
display.print(float(ttf) / 1000.00);
display.print("ms ");
display.print(F("Imax="));
display.print(amps);
display.println(F("A"));
display.display();
Serial.println (F(" ***"));
Serial.print (F("Total cycle time (to fire) = "));
Serial.print (float(ttf) / 1000.00); // convert to ms
Serial.println (F("msec"));
Serial.print (F("Maximum current = "));
Serial.print (amps);
Serial.println (F("A"));
Serial.println();
/* uncomment for LCD
// write results to LCD
lcd.clear();
lcd.setCursor (0, 0); //set cursor first col, first row
lcd.print (F("Single test #"));
lcd.print (test);
lcd.setCursor (0, 1); //set cursor first col, second row
lcd.print (F("TTF="));
lcd.print (float(ttf) / 1000.00); // convert to ms
lcd.print (F("ms"));
// DEBUG Serial.println (maxv);
// DEBUG Serial.println (mVolts);
Serial.print (F("Maximum current = "));
Serial.print (amps);
Serial.println (F("A"));
Serial.println();
lcd.print(F(" "));
lcd.print (amps);
lcd.print(F("A"));
*/
}
//--- Function to do a multi-fire test on a coil as if running in vehicle ---//
void multi_test()
{
// do some calcs on rpm as needed for delay (four-stroke, so single cyl ign fires every second cycle therefore div 2)
byte rpmdelay = ((60000 / rpm) * 2) - (interval / 1000); // attempts to roughly account for time in data_collect process ('interval') - byte means not much slower than 500RPM
float ttf_sum = 0;
float ttf_std_dev = 0;
float ttf_msec = 0;
float ttf_mean = 0;
float results_var = 0;
float ttf_max = 0;
float ttf_min = 10;
float ttf_max_current = 0;
byte discard = 2; // first few results from multi-test show higher ttf than normal, discard to give more accurate result
int miss = 0;
for (byte i = 0; i < numTests; i++) // Load data into array
{
single_fire_data();
resultVals[i][0] = ttf; //1st col of result array gets ttf
resultVals[i][1] = A0_max; // 2nd col of result array gets max voltage (to determine current)
delay(rpmdelay); // sets 'rpm' delay between each test firing,
}
for (byte i = discard; i < numTests; i++) // get results from each test and print to serial
{
ttf_msec = ((resultVals[i][0]) / 1000.00); // convert to ms
ttf_sum += ttf_msec;
ttf_mean = (ttf_sum / (numTests - discard)); //get mean of array results for ttf ***using testnum cost of discard
if (ttf_msec > ttf_max)
{
ttf_max = ttf_msec;
}
if (ttf_msec < ttf_min)
{
ttf_min = ttf_msec;
}
// uncomment two lines for ACS712
mVolts = ((resultVals[i][1]) / 1024.0) * 5000.0; // raw analog read val to millvolts
//amps = ((mVolts - 2500.0)/185.0); // millivolts to amps (utilise scale factor for ACS sensor range 5A chip
amps = ((mVolts - 2500.0) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
//amps = ((mVolts - 2500.0)/66.0); // millivolts to amps (utilise scale factor for ACS sensor range 30A chip
if (amps < 0.2) // if we have a low current it suggests firing issues
{
miss = miss + 1; //count number of missfires
}
if ( amps > ttf_max_current)
{
ttf_max_current = amps;
}
/*Serial.print (F("Maximum current = "));
Serial.print (amps);
Serial.println (F("A"));
Serial.print (F("*** Test number "));
Serial.print (i);
Serial.println (F(" ***"));
Serial.print (F("Total cycle time (to fire) = "));
Serial.print (ttf_msec);
Serial.println (F("msec"));*/
}
for (byte i = discard; i < numTests; i++) // get results from each test and print to serial
{
results_var += pow(ttf_mean - ttf_msec, 2); // get variance
ttf_std_dev = sqrt(results_var / (numTests - discard)); // get std deviation ***using testnum cost of discard instead numTests
}
//OLED Print
display.clearDisplay();
display.setCursor(0, 0);
display.print(F("M="));
display.print(ttf_mean);
display.print(F("ms ("));
display.print(ttf_min);
display.print(F("-"));
display.print(ttf_max);
display.println(F(")"));
display.setCursor(0, 8);
display.print(F("SD="));
display.print(ttf_std_dev);
display.print(F("; Dwell ="));
display.print((ttf_max - ttf_min) / (float(60000 / rpm) / 360));
display.println((char)167); // let's print the degree symbol!
display.setCursor(0, 16);
display.print(F("Max Current ="));
display.print(ttf_max_current);
display.println(F("amps"));
display.setCursor(0, 24);
display.print(rpm);
display.print(F(" RPM "));
display.print(miss);
display.println(F(" MISFIRES "));
display.display();// now that the display buffer is built, display it
/*
Serial.println ();
Serial.print (F("Mean time to fire = "));
Serial.print (ttf_mean);
Serial.println (F("mSec"));
Serial.print (F("Standard deviation = "));
Serial.print (ttf_std_dev);
Serial.println (F("mSec"));
Serial.print (F("Results Max = "));
Serial.print (ttf_max);
Serial.println (F("mSec"));
Serial.print (F("Results Min = "));
Serial.print (ttf_min);
Serial.print (F("mSec"));
Serial.print (rpm);
Serial.print (F(" RPM "));
if (miss > 0)
{
Serial.print (miss);
Serial.println (F(" MISFIRES! "));
}
else
{
Serial.println();
}
// DEBUG Serial.println (maxv);
// DEBUG Serial.println (mVolts);
Serial.print (F("Range = "));
Serial.print (ttf_max - ttf_min);
Serial.println (F("mSec"));
Serial.print (F("Degrees of variation at "));
Serial.print (rpm);
Serial.print (F(" RPM = "));
Serial.print ((ttf_max - ttf_min) / (float(60000 / rpm) / 360));
Serial.println (F(" degree(s)"));
*/
/* uncomment to use LCD
// LCD print
lcd.clear();
lcd.setCursor (0, 0); //set cursor first col, first row
lcd.print (F("M="));
lcd.print (ttf_mean);
lcd.print(F("ms"));
lcd.setCursor (9, 0); //set cursor 9th col, first row
lcd.print (F("SD="));
lcd.print (ttf_std_dev);
lcd.setCursor (0, 1); //set cursor first col, second row
if (miss>0)
{
lcd.print(F("***MISFIRE***"));
}
else
{
lcd.print(ttf_min);
lcd.print(F("-"));
lcd.print(ttf_max);
lcd.print(F(" "));
lcd.print ((ttf_max - ttf_min) / (float(60000 / rpm) / 360));
lcd.print ((char)223); // let's print the degree symbol!
Serial.print (F("Maximum current = "));
Serial.print (amps);
Serial.println (F("A"));
Serial.println();
lcd.print(F(" "));
lcd.print (amps);
lcd.print(F("A"));
}
*/
/* if (miss>0)
{
lcd.print(F("***MISFIRE***"));
}
else
{
lcd.print(ttf_min);
lcd.print(F("-"));
lcd.print(ttf_max);
lcd.print(F(" "));
lcd.print ((ttf_max - ttf_min)/(float(60000 / rpm)/360));
lcd.print ((char)223); // let's print the degree symbol!
lcd.print(F(" "));
lcd.print (amps);
lcd.print(F("A"));
}
*/
}
//the following function works like a time laps o-scope
void live_o_scope()
{
int RPM_live = 0;
float ttf_sum = 0;
float ttf_std_dev = 0;
float ttf_msec = 0;
float ttf_mean = 0;
float results_var = 0;
float ttf_max = 0;
float ttf_min = 10;
float ttf_max_current = 0;
float I_sum = 0;
float I_mean = 0;
byte discard = 2; // first few results from multi-test show higher ttf than normal, discard to give more accurate result
int miss = 0;
mVolts = 0.0;
display.clearDisplay();
display.setTextColor(WHITE, BLACK);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("Multifire O-Scope"));
// draw the axis, lables and tick marks
for (int y = 0; y < 5; y++) {
display.drawFastHLine(7, y * (32) / 7 + 9, 3, WHITE);
}
for (int x = 0; x < 6; x++) {
display.drawFastVLine(x * 23 + 10, 29, 3, WHITE);
}
display.setTextColor(WHITE, BLACK);
display.setTextSize(1);
display.setCursor(0, 24);
display.println("0");
display.setCursor(0, 8);
display.println("5");
//Yellow text at top
//display.fillRect(0, 0, 127 , 14, WHITE);
display.setTextColor(WHITE, BLACK);
display.drawFastHLine(10, 31, 128 - 10, WHITE);
display.drawFastVLine(10, 8, 32, WHITE);
RPM_time_old = micros();
for (int i = 0; i < 50 ; i++)
{
RPM_time_old = RPM_time_new ;
RPM_time_new = micros();
RPM_live = 120000000 / (RPM_time_new - RPM_time_old);
single_fire_data();
ttf_msec = (ttf / 1000.00); // convert to ms
ttf_sum += ttf_msec;
// uncomment two lines for ACS712
mVolts = (A0_max / 1024.0) * 5000.0; // raw analog read val to millvolts
//amps = ((mVolts - 2500.0) / 66.0); // millivolts to amps (utilise scale factor for ACS sensor range
//amps = ((mVolts - 2500.0)/185.0); // millivolts to amps (utilise scale factor for ACS sensor range 5A chip
amps = ((mVolts - 2500.0) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
//amps = ((mVolts - 2500.0)/66.0); // millivolts to amps (utilise scale factor for ACS sensor range 30A chip
// uncomment for CT
// amps = (maxv * .0222); // millivolts to amps (utilise scale factor for CT
I_sum += amps;
I_mean = (I_sum / i);
ttf_mean = (ttf_sum / i);
/* uncomment for serial
// write results to serial port
for (x = 1; x <= 127; x++) {
Serial.println (analogVals[x - 1][0]);
}
Serial.print (F("*** live O scope "));
Serial.println();*/
// write results to OLED
display.setCursor(0, 0);
display.print(F("t=")); display.print(ttf_mean); display.print(F("ms"));
display.print(F(" I=")); display.print(I_mean); display.print(F("A "));
display.println(RPM_live); display.setCursor(108, 7); display.print(F("rpm"));
for (x = 1; x <= 112; x++)
{
// digital value of max current in =660; 5= digital values of current range/#lines = 150/32 = 4.68
display.drawLine(x + 10 , ((660 - analogVals[x - 1][0])) / 4.68, x + 10 , (660 - (analogVals[x][0])) / 4.68, WHITE);
}
display.display();
}
/*
display.setTextSize(1);
display.setCursor(0, 0);
display.print("sp test TTF=");
display.print(float(ttf) / 1000.00);
display.print("ms ");
display.print(F("Imax="));
display.print(amps);
display.println(F("A"));
*/
}
void cap_test()
//--- Function to check capacitor value and resistance ---//
{
unsigned long new_time = 0;
mVolts = 0;
int cap_time = 0;
int r_volts = 0;
//long r_val = 487000; // charge resistor value in ohms
long r_val = 370000; // charge resistor value in ohms (should be in the few 100kohm range)
unsigned long sample_time;
sample_time = r_val * .00000047 * 1000000 / 30; // sample_time = r_val * 47 uF * 1000(to change to microsec) / 30 (location on graph to cross 63%)
float cap_val = 0.0;
long leak = 0;
digitalWrite(cap_chg_pin, LOW);
//OLED Display comment out
display.clearDisplay();
display.setTextColor(WHITE, BLACK);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("Capacitor Test"));
display.println(F("in progress..."));
display.display();
// LCD Print
/*
lcd.clear();
lcd.setCursor (0, 0); //set cursor first col, first row
lcd.print (F("Capacitor test"));
lcd.setCursor (0, 1); //set cursor first col, second row
lcd.print (F("in progress..."));
*/
// OLED Print *************************Add*****************
delay (90); //ensure the cap is discharged via charge pin low
digitalWrite(cap_chg_pin, HIGH); // use digi pin 13 to charge the cap via a resistor
time_now = millis();
for (int i = 0; i < 500; i++)
{
new_time = micros();
time_gone = millis() - time_now;
mVolts = analogRead (A2); //use analog pin A2 to read volts across unknown cap
//Serial.print (time_gone);
//Serial.print (" - ");
//Serial.println (mVolts);
if (mVolts <= (source_volts * 0.63212055882))
{
cap_time = time_gone; // time at which capacitor charge has reached 63.2% (one time constant)source_volts
}
if (i < numReadings)
{
analogVals[i][0] = mVolts;
analogVals[i][1] = 1023 * (1 - exp(-i / 30.0));
Serial.print (time_gone);
Serial.print (" - ");
Serial.println (mVolts);
}
while (micros() - new_time < sample_time); //delay time
}
display.clearDisplay();
//display.setCursor(0, 8);
//display.println("5");
// draw the axis, lables and tick marks
//draw 63% line
for (int y = 0; y < 30; y++) {
//display.drawFastHLine(7, y * (32) / 7 + 9, 3, WHITE);
display.drawFastHLine(10 + y * 4, 16, 1, WHITE);
display.drawFastHLine(10 + y * 6, 8, 2, WHITE);
display.drawLine(y * 5 + 10 , ((1360 - analogVals[y * 5 - 1][1])) / 43, y * 5 + 10 , (1360 - (analogVals[y * 5][1])) / 43, WHITE);
}
for (int x = 0; x < 12; x++) { //draw the upper and lower limits
display.drawFastVLine(30 + 10, 8 + 2 * x, 1, WHITE); //30 T constant + 10 offset
}
display.setTextColor(WHITE, BLACK);
display.drawFastHLine(10, 31, 128 - 10, WHITE);
display.drawFastVLine(10, 8, 32, WHITE);
display.setTextColor(WHITE, BLACK);
display.setTextSize(1);
display.setCursor(0, 0); display.println(F("Capacitor Test"));
display.setCursor(0, 12); display.println("63%");
//display.setCursor(20, 24); display.println(F(".47uF"));
display.display();
delay (1000);
for (int i = 1; i < numReadings; i++) {
// digital values of current range 1024 /#lines 24= 43; digital value input range 1024 + 43 * display range 24 * offset 8 = 1360
display.drawLine(i + 10 , ((1360 - analogVals[i - 1][0])) / 43, i + 10 , (1360 - (analogVals[i][0])) / 43, WHITE);
//display.drawLine(i + 10 , ((1360 - analogVals[i - 1][1])) / 43, i + 10 , (1360 - (analogVals[i][1])) / 43, WHITE);
display.display();
}
cap_val = ((float)cap_time / r_val) * 1000.0;
leak = mVolts * r_val / (source_volts - mVolts); // calculate the resistance of the unknown resistance (leakage) in voltage divider cct
if (leak < 0)
{
leak = 20000000; // if we get variable source volts then could go negative - may need to say 're-test!'?
}
display.setTextColor(BLACK, WHITE);
display.setCursor(90, 0);
if (leak > 10000000 && cap_val > 0.4 && cap_val < 0.6)
{
display.println(F(" PASS "));
}
else
{
display.println(F(" FAIL "));
}
if (analogVals[1][0] > 10) {
display.fillRect(79, 16, 128 , 32, BLACK);
display.setTextColor(WHITE, BLACK); display.setCursor(0, 0);
display.setCursor(80, 16);
display.print(cap_val); display.println(F(" uF"));
display.setCursor(80, 24);
display.print(leak / 1000000); display.println(F(" Mohm"));
}
else {
display.setCursor(20, 12);
display.println("Capacitor Shorted");
display.setCursor(20, 20);
display.println("Please open points");
}
digitalWrite(cap_chg_pin, LOW);
display.display();
delay (6000);
//OLED Display comment out
//display.clearDisplay();
display.fillRect(0, 8, 128 , 28, BLACK);
display.setTextColor(WHITE, BLACK); display.setCursor(0, 0);
display.println(F("Capacitor Test"));
display.setCursor(0, 8);
//display.print(F("C = "));
display.print(cap_val); display.println(F("uF Ideal .4-.6 uF"));
//LCD Printing
//lcd.clear();
Serial.print (cap_val);
if (cap_val > 0.4 && cap_val < 0.6)
{
//OLED Display comment out
display.setCursor(0, 24);
display.println(F(" PASS uF; "));
/* // LCD Print Uncoment to use LCD
Serial.print (F("uF"));
Serial.println (F(" **OK** :)"));
lcd.setCursor (0, 0);
lcd.print (F("C="));
lcd.print (cap_val);
lcd.print (F("uF *OK*"));
*/
}
else
{
//OLED Display comment out
display.setCursor(0, 24);
display.setTextColor(BLACK, WHITE); display.print(F(" FAIL ")); display.setTextColor(WHITE, BLACK); display.println(F("uF; "));
// LCD Print
/*
lcd.setCursor (0, 0);
lcd.print (F("C="));
lcd.print (cap_val);
lcd.print (F("uF *BAD*"));
*/
}
display.setCursor(0, 16); display.print(leak / 1000); display.println(F(" Kohm Ideal > 10M"));
Serial.print (leak);
display.setCursor(60, 24);
if (leak > 10000000) //test if > 10 Mohms
{
display.println(F("PASS ohm"));
Serial.println (F(" **OK** :)"));
/* // LCD Print
lcd.setCursor (0, 1);
lcd.print (F("R="));
lcd.print ((leak) / 1000000);
lcd.print ("M");
lcd.write (0);
lcd.print (F(" *OK*"));
*/
}
else
{
display.setTextColor(BLACK, WHITE); display.print(F(" FAIL ")); display.setTextColor(WHITE, BLACK); display.println(F("ohm"));
Serial.print (F(" ohms"));
Serial.println (F(" **BAD** :-("));
/* //LCD Print
lcd.setCursor (0, 1);
lcd.print (F("R="));
lcd.print ((leak) / 1000000);
lcd.print ("M");
lcd.write (0);
lcd.print (F(" *BAD*"));
*/
}
display.setTextColor(BLACK, WHITE);
display.setCursor(90, 0);
/*if (leak > 10000000 && cap_val > 0.4 && cap_val < 0.6)
{
display.println(F(" PASS "));
}
else
{
display.println(F(" FAIL "));
} */
display.display();
digitalWrite(cap_chg_pin, LOW);
}
//--- Main loop, detect short press of switch to call single fire, long press to call multi-fire ---//
void loop()
{
//read potentiometer and set rpm
rpm = analogRead(A1) / 50 * 100 + 500; // perform a read to clear register (comment out if no Potentiometer) units 100 rpm
//display.setCursor(80, 24); display.print(rpm); display.println(F("rpm ")); display.display();// now that the display buffer is built, display it
cap_swPinState = digitalRead(cap_swPin);
if (cap_swPinState == HIGH)
{
swPresentState = digitalRead(swPin); // what's the switch doing
if (swPresentState != swPrevState) // if not same as prev then...
{
delay(20); //debounce delay
swPresentState = digitalRead(swPin); // check again after debounce delay to be sure
if (swPresentState == LOW) // if switch is still on then it's real
{
swTimer = millis(); // set timer from on
}
if (swPresentState == HIGH) // sw not on now
{
unsigned long currentMillis = millis();
if ((currentMillis - swTimer >= short_in) && !(currentMillis - swTimer >= meduim_in)) // SHORT PB PRESS
{
Serial.println (F("- Single shot test -"));
//lcd.clear();
//lcd.print(F("Single shot test")); // use F() macro to reduce memory use
//testnum = (testnum + 1);
single_test();
}
if ((currentMillis - swTimer >= meduim_in) && !(currentMillis - swTimer >= long_in)) // MEDUIM PB PRESS
{
// the meduim long press was detected
Serial.println ();
Serial.println (F("- Multi-fire test -"));
Serial.println ();
//LCD Print
/*
lcd.clear();
lcd.print(rpm);
lcd.print(F("RPM multifire"));
lcd.setCursor (0, 1);
lcd.print(F("test in progress"));
*/
//OLED Print
display.clearDisplay();
display.setTextColor(WHITE, BLACK);
display.setTextSize(1);
display.setCursor(0, 0);
display.print(rpm);
display.println(F("RPM multifire"));
display.setCursor(0, 8);
display.println(F("test in progress"));
display.display();// now that the display buffer is built, display it
multi_test();
}
if ((currentMillis - swTimer >= long_in)) // LONG PB PRESS
{
// the long press was detected
Serial.println (F("- Multi-fire test O-scope"));
Serial.println ();
//read potentiometer and set rpm
rpm = analogRead(A1) / 100 * 200 + 500; // perform a read to clear register (comment out if no Potentiometer)
//OLED Print
live_o_scope();
}
}
swPrevState = swPresentState; // has state changed?
}
}
if (cap_swPinState == LOW)
{
digitalWrite(cap_chg_pin, LOW);
swPresentState = digitalRead(swPin); // what's the switch doing
if (swPresentState != swPrevState) // if not same as prev then...
{
delay(20); //debounce delay
swPresentState = digitalRead(swPin); // check again after debounce delay to be sure
if (swPresentState == LOW) // if switch is still on then it's real
{
swTimer = millis(); // set timer from on
}
if (swPresentState == HIGH) // sw not on now
{
unsigned long currentMillis = millis();
//if ((currentMillis - swTimer >= 60) && !(currentMillis - swTimer >= 600)) // sw short press
if ((currentMillis - swTimer >= short_in) && !(currentMillis - swTimer >= meduim_in)) // sw short press
{
Serial.println (F("Cap test"));
cap_test();
}
}
swPrevState = swPresentState; // has state changed?
}
}
}