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.
Diff: main.cpp
- Revision:
- 0:356e8d3c2cb7
- Child:
- 1:f95f37892056
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Feb 14 11:55:45 2018 +0000 @@ -0,0 +1,374 @@ +/******************************************************************************************* + FLORANION SCI 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 2.00 +#define RGBmask 0xFF +#define dacMask 0xFFF +#define samples 100 +#define samplesOut 1000 +#define baudrate 115000 +#define QVGA true //enter "false" here if no TFT Disülay is connected + +/************************************** 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 +PwmOut pwmAnalogOut(PTA13); // PWM out for Analog Voltage. +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 + //pwmAnalogOut.period_ms(5); // PWM out for Analog Voltage. +} + +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 + r=1-red; + g=1-green; + b=1-blue; + + //PWM Output RGB EXT (Shield Connector J19) + extRed=1-red; + extGreen=1-green; + extBlue=1-blue; + //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(); + 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) + { + 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); + } +} \ No newline at end of file