A new DIY electronic coil tester.

Discuss all things Model T related.
Forum rules
If you need help logging in, or have question about how something works, use the Support forum located here Support Forum
Complete set of Forum Rules Forum Rules

Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Sun May 31, 2020 6:21 pm

Steve,

Good to see another tester being constructed, thanks.

I'm interested that the SSR seems to be performing ok. I looked at using one of those but decided (from the data sheet) that the rise time was too slow. I did suspect it would be better than advertised, but never pursued it, so it's good you've done that and we now know it will work.

Having said that I wonder if the noise you're experiencing could somehow be related to the SSR? Did you try a motor controller or FET before going to the SSR?

Also, it's worth noting that twisting pairs of wires together assists with combating RFI/EMR effects. I see Matt did that with one of his cables, it may be something you could also try.

Just as a general comment; I've re-ordered the gear I had on order from January, which never arrived. Hopefully this time it'll get through and I'll be able to complete the next phase of my own tester. In the meantime it's been good to see the results posted by others, and very pleasing to know that the project retains some life in it!

On this, @barrym, as Matt has said it'd be good to see/hear more about your machine?


barrym
Posts: 3
Joined: Wed May 27, 2020 6:59 pm
First Name: Barry
Last Name: Moyer
Location: Langdon

Re: A new DIY electronic coil tester.

Post by barrym » Sun May 31, 2020 11:06 pm

Luke & Matt et al,

I am taking a different approach. I am using the Arduino Nano to capture the samples and then send the captured data to a PC application that will chart the values. I am planning on releasing the code on GitHub. The app appears to be working, although currently is measuring 0A current.
FACTapp.png
I am very comfortable with software, but not as much with electronics. My progress is a little slow since I am trying to reverse engineer the circuit diagrams and modify to match what I have available to me. I am not entirely sure how to connect to the coil, so I am doing a lot of reading the posts and searching on the internet.

I am simplifying the electronic side by using a 5A ACS712 module to detect current draw and a MOSFET to turn the coil on/off. I believe I have a circuit that I can use for the MOSFET.

I ran across an article that discussed the measurement of current. Since the ACS712 uses hall effect, it could be affected by the Model T coil. I am planning on shielding or social distancing the electronics from the coil to minimize the EMI.

I can guarantee that my setup will not be near as fancy as what I have seen! I have a wood base and back with elastic bands pulling the coil to spring loaded bolts to connect to the electronics.

My goal is to have a basic tester that I can use to adjust my coils. I had another member adjust 4 that I am using, but I have 4 coils that need the capacitors replaced and then adjusted. I saw a dramatic improvement with properly adjusted coils. Our club has 2 different types of coil testers (Stroboscope and ECCT) which are excellent devices. I am eternally grateful for the research that Mike Kossor has put into the ECCT tester, the articles he has published and his posts on the FACT.

--barrym


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Mon Jun 01, 2020 1:06 am

Thanks for the update on your tester Barry.

It's a fairly long thread but somewhere back amongst it you'll see I did a little python-based code snippet to plot the results as output by the Arduino. I expect you're doing something more sophisticated, but it may be of some interest.

IMV a 5A ACS712 may be a little light. I'd anticipate (typical) peak currents could reach higher than 5A, and you may find it could saturate somewhat, causing the resultant data to flat-top. That shouldn't mean no output at all mind you, it could be that the sensor you have is faulty, or maybe it's not in the right place in the cct?

I think I put out a couple of hand-drawn sketches of how the hardware bolted together, and Matt did some more professional graphics. If there's anything that's not clear you might let us know and I expect one of us should be able to address that. As long as the ACS712 is in series with the low-voltage switched feed to the coil I'd expect output from it - also I wouldn't expect much interaction from external mag influences.

Presently I'm using a motor-controller to switch the coils, but my original design used a FET, and that should be fine for what you intend (as long as it's capable of carrying the current). My reason for using the motor-controller was based around simplicity for anyone replicating it (it meant an almost fully 'modularised' approach was possible), as well as the excellent switching characteristics.


barrym
Posts: 3
Joined: Wed May 27, 2020 6:59 pm
First Name: Barry
Last Name: Moyer
Location: Langdon

Re: A new DIY electronic coil tester.

Post by barrym » Mon Jun 01, 2020 7:30 pm

Luke,

I do have ACS712 modules for 5A and 20A. I was thinking that +5A @ 12V might be sufficient, but I'll use the 20A module first.

The circuit I am working on will use the MOSFET (NPN) to switch the ground on/off to the coil (top button on side of coil). The ACS712 will measure current on the +12v source which connects to the bottom button on the coil. The high voltage (lower button on the side of the coil) will have a small gap which will allow it to arc to ground. All of the grounds for the supplies (+5V, +12V and High Voltage) will be tied together (i.e. common). Hopefully, I won't blow anything apart with this setup!

I noticed on your second hand-drawn diagram corresponding to v0.95 that the lower side connection (high voltage) connects to the bottom of the coil which should be a +6v/+12v. Your earlier drawing shows the high voltage arcing to ground.

I will draw up a proper circuit diagram for my setup.

Right now, I am dealing with supplying power to run the coil. I am using a power supply from an old PC, but the power supply is a switching power supply and it must have a minimum load to provide the proper voltages. I will be using a 12v bulb to provide a base load to keep the power supply happy. I live near Calgary (Canada) and we are still somewhat isolating, so it would be a 1 to 2 week delay to order anything, so I've been scrounging parts wherever I can! I have been learning more about electronics with this project, and have spent considerable time trying to match circuits with what I have lying around.

I agree with keeping everything modular. The key is to have the same compatible module. As a side note, I did run into an issue with the OLED display. The display module I got was not from Adafruit, so it took a bit of time to figure out how to use the Adafruit libraries with the display. The display had a sample to use the U8gx library, but the library is a bit bizarre to use unless the U8G2 library is used in a buffering mode which then took way too much memory. The Adafruit library takes a fraction of the memory that the U8G2 library does in a buffered mode. I think the difference between memory use is the intention that the U8G2 library can read back from the display where the Adafruit library cannot.

Many thanks for your insights.


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Wed Jun 03, 2020 7:43 pm

Barry,

It sounds to me like you're on the right track, and will be learning quite a bit on the way. You can get peak currents up to 6-7A or so, meaning the 20A sensor would be better. It's a shame there's not a 10A unit - you will see I used a CT initially, which worked ok, but I think the ACS devices are easier in terms of calibration etc.

WRT to the wiring, I was trying to replicate the way it worked on the car, then the [metal] cabinet I built for the coil limited some options, but I'm sure you'll work that out.

My recollection of messing around with PC PSU's is that some didn't require a parasitic load to start - you may get lucky. Alternatively I think there were some reasonably elegant ways to remove that limitation, probably a ddg search will reveal some useful info. You should be able to up the voltage from 12 to 13.8 or so too if you need.

FWIW I have come to the conclusion that it's useful to be able to test at least two voltages, particularly if you're doing coils for other people. There appears to be quite a variation in vehicles that use battery 6V, battery 12V, and/or magneto to run the coils. From limited research (published here) it seemed to me that there was quite a variation in coil operation according to voltage supplied, and that as a result it would be best to adjust coils to their normal operating voltage.

With those that use magneto, or switch from battery to magneto, this is more problematic as the voltage supplied to the coil will be variable, making any specific adjustment moot. However for those that use battery at (relatively) fixed voltages it's easy to set the tester supply to that voltage before testing and setting the coils. This is why I included the voltage check at initial turn-on.

You could use another modular approach for this if you got one of the many switchmode regulator boards that are available for a small sum, or build a simple linear regulator. It may also be that if you upped the voltage output in your PC PSU you'd get (say) 7V and 14.5V or thereabouts, a good value for the two most common battery voltages in use.

I'm sorry but I can't comment much on the OLED device(s), however it's useful to hear of your experiences, thank you. If you have any issues resolving anything there I expect Matt may have some useful info. As an aside I was going to use a completely different screen until things went awry earlier in the year, however I'm hopeful after a recent re-order that they will turn up in the next few weeks!

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Jun 04, 2020 5:32 pm

barrym wrote:
Mon Jun 01, 2020 7:30 pm
As a side note, I did run into an issue with the OLED display. The display module I got was not from Adafruit, so it took a bit of time to figure out how to use the Adafruit libraries with the display. The display had a sample to use the U8gx library, but the library is a bit bizarre to use unless the U8G2 library is used in a buffering mode which then took way too much memory. The Adafruit library takes a fraction of the memory that the U8G2 library does in a buffered mode. I think the difference between memory use is the intention that the U8G2 library can read back from the display where the Adafruit library cannot.

Many thanks for your insights.
Barry,
I am not using the Adafruit OLED, so I don't think it would be a issue. The reality is Aurdino is all about open source, so in concept you should be able to use any equivalent display.

There maybe a number of possible reasons for your issues:
  • Libraries not installed correctly. At the start I had some issues with the library. I don't recall what I did, but I think I started a fresh folder and made sure that I only added the library I needed.
  • Display Size I attempted to order 128x64 display, but found that it was 128x32. Perhaps your display is 128x64. You will need to change the code accordingly.
  • Display Address Some displays allow you to change the address. Check on the back to verify that you have the correct address.
I suggest that you load Adafruit's example code and associated libraries to verify that your OLED display is working with the Aurdino. Then from there get things working for the project.

I hope the best to you!

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Aug 29, 2020 1:47 am

I am working on making a PCB. Attached you will see a schematic and PCB layout. I believe the schematic is close to where we want it. The PCB needs lots of work but gives the general idea, I just didn’t want to go too far without getting feedback on the schematic. You will see that I have tried to leave the schematic flexible:
-Potentiometer can be on board or off board.
-Switch can be on board or of board.
-Pushbuton can be on board or of board.
-Inductors can entire surface mount or through hole.
Some of the flexibility is just in case things don’t work out also I said it up this way in case someone wants them out and use their own hardware.

Additionally you should notice that I have tried to separate the board to avoid noise on the micro processor.
Schematic_FACT_0.01.jpg
For clearer schematic open attachment.
For someone following this in detail I noticed the optoisolator was reversed and this is an updated version from yesterday's post.

PCB_FACT_0.01.JPG
I will be using the Chinese electronics fabricator called JLCPCB. I believe it will be about $15 per board assembled with all surface mount electronics. The Arduino & OLED would have to be added separately. The price is part of the reason that I made the board so small, but I am looking at possibly increasing it.

Looking forward to hearing any feedback you may have.
Attachments
Schematic_FACT_0.01.pdf
(87.1 KiB) Downloaded 210 times
Last edited by Matt in California on Sat Aug 29, 2020 8:11 pm, edited 4 times in total.


sedalia
Posts: 5
Joined: Sat Feb 22, 2020 5:36 pm
First Name: STEVE
Last Name: OWENS
* REQUIRED* Type and Year of Model Ts owned: 1926 Roadster
Location: Newton, IA

Re: A new DIY electronic coil tester.

Post by sedalia » Sat Aug 29, 2020 8:56 am

Let me know when you have the boards. I'm interested in buying one.

User avatar

MKossor
Posts: 458
Joined: Sun Jan 06, 2019 7:30 pm
First Name: Mike
Last Name: Kossor
* REQUIRED* Type and Year of Model Ts owned: 1927 Touring
Location: Kenilworth, NJ 07033
MTFCI Number: 22706

Re: A new DIY electronic coil tester.

Post by MKossor » Sat Aug 29, 2020 10:45 am

Nice job Matt, the project has come a long way. Surely you have expanded your knowledge considerably and will have the opportunity to learn much more.
I-Timer + ECCT Adjusted Coils = Best Model T Engine Performance Possible!
www.modeltitimer.com www.modeltecct.com

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Aug 29, 2020 8:07 pm

Mike,
Your comments are appreciated! I will also say that in the handful of words there is a lot of wisdom packed in there! Yes the "opportunities" to learn are many more in this project.

Steve,
I am building this open source. When it is more stable anyone could take the files and have the PCB board made/populated with parts at an assembly house. It would still be a DIY project. Even if the surface mount parts are soldered on there would be some know-how required. Perhaps a club could pick up a handful of them and members with more experience could help others. In reality it takes a multifaceted skill set of electronics/soldering/software. Not to mention time before developed. For a ready build option I suggest the ECCT.

MTFCA,
I am hoping that someone with RF design experience would look over the design and give any insight they may have. Anyone with any electrical experience is welcome to give feedback/insight.


Matt


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Wed Sep 02, 2020 3:17 am

Matt,

Good on you for doing this, I hope you get some responses.

Over here I'm beginning to see one or two things I ordered back in January, so perhaps I'll have some gear to work with by the time our summer break comes around.

Not sure yet if that'll mean much change to the code/hardware, but a bit more experimenting will tell I guess. At the moment it's fairly moot for me as my T is broken, but it'd be nice to finish the tester off and put it into a nice box before I move onto another project :-)

EDIT: Sorry Matt, I replied to your original post but now see there were several subsequent posts ...

It's been a long time since I laid out boards (Protel, in the 90's), however these were almost all for RF projects. I assume your enquiry is related mostly to feedback into the unit (?) in which case in general I'd keep a solid groundplane as much as possible, keep input tracks short, decouple as needed, and ensure ground/negative tracks are capable - the currents can be surprisingly high.

That said, given the breadboard nature of the efforts to date, I'm not sure there should be much of an issue - almost anything that reduces random lead lengths should help. It might be that you need to make up a prototype board at home (use the photocopy/etch method?) to trial and see if any decoupling caps are required?

Incidentally I mentioned where I was at more for general info - it seems to me the tester is sufficiently mature for a V1 board. Whatever we do later on may well not make much of a change to the hardware requirements/setup anyway.


troutjohn
Posts: 76
Joined: Sat Jan 19, 2019 8:21 am
First Name: John
Last Name: Trout
* REQUIRED* Type and Year of Model Ts owned: 1923 runabout, 1913 touring
Location: West Chester PA
MTFCA Number: 31644
MTFCI Number: 24831

Re: A new DIY electronic coil tester.

Post by troutjohn » Tue Sep 08, 2020 3:03 pm

I just finished my FACT Coil Tester. Many thanks to Matt and the others on the forum that contributed to this thread and made it possible to build one. I modeled the case based on a period buzz box. I build two coil bays, one for standard coils and one for larger 1913 coils. My son did the electronics and worked with and modify the code. Pictures are attached.

A could of questions:

What is the current thinking for target TTF for testing at 12V?
Should I primarily tune coils to TTF (with no double sparking) and not be concerned with differences in dwell or current?
What is the range of TTF should I shoot for for a set of four coils? e.g. < 0.1ms or < 0.01ms?

Thanks in advance,

John
Attachments
Coil Tester Multi Shot.jpg
FACT Coil Tester.jpg
Coil Tester Single shot.jpg


Poppie
Posts: 175
Joined: Sun Jan 06, 2019 7:33 pm
First Name: Neil
Last Name: Martin
* REQUIRED* Type and Year of Model Ts owned: 11 tourer 18 tourer 18 TT
Location: Sydney Australia

Re: A new DIY electronic coil tester.

Post by Poppie » Tue Sep 08, 2020 3:51 pm

HaHa , This should be interesting, I hope there is an explanation for the answers too...
John and Son,
You two have done an excellent job on your FACT and should be proud of the result and I am sure Luke and Mat will be the same.
I hope the answers are forthcoming.....N.

User avatar

MKossor
Posts: 458
Joined: Sun Jan 06, 2019 7:30 pm
First Name: Mike
Last Name: Kossor
* REQUIRED* Type and Year of Model Ts owned: 1927 Touring
Location: Kenilworth, NJ 07033
MTFCI Number: 22706

Re: A new DIY electronic coil tester.

Post by MKossor » Tue Sep 08, 2020 9:20 pm

Answers: Yes, +/- 1 degree variation @ 1000 RPM
I-Timer + ECCT Adjusted Coils = Best Model T Engine Performance Possible!
www.modeltitimer.com www.modeltecct.com


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Wed Sep 09, 2020 2:08 am

John,

Good to see your build - it looks as if you have a slot for two coils?

If you look back through the various posts you'll see a fair amount of into that may give you some idea of the target TTF and how that is derived.

In my view, based on personal experience, first principles, and information posted by Alan and Mike the typical TTF should be around 2.1 msec.

However that may not be the case for some coils, I have found some that needed another 500usec dwell time to operate correctly. Should this be the case the important thing is to ensure all the four coils in the set are adjusted to the same TTF. After all this is about consistent firing across the four cylinders - as Mike has been at pains to explain.

Just to conclude the answer and to summarise some of what has gone before; the ideal TTF for an individual coil is when the current ramp plateaus (this is the curve that is shown on Matt's Oled display, and on several 'scope traces in this thread). What these images show is the current rising in the coil (until the points open), when the current is no longer rising (the curve has flattened) there is no advantage in the coil being on for any longer. Over much testing from various people the time to plateau has found to be typically 2.0-2.1msec or so for most coils, hence that's the target. Bear in mind that these things were made many years ago when manufacturing tolerances (if any in this case) were much wider than they are now, so some variance is expected.

With regard to current; if the displayed current is much less than say 4.5A, or more than say 6.5A I'd look askance at the coil. Partly the results you get will depend on the sensor you're using, the coil characteristics and of course dwell time, which again I feel are somewhat variable. Mike may well have some comment on this as he's done a lot in this area.

As for differences, Mike's already answered that but in short you'd want the least amount possible. I look for low SD - in past posts you should see some data I've posted on this, which should give an idea of the range you might expect.

User avatar

John E. Guitar
Posts: 466
Joined: Sun Jan 06, 2019 2:52 pm
First Name: John
Last Name: Guitar
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1924 Tourer
Location: Ulladulla
Board Member Since: 2012

Re: A new DIY electronic coil tester.

Post by John E. Guitar » Thu Sep 10, 2020 8:38 am

Here's the new web link for JohnH's electronic coil tester page:

https://cool386.com/tester/tester.html

https://cool386.com/fordcoils/fordcoils.html

The links on the first page of this thread don't work any more.


troutjohn
Posts: 76
Joined: Sat Jan 19, 2019 8:21 am
First Name: John
Last Name: Trout
* REQUIRED* Type and Year of Model Ts owned: 1923 runabout, 1913 touring
Location: West Chester PA
MTFCA Number: 31644
MTFCI Number: 24831

Re: A new DIY electronic coil tester.

Post by troutjohn » Thu Sep 10, 2020 1:59 pm

Luke, thank you for your reply and all your work on the FACT Tester. Yes, I put in two bays, one for standard size and one for the larger early 1913 coils.

Mike thank you for your reply. I really appreciate your work and enjoyed your MTFCA seminar. If my calculations are correct +- 1 degree = +- 0.16ms. Does this seem correct?

John, thank you for the link. Very helpful.

I see from Luke's data that it is possible to adjust TTF quite accurately for a set of coils, so I will do this.

Below is some data that I thought I would share using the FACT tester on coils that I have in cars and extras. Both cars have been running quite well. I will compare them after readjustment with the FACT tester. I realize from reading the thread that we shouldn't compare data for the different testers. However, it is a starting point for me. Next I will tune them with the FACT to 2.1 ms TTF. For the coils labeled 1913 and Extra, they were adjusted with a Strobospark to 1.3 amps. For the set of coils in the 1912 I have no information except they were adjusted by a professional coil rebuilder some years ago.

Coil Tester. Time SD Dwel lAmps. Mis Tester Spark Amps

1913 1 TTF 2.40 0.02 3.14 3.96 0 Strobo Single 1.3
2 TTF 2.34 0.04 3.97 3.86 0 Strobo Single 1.3
3 TTF 2.30 0.00 2.79 3.61 0 Strobo Single 1.3
4 TTF 2.66 0.04 1.57 3.86 0 Strobo Single 1.3
Avg 2.43 0.16

Extra 1 TTF 2.33 0.09 5.72 4.49 0 Strobo Single 1.3 😉
2 TTF 2.16 0.08 2.44 4.74 0 Strobo Single 1.3
3 TTF 2.79 0.02 3.19 4.88 0 Strobo Single 1.3
4 TTF 40 Strobo Single 1.3
5 TTF 1.89 0.02 1.7 4.64 0 Strobo Single 1.3
6 TTF 1.97 0.02 2.23 4.83 0 Strobo Single 1.3
7 TTF 2.08 0.01 1.77 5.52 0 Strobo Single 1.3

1912 1 TTF 2.02 0.00 2.40 4.69 0
2 TTF 1.90 0.02 4.45 5.37 0
3 TTF 2.39 0.00 4.76 5.37 0
4 TTF 1.71 0.02 2.44 4.25 0
5 Extra TTF 2.17 0.07 2.75 5.18 0
Avg 2.04 0.29

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Sep 12, 2020 12:28 am

What a treat to see the posts! I missed an earlier post and didn't realize there are new posts.

Luke, Thanks for your insight. I will probably do my experimenting with actual PCB. They are only $2 each plus $5 to add parts and the cost of the parts. I know someone who got a board done and was surprised by the turnaround time and the quality looks good enough.

John, I like the work that you and your son did! A very nice box and great idea to be able to test early coils. I believe the first image is cut off due to the screen updating, because it seems to be working in the next photo. I like your color display. What display are you using? How much does it cost? As far as setting the coils I suggest that you retest it at both 6v and 12v. You should see that the who set has similar readings. I don' t worry too much about the current, but have the goal that the whole set has a consistent time to fire.

Matt


troutjohn
Posts: 76
Joined: Sat Jan 19, 2019 8:21 am
First Name: John
Last Name: Trout
* REQUIRED* Type and Year of Model Ts owned: 1923 runabout, 1913 touring
Location: West Chester PA
MTFCA Number: 31644
MTFCI Number: 24831

Re: A new DIY electronic coil tester.

Post by troutjohn » Sat Sep 12, 2020 7:44 pm

Hi Matt, Thank you for the kind words. I really appreciate what you Luke and others have done. the display is an oled display from adafruit.com. Cost is about $35. Can be cheaper from other suppliers. I’ll get my do to add more details.

John

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sun Sep 13, 2020 8:43 pm

John,
Thanks for the info on the color LED. I would like to make this an option on the printed circuit board. Could you send me information on the wiring connections?

Thanks!

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Dec 10, 2020 11:45 pm

...........
Last edited by Matt in California on Thu Dec 10, 2020 11:54 pm, edited 1 time in total.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Dec 10, 2020 11:52 pm

It has been a while since cut out some time to work on this. I hope to get this prototype made soon.

This is the schematic.
Schematic FACT v0_0.JPG
Well this is Version 0.0. I am sure there will be improvements, but I wanted to start somewhere. We will see how this goes.
PCB FACT v0_0.JPG

Matt
Last edited by Matt in California on Mon Dec 14, 2020 9:20 pm, edited 3 times in total.


wtrout
Posts: 3
Joined: Sun Dec 13, 2020 10:41 am
First Name: Will
Last Name: T
Location: Delaware

Re: A new DIY electronic coil tester.

Post by wtrout » Sun Dec 13, 2020 11:08 am

Matt,

Sorry I never saw that you had a question about the circuit in our coil tester; I didn't have an account here before. I'll draw one up. We're using a character LCD that uses I2C and has a few buttons on it as well. It takes all the irritation out of debouncing and handling inputs; not super exciting but when you just want to get that done and move on to other things it is VERY useful. The OLED is going via SPI so just 2 pins again; probably overkill again but hey, whatever!

We're having a lot of electrical noise issues when I put this all together in the box which I need to work out. I don't have the EE knowledge I would like to. Speaking of, what software are you using for the schematics and PCBs?

-Will

PS: I should say, we've left out the capacitor leak test circuit for now which does simplify things quite a bit.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Mon Dec 14, 2020 10:46 pm

Will,
Yes, the capacitor test makes wiring much more complicated.

Electrical noise should be expected with these Model T coils. The one I build and put in the box with lots of loose wires got for coils. I did the same on the circuit diagram/board above. I don't know the best inductance value so I will have to experiment with that. But if you add a ferrite on the wires connected to the coil it could help a lot.

Just today I sent off the design and had them make multiple boards and solder the surface mount parts. I used: The prices are very cheap especially if you have them make a handful of boards. Less than $10 including the surface mount parts soldered on. I will have to wait a few weeks to see if the design works. After I receive the boards I will need to solder on connectors and add the display and Arduino.

I see we are at a year and two days since Luke made the original post! It is great to see the different posts/variations that people have made!

Thanks to everyone!

Matt


wtrout
Posts: 3
Joined: Sun Dec 13, 2020 10:41 am
First Name: Will
Last Name: T
Location: Delaware

