Components and supplies
1N4148 – General Purpose Fast Switching
Tactile Switch, Top Actuated
Arduino Nano R3
0.96" OLED 64x128 Display Module
Apps and platforms
Arduino IDE
Project description
Code
code
c_cpp
1/* 2 (_20190212_OLEDoscilloscope.ino) 3 1285byte ram free 4 2019/02/12 5*/ 6 7#include <Wire.h> 8#include <Adafruit_GFX.h> 9#include <Adafruit_SSD1306.h> 10#include <avr/pgmspace.h> // PROGMEM 11#include <EEPROM.h> 12 13#define SCREEN_WIDTH 128 // OLED display width 14#define SCREEN_HEIGHT 64 // OLED display height 15#define REC_LENGTH 200 // 16 17// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) 18#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) 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"}; // \\0 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"}; // (48 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]; // (RAM) 28char chrBuff[10]; // 29String hScale = "xxxAs"; 30String vScale = "xxxx"; 31 32float lsb5V = 0.0055549; // 5V0.005371 V/1LSB 33float lsb50V = 0.051513; // 50V 0.05371 34 35volatile int vRange; // 0:A50V, 1:A 5V, 2:50V, 3:20V, 4:10V, 5:5V, 6:2V, 7:1V, 8:0.5V 36volatile int hRange; // 0:50m, 1:20m, 2:10m, 3:5m, 4;2m, 5:1m, 6:500u, 7;200u 37volatile int trigD; // 0:1: 38volatile int scopeP; // 0:, 1:, 2: 39volatile boolean hold = false; // 40volatile boolean paraChanged = false; // true 41volatile int saveTimer; // EEPROM 42int timeExec; // (ms) 43 44int dataMin; // (min:0) 45int dataMax; // (max:1023) 46int dataAve; // 10 max:10230) 47int rangeMax; // 48int rangeMin; // 49int rangeMaxDisp; // max100 50int rangeMinDisp; // min 51int trigP; // 52boolean trigSync; // 53int att10x; // 1 54 55void setup() { 56 pinMode(2, INPUT_PULLUP); // (int0 57 pinMode(8, INPUT_PULLUP); // Select 58 pinMode(9, INPUT_PULLUP); // Up 59 pinMode(10, INPUT_PULLUP); // Down 60 pinMode(11, INPUT_PULLUP); // Hold 61 pinMode(12, INPUT); // 1/10 62 pinMode(13, OUTPUT); // 63 64 // Serial.begin(115200); // RAM 65 if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64 66 // Serial.println(F("SSD1306 failed")); 67 for (;;); // Don't proceed, loop forever 68 } 69 loadEEPROM(); // EEPROM 70 analogReference(INTERNAL); // ADC1.1Vvref) 71 attachInterrupt(0, pin2IRQ, FALLING); // 72 startScreen(); // 73} 74 75void loop() { 76 digitalWrite(13, HIGH); 77 setConditions(); // RAM40 78 readWave(); // (1.6ms ) 79 digitalWrite(13, LOW); // 80 dataAnalize(); // (0.4-0.7ms) 81 writeCommonImage(); // (4.6ms) 82 plotData(); // (5.4ms+) 83 dispInf(); // (6.2ms) 84 display.display(); // (37ms) 85 saveEEPROM(); // EEPROM 86 while (hold == true) { // Hold 87 dispHold(); 88 delay(10); 89 } 90} 91 92void setConditions() { // 93 // PROGMEM 94 strcpy_P(chrBuff, (char*)pgm_read_word(&(hstring_table[hRange]))); // 95 hScale = chrBuff; // hScale 96 97 // 98 strcpy_P(chrBuff, (char*)pgm_read_word(&(vstring_table[vRange]))); // 99 vScale = chrBuff; // vScale 100 101 switch (vRange) { // 102 case 0: { // Auto50V 103 // rangeMax = 1023; 104 // rangeMin = 0; 105 att10x = 1; // 106 break; 107 } 108 case 1: { // Auto 5V 109 // rangeMax = 1023; 110 // rangeMin = 0; 111 att10x = 0; // 112 break; 113 } 114 case 2: { // 50V 115 rangeMax = 50 / lsb50V; // 116 rangeMaxDisp = 5000; // 100 117 rangeMin = 0; 118 rangeMinDisp = 0; 119 att10x = 1; // 120 break; 121 } 122 case 3: { // 20V 123 rangeMax = 20 / lsb50V; // 124 rangeMaxDisp = 2000; 125 rangeMin = 0; 126 rangeMinDisp = 0; 127 att10x = 1; // 128 break; 129 } 130 case 4: { // 10V 131 rangeMax = 10 / lsb50V; // 132 rangeMaxDisp = 1000; 133 rangeMin = 0; 134 rangeMinDisp = 0; 135 att10x = 1; // 136 break; 137 } 138 case 5: { // 5V 139 rangeMax = 5 / lsb5V; // 140 rangeMaxDisp = 500; 141 rangeMin = 0; 142 rangeMinDisp = 0; 143 att10x = 0; // 144 break; 145 } 146 case 6: { // 2V 147 rangeMax = 2 / lsb5V; // 148 rangeMaxDisp = 200; 149 rangeMin = 0; 150 rangeMinDisp = 0; 151 att10x = 0; // 152 break; 153 } 154 case 7: { // 1V 155 rangeMax = 1 / lsb5V; // 156 rangeMaxDisp = 100; 157 rangeMin = 0; 158 rangeMinDisp = 0; 159 att10x = 0; // 160 break; 161 } 162 case 8: { // 0.5V 163 rangeMax = 0.5 / lsb5V; // 164 rangeMaxDisp = 50; 165 rangeMin = 0; 166 rangeMinDisp = 0; 167 att10x = 0; // 168 break; 169 } 170 case 9: { // 0.5V 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(); // (0.4ms) 183 display.setTextColor(WHITE); // 184 display.setCursor(86, 0); // Start at top-left corner 185 display.println(F("av V")); // 1 186 display.drawFastVLine(26, 9, 55, WHITE); // 187 display.drawFastVLine(127, 9, 55, WHITE); // 188 189 display.drawFastHLine(24, 9, 7, WHITE); // Max 190 display.drawFastHLine(24, 36, 2, WHITE); // 191 display.drawFastHLine(24, 63, 7, WHITE); // 192 193 display.drawFastHLine(51, 9, 3, WHITE); // Max 194 display.drawFastHLine(51, 63, 3, WHITE); // 195 196 display.drawFastHLine(76, 9, 3, WHITE); // Max 197 display.drawFastHLine(76, 63, 3, WHITE); // 198 199 display.drawFastHLine(101, 9, 3, WHITE); // Max 200 display.drawFastHLine(101, 63, 3, WHITE); // 201 202 display.drawFastHLine(123, 9, 5, WHITE); // Max 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); // 3 211 } 212 } 213} 214 215void readWave() { // 216 if (att10x == 1) { // 1/10 217 pinMode(12, OUTPUT); // 218 digitalWrite(12, LOW); // LOW 219 } else { // 220 pinMode(12, INPUT); // Hi-z 221 } 222 223 switch (hRange) { // 224 225 case 0: { // 50ms 226 timeExec = 400 + 50; // (ms) EEPROM 227 ADCSRA = ADCSRA & 0xf8; // 3 228 ADCSRA = ADCSRA | 0x07; // 128 (arduino 229 for (int i = 0; i < REC_LENGTH; i++) { // 200 230 waveBuff[i] = analogRead(0); // 112s 231 delayMicroseconds(1888); // 232 } 233 break; 234 } 235 236 case 1: { // 20ms 237 timeExec = 160 + 50; // (ms) EEPROM 238 ADCSRA = ADCSRA & 0xf8; // 3 239 ADCSRA = ADCSRA | 0x07; // 128 (arduino 240 for (int i = 0; i < REC_LENGTH; i++) { // 200 241 waveBuff[i] = analogRead(0); // 112s 242 delayMicroseconds(688); // 243 } 244 break; 245 } 246 247 case 2: { // 10 ms 248 timeExec = 80 + 50; // (ms) EEPROM 249 ADCSRA = ADCSRA & 0xf8; // 3 250 ADCSRA = ADCSRA | 0x07; // 128 (arduino 251 for (int i = 0; i < REC_LENGTH; i++) { // 200 252 waveBuff[i] = analogRead(0); // 112s 253 delayMicroseconds(288); // 254 } 255 break; 256 } 257 258 case 3: { // 5 ms 259 timeExec = 40 + 50; // (ms) EEPROM 260 ADCSRA = ADCSRA & 0xf8; // 3 261 ADCSRA = ADCSRA | 0x07; // 128 (arduino 262 for (int i = 0; i < REC_LENGTH; i++) { // 200 263 waveBuff[i] = analogRead(0); // 112s 264 delayMicroseconds(88); // 265 } 266 break; 267 } 268 269 case 4: { // 2 ms 270 timeExec = 16 + 50; // (ms) EEPROM 271 ADCSRA = ADCSRA & 0xf8; // 3 272 ADCSRA = ADCSRA | 0x06; // 64 (0x1=2, 0x2=4, 0x3=8, 0x4=16, 0x5=32, 0x6=64, 0x7=128) 273 for (int i = 0; i < REC_LENGTH; i++) { // 200 274 waveBuff[i] = analogRead(0); // 56s 275 delayMicroseconds(24); // 276 } 277 break; 278 } 279 280 case 5: { // 1 ms 281 timeExec = 8 + 50; // (ms) EEPROM 282 ADCSRA = ADCSRA & 0xf8; // 3 283 ADCSRA = ADCSRA | 0x05; // 16 (0x1=2, 0x2=4, 0x3=8, 0x4=16, 0x5=32, 0x6=64, 0x7=128) 284 for (int i = 0; i < REC_LENGTH; i++) { // 200 285 waveBuff[i] = analogRead(0); // 28s 286 delayMicroseconds(12); // 287 } 288 break; 289 } 290 291 case 6: { // 500us 292 timeExec = 4 + 50; // (ms) EEPROM 293 ADCSRA = ADCSRA & 0xf8; // 3 294 ADCSRA = ADCSRA | 0x04; // 16(0x1=2, 0x2=4, 0x3=8, 0x4=16, 0x5=32, 0x6=64, 0x7=128) 295 for (int i = 0; i < REC_LENGTH; i++) { // 200 296 waveBuff[i] = analogRead(0); // 16s 297 delayMicroseconds(4); // 298 // 1.875snop 110.0625s @16MHz) 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: { // 200us 306 timeExec = 2 + 50; // (ms) EEPROM 307 ADCSRA = ADCSRA & 0xf8; // 3 308 ADCSRA = ADCSRA | 0x02; // :4(0x1=2, 0x2=4, 0x3=8, 0x4=16, 0x5=32, 0x6=64, 0x7=128) 309 for (int i = 0; i < REC_LENGTH; i++) { 310 waveBuff[i] = analogRead(0); // 6s 311 // 1.875snop 110.0625s @16MHz) 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; // 10 341 342 // max,min 343 if (vRange <= 1) { // Auto1 344 rangeMin = dataMin - 20; // -20 345 rangeMin = (rangeMin / 10) * 10; // 10 346 if (rangeMin < 0) { 347 rangeMin = 0; // 0 348 } 349 rangeMax = dataMax + 20; // +20 350 rangeMax = ((rangeMax / 10) + 1) * 10; // 10 351 if (rangeMax > 1020) { 352 rangeMax = 1023; // 10201023 353 } 354 355 if (att10x == 1) { // 356 rangeMaxDisp = 100 * (rangeMax * lsb50V); // ADC 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) { // 0 369 if ((waveBuff[trigP - 1] < (dataMax + dataMin) / 2) && (waveBuff[trigP] >= (dataMax + dataMin) / 2)) { 370 break; // 371 } 372 } else { // 0 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; // Unsync 382 } 383} 384 385void startScreen() { // 386 display.clearDisplay(); 387 display.setTextSize(1); // 2 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() { // Hold 400 display.fillRect(32, 12, 24, 8, BLACK); // 4 401 display.setCursor(32, 12); 402 display.print(F("Hold")); // 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); // (time/div) 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) { // 10 441 voltage = dataAve * lsb50V / 10.0; // 50V 442 } else { 443 voltage = dataAve * lsb5V / 10.0; // 5V 444 } 445 dtostrf(voltage, 4, 2, chrBuff); // x.xx 446 display.setCursor(98, 0); // 447 display.print(chrBuff); // 448 // display.print(saveTimer); // 449 450 // 451 voltage = rangeMaxDisp / 100.0; // Max 452 if (vRange == 1 || vRange > 4) { // 5VAuto5V 453 dtostrf(voltage, 4, 2, chrBuff); // *.** 454 } else { // 455 dtostrf(voltage, 4, 1, chrBuff); // **.* 456 } 457 display.setCursor(0, 9); 458 display.print(chrBuff); // Max 459 460 voltage = (rangeMaxDisp + rangeMinDisp) / 200.0; // 461 if (vRange == 1 || vRange > 4) { // 5VAuto5V 462 dtostrf(voltage, 4, 2, chrBuff); // 2 463 } else { // 464 dtostrf(voltage, 4, 1, chrBuff); // 1 465 } 466 display.setCursor(0, 33); 467 display.print(chrBuff); // 468 469 voltage = rangeMinDisp / 100.0; // Min 470 if (vRange == 1 || vRange > 4) { // 5VAuto5V 471 dtostrf(voltage, 4, 2, chrBuff); // 2 472 } else { 473 dtostrf(voltage, 4, 1, chrBuff); // 1 474 } 475 display.setCursor(0, 57); 476 display.print(chrBuff); // Min 477 478 // 479 if (trigSync == false) { // 480 display.setCursor(60, 55); // 481 display.print(F("Unsync")); // 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() { // EEPROM 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() { // EEPROM 510 int x; 511 x = EEPROM.read(0); // vRange 512 if ((x < 0) || (x > 9)) { // 0-9 513 x = 3; // 514 } 515 vRange = x; 516 517 x = EEPROM.read(1); // hRange 518 if ((x < 0) || (x > 7)) { // 0-9 519 x = 3; // 520 } 521 hRange = x; 522 x = EEPROM.read(2); // trigD 523 if ((x < 0) || (x > 1)) { // 0-9 524 x = 1; // 525 } 526 trigD = x; 527 x = EEPROM.read(3); // scopeP 528 if ((x < 0) || (x > 2)) { // 0-9 529 x = 1; // 530 } 531 scopeP = x; 532} 533 534void pin2IRQ() { // Pin2(int0) 535 //pin8,9,10,11Pin2 536 // 537 538 int x; // 539 x = PINB; // B 540 541 if ( (x & 0x07) != 0x07) { // 3High 542 saveTimer = 5000; // EEPROM(ms 543 paraChanged = true; // ON 544 } 545 546 if ((x & 0x01) == 0) { 547 scopeP++; 548 if (scopeP > 2) { 549 scopeP = 0; 550 } 551 } 552 553 if ((x & 0x02) == 0) { // UP 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) { // DOWN 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) { // HOLD 590 hold = ! hold; // 591 } 592} 593
Downloadable files
circuit
circuit
circuit
circuit
Comments
Only logged in users can leave comments