Keith G / Mbed 2 deprecated IOTM-Crossing

Dependencies:   EthernetInterface MQTT mbed-dsp mbed-rtos mbed

Fork of KL25Z_FFT_Demo_tony by Leicester Hackspace

Revision:
3:54760764be66
Parent:
2:aa24865dfef5
Child:
5:4152530c0cf5
diff -r aa24865dfef5 -r 54760764be66 main.cpp
--- a/main.cpp	Fri Jul 11 17:03:53 2014 +0000
+++ b/main.cpp	Fri Jan 08 15:49:02 2016 +0000
@@ -4,363 +4,108 @@
 // mods by Tony Abbey to simplify code to drive tri-colour LED as a "colour organ"
 
 #include "mbed.h"
-#include "NVIC_set_all_priorities.h"
-#include <ctype.h>
-#include "arm_math.h"
-#include "arm_const_structs.h"
-#include "FastAnalogIn.h"
 
-Serial pc(USBTX, USBRX);
-
-FastAnalogIn   Audio(PTC2);
-
-// #define RGBW_ext // Disable this line when you want to use the KL25Z on-board RGB LED.
-
-
-#ifndef RGBW_ext
-// RGB  direct output to PWM channels - on-board RGB LED
-    PwmOut gled(LED_GREEN);
-    PwmOut rled(LED_RED);
-    PwmOut bled(LED_BLUE);
-#else
-    PwmOut gled(D6);
-    PwmOut rled(D5);
-    PwmOut bled(D7);
-    
-#endif
+#include "EthernetInterface.h"
+#include "MQTTEthernet.h"
+#include "MQTTClient.h"
 
-// Dummy ISR for disabling NMI on PTA4 - !! DO NOT REMOVE THIS !!
-// More info at https://mbed.org/questions/1387/How-can-I-access-the-FTFA_FOPT-register-/
-extern "C" void NMI_Handler() {
-    DigitalIn test(PTA4);
-}
-
+#define IP_RETRIES 2
+#define HOSTNAME "192.168.0.1"
+//#define HOSTNAME "doughnut.kent.ac.uk"
+#define PORT 1883
 
-////////////////////////////////////////////////////////////////////////////////
-// CONFIGURATION
-// These values can be changed to alter the behavior of the spectrum display.
-// KL25Z limitations
-// -----------------
-// - When used with the Spectrogram python script :
-//   There is a substantial time lag between the music and the screen output.
-//   Max allowed SAMPLE_RATE_HZ is 40000
-//   Max allowed FFT_SIZE is 64
-////////////////////////////////////////////////////////////////////////////////
+enum Mode {RESPONCIVE, OVERRIDE};
 
-int SAMPLE_RATE_HZ = 8000;             // Sample rate of the audio in hertz - note was 20000
-float SPECTRUM_MIN_DB = 33.0;           // Audio intensity (in decibels) that maps to low LED brightness.
-float SPECTRUM_MAX_DB = 60.0;           // Audio intensity (in decibels) that maps to high LED brightness.
-int LEDS_ENABLED = 1;                   // Control if the LED's should display the spectrum or not.  1 is true, 0 is false.
-                                        // Useful for turning the LED display on and off with commands from the serial port.
-const int FFT_SIZE = 64;                // Size of the FFT.
-const int PIXEL_COUNT = 3;             // Number of pixels (RGB LED).  You should be able to increase this without
-                                        // any other changes to the program.
-const int MAX_CHARS = 65;               // Max size of the input command buffer
-int PRINT_ON = 0;                       // flag to send chars continually to serial output
+//buffers
+char mqtt_buffer[100];
+MQTT::Message message;
 
-////////////////////////////////////////////////////////////////////////////////
-// INTERNAL STATE
-// These shouldn't be modified unless you know what you're doing.
-////////////////////////////////////////////////////////////////////////////////
-const static arm_cfft_instance_f32 *S;
-Ticker samplingTimer;
-float samples[FFT_SIZE*2];
-float magnitudes[FFT_SIZE];
-int sampleCounter = 0;
-char commandBuffer[MAX_CHARS];
-float frequencyWindow[PIXEL_COUNT+1];
-float hues[PIXEL_COUNT];
-float oldhues[PIXEL_COUNT];
-float huescount = 1;
-bool commandRecv = 0;
-////////////////////////////////////////////////////////////////////////////////
-// UTILITY FUNCTIONS
-////////////////////////////////////////////////////////////////////////////////
-
-void rxisr() {
-    char c = pc.getc();
-    // Add any characters that aren't the end of a command (semicolon) to the input buffer.
-    if (c != ';') {
-        c = toupper(c);
-        strncat(commandBuffer, &c, 1);
-    } else {
-        // Parse the command because an end of command token was encountered.
-        commandRecv = 1;
-    }
-}
+//topics
+char personTopic[] = "shed/masterclass/iot/crossing/person";
+char modeTopic[] = "shed/masterclass/iot/crossing/mode";
 
