SHOW:
|
|
- or go back to the newest paste.
| 1 | /* | |
| 2 | Visualizing the MLX90640 Sensor Data using Processing | |
| 3 | By: Nick Poole | |
| 4 | SparkFun Electronics | |
| 5 | Date: June 5th, 2018 | |
| 6 | ||
| 7 | MIT License: Permission is hereby granted, free of charge, to any person obtaining a copy of this | |
| 8 | software and associated documentation files (the "Software"), to deal in the Software without | |
| 9 | restriction, including without limitation the rights to use, copy, modify, merge, publish, | |
| 10 | distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the | |
| 11 | Software is furnished to do so, subject to the following conditions: | |
| 12 | ||
| 13 | The above copyright notice and this permission notice shall be included in all copies or | |
| 14 | substantial portions of the Software. | |
| 15 | ||
| 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
| 17 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | |
| 19 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | ||
| 22 | Feel like supporting our work? Buy a board from SparkFun! | |
| 23 | https://www.sparkfun.com/products/14568 | |
| 24 | ||
| 25 | This example is intended as a companion sketch to the Arduino sketch found in the same folder. | |
| 26 | Once the accompanying code is running on your hardware, run this Processing sketch. | |
| 27 | This Processing sketch will receive the comma separated values generated by the Arduino code and | |
| 28 | use them to generate a thermal image. | |
| 29 | ||
| 30 | IF this example code generates ArrayOutOfBounds exceptions, double check that you are running | |
| 31 | the correct Teensy example code and try again. | |
| 32 | ||
| 33 | Hardware Connections: | |
| 34 | Attach the Sensor to your Teensy 3.2 or later using | |
| 35 | a Qwiic breadboard cable | |
| 36 | */ | |
| 37 | ||
| 38 | import processing.serial.*; | |
| 39 | ||
| 40 | String myString = null; | |
| 41 | Serial myPort; // The serial port | |
| 42 | ||
| 43 | float[] temps = new float[768]; | |
| 44 | String splitString[] = new String[1000]; | |
| 45 | float maxTemp = 0; | |
| 46 | float minTemp = 500; | |
| 47 | ||
| 48 | // The statements in the setup() function | |
| 49 | // execute once when the program begins | |
| 50 | void setup() {
| |
| 51 | size(480, 400); // Size must be the first statement | |
| 52 | noStroke(); | |
| 53 | frameRate(30); | |
| 54 | ||
| 55 | // Print a list of connected serial devices in the console | |
| 56 | printArray(Serial.list()); | |
| 57 | // Depending on where your sensor falls on this list, you | |
| 58 | // may need to change Serial.list()[0] to a different number | |
| 59 | myPort = new Serial(this, "/dev/ttyUSB1", 115200); | |
| 60 | myPort.clear(); | |
| 61 | // Throw out the first chunk in case we caught it in the | |
| 62 | // middle of a frame | |
| 63 | myString = myPort.readStringUntil(13); | |
| 64 | myString = null; | |
| 65 | // change to HSB color mode, this will make it easier to color | |
| 66 | // code the temperature data | |
| 67 | colorMode(HSB, 360, 100, 100); | |
| 68 | } | |
| 69 | ||
| 70 | // The statements in draw() are executed until the | |
| 71 | // program is stopped. Each statement is executed in | |
| 72 | // sequence and after the last line is read, the first | |
| 73 | // line is executed again. | |
| 74 | void draw() {
| |
| 75 | ||
| 76 | // When there is a sizeable amount of data on the serial port | |
| 77 | // read everything up to the first linefeed | |
| 78 | if(myPort.available() > 5000){
| |
| 79 | myString = myPort.readStringUntil(13); | |
| 80 | ||
| 81 | // Limit the size of this array so that it doesn't throw | |
| 82 | // OutOfBounds later when calling "splitTokens" | |
| 83 | if(myString.length() > 4608){
| |
| 84 | myString = myString.substring(0, 4608);} | |
| 85 | ||
| 86 | // generate an array of strings that contains each of the comma | |
| 87 | // separated values | |
| 88 | splitString = splitTokens(myString, ","); | |
| 89 | ||
| 90 | // Reset our min and max temperatures per frame | |
| 91 | maxTemp = 0; | |
| 92 | minTemp = 500; | |
| 93 | ||
| 94 | // For each floating point value, double check that we've acquired a number, | |
| 95 | // then determine the min and max temperature values for this frame | |
| 96 | for(int q = 0; q < 768; q++){
| |
| 97 | ||
| 98 | if(!Float.isNaN(float(splitString[q])) && float(splitString[q]) > maxTemp){
| |
| 99 | maxTemp = float(splitString[q]); | |
| 100 | }else if (!Float.isNaN(float(splitString[q])) && float(splitString[q]) < minTemp){
| |
| 101 | minTemp = float(splitString[q]); | |
| 102 | } | |
| 103 | ||
| 104 | } | |
| 105 | ||
| 106 | // for each of the 768 values, map the temperatures between min and max | |
| 107 | // to the blue through red portion of the color space | |
| 108 | for(int q = 0; q < 768; q++){
| |
| 109 | ||
| 110 | if(!Float.isNaN(float(splitString[q]))){
| |
| 111 | temps[q] = constrain(map(float(splitString[q]), minTemp, maxTemp, 180, 360),160,360);} | |
| 112 | else{
| |
| 113 | temps[q] = 0; | |
| 114 | } | |
| 115 | ||
| 116 | } | |
| 117 | } | |
| 118 | ||
| 119 | ||
| 120 | // Prepare variables needed to draw our heatmap | |
| 121 | int x = 0; | |
| 122 | int y = 0; | |
| 123 | int i = 0; | |
| 124 | background(0); // Clear the screen with a black background | |
| 125 | ||
| 126 | ||
| 127 | ||
| 128 | while(y < 360){
| |
| 129 | ||
| 130 | ||
| 131 | // for each increment in the y direction, draw 8 boxes in the | |
| 132 | // x direction, creating a 64 pixel matrix | |
| 133 | while(x < 480){
| |
| 134 | // before drawing each pixel, set our paintcan color to the | |
| 135 | // appropriate mapped color value | |
| 136 | fill(temps[i], 100, 100); | |
| 137 | rect(x,y,15,15); | |
| 138 | x = x + 15; | |
| 139 | i++; | |
| 140 | } | |
| 141 | ||
| 142 | y = y + 15; | |
| 143 | x = 0; | |
| 144 | } | |
| 145 | ||
| 146 | // Add a gaussian blur to the canvas in order to create a rough | |
| 147 | // visual interpolation between pixels. | |
| 148 | filter(BLUR,7); | |
| 149 | ||
| 150 | ||
| 151 | // Generate the legend on the bottom of the screen | |
| 152 | textSize(32); | |
| 153 | ||
| 154 | // Find the difference between the max and min temperatures in this frame | |
| 155 | float tempDif = maxTemp - minTemp; | |
| 156 | // Find 5 intervals between the max and min | |
| 157 | int legendInterval = round(tempDif / 5); | |
| 158 | // Set the first legend key to the min temp | |
| 159 | int legendTemp = round(minTemp); | |
| 160 | ||
| 161 | // Print each interval temperature in its corresponding heatmap color | |
| 162 | for(int intervals = 0; intervals < 6; intervals++){
| |
| 163 | fill(constrain(map(legendTemp, minTemp, maxTemp, 180, 360),160,360), 100, 100); | |
| 164 | text(legendTemp+"°", 70*intervals, 390); | |
| 165 | legendTemp += legendInterval; | |
| 166 | } | |
| 167 | ||
| 168 | } |