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
SOME BELIEVE PLANTS CAN FEEL OUR PRESENCE...
The FLORANIUM PROJECT is an innovative plant life indicator, similar to a humans polygraph, that allow you to visualize activities of living plants, caused by movement, touch, changes in climate, environment and many other elements of life. It's a whole new way to interact with green plants!
Please visit http://www.floranium.com or http://www.floranion.de for more information.
main.cpp
- Committer:
- lasmahei
- Date:
- 2018-02-22
- Revision:
- 2:de08bea849b8
- Parent:
- 1:f95f37892056
File content as of revision 2:de08bea849b8:
/******************************************************************************************* FLORANION Scientific SHIELD for FRDM KL25Z REV2.00 Discover the secret life of plants! (c) Martin Heine - Light Art Vision 2018 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/> ********************************************************************************************/ #include <mbed.h> #include <FastPWM.h> #include <SDBlockDevice.h> #include <FATFileSystem.h> #include "SPI_TFT_ILI9341.h" #include "Arial12x12.h" #include "Arial24x23.h" #include "Arial28x28.h" #include "font_big.h" #define firmware 1.00 // Firmware Version #define RGBmask 0xFF // RGB Color resolution (0xFF = 8 Bit = 256 Colors) #define dacMask 0xFFF // DAC Voltage resoltion #define samples 100 // Measuring samples #define baudrate 115000 // Baudrate for serial monitor over USB #define datalogger true // SD Card Data Recording (Datalogger) #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) #define extRGB true // RGB PWM at J19 Pins 1, 2, 3 #define onBoardRGB true // On Board RGB LED #define QVGA true // TFT QVGA Display support /************************************** Inits ***************************************/ // I/Os AnalogIn ain(PTB0); // Amplified and filtered Plant-Signal AnalogIn ain0(PTB1); // Non amplified absolute voltage level / skin resistance level. //LED Bar for Plants absolute voltage level / skin resistance level. DigitalOut barDot3(PTC9); DigitalOut barDot2(PTC8); DigitalOut barDot1(PTA5); DigitalOut barDot0(PTA4); DigitalOut barDot7(PTA12); DigitalOut barDot6(PTD4); DigitalOut barDot5(PTC17); DigitalOut barDot4(PTC16); DigitalIn Record(PTB8); // SD Card Data Record Switch //FastPWM pwmAnalogOut(PTA13); // Optional PWM out for Analog Voltage. all RGB PWMs must be disabled! AnalogOut aout(PTE30); // Analog Out (DAC) //Using FastPWM for higher speed and resolution. Otherwise, the RGB LED will flicker //RGB LED on the FRDM KL25Z board FastPWM r(LED_RED); FastPWM g(LED_GREEN); FastPWM b(LED_BLUE); //External RGB LEDs FastPWM extRed(PTE20); FastPWM extGreen(PTE21); FastPWM extBlue(PTE29); // SD-Card Pins SDBlockDevice sd(PTE1, PTE3, PTE2, PTE4); // mosi,miso,sck,cs FATFileSystem fs("sd"); // QVGA 2.2 TFT SPI 240x320 Color Display SPI_TFT_ILI9341 TFT(PTC6, PTC7, PTC5, PTC4, PTC0, PTC3, "TFT"); // mosi, miso, sclk, cs, reset, DC/RS DigitalOut LCD_LED(PTC12); // the display has a backlight switch on board Serial pc(USBTX, USBRX); Thread thread; /************************************* Global Variables ******************************/ long int plant, plant0, tmp, dacOut;; short int plantRGB; double pwmNormVal; float colorRange = 255; float Volt; int i; float bl; unsigned int upDown = 0; bool plantConnected, fileOpen, newFile = 1; bool rec = false; bool noLogo; bool SDOK; //char filename[64]; int n = 0; short unsigned y=16, yStart=16, yold = y, plantRGBold, plantBit4, plantBit4old, msg=0; float dacRange = 4095; /**************************************** Functions **********************************/ void barDot(short unsigned level) { barDot0 = 0; barDot1 = 0; barDot2 = 0; barDot3 = 0; barDot4 = 0; barDot5 = 0; barDot6 = 0; barDot7 = 0; switch (level) { case 0: barDot0 = 1; break; case 1: barDot1 = 1; break; case 2: barDot2 = 1; break; case 3: barDot3 = 1; break; case 4: barDot4 = 1; break; case 5: barDot5 = 1; break; case 6: barDot6 = 1; break; case 7: barDot7 = 1; break; } } void initPWMs() { r.period_ms(10); // RGB LED PWM Frequency g.period_ms(10); b.period_ms(10); extRed.period_ms(10); // RGB extern PWM Frequency extGreen.period_ms(10); extBlue.period_ms(10); //pwmAnalogOut.period_us(20); //50kHz PWM out for Analog Voltage. RGB PWMs need to be disabled! } void fadeBlue() { r=1; g=1; if (!upDown) i++; else i--; bl = (1/colorRange)*i; b=1-bl; if (i >=256) upDown = 1; if ((i == 0) && (upDown == 1)) upDown = 0; } void TFTinit() { TFT.claim(stdout); // send stdout to the TFT display TFT.set_orientation(1); TFT.background(Black); // set background to black TFT.foreground(White); // set chars to white TFT.cls(); // clear the screen LCD_LED = 1; // backlite on } void TFTwelcome() { TFT.foreground(Cyan); TFT.set_font((unsigned char*) Arial24x23); TFT.locate(80,100); TFT.printf("Welcome to"); TFT.locate(85,125); TFT.printf("Floranium"); wait(2); TFT.foreground(White); TFT.set_font((unsigned char*) Arial12x12); TFT.locate(20,200); TFT.printf("FLORANIUM Firmware Version %f",firmware); wait(1); TFT.cls(); // clear the screen TFT.rect(15,0,320,225,LightGrey); TFT.foreground(White); } void data2TFT() { if (msg == 1) { TFT.cls(); TFT.rect(15,0,320,225,LightGrey); yold = yStart; y = yStart; msg = 0; } plantBit4 = (plant & 0xFF00); // Avoid line at rollover from 255 -> 1 and 1 > 255 TFT.line(y+1,1,y+1,224,Cyan); // traveling blue line TFT.line(y,1,y,224,Black); if (y == 319) TFT.line(y,1,y,224,DarkGrey); if (plantBit4 - plantBit4old == 0) TFT.line(yold,plantRGBold/1.13,y,(RGBmask-plantRGB)/1.13,GreenYellow); // x-y to x-y plantRGBold = RGBmask-plantRGB; //invert so curve on display goes up when plantRGB increases yold = y; y++; plantBit4old = plantBit4; // to avoid line on display when upper or lower border reached. // Circle Bar on left side for overall voltage level TFT.fillcircle(6,6,5,DarkGrey); TFT.fillcircle(6,219,5,DarkGrey); TFT.fillrect(0,6,12,219,DarkGrey); TFT.fillcircle(6,219-(plant/310),5,GreenYellow); // bottom ADC and voltage values TFT.foreground(White); // TFT.locate(0,228); // TFT.printf("ADC %5d", plant); if (!Record) { if (SDOK) { TFT.fillcircle(6,230,5,Red); // Red Dot for recording } else { TFT.fillcircle(6,230,5,Yellow); // Yello Dot SD Card failure (not present) } } else { TFT.fillcircle(6,230,5,DarkGrey); } TFT.locate(16,228); TFT.printf("Udisp %6.4fV", Volt); TFT.locate(130,228); TFT.printf("RGB %3d", plantRGB); TFT.locate(225,228); TFT.printf("Uin %6.4fV", (plant0/65535.0)*3.3); // when curve reaches end of display, start from the beginning if (y >= 319) { yold = yStart; y = yStart; TFT.rect(15,0,320,225,LightGrey); } } void adc2rgb_thread() { unsigned short i; long long sample, sample0; float color,red,green,blue; while (1) { barDot(plant0/8192); // LED Bargraph for (i=1; i<=samples; i++) { sample += ain.read_u16(); // read filtered and amplified plant signal ADC Value sample0 += ain0.read_u16(); // read plant DC level ADC Value wait_us(100); } plant=sample/samples; // Averaging plant0 = sample0/samples; sample = 0; sample0= 0; pwmNormVal = (plant/65535.0); Volt = pwmNormVal*3.3; if (Volt <= 3.2) // Only if a green plant is connected! { plantConnected = true; plantRGB = (plant & RGBmask); // mask LSB Bit 0-4 for RGB LED Display // ********************* RGB LED Color mixing color = (1/colorRange)*plantRGB; if(plantRGB >= 0 && plantRGB <= 85 ) { red = 1-(color*3); green = color*3; blue = 0; } if(plantRGB > 85 && plantRGB <= 170) { red = 0; green = 2-(color*3); blue = (color*3)-1; } if(plantRGB > 170 && plantRGB <= 255) { red = (color*3)-2; green = 0; blue = (1-color)*3; } //FRDM-KL25Z RGB LED if (onBoardRGB) { r=1-red; g=1-green; b=1-blue; } else { r=1; g=1; b=1; } //PWM Output RGB EXT (Shield Connector J19) if (extRGB) { extRed=1-red; extGreen=1-green; extBlue=1-blue; } if (dac) aout = (1/colorRange)*plantRGB; // DAC Analog Out (J18) //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. } else { fadeBlue(); // fade blue LED slowly up and down if no plant is connected plantConnected = false; } } } void data2serial() { short unsigned bar,j; pc.printf("%5d %6.5f %3d ", plant, Volt, plantRGB); bar = (plant & 0xFF)/8; for (j=1; j<=bar; j++) pc.printf(" "); pc.printf("*\n\r"); } bool data2SDCard() { char filename[64]; if (newFile) { mkdir("/sd/data", 0777); while(1) { sprintf(filename, "/sd/data/flrm%04d.csv", n); // construct the filename fileNNN.csv FILE *fp = fopen(filename, "r"); // try and open it if(fp == NULL) { break; // if not found, we're done! } fclose(fp); // close the file n++; // and try the next one } pc.printf("Data are logged to file: %s...\n\r", filename); newFile = 0; } FILE *fp = fopen(filename, "a"); if(fp == NULL) { pc.printf("Could not open File for write. SD Card present?\n\r"); return 0; } fprintf(fp,"%5d,%6.4f,%3d\n\r", plant, Volt, plantRGB); fclose(fp); return 1; } /************************************ Main Program **********************************/ int main() { bool SDmounted; pc.baud(baudrate); initPWMs(); pc.printf("Welcome to \033[32mFLORANIUM \033[0m Firmware Vers. %3.2f (c)Light Art Vision 2018\n\n\r", firmware); if (QVGA) TFTinit(); if (QVGA) TFTwelcome(); thread.start(adc2rgb_thread); while(1) { data2serial(); if (QVGA) data2TFT(); if ((!Record) && (datalogger)) { if (!SDmounted) // Mount SD-Card if not already mounted { sd.init(); fs.mount(&sd); SDmounted = true; pc.printf("SD Card mounted\n\r"); } SDOK = data2SDCard(); } else { if (SDmounted) // Unmount SD-Card if not already unmounted { fs.unmount(); sd.deinit(); SDmounted = false; pc.printf("SD Card unmounted. You can remove it safely!\n\r"); newFile = 1; } } if (!QVGA) wait(0.5); } }