Re: A new DIY electronic coil tester.

Post by wtrout » Thu Dec 17, 2020 9:27 am

I made up a schematic using easyEDA. That's a great website to know about.

Yesterday I tore into the code/circuit to make some changes to deal with the interference. The I2C display/inputs definitely had greater issues so I've totally removed that and am now just using the SPI OLED and a basic rotary encoder (which is basically just 3 momentary switches). I also noticed that I was using software SPI so I changed that to the hardware SPI pins which dramatically increases the speed of the display (I didn't measure it but ~50x from what I read of other's tests). Now the charts render ~instantly.

Some notes on the schematic:

Right now the arduino is floating with it's own ground which I am not sure if is right or not. I guess I should probably tie the coil ground to earth at least? Maybe it doesn't matter.

The rotary encoder works by connecting pins A and B to C as it is turned. Each 'click' connects them A on, B on, A off, B off if going clockwise or B on, A on, B off, A off if going CCW. This allows the user to select the operating mode. You can also press the dial down which closes the 3rd switch; I tied this to D2 and attached an interrupt to activate the selected testing routine. (the interrupt is detached during the testing run).

I've omitted the cap test for now and we're just running a fixed 12v supply and fixed speed of 900 rpm. Adding the voltage detection/adjustment and a pot for speed changes would be easy enough so we may do that in the future.


I really appreciate the nice code you all put together. It was a big asset to have all the testing code ready to deploy. I need to clean up my modifications of it today at which point I'll post it!


EDIT: Here's the code. I thought about making some more changes including messing around with putting the ADC is free running mode but frankly this works fine so I'm going to leave it.

Code: Select all

/* The Ford Arduino Coil Tester ('FACT'), a program to test Model T 'buzz coils'
   Released under the GNU General Public Licence (https://www.gnu.org/licenses/gpl-3.0.html)

  Adapted code from Luke P and Robert R, Christchurch, New Zealand with revisions by Matt.

  wTrout 2020 Dec 17th
*/

#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>

const int BLACK           0x0000
const int BLUE            0x001F
const int RED             0xF800
const int GREEN           0x07E0
const int CYAN            0x07FF
const int MAGENTA         0xF81F
const int YELLOW          0xFFE0
const int WHITE           0xFFFF

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; //zero current
int ttf;
unsigned long time_now = 0;
const byte numReadings = 120;     //max number of values in array, 150 = approx 3ms (112 limit of display)
const byte numTests = 50;         //number of test cycles in multi test
const int interval = 4000;

unsigned int analogVals[numReadings][2]; // array name & columns
unsigned int x = 0;
unsigned int resultVals[numTests][2]; // array name
unsigned int y = 0;

//faster ADC reading
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

const byte SCREEN_WIDTH = 128;
const byte SCREEN_HEIGHT = 96;
const byte DC_PIN = 9;
const byte CS_PIN = 10;
const byte RST_PIN = 7;

//call display on hardwear SPI
Adafruit_SSD1351 display = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, CS_PIN, DC_PIN, RST_PIN);

const byte rotaryEncoderPinA = 4;
const byte rotaryEncoderPinB = 5;
const byte rEncoderPressPin = 2;
const byte relayPin = 3;

volatile bool activate = 0; //trigger variable for ISR, 1 -> activates selected test when loop() is running

int readDial(byte, byte);
void activateSwitch();
void singleTest();
void multiTest();
void singleFireData();

//==============================================================================

void setup() {
  sbi(ADCSRA, ADPS2); //more stuff for fast ADC read
  cbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);

  SPI.begin(); //start SPI for OLED display

  //set up input pins
  pinMode(rotaryEncoderPinA, INPUT_PULLUP);
  pinMode(rotaryEncoderPinB, INPUT_PULLUP);
  pinMode(rEncoderPressPin, INPUT_PULLUP);

  //activate the ISR on button release; this will set bool activate to 1
  attachInterrupt(digitalPinToInterrupt(rEncoderPressPin), activateSwitch, RISING);

  pinMode(relayPin, OUTPUT);

  display.begin();
  display.fillScreen(BLACK);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 0);
  display.println(F("Single Spark Test"));
  
  activate = 0; //make sure the ISR didn't trigger before the loop
}

//==============================================================================

void loop() {
  static bool mode = 1; //single (1) or multi (0) test selection; could be other type for more modes
  
  //repeatedly check the dial rotation state and return a 1 or -1 for one notch CW or CCW
  bool reading = readDial(rotaryEncoderPinA, rotaryEncoderPinB);
  mode ^= reading; //change mode when the rotary encoder changes a notch

  if(reading) { //change display if the mode changes
    display.setCursor(0, 0);
    if(mode) {
      display.println(F("Single Spark Test"));
    }
    else {
      display.println(F("Multi Spark Test"));
    }
  }

  if(activate) {//if activate is set by ISR
    detachInterrupt(rEncoderPressPin); //disable the ISR so the tests aren't interrupted
    if(mode) {//check the mode and run appropriate test
      singleTest();
    }
    else {
      multiTest();
    }
    attachInterrupt(digitalPinToInterrupt(rEncoderPressPin), activateSwitch, RISING); //re-enable the ISR for the loop
    activate = 0; //reset the activate flag
  }


}

//==============================================================================

int readDial(const byte rotaryEncoderPinA, const byte rotaryEncoderPinB) {
  //this function works as a loop through repeated and FREQUENT calls!
  
  static long timeSplit; //time gap between switch A and B turning on
  static long lastTimeSplit; //last unique time gap
  
  static int max = 0; //largest running gap
  static int min = 0; //smallest running gap; basically "max" in the negative direction
  static int direction; //resulting direction change of the dial; (-1, 0, 1)

  static long PinATime; //time when A was last on
  static long PinBTime; //time when B was last on

  bool PinAState = digitalRead(rotaryEncoderPinA); //reads the rotary encoder switch A
  bool PinBState = digitalRead(rotaryEncoderPinB); //and B
  long now = millis();

  PinATime = ((PinAState * now) + (!PinAState * PinATime)); //if PinA is on then PinATime is set to now; otherwise unchanged
  PinBTime = ((PinBState * now) + (!PinBState * PinBTime)); //if PinB is on then PinBTime is set to now; otherwise unchanged

  timeSplit = PinATime - PinBTime; //difference in time between when switch A and B were turned on; sign gives CW vs CCW direction

  if(timeSplit != lastTimeSplit){ //has anything changed since we last called readDial()? Ex: is the dial at rest and the timeSplit 0?
    //Serial.println(timeSplit);
    lastTimeSplit = timeSplit; //updates the "last" if there's a change
    
    if(timeSplit > max){ //is the time split positive or growing?
      max = timeSplit; //if yes update max
      if(min == 0){ //make sure it didn't start by turning the other way
        direction = 1; //it turned CW
      }
    }
    if(timeSplit < min){ //is the time split negative or dropping?
      min = timeSplit;
      if(max == 0){ //make sure it didn't start by turning the other way
        direction = -1; //it turned CCW
      }
    }
    if(timeSplit == 0){ //has the dial finished turning?
      max = 0; //reset vars
      min = 0;
      return direction; //return which way it turned
    }
  }

  return 0; //most of the time the dial is a rest and 0 is returned
}

//==============================================================================

//ISR function; short as possible
void activateSwitch() {
  activate = 1;
}

//==============================================================================

void singleFireData()
{
  //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(relayPin, HIGH); //set relayPin high to power coil for time interval
  time_now = micros();

  while (micros() < time_now + interval)
  {
    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
      analogVals[i][0] = (analogVals[i][0] + analogRead(A0)) / 2; //take a second reading and average the two (this helps fit on OLED screen)

      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(relayPin, LOW); // reset relayPin 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 singleTest()
{
  singleFireData();

  mVolts = (A0_max / 1024.0) * 5000.0; // raw analog read val to millvolts
  amps = ((mVolts - 2500.0) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip

  // write results to OLED
  display.fillScreen(BLACK);
  for (x = 1; x <= numReadings; x++) {
    // digital value of max current in =660; 5= digital values of current range/#lines = 150/32 = 4.68
    int y1 = (660 - analogVals[x - 1][0]) / 2;
    int y2 = (660 - analogVals[x][0]) / 2;
    display.drawFastVLine(x + 10 , y1, y2-y1, WHITE);
  }
  // draw the axis, lables and tick marks
  for (int y = 0; y < 6; y++) {
    display.drawFastHLine(6, 74 - (y*13), 4, YELLOW);
  }
  for (int x = 0; x < 6; x++) {
    display.drawFastVLine(x * 28 + 10, 80, 8, YELLOW);
  }
  display.setTextColor(YELLOW, BLACK);
  display.setTextSize(1);
  display.setCursor(0, 74-3);
  display.println("0");
  display.setCursor(0, 35-3);
  display.println("3");

  display.setTextColor(WHITE, BLACK);
  display.drawFastHLine(10, 74,  74 - 10, YELLOW);
  display.drawFastVLine(10, 8,  90, YELLOW);
  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"));

  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();
}

//==============================================================================

void multiTest()
{
  // 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
  {
    singleFireData();
    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;
    }
    
    mVolts = ((resultVals[i][1]) / 1024.0) * 5000.0; // raw analog read val to millvolts
    amps = ((mVolts - 2500.0) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A 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;
    }

  }
  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.fillScreen(BLACK);
  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   "));
}



Attachments
Schematic_CoilTester_2020-12-17_09-06-33.png

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Dec 17, 2020 6:08 pm

Will,
This is awesome! I love how you and others are taking this project in your own direction! Your idea with the rotary encoder. In hind sight I could (should?) have used more buttons rather than a potentiometer. The company doesn’t solder the potentiometer on... I also like the idea of color OLED, but frankly I wanted to get things on a PCB on what I tested because I feared I would never reach that goal.

As far as isolating things I would do that as much as possible. I don’t see why you would need to connect the grounds together.

Thanks for posting your code!

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sun Dec 20, 2020 1:32 am

I received word from JLCPCB that the order is on the way yesterday. Then shortly after I heard from DHL that the shipment is due to be delivered December 23rd. That is 10 days from the time day that I placed the order!

I will keep you posted when it arrives!

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Tue Dec 22, 2020 4:50 pm

Look what arrived one day early!
AE08394B-A0EF-4F09-8A07-D5D8569FCF64.jpeg
BD8D007C-DA59-4CCA-AF8C-CC50E7C97B26.jpeg
Even got a free key chain.
D55461E6-253C-4202-9710-572717015644.jpeg
422F2B29-669F-414F-A5E7-3B922E53974F.jpeg
2D4B33C7-8DA6-49E9-9B5F-BEA43ADAE09B.jpeg
Next step is some testing to find how many mistakes I made.

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Jan 02, 2021 12:33 am

Parts arrived a few days ago:
2DC4F14D-04F2-40BD-8E16-34DFF178D92F.jpeg
But when I soldered on the connectors I found that there was issues. It took me some time but I figured out that the current sensor was wired in reverse. Additionally the capacitor tester with not working again the connection was in reverse. The solution was cutting traces and adding jumpers.

Can you see three traces cut and three jumpers on the top side?
440B18D3-7A11-42D6-91BB-3B5F851A1D64.jpeg
How about the one jumper on the back?
AF509F2A-B5E9-4A62-8720-AE5165453B8D.jpeg
First try two mistakes. I will take that! I hope someone is enjoying the process of refining this printer circuit board.

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Jan 02, 2021 12:46 am

Now the board FACT PCB is working.
CC8449F1-58DF-4297-9DDD-19E3B2AA1988.jpeg
5F5AE33B-CCEB-4B4E-9F14-1DA40CFE1F4B.jpeg
After having a docking experience I figured out it needed to be mounted. I made wood standoffs, but in the future nylon ones should be procured.
26E994C0-25AC-4273-A5BC-A8E649785E24.jpeg
Note that it is basically three boards stacked:
1. Arduino Nano
2. FACT PCB
3. OLED

After I get some kinks worked out I hope to share the process where others could get there own made.

Matt


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Sat Jan 02, 2021 3:07 am

Good job Matt, and pleasing to see there's still some life left in this project...


Poppie
Posts: 175
Joined: Sun Jan 06, 2019 7:33 pm
First Name: Neil
Last Name: Martin
* REQUIRED* Type and Year of Model Ts owned: 11 tourer 18 tourer 18 TT
Location: Sydney Australia

Re: A new DIY electronic coil tester.

Post by Poppie » Sat Jan 02, 2021 4:23 am

Well said Luke, but what is the project?????,
Is it an electronic circuit exercise showing a visual display that a coil produces when battery voltage (DC) is applied to it, or is an exercise to properly adjust a MODEL T FORD ignition coil that was designed to start and run on an alternating current (AC) supply!!!
It would have been interesting how far Mat's MCCT tester would have developed and it is an Alternating Circuit (AC) supply.
I would love to know why the professional Model T Ford coil rebuilders have not replied /queried the D/C and A/C applied voltage for Model T coil adjustment. I use a Wilson Hcct tester in conjunction with a Fluke 289 multimeter and I don't use a Hammer. :roll: .
WHAT testing equipment do the professional coil builders use???.....N.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Jan 02, 2021 11:33 pm

Luke,
Thanks for getting this started. I have enjoyed the tinkering and I hope when I finalize things it will make the tester accessible to others.

The good news is that the electrical interference does not seem to be a issue with the new PCB. My hope was to keep the cost to be near the $15 dollars you mentioned in your original post a year ago. Here are the costs I have:
$5.50 PCB ($82.47 for 15 PCBs + surface mount assembly + shipping)
~$3.00 Parts to be solder on PCB (connectors, switch, potentiometers with shipping for 15)
~$4.00 Arduino Nano (purchase in quantity of 10)
~$3.00 0.96" OLED Display (purchase in quantity of 5)
$15.5 Total
*Other add ones would be a USB cord, alligator clips and a nice case for testing.

My thought is that someone in local chapter with some software knowhow and soldering ability could purchase parts for maybe 15 and help other members have an affordable tester for their coils.
Poppie wrote:
Sat Jan 02, 2021 4:23 am
Well said Luke, but what is the project?????,
Is it an electronic circuit exercise showing a visual display that a coil produces when battery voltage (DC) is applied to it, or is an exercise to properly adjust a MODEL T FORD ignition coil that was designed to start and run on an alternating current (AC) supply!!!
It would have been interesting how far Mat's MCCT tester would have developed and it is an Alternating Circuit (AC) supply.
I would love to know why the professional Model T Ford coil rebuilders have not replied /queried the D/C and A/C applied voltage for Model T coil adjustment. I use a Wilson Hcct tester in conjunction with a Fluke 289 multimeter and I don't use a Hammer. :roll: .
WHAT testing equipment do the professional coil builders use???.....N.
Neil,
I appreciate you joining the discussion. The setup you describe should be very effectives for tuning a set of coils. I am aware of people using oscilloscopes in testing coils, but I don't recall much discussion (posting) about the particulares. I think it would be a great contribution if you shared more about your setup and give people a tutorial. I also agree that it is better to not hammer on the coil. Please feel free to share about what tools you use.

In regard to the FACT tester- here is my response:
Goal of the FACT tester as mentioned in Luke's first post from a year ago is to make an cheap (<$20) time-to-fire coil tester that would be both affordable and within the skill set of the average model T owner.

Theory- Step Response testing method is a very common method to test systems to determine a particular parameter. I could find more words than you would care to read about why a step response is the go to method for testing electromechanical control systems. I know that you mention that the FACT is DC, but a step response is not static. My point is that we are looking for the dynamic response in a system. Furthermore this is exactly the the coil experiences when the car is running on the battery.

Practically speaking Frankly I can care less about the theory if we can't get something working practically. Earlier this week I talked with someone who has multiple times come out first in the Montana 500 endurance run. He is a very strong proponent of the ECCT coil tester that to my understanding works on the same theory as the FACT. I can't think of a better practical test for a tuned set of coils then to run a Model T at 55 MPH average for 500 miles. I have talked with another M500 participant who uses an oscilloscope similar to what you discribe. That leads me to my last point.

Testing on Magneto you mention using a oscilloscope with the magneto. I agree this is good. It is not outside what can be done with this hardware/software. It would take some time to reconfigure. I am currently focusing on getting the existing FACT more available (i.e. the new PCB). But I would like to hear more about your test methods. Simply put the FACT is really a cheap oscilloscope that measures current (plus/minus 20 amps). We can reconfigure it to work with magneto.

Respectfully,

Matt


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Sun Jan 03, 2021 5:41 am

Poppie wrote:
Sat Jan 02, 2021 4:23 am
Well said Luke, but what is the project?????,
Is it an electronic circuit exercise showing a visual display that a coil produces when battery voltage (DC) is applied to it, or is an exercise to properly adjust a MODEL T FORD ignition coil that was designed to start and run on an alternating current (AC) supply!!!
It would have been interesting how far Mat's MCCT tester would have developed and it is an Alternating Circuit (AC) supply.
I would love to know why the professional Model T Ford coil rebuilders have not replied /queried the D/C and A/C applied voltage for Model T coil adjustment. I use a Wilson Hcct tester in conjunction with a Fluke 289 multimeter and I don't use a Hammer. :roll: .
WHAT testing equipment do the professional coil builders use???.....N.
Neil,

The 'FACT' was started as a contribution to the Model T community, and the general body of knowledge, as a contemporary means to assess and adjust Model T coils.

Along the way I believe the project has educated a number of people in various facets of Model T ignition, in general electronics, and in coding with embedded microprocessors. It has also brought various people together who have worked to improve the original design and make contributions of their own.

With regard to AC etc, I can't comment on Matt's motorised tester but I'm sure he will! :-)

That said you could use an alternating supply with the FACT if you wish, and if you wanted to contribute something to the design that incorporated this I expect it would be very welcome. However while to some extent it's correct to state the coils were originally utilised with AC this is, and was, not a prerequisite, and many cars were and are run solely on DC.

If you look back through the posts I think you'll find several technical comments on AC vs DC (so no need to re-iterate them here), as well as on the variability in coil operation at different (DC) voltages. It's probably worth the read as it may answer some of your enquiry.

Otherwise I don't recall if any people who rebuild coils as a business have contributed to this discussion/project? Mike K has posted several times, which has been very useful, but that's about it I think - so you will probably need to ask them yourself...

Matt,

That's a good idea re accessibility, I hope some of the clubs take you up.

Pleasing to hear the interference is effectively dealt with. Unsurprising really, those long leads would certainly act as an antenna that'll do a reasonable job of receiving signals from the nearby spark-gap transmitter!

Also good to hear the dollar figure has worked out close as well - not in the least due to your design work.

FWIW the almost complete collapse of component delivery to me this year passed has meant the next version I was going to work on hasn't happened. Add to this all the other stuff that has happened and I'm now uncertain when I'll get to it :-(

Coupled with the component shortage, and as I try and make various contributions to open-source projects around the world, with some of them taking rather more time than anticipated, this has meant that the digital/analogue Model T speedometer project hasn't progressed much either, sigh. Perhaps that may happen later in the year...

Anyway I reiterate that it's good to see your work on this project, making it easy for people to assemble their own is a major step.

User avatar

MKossor
Posts: 458
Joined: Sun Jan 06, 2019 7:30 pm
First Name: Mike
Last Name: Kossor
* REQUIRED* Type and Year of Model Ts owned: 1927 Touring
Location: Kenilworth, NJ 07033
MTFCI Number: 22706

Re: A new DIY electronic coil tester.

Post by MKossor » Sun Jan 03, 2021 3:02 pm

Neil, The professional coil rebuilder who propagates the myth Model T coils Must Only be adjusted using AC because they designed to Run on AC (Magneto) simply does NOT understand the fundamental operation of the Model T ignition system. As I have attempted to explain to you on numerous occasions in considerable detail. Another, through review of those previous posts may be helpful as Luke suggests. They explain how coil current does not ever reverse direction when the coil charges and fires a spark (i.e. Direct, One Way, Current flowing each and every coil firing event).

This thread has indeed been a very educational endeavor and still offers great potential. At some point, this discussion will need to be relegated to the classified section as vending goods or services appears to be the ultimate goal and is prohibited here. As a long time electronics enthusiast, I applaud the collaborative effort which has advanced this project and helped others to expand their knowledge. As entrepreneur and Model T vendor suppling the commercial version of this project, I am torn trying to decide if it is worth the risk to replenish dwindling inventory with the expectation of a $15 DIY version coming to fruition. In that regard, this thread is a double-edged sword. The prudent path forward is to follow suit of other Model T vendors; wait for sufficient demand to accumulate before making smaller batch runs at higher cost. I hope to have the engine rebuild parts I need; still on back-order, by next spring.
I-Timer + ECCT Adjusted Coils = Best Model T Engine Performance Possible!
www.modeltitimer.com www.modeltecct.com

User avatar

John Housego
Posts: 30
Joined: Wed Jan 16, 2019 4:44 pm
First Name: John
Last Name: Housego
* REQUIRED* Type and Year of Model Ts owned: 1925 Tourer
Location: Aylesbury Bucks UK
Board Member Since: 2007

Re: A new DIY electronic coil tester.

Post by John Housego » Wed Jan 06, 2021 4:53 pm

Hello Mat,

I have not been following this for a while and was surprised you have now got a PCB, thats great, well done. I still have my FACT coil tester running and is working fine after all this time. Would be nice to tidy it up so I wonder if you are going to make the Gerber files available for the PCB at any time?

Thanks

John


Allan
Posts: 5172
Joined: Sun Jan 06, 2019 7:21 pm
First Name: Allan
Last Name: Bennett
* REQUIRED* Type and Year of Model Ts owned: 1912 van, 1917 shooting brake, 1929 roadster buckboard, 1924 tourer, 1925 barn find buckboard, 1925 D &F wide body roadster, 1927LHD Tudor sedan.
Location: Gawler, Australia

Re: A new DIY electronic coil tester.

Post by Allan » Wed Jan 06, 2021 6:10 pm

M 3yo grandson really likes the picture with he two triangular dog ears. He reckons they are just like Bluey's.

AllAn from down under.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Jan 07, 2021 1:51 am

John, I plan to make the Gerber files, BOM and placement files available when I finalize the next version. We can talk about getting them to you sooner than when I post them.

Mike, I read your post a few days ago. I hear your concern. What I want to say is I have an increasing respect for you. I have not missed how you have contributed to this discussion sharing your ideas knowing that we are building a DIY project that basically shared the same concept of measuring the time-to-fire to tune coils. I also hope that this design would create cenergy with the ECCT. I have a friend with a tea shop and a few years later Starbucks moved in the same strip mall. I asked if he was upset, he said that he actually thought it would build up his business. I believe that the FACT and ECCT have a much different market. If someone wants a time-proven, reliable, and supported design the ECCT is the way to go. If someone wants to do a DIY project the FACT could be fun. They may build a fancy wood box. But they have no warranty and no support. . . Not everyone has skills soldering, troubleshooting electronics and programing. All are needed for this DIY project. It is kinda like comparing a Cadillac with a Ford. Some people who get the FACT would never buy a ECCT. Some may buy a ECCT because the hear about the idea of a time-to-fire tuning, but don't want a DIY tester. In short the ECCT is a great product because you get the word out and market it, you stand behind it. You have the best product out there to test coils, but the irony is that people still want to give you a hard time.

Luke,
I don't recall you mentioning that your idea of a speedometer... I too am going to be very busy and don't know what I will be able to develop things in the next 5 months, but I combined Neil's idea of a Magneto Oscilloscope and a speedometer. The following picture shows a bench test with one FACT triggering the coil and the second one is modified to purley measure/display the current, RPM and Speed. Of course this would need some modifications, but could be used on a car or perhaps as Neil suggested on a HCCT.
6568879C-24ED-4F44-890B-81DEE6B038A2.jpeg
51B0CC0B-D65C-468C-979A-2C1A7B96D9CB.jpeg
BF798414-8441-4E94-BB31-C52D94AC1263.jpeg
DA328E30-BD63-4B33-9BE1-AC76BB0A8FD5.jpeg
Allan,
I remember when my daughter was young and would wake up to see the oscilloscope on in my office as I was testing things. That was always the first thing she wanted to do in the morning...

Matt

User avatar

A Whiteman
Posts: 987
Joined: Sun Jan 06, 2019 3:36 pm
First Name: Adrian
Last Name: Whiteman
* REQUIRED* Type and Year of Model Ts owned: 1926 TT, 1924 Colonial Roadster, 1924 'Bullnose' Morris, 1925 'Bullnose' Morris, 1936 JD AR
Location: South Island, New Zealand

Re: A new DIY electronic coil tester.

Post by A Whiteman » Thu Jan 07, 2021 3:33 am

Hi Matt - Two Thumbs Up from me.
Nice post, well put.
Cheers
Adrian


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Fri Jan 08, 2021 3:15 pm

Matt,

The speedometer comment was probably a bit of a non-sequitur. I had thought I'd mentioned it in this thread previously, but perhaps not - and in any event it would have been a long time ago now!

Regardless, there was another thread on it that didn't go anywhere because I'd spent most of my spare time on the coil tester. However the thought was to produce an electronic -> analogue speedometer for the Model T with a 'real' gauge, much as I had done some years ago with a flight training device I built. I seem to recollect putting up some examples, but will need to find that thread again and see where it was at before doing any more.

FWIW my first design, which is still around here somewhere, allowed for several input sources, including the ignition (working similarly to what you display). The issue with that input of course is that it is prior to the gears and so a dual (or more if you have a Ruckstell etc) scale is required. I tried utilsing MEMS gyro/accelerometers on the gear pedal to determine position and scale the output appropriately but decided it was probably over complicated. Much as with the coil tester I want[ed] to design something simple that most people could easily reproduce.

I do have a slight problem in advancing the speedometer (along with an 'electronic ignition' system I was toying with) because my Model T has been laid up for some months now (the motor is dead, and I can't get another), so testing is problematic. However I can probably utilise something else for the initial POC, and perhaps ask one of the other local Model T owners to do some quality control ;-)


troutjohn
Posts: 76
Joined: Sat Jan 19, 2019 8:21 am
First Name: John
Last Name: Trout
* REQUIRED* Type and Year of Model Ts owned: 1923 runabout, 1913 touring
Location: West Chester PA
MTFCA Number: 31644
MTFCI Number: 24831

Re: A new DIY electronic coil tester.

Post by troutjohn » Thu Feb 18, 2021 7:36 pm

My son Will and I have finished rebuilding and our FACT coil tester and it now appears to be working. You can see in the pictures the box has been divided into 2 boxes to separate the electronics from the spark and electromagnetic interference. We worked on shielding for several months to keep it from disrupting the Arduino and the separate boxes helped. He also rewrote the software. There are two coil bays – one for standard size and one for larger 1913 coils.

The 5" screen shows 50 spark traces. With the new software each spark measurement is shown so you can see the variation. For this coil the time to fire is 2.09 ms +- 0.08. Current is 3.08 A. It will also do single spark tests.

If there is interest he can post the code and other details.

Again, many thanks to Matt, Luke, and others for getting this started and making this possible.

John
Attachments
Coil Tester 3 copy 2.jpg
Coil Tester 2 copy 2.jpg
Coil Tester 1 copy 2.jpg

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sun Feb 21, 2021 12:15 pm

John,
Great work! I like how you have the options for the two styles of coils! Nice display! Do you prefer the dots plotting verses the lines connecting the lines?

I understand why you separated the coils and I have seen that it reduces electromagnetic interference. The good news is that the PCB I mentioned above seems to have solved the issues. I have been testing with the electronics in a box next to the coil with no issues. Message me if you want to give it a try.

Matt


troutjohn
Posts: 76
Joined: Sat Jan 19, 2019 8:21 am
First Name: John
Last Name: Trout
* REQUIRED* Type and Year of Model Ts owned: 1923 runabout, 1913 touring
Location: West Chester PA
MTFCA Number: 31644
MTFCI Number: 24831

Re: A new DIY electronic coil tester.

Post by troutjohn » Mon Feb 22, 2021 11:47 am

Hi Matt, I do like the dots because it give me an idea of the distribution of the firing of the 50 shots. I also sent you a PM.

John


wtrout
Posts: 3
Joined: Sun Dec 13, 2020 10:41 am
First Name: Will
Last Name: T
Location: Delaware

Re: A new DIY electronic coil tester.

Post by wtrout » Mon Feb 22, 2021 11:47 am

Here's some more info on the coil tester troutjohn posted.

Since we went with the larger display (480x272 pixel), I found the 328's RAM lacking which led to very difficult to troubleshoot issues. I had some SAMD21 based boards sitting around so I started working with them. They have way more RAM, faster processor and greater ADC capabilities. I ended up totally rewriting all the code to make the most of the hardware we chose (Adafruit's Qt Py, which is a fantastic board). It now samples at 100 ksps with 12bit depth, each one being 2x averaged and records for 4.5 mS for each test.

I'll link to my new code which is still heavily inspired by the work of you all here. There's also a schematic there which is a bit rough but should give the idea.

We had major issues with noise and interference which were solved by putting all the digital electronics in an aluminum enclosure with pretty heavy filters on the lines coming into the case (see the schematic). While I'd love to try this with Matt's PCB, I would have to fabrication a daughter board which would 'convert' the pin configuration of a SAMD board which runs at 3.3V max to the configuration of the Arduino Nano which is a 5V capable board.


Code and Schematic

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Fri Mar 05, 2021 2:31 am

Will & John,
This looks great! Thanks for posting the code!

You got my curiosity up about the SAMD21 chip. I ordered Seeed's XIAO board. It only costs $5 for about 4x speed and memory. I was finding that the Arduino Nano was near it limits. It would be nice to try the have the flexibility. It may not be hard to adapt it to the current FACT PCB that I designed. The only issue is the 3.3 volt limitation. The nice thing with the current PCB I haven't had issues with electric noise.

Matthew

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sun Mar 07, 2021 1:42 am

Here is the FACT PCB in a plastic box.
13D15CA3-3383-4D1E-95E2-3DE62A4C1321.jpeg
Here is a video on the build: https://youtu.be/r0aD2gI0bZ8

Enjoy,
Matt

User avatar

fbergski
Posts: 111
Joined: Sun Jan 06, 2019 11:16 am
First Name: Philip
Last Name: Berg
* REQUIRED* Type and Year of Model Ts owned: 1911 Touring 1916 Coupelet
Location: Simi Valley CA

Re: A new DIY electronic coil tester.

Post by fbergski » Tue Mar 09, 2021 8:04 pm

Matt,

Are you selling your FACT tester yet?


troutjohn
Posts: 76
Joined: Sat Jan 19, 2019 8:21 am
First Name: John
Last Name: Trout
* REQUIRED* Type and Year of Model Ts owned: 1923 runabout, 1913 touring
Location: West Chester PA
MTFCA Number: 31644
MTFCI Number: 24831

Re: A new DIY electronic coil tester.

Post by troutjohn » Tue Mar 09, 2021 9:14 pm

Matt, your box and design looks great!

John

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Wed Mar 10, 2021 2:02 am

Thanks John!

Philip,
I am not planning to sell these. I do need to do a bit more testing with this version of PCB before I make the next board. Then I plan to show others how to make these for themselves. It is a DIY project and requires some know how in soldering and software. I image if a club got together they would have the right people for the project.

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Wed Mar 17, 2021 11:34 am

Philip, I sent you a message and email.

I was thinking about the simplest design possible for a coil testing enclosure. My idea was to just use a couple pieces of plexiglass, small wood pieces and some basic hardware.

Here is the design:
0D092221-2DC9-480E-886B-106F47BC89EE.jpeg
And this was a how it came out:
A063F48E-FE91-453B-9869-808BFA41C203.jpeg
Most anyone should be able to build it. Here is a video showing the build:
https://youtu.be/odrrwqX-JlI

Now I am looking forward to getting the revised PCB test. This should have the misrouted traces fixed. Look for posts on that soon.

Matt


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Wed Mar 17, 2021 3:11 pm

Matt,

I'm not sure I'd advise having the spark gap quite so close to the componentry?

While the clear case is cool, and putting everything on a PCB has reduced the issues you were having, I'd still be inclined to shield the electronics from the coil and spark gap as much as possible. There's a fair amount of RF that's produced there...

It's a poor photograph from a descriptive point of view but you can see what I did in one of my earlier posts (viewtopic.php?f=2&t=9072#p67273) where three sides and the base of the coil receptacle are steel, and one side is polycarbonate.

It may be that you could include something similar within your current enclosure, but put the spark gap on the farside and PCB to the rear of a steel case held within your plexiglass sandwich? It's not a complete Faraday cage (https://en.wikipedia.org/wiki/Faraday_cage) but should assist in minimising possible EMF issues, yet retain the aesthetic you're going for?

Of course copper sheet or PCB (soldered together as needed) would achieve the same thing, but could look a little more, er, 'steampunk', if that were desired 8-)

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Mar 18, 2021 2:39 am

Luke,

My knee-jerk reaction is "If it ain't broke don't fix it." I have yet to see the FACT PCB fail due to electrical interference! I could use the excuse that I am putting the board so close just to test it :roll: , but I do see your point. You are correct this may not seem like the best example. Actually I am posting to get feedback, so I really appreciate your input. :mrgreen:

I image that anyone who has used a digital multimeter under the hood of their T knows exactly what you are describing! Additionally everyone that has played with FACT and the associated modules has seen issues with RF interference. On my first prototype that was enclosed (similar to this) I thought I wouldn't get it working, but I did by adding inductors.

So why does the FACT PCB seem to be immune? Here are some reasons:
  • Ferrite beads are added on all four inputs.
  • Flyback diode.
  • Optical isolation between microprocessor output and MOSFET.
  • PCB layout isolates high voltage and low voltage parts and makes all connections short.
  • All connections are short as possible.
  • Return path on secondary is short - actually as short as possible between the two points on the coil.
That said, I will continue to test it as I have it. But I do think you have a point about considering a better option. I noticed in your set up there is a long ground path that the spark would have to follow to get back to the secondary. On my setup I used a paperclip and ran it directly to the ground terminal.

Fun Stuff!

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Mon Mar 29, 2021 3:23 am

I received FACT PCB version 1.0. It tested and worked well.

PCB:
FACT ver 1_0.JPG
Schematic:
FACT ver 1_0.pdf
(170.76 KiB) Downloaded 141 times

For those who want to make there own, you will need these three files:
1. BOM- Bill of Materials:
BOM_PCB_FACT_3_12_21_2021-03-29.7z
(1.44 KiB) Downloaded 183 times
I had to zip this file to post it on the forum. You will need to unzip it to upload to the PCB builder.

2. Gerber files:
Gerber_PCB_FACT_3_12_21_2021-03-28.zip
(28.65 KiB) Downloaded 147 times
IUse this file when you upload this to PCB builder.

3. Pick and Place file:
PickAndPlace_PCB_FACT_3_12_21_2021-03-28.7z
(1.56 KiB) Downloaded 163 times
I had to zip this file to post it on the forum. You will need to unzip it to the PCB builder.

Important!
The following details should be done when having the PCB board built:
1. Don't place R10 (Trim Potentiometer is not needed.)
2. Don't place L1A, L2A, L3A, L4A. (These surface mount inductors work, but the thru hole inductors work better. It is your choice, but only use L#A or L#B.)
3. Use BL02RN2R1N1A or similar ferrite bead/inductor for L1B, L2B, L3B, L4B.
4. Add 0.96" I2C OLED to top of board. Be sure the pin out is the following order: VCC, GND, SCL, and SDA.
5. Add Arduino Nano to the bottom of the board.

Option:
1. On/Off switch- it is a good idea to be able to cut power.
2. A secondary pushbutton may be added using connector pins.
3. A secondary potentiometer may be added using the pins for R10. In this case turn R9 fully clockwise. Alternatively the PCB stitch may be used if a small hole is made in the acrylic cover.
4. Capacitance switch- If you want to use a secondary switch for capacitance test don't place SW1. Add wires to PCB from switch that is used. Alternatively the PCB stitch may be used if a small hole (slot) is made in the acrylic cover.

In the future I hope to give some more details. Feel free to let me know if you have any questions.

Matt

User avatar

John Housego
Posts: 30
Joined: Wed Jan 16, 2019 4:44 pm
First Name: John
Last Name: Housego
* REQUIRED* Type and Year of Model Ts owned: 1925 Tourer
Location: Aylesbury Bucks UK
Board Member Since: 2007

Re: A new DIY electronic coil tester.

Post by John Housego » Mon Mar 29, 2021 5:01 pm

Matt many thanks for your time and effort with this, I have downloaded all your files and will take a closer look with the view to order some boards. Thanks again. John

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Fri Apr 09, 2021 1:02 am

Well I have this coil tester on my desk near my computer. Sometime it stares at me until I get an idea. :idea: This week I realized there is no need for the toggle switch! :!: One issue was making sure it had contacts that could carry the high current. The funny thing is I found I could short those out! Now I just have two SPST buttons. The red one fires the coil the black one is for the capacitance test.
45D62BEE-4FA3-49C0-86D9-72C94712D1DC.jpeg
For those building these this information may come in really handy!

Enjoy!
Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sun May 02, 2021 8:17 am

This is intended to be insightful and hilarious.

As a designer (ie engineer) of a device there is nothing better than using yourself repetitively to detect needed improvement. I did that recently by simplifying the design with two switches.

As a promoter of a device there maybe nothing better than listening to people to know how their existing experience maybe improved. I did this when I demonstrated the FACT at the Tulare swap meet yesterday. I asked people how they tested their coils. I heard answers I didn’t expect:
  • “The first time I tested my coil I did it by putting my hand on the spark output.” :o
  • “I adjust the coils with the engine running and by ear using my leathermans tool.” :ugeek:
  • “I go to a swap meet get some coils. I try them as replacements one at a time. If the engine sounds better I use it as a replacement.” :mrgreen:
  • “I use a AC model railroad transformer and measure current.”
  • “My dad purchased our TT truck in 1965. I have never done anything to test the coils except clean the contacts with emery cloth.”


*Of course many others use more conventional methods: Buz box, HCCT, STROBO-SPARK and the ECCT.

I learned coils can be tested by touch, feel, sound and maybe even smell. (Maybe even taste;). I realized that these methods and many more have been used for the last 100 years. I was reminded how for many people electronics are very much a mystery and that not so long ago I didn’t have enough appreciation for a tuned model T coil.


Matt

User avatar

david_dewey
Posts: 521
Joined: Sun Jan 06, 2019 12:42 pm
First Name: David
Last Name: Dewey
* REQUIRED* Type and Year of Model Ts owned: 1916 touring, 1925 runaboaut, 1926 Tudor
Location: Oroville, CA
MTFCI Number: 19936
Board Member Since: 1999

Re: A new DIY electronic coil tester.

Post by david_dewey » Sun May 02, 2021 12:24 pm

I wus the guy with the toy train transformer! For the old-fashioned test system, I find it tests the coils with AC, and I can vary the voltage from 6VAC to 15VAC, more of a real-world test than a DC power supply and you can see if the amps changes with voltage--however, the new stuff is way more sophisticated, and I have one of Matt's "Beta units" here. My 'real world' work means it will be a couple of weeks before I can try it out. I do have one suggestion from your demonstration at the meet (and no idea if it is possible)--a larger read out; us old foggies find it hard to see small stuff! :)
It was great talking with you--that meet was really nice! The 5 hour drive each way, not so much! On the way home we stopped at a tourist trap for some Ice Cream (no DeWars in Tulare) and their "Antique Barn" (full of reproduction metal signs and some "old" stuff) had a single modern KW coil on the counter for $10, so I bought it, just for fun.
Oh, Matt had a "pretty good coil" and a "finely tuned coil" to compare on his device. That was really neat! The timing and repeatability between them was very insightful. As Scotty would say, "I'm givin' 'er all she's got Captain!" :)
T'ake care,
David Dewey


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Sun May 02, 2021 6:58 pm

