123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817 |
- /*
- * AML TMP+NOISE
- *
- * VERSION: 1.03
- *
- * The Sensorbox measures Temperature and Noise-Level and sends this information with the GPS-position to a webservice.
- *
- * ************************************************
- * GENERAL INFO AND COMPONENTS
- *
- * Measuring Battery: https://learn.adafruit.com/adafruit-feather-32u4-fona/power-management
- * Gettin Noise: http://arduinolearning.com/code/arduino-and-max4466-electret-module-example.php
- * Getting GSM Location: https://www.instructables.com/id/How-to-make-a-Mobile-Cellular-Location-Logger-with/
- *
- * Tiny GPS++ Library: http://arduiniana.org/libraries/tinygpsplus/
- *
- *
- * Battery saving:
- *
- * GPS Board: - Use EN Pin to turn of the board when not needed (https://learn.adafruit.com/adafruit-ultimate-gps/overview)
- * - EN soll laut der Quelle auf GND gesetzt werden. Es dauert dann aber länger bis wieder ein Fix gefunden wurde.
- *
- *
- * Feather FONA: - Cut the key trac on the bottom of the board (https://learn.adafruit.com/adafruit-feather-32u4-fona/power-management)
- * - If you want to depower the cell module, cut the KEY trace on the bottom of the board, wire KEY to an unused pad,
- * and toggle the pin low for 100ms to completely turn on/off the module.
- * - https://arduino.stackexchange.com/questions/54001/adafruit-feather-32u4-fona-key-pin
- * cut the trace and wire it to a micro controller pin
- * - Key - this is by default tied to ground, cut the trace on the bottom and wire to a microcontroller pin to manually turn the module on and off.
- * (Pulse low for a few seconds to change from on to off) This is the only way to truly disable the cellular module.
- *
- *************************************************
- * TODOS & BUGS:
- * - Die Ladeanzeige über die LED funktioniert nicht immer korrekt. Besonders gelbes Blinken (Aufladen) ist davon betroffen.
- *
- ************************************************
- *
- * IMPORTANT INFO:
- * - Be sure to use the correct Token and device number before uplading the code
- * - For A1 Sim-Cards the APN needs to be set in initFONA(). Uncomment the line if other SIM-Card is used or set the correct APN
- *
- * SOURCE TOKENS:
- * BOX 1: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjcsImlhdCI6MTYwMDg0NjI2MH0.YKzbg-8_hFuw1-W0Hqa5eLZAncfqlqT2rf2c95Abi7k
- * BOX 2: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjE1LCJpYXQiOjE2MDA4NDY3MTl9.Jk1CXJXeB6cm4T0QARoj_1BtxvsZF3jl5UhvPRMEBvQ
- * BOX 3: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEwLCJpYXQiOjE2MDA4NDYyMDZ9.rrA8lZ18SThb4L8mf18Krz7dK5ioCwqWd10BstT9GnE
- * BOX 4: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjE0LCJpYXQiOjE2MDA4NDY0MDR9.0BPUK7NVTlqi7i9QFx9kcVY55jsn0qskPWDL1PKyKec
- * BOX 5: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlhdCI6MTYwMDg0NjY2NH0.d5xvkTVDcHJl-K6KkohIWcUC5XcYNRZ_wzSLMvqAyvw
- * BOX 6: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlhdCI6MTYwMDg0NTg4M30.OjsoqjcAMhCh9WLkBpBtXyOlOL25mBXSxT1Uy3tM01M
- * BOX 7: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjUsImlhdCI6MTYwMDg0NjUwMH0.XqBhCwt9V6YTNE8fwfxrXahBxGGNHgLkXgO3XaqDcwI
- * BOX 8: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjExLCJpYXQiOjE2MDA4NDYxMjd9.uJPST-APKEpsS-CIimNh3ePNce2PaabuX5c3HNnVsfo
- * BOX 9: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjE2LCJpYXQiOjE2MTA3MTg5MjF9.2lk9xY4Gy0CR65V9giXPHrDR7Eei-O3R5sS1oD6hzsM
- *
- *
- ************************************************
- *
- */
- #include <Adafruit_NeoPixel.h>
- #include "Adafruit_FONA.h"
- #include <SoftwareSerial.h>
- #include <TinyGPS++.h>
- #include <AES.h>
- #define LEDPIN 13
- #define ANALOG_TEMP_PIN A0
- #define ANALOG_NOISE_PIN A1
- #define KEYPIN 12
- #define GPSENABLE 11
-
- #define FONA_RX 9
- #define FONA_TX 8
- #define FONA_RST 4
- #define FONA_RI 7
- #define aref_voltage 3.3
- Adafruit_NeoPixel pixel(1, LEDPIN, NEO_GRB + NEO_KHZ800);
- //Name of this Box
- String boxID = "BOX 009";
-
- //GSM
- SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
- SoftwareSerial *fonaSerial = &fonaSS;
- Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
- uint8_t type;
- //char URL[] = "http://airquality.media.tuwien.ac.at:10005/measurements";
- char URL[] = "http://aml.media.tuwien.ac.at:11312/api/sensordata/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjE2LCJpYXQiOjE2MTA3MTg5MjF9.2lk9xY4Gy0CR65V9giXPHrDR7Eei-O3R5sS1oD6hzsM";
- char URL2[] = "http://www.mobillab.wien/sensorbox/write/";
- //char URL[] = "www.kunstmedienkultur.com/sensorbox/";
- unsigned long ATtimeOut = 10000; // How long we will give an AT command to complete
- boolean initFONAagain = false;
- //GPS
- static const uint32_t GPSBaud = 9600;
- TinyGPSPlus gps;
- boolean encodeGPSAgain = false;
-
- //Timing
- unsigned long currentMillis =0;
- unsigned long singleBlinkDuration = 500; //Duration for 1 Blink
- unsigned long lastSingleBlinkStart = 0;
- unsigned long blinkSequenceDuration = 4200; //Duration for an blink sequence (not sure if needed)
- unsigned long lastBlinkSequenceStart = 0;
- unsigned long blinkPauseDuration = 200; //Duration for blink pause
- unsigned long lastBlinkPauseStart = 0;
- unsigned long blinkInterval = 10000; //Interval to blink
- unsigned long checkBatInterval = 15000; //Interval for Checking the Battery -> long interval: every 10 Minutes (if everthing is ok) 600000; short interval: every 15 seconds (150000)
- unsigned long lastBatCheck = 0;
- unsigned long sendToWebInterval = 1200000; //20 min = 1200000; 5min = 300000; //Interval for sending data to webservice
- unsigned long lastSendToWeb = 0;
- unsigned long pullLowDuration = 2000; //3 seconds for pulling KEYPIN low to turn off/on Fona
- unsigned long GPSUpdateInterval = 21600000; // 6hrs
- unsigned long lastGPSupdate = 0;
- unsigned long GPSUpdateTimeout = 180000; //Time for trying to find a fix! If over, then no fix found (indoor).
- unsigned long noiseSameplingInterval = 2000; //Start sampling
- unsigned long lastNoiseSampling = 0;
- //Temp
- byte tempPin = A0;
- float temperature;
- //Noise
- const int sampleWindow = 500; // Sample window width in mS (50 mS = 20Hz)
- unsigned int sample;
- int noiseAVG = 0;
- const int numReadings = 20; // change for higher smoothing
- int readings[numReadings]; // the readings from the analog input
- int readIndex = 0; // the index of the current reading
- int total = 0; // the running total
- double boxDB = 115;
- //Status Flags
- byte statusInfo[] = {
- 1, //Value = 1 - status everything ok (white)
- 0, //Value = 1 - no Position (blue)
- 0, //Value = 1 - no connection to server (GSM) (pink)
- 0, //Value = 1 - low battery (red)
- 0, //Value = 1 - is charging (yellow)
- 0, //Value = 1 - battery fully charged (green)
- };
- uint16_t lastBatteryLevel = 0;
- uint16_t lastMilliVolts = 0;
- boolean lastMessageSent = true;
- //encryption
- AES aes;
- byte *key = (unsigned char*)"0123491889010123";
- void setup() {
- //while (!Serial);
- Serial.begin(115200);
- Serial1.begin(GPSBaud);
- //Inbit LED and turn on pixel
- pixel.begin();
- pixel.setBrightness(30);
- pixel.setPixelColor(0, pixel.Color(255, 255, 255)); //light up while startup
- pixel.show();
-
- analogReference(EXTERNAL); //sets analog reference voltage to AREF pin
- // initialize the readings for Noise to 0:
- for (int thisReading = 0; thisReading < numReadings; thisReading++) {
- readings[thisReading] = 0;
- }
- //Pins to turn on and off gsm and gps
- pinMode(KEYPIN, OUTPUT);
- digitalWrite(KEYPIN, HIGH);
- pinMode(GPSENABLE, OUTPUT);
- digitalWrite(GPSENABLE, LOW);
- encodeGPSAgain = true;
- /*
- //Get initial position
- lastGPSupdate = millis();
- encodeGPS();
- //Switch FONA on to initially check battery status
- initFONA();
- if(initFONAagain) initFONA(); //Try again. In case FONA was turned off in 1st attempt
- lastMilliVolts = getBatteryVoltage();
- switchFONA();
- */
- delay(900000); //15minutes to charge the battery before anything else is done
-
- //Turn off pixel
- pixel.setPixelColor(0, pixel.Color(0, 0, 0));
- pixel.show();
-
-
- }
- void loop() {
-
- blinkStatus(); //After the last message led is constantly red
- if(!lastMessageSent) { //Turn off everything thats not needed
-
- if(encodeGPSAgain) encodeGPS(); //Encoding again if no valid or updated signal found; no rekursion here
- if(initFONAagain) initFONA(); //Init FONA again if FONA was off while first attempt
-
- //Sampling Noise in a specific interval.
- currentMillis = millis();
- if (currentMillis - lastNoiseSampling >= noiseSameplingInterval) {
- lastNoiseSampling = currentMillis;
- noiseAVG = getNoise();
- //Serial.println("Info: Noise: " + String(noiseAVG) + "dB");
- }
-
- //Getting GPS data in a specific interval.
- currentMillis = millis();
- if (currentMillis - lastGPSupdate >= GPSUpdateInterval) {
- //Serial.println("Checking GPS");
- lastGPSupdate = currentMillis;
- encodeGPS();
- }
- }
-
- //Send to Web in a specific interval
- currentMillis = millis();
- if ((currentMillis - lastSendToWeb >= sendToWebInterval)) {
- lastSendToWeb = currentMillis;
-
- //Send to Webservice, if battery is good enough and GPS was once valid
- //INFO: Checking for valid GPS Signal only makes sense for static use on one place.
- // For dynamic use with changing places the check should use gps.location.isUpdated()
- if(gps.location.isValid() && (lastMilliVolts >= 3500) && !lastMessageSent) {
- switchFONA();
- initFONA();
- lastMilliVolts = getBatteryVoltage();
- //Serial.println("INFO: Sending to URL");
- sendToWebService(getGeoJSONDataString(), URL);
- //(Serial.println("INFO: Sending to URL2");
- //sendToWebService(getGeoJSONDataString(), URL2);
- switchFONA();
- } else { //Check Battery
- switchFONA();
- initFONA();
- lastMilliVolts = getBatteryVoltage();
- switchFONA();
- }
- //SERVICE MESSAGES
- //Power too low, but last message not yet sent -> send last message; BUT make sure, that mV is plausible -> >500
- if ((lastMilliVolts < 3480) && (lastMilliVolts > 500) && !lastMessageSent) {
- switchFONA();
- initFONA();
- //sendToWebService(getServiceJSONDataString(" LAST MESSAGE - NO BATTERY"));
- sendToWebService(boxID + "Bat: " + lastMilliVolts + "mV ------- LAST MESSAGE - NO BATTERY", URL2);
- lastMessageSent = true; //set to false; needed if battery is charging and sensor is sending again
- switchFONA();
- } else if((lastMilliVolts > 3550) && lastMessageSent) { //Power sufficient again (after charging) -> back to work msg (just a service msg) (3520mV to avoid pending between last msg and back to work msg)
- switchFONA();
- initFONA();
- sendToWebService(boxID + "Bat: " + lastMilliVolts + "mV ------- BACK TO WORK", URL2);
- //sendToWebService(getGeoJSONDataString(), URL);
- lastMessageSent = false; //set to false; needed if battery is charging and sensor is sending again
- switchFONA();
- }
-
- //Try to get a valid GPS location
- if(!gps.location.isValid() && (lastMilliVolts >= 3550) && !lastMessageSent) {
- switchFONA();
- initFONA();
- sendToWebService(boxID + "Bat: " + lastMilliVolts + "mV ------- NO GPS", URL2); //TODO: Change to service message
- //sendToWebService(getGeoJSONDataString(), URL);
- switchFONA();
-
- GPSUpdateInterval = sendToWebInterval;
- //Serial.println("INFO: NO GPS (sendtowebservice; 258)");
- }
- }
-
- }
- void initFONA() {
- //Serial.println("INFO: Starting FONA init");
- fonaSerial->begin(4800);
- if (!fona.begin(*fonaSerial)) {
- //Serial.println(F("INIT - Couldn't find FONA"));
- switchFONA(); //In case Phona is turned off (happens wenn battery runs completely out and is charged up again.
- initFONAagain = true; //after switching ON try to init again
- //Serial.println("ERROR: init FONA again; FONA not found");
-
- statusInfo[2] = 1;
- // Try to turn it on
- //turnOn();
- if (!fona.begin(*fonaSerial)) {
- while (1)
- ;
- }
- } else {
- statusInfo[2] = 0;
- initFONAagain = false;
- }
-
- type = fona.type();
- // Set APN (needed for A1 Sim cards) -> Uncomment if other SIM-Cards are in use
- fona.setGPRSNetworkSettings(F("A1.net"), F("ppp@a1plus.at"), F("ppp"));
-
- // turn GPRS on
- delay(10000);
-
- if (!fona.enableGPRS(true)) {
- //Serial.println(F("INIT - Failed to turn on GPRS"));
- statusInfo[2] = 1;
- //Serial.println("ERROR: init FONA again; no GPRS");
- initFONAagain = true; //Try to init FONA again in the next loop
- } else {
- statusInfo[2] = 0;
- initFONAagain = false;
- }
- /* NOT WORKING: Sending timestamp couses HTTP POST ERROR
- // enable NTP time sync
- fona.enableNTPTimeSync(true, F("pool.ntp.org"));
- //Serial.println(F("INFO: Failed to enable NTP time sync"));
- */
-
- //turnOnOffFona();
- }
- void switchFONA() {
- //Switching FONA on and off through pulling the KEYPIN LOW for a while
- //Each pull to LOW switches the FONA, either on or off (depending on the current state)
-
- //Serial.println("INFO: Switching FONA");
- unsigned long startMillis = millis();
- while (millis() - startMillis < pullLowDuration) {
- digitalWrite (KEYPIN, LOW);
- }
- digitalWrite(KEYPIN, HIGH);
-
- }
- void sendToWebService(String message, char URL[]) {
- //Serial.println("INFO - Start sending to Webservice");
-
- uint16_t statuscode;
- int16_t length;
- //String datastring = getGeoJSON();
- //String datastring = getSimpleDataString(); //For readable output on Server
- String datastring = message;
-
-
- //******with encryption start******
- /*
- byte *key = (unsigned char*)"0123491889010123"; //needs to be randomized!!!!
- unsigned long long int my_iv = 36712162; //needs to be randomized!!!!
- byte plain[datastring.length()];
- datastring.getBytes(plain, datastring.length());
- int plainLength = sizeof(plain)-1; // don't count the trailing /0 of the string !
- int padedLength = plainLength + N_BLOCK - plainLength % N_BLOCK;
- aes.iv_inc();
- byte iv [N_BLOCK] ;
- byte plain_p[padedLength];
- byte cipher [padedLength] ;
- aes.set_IV(my_iv);
- aes.get_IV(iv);
- aes.do_aes_encrypt(plain,plainLength,cipher,key,128,iv);
- flushSerial();
- bool success = true;
- if (!fona.HTTP_POST_start(URL, F("text/plain"), (uint8_t *) plain, strlen(plain), &statuscode, (uint16_t *)&length)) {
- //Serial.println("HTTP POST FAILED!");
- statusInfo[2] = 1;
- } else {
- statusInfo[2] = 0;
- }
-
- */
- //******with encryption end******
- //******without encryption start******
-
- unsigned int len = datastring.length() + 1;
- char data[len];
- datastring.toCharArray(data, len);
- flushSerial();
- //char myData[] = "{\"simple\":\"json\"}";
- bool success = true;
- String test = "fona";
- unsigned int lenToken = test.length() + 1;
- char tokenData[lenToken];
- test.toCharArray(tokenData, lenToken);
-
-
- if (!fona.HTTP_POST_start(URL, F("text/plain"), (uint8_t *) data, strlen(data), &statuscode, (uint16_t *)&length)) {
- statusInfo[2] = 1; //HTTP Post failed
- //Serial.println("ERROR: HTTP post failed");
- //pixel.setPixelColor(0, pixel.Color(255 ,255, 255)); //white, just for testing
- //pixel.show();
-
- } else {
- statusInfo[2] = 0;
- }
-
- //******without encryption end******
-
- fona.HTTP_POST_end();
- //Serial.println("INFO - End sending to Webservice");
-
- }
- String getGeoJSONDataString() {
-
- /* GeoJSON should look like this:
- {
- "type": "Feature",
- "geometry": {
- "type": "Point",
- "coordinates": [100.0, 0.0]
- },
- "properties": {
- "Temperature": [24.5, "°C"],
- "Noise": [100.0, "dB"],
- "timestamp": "123456723495",
- }
- }
- */
-
- String json = "{\"type\":\"Feature\",\"geometry\":{\"type\": \"Point\", \"coordinates\":[" +
- floatToString(gps.location.lng()) + ", " + floatToString(gps.location.lat()) + "]}, \"properties\": {\"Temperature\":[" +
- String(getTemperature()) + ", \"°C\"], \"Noise\":[" + String(noiseAVG) + ", \"dB\"], \"timestamp\":\"" + getTimeString() + "\"}}";
-
-
- return json;
-
- }
- String getServiceJSONDataString(uint16_t batLevel, String message) {
- /* Service JSON should Look like this
- {
- "battery": 17.4,
- "status_message": "failed to get GPS fix"
- }
- */
-
- String json = "{\"battery\": " + String(batLevel) +
- ", \"status_message\": \"" + message + "\"}";
- return json;
-
- }
- String getTimeString() {
-
- /* NOT WORKING: Sending timestamp couses HTTP POST ERROR
- *
- *
- // read the time
- char timeBuffer[23];
- fona.getTime(timeBuffer, 23); // make sure replybuffer is at least 23 bytes!
- //Format timebuffer: YY/MM/DD,HH:MM+00
-
- //Serial.println("INFO: Time: " + String(timeBuffer));
- String timestamp = timeBuffer;
- */
- return "";
- }
- String getSimpleDataString() {
-
-
- return ("GPS: " + floatToString(gps.location.lng()) + ", " + floatToString(gps.location.lat()) +
- "; Temperature: " + String(getTemperature()) + " C; Noise: " + String(noiseAVG) + " DB; Battery: " + String(getBatteryLevel()) + " %; Voltage: " + String(getBatteryVoltage()) +" mV; " + boxID);
-
- }
- String floatToString(float val) {
-
- int i;
- char buff[10];
- String valueString = "";
- dtostrf(val, 4, 6, buff); //4 is mininum width, 6 is precision
- valueString += buff;
- return valueString;
-
- }
- //////////// Get Sensor Data ///////////////////
- void encodeGPS(){
- //Serial.println("INFO: Turning on GPS module");
- digitalWrite(GPSENABLE, HIGH);
- unsigned long start = millis();
- // For one second we parse GPS data and report some key values
- for (start; millis() - start < 1000;)
- {
- while (Serial1.available())
- {
- char c = Serial1.read();
- //Serial.write(c); // uncomment this line if you want to see the GPS data flowing
- gps.encode(c); // Did a new valid sentence come in?
- }
- }
- //Serial.println();
-
- // DEBUGGING: Re-encoding for a certain time
- if(millis() - lastGPSupdate <= GPSUpdateTimeout) {
-
- //if we haven't seen lots of data in 5 seconds, something's wrong.
- if (start > 5000 && gps.charsProcessed() < 10) {
- //Serial.println("ERROR: Not getting any GPS data! Encoding again");
- encodeGPSAgain = true;
-
- //TODO: Turning Module OFF here?
- } else if(!gps.location.isValid()) { //also add timer for circumstances when there is definately no signal to find
- //Serial.println("ERROR: GPS Data not valid! Encoding again");
- encodeGPSAgain = true;
- GPSUpdateInterval = sendToWebInterval; //SendToWebinterval is usually shorter.
- } else if(!gps.location.isUpdated()) {
- //Serial.println("ERROR: GPS Data not updated! Encoding again");
- encodeGPSAgain = true;
- } else {
- //Serial.println("INFO: GPS: " + floatToString(gps.location.lat()) + ", " + floatToString(gps.location.lng()));
- //Serial.println("INFO: Turning off GPS-Module");
- digitalWrite(GPSENABLE, LOW); //turn gps module off
- encodeGPSAgain = false;
- GPSUpdateInterval = 21600000;
- statusInfo[1] = 0;
- }
-
- } else {
- //Serial.println("ERROR: Timeout - No GPS-Data");
- statusInfo[1] = 1;
- //TODO: Send Error Message to Server
- digitalWrite(GPSENABLE, LOW); //turn gps module off
- encodeGPSAgain = false;
- GPSUpdateInterval = sendToWebInterval;
-
- }
- }
- float getTemperature(){
-
- int pinReading = analogRead(ANALOG_TEMP_PIN);
- float voltage = pinReading * aref_voltage;
- voltage /= 1024.0;
- float temp = (voltage - 0.5) * 100;
-
- //Serial.println("Temperature: " + String(temp));
-
- //(((analogRead(ANALOG_TEMP_PIN) * 3.3)/1024.0) - 0.5) * 100;
- return temp;
- }
- //source: http://arduinolearning.com/code/arduino-and-max4466-electret-module-example.php
- float getNoiseReading(){
- unsigned long startMillis= millis(); // Start of sample window
- unsigned int peakToPeak = 0; // peak-to-peak level
- unsigned int signalMax = 0;
- unsigned int signalMin = 1024;
- while (millis() - startMillis < sampleWindow){
- sample = analogRead(ANALOG_NOISE_PIN);
- if (sample < 1024){ // toss out spurious readings
- if (sample > signalMax){
- signalMax = sample; // save just the max levels
- }
- else if (sample < signalMin){
- signalMin = sample; // save just the min levels
- }
- }
- }
- peakToPeak = signalMax - signalMin; // max - min = peak-peak amplitude
- return peakToPeak; //* 3.3) / 1024; // convert to volts
- }
- int getNoise(){
- // subtract the last reading:
- total = total - readings[readIndex];
- double noiseReading = getNoiseReading();
- // read from the sensor:
- // https://forum.arduino.cc/index.php?topic=318908.0
- // 80 = db on SPL-Meter, 120 = Noise from Noise Sensor at 80 db on the SPL-Meter
-
- //How to calibrate:
- //take the SPL-Meter and the Sensorbox
- //uncomment this:
- //Serial.println("Noise:");
- //Serial.println(noiseReading);
- //Serial.println("");
- //uncomment the seria println before the return
- //play a sound to reach 80 db on the SPL Meter
- // change boxDB on top to Value which is showing for the Sensorbox
-
- readings[readIndex] = (20 * log(noiseReading / boxDB) + 80);
- // add the reading to the total:
- total = total + readings[readIndex];
- // advance to the next position in the array:
- readIndex = readIndex + 1;
- // if we're at the end of the array...
- if (readIndex >= numReadings) {
- // ...wrap around to the beginning:
- readIndex = 0;
- }
- // calculate the average:
- //for calibration of Noise
- //Serial.println(total / numReadings);
-
- return (total / numReadings);
- // send it to the computer as ASCII digits
- }
- uint16_t getBatteryLevel() {
-
- uint16_t vbat;
-
- fona.getBattPercent(&vbat);
- lastBatteryLevel = vbat;
- //Serial.println("Battery Level: " + String(vbat));
- return vbat;
- }
- uint16_t getBatteryVoltage() {
- uint16_t vbat;
- //uint16_t batStat; //NOT WORKING
- fona.getBattVoltage(&vbat);
- //ATTENTION: This function doesn NOT work with public FONA Library.!!!!
- //Status: 0 = not charging; 1 = charging; 2 = finished charging
- //More Info in SIM800 Series AT Command Manual
- //NOT WORKING: getBattStatus always returns 0
- //fona.getBattStatus(&batStat);
- //Serial.println("Battery Status: " + String(batStat));
- //Serial.println("MilliVolts: " + String(vbat));
- //Clear false readings with too high (unrealistic) values
- if(vbat > 4700) vbat=0;
-
- //Battery low
- if (vbat <= 3600 && vbat!=0 ) statusInfo[3] = 1;
- else statusInfo[3] = 0;
-
- //Battery charging
- if (vbat > lastMilliVolts && vbat!=0) statusInfo[4] = 1;
- else statusInfo[4] = 0;
-
- //Battery fully charged
- if (vbat > 4170 && vbat!=0) {
- statusInfo[5] = 1;
- statusInfo[4] = 0;
- } else {
- statusInfo[5] = 0;
- }
-
- return vbat;
- }
- //////////// Helpers & Output ///////////////////
- void blinkStatus() {
- //get number of statusInfo
- boolean blinkSequenceActive = false;
- currentMillis = millis();
-
- if(currentMillis - lastBlinkSequenceStart >= blinkInterval) { //start blinking
- blinkSequenceActive = true;
- lastBlinkSequenceStart = currentMillis;
-
- }
- if(blinkSequenceActive) { //do the blink sequence
- lastSingleBlinkStart = currentMillis;
-
- for(int i=0; i<sizeof(statusInfo); ) {
-
- switch (i) {
- case 0:
- pixel.setPixelColor(0, pixel.Color(255 ,255, 255)); //white -> status blink
- break;
- case 1:
- pixel.setPixelColor(0, pixel.Color(0,200, 255)); //blue -> no GPS
- break;
- case 2:
- pixel.setPixelColor(0, pixel.Color(255,0, 255)); //pink -> no GSM
- break;
- case 3:
- pixel.setPixelColor(0, pixel.Color(255,0, 0)); //red -> low Battery
- break;
- case 4:
- pixel.setPixelColor(0, pixel.Color(255,188, 0)); //orange -> bat charging
- break;
- case 5:
- pixel.setPixelColor(0, pixel.Color(0,255, 0)); //green -> bat fully charged
- break;
- }
- if(statusInfo[i] !=0) pixel.show();
- currentMillis = millis();
- if(currentMillis - lastSingleBlinkStart >= singleBlinkDuration) {
- i++; //increase counter to get to the next info
- lastSingleBlinkStart = currentMillis;
- pixel.setPixelColor(0, pixel.Color(0,0, 0)); //green -> bat fully charged
- pixel.show();
- }
-
- }
-
- }
-
- if(currentMillis - lastBlinkSequenceStart >= blinkSequenceDuration) { //turn off again
-
- pixel.setPixelColor(0, pixel.Color(0 ,0, 0));
- pixel.show();
- blinkSequenceActive = false;
- }
-
- }
- /*
- void printSensorData(){
- Serial.println("SensorData:");
- Serial.print("\nTemperature: "); Serial.println(getTemperature());
- Serial.print("\nNoise: "); Serial.println(getNoise());
- Serial.print("\nBattery: "); Serial.print(getBatteryLevel()); Serial.println(" %");
- Serial.print("\nLocation: "); Serial.print(gps.location.lat(), 6); Serial.print(", "); Serial.println(gps.location.lng(), 6);
- Serial.println("---------------------------------------");
- }
- String sensorDataToString() {
- String data = "Sensordata: Temperature: " + String(getTemperature()) + " Noise: " + String(getNoise()) + " Battery: " + String(getBatteryLevel()) + "% Location: " + String(gps.location.lat()) + ", " + String(gps.location.lng());
- return data;
- }
- */
- void flushSerial() {
- while (Serial.available()) {
- Serial.read();
- }
- }
|