Changes:

Changes:

* Remove loop delays
* Clock icon animation depends on rtc
* Time setup correct val loop
* Add full dew point support
* Add epmty space: " Err "
* Add backlight on buttons
* Spellings and minor fixes

--- meteo_lcd/meteo_lcd.ino
+++ meteo_lcd/meteo_lcd.ino
@@ -41,10 +41,10 @@
  01234567890123456789
 +--------------------+
 |In:  Err °C  Err% RH|
-|In: -20.5°C  100% RH|
-|Out:-20.5°C  100% RH|
-|             Err hPa|
-|          1013.9 hPa|
+|In: -20.5°C   100%RH|
+|Out:-20.5°C   100%RH|
+|DP:-70°C  1013.9 hPa|
+|DP: 70°C     Err hPa|
 |17:34:59  31.12.2017|
 +--------------------+
  */
@@ -80,14 +80,11 @@
 // Real-time clock
 DS3231 rtc;

-
-// Delay
-const int32_t delay_time = 100; // [ms]
-const int32_t meteo_delay = 2000; // [ms] Update meteo data every 2s
-int32_t delay_counter = 0;
-
 // Error value
 const int32_t err_val = 200000;
+
+// Show dew point or clock icon or none? (No place for both)
+bool show_dew_point = true;

 ////////////////////////////////////////////////////////////////////////////////
 //                DEW POINT SUPPORT
@@ -272,8 +269,14 @@

 void print_clock()
 {
+    static byte last_second;
+    if (last_second == rtc.getSecond()) {
+        // No update needed
+        return;
+    }
+    last_second = rtc.getSecond();
+
     static byte iter;
-
     iter = (iter + 1) % 8;
     print_clock_char(iter);
 }
@@ -334,7 +337,7 @@
      * 6 - exit;
     */

-    byte val;
+    int val;
     int change = 0;
     bool tmp1, tmp2;

@@ -529,21 +532,26 @@
 {
     lcd.setCursor(0, 0);
     lcd.print("In:      ");
-    lcd.print((char)223);
+    lcd.print((char)223); // '°'
     lcd.print("C     ");
-    lcd.print((char)37);
+    lcd.print((char)37); // '%'
     lcd.print(" RH");

     lcd.setCursor(0, 1);
     lcd.print("Out:     ");
-    lcd.print((char)223);
+    lcd.print((char)223); // '°'
     lcd.print("C     ");
-    lcd.print((char)37);
+    lcd.print((char)37); // '%'
     lcd.print(" RH");

     lcd.setCursor(0, 2);
-    lcd.print("             Err hPa");
+    if (show_dew_point)
+        lcd.print("DP:   ");
+    else
+        lcd.print("      ");
+    lcd.print((char)223); // '°'
+    lcd.print("C         hPa");

     lcd.setCursor(0, 3);
     lcd.print("                    ");
@@ -552,11 +560,11 @@
 ////////////////////////////////////////////////////////////////////////////////
 //                GET AND PRINT METEO DATA

-void set_error (int cur, int line, bool empty_char_after = false)
+void set_error (int cur, int line, bool empty_chars = false)
 {
     lcd.setCursor(cur, line);
-    if (empty_char_after) {
-        lcd.print("Err ");
+    if (empty_chars) {
+        lcd.print(" Err ");
     }
     else {
         lcd.print("Err");
@@ -572,14 +580,14 @@
 +--------------------+
 |In:  Err °C  Err% RH|
 |Out:-20.5°C  100% RH|
-|          1013.9 hPa|
+|DP:-70°C  1013.9 hPa|
 |17:34:59  31.12.2017|
 +--------------------+
  */

     // Temp inside
     if (temp_in >= err_val) {
-        set_error(5, 0, true);
+        set_error(4, 0, true);
     }
     else {
         lcd.setCursor(4, 0);
@@ -599,7 +607,7 @@

     // Temp outside
     if (temp_out >= err_val) {
-        set_error(5, 1, true);
+        set_error(4, 1, true);
     }
     else {
         lcd.setCursor(4, 1);
@@ -621,6 +629,13 @@
     lcd.setCursor(10, 2);
     dtostrf(pressure/100.0, 6, 1, buff);
     lcd.print(buff);
+
+    // Dew point
+    if (show_dew_point) {
+        lcd.setCursor(3, 2);
+        dtostrf(get_dew_point(temp_out, humid_out), 3, 0, buff);
+        lcd.print(buff);
+    }
 }

 void read_meteo_data(float &temp_in,  float &humid_in,
@@ -688,7 +703,7 @@

     // ##### Pressure #####
     // Nothing to do here
-    LOG("Pressuren: "); LOGLN(pressure);
+    LOG("Pressure: "); LOGLN(pressure);
 }

@@ -719,7 +734,7 @@

     // LCD
     lcd.init();
-    //print_clock_setup(); // Optional
+    print_clock_setup(); // Can be disabled if print_clock() isn't used

     lcd.backlight();
     //lcd.noBacklight();
@@ -758,10 +773,21 @@
 void loop ()
 {
     LOGLN("Loop");
-//    error_blink(1);

     if (enter_time_setup())
         time_setup(3 /* 4th row */);
+
+    if (was_button_pressed(BUTTON_UP)) {
+        lcd.backlight();
+    }
+    else if (was_button_pressed(BUTTON_DOWN)) {
+        lcd.noBacklight();
+    }
+    else if (was_button_pressed(BUTTON_OK)) {
+        lcd.backlight();
+	delay(4000);
+        lcd.noBacklight();
+    }

     // Update meteo data
     float temp_in, humid_in, temp_out, humid_out;
@@ -770,10 +796,10 @@
     read_meteo_data(temp_in, humid_in, temp_out, humid_out, pressure);
     fill_data(temp_in, temp_out, humid_in, humid_out, pressure);

+    // Clock icon - optional. Only if show_dew_point is disabled
+    // print_clock()
+
     // Update the displayed time
     print_time_string(3 /* 4th row */);
-
-    LOG("delay "); LOGLN(delay_time);
-    //delay(delay_time);
-}
-
+}
+


Change backlight logic

Change backlight logic

* Button UP for temporary backlight (~7s)
* Button DOWN for constant on/off backlight

--- meteo_lcd/meteo_lcd.ino
+++ meteo_lcd/meteo_lcd.ino
@@ -80,6 +80,7 @@

 // LCD Display
 LiquidCrystal_I2C lcd(0x27, 20, 4);  // set the LCD address to 0x27 for a 20 chars and 4 line display
+static bool LCD_backlight;

 // Real-time clock
@@ -732,16 +733,49 @@
 {
     const int default_state = HIGH; /*assume that button is pull-up*/

+    static byte off_time;
+    static bool should_off;
+
+    // This may cause that we miss off_time and the backlight will stay on.
+    // This may happend beause of some "lag" from sensors, or user will use
+    // DOWN+UP+OK buttons to set time;
+    // Anyway it's not a big issue. Backlight will be off eventually.
+    // User can always turn it off manually by pushing DOWN button.
+    if (should_off && off_time == rtc.getSecond()) {
+        lcd.noBacklight();
+        should_off = false;
+        LCD_backlight = false;
+    }
+
+    // BUTTON_UP
     if (digitalRead(BUTTON_DOWN) == default_state &&
         digitalRead(BUTTON_OK) == default_state &&
         was_button_pressed(BUTTON_UP)) {
+        if (LCD_backlight) {
+            // Do nothing
+            return;
+        }
         lcd.backlight();
+        LCD_backlight = true;
+        off_time = (rtc.getSecond() + 10) % 60;
+        should_off = true;
         return;
     }
+
+    // BUTTON_DOWN
     if (digitalRead(BUTTON_UP) == default_state &&
         digitalRead(BUTTON_OK) == default_state &&
         was_button_pressed(BUTTON_DOWN)) {
-        lcd.noBacklight();
+        if (LCD_backlight) {
+            lcd.noBacklight();
+            LCD_backlight = false;
+            should_off = false;
+        }
+        else {
+            lcd.backlight();
+            LCD_backlight = true;
+            should_off = false;
+        }
         return;
     }
 }
@@ -777,6 +811,7 @@
     print_clock_setup(); // Can be disabled if print_clock() isn't used

     lcd.backlight();
+    LCD_backlight = true;
     //lcd.noBacklight();
     lcd.noCursor();
     lcd.noBlink();


calibration controls, more refactoring, and discontinuity handling

--- Arduino/Turnstyle/Turnstyle.ino
+++ Arduino/Turnstyle/Turnstyle.ino
@@ -2,12 +2,10 @@
 #include <MadgwickAHRS.h>
 #include <NewPing.h>
 #include <Wire.h>
+#include <Adafruit_MCP23017.h>
 #include <Adafruit_RGBLCDShield.h>
 #include <CurieBLE.h>

-// parameters indicated with a *** should be tuned to fit the door.
-
-// ULTRASONIC -- settings match for blackboard-hardware V1.0
 #define TRIGGER_PIN_1  12  // Arduino pin tied to trigger pin on the first ultrasonic sensor.
 #define ECHO_PIN_1     11  // Arduino pin tied to echo pin on the first ultrasonic sensor.
 #define TRIGGER_PIN_2  10  // Arduino pin tied to trigger pin on the second ultrasonic sensor.
@@ -18,11 +16,12 @@
 #define OPEN_ANGLE 20       // Angle where door is considered open***
 #define MAX_DISTANCE 200    // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

-// USE THIS INSTEAD TO REVERSE THE DOOR DIRECTION
-// NewPing sonar_1(TRIGGER_PIN_2, ECHO_PIN_2, MAX_DISTANCE);  // NewPing setup of closer sensor.***
-// NewPing sonar_2(TRIGGER_PIN_1, ECHO_PIN_1, MAX_DISTANCE);  // NewPing setup of farther sensor.***
-NewPing sonar_1(TRIGGER_PIN_1, ECHO_PIN_1, MAX_DISTANCE);     // NewPing setup of closer sensor.***
-NewPing sonar_2(TRIGGER_PIN_2, ECHO_PIN_2, MAX_DISTANCE);     // NewPing setup of farther sensor.***
+// ULTRASONIC -- settings match for blackboard-hardware V1.0
+NewPing sonar_1(TRIGGER_PIN_1, ECHO_PIN_1, MAX_DISTANCE);
+NewPing sonar_2(TRIGGER_PIN_2, ECHO_PIN_2, MAX_DISTANCE);
+NewPing closeSonar = sonar_1;                               // NewPing setup of closer sensor.
+NewPing farSonar = sonar_2;                                 // NewPing setup of farther sensor.
+boolean enterFromLeftToRight = true;                        // is leftToRight movement considered entering or vice-versa?

 // RGB_LCD from Adafruit
 Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
@@ -64,7 +63,7 @@
   blePeripheral.addAttribute(turnstyleBleService);
   blePeripheral.addAttribute(turnstyleBleIntCharacteristic);
   blePeripheral.begin();
-  printIfDebug("Bluetooth device active, waiting for connections...");
+  printlnIfDebug("Bluetooth device active, waiting for connections...");

   // configure LCD
   lcd.begin(16, 2);
@@ -91,10 +90,6 @@
   microsBetweenReads = 1000000 / 2;     // must wait half a second between consecutive reads
   microsLastRead = micros();            // time since last movement detected

-  // NOTE: the initial angle of the door is always 180 degrees, so this commented code is not necessary for now.
-  // get initial angle of the door
-  // startAngle = measureYaw();
-
   // Indicate that setup is complete
   pinMode(ledPin, OUTPUT);
   digitalWrite(ledPin, HIGH);
@@ -105,11 +100,9 @@
   BLECentral central = blePeripheral.central();
   // if a central is connected to peripheral:
   if (central) {
-    if (debug) {
-      Serial.print("Connected to central: ");
-    }
+    printIfDebug("Connected to central: ");
     // print the central's MAC address:
-    printIfDebug(central.address());
+    printlnIfDebug(central.address());
     // turn on the LED to indicate the connection:
     digitalWrite(13, HIGH);
     // as long as the central is still connected:
@@ -118,10 +111,8 @@
     }
     // when the central disconnects, turn off the LED:
     digitalWrite(13, LOW);
-    if (debug) {
-      Serial.print("Disconnected from central: ");
-    }
-    printIfDebug(central.address());
+    printIfDebug("Disconnected from central: ");
+    printlnIfDebug(central.address());
   } else {
     loopHelper(false);
   }
@@ -145,9 +136,11 @@
         baselineYaw = currentYaw;
         switchClosedLastIteration = false;
       }
-      float absDifference = abs(currentYaw - baselineYaw);
-      // for now... i will fix with better logic later... probably account for directionality using a similar button system
-      doorAngle = absDifference;
+      float doorAngle = abs(currentYaw - baselineYaw);
+      // if the doorAngle is > 180, it must be due to the discontinuity, assuming doors open to an angle of max 180 degrees.
+      if (doorAngle > 180) {
+        doorAngle = 360 - doorAngle;
+      }
     } else {
       switchClosedLastIteration = true;
     }
@@ -155,11 +148,11 @@
     if (!isMagSwitchOpen || doorAngle < OPEN_ANGLE) { // Door is closed
       closeDoor();
     } else if ((microsNow - microsLastRead < microsBetweenReads)) { // Door is open, a movement was recently detected, and we are waiting between movements; do not double count or re-record the last passing time because the person may still be passing through.
-      printIfDebug("Movement Detected");
+      printlnIfDebug("Movement Detected");
     } else { // Door is open, but a complete movement has not been discovered recently.
       openDoor();
-      ping_1 = sonar_1.ping_cm();
-      ping_2 = sonar_2.ping_cm();
+      ping_1 = closeSonar.ping_cm();
+      ping_2 = farSonar.ping_cm();

       // This block and the next have similar logic.  When we detect a ping, we adjust population and reset the latest detection times if the other sensor's last detection time is recent.  Otherwise, we update the current sensor's last detection.
       if (detect(ping_2)) {
@@ -181,14 +174,46 @@
           closeLastTime = 0;
         }
       }
-      printinfo(doorAngle, ping_1, ping_2);
-    }
-
-    updateBleCharacteristic();
+      printInfoIfDebug(doorAngle, ping_1, ping_2);
+    }
+
+    // Only bother updating bluetooth data if a device is connected
+    if (connected) {
+      updateBleCharacteristic();
+    }
+
+    // CURRENT CONTROL SCHEME: left and right buttons make the entering direction in the orientation specified by the button.
+    // select buttons always toggles the orientation.
+    uint8_t buttons = lcd.readButtons();
+    if (buttons) {
+      if (buttons & BUTTON_LEFT) {
+        if (enterFromLeftToRight) {
+          swapSonars();
+        }
+      }
+      if (buttons & BUTTON_RIGHT) {
+        if (!enterFromLeftToRight) {
+          swapSonars();
+        }
+      }
+      if (buttons & BUTTON_SELECT) {
+        swapSonars();
+      }
+    }

     // increment previous time, so we keep proper pace
     microsPrevious = microsPrevious + microsPerReading;
   }
