Project 026 - DMM Continuity Tester

DISCLAIMER: This design is experimental, so if you decide to build one yourself then you are on your own, I can't be held responsible for any problems/issues/damage/injury that may occur if you decide to follow this build and make one yourself.

Pic1


DMM Continuity Tester V1.2


Watching YouTube videos where Multimeter reviewers reach the stage where they test the continuity beep mode of the meter by 'clicking' the probes together as fast as they can to see if they can beat the 'beep' into submission.....I thought "there must be a better way than that".

So, I immediately thought of producing a small circuit to short the probes together (p-type FET) and release in quick succession and on top of that provide a display where the timing can be adjusted. All thats required from that point is the reviewers ear to listen for the beep repeat falling apart.

An Arduino Pro Mini (5V) provides the processor, switch interface and LCD drive.

A laser cut front panel, bottom cover and a battery holder finishes it off.

Example MARK Examples (minimum) at 250ms SPACE:
- Brymen BM257 = 38ms
- Fluke 85 III = 0.9ms
- Fluke 87 = 0.9ms
- Agilent 34405A = 25ms
- Keysight 34461A - 1ms (needs Space = 300ms)
- Agilent 34401A = 20ms, but will work lower but gives continious tone
- Brymen BM786 = Better than 0.01ms
- V&A VA38 = 0.1ms (beep varies in volume to point it's hardly audible though, obviously not using a fixed beep length)
- Fluke 17B MAX = 30ms (courtesy of EEVBlog YT video)


V1.2 - I have made it all free/open source on a strictly non-commercial basis. So here's the files:
BOM
Schematic
Code
PCB Gerbers
Bottom Cover Gerbers
Front Panel (G-code & Lightburn files)


Notes:
- V1.2 offers the same same functionality as previous versions, I just added a bottom cover, integral battery holder and an on/off power switch.
- Please don't ask me to make you one, or if I have any prototypes I could sell you. Sorry!


External links:
EEVblog Forum thread -  https://www.eevblog.com/forum/projects/dmm-continuity-tester-v1-0-better-than-clicking-probes-together!/
EEVblog Mailbag Youtube video (featuring the DMM Cont. Tester) -  https://youtu.be/Xfs0dglIVOM?t=1275
EEVblog Fluke Multimeter test (featuring the DMM Cont. Tester) -  https://youtu.be/UER8fiI9WrY?t=1190


The design could go a lot further I guess, here's some ideas from the EEVBlog forum thread:

- Add a microphone to measure response time.
- Increase the speed so the likes of the BM786 can be measured (Use 16bit PWM or perhaps an STM32).
- Add some arbitary type modes, i.e. mimic running along 10pins of a connector.
- Add more output FETs with various different resistances to mimic crap probes etc.

Here's the code (without the libraries):


Arduino C++ - DMMcont.ino
1/*2DMM continuity Tester - DMMcont.ino3IanJ 25/02/2022 V1.24www.ianjohnston.com56V1.0 - First version7V1.1 - Disabled LED as it glitches the timing8v1.2 - mS changed to ms910DMM Continuity Tester11Put your DMM in continuity test mode with beep and connect the 4mm bananas.12Adjust MARK/SPACE accordingly to find out the fastest your DMM can be shorted.13Uses a p-type mosfet with a 1ohm RDS(on).14Range = 0.01ms (10uS) to 250ms1516Generally, leave SPACE at default and adjust MARK up/dn to find at what speed your DMM fails the test.1718Example MARK Examples (minumum) at 250ms SPACE:19- Brymen BM257 = 38ms20- Fluke 85 III = 0.9ms21- Fluke 87 = 0.9ms22- Agilent 34405A = 25ms23- Keysight 34461A - 1ms (needs Space = 300mS)24- Agilent 34401A = 20ms, but will work lower but gives continious tone25- Brymen BM786 = Better than 0.01ms26- V&A VA38 = 0.1ms (beep varies in volume to point it's hardly audible though, obviously not using a fixed beep length)2728Some DMM's don't adjust the length of the beep too well when running at fast MARK times, especially if Space is quite quick also.29Some DMM's though adjust the length of the beep accordingly so that the user gets more definitive feedback, i.e. 1 short = 1 beep.3031The winner is the Brymen BM786.....!3233Arduino code edited using NotePad++ and using IDE 1.8.13 for compile/upload only34Uploaded using a CP2102 USB to TTL Serial Adaptor3536Arduino Pro Mini (5Vdc/16MHz ATmega328)37D2	- S138D3	- S3	39D4	- S240D5	- CS LCD41D6	- RST LCD42D7	- A0 LCD43D8	- SCL LCD44D9	- SI LCD45D10	- LEDA LCD46D11	- S447D12	- Gate drive (BSS123)48D13	- Built in LED49*/50 51#include "TimedAction.h"52#include "U8g2lib.h"53 54// Digital Pins55#define SW1_pin 2 				// Switch S156#define SW2_pin 4 				// Switch S257#define SW3_pin 3 				// Switch S358#define SW4_pin 11 				// Switch S459#define Output_pin 12 			// Gate drive output60#define LED_pin 13 				// On-board Pro-Mini LED61 62// LCD Pins63U8G2_ST7565_ZOLEN_128X64_F_4W_SW_SPI U8G2(U8G2_MIRROR, 8, 9, 5, 7, 6);	// (U8G2_R0, /* clock=*/ 14, /* data=*/ 15, /* cs=*/ 11, /* dc=*/ 13, /* reset=*/ 12);64typedef u8g2_uint_t u8g_uint_t;65 66// Various vars67float Freq = 1;					// Hz68float Period = 250;				// ms69float Mark = 5000;				// us70unsigned int Space = 1;			// ms71long Markmax = 250000;			// us72unsigned int Spacemax = 500;	// ms73long Markmin = 1;				// us74unsigned int Spacemin = 1;		// ms75 76// Initializes TimedAction - Timer Interrupts77void TimerService01();78void TimerService02();79TimedAction Timedact01 = TimedAction(Period,TimerService01);   	// gate drive period (Mark + Space) (ms)80TimedAction Timedact02 = TimedAction(50,TimerService02);   		// key scanning (ms)81 82void setup() {83	84	delay(10);  // delay on boot, let everything settle down85	86    // LCD setup & write splash screen87	U8G2.begin();88	U8G2.setColorIndex(1);          // Pixel on89	U8G2.setContrast(10);           // Set contrast	90	U8G2.setFlipMode(1);			// Flip the screen91	U8G2.clearBuffer();92	93	U8G2.setFont(u8g2_font_logisoso16_tf);94	U8G2.setFontPosBottom();95	U8G2.drawStr(3, 20,"DMM Continuity");  // col, row 	96	U8G2.drawStr(40, 42, "Tester");  // col, row 97	98	U8G2.setFont(u8g2_font_6x10_tf);99	U8G2.setFontPosBottom();100	U8G2.drawStr(40, 54,"VER. V1.2");  // col, row 101	U8G2.drawStr(10, 64,"www.ianjohnston.com");  // col, row 102	U8G2.sendBuffer();	103	104	// setup pins105	pinMode(SW1_pin, INPUT_PULLUP);		// Mark -106	pinMode(SW2_pin, INPUT_PULLUP);		// Mark +107	pinMode(SW3_pin, INPUT_PULLUP);		// Space -108	pinMode(SW4_pin, INPUT_PULLUP);		// Space +109	pinMode(Output_pin, OUTPUT);		// Gate drive110	digitalWrite(Output_pin, LOW);111	pinMode(LED_pin, OUTPUT);			// LED112	digitalWrite(LED_pin, LOW);113	114	delay(2000);  // delay then clear screen115	U8G2.clearBuffer();116	U8G2.sendBuffer();117	118	// Calculate initial Space & Freq119	Space = Period - (Mark / 1000);		// ms120	Freq = 1 / (Period/1000);			// Calculate frequency of pulses in Hz121	122	// Update LCD123	LCD();124	125}126 127void loop() {					// A nice short main loop!128	129	// Refresh Timed Actions130	Timedact01.check();131	Timedact02.check();132 133}Codequote by Ian Johnston

 

Arduino C++ - LCD.ino
1// DMM continuity Tester - LCD.ino2// IanJ3// www.ianjohnston.com4 5// LCD6// The LCD update only happens on a keypress. This is to keep the integrity of the TimedActions since the U8G2 library can affect the timings.7 8// ********************** LCD ***********************9void LCD() {10	11	U8G2.clearBuffer();12	13	// write main screen14	U8G2.setFont(u8g2_font_9x15_tf);15	U8G2.setFontPosBottom();16	U8G2.drawStr(3, 14,"MARK");  // col, row 	17	U8G2.drawStr(67, 14,"SPACE");  // col, row 18	U8G2.drawStr(3, 49,"PERIOD");  // col, row 19	U8G2.drawStr(90, 49,"Hz");  // col, row 20	21	U8G2.setFont(u8g2_font_6x10_tf);22	U8G2.setFontPosBottom();23	U8G2.drawStr(42, 13,"ms");  // col, row 	24	U8G2.drawStr(116, 13,"ms");  // col, row 25	U8G2.drawStr(60, 48,"ms");  // col, row 26 27	// LCD Mark & Space28	U8G2.setFont(u8g2_font_logisoso16_tf);29	U8G2.setFontPosBottom();30	U8G2.setCursor(3, 33); // col, row31	32	if ( Mark <= 1000 ) {33		U8G2.print((Mark/1000)+0.01,2);34	}35	if ( Mark > 1000 && Mark <= 10000 ) {36		U8G2.print((Mark/1000)+0.01,1);37	}38	if ( Mark > 10000 ) {39		U8G2.print((Mark/1000)+0.01,0);40	}	41 42	U8G2.setCursor(67, 33); // col, row43    U8G2.print(Space);44	45	U8G2.setCursor(3, 68); // col, row46    U8G2.print(Period,0);47	48	U8G2.setCursor(90, 68); // col, row49	50	if (Freq < 100) {51		U8G2.print(Freq,1);52	} else {53		U8G2.print(Freq,0);		54	}55	56	U8G2.sendBuffer();57	58}Codequote by Ian Johnston

 

Arduino C++ - TimedActions.ino
1// DMM continuity Tester - TimedActions.ino2// IanJ3// www.ianjohnston.com4 5// Timed Actions6 7// ********************** Timed Action 01 - Gate drive ***********************8void TimerService01() {9	10	// delayMicroseconds only good up to 16383 (Arduino limitation)11	if ( Mark < 16383 ) {12		//digitalWrite(Output_pin, HIGH);    	// High13		PORTB |= _BV(PB4);						// faster than digitalWrite (bit 4 of port B)14		delayMicroseconds(abs(Mark));15		PORTB &= ~_BV(PB4);						// faster than digitalWrite (bit 4 of port B)16		//digitalWrite(Output_pin, LOW);    	// Low17		18	} else {19		//digitalWrite(Output_pin, HIGH);    	// High20		PORTB |= _BV(PB4);						// faster than digitalWrite (bit 4 of port B)21		delay(abs(Mark/1000));22		PORTB &= ~_BV(PB4);						// faster than digitalWrite (bit 4 of port B)23		//digitalWrite(Output_pin, LOW);    	// Low24	}25 26}27 28// ********************** Timed Action 02 - Keypad ***********************29void TimerService02() {30	31	byte inhibit = 0;32 33	if (digitalRead(SW1_pin) == LOW && Mark > 0 && Mark <= 1000) {34		Mark = Mark - 10;35		inhibit = 1;36	}37	if (digitalRead(SW2_pin) == LOW && Mark > 0 && Mark <= 1000) {38		Mark = Mark + 10;39		inhibit = 1;40	}	41	if (digitalRead(SW1_pin) == LOW && Mark > 1000 && Mark <= 10000) {42		Mark = Mark - 100;43		inhibit = 1;44	}45	if (digitalRead(SW2_pin) == LOW && Mark > 1000 && Mark <= 10000) {46		Mark = Mark + 100;47		inhibit = 1;48	}	49	if (digitalRead(SW1_pin) == LOW && Mark > 10000) {50		Mark = Mark - 1000;51		inhibit = 1;52	}53	if (digitalRead(SW2_pin) == LOW && Mark > 10000) {54		Mark = Mark + 1000;55		inhibit = 1;56	}	57	if (digitalRead(SW3_pin) == LOW) {58		Space = Space - 1;59		inhibit = 1;60	}61	if (digitalRead(SW4_pin) == LOW) {62		Space = Space + 1;63		inhibit = 1;64	}65	66	// low limits67	if ( Mark < Markmin ) {68		Mark = Markmin;69	}70	if ( Space < Spacemin ) {71		Space = Spacemin;72	}73	74	// high limits75	if ( Mark > Markmax ) {76		Mark = Markmax;77	}78	if ( Space > Spacemax ) {79		Space = Spacemax;80	}	81 82	// Calculate Period for Timed Action but only if a button has been pressed83	if ( inhibit == 1 ) {84		inhibit = 0;85		Period = (Mark/ 1000) + Space;			// calculate new period based on adjust Mark/Space86		Freq = 1 / (Period/1000);				// Calculate frequency of pulses87		Timedact01.setInterval(Period);88		//Timedact02.reset();89		LCD();									// Update LCD after any keypress and after TimedAction for Period has been updated90	}91}Codequote by Ian Johnston

 

Photos:

2025 06 26 13.49.22   2025 06 26 13.49.54   2025 06 26 13.50.02   2025 06 26 13.50.24   2025 06 26 13.49.39