Matt in California wrote:
Fri Apr 09, 2021 1:02 am
.... This week I realized there is no need for the toggle switch! .... Now I just have two SPST buttons. The red one fires the coil the black one is for the capacitance test.
Matt,

I was always concerned about possible back EMF, and affect on leakage/capacitance testing with other things connected, hence preferring (particularly at prototype stage) to mechanically isolate with the switch. It might be worth posting your modified cct for this so people understand what you're doing presently?

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Jun 10, 2021 12:41 pm

David, I think a train transformer at various voltages is a great idea! Please feel free to share your results with the FACT unit I passed on to you.

Luke, When I get a chance I will need to work on making a drawing of how to bypass the toggle switch. But if you look at the PDF of the schematic posted above, I shorted together connections 4,5 and 6 of the SW1. Then I ran connections 1 and 2 to a pushbutton. Along with those changes I updated the hardware. Anyone wanting to do this I can send the software files to. Just send me a PM. Eventually I will have a update on the PCB.

Please see attached user guide.
I hope to hear updates from people testing out the FACT PCB version 1.0.

Matt
Attachments
Model T FACT Adjustment (1).pdf
(12.43 MiB) Downloaded 171 times

User avatar

John Housego
Posts: 30
Joined: Wed Jan 16, 2019 4:44 pm
First Name: John
Last Name: Housego
* REQUIRED* Type and Year of Model Ts owned: 1925 Tourer
Location: Aylesbury Bucks UK
Board Member Since: 2007

Re: A new DIY electronic coil tester.

Post by John Housego » Tue Jul 13, 2021 4:53 am

Hi Matt, I have the new PCB up and running but with issues with capacitor test. I have investigated the software and think I have an old version V0.96. I note in your photos you are using V0.99. Is it possible for you to make the latest software version available? Thanks John (UK)

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Jul 15, 2021 1:59 am

John,
Thanks fore the heads up that I needed to post an updated version of code. I thought I had it posted.

Please try the following code. (I name this file FACT_1_00_v1_0_Board for my reference it means version 1.00 for board version 1.0, but unfortunately I didn't record the changes that I made from the version 0.98 :)

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).
   -----------------------------------------------------------------------------
   Version 0.97 (Matt), 1 Jan 2021

   Made changes for FACT 0.0 PCB including adjusting for aattenuated sign due to filter.
   Changed ideal leakage to >3Mohm
   Added diode voltage to measured the voltage
   -----------------------------------------------------------------------------
   Version 0.98 (Matt), 13 Feb 2021

   Changes on Current Readings
   -----------------------------------------------------------------------------
  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 1.00

// 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 19900.0 // resistor to input supply (20K resistor actual measurement)

//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)) + .76; // diode D2 voltage = .76

  //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, 1); display.println(F(" volts")); // display input voltage
  //display.println(F(".96 OLED OSCILLOSCOPE"));
  display.display();
  /*For testing
  while (1)
    if (digitalRead(swPin)) digitalWrite(outPin, HIGH);
    else digitalWrite(outPin, LOW);
  */
}

//--- 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 > 540)) //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) / 50.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);
    //following with filterering on current sensor levels drop
    // digital value of max current in =592; 5= digital values of current range/#lines = 80/32 = 2.5
    //&&display.drawLine(x + 10 , ((592 - analogVals[x - 1][0])) / 2.5, x + 10 , (592 - (analogVals[x][0])) / 2.5, 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) / 50.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("t="));
  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;
  int i = 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();
  while (swPresentState == HIGH)
    //for (int i = 0; i < 50 ; i++)
  {
    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) / 50.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.setCursor(120, 0); display.print(F(" "));
    display.setCursor(102, 0); 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);
      //following with filterering on current sensor levels drop
      // digital value of max current in =592; 5= digital values of current range/#lines = 80/32 = 2.5
      //&&display.drawLine(x + 10 , ((592 - analogVals[x - 1][0])) / 2.5, x + 10 , (592 - (analogVals[x][0])) / 2.5, WHITE);

    }
    display.display();
    swPresentState = digitalRead(swPin);
    for (int z = 0; z < (10230 - 10 * analogRead(A1)); z++) {
      asm("nop");
    }
  }

  /*
    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 ---//
{
#define leak_min 3000000 //3Mohm leak 
  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)
  long r_val = 120000; // 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 z = 0; z < 30; z++) {
    //display.drawFastHLine(7, z * (32) / 7 + 9, 3, WHITE);
    display.drawFastHLine(10 + z * 4, 16,  1, WHITE);
    display.drawFastHLine(10 + z * 6, 8,  2, WHITE);
    display.drawLine(z * 5 + 10 , ((1360 - analogVals[z * 5 - 1][1])) / 43, z * 5 + 10 , (1360 - (analogVals[z * 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 (25    );
  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 > leak_min && 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");
    display.display();
    return;
  }
  digitalWrite(cap_chg_pin, LOW);


  display.display();
  delay (2000);


  //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 > 3M"));
  //Serial.print (leak);
  display.setCursor(60, 24);
  if (leak > leak_min)  //test if > 3 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();
          swPresentState = HIGH;
          delay(500); //debounce delay
        }
      }
      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?
    }
  }
}
Please feel free to share your experience. I believe that you are the first one to have the PCB manufacture make the boards for you, besides me.

Fun Stuff!

Matt

User avatar

John Housego
Posts: 30
Joined: Wed Jan 16, 2019 4:44 pm
First Name: John
Last Name: Housego
* REQUIRED* Type and Year of Model Ts owned: 1925 Tourer
Location: Aylesbury Bucks UK
Board Member Since: 2007

Re: A new DIY electronic coil tester.

Post by John Housego » Tue Jul 27, 2021 6:04 am

Hi Matt,

Thanks for the latest software. I have my FACT cased now using your PCB design. I ordered blank boards and fitted components myself. I will do a report and pictures of my experience here once I have sorted the final issue which is the capacitor test. With a new good spec capacitor I get a PASS for value but FAIL for leakage with a reading around 400-480 ohms. Checking the hardware I am fairly sure all is OK. Just about to check the software to see if any issues, this may take me some time as I am a bit of a newbi on software.
IMG_20210727_090932.jpg
IMG_20210727_094546.jpg

User avatar

John Housego
Posts: 30
Joined: Wed Jan 16, 2019 4:44 pm
First Name: John
Last Name: Housego
* REQUIRED* Type and Year of Model Ts owned: 1925 Tourer
Location: Aylesbury Bucks UK
Board Member Since: 2007

Re: A new DIY electronic coil tester.

Post by John Housego » Sat Sep 11, 2021 4:02 pm

To follow up on my post above regarding the issue I had with the capacitor test function, this may be of assistance to anyone else attempting this project. I traced the problem to the incorrect 5 volt regulator detailed in the parts list and circuit diagram type CJ7805, this regulator needs 20 volts input to get the required 5 volts output so using 12 volts input, as specified, the 5 volt rail is too low (4.7 volts) giving the issue seen in my photos above. I could not get an equivalent footprint lower input voltage regulator here in the UK so I modified a standard L7805 to fit, this works fine and I now have a working FACT.

John

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Sep 11, 2021 5:47 pm

John,
Congratulations on getting your tester working!!!

I should have commented earlier. Your tester looks great! Your are the first person, that I know of, to order the boards and build your own tester.

Thanks for sharing your issue with the voltage regulator and fix. I have not run into that issue and I don't know why you are running into the issue. I tested my board the regulator should work fine down to 6 volts.

I looked at the data sheet:
https://datasheet.lcsc.com/lcsc/2101111 ... _C9070.pdf
The issue that you saw may be in large acceptable range (4.8-5.2 volts) with 5 volts as the typical value (see data sheet). I must have lucked out with the regulator output closer to 5 volts.

Perhaps this is a issue we may need to deal with in software if parts come in such a wide range of tolerances is creating an issue.

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sun Sep 19, 2021 5:04 pm

I have a few updates to make based on feedback from users.

V2.08 Code Update details
The code is now updated with the following features:
1. Larger OLED Display: Now you can choose in the code between 0.96" (SSD1306) and 1.3" (SH1106) display. See photo for comparison.
5F4F3520-288B-4758-888B-EDB68E3ED2CE.jpeg
2. Test/Mode pushbuttons. This is a move away from a toggle switch. This experience much easier.
3. Bar graph test graphically displays Time-To-Fire results.
4. New pin out for version 2.0 board. I will give an update on this new board soon. You can see it in the photo above.
5. Short circuit detection/protection. If a short on output detected, message is displayed and then power must be cycled. This alone is worth the software upgrade.

V2.8 Code

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
   Using Lukes Code.  Matt from California made changes.
   For more infomation on PCB hardware see:
   https://www.mtfca.com/phpBB3/viewtopic.php?p=180813#p180813

   Added code for .96" OLED.  This code also is set up for graphing current.  Set numReadings = 150 (170 caused trouble).
   -----------------------------------------------------------------------------
   Version 0.97 (Matt), 1 Jan 2021

   Made changes for FACT 0.0 PCB including adjusting for aattenuated sign due to filter.
   Changed ideal leakage to >3Mohm
   Added diode voltage to measured the voltage
   -----------------------------------------------------------------------------
   Version 0.98 (Matt), 13 Feb 2021

   Changes on Current Readings
   -----------------------------------------------------------------------------
   Version 0.99 (Matt), 5 April 2021

   Minor changes in text displayed.
   -----------------------------------------------------------------------------
   Version 1.00 (Matt), 7 April 2021

   Intended for Version 1.0 PCB
   Capacitor Test is now active whenever Cap_test contact is closed.
   This means that the switch should be removed and replace with a push button.
   -----------------------------------------------------------------------------
   Version 2.00 (Matt), 30 June 2021

   Intended for Version 2.0 PCB
   Pinout reconfigered for Version 2.0 PCB
   Changed OLED driver to SH1106 for larger OLED
   Made some veriables more discriptive (but same function)
   -----------------------------------------------------------------------------
   Version 2.02 (Matt), 28 August 2021

   Added live_bar_graph()function to test to display time-to-fire results as bars.
   -----------------------------------------------------------------------------
   Version 2.03 (Matt), 28 August 2021

   Minor changes for pushbottons and function with live_bar_graph()
   -----------------------------------------------------------------------------
   Version 2.04 (Matt), 28 August 2021

   Changes switch functions from capactor test to mode.
   Now you don't have to hold switch for a set amount of time, just change mode.
   -----------------------------------------------------------------------------
   Version 2.06 (Matt), 5 September 2021

   Minor change to cap test to make display time shorter.
   -----------------------------------------------------------------------------
   Version 2.07 (Matt), 6 September 2021

   Deleted unused code for LCD display, serial port and other code used for testing.
   Added code to alert users of short prior to any test.
   -----------------------------------------------------------------------------
   Version 2.08 (Matt), 11 September 2021

   Added compiler directives to switch between Hardware_Version 1.x & 2.x 
   Added compiler directives to switch between OLED SSD1306 or SH1106 dispays
   Edited live_bar_graph function to move bars to 1.7+-.5, 1.8.+-.5, 1.9 +-.5 etc.
   -----------------------------------------------------------------------------
   Pin Connections (for Version 2.0 board, you can adjust as needed)
   Arduino device
   Ground OLED ground
   +5VDC Vcc
   A0 Input to measure power 6-12 VDC (R1 ~10 Kohm A0 to ground, R2 20-30 Kohm to input power)
   A1 NC
   A2 Output to Solid State Switch (MOSFET) to connect where timer connects to coil
   A3 Input for data read from current sensor (5 VDC limit)
   A4 To OLED SDA (if no SDA pin)
   A5 To OLED SCL (if not SCL pin)
   A6 Input for RPM_Set control potentiometer (0-5 VDC)
   A7 Input for Capacitor Test where timer connects to coil (note resistor connects to D4)
   D2 Input Mode/Capacitor Test Pushbutton
   D3 Input Test Pushbutton (other side connected to GND)
   D4 Output Cap Charge Pin (connect to A2 with a resistor 300-500+ Kohms)
   D5 NC
   D6 NC
   D7 NC
   D8 TFT RES
   D9 TFT DC
   D10 TFT CS
   D11 TFT SDA
   D12
   D13 TFT SCL

   The following functions are performed with this code:
   -Single Fire Test- Displays single wafeform and current and time to fire
   -Multifire Test- Displays statistical data of 48 fires
   -Live Oscillosope- Continous single Fire Test
   -Bar Graph Test- 50 tests are placed into differnt bars
   -Capacitor Test

   PLEASE NOTE: The goal is to get a matching set of coils with a time to fire of.
   For example 3.5ms at 6V, and 2ms at 12V.
*/

