1
6
7#include <Wire.h>
8#include <Adafruit_GFX.h>
9#include <Adafruit_SSD1306.h>
10#include <avr/pgmspace.h>
11#include <EEPROM.h>
12
13#define SCREEN_WIDTH 128
14#define SCREEN_HEIGHT 64
15#define REC_LENGTH 200
16
17
18#define OLED_RESET -1
19Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
20
21
22const char vRangeName[10][5] PROGMEM = {"A50V", "A 5V", " 50V", " 20V", " 10V", " 5V", " 2V", " 1V", "0.5V", "0.2V"};
23const char * const vstring_table[] PROGMEM = {vRangeName[0], vRangeName[1], vRangeName[2], vRangeName[3], vRangeName[4], vRangeName[5], vRangeName[6], vRangeName[7], vRangeName[8], vRangeName[9]};
24const char hRangeName[8][6] PROGMEM = {" 50ms", " 20ms", " 10ms", " 5ms", " 2ms", " 1ms", "500us", "200us"};
25const char * const hstring_table[] PROGMEM = {hRangeName[0], hRangeName[1], hRangeName[2], hRangeName[3], hRangeName[4], hRangeName[5], hRangeName[6], hRangeName[7]};
26
27int waveBuff[REC_LENGTH];
28char chrBuff[10];
29String hScale = "xxxAs";
30String vScale = "xxxx";
31
32float lsb5V = 0.0055549;
33float lsb50V = 0.051513;
34
35volatile int vRange;
36volatile int hRange;
37volatile int trigD;
38volatile int scopeP;
39volatile boolean hold = false;
40volatile boolean paraChanged = false;
41volatile int saveTimer;
42int timeExec;
43
44int dataMin;
45int dataMax;
46int dataAve;
47int rangeMax;
48int rangeMin;
49int rangeMaxDisp;
50int rangeMinDisp;
51int trigP;
52boolean trigSync;
53int att10x;
54
55void setup() {
56 pinMode(2, INPUT_PULLUP);
57 pinMode(8, INPUT_PULLUP);
58 pinMode(9, INPUT_PULLUP);
59 pinMode(10, INPUT_PULLUP);
60 pinMode(11, INPUT_PULLUP);
61 pinMode(12, INPUT);
62 pinMode(13, OUTPUT);
63
64
65 if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
66
67 for (;;);
68 }
69 loadEEPROM();
70 analogReference(INTERNAL);
71 attachInterrupt(0, pin2IRQ, FALLING);
72 startScreen();
73}
74
75void loop() {
76 digitalWrite(13, HIGH);
77 setConditions();
78 readWave();
79 digitalWrite(13, LOW);
80 dataAnalize();
81 writeCommonImage();
82 plotData();
83 dispInf();
84 display.display();
85 saveEEPROM();
86 while (hold == true) {
87 dispHold();
88 delay(10);
89 }
90}
91
92void setConditions() {
93
94 strcpy_P(chrBuff, (char*)pgm_read_word(&(hstring_table[hRange])));
95 hScale = chrBuff;
96
97
98 strcpy_P(chrBuff, (char*)pgm_read_word(&(vstring_table[vRange])));
99 vScale = chrBuff;
100
101 switch (vRange) {
102 case 0: {
103
104
105 att10x = 1;
106 break;
107 }
108 case 1: {
109
110
111 att10x = 0;
112 break;
113 }
114 case 2: {
115 rangeMax = 50 / lsb50V;
116 rangeMaxDisp = 5000;
117 rangeMin = 0;
118 rangeMinDisp = 0;
119 att10x = 1;
120 break;
121 }
122 case 3: {
123 rangeMax = 20 / lsb50V;
124 rangeMaxDisp = 2000;
125 rangeMin = 0;
126 rangeMinDisp = 0;
127 att10x = 1;
128 break;
129 }
130 case 4: {
131 rangeMax = 10 / lsb50V;
132 rangeMaxDisp = 1000;
133 rangeMin = 0;
134 rangeMinDisp = 0;
135 att10x = 1;
136 break;
137 }
138 case 5: {
139 rangeMax = 5 / lsb5V;
140 rangeMaxDisp = 500;
141 rangeMin = 0;
142 rangeMinDisp = 0;
143 att10x = 0;
144 break;
145 }
146 case 6: {
147 rangeMax = 2 / lsb5V;
148 rangeMaxDisp = 200;
149 rangeMin = 0;
150 rangeMinDisp = 0;
151 att10x = 0;
152 break;
153 }
154 case 7: {
155 rangeMax = 1 / lsb5V;
156 rangeMaxDisp = 100;
157 rangeMin = 0;
158 rangeMinDisp = 0;
159 att10x = 0;
160 break;
161 }
162 case 8: {
163 rangeMax = 0.5 / lsb5V;
164 rangeMaxDisp = 50;
165 rangeMin = 0;
166 rangeMinDisp = 0;
167 att10x = 0;
168 break;
169 }
170 case 9: {
171 rangeMax = 0.2 / lsb5V;
172 rangeMaxDisp = 20;
173 rangeMin = 0;
174 rangeMinDisp = 0;
175 att10x = 0;
176 break;
177 }
178 }
179}
180
181void writeCommonImage() {
182 display.clearDisplay();
183 display.setTextColor(WHITE);
184 display.setCursor(86, 0);
185 display.println(F("av V"));
186 display.drawFastVLine(26, 9, 55, WHITE);
187 display.drawFastVLine(127, 9, 55, WHITE);
188
189 display.drawFastHLine(24, 9, 7, WHITE);
190 display.drawFastHLine(24, 36, 2, WHITE);
191 display.drawFastHLine(24, 63, 7, WHITE);
192
193 display.drawFastHLine(51, 9, 3, WHITE);
194 display.drawFastHLine(51, 63, 3, WHITE);
195
196 display.drawFastHLine(76, 9, 3, WHITE);
197 display.drawFastHLine(76, 63, 3, WHITE);
198
199 display.drawFastHLine(101, 9, 3, WHITE);
200 display.drawFastHLine(101, 63, 3, WHITE);
201
202 display.drawFastHLine(123, 9, 5, WHITE);
203 display.drawFastHLine(123, 63, 5, WHITE);
204
205 for (int x = 26; x <= 128; x += 5) {
206 display.drawFastHLine(x, 36, 2, WHITE);
207 }
208 for (int x = (127 - 25); x > 30; x -= 25) {
209 for (int y = 10; y < 63; y += 5) {
210 display.drawFastVLine(x, y, 2, WHITE);
211 }
212 }
213}
214
215void readWave() {
216 if (att10x == 1) {
217 pinMode(12, OUTPUT);
218 digitalWrite(12, LOW);
219 } else {
220 pinMode(12, INPUT);
221 }
222
223 switch (hRange) {
224
225 case 0: {
226 timeExec = 400 + 50;
227 ADCSRA = ADCSRA & 0xf8;
228 ADCSRA = ADCSRA | 0x07;
229 for (int i = 0; i < REC_LENGTH; i++) {
230 waveBuff[i] = analogRead(0);
231 delayMicroseconds(1888);
232 }
233 break;
234 }
235
236 case 1: {
237 timeExec = 160 + 50;
238 ADCSRA = ADCSRA & 0xf8;
239 ADCSRA = ADCSRA | 0x07;
240 for (int i = 0; i < REC_LENGTH; i++) {
241 waveBuff[i] = analogRead(0);
242 delayMicroseconds(688);
243 }
244 break;
245 }
246
247 case 2: {
248 timeExec = 80 + 50;
249 ADCSRA = ADCSRA & 0xf8;
250 ADCSRA = ADCSRA | 0x07;
251 for (int i = 0; i < REC_LENGTH; i++) {
252 waveBuff[i] = analogRead(0);
253 delayMicroseconds(288);
254 }
255 break;
256 }
257
258 case 3: {
259 timeExec = 40 + 50;
260 ADCSRA = ADCSRA & 0xf8;
261 ADCSRA = ADCSRA | 0x07;
262 for (int i = 0; i < REC_LENGTH; i++) {
263 waveBuff[i] = analogRead(0);
264 delayMicroseconds(88);
265 }
266 break;
267 }
268
269 case 4: {
270 timeExec = 16 + 50;
271 ADCSRA = ADCSRA & 0xf8;
272 ADCSRA = ADCSRA | 0x06;
273 for (int i = 0; i < REC_LENGTH; i++) {
274 waveBuff[i] = analogRead(0);
275 delayMicroseconds(24);
276 }
277 break;
278 }
279
280 case 5: {
281 timeExec = 8 + 50;
282 ADCSRA = ADCSRA & 0xf8;
283 ADCSRA = ADCSRA | 0x05;
284 for (int i = 0; i < REC_LENGTH; i++) {
285 waveBuff[i] = analogRead(0);
286 delayMicroseconds(12);
287 }
288 break;
289 }
290
291 case 6: {
292 timeExec = 4 + 50;
293 ADCSRA = ADCSRA & 0xf8;
294 ADCSRA = ADCSRA | 0x04;
295 for (int i = 0; i < REC_LENGTH; i++) {
296 waveBuff[i] = analogRead(0);
297 delayMicroseconds(4);
298
299 asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
300 asm("nop"); asm("nop"); asm("nop");
301 }
302 break;
303 }
304
305 case 7: {
306 timeExec = 2 + 50;
307 ADCSRA = ADCSRA & 0xf8;
308 ADCSRA = ADCSRA | 0x02;
309 for (int i = 0; i < REC_LENGTH; i++) {
310 waveBuff[i] = analogRead(0);
311
312 asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
313 asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
314 asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
315 }
316 break;
317 }
318 }
319}
320
321void dataAnalize() {
322 int d;
323 long sum = 0;
324
325
326 dataMin = 1023;
327 dataMax = 0;
328 for (int i = 0; i < REC_LENGTH; i++) {
329 d = waveBuff[i];
330 sum = sum + d;
331 if (d < dataMin) {
332 dataMin = d;
333 }
334 if (d > dataMax) {
335 dataMax = d;
336 }
337 }
338
339
340 dataAve = (sum + 10) / 20;
341
342
343 if (vRange <= 1) {
344 rangeMin = dataMin - 20;
345 rangeMin = (rangeMin / 10) * 10;
346 if (rangeMin < 0) {
347 rangeMin = 0;
348 }
349 rangeMax = dataMax + 20;
350 rangeMax = ((rangeMax / 10) + 1) * 10;
351 if (rangeMax > 1020) {
352 rangeMax = 1023;
353 }
354
355 if (att10x == 1) {
356 rangeMaxDisp = 100 * (rangeMax * lsb50V);
357 rangeMinDisp = 100 * (rangeMin * lsb50V);
358 } else {
359 rangeMaxDisp = 100 * (rangeMax * lsb5V);
360 rangeMinDisp = 100 * (rangeMin * lsb5V);
361 }
362 } else {
363
364 }
365
366
367 for (trigP = ((REC_LENGTH / 2) - 51); trigP < ((REC_LENGTH / 2) + 50); trigP++) {
368 if (trigD == 0) {
369 if ((waveBuff[trigP - 1] < (dataMax + dataMin) / 2) && (waveBuff[trigP] >= (dataMax + dataMin) / 2)) {
370 break;
371 }
372 } else {
373 if ((waveBuff[trigP - 1] > (dataMax + dataMin) / 2) && (waveBuff[trigP] <= (dataMax + dataMin) / 2)) {
374 break;
375 }
376 }
377 }
378 trigSync = true;
379 if (trigP >= ((REC_LENGTH / 2) + 50)) {
380 trigP = (REC_LENGTH / 2);
381 trigSync = false;
382 }
383}
384
385void startScreen() {
386 display.clearDisplay();
387 display.setTextSize(1);
388 display.setTextColor(WHITE);
389 display.setCursor(10, 25);
390 display.println(F("PM.GOHARIAN"));
391 display.setCursor(10, 45);
392 display.println(F("Pen oscope"));
393 display.display();
394 delay(5000);
395 display.clearDisplay();
396 display.setTextSize(1);
397}
398
399void dispHold() {
400 display.fillRect(32, 12, 24, 8, BLACK);
401 display.setCursor(32, 12);
402 display.print(F("Hold"));
403 display.display();
404}
405
406void dispInf() {
407 float voltage;
408
409 display.setCursor(2, 0);
410 display.print(vScale);
411 if (scopeP == 0) {
412 display.drawFastHLine(0, 7, 27, WHITE);
413 display.drawFastVLine(0, 5, 2, WHITE);
414 display.drawFastVLine(26, 5, 2, WHITE);
415 }
416
417
418 display.setCursor(34, 0);
419 display.print(hScale);
420 if (scopeP == 1) {
421 display.drawFastHLine(32, 7, 33, WHITE);
422 display.drawFastVLine(32, 5, 2, WHITE);
423 display.drawFastVLine(64, 5, 2, WHITE);
424 }
425
426
427 display.setCursor(75, 0);
428 if (trigD == 0) {
429 display.print(char(0x18));
430 } else {
431 display.print(char(0x19));
432 }
433 if (scopeP == 2) {
434 display.drawFastHLine(71, 7, 13, WHITE);
435 display.drawFastVLine(71, 5, 2, WHITE);
436 display.drawFastVLine(83, 5, 2, WHITE);
437 }
438
439
440 if (att10x == 1) {
441 voltage = dataAve * lsb50V / 10.0;
442 } else {
443 voltage = dataAve * lsb5V / 10.0;
444 }
445 dtostrf(voltage, 4, 2, chrBuff);
446 display.setCursor(98, 0);
447 display.print(chrBuff);
448
449
450
451 voltage = rangeMaxDisp / 100.0;
452 if (vRange == 1 || vRange > 4) {
453 dtostrf(voltage, 4, 2, chrBuff);
454 } else {
455 dtostrf(voltage, 4, 1, chrBuff);
456 }
457 display.setCursor(0, 9);
458 display.print(chrBuff);
459
460 voltage = (rangeMaxDisp + rangeMinDisp) / 200.0;
461 if (vRange == 1 || vRange > 4) {
462 dtostrf(voltage, 4, 2, chrBuff);
463 } else {
464 dtostrf(voltage, 4, 1, chrBuff);
465 }
466 display.setCursor(0, 33);
467 display.print(chrBuff);
468
469 voltage = rangeMinDisp / 100.0;
470 if (vRange == 1 || vRange > 4) {
471 dtostrf(voltage, 4, 2, chrBuff);
472 } else {
473 dtostrf(voltage, 4, 1, chrBuff);
474 }
475 display.setCursor(0, 57);
476 display.print(chrBuff);
477
478
479 if (trigSync == false) {
480 display.setCursor(60, 55);
481 display.print(F("Unsync"));
482 }
483}
484
485void plotData() {
486 long y1, y2;
487 for (int x = 0; x <= 98; x++) {
488 y1 = map(waveBuff[x + trigP - 50], rangeMin, rangeMax, 63, 9);
489 y1 = constrain(y1, 9, 63);
490 y2 = map(waveBuff[x + trigP - 49], rangeMin, rangeMax, 63, 9);
491 y2 = constrain(y2, 9, 63);
492 display.drawLine(x + 27, y1, x + 28, y2, WHITE);
493 }
494}
495
496void saveEEPROM() {
497 if (paraChanged == true) {
498 saveTimer = saveTimer - timeExec;
499 if (saveTimer < 0) {
500 paraChanged = false;
501 EEPROM.write(0, vRange);
502 EEPROM.write(1, hRange);
503 EEPROM.write(2, trigD);
504 EEPROM.write(3, scopeP);
505 }
506 }
507}
508
509void loadEEPROM() {
510 int x;
511 x = EEPROM.read(0);
512 if ((x < 0) || (x > 9)) {
513 x = 3;
514 }
515 vRange = x;
516
517 x = EEPROM.read(1);
518 if ((x < 0) || (x > 7)) {
519 x = 3;
520 }
521 hRange = x;
522 x = EEPROM.read(2);
523 if ((x < 0) || (x > 1)) {
524 x = 1;
525 }
526 trigD = x;
527 x = EEPROM.read(3);
528 if ((x < 0) || (x > 2)) {
529 x = 1;
530 }
531 scopeP = x;
532}
533
534void pin2IRQ() {
535
536
537
538 int x;
539 x = PINB;
540
541 if ( (x & 0x07) != 0x07) {
542 saveTimer = 5000;
543 paraChanged = true;
544 }
545
546 if ((x & 0x01) == 0) {
547 scopeP++;
548 if (scopeP > 2) {
549 scopeP = 0;
550 }
551 }
552
553 if ((x & 0x02) == 0) {
554 if (scopeP == 0) {
555 vRange++;
556 if (vRange > 9) {
557 vRange = 9;
558 }
559 }
560 if (scopeP == 1) {
561 hRange++;
562 if (hRange > 7) {
563 hRange = 7;
564 }
565 }
566 if (scopeP == 2) {
567 trigD = 0;
568 }
569 }
570
571 if ((x & 0x04) == 0) {
572 if (scopeP == 0) {
573 vRange--;
574 if (vRange < 0) {
575 vRange = 0;
576 }
577 }
578 if (scopeP == 1) {
579 hRange--;
580 if (hRange < 0) {
581 hRange = 0;
582 }
583 }
584 if (scopeP == 2) {
585 trigD = 1;
586 }
587 }
588
589 if ((x & 0x08) == 0) {
590 hold = ! hold;
591 }
592}
593
Anonymous user
2 years ago
Hi.great project. Please can you help me how to ajust position?thank you