+}
+
+// Flip the orientation of the sensors
+void swapSonars() {
+  NewPing temp = closeSonar;
+  closeSonar = farSonar;
+  farSonar = temp;
+  enterFromLeftToRight = !enterFromLeftToRight;
+  String message = enterFromLeftToRight ? "Enter this way->" : "<-Enter this way";
+  displayMessage(message);
 }

 void updateBleCharacteristic() {
@@ -196,69 +221,42 @@
   turnstyleBleIntCharacteristic.setValue(dataArray, 2);
 }

-float measureYaw() { // from the tutorial -- don't worry too much about this.
-  int aix, aiy, aiz;
-  int gix, giy, giz;
-  float ax, ay, az;
-  float gx, gy, gz;
-  // read raw data from CurieIMU
-  CurieIMU.readMotionSensor(aix, aiy, aiz, gix, giy, giz);
-
-  // convert from raw data to gravity and degrees/second units
-  ax = convertRawAcceleration(aix);
-  ay = convertRawAcceleration(aiy);
-  az = convertRawAcceleration(aiz);
-  gx = convertRawGyro(gix);
-  gy = convertRawGyro(giy);
-  gz = convertRawGyro(giz);
-
-  // update the filter, which computes orientation
-  filter.updateIMU(gx, gy, gz, ax, ay, az);
-
-  return filter.getYaw();
-}
-
 void incrementPopulation() {
   population++;
-  updatePopulationAndMoveCursor();
-  lcd.print("Welcome!        ");
+  updatePopulation();
+  displayMessage("Welcome!        ");
 }

 void decrementPopulation() {
   if (population > 0) { // whoops
     population--;
   }
-  updatePopulationAndMoveCursor();
-  lcd.print("Have a nice day!");
+  updatePopulation();
+  displayMessage("Have a nice day!");
 }

 void openDoor() { // only open the door if it wasn't already opened
   if (!isDoorOpen) {
     isDoorOpen = true;
-    printIfDebug("Door open");
+    printlnIfDebug("Door open");
   }
 }

 void closeDoor() { // only close the door if it wasn't already closed.
   if (isDoorOpen) {
-    lcd.setCursor(0, 1);
-    lcd.println("closed              ");
     isDoorOpen = false;
-    printIfDebug("Door closed");
-  }
-}
-
-// Update population and move cursor to where the message will be written
-void updatePopulationAndMoveCursor() {
+    printlnIfDebug("Door closed");
+  }
+}
+
+// Update population
+void updatePopulation() {
   lcd.setCursor(12, 0);
   lcd.print("    ");
   lcd.setCursor(12, 0);
   lcd.print(population);
-  lcd.setCursor(0, 1);
-
-  if (debug) {
-    Serial.print("Population: ");
-  }
+
+  printIfDebug("Population: ");
   Serial.print(population);
   if (!debug) {
     Serial.println("*");
@@ -270,24 +268,10 @@
   microsLastRead = micros();
 }

-// from tutorial
-float convertRawAcceleration(int aRaw) {
-  // since we are using 2G range
-  // -2g maps to a raw value of -32768
-  // +2g maps to a raw value of 32767
-
-  float a = (aRaw * 2.0) / 32768.0;
-  return a;
-}
-
-// from tutorial
-float convertRawGyro(int gRaw) {
-  // since we are using 250 degrees/seconds range
-  // -250 maps to a raw value of -32768
-  // +250 maps to a raw value of 32767
-
-  float g = (gRaw * 250.0) / 32768.0;
-  return g;
+// displays a message in the second line of the lcd.  Use for greetings/farewells and calibrations
+void displayMessage(String message) {
+  lcd.setCursor(0, 1);
+  lcd.print(message);
 }

 // did we get a detection?  boolean logic goes here to avoid doing >0 checks (which indicate that the ping was too far away)
@@ -295,7 +279,8 @@
   return pingValue < DETECTION_THRESH && pingValue > 0;
 }

-void printinfo(float doorAngle, int ping_1, int ping_2) {
+// prints measurement info
+void printInfoIfDebug(float doorAngle, int ping_1, int ping_2) {
   if (debug) {
     Serial.print("Door Angle: ");
     Serial.print(doorAngle);
@@ -307,8 +292,59 @@
   }
 }

+// wrap all Serial.prints using this function for ease of debugging
 void printIfDebug(String message) {
   if (debug) {
+    Serial.print(message);
+  }
+}
+
+// wrap all Serial.printlns using this function for ease of debugging
+void printlnIfDebug(String message) {
+  if (debug) {
     Serial.println(message);
   }
 }
+
+// from the tutorial -- don't worry too much about this.
+float measureYaw() {
+  int aix, aiy, aiz;
+  int gix, giy, giz;
+  float ax, ay, az;
+  float gx, gy, gz;
+  // read raw data from CurieIMU
+  CurieIMU.readMotionSensor(aix, aiy, aiz, gix, giy, giz);
+
+  // convert from raw data to gravity and degrees/second units
+  ax = convertRawAcceleration(aix);
+  ay = convertRawAcceleration(aiy);
+  az = convertRawAcceleration(aiz);
+  gx = convertRawGyro(gix);
+  gy = convertRawGyro(giy);
+  gz = convertRawGyro(giz);
+
+  // update the filter, which computes orientation
+  filter.updateIMU(gx, gy, gz, ax, ay, az);
+
+  return filter.getYaw();
+}
+
+// from tutorial
+float convertRawAcceleration(int aRaw) {
+  // since we are using 2G range
+  // -2g maps to a raw value of -32768
+  // +2g maps to a raw value of 32767
+
+  float a = (aRaw * 2.0) / 32768.0;
+  return a;
+}
+
+// from tutorial
+float convertRawGyro(int gRaw) {
+  // since we are using 250 degrees/seconds range
+  // -250 maps to a raw value of -32768
+  // +250 maps to a raw value of 32767
+
+  float g = (gRaw * 250.0) / 32768.0;
+  return g;
+}


Replaced stackCheck with library version

--- Arduino/V0p2_Main/V0p2_Main.ino
+++ Arduino/V0p2_Main/V0p2_Main.ino
@@ -760,11 +760,6 @@
   serialStatusReport();
 #endif

-  // Report current stack usage.
-  OTV0P2BASE::MemoryChecks::resetMinSP();
-  OTV0P2BASE::MemoryChecks::recordIfMinSP();
-  stackCheck();
-
   // Do OpenTRV-specific (late) setup.
   setupOpenTRV();
   }
@@ -772,43 +767,15 @@
 //========================================
 // MAIN LOOP
 //========================================
-#if 1
-// More detailed stack usage output
-inline void stackCheck()
-{
-	// Force restart if SPAM/heap/stack likely corrupt.
-    OTV0P2BASE::MemoryChecks::forceResetIfStackOverflow();
-
-    // Print max stack usage each cycle
-    const int16_t minsp = OTV0P2BASE::MemoryChecks::getMinSPSpaceBelowStackToEnd();
-    const uint8_t location = OTV0P2BASE::MemoryChecks::getLocation();
-    OTV0P2BASE::serialPrintAndFlush(F("minsp: "));
-    OTV0P2BASE::serialPrintAndFlush(minsp, HEX);
-    OTV0P2BASE::serialPrintAndFlush(F(" loc:"));
-    OTV0P2BASE::serialPrintAndFlush(location);
-    OTV0P2BASE::serialPrintlnAndFlush();
-
-    OTV0P2BASE::MemoryChecks::resetMinSP();
-}
-#endif
-
 void loop()
   {
 #if defined(EST_CPU_DUTYCYCLE)
   const unsigned long usStart = micros();
 #endif

-#if 1
-  // Force restart if SPAM/heap/stack likely corrupt.
-  OTV0P2BASE::MemoryChecks::forceResetIfStackOverflow();
-
   // Complain and keep complaining when getting near stack overflow.
   // TODO: make DEBUG-only when confident all configs OK.
-  const int16_t minsp = OTV0P2BASE::MemoryChecks::getMinSPSpaceBelowStackToEnd();
-  if(minsp < 64) { OTV0P2BASE::serialPrintlnAndFlush(F("!SH")); }
-#else
-  stackCheck();
-#endif
+  OTV0P2BASE::stackCheck();

   loopOpenTRV();


Update to WebClientRepeating comments

Update to WebClientRepeating comments

--- libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino
+++ libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino
@@ -6,8 +6,7 @@
  the Adafruit Ethernet shield, either one will work, as long as it's got
  a Wiznet Ethernet module on board.

- This example uses the String library, which is part of the Arduino core from
- version 0019. It also uses DNS, by assigning the Ethernet client with a MAC address,
+ This example uses DNS, by assigning the Ethernet client with a MAC address,
  IP address, and DNS address.

  Circuit:


dynamic filenames

dynamic filenames

--- Calibration/sdWrite/sdWrite.ino
+++ Calibration/sdWrite/sdWrite.ino
@@ -1,5 +1,10 @@
 #include <SD.h>
 #include <SPI.h>
+
+// This must be less than 8 characters (9 bytes)
+// Extra byte for being such a good programmer
+const int fileNameSize = 10;
+char strFileName[fileNameSize];

 void setup() {

@@ -18,6 +23,7 @@
     return;
   }
   Serial.println("card initialized.");
+  getNewFileName();
 }

 void loop() {
@@ -27,11 +33,34 @@
 }

 /*
+gives a new filename so we can open a new file each time
+no failure code, defaults to run0fv.txt
+*/
+void getNewFileName() {
+  Serial.println("started to get filename");
+  strncpy(strFileName, "run0.txt", fileNameSize);
+  int nameSize = 0;
+  for(int i = 0; SD.exists(strFileName); nameSize = sprintf(strFileName, "run%d.txt", i)) {
+    //catch potential overflow with the name size then we have an issue.
+    //so we write to the file "runOvf.txt"
+    Serial.print("checking filename ");
+    Serial.println(strFileName);
+    if(nameSize > 12) {
+      strncpy(strFileName, "runOfv.txt", fileNameSize);
+      return;
+    }
+   i++;
+  }
+  Serial.println("Got filename");
+  return;
+}
+
+/*
 Filename MUST be <=8 characters (not including the file extension) or the
 file will not be created
 */
 bool sdWrite(String data) {
-  File dataFile = SD.open("kai.txt", FILE_WRITE);
+  File dataFile = SD.open(strFileName, FILE_WRITE);
   // if the file is available, write to it:
   if (dataFile) {
     dataFile.println(data);


moving GPS before accel, to help with repeated sleeps / wakeups

--- motion-tracker/main.ino
+++ motion-tracker/main.ino
@@ -65,8 +65,6 @@
     lastMotion = 0;
     lastPublish = 0;

-    initAccel();
-
     // electron asset tracker shield needs this to enable the power to the gps module.
     pinMode(D6, OUTPUT);
     digitalWrite(D6, LOW);
@@ -75,6 +73,9 @@
     pinMode(D7, OUTPUT);
     digitalWrite(D7, LOW);

+    // wait a little for the GPS to wakeup
+    delay(250);
+
     GPS.begin(9600);
     mySerial.begin(9600);
     Serial.begin(9600);
@@ -84,7 +85,6 @@
     GPS.sendCommand("$PMTK101*32");
     delay(250);

-
     // request everything!
     GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_ALLDATA);
     delay(250);
@@ -92,6 +92,8 @@
     // turn off antenna updates
     GPS.sendCommand(PGCMD_NOANTENNA);
     delay(250);
+
+    initAccel();
 }


Update: added led level control and enabler pin for sensor

--- moisture-sensor.ino
+++ moisture-sensor.ino
@@ -1,24 +1,86 @@
-int sensorPin = A1;    // select the input pin for the potentiometer
+#define TIME_INTERVAL 1000
+#define ENABLER_PIN 2		// output pin that enables the sensor while reading the value
+#define SENSOR_PIN A1		// input pin for the sensor
+
+int ledPins[] = {3, 4, 5, 6, 7};
+
 int sensorValue = 0;  // variable to store the value coming from the sensor

-#define TIME_INTERVAL 1000
+int ledLevel = 0;

 long timer = 0;

 void setup() {
-  // declare the ledPin as an OUTPUT:
-   Serial.begin(115200);
+
+	// setup serial for debugging
+	Serial.begin(115200);
+
+	// setup outputs
+	pinMode(SENSOR_PIN, OUTPUT);
+
+	// test leds
+	for (int pin = 0; pin < (sizeof(ledPins)/sizeof(int)); pin++ ) {
+		pinMode(ledPins[pin], OUTPUT);
+		delay(150);
+		digitalWrite(ledPins[pin], HIGH);
+	}
+	delay(1000);
+	setLedLevel(0);
+	delay(100);
+
+	// test sensor
+	digitalWrite(ENABLER_PIN, HIGH);
+	sensorValue = analogRead(SENSOR_PIN);
+	Serial.print("[DEBUG]: test read value: ");
+	Serial.println(sensorValue);
+	digitalWrite(ENABLER_PIN, LOW);
 }

 void loop() {
+
+
 	unsigned long currentTime = millis();
-	if (currentTime - timer > TIME_INTERVAL) {
+	if ((unsigned long)(currentTime - timer) >= TIME_INTERVAL) {
+
+		// enable probe
+		digitalWrite(ENABLER_PIN, HIGH);
+		delay(10);
 		// read the value from the sensor:
-	  sensorValue = analogRead(sensorPin);
-	  Serial.print("sensor = " );
-	  Serial.println(sensorValue);
+		sensorValue = analogRead(SENSOR_PIN);
+		// disable probe after reading values
+		digitalWrite(ENABLER_PIN, LOW);

+
+
+		// breakpoints for different led levels:
+		if (sensorValue > 550) ledLevel = 5;
+		if (sensorValue < 550) ledLevel = 4;
+		if (sensorValue < 450) ledLevel = 3;
+		if (sensorValue < 350) ledLevel = 2;
+		if (sensorValue < 250) ledLevel = 1;
+		setLedLevel(ledLevel);
+
+		// debug data
+		Serial.print("[DEBUG]: current value: ");
+		Serial.println(sensorValue);
+
+		// save time
 		timer = currentTime;
 	}
-
-}+
+}
+
+void setLedLevel(int level) {
+	int ledArraySize = (sizeof(ledPins)/sizeof(int));
+	if (level < 0) level = 0;
+	if (level > (ledArraySize) )
+		level = ledArraySize;
+
+	for (int pin = 0; pin < ledArraySize; pin++ ) {
+		pinMode(ledPins[pin], OUTPUT);
+		if (level >= pin+1)
+			digitalWrite(ledPins[pin], HIGH);
+		else
+			digitalWrite(ledPins[pin], LOW);
+	}
+}


servo down changed to handle reversed servos

--- EggBotArduino/EggBotArduino.ino
+++ EggBotArduino/EggBotArduino.ino
@@ -56,7 +56,7 @@
 #define XAXIS_MAX_STEPCOUNT 300
 #define DEFAULT_ZOOM_FACTOR 1. // With a Zoom-Faktor of .65, I can print gcode for Makerbot Unicorn without changes.
 // The zoom factor can be also manipulated by the propretiary code M402
-
+#define SERVO_REVERSE 1

 /* --------- */

@@ -362,14 +362,14 @@
 					}
 					// Slow servo down
 					while (servo.read() != value){
-						if (servo.read() < value){
-							servo.write((int) servo.read()+1);
+						if ((servo.read() < value) ^ SERVO_REVERSE){
+							servo.write((int) servo.read()+1-2*SERVO_REVERSE);
 							for (int i = 0; i < 10; i++) {
 							  SoftwareServo::refresh();
 							  delay(4);
 							}
 						}
-						else if (servo.read() > value){
+						else{
 							servo.write((int) value);
 							SoftwareServo::refresh();
 						}


type set to 27C020 like; output beautyfied

--- Memory/FlashReader/FlashReader.ino
+++ Memory/FlashReader/FlashReader.ino
@@ -80,7 +80,7 @@
 uint8_t eepromData[kMAX_BLOCK_SIZE];
 uint32_t eepromAddr = 0;
 //EEprom::eEEPROMtype eepromType = EEprom::eEEPROM_2732;
-EEprom::eEEPROMtype eepromType = EEprom::eEEPROM_27040;
+EEprom::eEEPROMtype eepromType = EEprom::eEEPROM_27020;

 /**  */
 void setup() {
@@ -122,6 +122,9 @@

   if ( first ) {
     help_main.print(Serial);
+    Serial.print(F("E(E)PROM type: "));
+    Serial << (int)eeprom.getType() << " ("
+           << EEprom::getTypeString(eeprom.getType()) << ")" << endl;
     first = false;
   }

@@ -146,6 +149,7 @@
           eepromAddr = readInt32();
           //eepromAddr = Serial.parseInt();
           //Serial.println(eepromAddr);
+          Serial.println();
         break;

       case 'f':  // --- toggle output format
@@ -166,6 +170,7 @@
         total_length = readInt();
         //total_length = Serial.parseInt();
         //Serial.println(total_length);
+        Serial.println();
         break;

       case 'r':  // --- read length bytes starting from address
@@ -224,6 +229,7 @@
             eeprom.setType(eepromType);
             eepromAddr = 0;  // start again with first addr
           }
+          Serial.println();
         break;

       case 'h':


Encoders.ino: Don't try to drive the motors at full speed.

--- examples/Encoders/Encoders.ino
+++ examples/Encoders/Encoders.ino
@@ -106,11 +106,11 @@

   if (buttonA.isPressed())
   {
-    motors.setSpeeds(400, 400);
+    motors.setSpeeds(100, 100);
   }
   else if (buttonC.isPressed())
   {
-    motors.setSpeeds(-400, -400);
+    motors.setSpeeds(-100, -100);
   }
   else
   {


Yun example: change one Serial -> Console

--- examples/mqtt_yun/mqtt_yun.ino
+++ examples/mqtt_yun/mqtt_yun.ino
@@ -95,7 +95,7 @@

   // ping the server to keep the mqtt connection alive
   if(! mqtt.ping()) {
-    Serial.println(F("MQTT Ping failed."));
+    Console.println(F("MQTT Ping failed."));
   }

   delay(1000);


Update dht-test.ino

Update dht-test.ino

--- firmware/examples/dht-test.ino
+++ firmware/examples/dht-test.ino
@@ -29,8 +29,8 @@
 	delay(2000);

 // Reading temperature or humidity takes about 250 milliseconds!
-// Sensor readings may also be up to 2 seconds 'old' (its a very slow
-sensor)
+// Sensor readings may also be up to 2 seconds 'old' (its a
+// very slow sensor)
 	float h = dht.getHumidity();
 // Read temperature as Celsius
 	float t = dht.getTempCelcius();


thruster mixing now working correctly

thruster mixing now working correctly

--- motor_controller_with_stick/motor_controller_with_stick.ino
+++ motor_controller_with_stick/motor_controller_with_stick.ino
@@ -15,6 +15,7 @@
 const int L_EN_R = 12;
 const int R_EN_R = 13;

+const int m_factor = 2;
 Motor* m_motor_l;
 Motor* m_motor_r;

@@ -40,12 +41,10 @@

 void loop() {
   // put your main code here, to run repeatedly:
-Serial.println(analogRead(X_pin));
+  Serial.println(analogRead(X_pin));
   Serial.println(analogRead(Y_pin));
-  int axis_x = map(analogRead(X_pin), 0, 1023, 0, 255) - 128; // adjusted to calibrate joystick slightly (joystick a bit out of whack)
-  int axis_y = map(analogRead(Y_pin), 0, 1023, 0, 255) - 128;
-  //servo1.write(joyVal);
-  delay(50);
+  int axis_x = map(analogRead(X_pin), 0, 1023, 0, 255) - 127; // adjusted to calibrate joystick slightly (joystick a bit out of whack)
+  int axis_y = map(analogRead(Y_pin), 0, 1023, 0, 255) - 127;

   if (abs(axis_x) < threshold) {
     axis_x = 0;
@@ -74,8 +73,8 @@
     }
   }

-  m_motor_l->applyThrust(m_left_thrust);
-  m_motor_r->applyThrust(m_right_thrust);
+  m_motor_l->applyThrust(constrain(m_left_thrust * m_factor, -255, 255));
+  m_motor_r->applyThrust(constrain(m_right_thrust * m_factor, -255, 255));

   Serial.print("Mag: ");
   Serial.print(mag);
@@ -87,14 +86,7 @@
   Serial.print(axis_x);
   Serial.print("  y: ");
   Serial.println(axis_y);
-  delay(500);
-}
-
-int joystickMixingHack(int thrust){
-  if (thrust > 128) {
-    return 128 - (thrust - 128);
-  }
-  return thrust;
+  delay(50);
 }

 int getMagnitude(int x, int y){


custom tweaks to work better at Book Sellers location

--- servo-turning-sine-wave/servo-turning-sine-wave.ino
+++ servo-turning-sine-wave/servo-turning-sine-wave.ino
@@ -11,8 +11,8 @@
 //
 const double RADIANS_PER_DEGREE = 0.0174532925;

-const int LEFT_LIMIT = 40;
-const int RIGHT_LIMIT = 130;
+const int LEFT_LIMIT = 90;
+const int RIGHT_LIMIT = 180;

 // milliseconds to wait between servo movement: when servo is gently oscillating
 const int GENTLE_DELAY = 30;
@@ -54,13 +54,19 @@
 void loop()
 {
   // randomly determine which behavior
-  switch (random(2)) {
+  int behaviorMode = random(4);
+  Serial.print("BEHAVIOR MODE:\t");
+  Serial.println(behaviorMode);
+
+  switch (behaviorMode) {
     case 0:
-      currAngle = oscillateGently(currAngle, random(5, 10));
+    case 1:
+    case 2:
+      currAngle = oscillateGently(currAngle, random(3, 6));
       break;

-    case 1:
-      currAngle = shakeServo(currAngle, random(4));
+    case 3:
+      currAngle = shakeServo(currAngle, random(2, 4));
       break;
   }

@@ -72,16 +78,40 @@
 {
   for (int ii = 0; ii < numOscillations ; ii += 1) {
     delay(TURN_AROUND_DELAY);
-    //  Serial.println("------------------------------------------------------------");

     digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
-    angle = turnServo(myservo, angle, random(angle, RIGHT_LIMIT - SHAKE_OFFSET_ANGLE) + 1, GENTLE_DELAY);
+    int range = RIGHT_LIMIT - angle;
+    int skew = random(random(range));
+    int limit = RIGHT_LIMIT - skew;
+    angle = turnServo(myservo, angle, limit, GENTLE_DELAY);
+
+    Serial.println("---------------------------------------------------------------- RIGHT");
+    Serial.print("range: ");
+    Serial.print(range);
+    Serial.print("\tskewing: ");
+    Serial.print(skew);
+    Serial.print("\tlimit: ");
+    Serial.print(limit);
+    Serial.print("\tangle: ");
+    Serial.println(angle);

     delay(TURN_AROUND_DELAY);
-    //  Serial.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");

     digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
-    angle = turnServo(myservo, angle, random(SHAKE_OFFSET_ANGLE, angle), GENTLE_DELAY);
+    range = angle - LEFT_LIMIT;
+    skew = random(random(range));
+    limit = LEFT_LIMIT + skew;
+    angle = turnServo(myservo, angle, limit, GENTLE_DELAY);
+
+    Serial.println("---------------------------------------------------------------- LEFT");
+    Serial.print("range: ");
+    Serial.print(range);
+    Serial.print("\tskewing: ");
+    Serial.print(skew);
+    Serial.print("\tlimit: ");
+    Serial.print(limit);
+    Serial.print("\tangle: ");
+    Serial.println(angle);
   }

   return angle;


Added support to query nearby networks

Added support to query nearby networks

“/networks” page returns a JSON object of nearby network SSIDs

--- software/firmware/LogoBotEsp8266/LogoBotEsp8266.ino
+++ software/firmware/LogoBotEsp8266/LogoBotEsp8266.ino
@@ -5,7 +5,7 @@
 #include "WebPages.h"

 /* Settings you may want to configure for your LogoBot */
-#define LOGOBOT_SSID "LogobotBlue"
+#define LOGOBOT_SSID "LogobotPG"
 #define LOGOBOT_PWD "logobot1"
 #define LOGOBOT_URL "logo.bot"
 static const IPAddress apIP(192, 168, 4, 1);
@@ -155,6 +155,26 @@
   digitalWrite(led, 0);
 }

+static void handleNetworks() {
+  digitalWrite(led, 1);
+
+  int8_t netCount = WiFi.scanNetworks();
+
+  String json = "{\"response\": \"ok\"";
+  json += ", \"count\": \"" + String(netCount) + "\"";
+
+  json += ", names:[";
+  for (uint8_t i=0; i<netCount; i++) {
+    if (i > 0) json += ',';
+    json += "\"" + String(WiFi.SSID(i)) + "\"";
+  }
+  json += "]}";
+
+  server.send(200, F("application/json"), json);
+
+  digitalWrite(led, 0);
+}
+
 static void handleNotFound()
 {
   digitalWrite(led, 1);
@@ -183,7 +203,8 @@

   WiFi.mode(WIFI_AP);
   WiFi.softAPConfig(apIP, apIP, mask);
-  WiFi.softAP(LOGOBOT_SSID, LOGOBOT_PWD);
+  //WiFi.softAP(LOGOBOT_SSID, LOGOBOT_PWD);
+  WiFi.softAP(LOGOBOT_SSID);

   dnsServer.setTTL(300);
   dnsServer.setErrorReplyCode(DNSReplyCode::NonExistentDomain);
@@ -196,6 +217,7 @@
   server.on("/", handleRoot);
   server.on("/batch", handleBatch);
   server.on("/style.css", handleStyle);
+  server.on("/networks", handleNetworks);
   server.onNotFound(handleNotFound);

   server.begin();


clearer boot lights

clearer boot lights

--- drone/drone.ino
+++ drone/drone.ino
@@ -155,7 +155,7 @@
   digitalWrite(13, HIGH); //YELLOW
   digitalWrite(12, HIGH); //RED
   digitalWrite(11, HIGH); //GREEN
-  delay(1000);
+  delay(2000);
   digitalWrite(13, LOW); //YELLOW
   digitalWrite(11, LOW); //GREEN

@@ -164,7 +164,7 @@
     Serial.begin(115200);
   #endif

-  delay(500);
+  delay(2000);

   digitalWrite(13, HIGH); //YELLOW
   serialStatus("initializing motors");
@@ -199,6 +199,14 @@
   initializeReceiver();
   digitalWrite(12, LOW);

+  digitalWrite(11, HIGH); //GREEN
+  delay(500);
+  digitalWrite(11, LOW); //GREEN
+  delay(250);
+  digitalWrite(11, HIGH); //GREEN
+  delay(500);
+  digitalWrite(11, LOW); //GREEN
+  delay(250);
   digitalWrite(11, HIGH); //GREEN
 }


Some cleanup and small fixes

Some cleanup and small fixes

--- firmware/firmware.ino
+++ firmware/firmware.ino
@@ -9,9 +9,6 @@
 #define SERVERPORT  1883 // The port of the MQTT broker

 #define LED         4   // Pin controlling to the LED strip.
-#define DS18B20     5   // Pin of Dallas DS18B20 digital thermometer
-
-#define TMP_INTER   5  // Update interval of temperature given in minutes

 unsigned int i = 0;
@@ -25,29 +22,27 @@
 Adafruit_MQTT_Subscribe onoffsw = Adafruit_MQTT_Subscribe(&mqtt, "/light/1");
 Adafruit_MQTT_Publish status_mqtt = Adafruit_MQTT_Publish(&mqtt, "/light/1/status");

-// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
-// for some reason (only affects ESP8266, likely an arduino-builder bug).
-void MQTT_connect();
-
 void setup() {
   // Initialization
   pinMode(LED, OUTPUT);

-  Serial.begin(74880);
-  delay(10);
-  // Connect to WiFi access point.
-  Serial.println(); Serial.println();
-  Serial.print(F("Connecting to "));
-  Serial.println(WLAN_SSID);
+  Serial.begin(115200);
+  Serial.println();
+  Serial.println();

-  WiFi.begin(WLAN_SSID, WLAN_PASS);
-  if (WiFi.status() != WL_CONNECTED) {
+  // We start by connecting to a WiFi network
+  Serial.print("Connecting to ");
+  Serial.println(ssid);
+  WiFi.begin(ssid, pass);
+
+  while (WiFi.status() != WL_CONNECTED) {
     delay(500);
-    Serial.print(F("."));
+    Serial.print(".");
   }
-  Serial.println();
-  Serial.println(F("WiFi connected"));
-  Serial.println(F("IP address: "));
+  Serial.println("");
+
+  Serial.println("WiFi connected");
+  Serial.println("IP address: ");
   Serial.println(WiFi.localIP());

   // Setup MQTT subscription for onoff feed.
@@ -64,7 +59,7 @@
   // function definition further below.
   MQTT_connect();

-  while (mqtt.readSubscription(10000)) {
+  while (mqtt.readSubscription(1000)) {

     // Turn the strip on
     if (strcmp((char *)onoffsw.lastread, "{\"On\":1}") == 0 && !led_on) {


wake up the light after the measurements have been taken as to not have light pollution

--- firmware/firmware.ino
+++ firmware/firmware.ino
@@ -74,6 +74,9 @@
   Serial.print(F("Sensor pressure reading: "));
   Serial.println(sensor_data.pressure);

+  // wake up the led after the measurements
+  Heartbeat::start();
+
   // Startup our network.
   while (!network.init_wireless("TRYME", "Damian126No#ash!")){
     Serial.println(F("Failed connecting to wireless network, retying in 3 seconds."));


I few tweaks, the most important one flipping the -dTerm to +dTerm. It appears to be working correctly, now. (I'm not actually sure, yet, despite several tests...)

--- temp_ctrl/temp_ctrl.ino
+++ temp_ctrl/temp_ctrl.ino
@@ -21,18 +21,18 @@
 #define HEATER_PIN 8

 #define SAMPLE_DELAY_MS 50L
-#define PRINT_DELAY_MS 1000L
-#define HEATER_PERIOD_MS 5000L
-#define PID_UPDATE_PERIOD_MS 5000L
+#define PRINT_DELAY_MS 3000L
+#define HEATER_PERIOD_MS 1500L
+#define PID_UPDATE_PERIOD_MS 15000L

 //#define OPEN_LOOP_MODE
 #define PID_MODE

 #	define DUTY_INIT 0.0

-#define PGAIN 1.1
-#define IGAIN 0.01
-#define DGAIN 0
+#define PGAIN 1
+#define IGAIN 0
+#define DGAIN 10
 #define IMIN -10000 // arbitrarily large min and max so they don't have effect, for now
 #define IMAX 10000

@@ -134,7 +134,7 @@
 	dTerm = pid->dGain * (pid->dState - pos);
 	pid->dState = pos;

-	return pTerm - dTerm + iTerm;
+	return pTerm + iTerm + dTerm;
 }

 #define TEMPERATURE_DATA_POINT_COUNT 10


Resolved #9 network connection LED

Resolved #9 network connection LED

--- telephone/telephone.ino
+++ telephone/telephone.ino
@@ -10,7 +10,8 @@
 const int ASTERISK_PIN = A3;
 const int NUMBER_SIGN_PIN = A4;
 const int PLUS_PIN = A5;
-const int RING_PIN = 4;
+const int NO_NETWORK_LED_PIN = 13;
+const int RING_PIN = 5;
 const int AUTO_START_GSM_PIN = 8;

 // Should be 25Hz, but 31 is the arduino's minimum.
@@ -229,9 +230,11 @@
   pinMode(ASTERISK_PIN, INPUT);
   pinMode(NUMBER_SIGN_PIN, INPUT);
   pinMode(PLUS_PIN, INPUT);
+  pinMode(NO_NETWORK_LED_PIN, OUTPUT);
   pinMode(RING_PIN, OUTPUT);
   pinMode(AUTO_START_GSM_PIN, OUTPUT);
   delay(100);
+  digitalWrite(NO_NETWORK_LED_PIN, HIGH);
   digitalWrite(AUTO_START_GSM_PIN, HIGH);

   buttonHandset.setHandler(pickedUpHandler);
@@ -253,6 +256,7 @@
     }
     delay(1000);
   }
+  digitalWrite(NO_NETWORK_LED_PIN, LOW);
 }

 void loop() {


optimized ultrasonic reading * pulseIn() will block the main loop for 1sec max if the ultrasonic antenna is covered by something * ultrasonic read is time consuming, it's better to be a run_once job, otherwise following commands' result will be wrong if we read too early and main loop is blocked at the ultrasonic reading.

--- Firmware/Source/v1.2/grove_pi_v1_2_6/grove_pi_v1_2_6.ino
+++ Firmware/Source/v1.2/grove_pi_v1_2_6/grove_pi_v1_2_6.ino
@@ -42,7 +42,7 @@
 int index=0;
 int flag=0;
 int i;
-byte val=0,b[21],float_array[4],dht_b[21];
+byte val=0,b[21],float_array[4],dht_b[21],ultrasonic_b[3];
 unsigned char dta[21];
 int length;
 int aRead=0;
@@ -138,20 +138,24 @@
     //Ultrasonic Read
     else if(cmd[0]==7)
     {
-      pin=cmd[1];
-      pinMode(pin, OUTPUT);
-      digitalWrite(pin, LOW);
-      delayMicroseconds(2);
-      digitalWrite(pin, HIGH);
-      delayMicroseconds(5);
-      digitalWrite(pin,LOW);
-      pinMode(pin,INPUT);
-      dur = pulseIn(pin,HIGH);
-      RangeCm = dur/29/2;
-      b[1]=RangeCm/256;
-      b[2]=RangeCm%256;
-      //Serial.println(b[1]);
-      //Serial.println(b[2]);
+      if(run_once)
+      {
+          pin=cmd[1];
+          pinMode(pin, OUTPUT);
+          digitalWrite(pin, LOW);
+          delayMicroseconds(2);
+          digitalWrite(pin, HIGH);
+          delayMicroseconds(5);
+          digitalWrite(pin,LOW);
+          pinMode(pin,INPUT);
+          dur = pulseIn(pin,HIGH,50000); //limit the timeout to avoid blocking the program 1s when ranger is covered.
+          RangeCm = dur/29/2;
+          ultrasonic_b[1]=RangeCm/256;
+          ultrasonic_b[2]=RangeCm%256;
+          //Serial.println(b[1]);
+          //Serial.println(b[2]);
+          run_once = 0;
+      }
     }
     //Firmware version
     else if(cmd[0]==8)
@@ -745,15 +749,23 @@
 {
   if(cmd[0] == 1)
     Wire.write(val);
-  if(cmd[0] == 3 || cmd[0] == 7 || cmd[0] == 56)
+  if(cmd[0] == 3 || cmd[0] == 56)
     Wire.write(b, 3);
+  if(cmd[0] == 7)
+  {
+    Wire.write(ultrasonic_b, 3);
+    cmd[0] = 0;
+  }
   if(cmd[0] == 8 || cmd[0] == 20)
     Wire.write(b, 4);
   if(cmd[0] == 30)
     Wire.write(b, 9);
-  if(cmd[0] == 40)
+  if(cmd[0] == 40)
+  {
     Wire.write(dht_b, 9);
-
+    cmd[0] = 0;
+  }
+
   if(cmd[0]==21)
   {
     Wire.write(b,21);


displayLuH drafted

displayLuH drafted

--- hal100/hal100.ino
+++ hal100/hal100.ino
@@ -19,9 +19,9 @@
   http://www.arduino.cc/en/Tutorial/TFTDisplayText

-Motor 1 = "L" Motor
-Motor 2 = "C1" Motor "Cold"
-Motor 3 = "C2 Motor "Hot"
+  Motor 1 = "L" Motor
+  Motor 2 = "C1" Motor "Cold"
+  Motor 3 = "C2 Motor "Hot"

 */
 #include "proto/device_id.h"
@@ -34,8 +34,8 @@

 //Bell icon size: 16W*16H
 const unsigned char bell [] PROGMEM = {
-0x01, 0x80, 0x03, 0xc0, 0x0f, 0xf0, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc,
-0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0x3f, 0xfc,
+  0x01, 0x80, 0x03, 0xc0, 0x0f, 0xf0, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc,
+  0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0x3f, 0xfc,
 };

 // TFT display CS, RS and RST pins definition for Mega2560
@@ -80,8 +80,8 @@

 boolean presentValue = false;

- String EnteredFreqString, TuningFreqString;
- String DisplayValueLstring;
+String EnteredFreqString, TuningFreqString;
+String DisplayValueLstring;

 int i;

@@ -91,17 +91,17 @@
 const byte COLS = 4; // Four columns
 // Define the Keymap
 char keys[ROWS][COLS] = {
-// Buttons association 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8 9=9 0=0 *=Led OFF #=Led ON
-// TOP Buttons  C c L l
-//Buttons in middle H U D S
-
-// COL0-pin1, COL1-pin2, COL2-pin3, COL3-pin4
-  {'S', '1', '2', '3'}, // ROW0-pin5
+  // Buttons association 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8 9=9 0=0 *=Led OFF #=Led ON
+  // TOP Buttons  C c L l
+  //Buttons in middle H U D S
+
+  // COL0-pin1, COL1-pin2, COL2-pin3, COL3-pin4
+  {'S', '1', '2', '3'}, // ROW0-pin5
   {'K', '4', '5', '6'}, // ROW1-pin6
-  {'U', '7', '8', '9'}, // ROW2-pin7
+  {'U', '7', '8', '9'}, // ROW2-pin7
   {'D', '*', '0', '#'}, // ROW3-pin8
   {'c', 'C', 'h', 'H'}  // ROW4-pin9
-
+
 };

 // Connect keypad ROW0 Pad pin ->> 5=30 <<- pin Mega, ROW1 6=32, ROW2 7=23, ROW3 8=25, ROW4 9=27
@@ -116,30 +116,30 @@
 void busReceiver(char cmd, uint8_t length, const TCommand *payload) {
   switch (cmd) {
     case cmdStatus: {
-      Serial.print("cnt=");
-      Serial.print(payload->status.cnt);
-      Serial.print(", Value fwd=");
-      Serial.print(payload->status.adc.fwd);
-      Serial.print(", Value rfl=");
-      Serial.println(payload->status.adc.rfl);
-
-      float rfl = payload->status.adc.rfl;
-      float fwd = payload->status.adc.fwd;
-      float p = (rfl / fwd);
-      valueSWR = (1 + p) / (1 - p);
-
-      valueRotateL = payload->status.pos.lPos;
-      valueRotateC1 = payload->status.pos.c1Pos;
-      valueRotateC2 = payload->status.pos.c2Pos;
-      isBusy = payload->status.flags > 0;
-
-      displayRefresh = true;
-      break;
-    }
+        Serial.print("cnt=");
+        Serial.print(payload->status.cnt);
+        Serial.print(", Value fwd=");
+        Serial.print(payload->status.adc.fwd);
+        Serial.print(", Value rfl=");
+        Serial.println(payload->status.adc.rfl);
+
+        float rfl = payload->status.adc.rfl;
+        float fwd = payload->status.adc.fwd;
+        float p = (rfl / fwd);
+        valueSWR = (1 + p) / (1 - p);
+
+        valueRotateL = payload->status.pos.lPos;
+        valueRotateC1 = payload->status.pos.c1Pos;
+        valueRotateC2 = payload->status.pos.c2Pos;
+        isBusy = payload->status.flags > 0;
+
+        displayRefresh = true;
+        break;
+      }
     case cmdDebug: {
-      Serial.write((char *)payload, length);
-      break;
-    }
+        Serial.write((char *)payload, length);
+        break;
+      }
   }
 }

@@ -159,25 +159,25 @@
   // Displays SWR
   TFTscreen.stroke(0, 255, 0);                      // set the font color
   TFTscreen.setTextSize(2);                         // set the font size 2
-  TFTscreen.text("SWR", 5, 10);                     // write the text to coordinates
+  TFTscreen.text("SWR", 5, 10);                     // write the text to coordinates
   // Displays L
   TFTscreen.stroke(0, 255, 0);                      // set the font color
   TFTscreen.setTextSize(2);                         // set the font size 2
-  TFTscreen.text("L", 5, 40);                     // write the text to coordinates
+  TFTscreen.text("L", 5, 40);                     // write the text to coordinates
   // Displays C1
-  TFTscreen.stroke(0, 255, 0);                      // set the font color
+  TFTscreen.stroke(0, 255, 0);                      // set the font color
   TFTscreen.setTextSize(2);                         // set the font size 2
   TFTscreen.text("C1", 5, 60);                     // write the text to coordinates
   // Displays C2
-  TFTscreen.stroke(0, 255, 0);                      // set the font color
+  TFTscreen.stroke(0, 255, 0);                      // set the font color
   TFTscreen.setTextSize(2);                         // set the font size 2
-  TFTscreen.text("C2", 5, 80);                     // write the text to coordinates
+  TFTscreen.text("C2", 5, 80);                     // write the text to coordinates

   keypad.addEventListener(keypadEvent);             //add an event listener for this keypad
 }

 //void SetFrequencyStage1() {
-	// STAGE 1 tuning process
+// STAGE 1 tuning process
 //	calculateC();                                     // calculate C value at selected frequency
 //	calculateStepsC();                                // calculate steps needed to move C to value C
 //	CmoveStage1();                                    // send command to nano to move motor "C" to C step value
@@ -187,15 +187,15 @@
 //	EraseDisplayC1(), EraseDisplayL();                 // clear previous values L and C at display
 //	displayC1(), displayL();                           // display current values L and C at display
 //	mechSetPosition(round (valueRotateL), round (valueRotateC1), round (valueRotateC2));
-	// End STAGE 1 tuning process
+// End STAGE 1 tuning process
 //}

 // Pre-STAGE 1 (coarse tuning process) cleanups and displays - will be used later
 void SetFrequency() {                               // when # pressed - sets frequency value at the bottom of the screen
   eraseFreqTopScreen();                             // clear previously entered drequesncy at display top
-  eraseEnteredFrequency();                          // clear entered frequency at display bottom
+  eraseEnteredFrequency();                          // clear entered frequency at display bottom
   displayFreqTopScreen();                           // display desired frequesncy at display top
-//  SetFrequencyStage1();
+  //  SetFrequencyStage1();
 }

@@ -261,8 +261,8 @@
 }

 void displaySWRvalue() {                                    // process to display SWR values
-    EraseDisplaySWR();
-    displaySWR();
+  EraseDisplaySWR();
+  displaySWR();
 }

 void displaySWR() {                                         // display SWR values
@@ -327,6 +327,24 @@
   TFTscreen.stroke(0, 20, 20);
   TFTscreen.setTextSize(2);
   TFTscreen.text(DisplayValueC2, 40, 80);
+}
+
+void displayLuH() {
+  double stepsToMh(float x) {
+    return  3.2408606623203362e-001 * pow(x, 0)
+            +  4.8175734249036963e-005 * pow(x, 1)
+            + -8.2394558534492893e-009 * pow(x, 2)
+            +  4.1381892772191581e-012 * pow(x, 3)
+            + -5.0628320718901775e-016 * pow(x, 4)
+            +  3.2564586259750260e-020 * pow(x, 5)
+            + -1.1101886921087241e-024 * pow(x, 6)
+            +  1.3237902692887521e-029 * pow(x, 7)
+            +  3.9488291689952899e-034 * pow(x, 8)
+            + -1.8793946779017113e-038 * pow(x, 9)
+            +  3.2823426065013548e-043 * pow(x, 10)
+            + -2.7820892583909193e-048 * pow(x, 11)
+            +  9.4929814793314678e-054 * pow(x, 12);
+  }
 }

 void eraseFrequency() {                         // when * pressed - erases entered frequency bottom of the screen
@@ -370,7 +388,7 @@
 //}

 //void calculateStepsC() {                        // calculate needed steps for C
-  // Process for linear capacitor with 44-408 pF - need to ajust or change for different capacitor
+// Process for linear capacitor with 44-408 pF - need to ajust or change for different capacitor
 //  float totalStepsC = 2964;
 //  float pFmin = 20;
 //  float pFmax = 200;
@@ -388,8 +406,8 @@
 //}

 //void calculateStepsL() {                        // calculate needed steps for L
- // Process for non-linear variable inductor - need to ajust or change for different inductor
- // y = -0.0299x2 + 1.3867x + 0.5894
+// Process for non-linear variable inductor - need to ajust or change for different inductor
+// y = -0.0299x2 + 1.3867x + 0.5894
 // float totalStepsL = 2964;                                                              // total motor steps for 1 rotation
 // float LturnsRequred = ( -0.0299 * valueL * valueL ) + ( 1.3867 * valueL ) + 0.5894;    // poly math
 // valueRotateL = LturnsRequred * totalStepsL;
@@ -406,12 +424,12 @@

 void sendStatusRequest() {
   static const unsigned long REFRESH_INTERVAL = 100; // ms
-    static unsigned long lastRefreshTime = 0;
-    if(millis() - lastRefreshTime >= REFRESH_INTERVAL)
-    {
-      lastRefreshTime = millis();
-      mechSendStatusRequest();
-    }
+  static unsigned long lastRefreshTime = 0;
+  if (millis() - lastRefreshTime >= REFRESH_INTERVAL)
+  {
+    lastRefreshTime = millis();
+    mechSendStatusRequest();
+  }
 }

@@ -452,13 +470,13 @@
           mechFineTune();
           break;

-//        case 'U':                           // calibrate both motors
-//          mechCalibrate(channelC1);
-//          break;
-//        case 'D':                           // calibrate both motors
-//          mechCalibrate(channelL);
-//          break;
-
+          //        case 'U':                           // calibrate both motors
+          //          mechCalibrate(channelC1);
+          //          break;
+          //        case 'D':                           // calibrate both motors
+          //          mechCalibrate(channelL);
+          //          break;
+
       }
   }
 }
@@ -476,12 +494,12 @@
     //                                               entering required frequency at screen bottom
     if (presentValue != true) {
       /*
-      EnteredFreqString = EnteredFreqString + key;
-      int numLength = EnteredFreqString.length();
-      EnteredFreqString.toCharArray(enteredFreq, 6);
-      TFTscreen.stroke(0, 255, 0);
-      TFTscreen.setTextSize(2);
-      TFTscreen.text(enteredFreq, 50, 110);
+        EnteredFreqString = EnteredFreqString + key;
+        int numLength = EnteredFreqString.length();
+        EnteredFreqString.toCharArray(enteredFreq, 6);
+        TFTscreen.stroke(0, 255, 0);
+        TFTscreen.setTextSize(2);
+        TFTscreen.text(enteredFreq, 50, 110);
       */
     }
   }
@@ -511,5 +529,5 @@
     displayRefresh = false;
   }

-
-}
+
+}


JSONデータ送信タイミングを修正

JSONデータ送信タイミングを修正

--- Arduino/Waffle_GroveTempHumiSensor/Waffle_GroveTempHumiSensor.ino
+++ Arduino/Waffle_GroveTempHumiSensor/Waffle_GroveTempHumiSensor.ino
@@ -1,4 +1,5 @@
 #include <ArduinoJson.h>
+#define DHT11_PIN 0      // ADC0

 // Memory pool for JSON object tree.
 // Inside the brackets, 200 is the size of the pool in bytes.
@@ -6,7 +7,7 @@
 StaticJsonBuffer<200> jsonBuffer;
 JsonObject& json = jsonBuffer.createObject();

-#define DHT11_PIN 0      // ADC0
+int sensorValue = 0;

 byte read_dht11_dat()
 {
@@ -77,10 +78,12 @@
         Serial.println("DHT11 checksum error");
     }

-    for(i=0; i<50; i++){
+    sensorValue = dht11_dat[0]*10.24;
+
+    for(i=0; i<30; i++){
       json["humdity"] = dht11_dat[0];
       json["temperature"] = dht11_dat[2];
-      json["A0"] = dht11_dat[0]*10.23;
+      json["A0"] = sensorValue;
       json.printTo(Serial);
       Serial.println();
     }


Now it starts a new data log each time it is powered up

Big Changes:
1) Makes a new data log each time it is powered up rather than appending to the old one.
2) Uses the CSV file format (Comma Separated Values) for easier use in programs like excel and others.
3) First column contains the Date & Time with a space inbetween (I found Excel & Python parsed this date time format better)
     ^ This is easy to switch back (see the note in the get_date_time_string function)