#define ver 2.08

//****ATTENTION!!!**** CHANGE HARDWARE VERSION TO YOUR CONFIGURATION!!! ****ATTENTION!!!****
#define Hardware_Version 1    // 1= v1.0; 2=v2.0 *This changes pin out
#define Display 1             //1 = SSD1306; 2 = SH1106

#if Hardware_Version == 1
#define Cap_PB_Pin 5      // input pin for cap/coil test switch. Low for cap
#define Test_PB_Pin 8          //input pin for switch, normally high
#define Cap_Charge_Out_Pin 13    //for capacitor test
#define Vin_Measure_Pin A7      //for Input Power Voltage
#define Spark_Out_Pin 7        //output pin to ss relay for coil
#define Current_Measure_Pin A0      //for Input Power Voltage
#define Potentiometer_Pin A1
#define Capacitor_Measurment_Pin A2
#endif

#if Hardware_Version == 2
#define Cap_PB_Pin 2      // input pin for cap/coil test switch. Low for cap
#define Test_PB_Pin 3          //input pin for switch, normally high
#define Cap_Charge_Out_Pin 4    //for capacitor test
//Pin 5 NC
//Pin 6 NC
//Pin 7 NC
#define TFT_RES_Pin 8     //TFT not used
#define TFT_DC_Pin 9
#define TFT_CS_Pin 10
#define TFT_SDA_Pin 11
//Pin 12 NC
#define TFT_SCL_Pin 13
#define Vin_Measure_Pin A0      //for Input Power Voltage
//A1 NC
#define Spark_Out_Pin A2        //output pin to ss relay for coil
#define Current_Measure_Pin A3      //for Input Power Voltage
#define Potentiometer_Pin A6
#define Capacitor_Measurment_Pin A7
#endif

// Include any required OLED libraries


#if Display == 1
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 //OLED Width
#define SCREEN_HEIGHT 32 //OLED Height
#define OLED_RESET    4
#define Configure_Display Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET)
#endif

#if Display == 2 //Using SH1106
#include <Adafruit_SH1106.h>
#define OLED_RESET    4
#define Configure_Display Adafruit_SH1106 display(OLED_RESET)
#endif
Configure_Display;
// END OLED **************************************************************************************************************


//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
#define test_length 25

// voltmeter + resistor divider details
#define R1 10000.0    // resistor to ground
#define R2 20000.0    // resistor to input supply (20K resistor actual measurement)


//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_PB_PinState;
int ttf;  // time to fire
int test_mode = 0;

// 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 Vin_Digital_Max = 512; // set to zero current

//set variables for collect_data function array
unsigned int analogVals[numReadings][2]; // array name & columns
unsigned int test[test_length];
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

void setup()
{
  pinMode(Test_PB_Pin, INPUT_PULLUP); // set the switch pin as input and apply resistor to +5
  pinMode(Spark_Out_Pin, OUTPUT);// define output pin
  pinMode(Cap_Charge_Out_Pin, OUTPUT);// define output pin
  pinMode (Cap_PB_Pin, INPUT_PULLUP);
  sbi(ADCSRA, ADPS2); //more stuff for fast ADC read
  cbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);

  // Determine the input voltage to display
  int Vin_val = analogRead(Vin_Measure_Pin);
  //interim_val = (Vin_val * 5.0) / 1024.0;
  interim_val = (Vin_val * 4.89) / 1023.0;
  input_voltage = interim_val / (R1 / (R1 + R2)) + .75; // diode D2 voltage = .75

  //read potentiometer and set rpm
  rpm = analogRead(Potentiometer_Pin) / 50 * 100 + 500; // perform a read to clear register (comment out if no Potentiometer) units 100 rpm

  // The following for OLED comment if not used

#if Display == 1
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
#endif
#if Display == 2
  display.begin(SH1106_SWITCHCAPVCC, 0x3C);
#endif
  // The header file needs to be changed #define SH1106_128_32 (even though the display maybe 64 height it should be set to 32 because there is no memory to compile 64
  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.print(F("Hardware Version #")); display.print(Hardware_Version); display.println(F(".0"));
  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, 1); display.println(F(" volts")); // display input voltage
  display.display();
}

//--- Function to fire coil once and collect data ---//
void single_fire_data()
{
  Vin_Digital_Max = 512; // set to zero current
  int Vin_Digital_New = 0;
  mVolts = 0.0;
  ttf = 0;
  analogRead(Current_Measure_Pin); // perform a read to clear register
  digitalWrite(Spark_Out_Pin, HIGH); //set Spark_Out_Pin 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(Current_Measure_Pin); // 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(Current_Measure_Pin)) / 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(Current_Measure_Pin)); //take a third reading and average the three (this helps fit on OLED screen)
      analogVals[i][0] = (analogVals[i][0] + analogRead(Current_Measure_Pin)) / 3;
    }
    Vin_Digital_New = analogVals[i][0];
    if (Vin_Digital_New > Vin_Digital_Max && (Vin_Digital_New > 540)) //detect current increasing and write to 'maxval'
    {
      Vin_Digital_Max = Vin_Digital_New;
      ttf = analogVals[i][1];
    }
  }

  digitalWrite(Spark_Out_Pin, LOW); // reset Spark_Out_Pin to low and turn off power to coil
}

void single_test()
{
  single_fire_data();
  // uncomment two lines for ACS712
  mVolts = (Vin_Digital_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) / 50.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(F("0"));
  display.setCursor(0, 8);
  display.println(F("5"));

  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(F("TTF="));
  display.print(float(ttf) / 1000.00);
  display.print(F("ms "));
  display.print(F("Imax="));
  display.print(amps);
  display.println(F("A"));
  display.display();
}

//--- 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] = Vin_Digital_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
  {
    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) / 50.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;
    }
  }
  for (byte i = discard; i < numTests; i++) // get results from each test and print
  {
    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("t="));
  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
}

//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;
  int i = 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");
  display.setTextColor(WHITE, BLACK);
  display.drawFastHLine(10, 31,  128 - 10, WHITE);
  display.drawFastVLine(10, 8,  32, WHITE);
  RPM_time_old = micros();
  while (digitalRead(Test_PB_Pin))//Run until test pin pressed
    //for (int i = 0; i < 50 ; i++)
  {
    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 = (Vin_Digital_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) / 50.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);

    // 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.setCursor(120, 0); display.print(F(" "));
    display.setCursor(102, 0); 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);
      //following with filterering on current sensor levels drop
      // digital value of max current in =592; 5= digital values of current range/#lines = 80/32 = 2.5
      //&&display.drawLine(x + 10 , ((592 - analogVals[x - 1][0])) / 2.5, x + 10 , (592 - (analogVals[x][0])) / 2.5, WHITE);

    }
    display.display();
    swPresentState = digitalRead(Test_PB_Pin);
    for (int z = 0; z < (10230 - 10 * analogRead(Potentiometer_Pin)); z++) {
      asm("nop");
    }
  }
  while (!digitalRead(Test_PB_Pin)); //do nothing until test pin released
}

//the following function makes a bar graph of the time-to-fire results
void live_bar_graph()
{
  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;
  int i = 0;
  int ttf_bars = 0;
  mVolts = 0.0;
  for (int y = 0; y < 50; y++)
  {
    test[y] = 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 < 11; x++) {
    display.drawFastVLine(x * 10 + 19, 29, 3, WHITE);
  }
  for (int x = 0; x < 6; x++) {
    display.drawFastVLine(69, x * 4 + 10, 2, WHITE);
  }
  display.setTextColor(WHITE, BLACK);
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.drawFastHLine(10, 31,  128 - 10, WHITE);
  display.drawFastVLine(10, 8,  32, WHITE);
  RPM_time_old = micros();
  while (i < 50)
    //for (int i = 0; i < 50 ; i++)
  {
    i++;
    if (!digitalRead(Test_PB_Pin)) {
      i = 50; //end function if button pressed
    }
    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 = (Vin_Digital_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) / 50.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);

    // 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.setCursor(120, 0); display.print(F(" "));
    display.setCursor(102, 0); display.println(RPM_live);
    display.setCursor(108, 7);   display.print(F("rpm"));

    if (ttf / 100 < test_length)
    {
      ttf_bars = (ttf - 1350) / 100; //shift the window over 1350 ms, each bar is 100 ms wide
      test[ttf_bars] = test[ttf_bars] + 1;
      //display.drawLine(ttf_bars*2 , 31-test[ttf_bars], ttf_bars*2+1 , 31-test[ttf_bars], WHITE);
      display.drawFastHLine(ttf_bars * 10 + 5, 31 - test[ttf_bars] / 2,  9, WHITE);
      display.display();
    }
    swPresentState = digitalRead(Test_PB_Pin);
    for (int z = 0; z < (10230 - 10 * analogRead(Potentiometer_Pin)); z++) {
      asm("nop");
    }
  }
  while (!digitalRead(Test_PB_Pin)); //wait until button is released

}