-// Compute the average magnitude of a target frequency window vs. all other frequencies.
-void windowMean(float* magnitudes, int lowBin, int highBin, float* windowMean, float* otherMean)
-{
-    *windowMean = 0;
-    *otherMean = 0;
-    // Notice the first magnitude bin is skipped because it represents the
-    // average power of the signal.
-    for (int i = 1; i < FFT_SIZE/2; ++i) {
-        if (i >= lowBin && i <= highBin) {
-            *windowMean += magnitudes[i];
-        } else {
-            *otherMean += magnitudes[i];
-        }
-    }
-    *windowMean /= (highBin - lowBin) + 1;
-    *otherMean /= (FFT_SIZE / 2 - (highBin - lowBin));
-}
+//io
+AnalogIn sensor(A0);
+DigitalOut GND(A2);
+DigitalOut pelican(D0);
+Ticker presenceTimer;
 
-// Convert a frequency to the appropriate FFT bin it will fall within.
-int frequencyToBin(float frequency)
-{
-    float binFrequency = float(SAMPLE_RATE_HZ) / float(FFT_SIZE);
-    return int(frequency / binFrequency);
-}
-
+//state
+bool personPresent = false;
+volatile Mode mode = RESPONCIVE;
+volatile bool checkPresence = false;
 