Improvements:
1) Data log files are given the correct date created and date modified file metadata (shows up in file explorer / finder)
2) Temp sensors will now show NAN (Not a number) in the log if one somehow becomes disconnected or stops working.
3) Made the printing of the date & time much neater using the 'sprinf' c function.

--- OpenCTD_Feather_Adalogger/OpenCTD_master_m0/OpenCTD_master_m0.ino
+++ OpenCTD_Feather_Adalogger/OpenCTD_master_m0/OpenCTD_master_m0.ino
@@ -20,11 +20,12 @@
 RTC_DS3231 rtc; //define real-time clock

 const int chipSelect = 4; //sets chip select pin for SD card reader
+char datalogFileName[12];

 /* This integer specifies how high accuracy you want your pressure sensor to be (oversampling resolution).
- * Ok values: 256, 512, 1024, 2048, or 4096 (Higher = more accuracy but slower sampling frequency**)
+   Ok values: 256, 512, 1024, 2048, or 4096 (Higher = more accuracy but slower sampling frequency**)
  * ** There is no reason not to use the highest accuracy. This is because the datalogging rate is set by the
- * sampling/response frequency of the ec sensor [default = 1 sec] (this is to avoid the case where both sensors send data at the same time). */
+   sampling/response frequency of the ec sensor [default = 1 sec] (this is to avoid the case where both sensors send data at the same time). */
 #define PRESSURE_SENSOR_RESOLUTION 4096
 MS_5803 sensor = MS_5803(PRESSURE_SENSOR_RESOLUTION); // Define pressure sensor.