void cap_test()
//--- Function to check capacitor value and resistance ---//
{
#define leak_min 3000000 //3Mohm leak 
  unsigned long new_time = 0;
  mVolts = 0;
  int cap_time = 0;
  int r_volts = 0;
  long r_val = 120000; // 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_Charge_Out_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();

  delay (90); //ensure the cap is discharged via charge pin low
  digitalWrite(Cap_Charge_Out_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 (Capacitor_Measurment_Pin);  //use analog pin A7 to read volts across unknown cap

    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));
    }
    while (micros() - new_time < sample_time); //delay time

  }
  display.clearDisplay();
  // draw the axis, lables and tick marks
  //draw 63% line
  for (int z = 0; z < 30; z++) {
    //display.drawFastHLine(7, z * (32) / 7 + 9, 3, WHITE);
    display.drawFastHLine(10 + z * 4, 16,  1, WHITE);
    display.drawFastHLine(10 + z * 6, 8,  2, WHITE);
    display.drawLine(z * 5 + 10 , ((1360 - analogVals[z * 5 - 1][1])) / 43, z * 5 + 10 , (1360 - (analogVals[z * 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 > leak_min && 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(F("Capacitor Shorted"));
    display.setCursor(20, 20);
    display.println(F("Please open points"));
    digitalWrite(Cap_Charge_Out_Pin, LOW);
    display.display();
    return; //end test here if shorted
  }
  digitalWrite(Cap_Charge_Out_Pin, LOW);


  display.display();
  delay (3000);


  //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"));

  if (cap_val > 0.4 && cap_val < 0.6)
  {
    //OLED Display comment out
    display.setCursor(0, 24);
    display.println(F(" PASS uF; "));
  }
  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; "));
  }
  display.setCursor(0, 16); display.print(leak / 1000); display.println(F(" Kohm Ideal > 3M"));
  display.setCursor(60, 24);
  if (leak > leak_min)  //test if > 3 Mohms
  {
    display.println(F("PASS ohm"));
  }
  else
  {
    display.setTextColor(BLACK, WHITE); display.print(F(" FAIL ")); display.setTextColor(WHITE, BLACK); display.println(F("ohm"));
  }
  display.setTextColor(BLACK, WHITE);
  display.setCursor(90, 0);
  display.display();
  digitalWrite(Cap_Charge_Out_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(Potentiometer_Pin) / 50 * 100 + 500; // perform a read to clear register (comment out if no Potentiometer) units 100 rpm
  Cap_PB_PinState = digitalRead(Cap_PB_Pin);
  if (Cap_PB_PinState == HIGH && !digitalRead(Test_PB_Pin))
  {
    digitalWrite(Spark_Out_Pin, HIGH); // check for short
    //delay (1); //wait
    delayMicroseconds(50); //delay for current to ramp up
    Vin_Digital_Max = analogRead(Current_Measure_Pin);
    digitalWrite(Spark_Out_Pin, LOW); //set Spark_Out_Pin low
    mVolts = (Vin_Digital_Max / 1024.0) * 5000.0; // raw analog read val to millvolts
    amps = ((mVolts - 2500.0) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
    if (amps > 3) { //Three amps in 50 microseconds is the threshold to be considered a short
      display.clearDisplay();
      display.setTextColor(WHITE, BLACK);
      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println(F("OUTPUT SHORTED!!!"));
      display.println(F("-Verify Setup"));
      display.println(F("-Cycle power to reset"));
      display.display();
      while (1); //Hang program until short dealt with- power must be cycled to restart
    }
    while (!digitalRead(Test_PB_Pin));  //Do nothing until test pin released
    switch (test_mode) {
      case 0: {
          single_test();
          break;
        }
      case 1: {
          live_o_scope();
          break;
        }
      case 2: {
          live_bar_graph();
          break;
        }
      case 3: {
          multi_test();
          break;
        }
      case 4: {
          cap_test();
          break;
        }
    }

  }
  if (Cap_PB_PinState == LOW)
  {
    if (test_mode < 4) {
      test_mode = test_mode + 1;
    }
    else {
      test_mode = 0;
    }
    display.clearDisplay();
    display.setTextColor(WHITE, BLACK);
    display.setTextSize(1);
    display.setCursor(0, 0);
    switch (test_mode) {
      case 0: {
          display.println(F("SINGLE FIRE TEST"));
          break;
        }
      case 1: {
          display.println(F("LIVE OSCILLOSCOPE"));
          break;
        }
      case 2: {
          display.println(F("BAR GRAPH TEST"));
          break;
        }
      case 3: {
          display.println(F("MULTIFIRE TEST"));
          break;
        }
      case 4: {
          display.println(F("CAPACITOR TEST"));
          break;
        }
    }
    display.setCursor(0, 12);
    display.println(F(" Press Test Button"));
    display.println(F("      To Start"));
    display.display();// now that the display buffer is built, display it
    while (!digitalRead(Cap_PB_Pin));
    delay(100); //delay for switch debounce
  }
}
You are free to use/change this as stated under the the GNU General Public Licence (https://www.gnu.org/licenses/gpl-3.0.html)

Suggested Hardware Update
Here are the suggested hardware changes for two push buttons. (As an option, you can use the switch to change mode as well.)
FACT V1.0 with pins highlighted.JPG
Solder three connections together under purple line. Add mode pushbotton as shown.
D0CA2BF4-86AD-417D-A1BC-618648D18D46.jpeg
If you don't want to do the hardware change you will either not be able to do the capacitor test or you could change the code.

Matt


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Wed Sep 29, 2021 4:59 am

I've been following this project since about June ...I mess around with electronics some, mostly tube stuff, I'm a complete newbie to Arduino. I bought some Arduino parts and started putting it together... it didn't work at all... gave up for a while. bought a couple different parts, read some and watched some Arduino tutorials. finally got on it tonight and it came to life! Although something is off with the ramp/ single fire test... like it needs a vertical adjust to bring it down into view. Amperage reads high too, around 9 Amps. Time to fire seems to work, I adjusted the coils I've been running on for years down to under 2 MS ran out to the garage and put them back in and the engine is noticeably running better just with that.


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Wed Sep 29, 2021 4:17 pm

Tony,

Good to read that you've successfully built your own tester - well done!

I wonder what the current sensor is that you're using? It may be that it's a lower current version you have (5A), which could give the results you're experiencing.

Let us know, although you'd be better off with the 'correct' unit it's easy to modify the code to suit the sensor you (may) have.


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Wed Sep 29, 2021 4:36 pm

I have another current sensor, I’m pretty sure they were both 20 amp… I’ll switch it out and see what happens then maybe try to figure out the adjustments in the code…


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Thu Sep 30, 2021 3:38 pm

Tony,

You'll see in the code a couple of lines that read:

//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

The '//' makes the line a comment, which means it's not compiled. If you wanted you could simply put a '//' in front of the 20A line, and remove it from the 5A line, then re-compile into the Arduino and test that to see what you get.

It may not be the the issue of course (I'd also check all the ACS712 connections, and all the grounds etc) but it's a simple thing to do, and it may assist you in being more familiar with the code and how to make adjustments. You'll see that this line simply changes the division of the read sensor voltage and provides a result in 'amps' for later use in the code.


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Sat Oct 02, 2021 9:12 pm

Luke wrote:
Thu Sep 30, 2021 3:38 pm
Tony,

You'll see in the code a couple of lines that read:

//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

The '//' makes the line a comment, which means it's not compiled. If you wanted you could simply put a '//' in front of the 20A line, and remove it from the 5A line, then re-compile into the Arduino and test that to see what you get.

It may not be the the issue of course (I'd also check all the ACS712 connections, and all the grounds etc) but it's a simple thing to do, and it may assist you in being more familiar with the code and how to make adjustments. You'll see that this line simply changes the division of the read sensor voltage and provides a result in 'amps' for later use in the code.
OK I figured out the Amp censer setting and found I made a wrong connection. So now I have a display, it's not quite the ramp I'm seeing on here but I can see a double spark and adjust it out. Now I have to work on that spark messing with the board... It burned one up on me today...

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Oct 02, 2021 9:24 pm

Tony,
Great to hear that things are moving along for you! It is an accomplishment to get things working. You mention not having a clean ramp. Assuming that the capacitor is okay... And the contacts/cushion spring is clean. It may be your power source or wires. I had issues when the wires were too thin.

When I built the first tester and dealt with the wiring mess I told myself that never again would I do that so I designed the Printed Circuit Board (PCB). I have had virtually no issues with electrical interference after using the PCB. It is not magic, just short connections and inductors.

I would like to send you the PCB FACT. Please message me with your address. All I would like in return is you keep posting your progress.

Learning together,

Matt


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Mon Dec 06, 2021 4:42 pm

Wow thanks that would be great! PM sent... Sorry I've been MIA for a while life's been busy...


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Tue Dec 28, 2021 12:03 pm

IMG_4576 (2).JPG
IMG_4575.JPG
I doubt there's anything electronic wise I could do to improve this brilliant device so I'm going to put it into the fanciest box I can think of. I've always like the look of the old Jefferson coil testers but would likely never buy one since most are way to expensive and not really useful. I drug out some Mahogany from my garage today and started in on a FACT/Jefferson style box... I'll build a spark gap and maybe a cradle for a spark plug on the front and mount the board inside with a window to see the screen.
IMG_4578.JPG
Progress by the end of the day...
IMG_4581 (2).JPG
Turned a bronze bezel and temporarily mounted the board inside...
IMG_4584 (2).JPG
Ready for testing coils!
Last edited by Tonytiger75 on Thu Dec 30, 2021 5:39 pm, edited 3 times in total.

User avatar

John Housego
Posts: 30
Joined: Wed Jan 16, 2019 4:44 pm
First Name: John
Last Name: Housego
* REQUIRED* Type and Year of Model Ts owned: 1925 Tourer
Location: Aylesbury Bucks UK
Board Member Since: 2007

Re: A new DIY electronic coil tester.

Post by John Housego » Tue Dec 28, 2021 2:52 pm

Like the case Tony very nice design. John

User avatar

BE_ZERO_BE
Posts: 541
Joined: Sun Jan 06, 2019 12:27 pm
First Name: BOB
Last Name: CASCISA
* REQUIRED* Type and Year of Model Ts owned: 1916 TOURING
Location: POULSBO, WA
MTFCA Number: 16897
MTFCI Number: 16628

Re: A new DIY electronic coil tester.

Post by BE_ZERO_BE » Tue Dec 28, 2021 4:22 pm

 
It looks familiar Tony :)

 
Jefferson Tertr Ad.jpg
Respectfully Submitted,
Be_Zero_Be

I drive a Model T ... Microseconds don't matter :D

For every Absolute Model T Fact there are at least three exceptions.


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Tue Dec 28, 2021 8:25 pm

BE_ZERO_BE Yes that is the gizmo I'm patterning mine after.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Mon Jan 03, 2022 10:16 pm

Tony!
Wow! Great job on the box! I like the vintage look. Interesting way to make the extension on the switches. Alternatively, you could add wires to push buttons.

I am sure if you were willing to make more of those boxes, people would be interested me being the first!

Matt


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Mon Jan 10, 2022 5:29 pm

Yes I had thought of desoldering the push buttons but ended up making brass pushers that reach inside, there's a small length of sheet steel I riveted to the ends with a hole and guide wire to keep the pushers lined up with the board. I have a miniature 100K POT I was thinking of using for an external RPM control but for now I'm happy with it and my coils are buzzing along happily.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Mon Feb 28, 2022 1:08 am

I added an adjustable DC to DC power supply to the tester and connected it to a 18.5 VDC old laptop power supply.
FACT test unit.jpg
I now could take raw data from 7 to 16 VDC. (I tested many different coils and points from various manufactures and eras.)
Raw data.JPG
And this graph shows the Peak Current. (I found this useful for coils that varied greatly from average or didn't have a linear trend.)
Peak Amps.JPG
This is a graph of the Time-to-Fire data.
Time-To-Fire.JPG
Important to note is that I tuned the coils at 12 VDC for around 1.90 msec Time-to-Fire. It is clear from the data that even with this tuning the coils at one point (i.e. 12 VDC) the coils can vary. So on magneto they will not have the same time to fire. As I tuned more coils I have learned a two point tuning method by both adjusting the main vibrator spring and the cushion spring.

For reference at about 1600 RPM the crankshaft spins 10 degrees per millisecond or .1 millisecond is 1 degree. You can use that info to see the impact of .1, .2 or .3 millisecond variation would yield 1, 2 or 3 degree variation in time-to-fire. I believe that from this data one would want to find a set of coils that preformed the similar over the span of voltages.

Thoughts? Questions?

Matt


Tom_Carnegie
Posts: 71
Joined: Mon Jan 07, 2019 6:17 pm
First Name: Tom
Last Name: Carnegie
* REQUIRED* Type and Year of Model Ts owned: Many
Location: Spokane Valley, WA
MTFCA Number: 14685

Re: A new DIY electronic coil tester.

Post by Tom_Carnegie » Mon Feb 28, 2022 10:08 am

If you set the coils to 1.9 ms at 12V, why didn't the graphs for time to fire converge at 12V? How many times did you run this test? In other words, is this an average of several tests on each coil, or one shot on each coil? An interesting test, but I'm not sure what it shows.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Tue Mar 01, 2022 1:18 am

Tom,
Good points!

I am in the process of figuring out what the raw data means. Some coils are better set-up, tuned and tested then others. Here are the graphs showing only coils that are set to 1.89-1.91 ms at 12 VDC:
Time-To-Fire 2.JPG
Each data point represents an average time-to-fire at a given voltage. Just for verification I picked up a coil that I tested a few weeks ago and tested it again. The results are virtually the same within plus or minus one or two hundredth millisecond at any given voltage.

In the process of testing I believe that I discovered the following:
  • Two point testing needed- if you really want a tuned set of coils you should tune it at two places adjusting both springs. Some coils in the graph I show here I worked harder than others to get them to match. I used the lower voltage (i.e 7 VDC) as the second voltage. [I would imagine that making the second point higher may be ideal higher speed endurance runs.] Other coils I left as is just to show how much variation there is if the second point is not adjusted for.
  • Limit to adjustment- each coil can be adjusted to one point (i.e. 1.9 ms @12 VDC), but there seems to be a limit of adjustment when adjusting for a second point. This takes some going back and forth because one spring adjustment impacts the original adjustment.
  • Coil/points manufacture/era not important- as far as I can tell there was no difference in coils or points for variation based on manufacture. I believe I could have a totally mixed set of coils (i.e. Ford, KW old and KW new) and a totally mixed set of points (i.e. Ford, KW old, KW steel, KW new, Kingston steel, Shurhit, other) and adjust them with about the same results, but this may require picking from more than a set of four coils or changing the points.
  • Adjustable power supply on the tester is a good idea- for people who really want to have a maximum tuning experience.

I look forward to reading peoples comments.

Matt


Poppie
Posts: 175
Joined: Sun Jan 06, 2019 7:33 pm
First Name: Neil
Last Name: Martin
* REQUIRED* Type and Year of Model Ts owned: 11 tourer 18 tourer 18 TT
Location: Sydney Australia

Re: A new DIY electronic coil tester.

Post by Poppie » Tue Mar 01, 2022 6:24 am

Great work Matt with your electronic skills but I think you are wasting your time with Model T coils using DC as a set up voltage even though you can pulse and vary the potential difference of the source,
Try using a HCCT and the point of fire Method (try for TDC) and with the Three adjustments, adjusting the Bridge contact, the vibrating contact and the cushion spring at a current range around 1.3 plus or minus .3 AMPS you could find that all coils will fire spot on. This method uses the rise and fall of the magneto voltage, that is, the potential difference on the minus to plus cycle then plus to minus cycle of the magneto.
With DC, your coils would/could need re adjusting each time the running voltage is changed such as, generator charging voltage, start on battery then run on mag where the voltage changes all the time, also the ttf method relies on the timer accuracy and contact condition
With HCCT, the starting and running is the same and the timer turns on the power to the firing coil and the pre set magneto voltage fires the coil. My observations....n.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Wed Mar 02, 2022 1:58 am

Interesting comment Neil!

If I understand you correctly, you use a method of tuning coils where you can adjust a set of coils to all fire in perfect synchronization from 500 to 2500 RPM.

Matt


Poppie
Posts: 175
Joined: Sun Jan 06, 2019 7:33 pm
First Name: Neil
Last Name: Martin
* REQUIRED* Type and Year of Model Ts owned: 11 tourer 18 tourer 18 TT
Location: Sydney Australia

Re: A new DIY electronic coil tester.

Post by Poppie » Wed Mar 02, 2022 7:58 am

Matt,
I use a KRW HCCT and if I motorised it I would be game to take it up to say 1000rpm but I cannot see any need to do that. If my memory is correct, 65years ago at Trade school I seem to remember that electricity travels at the speed if light, 186,000 miles/second so why would the timing change ,and the mechanical points should work to at least the 2500 RPM mark.
My experience in coil testing showed me that the point of fire varies with Hcct RPMs. It was brought to my notice in the 1970s when a friend complained about a T coil he had on a single cyl buggy would retarded as his speed increased, at that time my HCCT was a 1923 T block,crank,flywheel and magneto coil set and that taught me a lot, I adjusted out his problem. It was a cheap as chips set up. In the 90s I was lucky enough to score a K R Wilson HCCT and I set it up like my 23block, Each serviced coil set, usually of 5 coils are set as described as before, the spare coil goes under the rear seat.
I have only once checked 4 adjusted T coils on a friends ECCT and (for memory) they ALL showed a 2 led(I assume degree) retard and I was not willing the belt the spring tension up to increase primary current draw, My coils are set to a piston point to fire I try for TDC, not a time to fire where the accuracy of the timer comes into play. My family runs 4 model Ts and 3 x 2cyls odd bods with no coil problems.
Matt, I am not an electronic electrician so I cannot understand Yours, MKs,and Lukes coil testing works programme using DC when the Model ignition coil was designed to operate on AC, and I cannot see how you can adjust out the timing error of different make/age and specifications of coils using a set single voltage DC system. At my age a 5 to 6 hundred Aust $ instrument is not worth it just to check my coil adjustments ..I hope this answers your question....n.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Thu Mar 24, 2022 12:54 am

Neil,
If I understand your response, you know that the point of fire (i.e. time-to-fire) decreases with an increase to RPM. The increase time-to-fire is because the voltage out of the magneto increases with RPM.

The point of sharing the response of different coils to with varying voltage pulses is to show that as the engine RPM fluctuates a set of coil may diverge. For the average Model T driver I this is not an issue. But for people like Tom Carnegie, who responded to my original post, it is very important. To drive a Model T engine at 80+ KPH for 800 Kilometers in three days the coils need to be a carefully matched set.

This tester cost less than $30. In other words just the capacitor test function pays for it's self. It may not be as cheap as your first tester. If I understand correctly your first tester was a Model T engine you acquired for free. I really love the idea of using an old engine to test coils, but the FACT tester is portable and weighs almost nothing.

I hope this clarifies things.

Matt


Corynick
Posts: 2
Joined: Mon Apr 04, 2022 1:26 pm
First Name: Cory
Last Name: Nickerson
Location: Lockeport, NS

Re: A new DIY electronic coil tester.

Post by Corynick » Wed Apr 06, 2022 9:35 pm

This thread is simply wonderful!

Are the files for the second PCB version available somewhere?

Thanks!

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Mon May 30, 2022 7:13 pm

Please see the updated instruction manual.
Model T FACT Adjustment 3_04.pdf
(1.55 MiB) Downloaded 70 times

Here is the latest version of the code. Version 3.04. There are a lot of changes, but the main thing is that this is comparable earlier hardware versions, .96 or 1.3 OLED displays, Arduino Nano and Arduino Nano Every. The correct settings need to be chosen at the top of the code so the compiler directives to activated the correct code.

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
   Using Lukes Code.  Matt from California made changes.
   For more infomation on PCB hardware see:
   https://www.mtfca.com/phpBB3/viewtopic.php?p=180813#p180813

   Added code for .96" OLED.  This code also is set up for graphing current.  Set numReadings = 150 (170 caused trouble).
   -----------------------------------------------------------------------------
   Version 0.97 (Matt), 1 Jan 2021

   Made changes for FACT 0.0 PCB including adjusting for aattenuated sign due to filter.
   Changed ideal leakage to >3Mohm
   Added diode voltage to measured the voltage
   -----------------------------------------------------------------------------
   Version 0.98 (Matt), 13 Feb 2021

   Changes on Current Readings
   -----------------------------------------------------------------------------
   Version 0.99 (Matt), 5 April 2021

   Minor changes in text displayed.
   -----------------------------------------------------------------------------
   Version 1.00 (Matt), 7 April 2021

   Intended for Version 1.0 PCB
   Capacitor Test is now active whenever Cap_test contact is closed.
   This means that the switch should be removed and replace with a push button.
   -----------------------------------------------------------------------------
   Version 2.00 (Matt), 30 June 2021

   Intended for Version 2.0 PCB
   Pinout reconfigered for Version 2.0 PCB
   Changed OLED driver to SH1106 for larger OLED
   Made some veriables more discriptive (but same function)
   -----------------------------------------------------------------------------
   Version 2.02 (Matt), 28 August 2021

   Added live_bar_graph()function to test to display time-to-fire results as bars.
   -----------------------------------------------------------------------------
   Version 2.03 (Matt), 28 August 2021

   Minor changes for pushbottons and function with live_bar_graph()
   -----------------------------------------------------------------------------
   Version 2.04 (Matt), 28 August 2021

   Changes switch functions from capactor test to mode.
   Now you don't have to hold switch for a set amount of time, just change mode.
   -----------------------------------------------------------------------------
   Version 2.06 (Matt), 5 September 2021

   Minor change to cap test to make display time shorter.
   -----------------------------------------------------------------------------
   Version 2.07 (Matt), 6 September 2021

   Deleted unused code for LCD display, serial port and other code used for testing.
   Added code to alert users of short prior to any test.
   -----------------------------------------------------------------------------
   Version 2.08 (Matt), 11 September 2021

   Added compiler directives to switch between Hardware_Version 1.x & 2.x
   Added compiler directives to switch between OLED SSD1306 or SH1106 dispays
   Edited live_bar_graph function to move bars to 1.7+-.5, 1.8.+-.5, 1.9 +-.5 etc.
   -----------------------------------------------------------------------------
   Version 2.09 (Matt), 25 September 2021

   Improved switch debounce.
   -----------------------------------------------------------------------------
   Version 2.10 (Matt), 10 October 2021

   Adjust center point of bars or rpm adjust
   -----------------------------------------------------------------------------
   Version 2.11 (Matt), 10 October 2021

   Pot for RPM adjustment
   -----------------------------------------------------------------------------
   Version 2.12 (Matt), 13 October 2021

   Changes to speed up capacitor test-fast_cap_test();
   Also changes for debounce
   -----------------------------------------------------------------------------
   Version 2.13 (Matt), 24 October 2021

   Changes to pb debounce functions and to get out of Capacitor Test easier
   -----------------------------------------------------------------------------
   Version 2.14 (Matt), 24 November 2021

   Changes for using Nano 33 IOT
   -----------------------------------------------------------------------------
   Version 2.15 (Matt), 23 December 2021

   Changes for 3.3 volt board
   -----------------------------------------------------------------------------
   Version 2.16 (Matt), 25 December 2021

   Added Read_Current()routine
   Added delay on reading input voltage
   Changed single_fire_data() using delay
   -----------------------------------------------------------------------------
   Version 3.00 (Matt), 25 March 2022

   Major changes made to acommidated SH110X driver
   To use 32x128 made arrays byte instead of int.  This required major changes...
   Removed Read_Current()routine
   Added functions
      -----------------------------------------------------------------------------
   Version 3.01 (Matt), 15 April 2022

   Fixed issue with selecting Hardware Version

   -----------------------------------------------------------------------------
   Version 3.02 (Matt), 21 April 2022

   Fixed issue with selecting Hardware Version

   -----------------------------------------------------------------------------
   Version 3.03 (Matt), 13 March 2022

   Improved compatibility with Arduino Nano Every and Nano IOT 33

   -----------------------------------------------------------------------------
   Version 3.04 (Matt), 13 March 2022

   Improved compatibility with Arduino Nano Every
   fixed error in single_fire_data()

   -----------------------------------------------------------------------------
   Pin Connections (for Version 2.0 board, you can adjust as needed)
   Arduino device
   Ground OLED ground
   +5VDC Vcc
   A0 Input to measure power 6-12 VDC (R1 ~10 Kohm A0 to ground, R2 20-30 Kohm to input power)
   A1 NC
   A2 Output to Solid State Switch (MOSFET) to connect where timer connects to coil
   A3 Input for data read from current sensor (5 VDC limit)
   A4 To OLED SDA (if no SDA pin)
   A5 To OLED SCL (if not SCL pin)
   A6 Input for RPM_Set control potentiometer (0-5 VDC)
   A7 Input for Capacitor Test where timer connects to coil (note resistor connects to D4)
   D2 Input Mode/Capacitor Test Pushbutton
   D3 Input Test Pushbutton (other side connected to GND)
   D4 Output Cap Charge Pin (connect to A2 with a resistor 300-500+ Kohms)
   D5 NC
   D6 NC
   D7 NC
   D8 TFT RES
   D9 TFT DC
   D10 TFT CS
   D11 TFT SDA
   D12
   D13 TFT SCL

   The following functions are performed with this code:
   -Single Fire Test- Displays single wafeform and current and time to fire
   -Multifire Test- Displays statistical data of 48 fires
   -Live Oscillosope- Continous single Fire Test
   -Bar Graph Test- 50 tests are placed into differnt bars
   -Capacitor Test

   PLEASE NOTE: The goal is to get a matching set of coils with a time to fire of.
   For example 3.5ms at 6V, and 2ms at 12V.
*/

#define ver 3.04

//****ATTENTION!!!**** CHANGE HARDWARE VERSION TO YOUR CONFIGURATION!!! ****ATTENTION!!!****
#define Hardware_Version 3       // 1= v1.0x; 2=v2.0x; 3=v3.0x *This changes pin out
#define Display 2                //1 = SSD1306; 2 = SH1106
#define Bar_Graph_Adjustment 2   // 1 = RPM adjustable; 2 = Center of bars adjustable with potentiometer 
#define Micro_Processor 2        // 1 = ATmega328; 2 = ATMega4809(Nano Every); 3 = SAMD21 (Nano 33)

#if Micro_Processor == 1||2
#define Vin 5000 // 5 volts
#endif

#if Micro_Processor == 3
#define Vin 3300 //3.3 volts
#endif

#if Hardware_Version == 1
#define Cap_PB_Pin 5      // input pin for cap/coil test switch. Low for cap
#define Test_PB_Pin 8          //input pin for switch, normally high
#define Cap_Charge_Out_Pin 13    //for capacitor test
#define Vin_Measure_Pin A7      //for Input Power Voltage
#define Spark_Out_Pin 7        //output pin to ss relay for coil
#define Current_Measure_Pin A0      //for Input Power Voltage
#define Potentiometer_Pin A1
#define Capacitor_Measurment_Pin A2
#endif

#if Hardware_Version != 1
#define Cap_PB_Pin 2      // input pin for cap/coil test switch. Low for cap
#define Test_PB_Pin 3          //input pin for switch, normally high
#define Cap_Charge_Out_Pin 4    //for capacitor test
//Pin 5 NC
//Pin 6 NC
//Pin 7 NC
#define TFT_RES_Pin 8     //TFT not used
#define TFT_DC_Pin 9
#define TFT_CS_Pin 10
#define TFT_SDA_Pin 11
//Pin 12 NC
#define TFT_SCL_Pin 13
#define Vin_Measure_Pin A0      //for Input Power Voltage
//A1 NC
#define Spark_Out_Pin A2        //output pin to ss relay for coil
#define Current_Measure_Pin A3      //for Input Power Voltage
#define Potentiometer_Pin A6
#define Capacitor_Measurment_Pin A7
#endif

// Include any required OLED libraries

#if Display == 1
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 //OLED Width
#define SCREEN_HEIGHT 64 //OLED Height
#define OLED_RESET    4
#define BLACK1 BLACK
#define WHITE1 WHITE
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);;
#endif

#if Display == 2  //Using SH1106 with Arduino Nano or Arduino Nano Every

//#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
#define SCREEN_WIDTH 128 //OLED Width
#define SCREEN_HEIGHT 64 //OLED Height
#define OLED_RESET    -1
#define WHITE1 SH110X_WHITE
#define BLACK1 SH110X_BLACK
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#endif

// END OLED **************************************************************************************************************

//setup for fast ADC read for ATmega328
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#define NOP __asm__ __volatile__ ("nop\n\t") //use for short delay

#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
#define test_length 25

// voltmeter + resistor divider details
#if Hardware_Version < 3
#define R3 10000.0    // resistor to ground
#endif
#if Hardware_Version == 3
#define R3 1000.0    // resistor to ground
#endif
#define R2 20000.0    // resistor to input supply (20K resistor actual measurement)


//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 Mode_PB_PinState;
boolean Test_PB_PinState;
float ttf;  // time to fire
int test_mode = 0;

// 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 Vin_Digital_Max = 512; // set to zero current

//set variables for collect_data function array
byte analogVals[numReadings][2]; // array name & columns
byte test[test_length];
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

void setup()
{
  pinMode(Test_PB_Pin, INPUT_PULLUP); // set the switch pin as input and apply resistor to +5
  pinMode(Spark_Out_Pin, OUTPUT);// define output pin
  pinMode(Cap_Charge_Out_Pin, OUTPUT);// define output pin
  pinMode(Cap_PB_Pin, INPUT_PULLUP);

#if Micro_Processor == 1
  sbi(ADCSRA, ADPS2); //more stuff for fast ADC read (ATmega328)
  cbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);
#endif
#if Micro_Processor == 2
  //ADC0_CTRLC = 0x54; // reduced cap, Vdd ref, 32 prescaler (ATega4809)
  ADC0_CTRLC = 0x53; // reduced cap, Vdd ref, 16 prescaler(ATega4809)
#endif
#if Micro_Processor == 3//Using Nano 33 IOT

  analogReadResolution(10);
#endif
  delay (1500); //give time delay to let input voltage stabilize
  // Determine the input voltage to display
  int Vin_val = analogRead(Vin_Measure_Pin);//read now some reason this makes second readding correct
  interim_val = (analogRead(Vin_Measure_Pin) * Vin / 1000) / 1023.0;
  input_voltage = interim_val  * ((R2 + R3) / R3) + .75; // diode D2 voltage = .75
  //input_voltage = analogRead(Vin_Measure_Pin);//show  raw value
  //read potentiometer and set rpm
  rpm = analogRead(Potentiometer_Pin) / 50 * 100 + 500; // perform a read to clear register (comment out if no Potentiometer) units 100 rpm

  // The following for OLED comment if not used

#if Display == 1
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
#endif

#if Display == 2 && Micro_Processor == 1 || 2 //Using SH1106 with Nano
  //display.begin(SH1106_SWITCHCAPVCC, 0x3C);
  delay(250); // wait for the OLED to power up
  display.begin(i2c_Address, true); // Address 0x3C default
#endif

#if Display == 2 && Micro_Processor == 3//Using SH1106 With Nano 33 IOT
  display.begin(i2c_Address, true); // Address 0x3C default
#endif
  // The header file needs to be changed #define SH1106_128_32 (even though the display maybe 64 height it should be set to 32 because there is no memory to compile 64
  display.clearDisplay();
  display.setTextColor(WHITE1, BLACK1);        // Draw white text
  display.setCursor(0, 0);
  display.setTextSize(2);             // Draw 2X-scale text
  display.println(F("FACT"));
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.println(F("Model T Coil Tester"));
  display.println(F(" "));
  display.setTextSize(2);             // Draw 2X-scale text
  display.print(F("Vin=")); display.print (input_voltage, 1); display.println(F(" V")); // display input voltage
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.print(F("Software Ver ")); display.println (ver);
  display.print(F("Hardware Ver ")); display.print(Hardware_Version); display.println(F(".0"));
  //display.setTextSize(1);             // Normal 1:1 pixel scale
  display.display();
  //delay (1500);
}

//--- Function to fire coil once and collect data ---//
void single_fire_data()
{

#if Micro_Processor == 1
  int delay_time = 17;
#endif
#if Micro_Processor == 2
  int delay_time = 0;
#endif
  Vin_Digital_Max = 0; // set to zero current
  int Vin_Digital_New = 0;
  int raw_measurement;
  byte ADCregOriginal;
  mVolts = 0.0;
  ttf = 0;
  analogRead(Current_Measure_Pin); // perform a read to clear register
  digitalWrite(Spark_Out_Pin, HIGH); //set Spark_Out_Pin 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
  {
    raw_measurement = analogRead(Current_Measure_Pin);

#if Hardware_Version < 3
    if (raw_measurement < 512) analogVals[i][0] = 512 - 512; //do same math the keep timing same.
    else analogVals[i][0] = raw_measurement - 512;
#endif
#if Hardware_Version == 3
    if (raw_measurement > 512) analogVals[i][0] = 512 - 512; //do same math the keep timing same.
    else analogVals[i][0] = 512 - raw_measurement; //Version 3.0 boards current is measured in reverseMicro_ProcessorMicro_Processorr
#endif
    analogVals[i][1] = (micros() - time_now) / 16; // time since start of loop (thus sample time), input to array col 2
#if Micro_Processor == 1 || 2
    delayMicroseconds(delay_time);
#endif

    //for(byte j = 0; j < 1; j++)
    //  NOP; // delay 62.5ns on a 16MHz AtMega

    //if (raw_measurement > 512) analogVals[i][0] = 512 - 512; //do same math the keep timing same.
    //else analogVals[i][0] = 512 - raw_measurement; //Version 3.0 boards current is measured in reverseMicro_ProcessorMicro_Processorr
    analogVals[i][1] = (micros() - time_now) / 16; // time since start of loop (thus sample time), input to array col 2

  }
  digitalWrite(Spark_Out_Pin, LOW); // reset Spark_Out_Pin to low and turn off power to coil
  for (byte i = 0; i < numReadings; i++) // test only for the number in the array
  {
    //if (Hardware_Version > 2) analogVals[i][0] = 1023 - analogVals[i][0];//reverse current for version 3 onward
    Vin_Digital_New = analogVals[i][0];

    if (Vin_Digital_New > Vin_Digital_Max && (Vin_Digital_New > 13)) //detect current increasing and write to 'maxval'
    {
      Vin_Digital_Max = Vin_Digital_New;
      ttf = analogVals[i][1];
    }
  }
  mVolts = (Vin_Digital_Max / 1024.0) * Vin; // raw analog read val to millvolts
  // for ACS712
  //  amps = ((mVolts) / 132.0); // millivolts to amps (utilise scale factor for ACS sensor range 5A chip
  amps = ((mVolts) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
  //  amps = ((mVolts) / 370.0); // millivolts to amps (utilise scale factor for ACS sensor range 30A chip
  ttf = ttf / 62.50; //convert micro seconds to milliseconds micro/8 (single_fire_data()) then micro/8/125 same as micro/1000
}

void print_axis()
{
  // draw the axis, lables and tick marks
  for (int y = 0; y < 5; y++) {
    display.drawFastHLine(7, y * (SCREEN_HEIGHT) / 7.7 + SCREEN_HEIGHT / 4 + 8, 3, WHITE1);
  }
  for (int x = 0; x < 6; x++) {
    display.drawFastVLine(x * 30 + 10, SCREEN_HEIGHT - 3, 3, WHITE1);
  }
  display.drawFastHLine(10, SCREEN_HEIGHT - 1,  128 - 10, WHITE1);
  display.drawFastVLine(10, 8,  SCREEN_HEIGHT, WHITE1);

}

void print_graph()
{
  for (x = 1; x < numReadings; x++) {
    display.drawLine(x + 10 , SCREEN_HEIGHT - analogVals[x - 1][0] / 2.7, x + 10 , SCREEN_HEIGHT - analogVals[x][0] / 2.7, WHITE1);
    //display.drawLine(x + 10 , SCREEN_HEIGHT - analogVals[x - 1][0] / 10, x + 10 , SCREEN_HEIGHT - analogVals[x][0] / 10, WHITE1);

  }
}

void single_test()
{
  single_fire_data();
  display.clearDisplay();
  print_axis();
  print_graph();

  display.setTextColor(WHITE1, BLACK1);
  display.setTextSize(2);
  display.setCursor(0, 0);   display.print(ttf);    display.print(F("ms "));
  display.setTextSize(1);
  display.setCursor(80, 0);   display.print(amps);    display.print(F(" Amp"));
  display.setCursor(0, SCREEN_HEIGHT * 7 / 8);
  display.println(F("0"));
  display.setCursor(0, SCREEN_HEIGHT / 3 );
  display.println(F("5"));
  display.display();
}


void live_o_scope() //the following function works like a time laps 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;
  int i = 0;
  mVolts = 0.0;
  ttf = 0;

  display.clearDisplay();
  print_axis();

  display.setCursor(0, SCREEN_HEIGHT * 7 / 8);
  display.println(F("0"));
  display.setCursor(0, SCREEN_HEIGHT / 3);
  display.println(F("5"));

  RPM_time_old = micros();
  //while (!digitalRead(Test_PB_Pin));//incase of of debounce
  while (digitalRead(Test_PB_Pin))//Run until test pin pressed
    //for (int i = 0; i < 50 ; i++)
  {
    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;
    //ttf_sum += ttf_msec;
    ttf_sum += ttf;
    I_sum += amps; //use new max current reading
    I_mean = (I_sum / i);
    ttf_mean = (ttf_sum / i);

    // write results to OLED
    print_graph();
    display.setTextSize(2);
    display.setCursor(0, 0);   display.print(ttf_mean);    display.print(F("ms "));
    display.setTextSize(1);
    display.setCursor(80, 0);   display.print(I_mean);    display.print(F(" Amp"));
    display.setCursor(80, 8); display.print(RPM_live); display.print(F("  ")); display.setCursor(104, 8); display.print(F(" RPM"));
    display.display();
    swPresentState = digitalRead(Test_PB_Pin);
    for (int z = 0; z < (10230 - 10 * analogRead(Potentiometer_Pin)); z++) {
      asm("nop");
    }
  }
  while (!digitalRead(Test_PB_Pin)); //do nothing until test pin released
}


void live_bar_graph()  //the following function makes a bar graph of the time-to-fire results
{
  int pot_read = 0;
  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;
  int i = 0;
  int ttf_bars = 0;
  mVolts = 0.0;
  for (int y = 0; y < 50; y++)
  {
    test[y] = 0;
  }
  display.clearDisplay();
  display.setTextColor(WHITE1, BLACK1);
  print_axis();
  // draw the axis, lables and tick marks

  for (int x = 0; x < 11; x++) {
    display.drawFastVLine(x * 10 + 19, SCREEN_HEIGHT - 3, 3, WHITE1);
  }
  for (int x = 0; x < 6; x++) {
    display.drawFastVLine(69, x * SCREEN_HEIGHT / 8 + SCREEN_HEIGHT * .25, 2, WHITE1);
  }


  RPM_time_old = micros();
  //delay(100); //For Debounce
  while (!digitalRead(Test_PB_Pin));//incase of of debounce
  while (i < 50)
    //for (int i = 0; i < 50 ; i++)
  {
    i++;
    if (!digitalRead(Test_PB_Pin) || !digitalRead(Cap_PB_Pin)) {
      //i = 50; //end function if button pressed
      return;
    }
    RPM_time_old = RPM_time_new ;
    RPM_time_new = micros();
    RPM_live = 120000000 / (RPM_time_new - RPM_time_old);
    single_fire_data();
    ttf_sum += ttf;
    I_sum += amps;
    I_mean = (I_sum / i);
    ttf_mean = (ttf_sum / i);

    // 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.setCursor(120, 0); display.print(F(" "));

#if Bar_Graph_Adjustment == 1
    display.setCursor(102, 0); display.println(RPM_live);
    display.setCursor(108, 7);   display.print(F("rpm"));
#endif
    if (ttf / 100 < test_length)
    {
#if Bar_Graph_Adjustment == 2
      pot_read = 1773 - analogRead(Potentiometer_Pin); //1773=1023+750 to reverse control Use Poteniometer to set bar graph center 1350 is start then 2000 in center
      display.setCursor(12, 8); display.print(F("Center->"));
      display.setCursor(78, 8); display.print(F("<-")); display.print((pot_read + 650) / 1000.0);  display.println(F("ms")); //display center position
      ttf_bars = (ttf * 1000 - pot_read) / 100; //shift the window starting 1000ms adjustable, each bar is 100 ms wide
#endif
#if Bar_Graph_Adjustment == 1
      ttf_bars = (ttf * 1000 - 1350) / 100; //shift the window over 1350 ms, each bar is 100 ms wide
#endif
      test[ttf_bars] = test[ttf_bars] + 1;
      display.drawFastHLine(ttf_bars * 10 + 5, SCREEN_HEIGHT - 1 - test[ttf_bars],  9, WHITE1);
      display.display();
    }
    swPresentState = digitalRead(Test_PB_Pin);
#if Bar_Graph_Adjustment == 1 //read Potentiomete Pin to determine speed
    for (int z = 0; z < (10230 - 10 * analogRead(Potentiometer_Pin)); z++) {
      asm("nop");
    }
#endif
#if Bar_Graph_Adjustment == 2
    for (int z = 0; z < 10230 - 10 * 576.0; z++) { //1500 rpm
      asm("nop");
    }
#endif
  }
  while (!digitalRead(Test_PB_Pin)); //wait until button is released
}

void multi_test()
{
  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;
  int i = 0;
  mVolts = 0.0;
  ttf = 0;



  RPM_time_old = micros();
  //while (!digitalRead(Test_PB_Pin));//incase of of debounce
  while (digitalRead(Test_PB_Pin) && digitalRead(Cap_PB_Pin))//Run until test pin pressed
    //for (int i = 0; i < 50 ; i++)
  {
    i++;
    RPM_time_old = RPM_time_new ;
    RPM_time_new = micros();
    RPM_live = 120000000 / (RPM_time_new - RPM_time_old);
    single_fire_data();
    ttf_sum += ttf;
    I_sum += amps; //use new max current reading
    I_mean = (I_sum / i);
    ttf_mean = (ttf_sum / i);
    if (ttf > ttf_max)
    {
      ttf_max = ttf;
    }
    if (ttf < ttf_min)
    {
      ttf_min = ttf;
    }
    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;
    }    results_var += pow(ttf_mean - ttf, 2); // get variance
    ttf_std_dev = sqrt(results_var / numTests); // get std deviation

    // write results to OLED
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(0, 0);
    display.print(F("t="));
    display.print(ttf_mean);
    display.print(F("ms"));
    display.setTextSize(1);
    display.print(F(" #"));
    display.print(i);
    display.setCursor(0, 21);
    display.print(F("(Min="));
    display.print(ttf_min);
    display.print(F(" - Max="));
    display.print(ttf_max);
    display.println(F(")"));
    display.setCursor(0, 32);
    display.print(F("SD="));
    display.print(ttf_std_dev);
    display.print(F("; Dwell= "));
    display.print((ttf_max - ttf_min) / (float(60000 / RPM_live) / 360));
    display.println((char)167); // let's print the degree symbol!
    display.setCursor(0, 43);
    display.print(F("Max Current= "));
    display.print(ttf_max_current);
    display.println(F("amps"));
    display.setCursor(0, 54);
    display.print(RPM_live);
    display.print(F(" RPM "));
    display.print(miss);
    display.print(F(" MISFIRES "));
    display.display();// now that the display buffer is built, display it*/
    swPresentState = digitalRead(Test_PB_Pin);
    for (int z = 0; z < (10230 - 10 * analogRead(Potentiometer_Pin)); z++) {
      asm("nop");
    }
  }
  /*
    //OLED Print
  */
}


void fast_cap_test() //--- Function to check capacitor value and resistance ---//
{
#define leak_min 3000000 //3Mohm leak 
  delay(120);
  while (!digitalRead(Test_PB_Pin));//incase of of debounce
  while (digitalRead(Test_PB_Pin) && digitalRead(Cap_PB_Pin))
  {
    unsigned long new_time = 0;
    mVolts = 0;
    int cap_time = 0;
    int r_volts = 0;
    long r_val = 120000; // 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_Charge_Out_Pin, LOW);
    delay (150); //ensure the cap is discharged via charge pin low
    digitalWrite(Cap_Charge_Out_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 (Capacitor_Measurment_Pin);  //use analog pin A7 to read volts across unknown cap
      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));
      }
      while ((micros() - new_time < sample_time) && digitalRead(Test_PB_Pin)); //delay time
    }
    digitalWrite(Cap_Charge_Out_Pin, LOW);
    display.clearDisplay();
    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)
    {
      leak = 20000000; // Set value to 20Mohms if greater than 20M or above source voltage
    }

    display.setCursor(0, 0);
    display.setTextSize(2);
    display.println(F("CAPACITOR"));
    /*display.setTextSize(1);
      display.setTextColor(WHITE1, BLACK1);
      display.println(F("CAPACITOR TEST"));
      display.setTextColor(BLACK1, WHITE1);
      display.setCursor(90, 0);
      if (leak > leak_min && cap_val > 0.4 && cap_val < 0.6)
      {
      display.println(F(" PASS "));
      }
      else
      {
      display.println(F(" FAIL "));
      }*/
    //if (analogVals[1][0] > 10) {
    //if (leak / 1000000 > 0) {
    if (analogVals[numReadings - 1][0] > 10) { //Consider shorted if last reading is very small
      //display.fillRect(79, 16,  128 , 32, BLACK1);
      if (cap_val > 0.4 && cap_val < 0.6) display.setTextColor(WHITE1, BLACK1);
      else display.setTextColor(BLACK1, WHITE1);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   display.setCursor(0, 0);
      display.setTextSize(3);
      display.setCursor(0, SCREEN_HEIGHT / 4);
      //display.print(F("C = "));
      display.print(cap_val);   display.println(F("uF"));
      display.setTextSize(2);
      //display.setCursor(0, 24);
      if (leak > leak_min) display.setTextColor(WHITE1, BLACK1);
      else display.setTextColor(BLACK1, WHITE1);
      display.print(F("R = ")); display.print(leak / 1000000); display.println(F("Mohm"));
    }
    else {
      display.setCursor(0, SCREEN_HEIGHT / 4);
      display.println(F("SHORTED"));
      display.setCursor(0, SCREEN_HEIGHT * 3 / 4);
      display.setTextSize(1);
      display.println(F("Please open contacts"));
      digitalWrite(Cap_Charge_Out_Pin, LOW);
      display.display();
      //return; //end test here if shorted
    }
    digitalWrite(Cap_Charge_Out_Pin, LOW);
    display.display();
  }
  display.fillRect(0, SCREEN_HEIGHT / 4,  128 , SCREEN_HEIGHT, BLACK1);
  display.setCursor(0, 0);
  display.setTextSize(2);
  display.setTextColor(WHITE1, BLACK1);
  display.println(F("CAPACITOR"));
  display.println(F("  TEST"));
  display.setTextSize(1);
  display.setCursor(0, SCREEN_HEIGHT * 3 / 4);
  display.println(F(" Press Test Button"));
  display.println(F("      To Start"));
  display.display();
}