-////////////////////////////////////////////////////////////////////////////////
-// SPECTRUM DISPLAY FUNCTIONS
-///////////////////////////////////////////////////////////////////////////////
-
-void spectrumSetup()
-{
-    // Set the frequency window values by evenly dividing the possible frequency
-    // spectrum across the number of neo pixels.
-    float windowSize = (SAMPLE_RATE_HZ / 2.0) / float(PIXEL_COUNT);
-    for (int i = 0; i < PIXEL_COUNT+1; ++i) {
-        frequencyWindow[i] = i*windowSize;
-    }
- 
+void presenceTick() {
+    checkPresence = true;
 }
 
-void spectrumLoop()
-{
-    // Update each LED based on the intensity of the audio
-    // in the associated frequency window.
-    static int SLpixcnt = 0;
-    float intensity, otherMean;  
-    int SLpixend = PIXEL_COUNT;
-    for (int i = SLpixcnt; i < SLpixend; ++i) {
-        windowMean(magnitudes,
-                   frequencyToBin(frequencyWindow[i]),
-                   frequencyToBin(frequencyWindow[i+1]),
-                   &intensity,
-                   &otherMean);
-        // Convert intensity to decibels.
-        intensity = 20.0*log10(intensity);
-        // Scale the intensity and clamp between 0 and 1.0.
-        intensity -= SPECTRUM_MIN_DB;
-        intensity = intensity < 0.0 ? 0.0 : intensity;
-        intensity /= (SPECTRUM_MAX_DB-SPECTRUM_MIN_DB);
-        //intensity = intensity > 1.0 ? 1.0 : intensity;
-        hues[i]=(intensity+oldhues[i]) / huescount; // averaging function
-        oldhues[i]=hues[i];
-        huescount += 1;
-        if (huescount > 9) huescount = 1;
-    }
-    rled=1.0-hues[0] ;  // onboard LED is common anode so inversion needed
-    gled=1.0-hues[1];
-    bled=1.0-hues[2];
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// SAMPLING FUNCTIONS
-////////////////////////////////////////////////////////////////////////////////
-
-void samplingCallback()
-{
-    // Read from the ADC and store the sample data
-    samples[sampleCounter] = (1024 * Audio) - 511.0f;
-    // samples[sampleCounter] =  Audio ; // just to see what this call actually produces
-    // Complex FFT functions require a coefficient for the imaginary part of the input.
-    // Since we only have real data, set this coefficient to zero.
-    samples[sampleCounter+1] = 0.0;
-    // Update sample buffer position and stop after the buffer is filled
-    sampleCounter += 2;
-    if (sampleCounter >= FFT_SIZE*2) {
-        samplingTimer.detach();
-    }
-}
-
-void samplingBegin()
-{
-    // Reset sample buffer position and start callback at necessary rate.
-    sampleCounter = 0;
-    samplingTimer.attach_us(&samplingCallback, 1000000/SAMPLE_RATE_HZ);
-}
-
-bool samplingIsDone()
-{
-    return sampleCounter >= FFT_SIZE*2;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// COMMAND PARSING FUNCTIONS
-// These functions allow parsing simple commands input on the serial port.
-// Commands allow reading and writing variables that control the device.
-//
-// All commands must end with a semicolon character.
-//
-// Example commands are:
-// GET SAMPLE_RATE_HZ;
-// - Get the sample rate of the device.
-// SET SAMPLE_RATE_HZ 400;
-// - Set the sample rate of the device to 400 hertz.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-void parseCommand(char* command)
-{ 
-    if (strcmp(command, "GET MAGNITUDES") == 0) {
-        for (int i = 1; i < FFT_SIZE; ++i) {
-            printf("%4.2f,", magnitudes[i]);
-        }
-    } else if (strcmp(command, "GET SAMPLES") == 0) {
-        for (int i = 0; i < FFT_SIZE*2; i+=2) {
-            printf("%f,", samples[i]);
-        }
-    } else if (strcmp(command, "GET FFT_SIZE") == 0) {
-        printf("%d\r\n", FFT_SIZE);
-    } else if (strcmp(command, "GET SAMPLE_RATE_HZ") == 0) {
-        printf("%d\r\n", SAMPLE_RATE_HZ);
-    } else if (strstr(command, "SET SAMPLE_RATE_HZ") != NULL) {
-        SAMPLE_RATE_HZ = (typeof(SAMPLE_RATE_HZ)) atof(command+(sizeof("SET SAMPLE_RATE_HZ")-1));
-    } else if (strcmp(command, "GET LEDS_ENABLED") == 0) {
-        printf("%d\r\n", LEDS_ENABLED);
-    } else if (strstr(command, "SET LEDS_ENABLED") != NULL) {
-        LEDS_ENABLED = (typeof(LEDS_ENABLED)) atof(command+(sizeof("SET LEDS_ENABLED")-1));
-    } else if (strcmp(command, "GET SPECTRUM_MIN_DB") == 0) {
-        printf("%f\r\n", SPECTRUM_MIN_DB);
-    } else if (strstr(command, "SET SPECTRUM_MIN_DB") != NULL) {
-        SPECTRUM_MIN_DB = (typeof(SPECTRUM_MIN_DB)) atof(command+(sizeof("SET SPECTRUM_MIN_DB")-1));
-    } else if (strcmp(command, "GET SPECTRUM_MAX_DB") == 0) {
-        printf("%f\r\n", SPECTRUM_MAX_DB);
-    } else if (strstr(command, "SET SPECTRUM_MAX_DB") != NULL) {
-        SPECTRUM_MAX_DB = (typeof(SPECTRUM_MAX_DB)) atof(command+(sizeof("SET SPECTRUM_MAX_DB")-1));
-    } else if (strcmp(command, "GET HUES") == 0) {
-        for (int i = 0; i < PIXEL_COUNT; ++i) {
-            printf("%f\r\n", hues[i]); 
-            }
-    } else if (strcmp(command, "GET FREQUENCIES") == 0) {
-        for (int i = 0; i < PIXEL_COUNT; ++i) {
-            printf("%f\r\n", frequencyWindow[i]); 
-            }
-    } else if (strcmp(command, "PRINT_ON") == 0) {
-        PRINT_ON = 1; 
-    } else if (strcmp(command, "PRINT_OFF") == 0) {
-        PRINT_ON = 0; 
-        }
-    // Update spectrum display values if sample rate was changed.
-    if (strstr(command, "SET SAMPLE_RATE_HZ ") != NULL) {
-        spectrumSetup();
-    }
-    
-
-    // Turn off the LEDs if the state changed.
-    if (LEDS_ENABLED == 0) {
-    }
-}
-
-void parserLoop()
-{
-    // Process any incoming characters from the serial port
-    while (pc.readable()) {
-        char c = pc.getc();
-        // (doesnt work!) printf("%c",c); // echo characters typed
-        // Add any characters that aren't the end of a command (semicolon) to the input buffer.
-        if (c != ';') {
-            c = toupper(c);
-            strncat(commandBuffer, &c, 1);
-        } else {
-            // Parse the command because an end of command token was encountered.
-            parseCommand(commandBuffer);
-            // Clear the input buffer
-            memset(commandBuffer, 0, sizeof(commandBuffer));
+void messageArrived(MQTT::MessageData& md) {
+    MQTT::Message &msg = md.message;
+    if(msg.payloadlen>0) {
+        switch(*(char*)msg.payload) {
+            case 'r': case 'R': mode = RESPONCIVE; pelican=personPresent; break;
+            case 'o': case 'O': mode = OVERRIDE; pelican=true; break;
         }
     }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// MAIN FUNCTION
-////////////////////////////////////////////////////////////////////////////////
-
-int main()
-{
-    NVIC_set_all_irq_priorities(1);
-    NVIC_SetPriority(UART0_IRQn, 0);
-    // Set up serial port.
-    pc.baud (38400);
-    pc.attach(&rxisr);
-
-    // Clear the input command buffer
-    memset(commandBuffer, 0, sizeof(commandBuffer));
-
-    // Initialize spectrum display
-    spectrumSetup();
-
-    // Begin sampling audio
-    samplingBegin();
+int main() {
 
-    // Init arm_ccft_32
-    switch (FFT_SIZE)
-    {
-    case 16:
-        S = & arm_cfft_sR_f32_len16;
-        break;
-    case 32:
-        S = & arm_cfft_sR_f32_len32;
-        break;
-    case 64:
-        S = & arm_cfft_sR_f32_len64;
-        break;
-    case 128:
-        S = & arm_cfft_sR_f32_len128;
-        break;
-    case 256:
-        S = & arm_cfft_sR_f32_len256;
-        break;
-    case 512:
-        S = & arm_cfft_sR_f32_len512;
-        break;
-    case 1024:
-        S = & arm_cfft_sR_f32_len1024;
-        break;
-    case 2048:
-        S = & arm_cfft_sR_f32_len2048;
-        break;
-    case 4096:
-        S = & arm_cfft_sR_f32_len4096;
-        break;
+    MQTTEthernet ipstack;
+    MQTT::Client<MQTTEthernet, Countdown> m_client(ipstack);
+    
+    int ip_result;
+    for(int i=0; i<IP_RETRIES; i++) {
+        int ip_result = ipstack.connect(HOSTNAME, PORT);
+        if(ip_result==0) break;
+    }
+    if (ip_result != 0) {
+        error("IP stack failed");
+    }
+    if(m_client.connect()!=MQTT::SUCCESS) {
+        error("MQTT connection failed");
+    }
+    if(m_client.subscribe(modeTopic, MQTT::QOS0, messageArrived)!=MQTT::SUCCESS) {
+        error("MQTT subscribe failed");
     }
-
+    
+    GND = 0; //provide sensor with ground
+    
+    presenceTimer.attach_us(&presenceTick,50000);
+    
     while(1) {
-        // Calculate FFT if a full sample is available.
-        if (samplingIsDone()) {
-            // Run FFT on sample data.
-            arm_cfft_f32(S, samples, 0, 1);
-            // Calculate magnitude of complex numbers output by the FFT.
-            arm_cmplx_mag_f32(samples, magnitudes, FFT_SIZE);
-
-            if (LEDS_ENABLED == 1) {
-                spectrumLoop();
-            }
-            wait_ms(10);
-            // Restart audio sampling.
-            samplingBegin();
-            if (PRINT_ON == 1) {
-                for (int i = 0; i < PIXEL_COUNT; ++i) {
-                printf("%f\r\n", hues[i]); 
+        
+        sleep();
+        
+        if(checkPresence) {
+            float s = sensor;
+            if((s<0.5f)!=personPresent) { //state changed
+                if(personPresent) {
+                    //last person left
+                    personPresent = false;
+                } else {
+                    //person arrived
+                    personPresent = true;
+                }
+                
+                sprintf(mqtt_buffer, "{\"personPresent\":%d}", personPresent);
+                message.qos = MQTT::QOS0;   // Send at least once
+                // Do not null terminate -- we have a length field, and it will piss off the JS front end
+                message.payloadlen = strlen(mqtt_buffer);
+                message.payload = (void*)mqtt_buffer;
+                m_client.publish(personTopic, message);
+                
+                if(mode==RESPONCIVE) {
+                    pelican = personPresent;
                 }
             }
-            }
-
-        // Parse any pending commands.
-        if(commandRecv) {
-//            pc.attach(NULL);
-            parseCommand(commandBuffer);
-            commandRecv = 0;
-            // Clear the input buffer
-            memset(commandBuffer, 0, sizeof(commandBuffer));
-//            pc.attach(&rxisr);
+            checkPresence = false;
         }
+        
+        m_client.yield(100);
     }
-}
+    
+    
+    /*    
+    */
+}
\ No newline at end of file