-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLED_8050A_TM1637_RT_Cont.ino
486 lines (443 loc) · 13.8 KB
/
LED_8050A_TM1637_RT_Cont.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
/*
LED_8050A_TM1637_RT_Cont.ino
LED display implementation for Fluke 8050A multimeter
- for TM1637 display
- with Continuity tone
Original code created 2021.06.4
Michael Damkier
Hamburg, Germany
(michael@vondervotteimittiss.com)
Modified 2021.06.11
John Wolfe (jpwolfe31@yahoo.com)
for use with TM1637 six digit display
and to add continuity tone using LF347
*/
/*
PIN ASSIGNMENTS
*/
#include <Arduino.h>
#include <TM1637TinyDisplay6.h> // Include 6-Digit Display Class Header
// Define TM1637 Digital Pins
#define CLK 12
#define DIO 13
// 8050A strobe lines
#define PIN_ST0 A0
#define PIN_ST1 A1
#define PIN_ST2 A2
#define PIN_ST3 A3
#define PIN_ST4 A4
// 8050A scancode lines
#define PIN_Z 2
#define PIN_Y 3
#define PIN_X 4
#define PIN_W 5
// Note - lines below are reversed from Strobe_8050A test software
// which uses PIN_HV 7 and PIN_DP 6
#define PIN_HV 6
#define PIN_DP 7
// Continuity additions
// When using D0 and D1, the serial port is not available for upload to the Uno,
// so these lines need to be disconnected when uploading the sketch
#define PIN_Fb_VOLT 0 // for check not in voltage mode
#define PIN_Fc_MA 1 // for check not in mA mode
#define PIN_RNGa 8 // for check in 200 ohm range
#define PIN_RNGb 9 // for check in 200 ohm range
#define PIN_RNGc 10 // for check in 200 ohm range
#define PIN_TONE 11 // for tone generation
// Continuity testing works by confirming the meter is in resistance mode in the 200 ohm range.
// Ohms being selected is confirmed when VOLT and MA are both 0 volts on IC pins 6(Fb) and 19(Fc)
// R200 range selection is confirmed by decoding IC pins 3(RNGa), 4(RNGb) and 5(RNGc) as follows when
// the range buttons are selected:
// RNGa-c 3 4 5 (IC pins)
// 200 5 5 0 (5 = 5 volts, 0 = 0 volts)
// 2k 0 5 5
// 20k 5 0 5
// 200k 0 0 5
// 2m 5 5 5
// 20m 0 0 0
// 200 and 2k 0 5 0
// 2m and 20m 5 0 0
// R200 is confirmed by finding 5 5 0 on pins 3, 4 and 5 through inputs D8, D9 and D10.
// Continuity is checked by measuring the ADC input voltage to determine resistance <50 ohms.
// The continuity tone is generated with a tone on pin 11.
/*
CONSTANTS
*/
// strobe lines
#define NUM_STROBES 5
#define ST0 0
#define ST1 1
#define ST2 2
#define ST3 3
#define ST4 4
// scancode lines
#define NUM_SCANCODES 6
#define SC0 0
#define SC1 1
#define SC2 2
#define SC3 3
#define SC4 4
#define SC5 5
#define SCANCODE_Z 0
#define SCANCODE_Y 1
#define SCANCODE_X 2
#define SCANCODE_W 3
#define SCANCODE_HV 4
#define SCANCODE_DP 5
#define SCANCODE_DB SCANCODE_Y
#define SCANCODE_1 SCANCODE_Z
#define SCANCODE_MINUS SCANCODE_W
#define SCANCODE_PLUS SCANCODE_X
#define SCANCODE_REL SCANCODE_DP
// pin arrays
static const uint8_t StrobePins[ NUM_STROBES ] = {
PIN_ST0,
PIN_ST1,
PIN_ST2,
PIN_ST3,
PIN_ST4
};
static const uint8_t ScanCodePins[ NUM_SCANCODES ] = {
PIN_Z, // 2^0
PIN_Y, // 2^1
PIN_X, // 2^2
PIN_W, // 2^3
PIN_HV,
PIN_DP
};
// Pin Change Interrupts
// Enable pin change interrupts in the PCICR Pin Change Interrupt Control Register
// by setting the appropriate PCIEn Pin Change Interrupt Enable bit(s)
// PCIE0 enables Arduino pins 8-13, mask bits PCINT0-5
// PCIE1 enables Arduino pins A0-A5, mask bits PCINT8-13
// PCIE2 enables Arduino pins 0-7, mask bits PCINT16-23
// Set the desired pin(s) in the appropriate PCMSKn Pin Change Mask Register
// PCMSK0 handles bits PCINT0-5
// PCMSK1 handles bits PCINT8-13
// PCMSK2 handles bits PCINT16-23
// for example, enable a pin change interrupt on Arduino pin 7
// PCICR = _BV( PCIE2 );
// PCMSK2 = _BV( PCINT23 );
//
//------------------------------------------------------------------
// Arduino pins for the 8050A strobe lines are defined in PIN_ST0-4.
// Adjust the following values, accordingly.
//------------------------------------------------------------------
//
// the control register interrupt enable bit
#define STROBE_INTERRUPT_ENABLE _BV( PCIE1 )
// pin change mask register
#define STROBE_INTERRUPT_MASK_REGISTER PCMSK1
// The ISR is called on the vector PCINTn_vect, corresponding PCIEn.
#define STROBE_INTERRUPT_VECTOR PCINT1_vect
// This array maps the Arduino pins used for the strobes to
// the appropriate bit-mask for setting the PCMSKn register.
static const uint8_t StrobePin2PCINT[ NUM_STROBES ] = {
_BV( PCINT8 ),
_BV( PCINT9 ),
_BV( PCINT10 ),
_BV( PCINT11 ),
_BV( PCINT12 )
};
// number of digits in the display
#define NUM_DIGITS 6
/*
TM1637 segment mapping DP, G, F, E, D, C, B, A and numbers
*/
#define LED_SEGMENT_A B00000001
#define LED_SEGMENT_B B00000010
#define LED_SEGMENT_C B00000100
#define LED_SEGMENT_D B00001000
#define LED_SEGMENT_E B00010000
#define LED_SEGMENT_F B00100000
#define LED_SEGMENT_G B01000000
#define LED_SEGMENT_DP B10000000
#define LED_SEGMENT_ALL B01111111
#define LED_SEGMENT_NONE B00000000
#define LED_SEGMENT_N0 B00111111
#define LED_SEGMENT_N1 B00000110
#define LED_SEGMENT_N2 B01011011
#define LED_SEGMENT_N3 B01001111
#define LED_SEGMENT_N4 B01100110
#define LED_SEGMENT_N5 B01101101
#define LED_SEGMENT_N6 B01111101
#define LED_SEGMENT_N7 B00000111
#define LED_SEGMENT_N8 B01111111
#define LED_SEGMENT_N9 B01101111
// for TM1637 display
TM1637TinyDisplay6 display(CLK, DIO); // 6-Digit Display Class
/*
GLOBALS
*/
// strobe position (ISR)
volatile uint8_t st;
// 8050A scancode buffer (ISR)
volatile uint8_t scanCodes[ NUM_STROBES ][ NUM_SCANCODES ];
// update display flag (ISR)
volatile boolean displayUpdate = false;
// TM1637 digit data
uint8_t digits[ NUM_DIGITS ] = {
LED_SEGMENT_NONE,
LED_SEGMENT_NONE,
LED_SEGMENT_NONE,
LED_SEGMENT_NONE,
LED_SEGMENT_NONE,
LED_SEGMENT_NONE
};
uint8_t digits_segments[ 10 ] = {
LED_SEGMENT_N0,
LED_SEGMENT_N1,
LED_SEGMENT_N2,
LED_SEGMENT_N3,
LED_SEGMENT_N4,
LED_SEGMENT_N5,
LED_SEGMENT_N6,
LED_SEGMENT_N7,
LED_SEGMENT_N8,
LED_SEGMENT_N9,
};
// not used - low-battery indicator
// boolean loBatt = false;
/*
FUNCTIONS
*/
// pin change interrupt service routine
// - reads the scancode values from the 8050A
// - sets the displayUpdate flag when all strobes are read
ISR( STROBE_INTERRUPT_VECTOR )
{
if ( digitalRead( StrobePins[ st ] ) == LOW )
{
// that was a falling transition
// (In the 4054/55/56 LCD drivers datasheet, it shows
// the data being latched on the strobe falling edge.)
// now, read the scan code values
for ( uint8_t i = SC0; i < NUM_SCANCODES; i++ )
{
scanCodes[ st ][ i ] = digitalRead( ScanCodePins[ i ] );
}
// next time, next strobe
st++;
if ( st >= NUM_STROBES )
{
// scancodes for all strobes are read
st = ST0; // reset strobe counter
// now is the time to update the display
displayUpdate = true;
}
// enable the appropriate strobe pin
STROBE_INTERRUPT_MASK_REGISTER = StrobePin2PCINT[ st ];
}
}
void formatDigits()
{
// clear digits
for ( uint8_t i = 0; i < NUM_DIGITS; i++ )
{
digits[ i ] = 0;
}
// convert BCD coding in digits 1 to 4 to LCD segment coding
uint8_t code;
uint8_t mask;
// obtain BCD codes from scancodes
for ( uint8_t i = ST1; i <= ST4; i++ )
{
code = SCANCODE_W; // MSB
mask = B00001000;
while ( mask )
{
if ( scanCodes[ i ][ code ] )
digits[ i ] |= mask;
code--;
mask >>= 1;
}
// Convert BCD coding to LCD segment coding
if (digits[ i ] <= 0x9) {
digits[ i ] = digits_segments [digits[ i ]];
}
else digits[ i ] = LED_SEGMENT_NONE; // for blank case 0xf
}
// set digit 0 (minus, 1, indicator BT)
// In the LED driver this digit uses no segment decode.
if ( scanCodes[ ST0 ][ SCANCODE_MINUS ] && ! scanCodes[ ST0 ][ SCANCODE_PLUS ] )
{
// The 8050A LCD displays both minus and plus signs.
// The plus sign is made up of the minus sign and the vertical plus segments.
// So, to correctly display minus, check that it is not on as a part of plus.
digits[ 0 ] |= LED_SEGMENT_G;
}
if ( scanCodes[ ST0 ][ SCANCODE_1 ] )
{
digits[ 0 ] |= (LED_SEGMENT_B | LED_SEGMENT_C);
}
// if ( loBatt ) // not used
// {
// digits[ 0 ] |= LED_SEGMENT_A;
// }
//
// Note - the following code was moved down from above so as not to interfere
// with revised BCD to LED segment coding
// set decimal points
// In the 8050A LCD display the dp is to the left of the digit, i.e., strobe 1-4.
// In the LED display, the dp is to the right, so map to digits 0-3.
for ( uint8_t i = ST1; i <= ST4; i++ )
{
if ( scanCodes[ i ][ SCANCODE_DP ] )
{
digits[ i - 1 ] |= LED_SEGMENT_DP;
}
}
// set digit 5 (indicators dB, HV, REL)
// In the LED driver this digit 5 uses no segment decode.
if ( scanCodes[ ST0 ][ SCANCODE_DB ] )
{
digits[ 5 ] |= LED_SEGMENT_A;
}
if ( scanCodes[ ST0 ][ SCANCODE_HV ] )
{
digits[ 5 ] |= LED_SEGMENT_G;
}
if ( scanCodes[ ST0 ][ SCANCODE_REL ] )
{
digits[ 5 ] |= LED_SEGMENT_D;
}
return;
}
void testContinuity()
{
// Check if unit just turned on. If so, do not generate tone.
if (millis() < 2000) return;
// Determine if in ohm mode (volt and ma not selected) and 200 ohm range selected
// If so, tone should be played if <50 ohms
bool volt_test = false;
bool ma_test = false;
bool r200_test = false;
bool r_test = false;
int r_measure = 0;
if( digitalRead(PIN_Fb_VOLT) == LOW) volt_test = true;
if( digitalRead(PIN_Fc_MA) == LOW) ma_test = true;
if( (digitalRead(PIN_RNGa) == HIGH) &&
(digitalRead(PIN_RNGb) == HIGH) &&
(digitalRead(PIN_RNGc) == LOW) ) r200_test = true;
r_measure = analogRead(A5);
r_measure = analogRead(A5);
// check if less than 50 ohms
// (4.412 A5 / 4.964 supply) times 1024 is 910
if( r_measure > 910 ) {r_test = true;}
if( volt_test && ma_test && r200_test && r_test)
{
// modify tone pitch as desired
int freq = 2000;
long dur = 100; // in ms, to reduce intermittent drop-outs
tone(PIN_TONE, freq, dur);
}
return;
}
void writeDigits()
{
display.setSegments(digits);
}
void updateDisplay()
{
// displayUpdate flag is set in the ISR
if ( displayUpdate )
{
displayUpdate = false;
formatDigits();
writeDigits();
}
}
// The Arduino setup and loop
void setup(void)
{
// Serial.begin(9600); // for debugging with serial monitor
// for TM1637 display
display.setBrightness(BRIGHT_HIGH);
display.clear();
// initialize strobe and scancode pins
for ( uint8_t i = ST0; i < NUM_STROBES; i++ )
{
pinMode( StrobePins[ i ], INPUT );
}
for ( uint8_t i = 0; i < NUM_SCANCODES; i++ )
{
pinMode( ScanCodePins[ i ], INPUT );
}
// enable pin change interrupts
cli();
st = ST0; // initialize the strobe counter
PCICR = STROBE_INTERRUPT_ENABLE;
STROBE_INTERRUPT_MASK_REGISTER = StrobePin2PCINT[ st ];
sei();
// for continuity testing
pinMode( PIN_Fb_VOLT, INPUT ); // note - no pull up resistors on inputs
pinMode( PIN_Fc_MA, INPUT );
pinMode( PIN_RNGa, INPUT );
pinMode( PIN_RNGb, INPUT );
pinMode( PIN_RNGc, INPUT );
pinMode ( A5, INPUT ); // analog read
}
void loop(void)
{
updateDisplay();
testContinuity();
}
/*
Connections
The 328P and 8050A ICs use GND as their +5 VCC and -5 as their GND
328P IC 8050A IC other board connects
1 RST NC connects to 8050A IC pin 40 VCC(gnd) through 10k resistor
2 D0 6 Fb (volt)
3 D1 19 Fc (mA)
4 D2 37 Z
5 D3 36 Y
6 D4 35 X
7 VCC 40 VCC (gnd) also connects to LED VCC
8 GND 20 GND (-5) also connects to LED GND and passive buzzer
9 XTAL NC connects to GND through 20pf cap
10 XTAL NC connects to GND through 20pf cap
11 D5 34 W
12 D6 23 HV
13 D7 22 DP
14 D8 3 RNGa
15 D9 4 RNGb
16 D10 5 RNGc
17 D11 NC connects to passive buzzer through 100 ohm resistor
18 D12 NC connects to LED CLK
19 D13 NC connects to LED DIO
20 VCC 40 VCC (gnd)
21 AREF NC
22 GND 20 GND (-5)
23 A0 15 ST0
24 A1 14 ST1
25 A2 13 ST2
26 A3 12 ST3
27 A4 11 ST4
28 A5 NC connects to LF347 pin 7 through 15k ohm resistor
LED Display
VCC connects to pin 40 of 8050A IC
GND connects to pin 20 of 8050A IC
DIO connects to pin 19 of 328P
CLK connects to pin 18 of 328P
LF347
OA1 is configured as an ultra high input impedance voltage follower buffer to sense
the voltage from the rear lead of R8 (the 220K 2 watt resistor) on the 8050A board
OA2 is configured as an inverter amplifier with a 10x gain to shift voltage
from the 0 to 6 volt range into the 0 to -5 volt range required for the 328P
and to better scale the desired range
1 OA1out connects to OA1- and to a 2k ohm resistor to OA2-
2 OA1- connects to OA1 out
3 OA1+ connects to the rear lead of R8 (220k ohm 2 watt resistor) through pin header
4 +VCC (+6) connects to TP3 on 8050A board through pin header
5 OA2+ connects to ground (pin 40 of 8050A IC (VCC (gnd)))
6 OA2- connects to a 2k ohm resistor to OA1out and to a 20k ohm resistor to OA2out
7 OA2out connects to 20k ohm resistor to OA2- and to a 15k ohm input
protection resistor to 328A pin 28(A5)
8 NC
9 NC
10 NC
11 -VCC (-5) connect to 8050A IC pin 20 (GND (-5))
12 NC
13 NC
14 NC
*/