@@ -36,9 +37,9 @@
 double pressure_abs; //define absolute pressure variable

 /* This integer specifies how high resolution you want your temperature sensors to be.
- * Ok values: 9,10,11,12 (Higher = more accuracy but slower sampling frequency**)
+   Ok values: 9,10,11,12 (Higher = more accuracy but slower sampling frequency**)
  * ** There is no reason not to use the highest accuracy. This is because the datalogging rate is set by the
- * sampling/response frequency of the ec sensor [default = 1 second] (this is to avoid the case where both sensors send data at the same time). */
+   sampling/response frequency of the ec sensor [default = 1 second] (this is to avoid the case where both sensors send data at the same time). */
 #define TEMP_SENSOR_RESOLUTION 12

 //Declare global temperature variables.
@@ -57,7 +58,7 @@
 byte received_from_sensor = 0; // How many characters have been received.
 byte string_received = 0; // Whether it received a string from the EC circuit.

-#define EC_SAMPLING_FREQUENCY 1 // Set the sampling frequency in seconds (no decimals) of the conductivity probe (which by extension sets the overall frequency of logging to the sd).
+#define EC_SAMPLING_FREQUENCY 1 // Set the requested sampling frequency of the conductivity probe in seconds (NO Decimals) (this by extension sets the overall frequency of logging).

 void setup () {

@@ -74,9 +75,13 @@
   while (!SD.begin(chipSelect)) {

     Serial.println("Card failed, or not present");
-    return;
-
-  }
+    delay(1000);
+
+  }
+
+  // This funny function allows the sd-library to set the correct file created & modified dates for all sd card files.
+  // (See the SDCardDateTimeCallback function defined at the end of this file)
+  SdFile::dateTimeCallback(SDCardDateTimeCallback);

   Serial.println("card initialized.");