void cap_test_graph()
//--- Function to check capacitor value and resistance ---//
{
#define leak_min 3000000 //3Mohm leak 
  unsigned long new_time = 0;
  mVolts = 0;
  int cap_time = 0;
  int r_volts = 0;
  long r_val = 120000; // 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_Charge_Out_Pin, LOW);
  display.fillRect(0, SCREEN_HEIGHT / 4,  128 , SCREEN_HEIGHT, BLACK1);
  display.setTextColor(WHITE1, BLACK1);
  display.setTextSize(1);
  display.setCursor(0, SCREEN_HEIGHT / 2);
  display.println(F("CAPACITOR TEST GRAPH"));
  display.println(F("in progress..."));
  display.display();

  delay (150); //ensure the cap is discharged via charge pin low
  digitalWrite(Cap_Charge_Out_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 (Capacitor_Measurment_Pin);  //use analog pin A7 to read volts across unknown cap

    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][0] = mVolts / 4;
      //analogVals[i][1] = 1023 * (1 - exp(-i / 30.0));
      analogVals[i][1] = 255 * (1 - exp(-i / 30.0));
    }
    while (micros() - new_time < sample_time); //delay time

  }
  display.fillRect(0, SCREEN_HEIGHT / 4,  128 , SCREEN_HEIGHT, BLACK1);
  // draw the axis, lables and tick marks
  //draw 63% line
  for (int z = 0; z < 30; z++) {
    display.drawFastHLine(10 + z * 4, SCREEN_HEIGHT / 2,  1, WHITE1);
    display.drawFastHLine(10 + z * 6, SCREEN_HEIGHT / 4 - 1,  2, WHITE1);
    display.drawLine(z * 5 + 10 , 63 - analogVals[z * 5 - 1][1] / 5.31, z * 5 + 10 , 63 - analogVals[z * 5][1] / 5.31, WHITE1);
  }
  for (int x = 0; x < 12; x++) { //draw the upper and lower limits
    display.drawFastVLine(30 + 10, SCREEN_HEIGHT / 4 + 5 * x - 1, 1, WHITE1); //30 T constant + 10 offset
  }
  display.setTextColor(WHITE1, BLACK1);
  display.drawFastHLine(10, SCREEN_HEIGHT - 1,  128 - 10, WHITE1);
  display.drawFastVLine(10, SCREEN_HEIGHT / 4,  SCREEN_HEIGHT, WHITE1);

  display.setTextColor(WHITE1, BLACK1);
  display.setTextSize(1);
  display.setCursor(0, SCREEN_HEIGHT / 2);   display.println("63%");
  display.display();
  delay (200);
  for (int i = 1; i < numReadings; i++) {
    display.drawLine(i + 10 , 63 - analogVals[i - 1][0] / 5.31, i + 10 , 63 - (analogVals[i][0]) / 5.31, WHITE1);
    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 )
  {
    leak = 20000000;
  }
  digitalWrite(Cap_Charge_Out_Pin, LOW);
  //if (leak / 1000000 > 0) {
  if (analogVals[numReadings - 1][0] > 10) { //Consider shorted if last reading is very small
    display.setTextSize(2);
    display.fillRect(60, SCREEN_HEIGHT / 2,  128 , SCREEN_HEIGHT, BLACK1);
    display.setTextColor(WHITE1, BLACK1);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    display.setCursor(0, 0);
    display.setCursor(50, SCREEN_HEIGHT / 2);
    display.print(cap_val);   display.println(F("uF"));
    display.setCursor(40, SCREEN_HEIGHT * 3 / 4);
    display.print(leak / 1000000); display.println(F(" Mohm"));
    display.display();
  }
  else {
    display.fillRect(0, SCREEN_HEIGHT / 4 - 1,  128 , SCREEN_HEIGHT, BLACK1);
    display.setCursor(0, SCREEN_HEIGHT / 4);
    display.setTextSize(2); display.println(F("SHORTED"));
    display.setCursor(0, SCREEN_HEIGHT * 3 / 4);
    display.setTextSize(1); display.println(F("Please open contacts"));
    digitalWrite(Cap_Charge_Out_Pin, LOW);
    display.display();
    return; //end test here if shorted
  }

  delay (1500);

  display.fillRect(0, SCREEN_HEIGHT / 4 - 1,  128 , SCREEN_HEIGHT - 4, BLACK1);
  display.setTextColor(WHITE1, BLACK1);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   display.setCursor(0, 0);
  display.setCursor(0, SCREEN_HEIGHT / 4);
  display.setTextSize(2);
  display.print(cap_val);  display.print(F(" uF "));
  display.setTextSize(1);
  display.setCursor(90, SCREEN_HEIGHT * 5 / 16);
  if (cap_val > 0.4 && cap_val < 0.6)
  {
    display.println(F(" PASS "));
  }
  else
  {
    display.setTextColor(BLACK1, WHITE1); display.print(F(" FAIL ")); display.setTextColor(WHITE1, BLACK1);
  }
  display.setCursor(0, SCREEN_HEIGHT / 2);
  display.println(F(" (Ideal .4-.6 uF)"));
  display.setTextSize(2);  display.print(leak / 1000000); display.print(F(" Mohm"));
  display.setTextSize(1);
  display.setCursor(90, SCREEN_HEIGHT * 11 / 16);
  if (leak > leak_min)  //test if > 3 Mohms
  {
    display.println(F(" PASS "));
  }
  else
  {
    display.setTextColor(BLACK1, WHITE1); display.println(F(" FAIL ")); display.setTextColor(BLACK1, WHITE1);
  }
  display.setCursor(0, SCREEN_HEIGHT * 7 / 8);
  display.println(F(" (Ideal > 3 Mohm)"));
  display.display();
}

void loop()
{
  //read potentiometer and set rpm
  rpm = analogRead(Potentiometer_Pin) / 50 * 100 + 500; // perform a read to clear register (comment out if no Potentiometer) units 100 rpm
  Mode_PB_PinState = digitalRead(Cap_PB_Pin);
  Test_PB_PinState = digitalRead(Test_PB_Pin);
  delay(100); //delay for switch debounce
  if (Mode_PB_PinState == HIGH && Test_PB_PinState && !digitalRead(Test_PB_Pin))
  {
    digitalWrite(Spark_Out_Pin, HIGH); // check for short
    for (int i = 1; i < 100; i++) {
      //delayMicroseconds(50); //delay for current to ramp up
      Vin_Digital_Max = analogRead(Current_Measure_Pin);
#if Hardware_Version < 3
      if (Vin_Digital_Max < 512) mVolts = 0; //do same math the keep timing same.
      else mVolts = Vin_Digital_Max - 512;
#endif
#if Hardware_Version == 3
      if (Vin_Digital_Max > 512) mVolts = 0; //do same math the keep timing same.
      else mVolts = 512 - Vin_Digital_Max; //Version 3.0 boards current is measured in reverseMicro_ProcessorMicro_Processorr
#endif
      digitalWrite(Spark_Out_Pin, LOW); //set Spark_Out_Pin low
      amps = ((mVolts) / 100.0 / 1023 * Vin); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
      if (amps > 3) { //Three amps in 50 microseconds is the threshold to be considered a short
        display.clearDisplay();
        display.setTextColor(WHITE1, BLACK1);
        display.setTextSize(2);
        display.setCursor(0, 0);
        display.println(Vin_Digital_Max);
        display.println(F("OUTPUT"));
        display.println(F("SHORTED!!!"));
        display.setTextSize(1);
        display.println(F("-Verify Setup"));
        display.println(F("-Cycle power to reset"));
        display.display();
        while (1) {
          display.clearDisplay();
          display.setTextColor(WHITE1, BLACK1);
          display.setTextSize(2);
          display.setCursor(0, 0);
          display.print(F("Cur "));
          display.println(analogRead(Current_Measure_Pin));
          display.print(F("Vin "));
          display.println(analogRead(Vin_Measure_Pin));
          display.print(F("Pot "));
          display.println(analogRead(Potentiometer_Pin));
          display.print(F("Cap "));
          display.println(analogRead(Capacitor_Measurment_Pin));
          display.display();
        }
        ; //Hang program until short dealt with- power must be cycled to restart
      }
      digitalWrite(Spark_Out_Pin, LOW); //set Spark_Out_Pin low
    }
    while (!digitalRead(Test_PB_Pin));  //Do nothing until test pin released
    switch (test_mode) {
      case 0: {
          single_test();
          break;
        }
      case 1: {
          live_o_scope();
          break;
        }
      case 2: {
          live_bar_graph();
          break;
        }
      case 3: {
          multi_test();
          break;
        }
      case 4: {
          fast_cap_test();
          break;
        }
      case 5: {
          cap_test_graph();
          break;
        }
    }
    delay(200); //delay for switch debounce
  }
  if (Mode_PB_PinState == LOW)
  {
    if (test_mode < 5) {
      test_mode = test_mode + 1;
    }
    else {
      test_mode = 0;
    }
    display.clearDisplay();
    display.setTextColor(WHITE1, BLACK1);
    display.setTextSize(2);
    display.setCursor(0, 0);
    switch (test_mode) {
      case 0: {
          display.println(F(" SINGLE"));
          display.println(F("FIRE TEST"));
          break;
        }
      case 1: {
          display.println(F("  LIVE"));
          display.println(F(" O-SCOPE"));
          break;
        }
      case 2: {
          display.println(F("BAR GRAPH"));
          display.println(F("  TEST"));
          break;
        }
      case 3: {
          display.println(F("MULTIFIRE"));
          display.println(F("  TEST"));
          break;
        }
      case 4: {
          display.println(F("CAPACITOR"));
          display.println(F("  TEST"));
          break;
        }
      case 5: {
          display.println(F("CAPACITOR"));
          display.println(F("GRAPH TEST"));
          break;
        }
    }
    display.setTextSize(1);
    display.setCursor(0, 48);
    display.println(F("  Press Test Button"));
    display.println(F("       To Start"));
    display.display();// now that the display buffer is built, display it
    display.display();
    while (!digitalRead(Cap_PB_Pin));
    delay(200); //delay for switch debounce
  }
}
Let me know if you get it working or have any questions.

Matt


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Sat Mar 11, 2023 11:52 pm

Also wondering if there would be an update to the board info. The one you sent me Matt, seems to have given out. The Arduino seems to work but it's not driving the coil, so I'm guessing the FET or whatever it is driving the coil has died. I was going to see about ordering some boards from JLCPCB but the files are for the earlier version I guess.. I'm new at this PCB ordering business but the JLC website seems to make things fairly straight forward.

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Tue Mar 14, 2023 1:26 am

Tony,
I just sent you an email. I want to help you resolve the issue that you have with your board.

Also, I wanted to share that I have updated the PCB to version 4.0.
FACT ver 4_0 Circuit.JPG
FACT ver 4_0 PCB.JPG
I would be happy to share the files to make the PCB when someone is interested in making their own. The main difference with version 4.0 is that there is one ground plane across the board (see the blue on the PCB). The solid ground plan minimizes occasional glitches due to electrical interference. This board is currently being tested with very positive results.

Matt


Tonytiger75
Posts: 25
Joined: Sun Jan 03, 2021 12:09 am
First Name: Tony
Last Name: Miller
* REQUIRED* Type and Year of Model Ts owned: 1925 Roadster
Location: Portsmouth Virginia
MTFCI Number: 19807
Board Member Since: 2018

Re: A new DIY electronic coil tester.

Post by Tonytiger75 » Sat Mar 18, 2023 11:07 am

Matt I would like to send off to get some of the latest boards made. I started in with the files posted earlier but ran into a couple snags with component availability and staying up way to late to think on such things...

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Sat Mar 18, 2023 4:41 pm

Tony,
I am happy to help you. I thought that I sent you an email through the forum. Please email me and I will get you set up.

Matt


Myxr6turbo
Posts: 89
Joined: Sat Jul 17, 2021 2:40 am
First Name: Shawn
Last Name: Barnard
* REQUIRED* Type and Year of Model Ts owned: 1926 coupe
Location: Australia, Victoria

Re: A new DIY electronic coil tester.

Post by Myxr6turbo » Sun Aug 20, 2023 12:50 am

Hi guys,

I was just going through the 3 pages of info and had a couple of questions.

1) Is it possible to make this with only an arduino and LCD?

2) Would it be possible for someone to send me the latest files to upload to JLCPCB please?

3) What is the latest program version?

Thanks in advance


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Sun Aug 20, 2023 4:43 pm

Myxr6turbo wrote:
Sun Aug 20, 2023 12:50 am
1) Is it possible to make this with only an arduino and LCD?
Shawn,

The last of the code examples before Matt added the Oled screen should work fine with a bog-standard Arduino and i2C 1602 LCD, after all that's what I used to develop the device originally.

I guess at some point Matt may put up the requisite detail for his PCB's, and from there you could simply leave out the Oled and just connect up an LCD to SCA/SCL as needed. Alternatively you could just to use a standard breakout board for the the Arduino, LCD & ACS current sensor etc and hook them together with (short) wires as per my prototype...

Luke.


Myxr6turbo
Posts: 89
Joined: Sat Jul 17, 2021 2:40 am
First Name: Shawn
Last Name: Barnard
* REQUIRED* Type and Year of Model Ts owned: 1926 coupe
Location: Australia, Victoria

Re: A new DIY electronic coil tester.

Post by Myxr6turbo » Mon Aug 21, 2023 3:44 am

I have just gone to buy one but they are missing 3 of the components and have no eta when they will be in. Does anyone have one made they would be willing to sell and ship to Australia?

Thanks again.


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Mon Aug 21, 2023 3:59 pm

Myxr6turbo wrote:
Mon Aug 21, 2023 3:44 am
I have just gone to buy one but they are missing 3 of the components and have no eta when they will be in. Does anyone have one made they would be willing to sell and ship to Australia?
Shawn,

