Discover the secret life of plants! FLORANIUM FDRM-KL25Z Shield An experimental Polygraph for green plants. www.floranion.de
Dependencies: FastPWM SPI_TFT_ILI9341 TFT_fonts
main.cpp
00001 /******************************************************************************************* 00002 FLORANION Scientific SHIELD for FRDM KL25Z REV2.00 00003 Discover the secret life of plants! 00004 (c) Martin Heine - Light Art Vision 2018 00005 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/> 00018 ********************************************************************************************/ 00019 #include <mbed.h> 00020 #include <FastPWM.h> 00021 #include <SDBlockDevice.h> 00022 #include <FATFileSystem.h> 00023 #include "SPI_TFT_ILI9341.h" 00024 #include "Arial12x12.h" 00025 #include "Arial24x23.h" 00026 #include "Arial28x28.h" 00027 #include "font_big.h" 00028 00029 #define firmware 1.00 // Firmware Version 00030 #define RGBmask 0xFF // RGB Color resolution (0xFF = 8 Bit = 256 Colors) 00031 #define dacMask 0xFFF // DAC Voltage resoltion 00032 #define samples 100 // Measuring samples 00033 #define baudrate 115000 // Baudrate for serial monitor over USB 00034 00035 #define datalogger true // SD Card Data Recording (Datalogger) 00036 #define dac true // Outputs the analog Voltage of the RGB Color Wheel via DAC at J18 Pin 1 (To watch plant signal with an Oscilloscope) 00037 #define extRGB true // RGB PWM at J19 Pins 1, 2, 3 00038 #define onBoardRGB true // On Board RGB LED 00039 #define QVGA true // TFT QVGA Display support 00040 00041 /************************************** Inits ***************************************/ 00042 // I/Os 00043 AnalogIn ain(PTB0); // Amplified and filtered Plant-Signal 00044 AnalogIn ain0(PTB1); // Non amplified absolute voltage level / skin resistance level. 00045 00046 //LED Bar for Plants absolute voltage level / skin resistance level. 00047 DigitalOut barDot3(PTC9); 00048 DigitalOut barDot2(PTC8); 00049 DigitalOut barDot1(PTA5); 00050 DigitalOut barDot0(PTA4); 00051 DigitalOut barDot7(PTA12); 00052 DigitalOut barDot6(PTD4); 00053 DigitalOut barDot5(PTC17); 00054 DigitalOut barDot4(PTC16); 00055 DigitalIn Record(PTB8); // SD Card Data Record Switch 00056 //FastPWM pwmAnalogOut(PTA13); // Optional PWM out for Analog Voltage. all RGB PWMs must be disabled! 00057 AnalogOut aout(PTE30); // Analog Out (DAC) 00058 00059 //Using FastPWM for higher speed and resolution. Otherwise, the RGB LED will flicker 00060 00061 //RGB LED on the FRDM KL25Z board 00062 FastPWM r(LED_RED); 00063 FastPWM g(LED_GREEN); 00064 FastPWM b(LED_BLUE); 00065 00066 //External RGB LEDs 00067 FastPWM extRed(PTE20); 00068 FastPWM extGreen(PTE21); 00069 FastPWM extBlue(PTE29); 00070 00071 // SD-Card Pins 00072 SDBlockDevice sd(PTE1, PTE3, PTE2, PTE4); // mosi,miso,sck,cs 00073 FATFileSystem fs("sd"); 00074 00075 // QVGA 2.2 TFT SPI 240x320 Color Display 00076 SPI_TFT_ILI9341 TFT(PTC6, PTC7, PTC5, PTC4, PTC0, PTC3, "TFT"); // mosi, miso, sclk, cs, reset, DC/RS 00077 DigitalOut LCD_LED(PTC12); // the display has a backlight switch on board 00078 00079 Serial pc(USBTX, USBRX); 00080 00081 Thread thread; 00082 00083 /************************************* Global Variables ******************************/ 00084 long int plant, plant0, tmp, dacOut;; 00085 short int plantRGB; 00086 double pwmNormVal; 00087 float colorRange = 255; 00088 float Volt; 00089 int i; float bl; unsigned int upDown = 0; 00090 bool plantConnected, fileOpen, newFile = 1; 00091 bool rec = false; 00092 bool noLogo; 00093 bool SDOK; 00094 //char filename[64]; 00095 int n = 0; 00096 short unsigned y=16, yStart=16, yold = y, plantRGBold, plantBit4, plantBit4old, msg=0; 00097 float dacRange = 4095; 00098 00099 /**************************************** Functions **********************************/ 00100 void barDot(short unsigned level) 00101 { 00102 barDot0 = 0; 00103 barDot1 = 0; 00104 barDot2 = 0; 00105 barDot3 = 0; 00106 barDot4 = 0; 00107 barDot5 = 0; 00108 barDot6 = 0; 00109 barDot7 = 0; 00110 00111 switch (level) 00112 { 00113 case 0: barDot0 = 1; break; 00114 case 1: barDot1 = 1; break; 00115 case 2: barDot2 = 1; break; 00116 case 3: barDot3 = 1; break; 00117 case 4: barDot4 = 1; break; 00118 case 5: barDot5 = 1; break; 00119 case 6: barDot6 = 1; break; 00120 case 7: barDot7 = 1; break; 00121 } 00122 } 00123 00124 void initPWMs() 00125 { 00126 r.period_ms(10); // RGB LED PWM Frequency 00127 g.period_ms(10); 00128 b.period_ms(10); 00129 00130 extRed.period_ms(10); // RGB extern PWM Frequency 00131 extGreen.period_ms(10); 00132 extBlue.period_ms(10); 00133 00134 //pwmAnalogOut.period_us(20); //50kHz PWM out for Analog Voltage. RGB PWMs need to be disabled! 00135 } 00136 00137 void fadeBlue() 00138 { 00139 r=1; 00140 g=1; 00141 if (!upDown) i++; else i--; 00142 bl = (1/colorRange)*i; 00143 b=1-bl; 00144 if (i >=256) upDown = 1; 00145 if ((i == 0) && (upDown == 1)) upDown = 0; 00146 } 00147 00148 void TFTinit() 00149 { 00150 TFT.claim(stdout); // send stdout to the TFT display 00151 TFT.set_orientation(1); 00152 TFT.background(Black); // set background to black 00153 TFT.foreground(White); // set chars to white 00154 TFT.cls(); // clear the screen 00155 LCD_LED = 1; // backlite on 00156 } 00157 00158 void TFTwelcome() 00159 { 00160 TFT.foreground(Cyan); 00161 TFT.set_font((unsigned char*) Arial24x23); 00162 TFT.locate(80,100); 00163 TFT.printf("Welcome to"); 00164 TFT.locate(85,125); 00165 TFT.printf("Floranium"); 00166 wait(2); 00167 TFT.foreground(White); 00168 TFT.set_font((unsigned char*) Arial12x12); 00169 TFT.locate(20,200); 00170 TFT.printf("FLORANIUM Firmware Version %f",firmware); 00171 wait(1); 00172 TFT.cls(); // clear the screen 00173 TFT.rect(15,0,320,225,LightGrey); 00174 TFT.foreground(White); 00175 } 00176 00177 void data2TFT() 00178 { 00179 if (msg == 1) 00180 { 00181 TFT.cls(); 00182 TFT.rect(15,0,320,225,LightGrey); 00183 yold = yStart; 00184 y = yStart; 00185 msg = 0; 00186 } 00187 00188 plantBit4 = (plant & 0xFF00); // Avoid line at rollover from 255 -> 1 and 1 > 255 00189 TFT.line(y+1,1,y+1,224,Cyan); // traveling blue line 00190 TFT.line(y,1,y,224,Black); 00191 if (y == 319) TFT.line(y,1,y,224,DarkGrey); 00192 if (plantBit4 - plantBit4old == 0) TFT.line(yold,plantRGBold/1.13,y,(RGBmask-plantRGB)/1.13,GreenYellow); // x-y to x-y 00193 00194 plantRGBold = RGBmask-plantRGB; //invert so curve on display goes up when plantRGB increases 00195 yold = y; 00196 y++; 00197 plantBit4old = plantBit4; // to avoid line on display when upper or lower border reached. 00198 00199 // Circle Bar on left side for overall voltage level 00200 TFT.fillcircle(6,6,5,DarkGrey); 00201 TFT.fillcircle(6,219,5,DarkGrey); 00202 TFT.fillrect(0,6,12,219,DarkGrey); 00203 TFT.fillcircle(6,219-(plant/310),5,GreenYellow); 00204 00205 // bottom ADC and voltage values 00206 TFT.foreground(White); 00207 // TFT.locate(0,228); 00208 // TFT.printf("ADC %5d", plant); 00209 if (!Record) 00210 { 00211 if (SDOK) 00212 { 00213 TFT.fillcircle(6,230,5,Red); // Red Dot for recording 00214 } 00215 else 00216 { 00217 TFT.fillcircle(6,230,5,Yellow); // Yello Dot SD Card failure (not present) 00218 } 00219 } 00220 else 00221 { 00222 TFT.fillcircle(6,230,5,DarkGrey); 00223 } 00224 TFT.locate(16,228); 00225 TFT.printf("Udisp %6.4fV", Volt); 00226 TFT.locate(130,228); 00227 TFT.printf("RGB %3d", plantRGB); 00228 TFT.locate(225,228); 00229 TFT.printf("Uin %6.4fV", (plant0/65535.0)*3.3); 00230 00231 // when curve reaches end of display, start from the beginning 00232 if (y >= 319) 00233 { 00234 yold = yStart; 00235 y = yStart; 00236 TFT.rect(15,0,320,225,LightGrey); 00237 } 00238 } 00239 00240 void adc2rgb_thread() 00241 { 00242 unsigned short i; 00243 long long sample, sample0; 00244 float color,red,green,blue; 00245 00246 while (1) 00247 { 00248 barDot(plant0/8192); // LED Bargraph 00249 00250 for (i=1; i<=samples; i++) 00251 { 00252 sample += ain.read_u16(); // read filtered and amplified plant signal ADC Value 00253 sample0 += ain0.read_u16(); // read plant DC level ADC Value 00254 wait_us(100); 00255 } 00256 00257 plant=sample/samples; // Averaging 00258 plant0 = sample0/samples; 00259 00260 sample = 0; 00261 sample0= 0; 00262 pwmNormVal = (plant/65535.0); 00263 Volt = pwmNormVal*3.3; 00264 00265 if (Volt <= 3.2) // Only if a green plant is connected! 00266 { 00267 plantConnected = true; 00268 plantRGB = (plant & RGBmask); // mask LSB Bit 0-4 for RGB LED Display 00269 00270 // ********************* RGB LED Color mixing 00271 color = (1/colorRange)*plantRGB; 00272 if(plantRGB >= 0 && plantRGB <= 85 ) { red = 1-(color*3); green = color*3; blue = 0; } 00273 if(plantRGB > 85 && plantRGB <= 170) { red = 0; green = 2-(color*3); blue = (color*3)-1; } 00274 if(plantRGB > 170 && plantRGB <= 255) { red = (color*3)-2; green = 0; blue = (1-color)*3; } 00275 00276 //FRDM-KL25Z RGB LED 00277 if (onBoardRGB) 00278 { 00279 r=1-red; 00280 g=1-green; 00281 b=1-blue; 00282 } 00283 else 00284 { 00285 r=1; 00286 g=1; 00287 b=1; 00288 } 00289 00290 //PWM Output RGB EXT (Shield Connector J19) 00291 if (extRGB) 00292 { 00293 extRed=1-red; 00294 extGreen=1-green; 00295 extBlue=1-blue; 00296 } 00297 00298 if (dac) aout = (1/colorRange)*plantRGB; // DAC Analog Out (J18) 00299 //pwmAnalogOut = pwmNormVal; // PWM out for Analog Voltage (PWM: J15 and DC J12) Please Comment out RGB Color Display above if this PWM or/and Analog Output is used. 00300 } 00301 else 00302 { 00303 fadeBlue(); // fade blue LED slowly up and down if no plant is connected 00304 plantConnected = false; 00305 } 00306 } 00307 } 00308 00309 void data2serial() 00310 { 00311 short unsigned bar,j; 00312 pc.printf("%5d %6.5f %3d ", plant, Volt, plantRGB); 00313 bar = (plant & 0xFF)/8; 00314 for (j=1; j<=bar; j++) pc.printf(" "); 00315 pc.printf("*\n\r"); 00316 } 00317 00318 bool data2SDCard() 00319 { 00320 char filename[64]; 00321 00322 if (newFile) 00323 { 00324 mkdir("/sd/data", 0777); 00325 while(1) 00326 { 00327 sprintf(filename, "/sd/data/flrm%04d.csv", n); // construct the filename fileNNN.csv 00328 FILE *fp = fopen(filename, "r"); // try and open it 00329 if(fp == NULL) 00330 { 00331 break; // if not found, we're done! 00332 } 00333 fclose(fp); // close the file 00334 n++; // and try the next one 00335 } 00336 pc.printf("Data are logged to file: %s...\n\r", filename); 00337 newFile = 0; 00338 } 00339 FILE *fp = fopen(filename, "a"); 00340 if(fp == NULL) 00341 { 00342 pc.printf("Could not open File for write. SD Card present?\n\r"); 00343 return 0; 00344 } 00345 fprintf(fp,"%5d,%6.4f,%3d\n\r", plant, Volt, plantRGB); 00346 fclose(fp); 00347 return 1; 00348 } 00349 00350 /************************************ Main Program **********************************/ 00351 int main() 00352 { 00353 bool SDmounted; 00354 00355 pc.baud(baudrate); 00356 initPWMs(); 00357 pc.printf("Welcome to \033[32mFLORANIUM \033[0m Firmware Vers. %3.2f (c)Light Art Vision 2018\n\n\r", firmware); 00358 if (QVGA) TFTinit(); 00359 if (QVGA) TFTwelcome(); 00360 00361 thread.start(adc2rgb_thread); 00362 while(1) 00363 { 00364 data2serial(); 00365 if (QVGA) data2TFT(); 00366 if ((!Record) && (datalogger)) 00367 { 00368 if (!SDmounted) // Mount SD-Card if not already mounted 00369 { 00370 sd.init(); 00371 fs.mount(&sd); 00372 SDmounted = true; 00373 pc.printf("SD Card mounted\n\r"); 00374 00375 } 00376 SDOK = data2SDCard(); 00377 } 00378 else 00379 { 00380 if (SDmounted) // Unmount SD-Card if not already unmounted 00381 { 00382 fs.unmount(); 00383 sd.deinit(); 00384 SDmounted = false; 00385 pc.printf("SD Card unmounted. You can remove it safely!\n\r"); 00386 newFile = 1; 00387 } 00388 } 00389 if (!QVGA) wait(0.5); 00390 } 00391 }
Generated on Wed Jul 27 2022 15:44:29 by 1.7.2