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.

/media/uploads/lasmahei/screenshot_2018-02-14_13-35-22.png/media/uploads/lasmahei/floranium.png

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