What 'one' is this, and what are these components?

As far as I'm aware all the requisite modules for a modular design were still available from the usual suspects as of yesterday. If it's a PCB you're really wanting I expect you could uplift any 'missing' components from a module.

Luke.


Myxr6turbo
Posts: 89
Joined: Sat Jul 17, 2021 2:40 am
First Name: Shawn
Last Name: Barnard
* REQUIRED* Type and Year of Model Ts owned: 1926 coupe
Location: Australia, Victoria

Re: A new DIY electronic coil tester.

Post by Myxr6turbo » Mon Aug 21, 2023 5:25 pm

These 3 are missing
Attachments
Components.jpg

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Mon Aug 21, 2023 9:23 pm

Here are the latest files for version 4. I would strongly encourage that you use this version.
Gerber_PCB_FACT_2_22_22.zip
(46.94 KiB) Downloaded 22 times
BOM and Pick and place.zip
(3.1 KiB) Downloaded 19 times
I had to zip the POM and Pick and Place. You will need to extract that file so that you are left with the Gerber zip file and two excel files. Then you can load them up on JLCPCB.com. Please let me know if you have any issues.

I recommend that you use an OLED. If you use something else, then you need to figure out the code and the O-Scope is my favorite part of the design.

Matt

User avatar

Matt in California
Posts: 726
Joined: Sun Jan 06, 2019 5:42 pm
First Name: Matt
Last Name: G
* REQUIRED* Type and Year of Model Ts owned: 1926 Touring, 1926 Fordor Project, TT C-cab flatbed farm field find, TT dump truck project
Location: California
MTFCA Number: 30697

Re: A new DIY electronic coil tester.

Post by Matt in California » Tue Aug 22, 2023 12:47 am

This is the most recent version of the Arduino code:

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
   Using Lukes Code.  Matt from California made changes.
   For more infomation on PCB hardware see:
   https://www.mtfca.com/phpBB3/viewtopic.php?p=180813#p180813

   Added code for .96" OLED.  This code also is set up for graphing current.  Set numReadings = 150 (170 caused trouble).
   -----------------------------------------------------------------------------
   Version 0.97 (Matt), 1 Jan 2021

   Made changes for FACT 0.0 PCB including adjusting for aattenuated sign due to filter.
   Changed ideal leakage to >3Mohm
   Added diode voltage to measured the voltage
   -----------------------------------------------------------------------------
   Version 0.98 (Matt), 13 Feb 2021

   Changes on Current Readings
   -----------------------------------------------------------------------------
   Version 0.99 (Matt), 5 April 2021

   Minor changes in text displayed.
   -----------------------------------------------------------------------------
   Version 1.00 (Matt), 7 April 2021

   Intended for Version 1.0 PCB
   Capacitor Test is now active whenever Cap_test contact is closed.
   This means that the switch should be removed and replace with a push button.
   -----------------------------------------------------------------------------
   Version 2.00 (Matt), 30 June 2021

   Intended for Version 2.0 PCB
   Pinout reconfigered for Version 2.0 PCB
   Changed OLED driver to SH1106 for larger OLED
   Made some veriables more discriptive (but same function)
   -----------------------------------------------------------------------------
   Version 2.02 (Matt), 28 August 2021

   Added live_bar_graph()function to test to display time-to-fire results as bars.
   -----------------------------------------------------------------------------
   Version 2.03 (Matt), 28 August 2021

   Minor changes for pushbottons and function with live_bar_graph()
   -----------------------------------------------------------------------------
   Version 2.04 (Matt), 28 August 2021

   Changes switch functions from capactor test to mode.
   Now you don't have to hold switch for a set amount of time, just change mode.
   -----------------------------------------------------------------------------
   Version 2.06 (Matt), 5 September 2021

   Minor change to cap test to make display time shorter.
   -----------------------------------------------------------------------------
   Version 2.07 (Matt), 6 September 2021

   Deleted unused code for LCD display, serial port and other code used for testing.
   Added code to alert users of short prior to any test.
   -----------------------------------------------------------------------------
   Version 2.08 (Matt), 11 September 2021

   Added compiler directives to switch between Hardware_Version 1.x & 2.x
   Added compiler directives to switch between OLED SSD1306 or SH1106 dispays
   Edited live_bar_graph function to move bars to 1.7+-.5, 1.8.+-.5, 1.9 +-.5 etc.
   -----------------------------------------------------------------------------
   Version 2.09 (Matt), 25 September 2021

   Improved switch debounce.
   -----------------------------------------------------------------------------
   Version 2.10 (Matt), 10 October 2021

   Adjust center point of bars or rpm adjust
   -----------------------------------------------------------------------------
   Version 2.11 (Matt), 10 October 2021

   Pot for RPM adjustment
   -----------------------------------------------------------------------------
   Version 2.12 (Matt), 13 October 2021

   Changes to speed up capacitor test-fast_cap_test();
   Also changes for debounce
   -----------------------------------------------------------------------------
   Version 2.13 (Matt), 24 October 2021

   Changes to pb debounce functions and to get out of Capacitor Test easier
   -----------------------------------------------------------------------------
   Version 2.14 (Matt), 24 November 2021

   Changes for using Nano 33 IOT
   -----------------------------------------------------------------------------
   Version 2.15 (Matt), 23 December 2021

   Changes for 3.3 volt board
   -----------------------------------------------------------------------------
   Version 2.16 (Matt), 25 December 2021

   Added Read_Current()routine
   Added delay on reading input voltage
   Changed single_fire_data() using delay
   -----------------------------------------------------------------------------
   Version 3.00 (Matt), 25 March 2022

   Major changes made to acommidated SH110X driver
   To use 32x128 made arrays byte instead of int.  This required major changes...
   Removed Read_Current()routine
   Added functions
      -----------------------------------------------------------------------------
   Version 3.01 (Matt), 15 April 2022

   Fixed issue with selecting Hardware Version

   -----------------------------------------------------------------------------
   Version 3.02 (Matt), 21 April 2022

   Fixed issue with selecting Hardware Version

   -----------------------------------------------------------------------------
   Version 3.03 (Matt), 13 March 2022

   Improved compatibility with Arduino Nano Every and Nano IOT 33

   -----------------------------------------------------------------------------
   Version 3.04 (Matt), 13 March 2022

   Improved compatibility with Arduino Nano Every
   fixed error in single_fire_data()

   -----------------------------------------------------------------------------
   Version 3.05 (Matt), 20 August 2022

   Improved compatibility with Arduino Nano Every
   fixed error in single_fire_data()

   -----------------------------------------------------------------------------
   Pin Connections (for Version 2.0 (&3.0?) board, you can adjust as needed)
   Arduino device
   Ground OLED ground
   +5VDC Vcc
   A0 Input to measure power 6-12 VDC (R1 ~10 Kohm A0 to ground, R2 20-30 Kohm to input power)
   A1 NC
   A2 Output to Solid State Switch (MOSFET) to connect where timer connects to coil
   A3 Input for data read from current sensor (5 VDC limit)
   A4 To OLED SDA (if no SDA pin)
   A5 To OLED SCL (if not SCL pin)
   A6 Input for RPM_Set control potentiometer (0-5 VDC)
   A7 Input for Capacitor Test where timer connects to coil (note resistor connects to D4)
   D2 Input Mode/Capacitor Test Pushbutton
   D3 Input Test Pushbutton (other side connected to GND)
   D4 Output Cap Charge Pin (connect to A2 with a resistor 300-500+ Kohms)
   D5 NC
   D6 NC
   D7 NC
   D8 TFT RES
   D9 TFT DC
   D10 TFT CS
   D11 TFT SDA
   D12
   D13 TFT SCL

   -----------------------------------------------------------------------------
   Version 4.00 (Matt), 17 Febuary 2023

   Added capability for Version 4.0 board
   Changed the voltage in measurement to average inptuts

   -----------------------------------------------------------------------------
   Pin Connections (for Version 4.0 board, you can adjust as needed)
   Arduino device
   Ground OLED ground
   +5VDC Vcc
   A0 Input for RPM_Set control potentiometer (0-5 VDC)
   A1 Input for Capacitor Test where timer connects to coil (note resistor connects to D4)
   A2 NC
   A3 Input for data read from current sensor (5 VDC limit)
   A4 To OLED SDA (if no SDA pin)
   A5 To OLED SCL (if not SCL pin)
   A6 NC
   A7 Input to measure power 6-12 VDC (R1 ~10 Kohm A0 to ground, R2 20-30 Kohm to input power)
   D2 Output to Solid State Switch (MOSFET) to connect where timer connects to coil
   D3 NC
   D4 NC
   D5 NC
   D6 NC
   D7 NC
   D8 NC
   D9 NC
   D10 Output Cap Charge Pin (connect to A1 with a resistor 120 Kohms)
   D11 Input Mode/Capacitor Test Pushbutton
   D12 Input Test Pushbutton (other side connected to GND)
   D13 NC

   The following functions are performed with this code:
   -Single Fire Test- Displays single wafeform and current and time to fire
   -Multifire Test- Displays statistical data of 48 fires
   -Live Oscillosope- Continous single Fire Test
   -Bar Graph Test- 50 tests are placed into differnt bars
   -Capacitor Test

   PLEASE NOTE: The goal is to get a matching set of coils with a time to fire of.
   For example 3.5ms at 6V, and 2ms at 12V.
*/

#define ver 4.00

//****ATTENTION!!!**** CHANGE HARDWARE VERSION TO YOUR CONFIGURATION!!! ****ATTENTION!!!****
#define Hardware_Version 4       // 1= v1.0x; 2=v2.0x; 3=v3.0x; 4=v4.0x *This changes pin out
#define Display 2                // 1 = SSD1306; 2 = SH1106; 3 = ST7789
#define Bar_Graph_Adjustment 2   // 1 = RPM adjustable; 2 = Center of bars adjustable with potentiometer 
#define Micro_Processor 2        // 1 = ATmega328; 2 = ATMega4809(Nano Every); 3 = SAMD21 (Nano 33) //#3 untested

#if Micro_Processor == 1
#define Vin 5000 // 5 volts
#endif

#if Micro_Processor == 2
#define Vin 5000 // 5 volts
#endif

#if Micro_Processor == 3
#define Vin 3300 //3.3 volts
#endif

#if Hardware_Version == 1
#define Cap_PB_Pin 5            // input pin for cap/coil test switch. Low for cap
#define Test_PB_Pin 8           //input pin for switch, normally high
#define Cap_Charge_Out_Pin 13   //for capacitor test
#define Vin_Measure_Pin A7      //for Input Power Voltage
#define Spark_Out_Pin 7         //output pin to ss relay for coil
#define Current_Measure_Pin A0  //for Input Power Voltage
#define Potentiometer_Pin A1
#define Capacitor_Measurment_Pin A2
#endif

#if Hardware_Version == 2
#define Cap_PB_Pin 2           // input pin for cap/coil test switch. Low for cap
#define Test_PB_Pin 3          // input pin for switch, normally high
#define Cap_Charge_Out_Pin 4   // for capacitor test
//Pin 5 NC
//Pin 6 NC
//Pin 7 NC
#define TFT_RES_Pin 8     //TFT not used
#define TFT_DC_Pin 9
#define TFT_CS_Pin 10
#define TFT_SDA_Pin 11
//Pin 12 NC
#define TFT_SCL_Pin 13
#define Vin_Measure_Pin A0      //for Input Power Voltage
//A1 NC
#define Spark_Out_Pin A2        //output pin to ss relay for coil
#define Current_Measure_Pin A3      //for Input Power Voltage
#define Potentiometer_Pin A6
#define Capacitor_Measurment_Pin A7
#endif

#if Hardware_Version == 3
#define Cap_PB_Pin 2           // input pin for cap/coil test switch. Low for cap
#define Test_PB_Pin 3          // input pin for switch, normally high
#define Cap_Charge_Out_Pin 4   // for capacitor test
//Pin 5 NC
//Pin 6 NC
//Pin 7 NC
#define TFT_RES_Pin 8     //TFT not used
#define TFT_DC_Pin 9
#define TFT_CS_Pin 10
#define TFT_SDA_Pin 11
//Pin 12 NC
#define TFT_SCL_Pin 13
#define Vin_Measure_Pin A0      //for Input Power Voltage
//A1 NC
#define Spark_Out_Pin A2        //output pin to ss relay for coil
#define Current_Measure_Pin A3      //for Input Power Voltage
#define Potentiometer_Pin A6
#define Capacitor_Measurment_Pin A7
#endif

#if Hardware_Version == 4
#define Spark_Out_Pin 2        //output pin to ss relay for coil
// Pin 3 NC
// Pin 4 NC
// Pin 5 NC
// Pin 6 NC
// Pin 7 NC
// Pin 8 NC
// Pin 9 NC
#define Cap_Charge_Out_Pin 10    //for capacitor test
#define Cap_PB_Pin 11      // input pin for cap/coil test switch. Low for cap
#define Test_PB_Pin 12          //input pin for switch, normally high
//Pin 12 NC
#define TFT_SCL_Pin 13
#define Potentiometer_Pin A0
#define Capacitor_Measurment_Pin A1
//NC A2
#define Current_Measure_Pin A3      //for Input Power Voltage
//SDA A4 //defined elsewhere
//SCL A5 //defined elsewhere
//NC A6
#define Vin_Measure_Pin A7      //for Input Power Voltage
#endif

// Include any required OLED libraries

#if Display == 1
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 //OLED Width
#define SCREEN_HEIGHT 64 //OLED Height
#define OLED_RESET    4
#define BLACK1 BLACK
#define WHITE1 WHITE
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);;
#endif

#if Display == 2  //Using SH1106 with Arduino Nano or Arduino Nano Every

//#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
#define SCREEN_WIDTH 128 //OLED Width
#define SCREEN_HEIGHT 64 //OLED Height
#define OLED_RESET    -1
#define WHITE1 SH110X_WHITE
#define BLACK1 SH110X_BLACK
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#endif

#if Display == 3  //Using SH7789 with Arduino Nano or Arduino Nano Every

#include <Adafruit_GFX.h> // Core graphics library
//#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>
#define TFT_CS 9
#define TFT_RST 7
#define TFT_DC 8
#define TFT_BLK  10 //define TFT_BLK pin
#define TFT_MOSI 11 // Data out
#define TFT_SCLK 13 // Clock out
//If you buy your TFT from eBay don't be surprised if the colours are messed up.
//I found this code sorted my colours out. The library's colours (e.g. ST77XX_CYAN)
//were all wrong on my particular TFT screen
//Credit for sorting this:
//https://forum.arduino.cc/t/colour-confusion-issue-with-unbranded-160x80-tft-and-adafruit-library/604752/12
#define BLACK1 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE1 0xFFFF
#define DGRAY 0x2945
#define LGRAY 0x528A
#define ORANGE 0xFC02

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
//Define a vertical start position which makes it easy to move everything for specific displays
#define tft display
#define START_POS 2

#endif

// END OLED **************************************************************************************************************

//setup for fast ADC read for ATmega328
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#define NOP __asm__ __volatile__ ("nop\n\t") //use for short delay

#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
#define test_length 25

// voltmeter + resistor divider details
#if Hardware_Version == 1
#define R3 10000.0    // resistor to ground
#endif
#if Hardware_Version == 3||4
#define R3 1000.0    // resistor to ground
#endif
#define R2 20000.0    // resistor to input supply (20K resistor actual measurement)


//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 Mode_PB_PinState;
boolean Test_PB_PinState;
float ttf;  // time to fire
int test_mode = 0;

// 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 Vin_Digital_Max = 512; // set to zero current

//set variables for collect_data function array
byte analogVals[numReadings][2]; // array name & goodnews=columns
byte test[test_length];
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

void setup()
{
  pinMode(Test_PB_Pin, INPUT_PULLUP); // set the switch pin as input and apply resistor to +5
  pinMode(Spark_Out_Pin, OUTPUT);// define output pin
  pinMode(Cap_Charge_Out_Pin, OUTPUT);// define output pin
  pinMode(Cap_PB_Pin, INPUT_PULLUP);

#if Micro_Processor == 1
  sbi(ADCSRA, ADPS2); //more stuff for fast ADC read (ATmega328)
  cbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);
#endif
#if Micro_Processor == 2
  //ADC0_CTRLC = 0x54; // reduced cap, Vdd ref, 32 prescaler (ATega4809)
  ADC0_CTRLC = 0x53; // reduced cap, Vdd ref, 16 prescaler(ATega4809)
#endif
#if Micro_Processor == 3//Using Nano 33 IOT

  analogReadResolution(10);
#endif

  delay (1500); //give time delay to let input voltage stabilize

  // Determine the input voltage to display by avarage of 100 values
  float Vin_val = analogRead(Vin_Measure_Pin) / 1000.0;
  //Vin_val = analogRead(Vin_Measure_Pin)/1000.0;
  for (byte i = 0; i < 100; i++) // test only for the number in the array
  {
    Vin_val = analogRead(Vin_Measure_Pin) / 1000.0 + Vin_val;
  }
  interim_val = (Vin_val / 100) * Vin / 1023.0; //divide by 100 to find average of 100 values then determine voltage with ratio
  input_voltage = interim_val  * ((R2 + R3) / R3) + .75; // diode D2 voltage = .75

  //read potentiometer and set rpm
  rpm = analogRead(Potentiometer_Pin) / 50 * 100 + 500; // perform a read to clear register (comment out if no Potentiometer) units 100 rpm

  // The following for OLED comment if not used

#if Display == 1
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
#else,
#if Display == 2 && Micro_Processor == 1 || 2 //Using SH1106 with Nano
  //isplay.begin(SH1106_SWITCHCAPVCC, 0x3C);
  delay(250); // wait for the OLED to power up
  display.begin(i2c_Address, true); // Address 0x3C default
#endif
#endif

#if Display == 2 && Micro_Processor == 3//Using SH1106 With Nano 33 IOT
  display.begin(i2c_Address, true); // Address 0x3C default
#endif

#if Display == 3 //Using SH7789 with Nano
  pinMode(TFT_BLK, OUTPUT);// define output pin
  //digitalWrite(TFT_BLK, HIGH); //turn on display backlight
  analogWrite(TFT_BLK, 100); //set brightness 1-254
  // use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT:
  //tft.init(240, 240);           // Init ST7789 240x240

  // OR use this initializer (uncomment) if using a 2.0" 320x240 TFT:
  //tft.init(240, 320);           // Init ST7789 320x240

  // OR use this initializer (uncomment) if using a 1.14" 240x135 TFT:
  tft.init(135, 240);           // Init ST7789 240x135
  tft.setRotation(2);//Horizonal
  //display.clearDisplay();
  tft.fillScreen(ST77XX_BLACK);
#endif
  // The header file needs to be changed #define SH1106_128_32 (even though the display maybe 64 height it should be set to 32 because there is no memory to compile 64
  display.clearDisplay();
  display.setTextColor(WHITE1, BLACK1);        // Draw white text
  display.setCursor(0, 0);
  display.setTextSize(2);             // Draw 2X-scale text
  display.println(F("FACT"));
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.println(F("Model T Coil Tester"));
  display.println(F(" "));
  display.setTextSize(2);             // Draw 2X-scale text
  display.print(F("Vin=")); display.print (input_voltage, 1); display.println(F(" V")); // display input voltage
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.print(F("Software Ver ")); display.println (ver);
  display.print(F("Hardware Ver ")); display.print(Hardware_Version); display.println(F(".0"));
  //display.setTextSize(1);             // Normal 1:1 pixel scale
  display.display();
  //delay (1500);
}

//--- Function to fire coil once and collect data ---//
void single_fire_data()
{

#if Micro_Processor == 1
  int delay_time = 17;
#endif
#if Micro_Processor == 2
  int delay_time = 0;
#endif
#if Micro_Processor == 3
  int delay_time = 0;
#endif
  Vin_Digital_Max = 0; // set to zero current
  int Vin_Digital_New = 0;
  int raw_measurement;
  byte ADCregOriginal;
  mVolts = 0.0;
  ttf = 0;
  analogRead(Current_Measure_Pin); // perform a read to clear register
  digitalWrite(Spark_Out_Pin, HIGH); //set Spark_Out_Pin 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
  {
    raw_measurement = analogRead(Current_Measure_Pin);

#if Hardware_Version < 3
    if (raw_measurement < 512) analogVals[i][0] = 512 - 512; //do same math the keep timing same.
    else analogVals[i][0] = raw_measurement - 512;
#endif
#if Hardware_Version == 3||4
    if (raw_measurement > 512) analogVals[i][0] = 512 - 512; //do same math the keep timing same.
    else analogVals[i][0] = 512 - raw_measurement; //Version 3.0 boards current is measured in reverseMicro_ProcessorMicro_Processorr
#endif
    analogVals[i][1] = (micros() - time_now) / 16; // time since start of loop (thus sample time), input to array col 2
#if Micro_Processor == 1 || 2
    delayMicroseconds(delay_time);
#endif

    //for(byte j = 0; j < 1; j++)
    //  NOP; // delay 62.5ns on a 16MHz AtMega

    //if (raw_measurement > 512) analogVals[i][0] = 512 - 512; //do same math the keep timing same.
    //else analogVals[i][0] = 512 - raw_measurement; //Version 3.0 boards current is measured in reverseMicro_ProcessorMicro_Processorr
    analogVals[i][1] = (micros() - time_now) / 16; // time since start of loop (thus sample time), input to array col 2

  }
  digitalWrite(Spark_Out_Pin, LOW); // reset Spark_Out_Pin to low and turn off power to coil
  for (byte i = 0; i < numReadings; i++) // test only for the number in the array
  {
    //if (Hardware_Version > 2) analogVals[i][0] = 1023 - analogVals[i][0];//reverse current for version 3 onward
    Vin_Digital_New = analogVals[i][0];

    if (Vin_Digital_New > Vin_Digital_Max && (Vin_Digital_New > 13)) //detect current increasing and write to 'maxval'
    {
      Vin_Digital_Max = Vin_Digital_New;
      ttf = analogVals[i][1];
    }
  }
  mVolts = (Vin_Digital_Max / 1024.0) * Vin; // raw analog read val to millvolts
  // for ACS712
  //  amps = ((mVolts) / 132.0); // millivolts to amps (utilise scale factor for ACS sensor range 5A chip
  amps = ((mVolts) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
  //  amps = ((mVolts) / 370.0); // millivolts to amps (utilise scale factor for ACS sensor range 30A chip
  ttf = ttf / 62.50; //convert micro seconds to milliseconds micro/8 (single_fire_data()) then micro/8/125 same as micro/1000
}

void print_axis()
{
  // draw the axis, lables and tick marks
  for (int y = 0; y < 5; y++) {
    display.drawFastHLine(7, y * (SCREEN_HEIGHT) / 7.7 + SCREEN_HEIGHT / 4 + 8, 3, WHITE1);
  }
  for (int x = 0; x < 6; x++) {
    display.drawFastVLine(x * 30 + 10, SCREEN_HEIGHT - 3, 3, WHITE1);
  }
  display.drawFastHLine(10, SCREEN_HEIGHT - 1,  128 - 10, WHITE1);
  display.drawFastVLine(10, 8,  SCREEN_HEIGHT, WHITE1);

}

void print_graph()
{
  for (x = 1; x < numReadings; x++) {
    display.drawLine(x + 10 , SCREEN_HEIGHT - analogVals[x - 1][0] / 2.7, x + 10 , SCREEN_HEIGHT - analogVals[x][0] / 2.7, WHITE1);
    //display.drawLine(x + 10 , SCREEN_HEIGHT - analogVals[x - 1][0] / 10, x + 10 , SCREEN_HEIGHT - analogVals[x][0] / 10, WHITE1);

  }
}

void single_test()
{
  single_fire_data();
  display.clearDisplay();
  print_axis();
  print_graph();

  display.setTextColor(WHITE1, BLACK1);
  display.setTextSize(2);
  display.setCursor(0, 0);   display.print(ttf);    display.print(F("ms "));
  display.setTextSize(1);
  display.setCursor(80, 0);   display.print(amps);    display.print(F(" Amp"));
  display.setCursor(0, SCREEN_HEIGHT * 7 / 8);
  display.println(F("0"));
  display.setCursor(0, SCREEN_HEIGHT / 3 );
  display.println(F("5"));
  display.display();
}


void live_o_scope() //the following function works like a time laps 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;
  int i = 0;
  mVolts = 0.0;
  ttf = 0;

  display.clearDisplay();
  print_axis();

  display.setCursor(0, SCREEN_HEIGHT * 7 / 8);
  display.println(F("0"));
  display.setCursor(0, SCREEN_HEIGHT / 3);
  display.println(F("5"));

  RPM_time_old = micros();
  //while (!digitalRead(Test_PB_Pin));//incase of of debounce
  while (digitalRead(Test_PB_Pin))//Run until test pin pressed
    //for (int i = 0; i < 50 ; i++)
  {
    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;
    //ttf_sum += ttf_msec;
    ttf_sum += ttf;
    I_sum += amps; //use new max current reading
    I_mean = (I_sum / i);
    ttf_mean = (ttf_sum / i);

    // write results to OLED
    print_graph();
    display.setTextSize(2);
    display.setCursor(0, 0);   display.print(ttf_mean);    display.print(F("ms "));
    display.setTextSize(1);
    display.setCursor(80, 0);   display.print(I_mean);    display.print(F(" Amp"));
    display.setCursor(80, 8); display.print(RPM_live); display.print(F("  ")); display.setCursor(104, 8); display.print(F(" RPM"));
    display.display();
    swPresentState = digitalRead(Test_PB_Pin);
    for (int z = 0; z < (10230 - 10 * analogRead(Potentiometer_Pin)); z++) {
      asm("nop");
    }
  }
  while (!digitalRead(Test_PB_Pin)); //do nothing until test pin released
}