@@ -89,13 +94,16 @@

   }

-  File dataFile = SD.open("datalog.txt", FILE_WRITE);
+  get_numbered_filename(datalogFileName, "LOG", "CSV");
+
+  Serial.print("Writing to datalog: ");
+  Serial.println(datalogFileName);
+
+  File dataFile = SD.open(datalogFileName, FILE_WRITE);

   if (dataFile) {

-    dataFile.println("");
-    dataFile.println("=== New Cast ===");
-    dataFile.println("");
+    dataFile.println("Date Time,Pressure,Temp A,Temp B,Temp C,Conductivity");
     dataFile.close();

   }
@@ -109,17 +117,19 @@

   }

-  delay(250);       // Wait a quarter second to continue.
+  delay(250);   // Wait a quarter second to continue.

   //Initialize sensors
+  Serial.println("-- Pressure Sensor Info: --");
   sensor.initializeMS_5803(); // Initialize pressure sensor
-
+  Serial.println("---------------------------");
+
   sensors.begin();  // Intialize the temperature sensors.
   sensors.setResolution(TEMP_SENSOR_RESOLUTION);  // Set the resolution (accuracy) of the temperature sensors.
   sensors.requestTemperatures(); // on the first pass request all temperatures in a blocking way to start the variables with true data.
-  tempA = sensors.getTempCByIndex(0);
-  tempB = sensors.getTempCByIndex(1);
-  tempC = sensors.getTempCByIndex(2);
+  tempA = get_temp_c_by_index(0);
+  tempB = get_temp_c_by_index(1);
+  tempC = get_temp_c_by_index(2);
   sensors.setWaitForConversion(false);  // Now tell the Dallas Temperature library to not block this script while it's waiting for the temperature mesurement to happen

   ecSerial.begin(9600); // Set baud rate for conductivity circuit.
@@ -134,17 +144,17 @@
   } while (EC_data[1] != 'I'); // Keep looping until the ecSerial has sent the board info string (also indicating it has booted up, I think...)

   Serial.print("EC Board Info (Format: ?I,[board type],[Firmware Version]) -> "); Serial.println(EC_data);
-
+
   delay(10);
   ecSerial.write('C');  // Tell electrical conductivity board to continously ("C") transmit mesurements ...
   ecSerial.write(',');  //
   ecSerial.print(EC_SAMPLING_FREQUENCY);    // ... every x seconds (here x is the EC_SAMPLING_FREQUENCY variable)
