├── CanonMicProcessor_05.ino ├── ParkingAttendent_03.ino ├── ParkingAttendent_STL.zip ├── Radio_SourceCode.ino ├── ServoSymphony.ino └── ThermalCamera_Fast.ino /CanonMicProcessor_05.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This program is a microphone montitor for a DSLR, it will sit between a mic and DSLR input 4 | so the user can control the mic levels and see the levels. 5 | 6 | compile 96 mhz, debug or fastest 7 | 8 | rev data Description author 9 | 1.0 4/8/2018 initial creation Kasprzak 10 | 2.0 4/14/2018 added filters Kasprzak 11 | 3.0 5/12/2018 added 30 band FFT Kasprzak 12 | 4.0 5/20/2018 added cute splash screen Kasprzak 13 | 5.0 6/2/2018 added mic level reminder Kasprzak 14 | 15 | connection map 16 | 17 | Teensy 3.2 Display 18 | 19 | 0 Touch pin 20 | 1 Touch pin 21 | 2 Touch pin 22 | 3 Touch pin 23 | 4 Touch pin 24 | 5 LED pin (PWM to control brightness) 25 | 6 26 | 7 MOSI 27 | 8 28 | 9 29 | 10 30 | 11 31 | 12 MISO 32 | 13 33 | 14 SCK 34 | A1 35 | A2 36 | A3 37 | A4 38 | A5 39 | A6 Chip Select 40 | A7 DC 41 | A8 42 | A9 43 | 44 | */ 45 | 46 | // #define Debug 47 | 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include "UTouch.h" 56 | #include // custom fonts that ships with ILI9341_t3.h 57 | #include // custom fonts that ships with ILI9341_t3.h 58 | #include // custom fonts that ships with ILI9341_t3.h 59 | #include 60 | 61 | // some audip defines and pin defines 62 | #define FILTER_Q .5 63 | #define MIC_BAR_GAIN 20.0 64 | #define LED_PIN 5 65 | #define DC_PIN 21 66 | #define BAT_PIN 16 67 | #define CS_PIN 20 68 | #define PIN_RST 255 // 255 = unused, connect to 3.3V 69 | #define MO_PIN 7 70 | #define Display_SCLK 14 71 | #define MI_PIN 12 72 | #define WIDTH 7 73 | #define OFFSET 25 74 | #define HIGHPASS 60 75 | #define LOWPASS 8000 76 | 77 | // variables for the locations of the keypad buttons 78 | #define BUTTON_X 100 79 | #define BUTTON_Y 80 80 | #define BUTTON_W 60 81 | #define BUTTON_H 30 82 | #define BUTTON_SPACING_X 10 83 | #define BUTTON_SPACING_Y 10 84 | #define BUTTON_TEXTSIZE 2 85 | 86 | // GUItool: automatically generated code from 87 | // https://www.pjrc.com/teensy/gui/index.html 88 | AudioInputI2S i2s1; 89 | AudioMixer4 mixer1; 90 | AudioFilterBiquad biquad1; 91 | AudioAnalyzeFFT1024 fft1024_1; 92 | AudioOutputI2S i2s2; 93 | AudioConnection patchCord1(i2s1, 0, mixer1, 0); 94 | AudioConnection patchCord2(i2s1, 1, mixer1, 1); 95 | AudioConnection patchCord3(mixer1, biquad1); 96 | AudioConnection patchCord4(biquad1, 0, i2s2, 1); 97 | AudioConnection patchCord5(biquad1, 0, i2s2, 0); 98 | AudioConnection patchCord6(biquad1, fft1024_1); 99 | AudioControlSGTL5000 sgtl5000_1; 100 | 101 | // create the display object 102 | // note I've modifed the library to accept the screen size, that way I can drive different size displays 103 | // from the same lib--i just pass in the size 104 | 105 | ILI9341_t3 Display = ILI9341_t3(CS_PIN, DC_PIN, 240, 320, PIN_RST, MO_PIN, Display_SCLK, MI_PIN); 106 | 107 | // some more varibales 108 | int left, top, wide, high; 109 | unsigned long curtime, pretime; 110 | 111 | int TempNum; 112 | int HighPassF = 0; 113 | int LowPassF = 0; 114 | int MicGain = 5; 115 | float BatVolts = 0.0; 116 | byte ShowHistory = 0; 117 | byte Background = 0; 118 | byte Brightness = 255; 119 | byte HighPass = 0; 120 | byte LowPass = 0; 121 | uint16_t BackColor = C_BLACK; // i have a custom "Colors.h" that lists all the colors i use 122 | uint16_t ForeColor = C_WHITE; 123 | unsigned long Showit; 124 | int oButtonLocation; 125 | int ButtonLocation; 126 | 127 | char FilterText[2][5] = {"Off", "On" }; 128 | char HistoryText[2][5] = {"No", "Yes" }; 129 | 130 | // keypad code taken from Adafruit examples 131 | char KeyPadBtnText[12][5] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "Done", "0", "Clr" }; 132 | uint16_t KeyPadBtnColor[12] = {C_BLUE, C_BLUE, C_BLUE, 133 | C_BLUE, C_BLUE, C_BLUE, 134 | C_BLUE, C_BLUE, C_BLUE, 135 | C_DKGREEN, C_BLUE, C_DKRED 136 | }; 137 | byte Qty, j, i, row, col, b; 138 | int x, y, h, w, loval, hival, Count; 139 | int line1; 140 | 141 | volatile float MixerGain; 142 | // An array to hold the 32 frequency bands 143 | volatile float level[32]; 144 | volatile float Max[32]; 145 | float BatLevel; 146 | 147 | // create the touch object 148 | UTouch Touch( 0, 1, 2, 3, 4); 149 | 150 | Adafruit_GFX_Button KeyPadBtn[12]; 151 | Adafruit_GFX_Button SetupBtn; 152 | Adafruit_GFX_Button HistoryBtn; 153 | Adafruit_GFX_Button MicGainBtn; 154 | Adafruit_GFX_Button BackColorBtn; 155 | Adafruit_GFX_Button HighPassFBtn; 156 | Adafruit_GFX_Button LowPassFBtn; 157 | Adafruit_GFX_Button DoneBtn; 158 | Adafruit_GFX_Button HighPassBtn; 159 | Adafruit_GFX_Button LowPassBtn; 160 | Adafruit_GFX_Button OKBtn; 161 | 162 | void setup() { 163 | 164 | Serial.begin(9600); 165 | 166 | AudioMemory(60); 167 | pinMode(BAT_PIN, INPUT); 168 | Display.begin(); 169 | Display.fillScreen(C_BLACK); 170 | Display.setRotation(3); 171 | 172 | // I save basic parameters, like background color and filter values to the EEPROM 173 | GetParameters(); 174 | 175 | if (Background == 0) { 176 | BackColor = C_BLACK; 177 | ForeColor = C_WHITE; 178 | } 179 | else { 180 | BackColor = C_WHITE; 181 | ForeColor = C_BLACK; 182 | } 183 | 184 | // set the display background brightness 185 | analogWrite(LED_PIN, Brightness); 186 | Display.fillScreen(BackColor); 187 | 188 | // start setting the audio board parameters 189 | // i really have no idea if these are the optimal settings 190 | // after days of trial and error, they seem to be the best 191 | sgtl5000_1.enable(); 192 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); 193 | sgtl5000_1.volume(.85); 194 | sgtl5000_1.lineInLevel(MicGain); 195 | sgtl5000_1.lineOutLevel(50); 196 | sgtl5000_1.audioPreProcessorEnable(); 197 | 198 | // setup the FFT 199 | fft1024_1.windowFunction(AudioWindowHanning1024); 200 | 201 | // initilize the touch screen 202 | Touch.InitTouch(); 203 | Touch.setPrecision(PREC_EXTREME); 204 | 205 | // create all the buttons 206 | SetupBtn.initButton(&Display, 289, 18, 60, 29, C_WHITE, C_DKGREY, C_LTGREY, "SET", 2); 207 | OKBtn.initButton(&Display, 280, 18, 80, 29, C_WHITE, C_DKGREY, C_LTGREY, "OK", 2); 208 | DoneBtn.initButton(&Display, 270, 18, 80, 29, C_WHITE, C_DKGREY, C_LTGREY, "Done", 2); 209 | 210 | HistoryBtn.initButton(&Display, 225, 70, 50, 25, C_DKGREY, C_GREY, C_BLACK, "Set", 2); 211 | MicGainBtn.initButton(&Display, 225, 100, 50, 25, C_DKGREY, C_GREY, C_BLACK, "Set", 2); 212 | HighPassBtn.initButton(&Display, 225, 130, 50, 25, C_DKGREY, C_GREY, C_BLACK, "Set", 2); 213 | LowPassBtn.initButton(&Display, 225, 160, 50, 25, C_DKGREY, C_GREY, C_BLACK, "Set", 2); 214 | HighPassFBtn.initButton(&Display, 280, 130, 50, 25, C_DKGREY, C_GREY, C_BLACK, "Set", 2); 215 | LowPassFBtn.initButton(&Display, 280, 160, 50, 25, C_DKGREY, C_GREY, C_BLACK, "Set", 2); 216 | BackColorBtn.initButton(&Display, 225, 190, 50, 25, C_DKGREY, C_GREY, C_BLACK, "Set", 2); 217 | 218 | // create KeyPadBtn 219 | for (row = 0; row < 4; row++) { 220 | for (col = 0; col < 3; col++) { 221 | KeyPadBtn[col + row * 3].initButton(&Display, BUTTON_X + col * (BUTTON_W + BUTTON_SPACING_X), 222 | BUTTON_Y + row * (BUTTON_H + BUTTON_SPACING_Y), 223 | BUTTON_W, BUTTON_H, C_WHITE, KeyPadBtnColor[col + row * 3], C_WHITE, 224 | KeyPadBtnText[col + row * 3], BUTTON_TEXTSIZE); 225 | } 226 | } 227 | 228 | // set the initial mic gain location 229 | ButtonLocation = 140; 230 | oButtonLocation = ButtonLocation; 231 | 232 | // turn on the mixers 233 | mixer1.gain(0, MixerGain); 234 | mixer1.gain(1, MixerGain); 235 | mixer1.gain(2, 0.0); 236 | mixer1.gain(3, 0.0); 237 | 238 | // show a cute little splash screen 239 | SplashScreen(); 240 | 241 | // remind the user to set the mic input level very low 242 | StartupScreen(); 243 | 244 | Display.fillScreen(BackColor); 245 | 246 | // draw the main screen 247 | DrawMainScreen(); 248 | 249 | // update the gain (graphic and amplification, and filters) 250 | UpdateGain(); 251 | ActivateFilters(); 252 | 253 | curtime = 70000; 254 | pretime = 0; 255 | 256 | } 257 | 258 | void loop() { 259 | 260 | // I have everything in the fft read loop, so far no issues, but i should have some catch code outside that if 261 | 262 | if (fft1024_1.available()) { 263 | 264 | // read the batter level every minute 265 | if (curtime - pretime > 60000) { 266 | 267 | x = 5; 268 | y = 8; 269 | w = 60; 270 | h = 15; 271 | loval = 0; 272 | hival = 100.0; 273 | pretime = curtime; 274 | BatVolts = 0.0; 275 | 276 | for (i = 0; i < 100; i++) { 277 | BatVolts = BatVolts + analogRead(BAT_PIN); 278 | } 279 | 280 | BatVolts = BatVolts / 100.0; 281 | //Serial.println(BatVolts); 282 | BatVolts = BatVolts * (3.3 / 1024.0); 283 | 284 | BatVolts = (BatVolts * (1000.0 + 4700.0)) / 1000.0; 285 | 286 | BatVolts = (map(BatVolts * 10, 70, 90, 0, 1000)) / 10.0; 287 | 288 | if (BatVolts > 100.0) { 289 | BatVolts = 100.0; 290 | } 291 | if (BatVolts < 0.0) { 292 | BatVolts = 0.0; 293 | } 294 | 295 | // draw the border, scale, and label once 296 | // avoid doing this on every update to minimize flicker 297 | // draw the border and scale 298 | 299 | Display.drawRect(x, y, w, h, ForeColor); 300 | Display.setTextColor(ForeColor, BackColor); 301 | 302 | // compute level of bar graph that is scaled to the width and the hi and low vals 303 | // this is needed to accompdate for +/- range capability 304 | // draw the bar graph 305 | // write a upper and lower bar to minimize flicker cause by blanking out bar and redraw on update 306 | BatLevel = (w * (((BatVolts - loval) / (hival - loval)))); 307 | 308 | if (BatLevel < 25.0) { 309 | Display.fillRect(x + BatLevel + 1, y + 1, w - BatLevel - 2, h - 2, C_DKRED); 310 | Display.fillRect(x + 1, y + 1 , BatLevel - 0, h - 2, C_RED); 311 | } 312 | else { 313 | Display.fillRect(x + BatLevel + 1, y + 1, w - BatLevel - 2, h - 2, C_DKGREEN); 314 | Display.fillRect(x + 1, y + 1 , BatLevel - 0, h - 2, C_GREEN); 315 | } 316 | } 317 | 318 | 319 | curtime = millis(); 320 | 321 | // anyone touch anything? 322 | ProcessTouch(); 323 | 324 | // process the fft spectrum 325 | level[0] = fft1024_1.read(0, 1) * 1.000 * MIC_BAR_GAIN; 326 | level[1] = fft1024_1.read(2, 3) * 1.552 * MIC_BAR_GAIN; 327 | level[2] = fft1024_1.read(4, 5) * 1.904 * MIC_BAR_GAIN; 328 | level[3] = fft1024_1.read(6, 7) * 2.178 * MIC_BAR_GAIN; 329 | level[4] = fft1024_1.read(8, 9) * 2.408 * MIC_BAR_GAIN; 330 | level[5] = fft1024_1.read(10, 12) * 2.702 * MIC_BAR_GAIN; 331 | level[6] = fft1024_1.read(13, 15) * 2.954 * MIC_BAR_GAIN; 332 | level[7] = fft1024_1.read(16, 18) * 3.178 * MIC_BAR_GAIN; 333 | level[8] = fft1024_1.read(19, 22) * 3.443 * MIC_BAR_GAIN; 334 | level[9] = fft1024_1.read(23, 26) * 3.681 * MIC_BAR_GAIN; 335 | level[10] = fft1024_1.read(27, 31) * 3.950 * MIC_BAR_GAIN; 336 | level[11] = fft1024_1.read(32, 37) * 4.239 * MIC_BAR_GAIN; 337 | level[12] = fft1024_1.read(38, 43) * 4.502 * MIC_BAR_GAIN; 338 | level[13] = fft1024_1.read(44, 50) * 4.782 * MIC_BAR_GAIN; 339 | level[14] = fft1024_1.read(51, 58) * 5.074 * MIC_BAR_GAIN; 340 | level[15] = fft1024_1.read(59, 67) * 5.376 * MIC_BAR_GAIN; 341 | level[16] = fft1024_1.read(68, 78) * 5.713 * MIC_BAR_GAIN; 342 | level[17] = fft1024_1.read(79, 90) * 6.049 * MIC_BAR_GAIN; 343 | level[18] = fft1024_1.read(91, 104) * 6.409 * MIC_BAR_GAIN; 344 | level[19] = fft1024_1.read(105, 120) * 6.787 * MIC_BAR_GAIN; 345 | level[20] = fft1024_1.read(121, 138) * 7.177 * MIC_BAR_GAIN; 346 | level[21] = fft1024_1.read(139, 159) * 7.596 * MIC_BAR_GAIN; 347 | level[22] = fft1024_1.read(160, 182) * 8.017 * MIC_BAR_GAIN; 348 | level[23] = fft1024_1.read(183, 209) * 8.473 * MIC_BAR_GAIN; 349 | level[24] = fft1024_1.read(210, 240) * 8.955 * MIC_BAR_GAIN; 350 | level[25] = fft1024_1.read(241, 275) * 9.457 * MIC_BAR_GAIN; 351 | level[26] = fft1024_1.read(276, 315) * 9.984 * MIC_BAR_GAIN; 352 | level[27] = fft1024_1.read(316, 361) * 10.544 * MIC_BAR_GAIN; 353 | level[28] = fft1024_1.read(362, 413) * 11.127 * MIC_BAR_GAIN; 354 | level[29] = fft1024_1.read(414, 473) * 11.747 * MIC_BAR_GAIN; 355 | level[30] = fft1024_1.read(474, 542) * 12.405 * MIC_BAR_GAIN; 356 | 357 | for (i = 0; i < 31; i++) { // cycle through the 16 channels 358 | 359 | // scale the level to the bar height and clamp if exceed max 360 | line1 = level[i] * 170; 361 | if (line1 > 170) { 362 | line1 = 170; 363 | } 364 | // now it's just a matter of displaying some little boxes for each bar in a certian color 365 | // get number of bars 366 | Qty = line1 / 10; 367 | for (j = Qty; j < 18; j++) { 368 | Display.fillRect( (i * WIDTH) + OFFSET, 210 - (j * 10), WIDTH - 1, 9, BackColor); 369 | } 370 | if (ShowHistory) { 371 | if (Qty > Max[i]) { 372 | Max[i] = Qty - 1; 373 | } 374 | if ((millis() - Showit ) > 2000) { 375 | Showit = millis(); 376 | for (byte k = 0; k < 32; k++) { 377 | Display.fillRect((i * WIDTH) + OFFSET, 210 - (Max[k] * 10), WIDTH - 1, 9, BackColor); 378 | Max[k] = 0; 379 | } 380 | } 381 | else { 382 | if (Max[i] < 11) { 383 | Display.fillRect( (i * WIDTH) + OFFSET, 210 - (Max[i] * 10), WIDTH - 1, 9, C_GREEN); 384 | } 385 | else if (Max[i] < 16) { 386 | Display.fillRect( (i * WIDTH) + OFFSET, 210 - (Max[i] * 10), WIDTH - 1, 9, C_YELLOW); 387 | } 388 | else { 389 | Display.fillRect( (i * WIDTH) + OFFSET, 210 - (Max[i] * 10), WIDTH - 1, 9, C_RED); 390 | } 391 | } 392 | } 393 | for ( j = 0; j < Qty; j++) { 394 | if (j < 11) { 395 | Display.fillRect( (i * WIDTH) + OFFSET, 210 - (j * 10), WIDTH - 1, 9, C_GREEN); 396 | } 397 | else if (j < 16) { 398 | Display.fillRect( (i * WIDTH) + OFFSET, 210 - (j * 10), WIDTH - 1, 9, C_YELLOW); 399 | } 400 | else { 401 | Display.fillRect( (i * WIDTH) + OFFSET, 210 - (j * 10), WIDTH - 1, 9, C_RED); 402 | } 403 | } 404 | } 405 | } 406 | } 407 | 408 | void ActivateFilters() { 409 | 410 | if (HighPass == 1) { 411 | biquad1.setHighpass(0, HighPassF, FILTER_Q); 412 | } 413 | else if (HighPass == 0) { 414 | biquad1.setHighpass(0, 20, FILTER_Q); 415 | } 416 | 417 | if (LowPass == 1) { 418 | biquad1.setLowpass(0, LowPassF, FILTER_Q); 419 | } 420 | else if (LowPass == 0) { 421 | biquad1.setLowpass(0, 20000, FILTER_Q); 422 | } 423 | 424 | } 425 | 426 | void DrawMainScreen() { 427 | 428 | Display.setFont(Arial_18_Bold); 429 | 430 | Display.setTextColor(C_DKGREY, BackColor); 431 | Display.setCursor(80, 7); 432 | Display.print(F("Mic Monitor")); 433 | 434 | Display.setTextColor(C_BLUE, BackColor); 435 | Display.setCursor(78, 5); 436 | Display.print(F("Mic Monitor")); 437 | 438 | Display.setFont(Arial_14); 439 | SetupBtn.drawButton(); 440 | 441 | Display.setFont(Arial_12_Bold); 442 | Display.setTextColor(ForeColor, BackColor); 443 | 444 | Display.setCursor(2, 220); 445 | Display.print(F("-o")) ; 446 | Display.setCursor(16, 220); 447 | Display.print(F("o")) ; 448 | 449 | Display.setCursor(2, 100); 450 | Display.print(F("-12")) ;; 451 | 452 | Display.setCursor(2, 45); 453 | Display.print(F("+3")) ;; 454 | 455 | Display.drawFastHLine( 27, 220, 215, C_GREY); 456 | Display.drawFastHLine( 27, 109, 215, C_GREY); 457 | Display.drawFastHLine( 27, 49, 215, C_GREY); 458 | 459 | Display.setCursor(30, 225); 460 | Display.print(F("100")) ;; 461 | 462 | Display.setCursor(95, 225); 463 | Display.print(F("1000")) ;; 464 | Display.setCursor(195, 225); 465 | Display.print(F("10000")) ;; 466 | 467 | // Display.fillRoundRect (266, oButtonLocation, 45, 25, 3, BackColor); 468 | Display.fillRoundRect( 258, 40, 60, 190, 6, C_GREY); 469 | Display.drawRoundRect( 258, 40, 60, 190, 6, C_DKGREY); 470 | 471 | Display.setFont(Arial_12_Bold); 472 | Display.setTextColor(C_BLACK, BackColor); 473 | Display.setCursor(268, 45); 474 | Display.print(F("Gain")) ; 475 | 476 | Display.setCursor(275, 205); 477 | Display.print(F("L")) ; 478 | Display.setCursor(295, 205); 479 | Display.print(F("R")) ; 480 | 481 | 482 | } 483 | 484 | 485 | void UpdateGain() { 486 | 487 | MixerGain = (float) ButtonLocation * - 0.020 + 5.0; 488 | MixerGain = map(ButtonLocation, 60, 170, 50, 0); 489 | MixerGain = (float) MixerGain / 10.0; 490 | 491 | if (MixerGain < 0.1) { 492 | MixerGain = 0.0; 493 | } 494 | 495 | Display.fillRoundRect (266, oButtonLocation, 45, 25, 3, C_GREY); 496 | oButtonLocation = ButtonLocation; 497 | Display.fillRect( 275, 60, 3, 140, C_BLACK); 498 | Display.fillRect( 298, 60, 3, 140, C_BLACK); 499 | 500 | Display.fillRoundRect (266, ButtonLocation, 45, 25, 3, C_DKBLUE); 501 | Display.drawRoundRect (266, ButtonLocation, 45, 25, 3, C_DKGREY); 502 | 503 | Display.setCursor(275, ButtonLocation + 7); 504 | Display.setFont(Arial_10); 505 | Display.setTextColor(C_WHITE, C_GREY); 506 | Display.print(MixerGain, 1); 507 | 508 | mixer1.gain(0, MixerGain); 509 | mixer1.gain(1, MixerGain); 510 | mixer1.gain(2, 0); 511 | mixer1.gain(3, 0); 512 | } 513 | 514 | void ProcessTouch() { 515 | 516 | if (Touch.dataAvailable()) { 517 | Touch.read(); 518 | x = Touch.getX(); 519 | y = Touch.getY(); 520 | // depending on your display, you may have to map x y to match screen orientation 521 | #ifdef Debug 522 | Serial.print(F("x: ")); 523 | Serial.print(x); 524 | Serial.print(F(" - y: ")); 525 | Serial.println(y); 526 | #endif 527 | 528 | delay(10); // debounce the touch 529 | 530 | if (PressIt(SetupBtn, x, y) == true) { 531 | SetupScreen(); 532 | return; 533 | } 534 | 535 | else if ((x > 250) & (y > 53) & (y < 180) & (y > 59)) { 536 | ButtonLocation = y; 537 | UpdateGain(); 538 | } 539 | 540 | else if (( x > 10) & (x < 200)) { 541 | Brightness = map(y, 0, 240, 255, 5); 542 | analogWrite(LED_PIN, Brightness); 543 | } 544 | 545 | } 546 | 547 | } 548 | 549 | void SetupScreen() { 550 | 551 | bool KeepIn = true; 552 | 553 | DrawSetupScreen(); 554 | 555 | while (KeepIn) { 556 | 557 | if (Touch.dataAvailable()) { 558 | 559 | Touch.read(); 560 | 561 | x = Touch.getX(); 562 | y = Touch.getY(); 563 | 564 | if (PressIt(HistoryBtn, x, y) == true) { 565 | if (ShowHistory == 1) { 566 | ShowHistory = 0; 567 | } 568 | else if (ShowHistory == 0) { 569 | ShowHistory = 1; 570 | } 571 | DrawSetupScreen(); 572 | } 573 | 574 | if (PressIt(MicGainBtn, x, y) == true) { 575 | KeyPad(MicGain, 0, 15); 576 | sgtl5000_1.lineInLevel(MicGain); 577 | } 578 | 579 | if (PressIt(BackColorBtn, x, y) == true) { 580 | if (Background == 0) { 581 | Background = 1; 582 | BackColor = C_WHITE; 583 | ForeColor = C_BLACK; 584 | DrawSetupScreen(); 585 | } 586 | 587 | else { 588 | Background = 0; 589 | BackColor = C_BLACK; 590 | ForeColor = C_WHITE; 591 | DrawSetupScreen(); 592 | } 593 | // save back color 594 | } 595 | 596 | if (PressIt(HighPassBtn, x, y) == true) { 597 | if (HighPass == 0) { 598 | HighPass = 1; 599 | } 600 | else if (HighPass == 1) { 601 | HighPass = 0; 602 | } 603 | ActivateFilters(); 604 | DrawSetupScreen(); 605 | } 606 | 607 | if (PressIt(LowPassBtn, x, y) == true) { 608 | if (LowPass == 0) { 609 | LowPass = 1; 610 | } 611 | else if (LowPass == 1) { 612 | LowPass = 0; 613 | } 614 | ActivateFilters(); 615 | DrawSetupScreen(); 616 | } 617 | 618 | if (PressIt(HighPassFBtn, x, y) == true) { 619 | KeyPad(HighPassF, 20, 400); 620 | ActivateFilters(); 621 | DrawSetupScreen(); 622 | } 623 | 624 | if (PressIt(LowPassFBtn, x, y) == true) { 625 | KeyPad(LowPassF, 400, 20000); 626 | ActivateFilters(); 627 | DrawSetupScreen(); 628 | } 629 | 630 | if (PressIt(DoneBtn, x, y) == true) { 631 | KeepIn = false; 632 | } 633 | } 634 | } 635 | 636 | // save data and exit 637 | EEPROM.put(10, ShowHistory); 638 | EEPROM.put(20, Background); 639 | EEPROM.put(30, MicGain); 640 | EEPROM.put(40, HighPass); 641 | EEPROM.put(50, LowPass); 642 | EEPROM.put(60, HighPassF); 643 | EEPROM.put(70, LowPassF); 644 | Display.fillScreen(BackColor); 645 | curtime = 70000; 646 | pretime = 0; 647 | DrawMainScreen(); 648 | UpdateGain(); 649 | } 650 | 651 | 652 | void DrawSetupScreen() { 653 | 654 | Display.fillScreen(BackColor); 655 | Display.setFont(Arial_18_Bold); 656 | Display.setTextColor(C_DKGREY, BackColor); 657 | Display.setCursor(5, 7); 658 | Display.print(F("Setup")); 659 | Display.setTextColor(C_BLUE, BackColor); 660 | Display.setCursor(3, 5); 661 | Display.print(F("Setup")); 662 | Display.setTextColor(ForeColor, BackColor); 663 | Display.setFont(Arial_12_Bold); 664 | HistoryBtn.drawButton(); 665 | MicGainBtn.drawButton(); 666 | HighPassBtn.drawButton(); 667 | LowPassBtn.drawButton(); 668 | 669 | if (HighPass) { 670 | HighPassFBtn.drawButton(); 671 | } 672 | 673 | if (LowPass) { 674 | LowPassFBtn.drawButton(); 675 | } 676 | 677 | BackColorBtn.drawButton(); 678 | 679 | Display.setFont(Arial_14); 680 | DoneBtn.drawButton(); 681 | 682 | Display.setTextColor(ForeColor, BackColor); 683 | Display.setFont(Arial_12); 684 | Display.setCursor(10 , 65); 685 | Display.print(F("Show bar history: ") + String(HistoryText[ShowHistory])); 686 | Display.setCursor(10 , 95); 687 | Display.print(F("Microphone gain: ") + String(MicGain)); 688 | Display.setCursor(10 , 125); 689 | if (HighPass == 1) { 690 | Display.print(F("High Pass: ") + String(FilterText[HighPass]) + F(", ") + String(HighPassF) + F(" hz")); 691 | } 692 | else { 693 | Display.print(F("High Pass: ") + String(FilterText[HighPass])); 694 | } 695 | Display.setCursor(10 , 155); 696 | if (LowPass == 1) { 697 | Display.print(F("Low Pass: ") + String(FilterText[LowPass]) + F(", ") + String(LowPassF) + F(" hz")); 698 | } 699 | else { 700 | Display.print(F("Low Pass: ") + String(FilterText[LowPass])); 701 | } 702 | Display.setCursor(10 , 185); 703 | Display.print(F("Background color")); 704 | 705 | } 706 | 707 | void KeyPad(int & TheNumber, int MinVal, int MaxVal) { 708 | 709 | Display.setFont(Arial_14); 710 | 711 | left = BUTTON_X - (BUTTON_W); 712 | top = BUTTON_Y - (2 * BUTTON_H); 713 | wide = (3 * BUTTON_W ) + (8 * BUTTON_SPACING_X); 714 | high = 5 * (BUTTON_H + BUTTON_SPACING_Y); 715 | TempNum = TheNumber; 716 | bool KeepIn = true; 717 | 718 | Display.fillRect(left, top, wide , high, C_DKGREY); 719 | Display.drawRect(left, top, wide , high, C_LTGREY); 720 | 721 | Display.fillRect(left + 10, top + 10, wide - 20 , 30, C_GREY); 722 | Display.drawRect(left + 10, top + 10, wide - 20 , 30, C_WHITE); 723 | 724 | Display.setCursor(left + 110 , top + 18); 725 | Display.setTextColor(C_BLACK, 80); 726 | Display.print(F("(") + String(MinVal) + F(" - ") + String(MaxVal) + F(")")); 727 | 728 | Display.setCursor(left + 20 , top + 18); 729 | Display.setTextColor(C_BLACK, C_GREY); 730 | Display.print(TheNumber); 731 | 732 | for (row = 0; row < 4; row++) { 733 | for (col = 0; col < 3; col++) { 734 | KeyPadBtn[col + row * 3].drawButton(); 735 | } 736 | } 737 | 738 | while (KeepIn) { 739 | // get the touch point 740 | if (Touch.dataAvailable()) { 741 | 742 | Touch.read(); 743 | 744 | x = Touch.getX(); 745 | y = Touch.getY(); 746 | 747 | // go thru all the KeyPadBtn, checking if they were pressed 748 | for (b = 0; b < 12; b++) { 749 | if (PressIt(KeyPadBtn[b], x, y) == true) { 750 | if ((b < 9) | (b == 10)) { 751 | TempNum *= 10; 752 | if (TempNum == 0) { 753 | Display.fillRect(left + 10, top + 10, 80 , 30, C_GREY); 754 | } 755 | 756 | 757 | if (b != 10) { 758 | TempNum += (b + 1); 759 | } 760 | if (TempNum > MaxVal) { 761 | Display.fillRect(left + 10, top + 10, 80 , 30, C_GREY); 762 | TempNum = TempNum / 10; 763 | // TempNum -= (b + 1); 764 | } 765 | } 766 | // clr button! delete char 767 | if (b == 11) { 768 | Display.fillRect(left + 10, top + 10, 80 , 30, C_GREY); 769 | Display.drawRect(left + 10, top + 10, 80 , 30, C_WHITE); 770 | TempNum = 0; 771 | } 772 | if (b == 9) { 773 | if (TempNum >= MinVal) { 774 | KeepIn = false; 775 | } 776 | } 777 | Display.setCursor(left + 20 , top + 18); 778 | Display.setTextColor(C_BLACK, C_GREY); 779 | Display.print(TempNum); 780 | } 781 | } 782 | } 783 | } 784 | 785 | TheNumber = TempNum; 786 | DrawSetupScreen(); 787 | 788 | } 789 | 790 | void GetParameters() { 791 | 792 | byte i, test; 793 | 794 | EEPROM.get(0, test); 795 | if (test == 255) { 796 | // new programmer reset the whole thing 797 | for (i = 0; i < 255; i++) { 798 | EEPROM.put(i, 0); 799 | } 800 | // set some defaulTouch 801 | // and populate the eeprom 802 | 803 | ShowHistory = 0; 804 | EEPROM.get(10, ShowHistory); 805 | Background = 0; 806 | EEPROM.put(20, Background); 807 | MicGain = 5; 808 | EEPROM.put(30, MicGain); 809 | HighPass = 0; 810 | EEPROM.put(40, HighPass); 811 | LowPass = 0; 812 | EEPROM.put(50, LowPass); 813 | HighPassF = 4000; 814 | EEPROM.put(40, HighPassF); 815 | LowPassF = 40; 816 | EEPROM.put(50, LowPassF); 817 | 818 | } 819 | 820 | EEPROM.get(10, ShowHistory); 821 | EEPROM.get(20, Background); 822 | EEPROM.get(30, MicGain); 823 | EEPROM.get(40, HighPass); 824 | EEPROM.get(50, LowPass); 825 | EEPROM.get(60, HighPassF); 826 | EEPROM.get(70, LowPassF); 827 | } 828 | 829 | bool PressIt(Adafruit_GFX_Button TheButton, int x, int y) { 830 | 831 | if (TheButton.contains(x, y)) { 832 | TheButton.press(true); // tell the button it is pressed 833 | } else { 834 | TheButton.press(false); // tell the button it is NOT pressed 835 | } 836 | if (TheButton.justReleased()) { 837 | TheButton.drawButton(); // draw normal 838 | } 839 | if (TheButton.justPressed()) { 840 | TheButton.drawButton(true); // draw invert! 841 | delay(200); // UI debouncing 842 | TheButton.drawButton(false); // draw invert! 843 | return true; 844 | } 845 | return false; 846 | } 847 | 848 | 849 | void StartupScreen() { 850 | 851 | unsigned long LastTime = 0; 852 | bool KeepIn = true; 853 | bool LastColor = true; 854 | 855 | analogWrite(LED_PIN, 255); 856 | 857 | Display.fillScreen(C_BLACK); 858 | Display.setFont(Arial_14); 859 | OKBtn.drawButton(); 860 | Display.setTextColor(C_WHITE, C_BLACK); 861 | 862 | Display.setCursor(10, 50); 863 | Display.print(F("Set the CAMERA mic level to 17%")); 864 | 865 | Display.setFont(Arial_10_Bold); 866 | Display.fillRect(60, 80, 200 , 20, C_DKRED); 867 | Display.setCursor(65, 85); 868 | Display.print(F("Sound Recording")); 869 | Display.setFont(Arial_10); 870 | Display.setCursor(65, 115); 871 | Display.print(F("Sound Rec.")); 872 | Display.setCursor(160, 115); 873 | Display.print(F("Manual")); 874 | 875 | Display.setCursor(65, 147); 876 | Display.print(F("Rec. level")); 877 | 878 | Display.fillRect(155, 150, 100 , 2, C_WHITE); 879 | 880 | Display.fillRect(155, 145, 2 , 10, C_WHITE); 881 | Display.fillRect(155 + 25, 145, 2 , 10, C_WHITE); 882 | Display.fillRect(155 + 50, 145, 2 , 10, C_WHITE); 883 | Display.fillRect(155 + 75, 145, 2 , 10, C_WHITE); 884 | Display.fillRect(155 + 100, 145, 2 , 10, C_WHITE); 885 | 886 | Display.fillRect(60, 175, 200 , 60, C_DKGREY); 887 | 888 | Display.setCursor(65, 180); 889 | Display.print(F("-dB 40")); 890 | Display.setCursor(180, 180); 891 | Display.print(F("12")); 892 | Display.setCursor(240, 180); 893 | Display.print(F("0")); 894 | 895 | Display.setCursor(65, 200); 896 | Display.print(F("L")); 897 | 898 | Display.setCursor(65, 220); 899 | Display.print(F("R")); 900 | 901 | for (int i = 80; i < 248; i += 12) { 902 | 903 | if (i < 188) { 904 | Display.fillRect(i, 200, 10 , 10, C_WHITE); 905 | Display.fillRect(i, 220, 10 , 10, C_WHITE); 906 | } 907 | else if (i < 212) { 908 | Display.fillRect(i, 200, 10 , 10, C_YELLOW); 909 | Display.fillRect(i, 220, 10 , 10, C_YELLOW); 910 | } 911 | else { 912 | Display.fillRect(i, 200, 10 , 10, C_MDGREY); 913 | Display.fillRect(i, 220, 10 , 10, C_MDGREY); 914 | } 915 | } 916 | 917 | Display.drawRect (60, 80, 200, 155, C_GREY); 918 | 919 | while (KeepIn) { 920 | 921 | if ((millis() - LastTime) > 200) { 922 | LastTime = millis(); 923 | 924 | if (LastColor == true) { 925 | LastColor = false; 926 | Display.fillTriangle (155 - 4 + 16, 135, 155 + 4 + 16, 135, 155 + 16, 148, C_RED); 927 | 928 | } 929 | else { 930 | LastColor = true; 931 | Display.fillTriangle (155 - 4 + 16, 135, 155 + 4 + 16, 135, 155 + 16, 148, C_GREEN); 932 | 933 | } 934 | } 935 | 936 | if (Touch.dataAvailable()) { 937 | Touch.read(); 938 | x = Touch.getX(); 939 | y = Touch.getY(); 940 | if ((PressIt(OKBtn, x, y) == true)) { 941 | KeepIn = false; 942 | } 943 | } 944 | } 945 | } 946 | 947 | void SplashScreen() { 948 | 949 | analogWrite(LED_PIN, 255); 950 | 951 | Display.fillScreen(C_BLACK); 952 | Display.fillScreenVGradient(0x000A, 0x0000); 953 | delay(500); 954 | for (int i = 0; i < 320; i += 2) { 955 | Display.setTextColor(C_RED, C_BLACK); 956 | Display.setFont(ArialBlack_40); 957 | Display.setCursor(11, 40); 958 | Display.print(F("Canon 7D")); 959 | 960 | Display.setTextColor(C_WHITE, C_BLACK); 961 | Display.setFont(Arial_20); 962 | Display.setCursor(30, 120); 963 | Display.print(F("Microphone Monitor")); 964 | 965 | Display.setFont(Arial_16); 966 | Display.setCursor(40, 180); 967 | Display.print(F("v 1.0 Kasprzak (c)")); 968 | Display.setScroll(i); 969 | } 970 | 971 | delay(2000); 972 | 973 | } 974 | -------------------------------------------------------------------------------- /ParkingAttendent_03.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Free code for the NeoPixed garage attendent. 4 | uses a ultrasonic distance sensor to find distance to front of car 5 | illuminates pixels for the distance 6 | that way you don't smash into things 7 | 8 | */ 9 | 10 | 11 | #include 12 | #include 13 | 14 | #define PIN_SIG 8 15 | #define PIN_ECHO 9 16 | #define PIN_TRIG 10 17 | #define PIN_DIST A0 18 | 19 | #define NUMPIXELS 60 20 | #define MINBRIGHT 1 21 | #define MAXBRIGHT 100 22 | 23 | // needed for Arduino in handling timeout 24 | unsigned long OldTime; 25 | 26 | // distance measuring variables 27 | int Distance, OldDistance, Offset; 28 | byte i, Pulse = 0; 29 | bool Run = false; 30 | bool Up = true; 31 | 32 | // create the light strip object 33 | Adafruit_NeoPixel LightStrip(NUMPIXELS, PIN_SIG, NEO_GRB + NEO_KHZ800); 34 | 35 | // increase timeout to measure longer distance 36 | Ultrasonic UDist(PIN_ECHO, PIN_TRIG, 30000UL); 37 | 38 | // include if you are using a Teensy 39 | // elapsedMillis ElapsedTime; 40 | 41 | void setup() { 42 | 43 | Serial.begin(9600); 44 | 45 | // initialize the light strip 46 | LightStrip.begin(); 47 | 48 | } 49 | 50 | void loop() { 51 | Distance = 0; 52 | 53 | // some distance flickering so do some averaging 54 | for (i = 0; i < 5; i++) { 55 | Distance = Distance + UDist.read(INC) ; 56 | } 57 | // average the distance 58 | Distance = Distance / 5; 59 | 60 | // my neopixel as 60 leds but i'd like to scale the 0-60 to 0 to 100 inches 61 | Distance = map(Distance, 0, 100, 0, 60); 62 | 63 | // do some range checking to keep pixels in 0-60 64 | // recall we are mapping 0 to 100 inches, so the range can be outside the 65 | // pixel count 66 | if (Distance > 60) { 67 | Distance = 60; 68 | } 69 | 70 | if (Distance < 0) { 71 | Distance = 0; 72 | } 73 | 74 | // add up to another 20 inches for adjustment 75 | // this lets' you calibrate the unit so you can account for large bumpers 76 | // stuff near the wall etc 77 | // simple here just divide 1024 measured bits by 50 to get 20 78 | Offset = analogRead(PIN_DIST) / 50; 79 | 80 | // if activity, reset counter which will wake up the unit, and display measured distance 81 | if (abs(Distance - OldDistance) > 2) { 82 | OldDistance = Distance; 83 | ElapsedTime = 0; 84 | Run = true; 85 | } 86 | 87 | // code for arduino (poor mans wrap around fixer) 88 | // my timeout is 8 seconds 89 | if (abs(millis() - OldTime) > 8000) { 90 | OldTime = millis(); 91 | LightStrip.clear(); 92 | Run = false; 93 | } 94 | 95 | // use this code if you are using a teensy 96 | /* 97 | if (ElapsedTime > 8000) { 98 | ElapsedTime = 0; 99 | LightStrip.clear(); 100 | Run = false; 101 | } 102 | */ 103 | 104 | if (Run) { 105 | 106 | Distance = Distance - Offset; 107 | 108 | if (Distance > 20) { 109 | // in the yellow region 110 | LightStrip.fill(LightStrip.Color(MINBRIGHT, MINBRIGHT, 0), 0, 40); // yellow 111 | LightStrip.fill(LightStrip.Color(0, MINBRIGHT, 0), 40, 10); // green 112 | LightStrip.fill(LightStrip.Color(MINBRIGHT, 0, 0), 50, 10); // red 113 | // now paint amount of yellow 114 | if (Distance < 60) { 115 | LightStrip.fill(LightStrip.Color(MAXBRIGHT, MAXBRIGHT, 0), 0, 60 - Distance); // yellow 116 | } 117 | } 118 | else if (( Distance > 10) && (Distance <= 20) ) { 119 | // in the green region 120 | LightStrip.fill(LightStrip.Color(MAXBRIGHT, MAXBRIGHT, 0), 0, 40); // yellow 121 | LightStrip.fill(LightStrip.Color(0, MINBRIGHT, 0), 40, 10); // green 122 | LightStrip.fill(LightStrip.Color(MINBRIGHT, 0, 0), 50, 10); // red 123 | // now paint amount of green 124 | LightStrip.fill(LightStrip.Color(0, MAXBRIGHT, 0), 40, 21 - Distance); // green 125 | } 126 | else if (( Distance >= 0) && (Distance <= 10) ) { 127 | // in the red region 128 | LightStrip.fill(LightStrip.Color(MAXBRIGHT, MAXBRIGHT, 0), 0, 40); // yellow 129 | LightStrip.fill(LightStrip.Color(0, MAXBRIGHT, 0), 40, 10); // green 130 | LightStrip.fill(LightStrip.Color(MINBRIGHT, 0, 0), 50, 10); // red 131 | // now paint amount of green 132 | LightStrip.fill(LightStrip.Color(MAXBRIGHT, 0, 0), 50, 11 - Distance); // red 133 | } 134 | 135 | 136 | } 137 | 138 | 139 | // OK my little blue LED pulsing in brightness to let you know the unit 140 | // is waiting..really don't need this :) 141 | if (!Run) { 142 | 143 | if (Pulse == 100) { 144 | Up = false; 145 | } 146 | if (Pulse == 0) { 147 | Up = true; 148 | } 149 | if (Up) { 150 | Pulse += 5; 151 | } 152 | else { 153 | Pulse -= 5; 154 | } 155 | LightStrip.setPixelColor(0, LightStrip.Color(0, 0, Pulse)); 156 | delay(10); 157 | } 158 | else { 159 | LightStrip.setPixelColor(0, LightStrip.Color(0, 0, 100)); 160 | delay(50); 161 | } 162 | 163 | // now that we have built the LED array, fire them up 164 | LightStrip.show(); 165 | 166 | 167 | } 168 | -------------------------------------------------------------------------------- /ParkingAttendent_STL.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrisKasprzak/SampleCode/c81b0cf6bdd05457987d28841aed28172b6dec65/ParkingAttendent_STL.zip -------------------------------------------------------------------------------- /Radio_SourceCode.ino: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////// 2 | //// RECEIVER CODE /////////////////////////////////////////////////////////// 3 | ///////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | /* 7 | 8 | receiver code for an RC sail boat that has rudder and main and jib sheet control 9 | 10 | Revisions 11 | rev date author description 12 | 1 06-17-2011 kasprzak initial creation 13 | 14 | Pin connections 15 | Arduino device 16 | Ground ground 17 | A0 18 | A1 19 | A2 20 | A3 21 | A4 22 | A5 23 | 1 24 | 2 IRQ (not used) brown 25 | 3 26 | 4 Rudder servo control line 27 | 5 28 | 6 Sail servo control line 29 | 7 30 | 8 31 | 9 CE (UNO only) 40 mega 32 | 10 CSN (UNO only) 53 mega 33 | 11 MOSI (UNO only) 51 mega 34 | 12 MISO (UNO only) 50 mega 35 | 13 SCK (UNO only) 52 mega 36 | SDA 37 | SLC 38 | 39 | Top view (pins on bottom) 40 | IRQ MISO 41 | MOSI SCK 42 | CSN CE 43 | VCC GND 44 | 45 | links to library 46 | https://github.com/maniacbug/RF24 47 | 48 | link to Transceiver 49 | http://www.amazon.com/gp/product/B00E594ZX0?psc=1&redirect=true&ref_=oh_aui_detailpage_o03_s00 50 | 51 | link to rf24 help page 52 | http://starter-kit.nettigo.eu/2014/connecting-and-programming-nrf24l01-with-arduino-and-other-boards/ 53 | 54 | */ 55 | 56 | #define RUD_PIN 4 57 | #define SAI_PIN 6 58 | 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | 65 | // a common data structure used to pass data to the reciever 66 | // commented below 67 | #include 68 | 69 | 70 | // uno 71 | RF24 radio(9, 10); 72 | 73 | //mega 74 | // RF24 radio(40,53); 75 | 76 | // address for both units 77 | const byte rxAddr[6] = "00001"; 78 | 79 | int Rudd; 80 | byte Sail; 81 | 82 | // initialize the data structure 83 | RCPacket data; 84 | 85 | // initialize the servos 86 | Servo RuddSVO; 87 | Servo SailSVO; 88 | 89 | void setup() 90 | { 91 | 92 | RuddSVO.attach(RUD_PIN); 93 | SailSVO.attach(SAI_PIN); 94 | 95 | radio.begin(); 96 | 97 | /* 98 | rf24 power constants 99 | RF24_PA_MIN 100 | RF24_PA_LOW 101 | RF24_PA_HIGH 102 | RF24_PA_MAX 103 | 104 | */ 105 | 106 | radio.setPALevel(RF24_PA_HIGH); 107 | radio.setRetries(15, 15); 108 | radio.openReadingPipe(0, rxAddr); 109 | radio.startListening(); 110 | 111 | } 112 | 113 | void loop() 114 | { 115 | 116 | if (radio.available()) { 117 | 118 | radio.read(&data, sizeof(data)); 119 | 120 | // the input pot has already been converted to the rudder sweep angle 121 | // so just write it to the servo 122 | 123 | 124 | RuddSVO.write(data.Rudd); 125 | 126 | // the directon and speed has already been converted for the sheet in / out 127 | // so just write it to the servo 128 | SailSVO.write(data.Sail); 129 | 130 | } 131 | 132 | 133 | // future 134 | // 1. write a call back to send back what was recieved for transmitter to verify 135 | // 2. adjust power lower if reciever can find the radio, else adjust the power higher 136 | // 3. come home function with GPS so if radio is lost boat comes home 137 | 138 | } 139 | 140 | 141 | 142 | ///////////////////////////////////////////////////////////////////////////////// 143 | ///// DATA STRUCTURE //////////////////////////////////////////////////////////// 144 | ///////////////////////////////////////////////////////////////////////////////// 145 | 146 | /* 147 | 148 | 149 | This structure is in a .h file called structure.h and stored in the Arduino library folder 150 | 151 | 152 | 153 | struct RCPacket { 154 | 155 | unsigned long curtime; 156 | byte Rudd; 157 | byte Sail; 158 | 159 | 160 | 161 | }; 162 | 163 | */ 164 | 165 | 166 | 167 | ///////////////////////////////////////////////////////////////////////////////// 168 | //// TRANSMITTER CODE /////////////////////////////////////////////////////////// 169 | ///////////////////////////////////////////////////////////////////////////////// 170 | 171 | /* 172 | 173 | 174 | transmitter code for an RC sail boat that has rudder and main and jib sheet control 175 | 176 | Revisions 177 | rev date author description 178 | 1 06-17-2011 kasprzak initial creation 179 | 180 | Pin connections 181 | Arduino device 182 | Ground ground 183 | A0 184 | A1 185 | A2 186 | A3 187 | A4 188 | A5 189 | 1 190 | 2 IRQ (not used) brown 191 | 3 192 | 4 193 | 5 194 | 6 Sail servo control line 195 | 7 Rudder servo control line 196 | 8 197 | 9 CE (UNO only) 40 mega 198 | 10 CSN (UNO only) 53 mega 199 | 11 MOSI (UNO only) 51 mega 200 | 12 MISO (UNO only) 50 mega 201 | 13 SCK (UNO only) 52 mega 202 | SDA 203 | SLC 204 | 205 | Top view (pins on bottom) 206 | IRQ MISO 207 | MOSI SCK 208 | CSN CE 209 | VCC GND 210 | 211 | links to library 212 | https://github.com/maniacbug/RF24 213 | 214 | link to Transceiver 215 | http://www.amazon.com/gp/product/B00E594ZX0?psc=1&redirect=true&ref_=oh_aui_detailpage_o03_s00 216 | 217 | link to rf24 help page 218 | http://starter-kit.nettigo.eu/2014/connecting-and-programming-nrf24l01-with-arduino-and-other-boards/ 219 | 220 | 221 | 222 | #include 223 | #include 224 | #include 225 | #include 226 | 227 | #define ADJ_PIN A0 228 | #define SIN_PIN 2 229 | #define SOU_PIN 4 230 | 231 | int Rudd; 232 | bool SailIn; 233 | bool SailOu; 234 | 235 | // mega 236 | // RF24 radio(40, 53); 237 | 238 | //uno 239 | RF24 radio(9, 10); 240 | 241 | // initialize the data structure 242 | RCPacket data; 243 | 244 | // address for both units 245 | const byte rxAddr[6] = "00001"; 246 | 247 | void setup() { 248 | Serial.begin(9600); 249 | radio.begin(); 250 | 251 | 252 | // rf24 power constants 253 | // RF24_PA_MIN 254 | // RF24_PA_LOW 255 | // RF24_PA_HIGH 256 | // RF24_PA_MAX 257 | 258 | 259 | 260 | radio.setPALevel(RF24_PA_HIGH); 261 | radio.setRetries(15, 15); 262 | radio.openWritingPipe(rxAddr); 263 | radio.stopListening(); 264 | 265 | // 100k pot for the rudder input 266 | pinMode(ADJ_PIN, INPUT); 267 | 268 | // use pullup to use Arduino internal 20K pullups 269 | // saves me having to solder in resistors 270 | pinMode(SIN_PIN, INPUT_PULLUP); 271 | pinMode(SOU_PIN, INPUT_PULLUP); 272 | 273 | } 274 | 275 | void loop() { 276 | 277 | // may some day use this for a call back comparison to ensure signal was recieved 278 | data.curtime = millis() / 1000; 279 | 280 | // read the pot value and the digital pins for the rudder adjustment 281 | Rudd = analogRead(ADJ_PIN) ; 282 | 283 | 284 | // store the pot value in the data structure 285 | // map the 0 to 3.3 volt signal to a 110 degree arc 286 | // mapping to 110 degree to give full pot sweep for finer control 287 | // note i'm using 3.3 volts (204.6 * 3.3) as the pin was easier to solder to... 288 | // write the converted voltage 289 | 290 | data.Rudd = map(Rudd, 0, 690, 35, 145); 291 | 292 | 293 | // now set the sail adjustment 294 | SailIn = digitalRead(SIN_PIN) ; 295 | SailOu = digitalRead(SOU_PIN) ; 296 | // for this constant rotation servo 0 is CCW, 180 is CW and 90 is off 297 | // other values set the direction and speed 298 | // i want the servo to run slower to avoild tangling the sheet line so 299 | // using 70 for CCW, 110 for CW and 90 for off 300 | // the transmitte simply sends these values depending on what switched is pressed 301 | if (SailIn == LOW & SailOu == HIGH) { 302 | // bring sail in 303 | data.Sail = 70; 304 | } 305 | else if (SailIn == HIGH & SailOu == LOW) { 306 | // bring sail out 307 | data.Sail = 110; 308 | } 309 | else { 310 | // stop sail 311 | data.Sail = 90; 312 | } 313 | 314 | Serial.println(data.Rudd); 315 | Serial.println(data.Sail); 316 | Serial.println(" "); 317 | 318 | // write the data to the radio 319 | radio.write(&data, sizeof(data)); 320 | 321 | // future 322 | // 1. write a call back to ask what was recieved and verify 323 | // 2. adjust power lower but if recieve can find the radio adjust the power higher 324 | // 3. come home function with GPS so if radio is lost boat comes home 325 | 326 | 327 | } 328 | 329 | */ 330 | 331 | -------------------------------------------------------------------------------- /ServoSymphony.ino: -------------------------------------------------------------------------------- 1 | #define TEMPO 1000000 2 | #define R1 1 3 | #define R2 2 4 | #define R4 4 5 | #define R8 8 6 | #define R16 16 7 | #define R32 32 8 | 9 | #define N_A0 27.5 10 | #define N_B0 30.87 11 | #define N_C1 32.71 12 | #define N_D1 36.71 13 | #define N_E1 41.2 14 | #define N_F1 43.65 15 | #define N_G1 49 16 | #define N_A1 55 17 | #define N_B1 61.74 18 | 19 | #define N_C2 65.41 20 | #define N_D2 73.42 21 | #define N_E2 82.41 22 | #define N_F2 87.31 23 | #define N_G2 98 24 | #define N_A2 100 25 | #define N_B2 123.47 26 | 27 | #define N_C3 130.81 28 | #define N_D3 146.83 29 | #define N_E3 164.81 30 | #define N_F3 174.61 31 | #define N_G3 196 32 | #define N_A3 220 33 | #define N_B3F 233.08 34 | #define N_B3 246.94 35 | 36 | #define N_C4 261.63 37 | #define N_D4F 277.18 38 | #define N_D4 293.67 39 | #define N_E4 329.63 40 | #define N_F4 349.23 41 | #define N_G4 392 42 | #define N_A4 440 43 | #define N_B4 493.88 44 | 45 | #define N_C5 523.25 46 | #define N_D5 587.33 47 | #define N_D5S 622.25 48 | #define N_E5 659.26 49 | #define N_F5 698.46 50 | #define N_F5S 740 51 | #define N_G5 783.99 52 | #define N_G5S 831.61 53 | #define N_A5 880 54 | #define N_B5 987.77 55 | 56 | #define N_C6 1046.5 57 | #define N_D6 1174.7 58 | #define N_D6S 1244.5 59 | #define N_E6 1318.5 60 | #define N_F6 1396.9 61 | #define N_F6S 1480 62 | #define N_G6 1568 63 | #define N_G6S 1661.2 64 | #define N_A6 1760 65 | #define N_B6 1975.5 66 | 67 | #define N_C7 2093 68 | #define N_D7 2349.3 69 | #define N_E7 2637 70 | #define N_F7 2793 71 | #define N_G7 3136 72 | #define N_A7 3520 73 | #define N_B7 3951.1 74 | 75 | #define N_C8 2093 76 | 77 | #define XMOTOR_DIR 0 78 | #define XMOTOR_STEP 1 79 | #define XMOTOR_EN 5 80 | 81 | int i; 82 | unsigned long TheStart; 83 | 84 | void setup() { 85 | 86 | Serial.begin(9600); 87 | while (!Serial) {} 88 | pinMode(XMOTOR_EN, OUTPUT); 89 | pinMode(XMOTOR_DIR, OUTPUT); 90 | pinMode(XMOTOR_STEP, OUTPUT); 91 | 92 | pinMode(2, OUTPUT); 93 | pinMode(3, OUTPUT); 94 | pinMode(4, OUTPUT); 95 | 96 | 97 | digitalWrite(XMOTOR_DIR, LOW); 98 | digitalWrite(XMOTOR_STEP, HIGH); 99 | digitalWrite(XMOTOR_EN, HIGH); 100 | 101 | digitalWrite(2, LOW); 102 | digitalWrite(3, LOW); 103 | digitalWrite(4, LOW); 104 | 105 | 106 | } 107 | 108 | void loop() { 109 | 110 | ThunderStruck(); 111 | // SmokeOnTheWater(); 112 | } 113 | 114 | 115 | 116 | void SlideNote(long FirstNote, long SecondNote, unsigned long Delay) { 117 | 118 | digitalWrite(XMOTOR_EN, LOW); 119 | digitalWrite(XMOTOR_DIR, LOW); 120 | unsigned int Steps; 121 | 122 | if (FirstNote < SecondNote) { 123 | Steps = SecondNote - FirstNote; 124 | for (i = FirstNote; i < SecondNote; i++) { 125 | TheStart = micros(); 126 | while ((micros() - TheStart) < (TEMPO / (Steps * Delay))) { 127 | digitalWrite(XMOTOR_STEP, HIGH); 128 | delayMicroseconds(1000000.0 / i); 129 | digitalWrite(XMOTOR_STEP, LOW); 130 | delayMicroseconds(1); 131 | } 132 | } 133 | } 134 | else { 135 | Steps = FirstNote - SecondNote; 136 | for (i = FirstNote; i > SecondNote; i--) { 137 | TheStart = micros(); 138 | while ((micros() - TheStart) < (TEMPO / (Steps * Delay))) { 139 | digitalWrite(XMOTOR_STEP, HIGH); 140 | delayMicroseconds(1000000.0 / i); 141 | digitalWrite(XMOTOR_STEP, LOW); 142 | delayMicroseconds(1); 143 | } 144 | } 145 | } 146 | digitalWrite(XMOTOR_EN, HIGH); 147 | 148 | } 149 | 150 | 151 | void Rest(unsigned int val) { 152 | 153 | delayMicroseconds(TEMPO / val); 154 | } 155 | 156 | void PlayNote(long Note, unsigned long Delay) { 157 | 158 | digitalWrite(XMOTOR_EN, LOW); 159 | digitalWrite(XMOTOR_DIR, LOW); 160 | TheStart = micros(); 161 | 162 | while ((micros() - TheStart) <= (TEMPO / Delay)) { 163 | digitalWrite(XMOTOR_STEP, HIGH); 164 | delayMicroseconds(1000000.0 / Note); 165 | digitalWrite(XMOTOR_STEP, LOW); 166 | delayMicroseconds(1); 167 | 168 | } 169 | 170 | 171 | digitalWrite(XMOTOR_EN, HIGH); 172 | 173 | } 174 | 175 | void Scale() { 176 | 177 | PlayNote(N_C3, 100); 178 | PlayNote(N_D3, 100); 179 | PlayNote(N_E3, 100); 180 | PlayNote(N_F3, 100); 181 | PlayNote(N_G3, 100); 182 | PlayNote(N_A3, 100); 183 | PlayNote(N_B3, 100); 184 | 185 | PlayNote(N_C4, 100); 186 | PlayNote(N_D4, 100); 187 | PlayNote(N_E4, 100); 188 | PlayNote(N_F4, 100); 189 | PlayNote(N_G4, 100); 190 | PlayNote(N_A4, 100); 191 | PlayNote(N_B4, 100); 192 | 193 | PlayNote(N_C5, 100); 194 | PlayNote(N_D5, 100); 195 | PlayNote(N_E5, 100); 196 | PlayNote(N_F5, 100); 197 | PlayNote(N_G5, 100); 198 | PlayNote(N_A5, 100); 199 | PlayNote(N_B5, 100); 200 | 201 | PlayNote(N_C6, 100); 202 | PlayNote(N_D6, 100); 203 | PlayNote(N_E6, 100); 204 | PlayNote(N_F6, 100); 205 | PlayNote(N_G6, 100); 206 | PlayNote(N_A6, 100); 207 | PlayNote(N_B6, 100); 208 | 209 | } 210 | 211 | 212 | 213 | void ThunderStruck() { 214 | 215 | 216 | PlayNote(N_B5, R8); 217 | for (i = 0; i < 8; i++) { 218 | PlayNote(N_D6S, R8); 219 | PlayNote(N_B5, R8); 220 | PlayNote(N_F6S, R8); 221 | PlayNote(N_B5, R8); 222 | } 223 | for (i = 0; i < 8; i++) { 224 | PlayNote(N_E6, R8); 225 | PlayNote(N_B5, R8); 226 | PlayNote(N_G6, R8); 227 | PlayNote(N_B5, R8); 228 | } 229 | for (i = 0; i < 8; i++) { 230 | PlayNote(N_D6S, R8); 231 | PlayNote(N_B5, R8); 232 | PlayNote(N_F6S, R8); 233 | PlayNote(N_B5, R8); 234 | } 235 | for (i = 0; i < 8; i++) { 236 | PlayNote(N_E6, R8); 237 | PlayNote(N_B5, R8); 238 | PlayNote(N_G6, R8); 239 | PlayNote(N_B5, R8); 240 | } 241 | 242 | //0000000000000000000000000000000000000000 243 | for (i = 0; i < 8; i++) { 244 | //1 245 | PlayNote(N_B6, R8); 246 | PlayNote(N_B5, R8); 247 | PlayNote(N_A6, R8); 248 | PlayNote(N_B5, R8); 249 | //2 250 | PlayNote(N_G6S, R8); 251 | PlayNote(N_B5, R8); 252 | PlayNote(N_A6, R8); 253 | PlayNote(N_B5, R8); 254 | //3 255 | PlayNote(N_G6S, R8); 256 | PlayNote(N_B5, R8); 257 | PlayNote(N_F6S, R8); 258 | PlayNote(N_B5, R8); 259 | // 4 260 | PlayNote(N_G6S, R8); 261 | PlayNote(N_B5, R8); 262 | PlayNote(N_E6, R8); 263 | PlayNote(N_B5, R8); 264 | // 5 265 | PlayNote(N_F6S, R8); 266 | PlayNote(N_B5, R8); 267 | PlayNote(N_D6S, R8); 268 | PlayNote(N_B5, R8); 269 | // 6 270 | PlayNote(N_E6, R8); 271 | PlayNote(N_B5, R8); 272 | PlayNote(N_D6S, R8); 273 | PlayNote(N_B5, R8); 274 | // 7 275 | PlayNote(N_E6, R8); 276 | PlayNote(N_B5, R8); 277 | PlayNote(N_D6S, R8); 278 | PlayNote(N_B5, R8); 279 | // 8 280 | PlayNote(N_E6, R8); 281 | PlayNote(N_B5, R8); 282 | PlayNote(N_D6S, R8); 283 | PlayNote(N_B5, R8); 284 | } 285 | } 286 | void SmokeOnTheWater() { 287 | 288 | PlayNote(N_G3, R4); 289 | PlayNote(N_B3F, R4); 290 | PlayNote(N_C4, R2); 291 | 292 | PlayNote(N_G3, R4); 293 | PlayNote(N_B3F, R4); 294 | PlayNote(N_D4F, R8); 295 | PlayNote(N_C4, R4); 296 | PlayNote(N_C4, R8); 297 | 298 | PlayNote(N_G3, R4); 299 | PlayNote(N_B3F, R4); 300 | PlayNote(N_C4, R2); 301 | PlayNote(N_B3F, R4); 302 | Rest(R32); 303 | PlayNote(N_G3, R8); 304 | Rest(R32); 305 | PlayNote(N_G3, R8); 306 | SlideNote(N_G3, N_E3, R2); 307 | 308 | Rest(R2); 309 | 310 | PlayNote(N_G3, R4); 311 | PlayNote(N_B3F, R4); 312 | PlayNote(N_C4, R2); 313 | 314 | PlayNote(N_G3, R4); 315 | PlayNote(N_B3F, R4); 316 | PlayNote(N_D4F, R8); 317 | PlayNote(N_C4, R4); 318 | PlayNote(N_C4, R8); 319 | 320 | PlayNote(N_G3, R4); 321 | PlayNote(N_B3F, R4); 322 | PlayNote(N_C4, R2); 323 | PlayNote(N_B3F, R4); 324 | Rest(R32); 325 | PlayNote(N_G3, R8); 326 | Rest(R32); 327 | PlayNote(N_G3, R8); 328 | SlideNote(N_G3, N_E3, R4); 329 | 330 | Rest(R4); 331 | 332 | PlayNote(N_G3, R4); 333 | PlayNote(N_B3F, R4); 334 | Rest(R32); 335 | PlayNote(N_B3F, R4); 336 | Rest(R32); 337 | PlayNote(N_G3, R4); 338 | PlayNote(N_B3F, R4); 339 | Rest(R32); 340 | PlayNote(N_B3F, R4); 341 | SlideNote(N_B3F, N_C4, R4); 342 | 343 | Rest(R4); 344 | 345 | PlayNote(N_G3, R4); 346 | PlayNote(N_B3F, R4); 347 | Rest(R32); 348 | PlayNote(N_B3F, R4); 349 | PlayNote(N_G3, R4); 350 | PlayNote(N_B3F, R4); 351 | 352 | SlideNote(N_B3F, N_G3, R4); 353 | Rest(R4); 354 | 355 | PlayNote(N_G3, R4); 356 | PlayNote(N_B3F, R4); 357 | PlayNote(N_C4, R2); 358 | 359 | PlayNote(N_G3, R4); 360 | PlayNote(N_B3F, R4); 361 | PlayNote(N_D4F, R8); 362 | PlayNote(N_C4, R4); 363 | PlayNote(N_C4, R8); 364 | 365 | PlayNote(N_G3, R4); 366 | PlayNote(N_B3F, R4); 367 | PlayNote(N_C4, R2); 368 | PlayNote(N_B3F, R4); 369 | Rest(R32); 370 | PlayNote(N_G3, R8); 371 | Rest(R32); 372 | PlayNote(N_G3, R8); 373 | SlideNote(N_G3, N_E3, R2); 374 | 375 | 376 | } 377 | -------------------------------------------------------------------------------- /ThermalCamera_Fast.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This program is for upsizing an 8 x 8 array of thermal camera readings 4 | it will size up by 10x and display to a 240 x 320 5 | interpolation is linear and "good enough" given the display is a 5-6-5 color palet 6 | Total final array is an array of 70 x 70 of internal points only 7 | 8 | Revisions 9 | 1.0 Kasprzak Initial code 10 | 2.0 Kasprzak removed functions for better speed (and went from 2.37 to 4.44 fps 11 | 12 | MCU https://www.amazon.com/Teensy-3-2-with-pins/dp/B015QUPO5Y/ref=sr_1_2?s=industrial&ie=UTF8&qid=1510373806&sr=1-2&keywords=teensy+3.2 13 | Display https://www.amazon.com/Wrisky-240x320-Serial-Module-ILI9341/dp/B01KX26JJU/ref=sr_1_10?ie=UTF8&qid=1510373771&sr=8-10&keywords=240+x+320+tft 14 | Thermal sensor https://learn.adafruit.com/adafruit-amg8833-8x8-thermal-camera-sensor/overview 15 | display library https://github.com/PaulStoffregen/ILI9341_t3 16 | font library https://github.com/PaulStoffregen/ILI9341_fonts 17 | sensor library https://github.com/adafruit/Adafruit_AMG88xx 18 | touchscreen lib https://github.com/dgolda/UTouch 19 | equations generated from http://web-tech.ga-usa.com/2012/05/creating-a-custom-hot-to-cold-temperature-color-gradient-for-use-with-rrdtool/index.html 20 | 21 | Pinouts 22 | MCU Device 23 | A4 AMG SDA 24 | A5 AMG SCL 25 | Gnd Dispaly GND, AMG Gnd 26 | 3v3 Dispaly Vcc,Display LED,Display RST, AMG Vcc 27 | 2 Dispaly T_CLK 28 | 3 Dispaly T_CS 29 | 4 Dispaly T_DIN 30 | 5 Dispaly T_DO 31 | 6 Dispaly T_IRQ 32 | 9 Display D/C 33 | 10 Display CS 34 | 11 Display MOSI 35 | 12 Dispaly MISO 36 | 13 Display SCK 37 | 38 | */ 39 | 40 | #include "ILI9341_t3.h" // very fast library 41 | #include "font_ArialBoldItalic.h" // fonts for the startup screen 42 | #include "font_Arial.h" // fonts for the legend 43 | #include "font_DroidSans.h" // fonts for the startup screen 44 | // #include "Fonts\kris.h" // fonts for the startup screen 45 | #include // thermal camera lib 46 | #include // touchscreen lib 47 | 48 | #define PIN_CS 10 // chip select for the display 49 | #define PIN_DC 9 // d/c pin for the display 50 | 51 | // constants for the cute little keypad 52 | #define KEYPAD_TOP 15 53 | #define KEYPAD_LEFT 50 54 | #define BUTTON_W 60 55 | #define BUTTON_H 30 56 | #define BUTTON_SPACING_X 10 57 | #define BUTTON_SPACING_Y 10 58 | #define BUTTON_TEXTSIZE 2 59 | 60 | // fire up the display using a very fast driver 61 | ILI9341_t3 Display = ILI9341_t3(PIN_CS, PIN_DC); 62 | 63 | // note if you have a white screen trying connecting a reset line (say pin 7 on your teensy to RST on the display and use this line 64 | // if you have no pins left, put a 1K series resistor between Vcc and RST on the dispay and a 10 uf cap between RST and GND on the display 65 | // basically add a low pass filter--this will slow the charge to the RST pin (you may need to experiment with the resistor and cap values 66 | // ILI9341_t3 Display = ILI9341_t3(PIN_CS, PIN_DC, 7); 67 | 68 | 69 | // create some colors for the keypad buttons 70 | #define C_BLUE Display.color565(0,0,255) 71 | #define C_RED Display.color565(255,0,0) 72 | #define C_GREEN Display.color565(0,255,0) 73 | #define C_WHITE Display.color565(255,255,255) 74 | #define C_BLACK Display.color565(0,0,0) 75 | #define C_LTGREY Display.color565(200,200,200) 76 | #define C_DKGREY Display.color565(80,80,80) 77 | #define C_GREY Display.color565(127,127,127) 78 | 79 | 80 | unsigned long CurTime; 81 | 82 | // create some text for the keypad butons 83 | char KeyPadBtnText[12][5] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "Done", "0", "Clr" }; 84 | 85 | // define some colors for the keypad buttons 86 | uint16_t KeyPadBtnColor[12] = {C_BLUE, C_BLUE, C_BLUE, C_BLUE, C_BLUE, C_BLUE, C_BLUE, C_BLUE, C_BLUE, C_GREEN, C_BLUE, C_RED }; 87 | uint16_t TheColor; 88 | // start with some initial colors 89 | uint16_t MinTemp = 25; 90 | uint16_t MaxTemp = 35; 91 | 92 | // variables for interpolated colors 93 | byte red, green, blue; 94 | 95 | // variables for row/column interpolation 96 | byte i, j, k, row, col, incr; 97 | float intPoint, val, a, b, c, d, ii; 98 | byte aLow, aHigh; 99 | 100 | // size of a display "pixel" 101 | byte BoxWidth = 3; 102 | byte BoxHeight = 3; 103 | 104 | 105 | uint16_t PixelColor; 106 | 107 | 108 | int x, y; 109 | char buf[20]; 110 | 111 | // variable to toggle the display grid 112 | int ShowGrid = -1; 113 | int DefaultTemp = -1; 114 | 115 | // array for the 8 x 8 measured pixels 116 | float pixels[64]; 117 | 118 | // array for the interpolated array 119 | float HDTemp[80][80]; 120 | 121 | 122 | 123 | char name[] = "9px_0000.bmp"; // filename convention (will auto-increment) 124 | const int w = 320; // image width in pixels 125 | const int h = 240; // " height 126 | const boolean debugPrint = true; // print details of process over serial? 127 | 128 | const int imgSize = w * h; 129 | int px[w * h]; // actual pixel data (grayscale - added programatically below) 130 | 131 | const uint8_t cardPin = 8; // pin that the SD is connected to (d8 for SparkFun MicroSD shield) 132 | 133 | 134 | 135 | // create the keypad buttons 136 | // note the ILI9438_3t library makes use of the Adafruit_GFX library (which makes use of the Adafruit_button library) 137 | Adafruit_GFX_Button KeyPadBtn[12]; 138 | 139 | // create the camara object 140 | Adafruit_AMG88xx ThermalSensor; 141 | 142 | // create the touch screen object 143 | UTouch Touch( 2, 3, 4, 5, 6); 144 | 145 | void setup() { 146 | 147 | // Serial.begin(9600); 148 | 149 | // start the display and set the background to black 150 | Display.begin(); 151 | Display.fillScreen(C_BLACK); 152 | 153 | // initialize the touch screen and set location precision 154 | Touch.InitTouch(); 155 | Touch.setPrecision(PREC_EXTREME); 156 | 157 | // create the keypad buttons 158 | for (row = 0; row < 4; row++) { 159 | for (col = 0; col < 3; col++) { 160 | KeyPadBtn[col + row * 3].initButton(&Display, BUTTON_H + BUTTON_SPACING_X + KEYPAD_LEFT + col * (BUTTON_W + BUTTON_SPACING_X ), 161 | KEYPAD_TOP + 2 * BUTTON_H + row * (BUTTON_H + BUTTON_SPACING_Y), 162 | BUTTON_W, BUTTON_H, C_WHITE, KeyPadBtnColor[col + row * 3], C_WHITE, 163 | KeyPadBtnText[col + row * 3], BUTTON_TEXTSIZE); 164 | } 165 | } 166 | 167 | // set display rotation (you may need to change to 0 depending on your display 168 | Display.setRotation(3); 169 | 170 | 171 | // show a cute splash screen (paint text twice to show a little shadow 172 | Display.setFont(DroidSans_40); 173 | Display.setCursor(22, 21); 174 | Display.setTextColor(C_WHITE, C_BLACK); 175 | Display.print("Thermal"); 176 | 177 | Display.setFont(DroidSans_40); 178 | Display.setCursor(20, 20); 179 | Display.setTextColor(C_BLUE, C_BLACK); 180 | Display.print("Thermal"); 181 | 182 | Display.setFont(Arial_48_Bold_Italic); 183 | Display.setCursor(52, 71); 184 | Display.setTextColor(C_WHITE, C_BLACK); 185 | Display.print("Camera"); 186 | 187 | Display.setFont(Arial_48_Bold_Italic); 188 | Display.setCursor(50, 70); 189 | Display.setTextColor(C_RED, C_BLACK); 190 | Display.print("Camera"); 191 | 192 | 193 | // let sensor boot up 194 | bool status = ThermalSensor.begin(); 195 | delay(100); 196 | 197 | // check status and display results 198 | if (!status) { 199 | while (1) { 200 | Display.setFont(DroidSans_20); 201 | Display.setCursor(20, 150); 202 | Display.setTextColor(C_RED, C_BLACK); 203 | Display.print("Sensor: FAIL"); 204 | delay(500); 205 | Display.setFont(DroidSans_20); 206 | Display.setCursor(20, 150); 207 | Display.setTextColor(C_BLACK, C_BLACK); 208 | Display.print("Sensor: FAIL"); 209 | delay(500); 210 | } 211 | } 212 | else { 213 | Display.setFont(DroidSans_20); 214 | Display.setCursor(20, 150); 215 | Display.setTextColor(C_GREEN, C_BLACK); 216 | Display.print("Sensor: FOUND"); 217 | } 218 | 219 | // read the camera for initial testing 220 | ThermalSensor.readPixels(pixels); 221 | 222 | // check status and display results 223 | if (pixels[0] < 0) { 224 | while (1) { 225 | Display.setFont(DroidSans_20); 226 | Display.setCursor(20, 180); 227 | Display.setTextColor(C_RED, C_BLACK); 228 | Display.print("Readings: FAIL"); 229 | delay(500); 230 | Display.setFont(DroidSans_20); 231 | Display.setCursor(20, 180); 232 | Display.setTextColor(C_BLACK, C_BLACK); 233 | Display.print("Readings: FAIL"); 234 | delay(500); 235 | } 236 | } 237 | else { 238 | Display.setFont(DroidSans_20); 239 | Display.setCursor(20, 180); 240 | Display.setTextColor(C_GREEN, C_BLACK); 241 | Display.print("Readings: OK"); 242 | delay(2000); 243 | } 244 | 245 | // set display rotation and clear the fonts..the rotation of this display is a bit weird 246 | 247 | Display.setFontAdafruit(); 248 | Display.fillScreen(C_BLACK); 249 | 250 | // get the cutoff points for the color interpolation routines 251 | // note this function called when the temp scale is changed 252 | Getabcd(); 253 | 254 | // draw a cute legend with the scale that matches the sensors max and min 255 | DrawLegend(); 256 | 257 | // draw a large white border for the temperature area 258 | Display.fillRect(10, 10, 220, 220, C_WHITE); 259 | 260 | Display.setRotation(2); 261 | 262 | 263 | } 264 | 265 | void loop() { 266 | 267 | // CurTime = millis(); 268 | 269 | // if someone touched the screen do something with it 270 | if (Touch.dataAvailable()) { 271 | ProcessTouch(); 272 | 273 | } 274 | 275 | // read the sensor 276 | ThermalSensor.readPixels(pixels); 277 | // now that we have an 8 x 8 sensor array 278 | // interpolate to get a bigger screen 279 | // interpolate the 8 rows (interpolate the 70 column points between the 8 sensor pixels first) 280 | for (row = 0; row < 8; row ++) { 281 | for (col = 0; col < 70; col ++) { 282 | // get the first array point, then the next 283 | // also need to bump by 8 for the subsequent rows 284 | aLow = col / 10 + (row * 8); 285 | aHigh = (col / 10) + 1 + (row * 8); 286 | // get the amount to interpolate for each of the 10 columns 287 | // here were doing simple linear interpolation mainly to keep performace high and 288 | // display is 5-6-5 color palet so fancy interpolation will get lost in low color depth 289 | intPoint = (( pixels[aHigh] - pixels[aLow] ) / 10.0 ); 290 | // determine how much to bump each column (basically 0-9) 291 | incr = col % 10; 292 | // find the interpolated value 293 | val = (intPoint * incr ) + pixels[aLow]; 294 | // store in the 70 x 70 array 295 | // since display is pointing away, reverse row to transpose row data 296 | HDTemp[ (7 - row) * 10][col] = val; 297 | 298 | } 299 | } 300 | 301 | // now that we have row data with 70 columns 302 | // interpolate each of the 70 columns 303 | // forget Arduino..no where near fast enough..Teensy at > 72 mhz is the starting point 304 | for (col = 0; col < 70; col ++) { 305 | for (row = 0; row < 70; row ++) { 306 | // get the first array point, then the next 307 | // also need to bump by 8 for the subsequent cols 308 | aLow = (row / 10 ) * 10; 309 | aHigh = aLow + 10; 310 | // get the amount to interpolate for each of the 10 columns 311 | // here were doing simple linear interpolation mainly to keep performace high and 312 | // display is 5-6-5 color palet so fancy interpolation will get lost in low color depth 313 | intPoint = (( HDTemp[aHigh][col] - HDTemp[aLow][col] ) / 10.0 ); 314 | // determine how much to bump each column (basically 0-9) 315 | incr = row % 10; 316 | // find the interpolated value 317 | val = (intPoint * incr ) + HDTemp[aLow][col]; 318 | // store in the 70 x 70 array 319 | HDTemp[ row ][col] = val; 320 | } 321 | } 322 | // display the 70 x 70 array 323 | 324 | // rip through 70 rows 325 | for (row = 0; row < 70; row ++) { 326 | 327 | // fast way to draw a non-flicker grid--just make every 10 pixels 2x2 as opposed to 3x3 328 | // drawing lines after the grid will just flicker too much 329 | if (ShowGrid < 0) { 330 | BoxWidth = 3; 331 | } 332 | else { 333 | if ((row % 10 == 9) ) { 334 | BoxWidth = 2; 335 | } 336 | else { 337 | BoxWidth = 3; 338 | } 339 | } 340 | // then rip through each 70 cols 341 | for (col = 0; col < 70; col++) { 342 | 343 | // fast way to draw a non-flicker grid--just make every 10 pixels 2x2 as opposed to 3x3 344 | if (ShowGrid < 0) { 345 | BoxHeight = 3; 346 | } 347 | else { 348 | if ( (col % 10 == 9)) { 349 | BoxHeight = 2; 350 | } 351 | else { 352 | BoxHeight = 3; 353 | } 354 | } 355 | // finally we can draw each the 70 x 70 points, note the call to get interpolated color 356 | 357 | val = HDTemp[ row ][col]; 358 | 359 | red = constrain(255.0 / (c - b) * val - ((b * 255.0) / (c - b)), 0, 255); 360 | 361 | if ((val > MinTemp) & (val < a)) { 362 | green = constrain(255.0 / (a - MinTemp) * val - (255.0 * MinTemp) / (a - MinTemp), 0, 255); 363 | } 364 | else if ((val >= a) & (val <= c)) { 365 | green = 255; 366 | } 367 | else if (val > c) { 368 | green = constrain(255.0 / (c - d) * val - (d * 255.0) / (c - d), 0, 255); 369 | } 370 | else if ((val > d) | (val < a)) { 371 | green = 0; 372 | } 373 | 374 | if (val <= b) { 375 | blue = constrain(255.0 / (a - b) * val - (255.0 * b) / (a - b), 0, 255); 376 | } 377 | else if ((val > b) & (val <= d)) { 378 | blue = 0; 379 | } 380 | else if (val > d) { 381 | blue = constrain(240.0 / (MaxTemp - d) * val - (d * 240.0) / (MaxTemp - d), 0, 240); 382 | } 383 | 384 | // use the displays color mapping function to get 5-6-5 color palet (R=5 bits, G=6 bits, B-5 bits) 385 | // TheColor = Display.color565(red, green, blue); 386 | 387 | TheColor = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3); 388 | Display.fillRect((row * 3) + 15, (col * 3) + 15, BoxWidth, BoxHeight, TheColor); 389 | } 390 | } 391 | 392 | } 393 | 394 | 395 | // my fast yet effective color interpolation routine 396 | uint16_t GetColor(float val) { 397 | 398 | /* 399 | pass in value and figure out R G B 400 | several published ways to do this I basically graphed R G B and developed simple linear equations 401 | again a 5-6-5 color display will not need accurate temp to R G B color calculation 402 | 403 | equations based on 404 | http://web-tech.ga-usa.com/2012/05/creating-a-custom-hot-to-cold-temperature-color-gradient-for-use-with-rrdtool/index.html 405 | 406 | */ 407 | 408 | red = constrain(255.0 / (c - b) * val - ((b * 255.0) / (c - b)), 0, 255); 409 | 410 | if ((val > MinTemp) & (val < a)) { 411 | green = constrain(255.0 / (a - MinTemp) * val - (255.0 * MinTemp) / (a - MinTemp), 0, 255); 412 | } 413 | else if ((val >= a) & (val <= c)) { 414 | green = 255; 415 | } 416 | else if (val > c) { 417 | green = constrain(255.0 / (c - d) * val - (d * 255.0) / (c - d), 0, 255); 418 | } 419 | else if ((val > d) | (val < a)) { 420 | green = 0; 421 | } 422 | 423 | if (val <= b) { 424 | blue = constrain(255.0 / (a - b) * val - (255.0 * b) / (a - b), 0, 255); 425 | } 426 | else if ((val > b) & (val <= d)) { 427 | blue = 0; 428 | } 429 | else if (val > d) { 430 | blue = constrain(240.0 / (MaxTemp - d) * val - (d * 240.0) / (MaxTemp - d), 0, 240); 431 | } 432 | 433 | // use the displays color mapping function to get 5-6-5 color palet (R=5 bits, G=6 bits, B-5 bits) 434 | return Display.color565(red, green, blue); 435 | 436 | } 437 | 438 | // function to automatically set the max / min scale based on adding an offset to the average temp from the 8 x 8 array 439 | // you could also try setting max and min based on the actual max min 440 | void SetTempScale() { 441 | 442 | if (DefaultTemp < 0) { 443 | MinTemp = 25; 444 | MaxTemp = 35; 445 | Getabcd(); 446 | DrawLegend(); 447 | } 448 | else { 449 | 450 | val = 0.0; 451 | for (i = 0; i < 64; i++) { 452 | val = val + pixels[i]; 453 | } 454 | val = val / 64.0; 455 | 456 | MaxTemp = val + 2.0; 457 | MinTemp = val - 2.0; 458 | Getabcd(); 459 | DrawLegend(); 460 | } 461 | 462 | } 463 | 464 | // function to get the cutoff points in the temp vs RGB graph 465 | void Getabcd() { 466 | 467 | a = MinTemp + (MaxTemp - MinTemp) * 0.2121; 468 | b = MinTemp + (MaxTemp - MinTemp) * 0.3182; 469 | c = MinTemp + (MaxTemp - MinTemp) * 0.4242; 470 | d = MinTemp + (MaxTemp - MinTemp) * 0.8182; 471 | 472 | } 473 | 474 | // function to handle screen touches 475 | void ProcessTouch() { 476 | 477 | Display.setRotation(3); 478 | Touch.read(); 479 | 480 | x = Touch.getY(); 481 | y = Touch.getX(); 482 | x = map(x, 0, 235, 320, 0); 483 | y = map(y, 379, 0, 240, 0); 484 | 485 | 486 | // yea i know better to have buttons 487 | if (x > 200) { 488 | if (y < 80) { 489 | KeyPad(MaxTemp); 490 | } 491 | else if (y > 160) { 492 | KeyPad(MinTemp); 493 | } 494 | else { 495 | DefaultTemp = DefaultTemp * -1; 496 | SetTempScale(); 497 | } 498 | } 499 | 500 | else if (x <= 200) { 501 | // toggle grid 502 | ShowGrid = ShowGrid * -1; 503 | if (ShowGrid > 0) { 504 | Display.fillRect(15, 15, 210, 210, C_BLACK); 505 | } 506 | } 507 | 508 | Display.setRotation(2); 509 | } 510 | 511 | // function to draw a cute little legend 512 | void DrawLegend() { 513 | 514 | // my cute little color legend with max and min text 515 | j = 0; 516 | 517 | float inc = (MaxTemp - MinTemp ) / 160.0; 518 | 519 | for (ii = MinTemp; ii < MaxTemp; ii += inc) { 520 | Display.drawFastHLine(260, 200 - j++, 30, GetColor(ii)); 521 | } 522 | 523 | Display.setTextSize(2); 524 | Display.setCursor(245, 20); 525 | Display.setTextColor(C_WHITE, C_BLACK); 526 | sprintf(buf, "%2d/%2d", MaxTemp, (int) (MaxTemp * 1.8) + 32); 527 | Display.fillRect(233, 15, 94, 22, C_BLACK); 528 | Display.setFont(Arial_14); 529 | Display.print(buf); 530 | 531 | Display.setTextSize(2); 532 | // Display.setFont(Arial_24_Bold); 533 | Display.setCursor(245, 220); 534 | Display.setTextColor(C_WHITE, C_BLACK); 535 | sprintf(buf, "%2d/%2d", MinTemp, (int) (MinTemp * 1.8) + 32); 536 | Display.fillRect(233, 215, 94, 55, C_BLACK); 537 | Display.setFont(Arial_14); 538 | Display.print(buf); 539 | 540 | 541 | } 542 | 543 | // function to draw a numeric keypad 544 | void KeyPad(uint16_t &TheNumber) { 545 | 546 | int left = KEYPAD_LEFT; 547 | int top = KEYPAD_TOP; 548 | int wide = (3 * BUTTON_W ) + (4 * BUTTON_SPACING_X); 549 | int high = (5 * BUTTON_H) + (6 * BUTTON_SPACING_Y); 550 | int TempNum = TheNumber; 551 | bool KeepIn = true; 552 | 553 | Display.fillRect(left, top, wide , high, C_DKGREY); 554 | Display.drawRect(left, top, wide , high, C_LTGREY); 555 | 556 | Display.fillRect(left + 10, top + 10, wide - 20 , 30, C_WHITE); 557 | Display.drawRect(left + 10, top + 10, wide - 20 , 30, C_DKGREY); 558 | 559 | Display.setCursor(left + 20 , top + 20); 560 | Display.setTextColor(C_BLACK, C_WHITE); 561 | 562 | Display.print(TheNumber); 563 | 564 | for (row = 0; row < 4; row++) { 565 | for (col = 0; col < 3; col++) { 566 | KeyPadBtn[col + row * 3].drawButton(); 567 | } 568 | } 569 | delay(300); // debounce 570 | while (KeepIn) { 571 | // get the touch point 572 | 573 | 574 | 575 | // if nothing or user didn't press hard enough, don't do anything 576 | if (Touch.dataAvailable()) { 577 | Touch.read(); 578 | x = Touch.getY(); 579 | y = Touch.getX(); 580 | x = map(x, 0, 235, 320, 0); 581 | y = map(y, 379, 0, 240, 0); 582 | // go thru all the KeyPadBtn, checking if they were pressed 583 | for (byte b = 0; b < 12; b++) { 584 | if (PressIt(KeyPadBtn[b], x, y) == true) { 585 | 586 | if ((b < 9) | (b == 10)) { 587 | 588 | TempNum *= 10; 589 | if (TempNum == 0) { 590 | Display.fillRect(left + 10, top + 10, wide - 20 , 30, C_WHITE); 591 | } 592 | 593 | if (b != 10) { 594 | TempNum += (b + 1); 595 | } 596 | 597 | if (TempNum > 80) { 598 | Display.fillRect(left + 10, top + 10, wide - 20 , 30, C_WHITE); 599 | //Display.setCursor(left + 100 , top + 20); 600 | //Display.setTextColor(C_RED, C_WHITE); 601 | //Display.print("Max 100"); 602 | TempNum = 0; 603 | TempNum += (b + 1); 604 | } 605 | } 606 | // clr button 607 | if (b == 11) { 608 | Display.fillRect(left + 10, top + 10, wide - 20 , 30, C_WHITE); 609 | Display.drawRect(left + 10, top + 10, wide - 20 , 30, C_DKGREY); 610 | TempNum = 0; 611 | } 612 | if (b == 9) { 613 | KeepIn = false; 614 | } 615 | 616 | Display.setCursor(left + 20 , top + 20); 617 | Display.setTextColor(C_BLACK, C_WHITE); 618 | 619 | Display.print(TempNum); 620 | 621 | } 622 | } 623 | } 624 | } 625 | 626 | // clear screen redraw previous screen 627 | // update the Current Channel 628 | TheNumber = TempNum; 629 | 630 | Display.fillRect(0, 0, 319, 239, C_BLACK); 631 | Display.fillRect(10, 10, 220, 220, C_WHITE); 632 | Display.fillRect(15, 15, 210, 210, C_BLACK); 633 | Getabcd(); 634 | DrawLegend(); 635 | 636 | } 637 | 638 | // function to handle color inversion of a pressed button 639 | bool PressIt(Adafruit_GFX_Button TheButton, int x, int y) { 640 | 641 | 642 | if (TheButton.contains(x, y)) { 643 | TheButton.press(true); // tell the button it is pressed 644 | } else { 645 | TheButton.press(false); // tell the button it is NOT pressed 646 | } 647 | if (TheButton.justReleased()) { 648 | TheButton.drawButton(); // draw normal 649 | } 650 | if (TheButton.justPressed()) { 651 | TheButton.drawButton(true); // draw invert! 652 | delay(200); // UI debouncing 653 | TheButton.drawButton(false); // draw invert! 654 | return true; 655 | } 656 | return false; 657 | } 658 | 659 | 660 | // end of code 661 | --------------------------------------------------------------------------------