void live_bar_graph()  //the following function makes a bar graph of the time-to-fire results
{
  int pot_read = 0;
  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;
  int i = 0;
  int ttf_bars = 0;
  mVolts = 0.0;
  for (int y = 0; y < 50; y++)
  {
    test[y] = 0;
  }
  display.clearDisplay();
  display.setTextColor(WHITE1, BLACK1);
  print_axis();
  // draw the axis, lables and tick marks

  for (int x = 0; x < 11; x++) {
    display.drawFastVLine(x * 10 + 19, SCREEN_HEIGHT - 3, 3, WHITE1);
  }
  for (int x = 0; x < 6; x++) {
    display.drawFastVLine(69, x * SCREEN_HEIGHT / 8 + SCREEN_HEIGHT * .25, 2, WHITE1);
  }


  RPM_time_old = micros();
  //delay(100); //For Debounce
  while (!digitalRead(Test_PB_Pin));//incase of of debounce
  while (i < 50)
    //for (int i = 0; i < 50 ; i++)
  {
    i++;
    if (!digitalRead(Test_PB_Pin) || !digitalRead(Cap_PB_Pin)) {
      //i = 50; //end function if button pressed
      return;
    }
    RPM_time_old = RPM_time_new ;
    RPM_time_new = micros();
    RPM_live = 120000000 / (RPM_time_new - RPM_time_old);
    single_fire_data();
    ttf_sum += ttf;
    I_sum += amps;
    I_mean = (I_sum / i);
    ttf_mean = (ttf_sum / i);

    // 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.setCursor(120, 0); display.print(F(" "));

#if Bar_Graph_Adjustment == 1
    display.setCursor(102, 0); display.println(RPM_live);
    display.setCursor(108, 7);   display.print(F("rpm"));
#endif
    if (ttf / 100 < test_length)
    {
#if Bar_Graph_Adjustment == 2
      pot_read = 1773 - analogRead(Potentiometer_Pin); //1773=1023+750 to reverse control Use Poteniometer to set bar graph center 1350 is start then 2000 in center
      display.setCursor(12, 8); display.print(F("Center->"));
      display.setCursor(78, 8); display.print(F("<-")); display.print((pot_read + 650) / 1000.0);  display.println(F("ms")); //display center position
      ttf_bars = (ttf * 1000 - pot_read) / 100; //shift the window starting 1000ms adjustable, each bar is 100 ms wide
#endif
#if Bar_Graph_Adjustment == 1
      ttf_bars = (ttf * 1000 - 1350) / 100; //shift the window over 1350 ms, each bar is 100 ms wide
#endif
      test[ttf_bars] = test[ttf_bars] + 1;
      display.drawFastHLine(ttf_bars * 10 + 5, SCREEN_HEIGHT - 1 - test[ttf_bars],  9, WHITE1);
      display.display();
    }
    swPresentState = digitalRead(Test_PB_Pin);
#if Bar_Graph_Adjustment == 1 //read Potentiomete Pin to determine speed
    for (int z = 0; z < (10230 - 10 * analogRead(Potentiometer_Pin)); z++) {
      asm("nop");
    }
#endif
#if Bar_Graph_Adjustment == 2
    for (int z = 0; z < 10230 - 10 * 576.0; z++) { //1500 rpm
      asm("nop");
    }
#endif
  }
  while (!digitalRead(Test_PB_Pin)); //wait until button is released
}

void multi_test()
{
  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;
  int i = 0;
  mVolts = 0.0;
  ttf = 0;



  RPM_time_old = micros();
  //while (!digitalRead(Test_PB_Pin));//incase of of debounce
  while (digitalRead(Test_PB_Pin) && digitalRead(Cap_PB_Pin))//Run until test pin pressed
    //for (int i = 0; i < 50 ; i++)
  {
    i++;
    RPM_time_old = RPM_time_new ;
    RPM_time_new = micros();
    RPM_live = 120000000 / (RPM_time_new - RPM_time_old);
    single_fire_data();
    ttf_sum += ttf;
    I_sum += amps; //use new max current reading
    I_mean = (I_sum / i);
    ttf_mean = (ttf_sum / i);
    if (ttf > ttf_max)
    {
      ttf_max = ttf;
    }
    if (ttf < ttf_min)
    {
      ttf_min = ttf;
    }
    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;
    }    results_var += pow(ttf_mean - ttf, 2); // get variance
    ttf_std_dev = sqrt(results_var / numTests); // get std deviation

    // write results to OLED
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(0, 0);
    display.print(F("t="));
    display.print(ttf_mean);
    display.print(F("ms"));
    display.setTextSize(1);
    display.print(F(" #"));
    display.print(i);
    display.setCursor(0, 21);
    display.print(F("(Min="));
    display.print(ttf_min);
    display.print(F(" - Max="));
    display.print(ttf_max);
    display.println(F(")"));
    display.setCursor(0, 32);
    display.print(F("SD="));
    display.print(ttf_std_dev);
    display.print(F("; Dwell= "));
    display.print((ttf_max - ttf_min) / (float(60000 / RPM_live) / 360));
    display.println((char)167); // let's print the degree symbol!
    display.setCursor(0, 43);
    display.print(F("Max Current= "));
    display.print(ttf_max_current);
    display.println(F("amps"));
    display.setCursor(0, 54);
    display.print(RPM_live);
    display.print(F(" RPM "));
    display.print(miss);
    display.print(F(" MISFIRES "));
    display.display();// now that the display buffer is built, display it*/
    swPresentState = digitalRead(Test_PB_Pin);
    for (int z = 0; z < (10230 - 10 * analogRead(Potentiometer_Pin)); z++) {
      asm("nop");
    }
  }
  /*
    //OLED Print
  */
}


void fast_cap_test() //--- Function to check capacitor value and resistance ---//
{
#define leak_min 3000000 //3Mohm leak 
  float cap_val = 0.0;
  unsigned long new_time = 0;
  mVolts = 0;
  int cap_time = 0;
  int r_volts = 0;
#if Hardware_Version < 4
  long R8_val = 120000; // charge resistor value in ohms (120kohm range)
  long R13_val = 1000; // divider resistor
#endif
#if Hardware_Version == 4
  long R8_val = 120000; // charge resistor value in ohms (120kohm range)
  long R13_val  = 10000; // divider resistor
#endif
  unsigned long sample_time;
  sample_time = (R8_val + R13_val ) * .00000047 * 1000000 / 30; // sample_time = r_val * 47 uF * 1000(to change to microsec) / 30 (location on graph to cross 63%)
  long leak = 0;
  delay(120);
  while (!digitalRead(Test_PB_Pin));//incase of of debounce
  while (digitalRead(Test_PB_Pin) && digitalRead(Cap_PB_Pin))
  {
    digitalWrite(Cap_Charge_Out_Pin, LOW);
    //ensure the cap is discharged via charge pin low
    mVolts = (analogRead (Capacitor_Measurment_Pin) * (R8_val + R13_val) - (R13_val * source_volts)) / R8_val; //calculate voltage on capacitor
    while (mVolts > 0) { //wait to discharge capacitor
      mVolts = (analogRead (Capacitor_Measurment_Pin) * (R8_val + R13_val) - (R13_val * source_volts)) / R8_val; //calculate voltage on capacitor
    }
    delay (200); //ensure the cap is discharged via charge pin low
    digitalWrite(Cap_Charge_Out_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 (Capacitor_Measurment_Pin);  //use analog pin Capacitor_Measurment_Pin to read volts across unknown cap
      mVolts = (analogRead (Capacitor_Measurment_Pin) * (R8_val + R13_val) - (R13_val * source_volts)) / R8_val; //calculate voltage on capacitor

      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));
        }*/
      while ((micros() - new_time < sample_time) && digitalRead(Test_PB_Pin)); //delay time
    }
    digitalWrite(Cap_Charge_Out_Pin, LOW);
    display.clearDisplay();
    cap_val = ((float)cap_time / (R8_val + R13_val)) * 1000.0;
    leak = mVolts * (R8_val + R13_val ) / (source_volts - mVolts); // calculate the resistance of the unknown resistance (leakage) in voltage divider cct

    if (leak < 0 || leak > 20000000)
    {
      leak = 20000000; // Set value to 20Mohms if greater than 20M or above source voltage
    }

    display.setCursor(0, 0);
    display.setTextSize(2);
    display.println(F("CAPACITOR"));
    /*display.setTextSize(1);
      display.setTextColor(WHITE1, BLACK1);
      display.println(F("CAPACITOR TEST"));
      display.setTextColor(BLACK1, WHITE1);
      display.setCursor(90, 0);
      if (leak > leak_min && cap_val > 0.4 && cap_val < 0.6)
      {
      display.println(F(" PASS "));
      }
      else
      {
      display.println(F(" FAIL "));
      }*/
    //if (analogVals[1][0] > 10) {
    //if (leak / 1000000 > 0) {
    //if (analogVals[numReadings - 1][0] > 10) { //Consider shorted if last reading is very small
    if (mVolts > 10) { //Consider shorted if last reading is very small
      //display.fillRect(79, 16,  128 , 32, BLACK1);
      if (cap_val > 0.4 && cap_val < 0.6) display.setTextColor(WHITE1, BLACK1);
      else display.setTextColor(BLACK1, WHITE1);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   display.setCursor(0, 0);
      display.setTextSize(3);
      display.setCursor(0, SCREEN_HEIGHT / 4);
      //display.print(F("C = "));
      display.print(cap_val);   display.println(F("uF"));
      display.setTextSize(2);
      //display.setCursor(0, 24);
      if (leak > leak_min) display.setTextColor(WHITE1, BLACK1);
      else display.setTextColor(BLACK1, WHITE1);
      display.print(F("R = ")); display.print(leak / 1000000); display.println(F("Mohm"));
    }
    else {
      display.setCursor(0, SCREEN_HEIGHT / 4);
      display.println(F("SHORTED"));
      display.setCursor(0, SCREEN_HEIGHT * 3 / 4);
      display.setTextSize(1);
      display.println(F("Please open contacts"));
      digitalWrite(Cap_Charge_Out_Pin, LOW);
      display.display();
      //return; //end test here if shorted
    }
    digitalWrite(Cap_Charge_Out_Pin, LOW);
    display.display();
  }
  display.fillRect(0, SCREEN_HEIGHT / 4,  128 , SCREEN_HEIGHT, BLACK1);
  display.setCursor(0, 0);
  display.setTextSize(2);
  display.setTextColor(WHITE1, BLACK1);
  display.println(F("CAPACITOR"));
  display.println(F("  TEST"));
  display.setTextSize(1);
  display.setCursor(0, SCREEN_HEIGHT * 3 / 4);
  display.println(F(" Press Test Button"));
  display.println(F("      To Start"));
  display.display();
}

void cap_test_graph()
//--- Function to check capacitor value and resistance ---//
{
#define leak_min 3000000 //3Mohm leak 
  unsigned long new_time = 0;
  mVolts = 0;
  int cap_time = 0;
  int r_volts = 0;
#if Hardware_Version < 4
  long R8_val = 120000; // charge resistor value in ohms (120kohm range)
  long R13_val = 1000; // divider resistor
#endif
#if Hardware_Version == 4
  long R8_val = 120000; // charge resistor value in ohms (120kohm range)
  long R13_val  = 10000; // divider resistor
#endif
  unsigned long sample_time;
  sample_time = (R8_val + R13_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_Charge_Out_Pin, LOW);
  display.fillRect(0, SCREEN_HEIGHT / 4,  128 , SCREEN_HEIGHT, BLACK1);
  display.setTextColor(WHITE1, BLACK1);
  display.setTextSize(1);
  display.setCursor(0, SCREEN_HEIGHT / 2);
  display.println(F("CAPACITOR TEST GRAPH"));
  display.println(F("in progress..."));
  display.display();

  delay (150); //ensure the cap is discharged via charge pin low
  digitalWrite(Cap_Charge_Out_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 (Capacitor_Measurment_Pin);  //use analog pin A7 to read volts across unknown cap
    mVolts = (analogRead (Capacitor_Measurment_Pin) * (R8_val + R13_val) - (R13_val * source_volts)) / R8_val; //calculate voltage on capacitor
    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][0] = mVolts / 4;
      //analogVals[i][1] = 1023 * (1 - exp(-i / 30.0));
      analogVals[i][1] = 255 * (1 - exp(-i / 30.0));
    }
    while (micros() - new_time < sample_time); //delay time

  }
  display.fillRect(0, SCREEN_HEIGHT / 4,  128 , SCREEN_HEIGHT, BLACK1);
  // draw the axis, lables and tick marks
  //draw 63% line
  for (int z = 0; z < 30; z++) {
    display.drawFastHLine(10 + z * 4, SCREEN_HEIGHT / 2,  1, WHITE1);
    display.drawFastHLine(10 + z * 6, SCREEN_HEIGHT / 4 - 1,  2, WHITE1);
    display.drawLine(z * 5 + 10 , 63 - analogVals[z * 5 - 1][1] / 5.31, z * 5 + 10 , 63 - analogVals[z * 5][1] / 5.31, WHITE1);
  }
  for (int x = 0; x < 12; x++) { //draw the upper and lower limits
    display.drawFastVLine(30 + 10, SCREEN_HEIGHT / 4 + 5 * x - 1, 1, WHITE1); //30 T constant + 10 offset
  }
  display.setTextColor(WHITE1, BLACK1);
  display.drawFastHLine(10, SCREEN_HEIGHT - 1,  128 - 10, WHITE1);
  display.drawFastVLine(10, SCREEN_HEIGHT / 4,  SCREEN_HEIGHT, WHITE1);

  display.setTextColor(WHITE1, BLACK1);
  display.setTextSize(1);
  display.setCursor(0, SCREEN_HEIGHT / 2);   display.println("63%");
  display.display();
  delay (200);
  for (int i = 1; i < numReadings; i++) {
    display.drawLine(i + 10 , 63 - analogVals[i - 1][0] / 5.31, i + 10 , 63 - (analogVals[i][0]) / 5.31, WHITE1);
    display.display();
  }
  cap_val = ((float)cap_time / (R8_val + R13_val)) * 1000.0;
  /*if (cap_val > 1) { //give more time to read if large capacitance
    while (mVolts < analogRead (Capacitor_Measurment_Pin)) { //wait until capacitor quits charging
      mVolts = analogRead (Capacitor_Measurment_Pin);
      delay(2000);
    }
    }*/
  mVolts = analogRead (Capacitor_Measurment_Pin);//find voltage that capacitor charges to
  leak = mVolts * (R8_val + R13_val) / (source_volts - mVolts); // calculate the resistance of the unknown resistance (leakage) in voltage divider cct

  if (leak < 0 || leak > 20000000 )
  {
    leak = 20000000;
  }
  digitalWrite(Cap_Charge_Out_Pin, LOW);
  //if (leak / 1000000 > 0) {
  if (analogVals[numReadings - 1][0] > 10) { //Consider shorted if last reading is very small
    display.setTextSize(2);
    display.fillRect(60, SCREEN_HEIGHT / 2,  128 , SCREEN_HEIGHT, BLACK1);
    display.setTextColor(WHITE1, BLACK1);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    display.setCursor(0, 0);
    display.setCursor(50, SCREEN_HEIGHT / 2);
    display.print(cap_val);   display.println(F("uF"));
    display.setCursor(40, SCREEN_HEIGHT * 3 / 4);
    display.print(leak / 1000000); display.println(F(" Mohm"));
    display.display();
  }
  else {
    display.fillRect(0, SCREEN_HEIGHT / 4 - 1,  128 , SCREEN_HEIGHT, BLACK1);
    display.setCursor(0, SCREEN_HEIGHT / 4);
    display.setTextSize(2); display.println(F("SHORTED"));
    display.setCursor(0, SCREEN_HEIGHT * 3 / 4);
    display.setTextSize(1); display.println(F("Please open contacts"));
    digitalWrite(Cap_Charge_Out_Pin, LOW);
    display.display();
    return; //end test here if shorted
  }

  delay (1500);

  display.fillRect(0, SCREEN_HEIGHT / 4 - 1,  128 , SCREEN_HEIGHT - 4, BLACK1);
  display.setTextColor(WHITE1, BLACK1);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   display.setCursor(0, 0);
  display.setCursor(0, SCREEN_HEIGHT / 4);
  display.setTextSize(2);
  display.print(cap_val);  display.print(F(" uF "));
  display.setTextSize(1);
  display.setCursor(90, SCREEN_HEIGHT * 5 / 16);
  if (cap_val > 0.4 && cap_val < 0.6)
  {
    display.println(F(" PASS "));
  }
  else
  {
    display.setTextColor(BLACK1, WHITE1); display.print(F(" FAIL ")); display.setTextColor(WHITE1, BLACK1);
  }
  display.setCursor(0, SCREEN_HEIGHT / 2);
  display.println(F(" (Ideal .4-.6 uF)"));
  display.setTextSize(2);  display.print(leak / 1000000); display.print(F(" Mohm"));
  display.setTextSize(1);
  display.setCursor(90, SCREEN_HEIGHT * 11 / 16);
  if (leak > leak_min)  //test if > 3 Mohms
  {
    display.println(F(" PASS "));
  }
  else
  {
    display.setTextColor(BLACK1, WHITE1); display.println(F(" FAIL ")); display.setTextColor(BLACK1, WHITE1);
  }
  display.setCursor(0, SCREEN_HEIGHT * 7 / 8);
  display.println(F(" (Ideal > 3 Mohm)"));
  display.display();
}

void loop()
{
  //read potentiometer and set rpm
  rpm = analogRead(Potentiometer_Pin) / 50 * 100 + 500; // perform a read to clear register (comment out if no Potentiometer) units 100 rpm
  Mode_PB_PinState = digitalRead(Cap_PB_Pin);
  Test_PB_PinState = digitalRead(Test_PB_Pin);
  delay(100); //delay for switch debounce
  if (Mode_PB_PinState == HIGH && Test_PB_PinState && !digitalRead(Test_PB_Pin))
  {
    digitalWrite(Spark_Out_Pin, HIGH); // check for short
    for (int i = 1; i < 100; i++) {
      //delayMicroseconds(50); //delay for current to ramp up
      Vin_Digital_Max = analogRead(Current_Measure_Pin);

#if Hardware_Version == 1
      mVolts = (Vin_Digital_Max / 1024.0) * 5000.0; // raw analog read val to millvolts
      amps = ((mVolts - 2500.0) / 100.0); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
#endif
#if Hardware_Version == 2
      if (Vin_Digital_Max < 512) mVolts = 0; //do same math the keep timing same.
      else mVolts = Vin_Digital_Max - 512;
#endif
#if Hardware_Version == 3||4
      if (Vin_Digital_Max > 512) mVolts = 0; //do same math the keep timing same.
      else mVolts = 512 - Vin_Digital_Max; //Version 3.0 boards current is measured in reverseMicro_ProcessorMicro_Processorr
#endif

      digitalWrite(Spark_Out_Pin, LOW); //set Spark_Out_Pin low
      amps = ((mVolts) / 100.0 / 1023 * Vin); // millivolts to amps (utilise scale factor for ACS sensor range 20A chip
      if (amps > 3) { //Three amps in 50 microseconds is the threshold to be considered a short
        display.clearDisplay();
        display.setTextColor(WHITE1, BLACK1);
        display.setTextSize(2);
        display.setCursor(0, 0);
        display.println(Vin_Digital_Max);
        display.println(F("OUTPUT"));
        display.println(F("SHORTED!!!"));
        display.setTextSize(1);
        display.println(F("-Verify Setup"));
        display.println(F("-Cycle power to reset"));
        display.display();
        while (1) {
          display.clearDisplay();
          display.setTextColor(WHITE1, BLACK1);
          display.setTextSize(2);
          display.setCursor(0, 0);
          display.print(F("Cur "));
          display.println(analogRead(Current_Measure_Pin));
          display.print(F("Vin "));
          display.println(analogRead(Vin_Measure_Pin));
          display.print(F("Pot "));
          display.println(analogRead(Potentiometer_Pin));
          display.print(F("Cap "));
          display.println(analogRead(Capacitor_Measurment_Pin));
          display.display();
        }
        ; //Hang program until short dealt with- power must be cycled to restart
      }
      digitalWrite(Spark_Out_Pin, LOW); //set Spark_Out_Pin low
    }
    while (!digitalRead(Test_PB_Pin));  //Do nothing until test pin released
    switch (test_mode) {
      case 0: {
          single_test();
          break;
        }
      case 1: {
          live_o_scope();
          break;
        }
      case 2: {
          live_bar_graph();
          break;
        }
      case 3: {
          multi_test();
          break;
        }
      case 4: {
          fast_cap_test();
          break;
        }
      case 5: {
          cap_test_graph();
          break;
        }
    }
    delay(200); //delay for switch debounce
  }
  if (Mode_PB_PinState == LOW)
  {
    if (test_mode < 5) {
      test_mode = test_mode + 1;
    }
    else {
      test_mode = 0;
    }
    display.clearDisplay();
    display.setTextColor(WHITE1, BLACK1);
    display.setTextSize(2);
    display.setCursor(0, 0);
    switch (test_mode) {
      case 0: {
          display.println(F(" SINGLE"));
          display.println(F("FIRE TEST"));
          break;
        }
      case 1: {
          display.println(F("  LIVE"));
          display.println(F(" O-SCOPE"));
          break;
        }
      case 2: {
          display.println(F("BAR GRAPH"));
          display.println(F("  TEST"));
          break;
        }
      case 3: {
          display.println(F("MULTIFIRE"));
          display.println(F("  TEST"));
          break;
        }
      case 4: {
          display.println(F("CAPACITOR"));
          display.println(F("  TEST"));
          break;
        }
      case 5: {
          display.println(F("CAPACITOR"));
          display.println(F("GRAPH TEST"));
          break;
        }
    }
    display.setTextSize(1);
    display.setCursor(0, 48);
    display.println(F("  Press Test Button"));
    display.println(F("       To Start"));
    display.display();// now that the display buffer is built, display it
    //display.display();
    while (!digitalRead(Cap_PB_Pin));
    delay(200); //delay for switch debounce

  }
}

Last edited by Matt in California on Mon Aug 28, 2023 2:39 am, edited 1 time in total.


Myxr6turbo
Posts: 89
Joined: Sat Jul 17, 2021 2:40 am
First Name: Shawn
Last Name: Barnard
* REQUIRED* Type and Year of Model Ts owned: 1926 coupe
Location: Australia, Victoria

Re: A new DIY electronic coil tester.

Post by Myxr6turbo » Tue Aug 22, 2023 3:53 am

That's perfect. Thanks Matt.

Just uploaded the files. Going to be $128 delivered to Australia for 5. :D


Topic author
Luke
Posts: 584
Joined: Fri Dec 13, 2019 1:04 am
First Name: Luke
Last Name: P
* REQUIRED* Type and Year of Model Ts owned: 1926
Location: New Zealand

Re: A new DIY electronic coil tester.

Post by Luke » Tue Aug 22, 2023 4:20 pm

Myxr6turbo wrote:
Tue Aug 22, 2023 3:53 am
Just uploaded the files. Going to be $128 delivered to Australia for 5. :D
Is that for the PCB loaded? I'm surprised they were unable to source the simple components you referenced earlier...

Luke.

Post Reply Previous topicNext topic