-  ecSerial.write('\r'); // Finish the command with the carrage return character.
-
+  ecSerial.write('\r'); // Finish the command with the carrage return character.
+
   received_from_sensor = ecSerial.readBytesUntil('\r', EC_data, 10); // keep reading the reply until the return character is recived (or it gets to be 10 characters long, which shouldn't happen)
   EC_data[received_from_sensor] = 0; // Null terminate the data by setting the value after the final character to 0.
   Serial.print("EC Frequency Set Sucessfully? -> "); Serial.println(EC_data);
-
+  Serial.println("--- Starting Datalogging ---");
 }

 void loop () {
@@ -163,20 +173,20 @@

     // Read the temperature sensors.
     if (millis() - tempADelayStartTime > requiredMesurementDelay) { // wait for conversion to happen before attempting to read temp probe A's value;
-      tempA = sensors.getTempCByIndex(0);
+      tempA = get_temp_c_by_index(0);
       sensors.requestTemperaturesByIndex(0);  // request temp sensor A start mesuring so it can be read on the following loop (if enough time elapses).
       tempADelayStartTime = millis();  // mark when we made the request to make sure we wait long enough before reading it.
     }

     if (millis() - tempBDelayStartTime > requiredMesurementDelay) { // wait for conversion to happen before attempting to read temp probe B's value;
-      tempB = sensors.getTempCByIndex(1);
+      tempB = get_temp_c_by_index(1);
       sensors.requestTemperaturesByIndex(1);  // request temp sensor B start mesuring so it can be read on the following loop (if enough time elapses).
       tempBDelayStartTime = millis();  // mark when we made the request to make sure we wait long enough before reading it.
     }

     if (millis() - tempCDelayStartTime > requiredMesurementDelay) { // wait for conversion to happen before attempting to read temp probe C's value;
-      tempC = sensors.getTempCByIndex(2);
+      tempC = get_temp_c_by_index(2);
       sensors.requestTemperaturesByIndex(2);  // request temp sensor C start mesuring so it can be read on the following loop (if enough time elapses).
       tempCDelayStartTime = millis(); // mark when we made the request to make sure we wait long enough before reading it.
     }
@@ -185,185 +195,36 @@
     pressure_abs = sensor.pressure();

     DateTime now = rtc.now(); //check RTC
-
-    //output readings to serial monitor. A whole mess of if/else statements to keep numbers formatted correctly
-    Serial.print(now.year(), DEC);
-    Serial.print('/');
-
-    if (now.month() < 10) {
-
-      Serial.print(0);
-      Serial.print(now.month(), DEC);
-
-    }
-
-    else {
-
-      Serial.print(now.month(), DEC);
-
-    }
-
-    Serial.print('/');
-
-    if (now.day() < 10) {
-
-      Serial.print(0);
-      Serial.print(now.day(), DEC);
-
-    }
-
-    else {
-
-      Serial.print(now.day(), DEC);
-
-    }
-
-    Serial.print("  ");
-
-    if (now.hour() < 10) {
-
-      Serial.print(0);
-      Serial.print(now.hour(), DEC);
-
-    }
-
-    else {
-
-      Serial.print(now.hour(), DEC);
-
-    }
-
-    Serial.print(':');
-
-    if (now.minute() < 10) {
-
-      Serial.print(0);
-      Serial.print(now.minute(), DEC);
-
-    }
-
-    else {
-
-      Serial.print(now.minute(), DEC);
-
-    }
-
-    Serial.print(':');
-
-    if (now.second() < 10) {
-
-      Serial.print(0);
-      Serial.print(now.second(), DEC);
-
-    }
-
-    else {
-
-      Serial.print(now.second(), DEC);
-
-    }
-
-    Serial.print("  ");
+    char dateTimeString[40];
+    get_date_time_string(dateTimeString, now);
+
+    //output readings to serial
+    Serial.print(dateTimeString);
+    Serial.print(",");
     Serial.print(pressure_abs);
-    Serial.print("  ");
+    Serial.print(",");
     Serial.print(tempA);
-    Serial.print("  ");
+    Serial.print(",");
     Serial.print(tempB);
-    Serial.print("  ");
+    Serial.print(",");
     Serial.print(tempC);
-    Serial.print("  ");
+    Serial.print(",");
     Serial.println(EC);

-    //output readings to data file. A whole mess of if/else statements to keep numbers formatted correctly
-    File dataFile = SD.open("datalog.txt", FILE_WRITE);
-
+    //output readings to data file.
+    File dataFile = SD.open(datalogFileName, FILE_WRITE);
     if (dataFile) {

-      dataFile.print(now.year(), DEC);
-      dataFile.print('/');
-
-      if (now.month() < 10) {
-
-        dataFile.print(0);
-        dataFile.print(now.month(), DEC);
-
-      }
-
-      else {
-
-        dataFile.print(now.month(), DEC);
-
-      }
-
-      dataFile.print('/');
-
-      if (now.day() < 10) {
-
-        dataFile.print(0);
-        dataFile.print(now.day(), DEC);
-
-      }
-
-      else {
-
-        dataFile.print(now.day(), DEC);
-
-      }
-
-      dataFile.print("  ");
-
-      if (now.hour() < 10) {
-
-        dataFile.print(0);
-        dataFile.print(now.hour(), DEC);
-
-      }
-
-      else {
-
-        dataFile.print(now.hour(), DEC);
-
-      }
-
-      dataFile.print(':');
-
-      if (now.minute() < 10) {
-
-        dataFile.print(0);
-        dataFile.print(now.minute(), DEC);
-
-      }
-
-      else {
-
-        dataFile.print(now.minute(), DEC);
-
-      }
-
-      dataFile.print(':');
-
-      if (now.second() < 10) {
-
-        dataFile.print(0);
-        dataFile.print(now.second(), DEC);
-
-      }
-
-      else {
-
-        dataFile.print(now.second(), DEC);
-
-      }
-
-      dataFile.print("  ");
+      dataFile.print(dateTimeString);
+      dataFile.print(",");
       dataFile.print(pressure_abs);
-      dataFile.print("  ");
+      dataFile.print(",");
       dataFile.print(tempA);
-      dataFile.print("  ");
+      dataFile.print(",");
       dataFile.print(tempB);
-      dataFile.print("  ");
+      dataFile.print(",");
       dataFile.print(tempC);
-      dataFile.print("  ");
+      dataFile.print(",");
       dataFile.println(EC);
       dataFile.close();

@@ -375,6 +236,51 @@

 }

+void get_numbered_filename(char* outStr, char* filePrefix, char* fileExtension) {
+
+  // Make base filename
+  sprintf(outStr, "%s000.%s", filePrefix, fileExtension);
+  int namelength = strlen(outStr);
+  if (namelength > 12) Serial.println("Error: filename too long. Shorten your filename to < 5 characters (12 chars total w number & file extension) !");
+
+  // Keep incrementing the number part of filename until we reach an unused filename
+  int i = 1;
+  while (SD.exists(outStr)) {  // keep looping if filename already exists on card. [If the filename doesn't exist, the loop exits, so we found our first unused filename!]
+
+    int hundreds = i / 100;
+    outStr[namelength - 7] = '0' + hundreds;
+    outStr[namelength - 6] = '0' + (i / 10) - (hundreds * 10);
+    outStr[namelength - 5] = '0' + i % 10;
+    i++;
+
+  }
+
+}
+
+void get_date_time_string(char* outStr, DateTime date) {
+  // outputs the date as a date time string,
+  sprintf(outStr, "%02d/%02d/%02d %02d:%02d:%02d", date.month(), date.day(), date.year(), date.hour(), date.minute(), date.second());
+  // Note: If you would like the date & time to be seperate columns chabge the space in the formatting string to a comma - this works because the file type is CSV (Comma Seperated Values)
+}
+
+void SDCardDateTimeCallback(uint16_t* date, uint16_t* time) // This funny function allows the sd-library to set the correct file created & modified dates for all sd card files (As would show up in the file explorer on your computer)
+{
+  DateTime now = rtc.now();
+  *date = FAT_DATE(now.year(), now.month(), now.day());
+  *time = FAT_TIME(now.hour(), now.minute(), now.second());
+}
+
+float get_temp_c_by_index(int sensor_index) {
+
+  float value = sensors.getTempCByIndex(sensor_index);
+  if (value == DEVICE_DISCONNECTED_C) {
+    return NAN; // Return Not a Number (NAN) to indicate temperature probe has error or is disconnected.
+  } else {
+    return value; // otherwise return the measured value.
+  }
+
+}
+
 void parse_data() { // Parses data from the EC Circuit.

   EC = strtok(EC_data, ",");


Better serial messages for starting the log

--- OpenCTD_Feather_Adalogger/OpenCTD_master_m0/OpenCTD_master_m0.ino
+++ OpenCTD_Feather_Adalogger/OpenCTD_master_m0/OpenCTD_master_m0.ino
@@ -102,10 +102,13 @@
   File dataFile = SD.open(datalogFileName, FILE_WRITE);

   if (dataFile) {
-
+    Serial.println("====================================================");
+    Serial.println("Date Time,Pressure,Temp A,Temp B,Temp C,Conductivity");
     dataFile.println("Date Time,Pressure,Temp A,Temp B,Temp C,Conductivity");
     dataFile.close();

+  } else {
+    Serial.println("Err: Can't open datalog!")
   }

   //Initialize real-time clock


Fix silly pointer rather than string bug in debug output.

--- test/PoE-test/tussendeur-asis-2017/tussendeur-asis-2017.ino
+++ test/PoE-test/tussendeur-asis-2017/tussendeur-asis-2017.ino
@@ -419,7 +419,7 @@

 void openDoor() {
   char msg[255];
-  snprintf(msg, sizeof(msg), "[%p] Engaging solenoid", pname);
+  snprintf(msg, sizeof(msg), "[%s] Engaging solenoid", pname);
   doorstate = OPEN;
   client.publish(log_topic, msg);
   Serial.println(msg);


Removed Autoconnect setting. Address is saved in BT adapter.

Signed-off-by: Cruz Monrreal II <663375bc5b4c6ed13a95cc63b2dd9f1e16363f4e@gmail.com>

--- examples/AutoConfigBluetoothForSphero/AutoConfigBluetoothForSphero.ino
+++ examples/AutoConfigBluetoothForSphero/AutoConfigBluetoothForSphero.ino
@@ -78,12 +78,9 @@
     // Save address
     sendCmd("SR," + sphero_id.substring(0, 12));

-    // Configure Bluetooth to autoreconnect
-    sendCmd("SM,3");
-
     // We're done here!
     sendCmd("---");
-    Serial.println("\nConfiguration complete!\nYou're Sphero will now autoconnect upon powerup!\n\nHave fun ^^;");
+    Serial.println("\nConfiguration complete!\nYou're Sphero's address has been saved in the Bluetooth Module\n\nHave fun ^^;");

     // Idle...
     while(true);


Get in sync with sensorState library.

Get in sync with sensorState library.

--- webservertask.ino
+++ webservertask.ino
@@ -228,12 +228,12 @@

     else if ( request->hasArg( "sensorlogging" ) ) {
       if ( !sensor.count() ) return request->send( 501, HEADER_HTML, NOT_PRESENT_ERROR_501 );
-      return request->send( 200, HEADER_HTML, sensor.logging() ? "ON" : "OFF" );
+      return request->send( 200, HEADER_HTML, sensor.isLogging() ? "ON" : "OFF" );
     }

     else if ( request->hasArg( "sensorerrorlogging" ) ) {
       if ( !sensor.count() ) return request->send( 501, HEADER_HTML, NOT_PRESENT_ERROR_501 );
-      return request->send( 200, HEADER_HTML, sensor.errorLogging() ? "ON" : "OFF" );
+      return request->send( 200, HEADER_HTML, sensor.isErrorLogging() ? "ON" : "OFF" );
     }

     else if ( request->hasArg( "sensorname" ) ) {


Changed from (deprecated) asctime to strftime.

--- webservertask.ino
+++ webservertask.ino
@@ -114,7 +114,14 @@
     AsyncResponseStream *response;
     if ( request->hasArg( "boottime" ) )
     {
-      return request->send( 200, HTML_HEADER, asctime( localtime( &systemStart.tv_sec ) ) );
+      time_t rawtime;
+      struct tm * timeinfo;
+      char buffer [25];
+
+      time (&rawtime);
+      timeinfo = localtime ( &rawtime );
+      strftime ( buffer, sizeof(buffer), "%c", timeinfo );
+      return request->send( 200, HTML_HEADER, buffer );
     }

     else if ( request->hasArg( "channelcolors" ) )


added rollover and filters

added rollover and filters

--- stabilize/stabilize.ino
+++ stabilize/stabilize.ino
@@ -13,8 +13,6 @@
 #define LOOP_LOGGING 0
 //1: enable logging in loop
 //0: disable logging in loop
-
-#define RUN_MOTORS 1

 #define MAX_FREQUENCY 50
 const long MIN_LOOP_TIME = 1000/MAX_FREQUENCY;
@@ -75,19 +73,20 @@
   return rad * 360.0/(2.0*PI/360);
 }

-float yawRollover(float yaw) {
-  static float prev = 0;
-  static float mod = 0;
-  float delta = yaw + mod - prev
-  if(delta < prev-360.0){
-    //rollover 360
-    mod = mod + 360.0;
-  } else if(delta > prev) {
-    //rollover 0
-    mod = mod - 360.0;
+float rollover(float* prev, float* mod, float value) {
+  float margin = 50;
+
+  //rollover 0
+  if(*prev - margin < 0 && value + margin > 360.0){
+    *mod = *mod - 360.0;
   }
-  prev = yaw+mod;
-  return prev;
+
+  //rollover 360
+  if(*prev + margin > 360.0 && value - margin < 0.0) {
+    *mod = *mod + 360.0;
+  }
+  *prev = value;
+  return value + *mod;
 }

 void setup() {
@@ -105,40 +104,57 @@
 }

 void loop() {
+  //filter setup
   FilterOnePole rollHighpass(HIGHPASS, rollFrequencyCutoff);
   FilterOnePole pitchHighpass(HIGHPASS, pitchFrequencyCutoff);
   FilterOnePole yawHighpass(HIGHPASS, yawFrequencyCutoff);
+
+  //rollover storage
+  float roll_mod = 0.0;
+  float pitch_mod = 0.0;
+  float yaw_mod = 0.0;
+
+  float roll_prev = 0.0;
+  float pitch_prev = 0.0;
+  float yaw_prev = 0.0;
+
+  float roll_rollover = 0.0;
+  float pitch_rollover = 0.0;
+  float yaw_rollover = 0.0;
+
   while(1) {
-    //failover tasks

-    //imu
+    //imu or failover
     if(!updateImu()) {
       logln("Something went wrong with the IMU.");
       return; //skip the cycle if the imu doesn't update correctly
     }

+    //limit cycle frequency to MAX_FREQUENCY
     static long time_last = 0;
-
-    //limit cycle frequency to MAX_FREQUENCY
     while(millis()-time_last < MIN_LOOP_TIME);
     long loop_time = millis() - time_last;
     time_last += loop_time;
-
+
+    //update rollover
+    roll_rollover = rollover(&roll_prev, &roll_mod, imu.roll);
+    pitch_rollover = rollover(&pitch_prev, &pitch_mod, imu.pitch);
+    yaw_rollover = rollover(&yaw_prev, &yaw_mod, imu.yaw);
+
     //update washout filters
-    rollHighpass.input(imu.roll);
-    pitchHighpass.input(imu.pitch);
-    yawHighpass.input(imu.yaw);
+    rollHighpass.input(roll_rollover);
+    pitchHighpass.input(pitch_rollover);
+    yawHighpass.input(yaw_rollover);

-    if(RUN_MOTORS) {
-      //sync and update motor commands
-      syncMotor(2); //roll
-      syncMotor(1); //pitch
-      syncMotor(3); //yaw
-
-      setVal(2, ANGLE, degree2rad(imu.roll)+3.14); //roll
-      setVal(1, ANGLE, degree2rad(imu.pitch)+1.5); //pitch
-      setVal(3, ANGLE, degree2rad(-imu.yaw) + 1.5); //yaw
-    }
+    //set motor commands
+    setVal(2, ANGLE, degree2rad(rollHighpass.output()) + 3.14); //roll
+    setVal(1, ANGLE, degree2rad(pitchHighpass.output()) + 1.5); //pitch
+    setVal(3, ANGLE, degree2rad(-yawHighpass.output()) + 1.5);  //yaw
+
+    //sync motor info
+    syncMotor(2); //roll
+    syncMotor(1); //pitch
+    syncMotor(3); //yaw

     logln("Compiling output...");

@@ -146,6 +162,7 @@
     ct++;

     static char string[300];
+
     //compile output
     sprintf(string, "%d,%d,%f,%f,%f,%f,%f,%f,%f,%f,%f",ct,loop_time,imu.roll,imu.pitch,imu.yaw,imu.ax,imu.ay,imu.az,getVal(1, ANGLE),getVal(2, ANGLE),getVal(3, ANGLE));


Updated PushButton example with INPUT_PULLUP

--- examples/PushButton/PushButton.ino
+++ examples/PushButton/PushButton.ino
@@ -19,7 +19,7 @@
   // initialise digital pins as outputs
   pinMode(LED1, OUTPUT);
   pinMode(LED2, OUTPUT);
-  pinMode(PUSH2, INPUT);
+  pinMode(PUSH2, INPUT_PULLUP);
   lights(0);
 }


IDEからの書き込みがエラーになるようになる問題を修正。

IDEからの書き込みがエラーになるようになる問題を修正。

--- examples/Serial2TFT/Serial2TFT.ino
+++ examples/Serial2TFT/Serial2TFT.ino
@@ -46,6 +46,9 @@

 void setup() {
   Serial.begin(115200);
+  while (!Serial) { // これがないとIDEからの書き込みがエラーになる
+    // wait for Leonardo
+  }
   pinMode(SD_SS_PIN, OUTPUT);

   tft.reset();


Dispçay mostra a versão correta

Dispçay mostra a versão correta

--- ATmega/ATmega.ino
+++ ATmega/ATmega.ino
@@ -67,7 +67,7 @@

   lcd.begin(16, 2);
   lcd.setCursor(6, 0); lcd.print("SMCP");
-  lcd.setCursor(3, 1); escreverAcentos("Versão 0.7");
+  lcd.setCursor(2, 1); escreverAcentos("Versão 0.7.1");
   emon1.current(pino_sct, calibra);
   esp8266.begin(9600);
   esp8266.println("Ligado");


CTRL-C, CTRL-D or 'Z' to interrupt operation

--- Arduino/BLuB/BLuB.ino
+++ Arduino/BLuB/BLuB.ino
@@ -10,6 +10,7 @@
 #define kBLuBVersion	"v0.08  2013-June-26  yorgle@gmail.com"

 // v0.08  2013-June-26  Autoload and Autorun added
+//			ctrl-c/ctrl-d/Z to break a running program
 //
 // v0.07  2013-June-25  PEek, POke, for RAM and EEPROM implemented
 //			auto-pinMode()
@@ -99,6 +100,7 @@
 char * gosubStack[ kNGosubs ];

 // Return values for the opcode handlers
+#define kJRInterrupt    (-7)    /* ctrl-c/break interrupted */
 #define kJRGosubStack	(-6)	/* Stack error for CAll */
 #define kJRDBZError	(-5)	/* Divide by Zero error */
 #define kJRSyntaxError	(-4)	/* general syntax erorr */
@@ -262,7 +264,6 @@
 {
   int chp = 0;

-
   // read a line or so into our buffer
   do {
     while( !Serial.available() );
@@ -271,13 +272,15 @@
     chp++;
   } while(    //Serial.available()
            buf[chp-1] != '\n'
+           && buf[chp-1] != '\r'
            && chp < maxbuf );

   // terminate the buffer
   buf[chp] = '\0';

   // strip newline
-  if( chp > 0 && buf[ chp-1 ] == '\n' ) buf[chp-1] = '\0';
+  if( chp > 0 && ( buf[ chp-1 ] == '\n' || buf[ chp-1 ] == '\r') ) { buf[chp-1] = '\0'; chp--; }
+  if( chp > 0 && ( buf[ chp-1 ] == '\n' || buf[ chp-1 ] == '\r') ) buf[chp-1] = '\0';

   if( echoback ) Serialprint( "\n" );
 }
@@ -1160,6 +1163,19 @@

 		next = evaluate_line( ln, &bufc );

+                while( Serial.available() > 0 ) {
+                  int ch = Serial.read();
+                  if( ch == 3 || ch == 4 || ch == 90 ) {
+                    // ctrl-c or ctrl-d or 'Z'
+                      next = kJRInterrupt;
+                  }
+                }
+
+                if( next == kJRInterrupt ) {
+                        Serialprintln( "Interrupt." );
+                        next = kJRStop;
+                }
+
 		if( next == kJRGosubStack ) {
 			Serialprintln( "Gosub stack error." );
 			next = kJRStop;
@@ -1359,9 +1375,10 @@
 	Serial.print( ":) " );

 	// get a line of input
+#ifdef kLocalEcho
+	getSerialLine( linebuf, kLineLen, true );
+#else
 	getSerialLine( linebuf, kLineLen, false );
-#ifdef kLocalEcho
-        Serial.println( linebuf );
 #endif

 	bptr = linebuf;


corrected encoder ids, lcd messages

corrected encoder ids, lcd messages

--- VisSynthRemote/VisSynthRemote.ino
+++ VisSynthRemote/VisSynthRemote.ino
@@ -174,7 +174,7 @@
   Serial.begin(9600);

   lcd.home();
-  lcd.println("INIT");
+  lcd.print("INIT ");

   bool success=false;

@@ -201,7 +201,7 @@

   Serial.println("RedFly init succeed.");

-  lcd.println("READY");
+  lcd.print("READY");

   pinMode(RED_LED,OUTPUT);
   digitalWrite(RED_LED,HIGH);
@@ -287,10 +287,10 @@
 #define pin_e0 53

-Encoder enc0(3,53,54,55);
-Encoder enc1(2,50,51,52);
-Encoder enc2(1,47,48,49);
-Encoder enc3(0,44,45,46);
+Encoder enc0(0,53,54,55);
+Encoder enc1(1,50,51,52);
+Encoder enc2(2,47,48,49);
+Encoder enc3(3,44,45,46);

 String buffer;
 void loop() {


add new patterns: blinking two background lights on at a time from left to right, turning lights on and off from the inside out, turning on from left to right, keeping the last light on

--- CocaCola/CocaCola.ino
+++ CocaCola/CocaCola.ino
@@ -28,6 +28,24 @@
     for (int i = 0; i < sizeof(letters); i++) {
         log('lettersAllOff i: ', i);
         digitalWrite(letters[i], PATTERN_OFF);
+        delay(none);
+    }
+}
+
+void backgroundAllOn() {
+    log('backgroundAllOn - START');
+    for (int i = 0; i < sizeof(background); i++) {
+        log('backgroundAllOn ', i);
+        digitalWrite(background[i], PATTERN_ON);
+        delay(none);
+    }
+}
+
+void backgroundAllOff() {
+    log('backgroundAllOff - START');
+    for (int i = 0; i < sizeof(background); i++) {
+        log('backgroundAllOff i: ', i);
+        digitalWrite(background[i], PATTERN_OFF);
         delay(none);
     }
 }
@@ -83,6 +101,30 @@
     }
 }

+void backgroundOffOutsideIn() {
+    log('backgroundOffOutsideIn - START');
+    for (int i = 0, j = sizeof(background) - 1; i < (sizeof(background) / 2); i++, j--) {
+        log('backgroundOffOutsideIn i: ', i);
+        digitalWrite(background[i], PATTERN_OFF);
+        delay(none);
+        log('backgroundOffOutsideIn j: ', j);
+        digitalWrite(background[j], PATTERN_OFF);
+        delay(minimal);
+    }
+}
+
+void backgroundOnInsideOut() {
+    log('backgroundOnInsideOut - START');
+    for (int i = (sizeof(background) / 2) - 1, j = i + 1; i >= 0; i--, j++) {
+        log('backgroundOnInsideOut i: ', i);
+        digitalWrite(background[i], PATTERN_ON);
+        delay(none);
+        log('backgroundOnInsideOut j: ', j);
+        digitalWrite(background[j], PATTERN_ON);
+        delay(minimal);
+    }
+}
+
 void allOff() {
     for (int i = 0; i < sizeof(Lights); i++) {
         digitalWrite(Lights[i], PATTERN_OFF);
@@ -105,10 +147,52 @@
     backgroundOffRightToLeft();
 }

-void outsideInOnInsideOutOffBackground() {
-    backgroundOnOutsideIn();
-    delay(extended);
-    backgroundOffInsideOut();
+void outsideInOnInsideOutOffBackground(int times, int endingWithLightsOn) {
+	for (int count = 0; count < times; count++) {
+      backgroundOnOutsideIn();
+      delay(extended);
+		if (count + 1 != times || !endingWithLightsOn) {
+			backgroundOffInsideOut();
+		}
+	}
+}
+
+void insideOutOnOutsideInOffBackground(int times, int endingWithLightsOn) {
+	for (int count = 0; count < times; count++) {
+	    backgroundOnInsideOut();
+	    delay(extended);
+ 		 if (count + 1 != times || !endingWithLightsOn) {
+			 backgroundOffOutsideIn();
+		 }
+	 }
+}
+
+void racingOnLeftToRight() {
+	for (int x = 0; x < sizeof(background); x++) {
+		for (int y = 0; y < sizeof(background) - x - 1; y++) {
+			digitalWrite(background[y], PATTERN_ON);
+			delay(minimal);
+			digitalWrite(background[y], PATTERN_OFF);
+		}
+
+		digitalWrite(background[sizeof(background) - x - 1], PATTERN_ON);
+		delay(minimal);
+	}
+}
+
+void blinkBackgroundPairLeftToRight() {
+	int half = sizeof(background) / 2;
+
+	for (int count = 0; count < random(5, 10); count++) {
+		for (int x = 0; x < half; x++) {
+			digitalWrite(background[x], PATTERN_ON);
+			digitalWrite(background[x + half], PATTERN_ON);
+			delay(minimal);
+
+			digitalWrite(background[x], PATTERN_OFF);
+			digitalWrite(background[x + half], PATTERN_OFF);
+		}
+	}
 }

 void blinkLetters(int times) {
@@ -121,6 +205,16 @@
     }
 }

+void blinkBackground(int times) {
+   for (int x = 0; x < times; x++) {
+       backgroundAllOff();
+       delay(blinky);
+
+       backgroundAllOn();
+       delay(blinky);
+   }
+}
+
 // Arduino loop

 void loop() {
@@ -130,9 +224,16 @@
     classicBackground();
     delay(normal);

-    outsideInOnInsideOutOffBackground();
+    outsideInOnInsideOutOffBackground(random(2, 5), true);
     delay(normal);

+	 insideOutOnOutsideInOffBackground(random(2, 5), false)
+	 delay(normal);
+
+	 racingOnLeftToRight();
+	 blinkBackground(random(5, 10));
+    delay(normal);
+
     blinkLetters(random(5, 10));

     lettersAllOff();


fix missing paren

fix missing paren

--- BinaryKeyboard.ino
+++ BinaryKeyboard.ino
@@ -192,7 +192,7 @@

 void sendVal(char val)
 {
-    if (val >= 32 || (HID_MODE && (val == HID_BS || val == HID_TAB || val == HID_ENTER)) {
+    if (val >= 32 || (HID_MODE && (val == HID_BS || val == HID_TAB || val == HID_ENTER))) {
         Keyboard.write(val);
     } else {
         Keyboard.press(KEY_LEFT_CTRL);


Sending alert SMS to 5 phone numbers when hourly rainfall is more than 25 mm/h

--- IWMIv3/IWMIv3.ino
+++ IWMIv3/IWMIv3.ino
@@ -37,15 +37,17 @@
 //FOR GSM COMS
 GSM_Module Module(SIM900);// For SIM900 GSM
 //GSM_Module Module(SM5100B);// For SM5100B GSM
-//SERVER Definitions
+String Mobile_No1 = "+94776141305";          // Mobile Number 1 which the SMS Sends
+String Mobile_No2 = "+94776141305";          // Mobile Number 2 which the SMS Sends
+String Mobile_No3 = "+94776141305";          // Mobile Number 3 which the SMS Sends
+String Mobile_No4 = "+94776141305";          // Mobile Number 4 which the SMS Sends
+String Mobile_No5 = "+94776141305";          // Mobile Number 5 which the SMS Sends
+String Test_SMS  = "IWMIMWSv3 Station initializing";    // Test content of the SMS
+int Status;
+//PhP SERVER Definitions
 //String HOST      = "lahiruwije.ddns.net";   // Host name or address of the web server
 //int    PORT      = 80;
-String Mobile_No = "+94776141305";          // Mobile Number which the SMS Sends
-String Test_SMS  = "IWMIMWSv3 Station initializing";    // Test content of the SMS
-int Status;
-
-
-
+//END OF GSM COMS

 TinyGPSPlus gps;

@@ -280,7 +282,11 @@
   *****************************************************************************************************************/
   lcd.clear();
   lcd.print(F("Sending a Test SMS"));
-  Status = Module.Send_SMS(Mobile_No, Test_SMS);
+  Status = Module.Send_SMS(Mobile_No1, Test_SMS);
+  Status = Module.Send_SMS(Mobile_No2, Test_SMS);
+  Status = Module.Send_SMS(Mobile_No3, Test_SMS);
+  Status = Module.Send_SMS(Mobile_No4, Test_SMS);
+  Status = Module.Send_SMS(Mobile_No5, Test_SMS);
   if( Status == OK ){
     lcd.setCursor(0, 2);
     lcd.print(F("SMS Sent"));
@@ -329,7 +335,16 @@
   seconds += loopMSecond/1000;
   if(++seconds > 59) seconds = 0;
   minutes += seconds/60;
-  if(++minutes > 59) minutes = 0;
+  if(++minutes > 59) {
+    minutes = 0;
+    //SMS Alert if hourly rain > 25 mm/h
+    if(rainin > 25.0){
+      sendSMS();
+    }
+    //Hourly online reporting
+    //Send temperature&humidity to PhP Server (to be enhanced)
+    //send2Server();
+  }
   minutes_5m += seconds/60;
   if(++minutes_5m > 4){
     minutes_5m = 0;
@@ -347,6 +362,8 @@

   //Report all readings
   printWeather();
+  //Send SMS alert
+  //sendSMS();
   //Turn off stat LED
   digitalWrite(STAT2, LOW);
   //Wait 1 second, and gather GPS data
@@ -658,6 +675,110 @@

 }

-
-
-
+void sendSMS()
+{
+  /*****************************************************************************************************************
+    Sending an alert SMS
+  *****************************************************************************************************************/
+  lcd.clear();
+  char sz[128];
+  sprintf(sz, "%.6f,%.6f,%02d-%02d-%02d,%02d:%02d:%02d,%.3f mm/h",gps.location.lng(),gps.location.lat(),gps.date.year(),gps.date.month(),gps.date.day(),gps.time.hour(),gps.time.minute(),gps.time.second(),rainin);//[4]
+
+  lcd.print(F("Sending an alert SMS (long,lat,date,time,hourly rainfall"));
+  Status = Module.Send_SMS(Mobile_No1, sz);
+  if( Status == OK ){
+    lcd.setCursor(0, 2);
+    lcd.print(F("SMS Sent to No1"));
+  }else{
+    lcd.clear();
+    lcd.print(F("SMS ERROR to No1: "));
+    lcd.setCursor(0, 2);
+    lcd.print(Status);
+  }
+  Status = Module.Send_SMS(Mobile_No2, sz);
+  if( Status == OK ){
+    lcd.setCursor(0, 2);
+    lcd.print(F("SMS Sent to No2"));
+  }else{
+    lcd.clear();
+    lcd.print(F("SMS ERROR to No2: "));
+    lcd.setCursor(0, 2);
+    lcd.print(Status);
+  }
+  Status = Module.Send_SMS(Mobile_No3, sz);
+  if( Status == OK ){
+    lcd.setCursor(0, 2);
+    lcd.print(F("SMS Sent to No3"));
+  }else{
+    lcd.clear();
+    lcd.print(F("SMS ERROR to No3: "));
+    lcd.setCursor(0, 2);
+    lcd.print(Status);
+  }
+  Status = Module.Send_SMS(Mobile_No4, sz);
+  if( Status == OK ){
+    lcd.setCursor(0, 2);
+    lcd.print(F("SMS Sent to No4"));
+  }else{
+    lcd.clear();
+    lcd.print(F("SMS ERROR to No4: "));
+    lcd.setCursor(0, 2);
+    lcd.print(Status);
+  }
+  Status = Module.Send_SMS(Mobile_No5, sz);
+  if( Status == OK ){
+    lcd.setCursor(0, 2);
+    lcd.print(F("SMS Sent to No5"));
+  }else{
+    lcd.clear();
+    lcd.print(F("SMS ERROR to No5: "));
+    lcd.setCursor(0, 2);
+    lcd.print(Status);
+  }
+  /*****************************************************************************************************************
+    Finished Sending an alert SMS
+  *****************************************************************************************************************/
+
+
+
+}
+
+//void send2Server(){
+///*****************************************************************************************************************
+//    Connecting to the Server and Sending Data
+//*****************************************************************************************************************/
+//  Serial.println("Connecting to Server");
+//
+//  Status = Module.POST_Data(HOST, PORT, myPressure.readTemp(), myHumidity.readHumidity());
+//
+//  if( Status == OK ){
+//
+//    Serial.print("Connecting Successful");
+//    Serial.print("    ");
+//    Serial.println(Module.Received_String());
+//
+//  }else{
+//
+//    Serial.print("TCP ERROR Code : ");
+//    Serial.print(Status);
+//    Serial.print("    ");
+//    Serial.println(Module.Received_String());
+//
+//  }
+//
+//// Listen to the Module print received data.
+//
+//  while(1){
+//
+//    do{
+//
+//        Module.Wait(1000);
+//
+//      }while(!Module.String_Received());
+//
+//      Serial.println(Module.Received_String());
+//
+//  };
+//}
+
+


Version 2.51. Module successfully makes GET request to httpbin

--- module/module.ino
+++ module/module.ino
@@ -94,7 +94,6 @@
 	WIFI.listen();
 	startConnection();
 	GET();
-
 	bool done = false;
 	while (!done) {
 		while (WIFI.available()) {
@@ -105,6 +104,7 @@
 		}
 	}

+	Serial.println();
 	RFID.listen();
 	delay(scanInterval);
 }


updated LCD display

updated LCD display

--- mwsLCD/mwsLCD.ino
+++ mwsLCD/mwsLCD.ino
@@ -195,12 +195,6 @@
   minutes_10m = gps.time.minute();
   seconds = gps.time.second();
   lastSecond = millis();
-  //Serial.println("");
-  //Serial.println(minutes);
-  //Serial.println(minutes_5m);
-  //Serial.println(minutes_10m);
-  //Serial.println(seconds);
-  //Serial.println(lastSecond);
   // attach external interrupt pins to IRQ functions
   attachInterrupt(0, rainIRQ, FALLING);
   attachInterrupt(1, wspeedIRQ, FALLING);
@@ -208,18 +202,16 @@
   // turn on interrupts
   interrupts();

-  //Serial.println("Weather Shield online!");
-
 }

 void loop()
 {
   //Keep track of which minute it is
-  if(millis() - lastSecond >= 10000)
+  if(millis() - lastSecond >= 1000)
   {
     digitalWrite(STAT1, HIGH); //Blink stat LED

-    lastSecond += 10000;
+    lastSecond += 1000;

     //Take a speed and direction reading every second for 2 minute average
     seconds_2m += 10;
@@ -227,27 +219,12 @@

     //Calc the wind speed and direction every second for 120 second to get 2 minute average
     float currentSpeed = get_wind_speed();
-    //float currentSpeed = random(5); //For testing
     int currentDirection = get_wind_direction();
     windspdavg[seconds_2m] = (int)currentSpeed;
     winddiravg[seconds_2m] = currentDirection;
-    //if(seconds_2m % 10 == 0) displayArrays(); //For testing
-
-    //Check to see if this is a gust for the minute
-//    if(currentSpeed > windgust_10m[minutes_10m])
-//    {
-//      windgust_10m[minutes_10m] = currentSpeed;
-//      windgustdirection_10m[minutes_10m] = currentDirection;
-//    }
-
-    //Check to see if this is a gust for the day
-//    if(currentSpeed > windgustms)
-//    {
-//      windgustms = currentSpeed;
-//      windgustdir = currentDirection;
-//    }
-    //Minute loop
+
     seconds += 10;
+    //Minutes loop
     if(seconds > 59)
     {
       seconds = 0;
@@ -259,12 +236,10 @@

       rainHour[minutes] = 0; //Zero out this minute's rainfall amount
       //rain5m[minutes_5m] = 0; //Zero out this 5 minutes' rain Niroshan
-//      windgust_10m[minutes_10m] = 0; //Zero out this minute's gust
+
+      //Report all readings every minute
+      printWeather();
     }
-
-    //Report all readings every second
-    printWeather();
-
     digitalWrite(STAT1, LOW); //Turn off stat LED
   }

@@ -288,13 +263,9 @@
 float get_light_level()
 {
   float operatingVoltage = analogRead(REFERENCE_3V3);
-
   float lightSensor = analogRead(LIGHT);
-
   operatingVoltage = 3.3 / operatingVoltage; //The reference voltage is 3.3V
-
   lightSensor = operatingVoltage * lightSensor;
-
   return(lightSensor);
 }

@@ -320,7 +291,6 @@
   float windSpeed = (float)windClicks / deltaTime; //3 / 0.750s = 4
   windClicks = 0; //Reset and start watching for new wind
   lastWindCheck = millis();
-  //windSpeed *= 1.492; //4 * 1.492 = 5.968MPH
   return(windSpeed);
 }

@@ -370,12 +340,6 @@
   //Calc windspeed
   float windspeedms = get_wind_speed();

-  //Calc windgustms
-  //Calc windgustdir
-  //Report the largest windgust today
-//  windgustms = 0;
-//  windgustdir = 0;
-
   //Calc windspdms_avg2m
   float temp = 0;
   for(int i = 0 ; i < 120 ; i++)
@@ -390,21 +354,6 @@
   temp /= 120;
   int winddir_avg2m = temp;

-  //Calc windgustms_10m
-  //Calc windgustdir_10m
-  //Find the largest windgust in the last 10 minutes
-//  windgustms_10m = 0;
-//  windgustdir_10m = 0;
-  //Step through the 10 minutes
-//  for(int i = 0; i < 10 ; i++)
-//  {
-//    if(windgust_10m[i] > windgustms_10m)
-//    {
-//      windgustms_10m = windgust_10m[i];
-//      windgustdir_10m = windgustdirection_10m[i];
-//    }
-//  }
-
   //Calc humidity
   float humidity = myHumidity.readHumidity();
   //float temp_h = myHumidity.readTemperature();


Update LEDHouseplantMonitor.ino

Update LEDHouseplantMonitor.ino

Typo in comment

--- 03-PlantMonitor/Code/01-LEDHouseplantMonitor/LEDHouseplantMonitor.ino
+++ 03-PlantMonitor/Code/01-LEDHouseplantMonitor/LEDHouseplantMonitor.ino
@@ -22,7 +22,7 @@
 {
 Serial.begin(9600);   // open serial over USB

-pinMode(soilPower, OUTPUT);//Set D7 as an OUTPUT
+pinMode(soilPower, OUTPUT);//Set D6 as an OUTPUT
 digitalWrite(soilPower, LOW);//Set to LOW so no power is flowing through the sensor
 }


Update main.ino

Update main.ino

--- main/main.ino
+++ main/main.ino
@@ -54,17 +54,144 @@

  midiEventPacket_t rx;
  rx = MidiUSB.read();
-    if (rx.header != 0) {
-     Serial.print("Received: ");
-      Serial.print(rx.header, HEX);
-      Serial.print("-");
-      Serial.print(rx.byte1, HEX);
-      Serial.print("-");
-      Serial.print(rx.byte2, HEX);
-      Serial.print("-");
-      Serial.println(rx.byte3, HEX);
-    }
-
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 70) { // SongLed
+      digitalWrite(SongLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 71) { // PatternLed
+      digitalWrite(PatternLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 72) { // KitLed
+      digitalWrite(KitLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 73) { // MinusLed
+      digitalWrite(MinusLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 74) { // PlusLed
+      digitalWrite(PlusLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 75) { // TempoLed
+      digitalWrite(TempoLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 76) { // PlayLed
+      digitalWrite(PlayLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 77) { // RecLed
+      digitalWrite(RecLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 78) { // BankLed
+      digitalWrite(BankLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 79) { // CrashLed
+      digitalWrite(CrashLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 80) { // CupLed
+      digitalWrite(CupLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 81) { // RideLed
+      digitalWrite(RideLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 82) { // FunctionLed
+      digitalWrite(FunctionLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 83) { // KickLed
+      digitalWrite(KickLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 84) { // SnareLed
+      digitalWrite(SnareLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 85) { // ClosedHatLed
+      digitalWrite(ClosedHatLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+ if((rx.header >> 4) == 2) { // channel 3 (channel 1 has value 0)
+  if((rx.header & 0b1111) == 0b1011) { // control change
+    if(rx.byte1 == 86) { // OpenHatLed
+      digitalWrite(OpenHatLed, rx.byte2 >> 6); // 0 >> 6 = 0 and 127 >> 6 = 1
+     }
+   }
+ }
+
+
 }

 void setMidiOut(){