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 | } |