Another attempt at progmem

Another attempt at progmem

--- projects/SumpPumpController/Arduino/Arduino.ino
+++ projects/SumpPumpController/Arduino/Arduino.ino
@@ -35,6 +35,68 @@
 // Buffer for char conversions
 char buf [100];

+// PROGMEM string declarations
+const char str_alertPresent[] PROGMEM = "alertPresent";
+const char str_alarmPresent[] PROGMEM = "alarmPresent";
+const char str_YES_Ack_ed[] PROGMEM = "YES, Ack'ed";
+const char str_YES[] PROGMEM = "YES";
+const char str_NO[] PROGMEM = "NO";
+const char str_alertReason[] PROGMEM = "alertReason";
+const char str_getDistance[] PROGMEM = "getDistance";
+const char str_getPressure[] PROGMEM = "getPressure";
+const char str_getBattVoltage[] PROGMEM = "getBattVoltage";
+const char str_dmV[] PROGMEM = "%dmV";
+const char str_getAcPumpOnTime[] PROGMEM = "getAcPumpOnTime";
+const char str_d[] PROGMEM = "%d";
+const char str_getLastSelfTest[] PROGMEM = "getLastSelfTest";
+const char str_forceAlert[] PROGMEM = "forceAlert";
+const char str_Force_command[] PROGMEM = "Force command";
+const char str_OK[] PROGMEM = "OK";
+const char str_resetAlert[] PROGMEM = "resetAlert";
+const char str_startSelfTest[] PROGMEM = "startSelfTest";
+const char str_set[] PROGMEM = "set";
+const char str_debug[] PROGMEM = "debug";
+const char str_Unrecognized_command[] PROGMEM = "Unrecognized command";
+const char str_setAlertBatteryVoltage[] PROGMEM = "setAlertBatteryVoltage:";
+const char str_ERROR[] PROGMEM = "ERROR";
+const char str_setAlertWaterLevel[] PROGMEM = "setAlertWaterLevel:";
+const char str_setBaudRate[] PROGMEM = "setBaudRate:";
+const char str_setAcPumpOnThreshold[] PROGMEM = "setAcPumpOnThreshold:";
+const char str_setAlertPressureLevel[] PROGMEM = "setAlertPressureLevel:";
+const char str_setAcPumpOnTimeWarning[] PROGMEM = "setAcPumpOnTimeWarning:";
+const char str_setSelftestTimeBetween[] PROGMEM = "setSelftestTimeBetween:";
+const char str_setSelfTestTimeLimit[] PROGMEM = "setSelfTestTimeLimit:";
+const char str_setSelfTestMinDepth[] PROGMEM = "setSelfTestMinDepth:";
+const char str_setSelfTestDepthDiff[] PROGMEM = "setSelfTestDepthDiff:";
+const char str_setDepthMeasureTime[] PROGMEM = "setDepthMeasureTime:";
+const char str_setBuzzerEnabled[] PROGMEM = "setBuzzerEnabled:";
+const char str_setZeroPressure[] PROGMEM = "setZeroPressure:";
+const char str_setPointsPerCm[] PROGMEM = "setPointsPerCm:";
+const char str_setDcPumpOnTimeWarning[] PROGMEM = "setDcPumpOnTimeWarning:";
+const char str_ERROR_1_3600_expected[] PROGMEM = "ERROR: 1-3600 expected.";
+const char str_time_lu[] PROGMEM = "time=%lu";
+const char str_rangeLH_0_d_d[] PROGMEM = "rangeLH[0]=%d,%d";
+const char str_rangeLH_1_d_d[] PROGMEM = "&rangeLH[1]=%d,%d";
+const char str_DcHeight_d_d[] PROGMEM = "&DcHeight=%d,%d";
+const char str_pressure_d[] PROGMEM = "&pressure=%d";
+const char str_AcPumpCycles_d[] PROGMEM = "&AcPumpCycles=%d";
+const char str_lastAlertTime_lu[] PROGMEM = "&lastAlertTime=%lu";
+const char str_rawDepthPressure_d[] PROGMEM = "&rawDepthPressure=%d";
+const char str_timeSince_lu[] PROGMEM = "timeSince=%lu&";
+const char str_cyclesSince_d[] PROGMEM = "cyclesSince=%d&";
+const char str_voltage_d[] PROGMEM = "voltage=%d&";
+const char str_length_d[] PROGMEM = "length=%d&";
+const char str_pumpedHeight_d[] PROGMEM = "pumpedHeight=%d&";
+const char str_result_d[] PROGMEM = "result=%d";
+const char str_Weak_battery_dmV[] PROGMEM = "Weak battery: %dmV";
+const char str_DC_Pump_failure_dCM_pumped_in_d_sec[] PROGMEM = "DC Pump failure: %dCM pumped in %d sec.";
+const char str_DC_Pump_ON[] PROGMEM = "DC Pump ON";
+const char str_DC_pump_ON_too_long[] PROGMEM = "DC pump ON too long";
+const char str_Battery_voltage[] PROGMEM = "Battery voltage";
+const char str_Water_level_d[] PROGMEM = "Water level: %d";
+const char str_High_pressure[] PROGMEM = "High pressure";
+const char str_AC_pump_ON_for_too_long[] PROGMEM = "AC pump ON for too long";
+
 void setup()
 {
   readConfig();
@@ -82,49 +144,49 @@
 {
   // Process RS-485 commands
   if (net.messageReceived()) {
-    if (net.assertCommand(PSTR("alertPresent")) || net.assertCommand(PSTR("alarmPresent"))) {
+    if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_alertPresent)))) || net.assertCommand(PSTR((char*)pgm_read_word(&(str_alarmPresent))))) {
       if (alert.present) {
         if (alert.acknowledged) {
-          net.sendResponse(PSTR("YES, Ack'ed"));
+          net.sendResponse(PSTR((char*)pgm_read_word(&(str_YES_Ack_ed))));
         } else {
-          net.sendResponse(PSTR("YES"));
+          net.sendResponse(PSTR((char*)pgm_read_word(&(str_YES))));
         }
       } else {
-        net.sendResponse(PSTR("NO"));
+        net.sendResponse(PSTR((char*)pgm_read_word(&(str_NO))));
       }
-    } else if (net.assertCommand(PSTR("alertReason"))) {
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_alertReason))))) {
       net.sendResponse(alert.condition);
-    } else if (net.assertCommand(PSTR("getDistance"))) {
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_getDistance))))) {
       net.sendResponse(itoa(readDistance(), buf, 10));
-    } else if (net.assertCommand(PSTR("getPressure"))) {
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_getPressure))))) {
       net.sendResponse(itoa(readPressure(), buf, 10));
-    } else if (net.assertCommand(PSTR("getBattVoltage"))) {
-      sprintf(buf, "%dmV", readBatteryVoltage());
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_getBattVoltage))))) {
+      sprintf(buf, (char*)pgm_read_word(&(str_dmV)), readBatteryVoltage());
       net.sendResponse(buf);
-    } else if (net.assertCommand(PSTR("getAcPumpOnTime"))) {
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_getAcPumpOnTime))))) {
       if (acpump.currentlyOn) {
-        sprintf(buf, "%d", acpump.onSeconds + (now() - acpump.switchOnTime));
+        sprintf(buf, (char*)pgm_read_word(&(str_d)), acpump.onSeconds + (now() - acpump.switchOnTime));
       } else {
-        sprintf(buf, "%d", acpump.onSeconds);
+        sprintf(buf, (char*)pgm_read_word(&(str_d)), acpump.onSeconds);
       }
       net.sendResponse(buf);
-    } else if (net.assertCommand(PSTR("getLastSelfTest"))) {
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_getLastSelfTest))))) {
       sendSelfTestResponse();
-    } else if (net.assertCommand(PSTR("forceAlert"))) {
-      raiseAlert(ExternallyForced, PSTR("Force command"));
-      net.sendResponse(PSTR("OK"));
-    } else if (net.assertCommand(PSTR("resetAlert"))) {
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_forceAlert))))) {
+      raiseAlert(ExternallyForced, PSTR((char*)pgm_read_word(&(str_Force_command))));
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_resetAlert))))) {
       resetAlert();
-      net.sendResponse(PSTR("OK"));
-    } else if (net.assertCommand(PSTR("startSelfTest"))) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_startSelfTest))))) {
       dcSelfTestStart();
-      net.sendResponse(PSTR("OK"));
-    } else if (net.assertCommandStarts(PSTR("set"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_set))), buf)) {
       processSetCommands();
-    } else if (net.assertCommand(PSTR("debug"))) {
+    } else if (net.assertCommand(PSTR((char*)pgm_read_word(&(str_debug))))) {
       sendDebugResponse();
     } else {
-      net.sendResponse(PSTR("Unrecognized command"));
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_Unrecognized_command))));
     }
   }

@@ -169,25 +231,25 @@
 // Write to the configuration when we receive new parameters
 void processSetCommands()
 {
-  if (net.assertCommandStarts(PSTR("setAlertBatteryVoltage:"), buf)) {
+  if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setAlertBatteryVoltage))), buf)) {
     unsigned int tmp = strtol(buf, NULL, 10);
     if (tmp > 9000 && tmp < 15000) {
       conf.alertBatteryVoltage = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setAlertWaterLevel:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setAlertWaterLevel))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp > -100 && tmp < 100) {
       conf.alertWaterLevel = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setBaudRate:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setBaudRate))), buf)) {
     long tmp = strtol(buf, NULL, 10);
     // Supported: 9600, 14400, 19200, 28800, 38400, 57600, or 115200
     if (tmp == 9600 ||
@@ -200,143 +262,143 @@
     ) {
       conf.baudRate = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
       Serial.end();
       Serial.begin(tmp);
     } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setAcPumpOnThreshold:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setAcPumpOnThreshold))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp > 0 && tmp < 1025) {
       conf.acPumpOnThreshold = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setAlertPressureLevel:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setAlertPressureLevel))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp > 0 && tmp < 1025) {
       conf.alertPressureLevel = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setAcPumpOnTimeWarning:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setAcPumpOnTimeWarning))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp > 0 && tmp < 30000) {
       conf.acPumpOnTimeWarning = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setSelftestTimeBetween:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setSelftestTimeBetween))), buf)) {
     long tmp = strtol(buf, NULL, 10);
     if (tmp > 0 && tmp < 1000000L) {
       conf.selftestTimeBetween = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setSelfTestTimeLimit:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setSelfTestTimeLimit))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     // More than 6 seconds, as we're checking that DC pump is on at 6 second mark.
     if (tmp > 6 && tmp < 200) {
       conf.selfTestTimeLimit = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setSelfTestMinDepth:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setSelfTestMinDepth))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp > -100 && tmp < 100) {
       conf.selfTestMinDepth = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setSelfTestDepthDiff:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setSelfTestDepthDiff))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp > 0 && tmp < 100) {
       conf.selfTestDepthDiff = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setDepthMeasureTime:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setDepthMeasureTime))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp >= 0 && tmp < 120) {
       conf.depthMeasureTime = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setBuzzerEnabled:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setBuzzerEnabled))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp == 1 || tmp == 0) {
       conf.buzzerEnabled = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setZeroPressure:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setZeroPressure))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp >= 0 && tmp < 1023) {
       conf.zeroPressure = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setPointsPerCm:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setPointsPerCm))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp >= -1024 && tmp < 1024) {
       conf.pointsPerCm = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR"));
-    }
-  } else if (net.assertCommandStarts(PSTR("setDcPumpOnTimeWarning:"), buf)) {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR))));
+    }
+  } else if (net.assertCommandStarts(PSTR((char*)pgm_read_word(&(str_setDcPumpOnTimeWarning))), buf)) {
     int tmp = strtol(buf, NULL, 10);
     if (tmp >= 1 && tmp < 3600) {
       conf.dcPumpOnTimeWarning = tmp;
       saveConfig();
-      net.sendResponse(PSTR("OK"));
-    } else {
-      net.sendResponse(PSTR("ERROR: 1-3600 expected."));
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_OK))));
+    } else {
+      net.sendResponse(PSTR((char*)pgm_read_word(&(str_ERROR_1_3600_expected))));
     }
   } else {
-    net.sendResponse(PSTR("Unrecognized command"));
+    net.sendResponse(PSTR((char*)pgm_read_word(&(str_Unrecognized_command))));
   }
 }

 void sendDebugResponse()
 {
-  sprintf(buf, PSTR("time=%lu"), now());
-  net.responseSendPart(buf);
-  sprintf(buf, PSTR("rangeLH[0]=%d,%d"), range.lows[0], range.highs[0]);
-  net.responseSendPart(buf);
-  sprintf(buf, PSTR("&rangeLH[1]=%d,%d"), range.lows[1], range.highs[1]);
-  net.responseSendPart(buf);
-  sprintf(buf, PSTR("&DcHeight=%d,%d"), selftest.startingHeight, selftest.endingHeight);
-  net.responseSendPart(buf);
-  sprintf(buf, PSTR("&pressure=%d"), analogRead(PRESSURE_SENSOR_PIN));
-  net.responseSendPart(buf);
-  sprintf(buf, PSTR("&AcPumpCycles=%d"), acpump.onCycles);
-  net.responseSendPart(buf);
-  sprintf(buf, PSTR("&lastAlertTime=%lu"), alert.timeTriggered);
-  net.responseSendPart(buf);
-  sprintf(buf, PSTR("&rawDepthPressure=%d"), analogRead(DEPTH_PRESSURE_SENSOR_PIN));
+  sprintf(buf, PSTR((char*)pgm_read_word(&(str_time_lu))), now());
+  net.responseSendPart(buf);
+  sprintf(buf, PSTR((char*)pgm_read_word(&(str_rangeLH_0_d_d))), range.lows[0], range.highs[0]);
+  net.responseSendPart(buf);
+  sprintf(buf, PSTR((char*)pgm_read_word(&(str_rangeLH_1_d_d))), range.lows[1], range.highs[1]);
+  net.responseSendPart(buf);
+  sprintf(buf, PSTR((char*)pgm_read_word(&(str_DcHeight_d_d))), selftest.startingHeight, selftest.endingHeight);
+  net.responseSendPart(buf);
+  sprintf(buf, PSTR((char*)pgm_read_word(&(str_pressure_d))), analogRead(PRESSURE_SENSOR_PIN));
+  net.responseSendPart(buf);
+  sprintf(buf, PSTR((char*)pgm_read_word(&(str_AcPumpCycles_d))), acpump.onCycles);
+  net.responseSendPart(buf);
+  sprintf(buf, PSTR((char*)pgm_read_word(&(str_lastAlertTime_lu))), alert.timeTriggered);
+  net.responseSendPart(buf);
+  sprintf(buf, PSTR((char*)pgm_read_word(&(str_rawDepthPressure_d))), analogRead(DEPTH_PRESSURE_SENSOR_PIN));
   net.responseSendPart(buf);
 //  sprintf(buf, );
 //  net.responseSendPart(buf);
@@ -350,17 +412,17 @@

 void sendSelfTestResponse()
 {
-   sprintf(buf, PSTR("timeSince=%lu&"), (now() - selftest.lastTestTime));
+   sprintf(buf, PSTR((char*)pgm_read_word(&(str_timeSince_lu))), (now() - selftest.lastTestTime));
    net.responseSendPart(buf);
-   sprintf(buf, PSTR("cyclesSince=%d&"), acpump.onCycles-selftest.acCycles);
+   sprintf(buf, PSTR((char*)pgm_read_word(&(str_cyclesSince_d))), acpump.onCycles-selftest.acCycles);
    net.responseSendPart(buf);
-   sprintf(buf, PSTR("voltage=%d&"), selftest.batteryVoltageMv);
+   sprintf(buf, PSTR((char*)pgm_read_word(&(str_voltage_d))), selftest.batteryVoltageMv);
    net.responseSendPart(buf);
-   sprintf(buf, PSTR("length=%d&"), (int)selftest.testLength);
+   sprintf(buf, PSTR((char*)pgm_read_word(&(str_length_d))), (int)selftest.testLength);
    net.responseSendPart(buf);
-   sprintf(buf, PSTR("pumpedHeight=%d&"), selftest.startingHeight - selftest.endingHeight);
+   sprintf(buf, PSTR((char*)pgm_read_word(&(str_pumpedHeight_d))), selftest.startingHeight - selftest.endingHeight);
    net.responseSendPart(buf);
-   sprintf(buf, PSTR("result=%d"), selftest.passed);
+   sprintf(buf, PSTR((char*)pgm_read_word(&(str_result_d))), selftest.passed);
    net.responseSendPart(buf);
    net.responseEnd();
 }
@@ -422,14 +484,14 @@
     // Battery voltage should not drop too much
     if (selftest.batteryVoltageMv < conf.alertBatteryVoltage) {
       selftest.passed = false;
-      sprintf(buf, PSTR("Weak battery: %dmV"), selftest.batteryVoltageMv);
+      sprintf(buf, PSTR((char*)pgm_read_word(&(str_Weak_battery_dmV))), selftest.batteryVoltageMv);
       raiseAlert(DcPumpMalfunction, buf);
       return;
     }
     // Determine if water level was reduced enough
     if (selftest.startingHeight - selftest.endingHeight < 5) {
       selftest.passed = false;
-      sprintf(buf, PSTR("DC Pump failure: %dCM pumped in %d sec."), (selftest.startingHeight - selftest.endingHeight), (int)selftest.testLength);
+      sprintf(buf, PSTR((char*)pgm_read_word(&(str_DC_Pump_failure_dCM_pumped_in_d_sec))), (selftest.startingHeight - selftest.endingHeight), (int)selftest.testLength);
       raiseAlert(DcPumpMalfunction, buf);
       return;
     }
@@ -468,13 +530,13 @@
   // If voltage is more than 0, then pump is on, and we need to sound an alert
   // Need to make sure to wait a few seconds after self test to see if DC pump is ON
   if (mv > 9000 && (now() - selftest.lastTestTime) > (conf.selfTestTimeLimit + 6)) {
-    raiseAlert(DcPumpActivated, PSTR("DC Pump ON"));
+    raiseAlert(DcPumpActivated, PSTR((char*)pgm_read_word(&(str_DC_Pump_ON))));
     // Record that the pump is on, or process alert, if it was already on.
     if (!dcpump.currentlyOn) {
       dcpump.currentlyOn = true;
       dcpump.switchOnTime = now();
     } else if ((now() - dcpump.switchOnTime) > conf.dcPumpOnTimeWarning) {
-      raiseAlert(DcPumpOverload, PSTR("DC pump ON too long"));
+      raiseAlert(DcPumpOverload, PSTR((char*)pgm_read_word(&(str_DC_pump_ON_too_long))));
     }
   } else {
     dcpump.currentlyOn = false;
@@ -487,7 +549,7 @@
 {
   unsigned int mv = getVoltage( BATTERY_VOLTAGE_PIN );
   if (mv < conf.alertBatteryVoltage) {
-    raiseAlert(DischargedBattery, PSTR("Battery voltage"));
+    raiseAlert(DischargedBattery, PSTR((char*)pgm_read_word(&(str_Battery_voltage))));
   }
   return mv;
 }
@@ -511,7 +573,7 @@

   if (range.distance > conf.alertWaterLevel) {
     char tmp[40];
-    sprintf(tmp, PSTR("Water level: %d"), range.distance);
+    sprintf(tmp, PSTR((char*)pgm_read_word(&(str_Water_level_d))), range.distance);
     raiseAlert(WaterLevel, tmp);
   }
   return range.distance;
@@ -523,7 +585,7 @@

   // Alert business
   if (acpump.lastPressure > conf.alertPressureLevel) {
-    raiseAlert(HighPressure, PSTR("High pressure"));
+    raiseAlert(HighPressure, PSTR((char*)pgm_read_word(&(str_High_pressure))));
   }

   boolean currentlyOn;
@@ -559,7 +621,7 @@
   // Check if AC pump was on for too long
   if (currentlyOn) {
     if ((now() - acpump.switchOnTime) > conf.acPumpOnTimeWarning) {
-      raiseAlert(AcPumpOverload, PSTR("AC pump ON for too long"));
+      raiseAlert(AcPumpOverload, PSTR((char*)pgm_read_word(&(str_AC_pump_ON_for_too_long))));
     }
   }


Updated with fan monitor and control.

Updated with fan monitor and control.

Increased loop delay to 15s so a measurement happens every 15s

--- Software/humidity.ino
+++ Software/humidity.ino
@@ -5,11 +5,9 @@
 // This #include statement was automatically added by the Spark IDE.
 #include "HTU21D/HTU21D.h"

-int ledSampling = D2; // use led for now, but this is RS232 comms LED.
-//int clockSpeed = CLOCK_SPEED_400KHZ;
-
-// Loop counter
-int loopCounter = 0;
+int ledSampling = D2;
+int fanPulseIn = D4; // Max pin for Core intterupt
+int fanControl  = D7;

 // Temperature and humidity
 HTU21D humiditySensor;
@@ -17,13 +15,44 @@
 // Spark variables for tracking humidity and temperature
 double humidity = 0;
 double temperature = 0;
+int faultCode = 0;
+int fanSpeed = 0; // percentage
+int fanOverrideSpeed = 0; // User requested fan speed. Overrides auto speed.
+int fanPulsesPerInterval = 0; // Non volatile int
+
+int setFanOnAt(String level);
+int fanOn(String command);
+int fanOff(String command);
+int reset(String command);
+
+int fanOnAtHumidityLevel = 20;
+
+// Count of fan pulses
+volatile int fanPulseCount = 0;
+

 void setup() {
     pinMode(ledSampling, OUTPUT);
+    pinMode(fanPulseIn, INPUT_PULLUP);
+    pinMode(fanControl, OUTPUT);
+    digitalWrite(ledSampling, LOW);
+    digitalWrite(fanControl, LOW);
+
+    attachInterrupt(fanPulseIn, fanPulse, FALLING);

     Spark.variable("humidity", &humidity, DOUBLE);
     Spark.variable("temperature", &temperature, DOUBLE);
-
+    Spark.variable("faultCode", &faultCode, INT);
+    Spark.variable("fanSpeed", &fanSpeed, INT);
+    Spark.variable("fanPulses", &fanPulsesPerInterval, INT);
+    //Spark.variable("fanOnAt", &fanOnAtHumidityLevel, INT);
+
+    // register the cloud function
+    Spark.function("setFanOnAt", setFanOnAt);
+    Spark.function("fanOn", fanOn);
+    Spark.function("fanOff", fanOff);
+    Spark.function("reset", reset);
+
     // Take control of the spark LED and make it dimmer as it's very
     // bright by default.
     RGB.control(true);
@@ -42,11 +71,11 @@
     // Initialize Temperature and humidity
     if (!humiditySensor.begin()) {
         RGB.color(255, 0, 00);
-        Spark.publish("Setup", "Humidity Sensor setup failed.");
+        Spark.publish("Status", "Humidity Sensor setup failed.");
     }

     //delay(1000);
-    Spark.publish("Setup", "Setup complete.");
+    Spark.publish("Status", "Setup complete.");
     RGB.color(0, 0, 0);
     delay(2000);
 }
@@ -55,26 +84,31 @@

     digitalWrite(ledSampling, HIGH);
     RGB.color(0, 0, 125);
-    Spark.publish("Reading", "Reading...");
-    delay(100);
-
+    //Spark.publish("Reading", "Reading...");
+    //delay(100);
+
+    // Reset the fault code before measuring.
+    faultCode = 0;
     readHumidity();
+    // Small delay before re-reading to see if this helps resolve the errors.
+    delay(250);
     readTemperature();

-    delay(100);
     RGB.color(0, 0, 0);
     digitalWrite(ledSampling, LOW);
-    loopCounter = 0;
-
-    delay(2000);
-
+
+    // Store the fan pulses during this loop
+    fanPulsesPerInterval = fanPulseCount;
+    fanPulseCount = 0;
+
      // Do not use Sleep as it breaks Photon WiFi!
     // Can we put the Core into low power mode?
     // Photon:
     //System.sleep(2);
     // Core:
     // Spark.sleep(1);
-    delay(2000);
+    // Sleep for x seconds.
+    delay(15000);
 }

 void readHumidity() {
@@ -82,15 +116,14 @@
     if (h < 100) {
         humidity = (double)h;
         Spark.publish("Humidity", "Measured humidity as: " + String(h));
-        if (h < 20) {
-            RGB.color(0, 255, 0);
-        } else if (h<50) {
-            RGB.color(255, 255, 0);
-        }
+        updateControl(humidity);
     } else {
+        faultCode = h;
         Spark.publish("Error", "Error reading humidity. Reported: " + String(h));
         RGB.color(255, 0, 0);
-        delay(1000);
+        // Force a delay to try and help I2C
+        delay(3000);
+        //reset("Humidity Fault");
     }
 }

@@ -100,8 +133,104 @@
         temperature = (double)t;
         Spark.publish("Temperature", "Measured temperature as: " + String(temperature));
     } else {
+        faultCode = t;
         Spark.publish("Error", "Error reading temperature. Reported: " + String(t));
         RGB.color(255, 0, 0);
-        delay(1000);
-    }
+        // Force a delay to try and help I2C
+        delay(3000);
+        //reset("Temperature Fault");
+    }
+}
+
+void updateControl(float humidity) {
+    // Use the global fanSpeed variable.
+
+    int newFanOnCount = fanSpeed;
+
+    if (humidity < fanOnAtHumidityLevel) {
+        // Humidity is in range. Do nothing
+        RGB.color(0, 255, 0);
+        // Humidity is below required level
+        // decrease the number of itterations the fan needs to be on for.
+        newFanOnCount--;
+    } else if (humidity < 40) { // Do we need this settabke?
+        // Humidity is high so put fan on, but low.
+        RGB.color(255, 128, 0);
+        // Run the fan for 4 itterations of the main loop (about 1 minute).
+        // on top of how long it takes to get below thresold.
+        newFanOnCount = 4;
+        // TODO: Turn the fan on.
+    } else  {
+        // humidity is very high, fan on full speed.
+        RGB.color(255, 0, 128);
+        newFanOnCount = 12;
+        //fanSpeed = 100;
+    }
+
+    if (newFanOnCount < 0) {
+        newFanOnCount = 0;
+    }
+
+    setFan(newFanOnCount);
+}
+
+// Particle Method
+int setFanOnAt(String level) {
+    // This relies on level being a single numeric value.
+    fanOnAtHumidityLevel = level.toInt();
+    Spark.publish("Status", "Setting fan trigger humidity level at: " + String(fanOnAtHumidityLevel) + "%, request was : '" + level + "' ");
+    return 0;
+}
+
+// Particle Method
+int fanOn(String command)
+{
+    Spark.publish("Status", "Switching fan on to 100%.");
+    fanOverrideSpeed = 100;
+    // On for 10 mins (4 itterations per min)
+    setFan(10 * 4);
+    return fanOverrideSpeed;
+}
+
+// Particle Method
+int fanOff(String command)
+{
+    Spark.publish("Status", "Switching fan off.");
+    fanOverrideSpeed = 0;
+    // On for 0 itterations
+    setFan(0);
+    return fanOverrideSpeed;
+}
+
+// Particle Method
+int reset(String args) {
+    // Photon only?
+    Spark.publish("Status", "I'm going to reset in 10 seconds. Reason: " + args);
+    delay(10000);
+    System.reset();
+    return 0;
+}
+
+// Use the number of cycles that the fan should be on for.
+void setFan(int fanCount) {
+
+    int newfanSpeed = fanCount; //max(speed, fanOverrideSpeed);
+
+    if (newfanSpeed != fanSpeed) {
+        Spark.publish("Status", "Setting fan speed to:" + String(newfanSpeed));
+    }
+
+    // Store in the Particle variable
+    fanSpeed = newfanSpeed;
+
+    // TODO: Use AnalogWrite when fan connected to it.
+    if (fanSpeed > 0) {
+        digitalWrite(fanControl, HIGH);
+    } else {
+        digitalWrite(fanControl, LOW);
+    }
+}
+
+void fanPulse() {
+    fanPulseCount++;
 }


corrected translation of hex numbers to decimal numbers (#342)

--- examples/ReadAndWrite/ReadAndWrite.ino
+++ examples/ReadAndWrite/ReadAndWrite.ino
@@ -2,17 +2,17 @@
  * ----------------------------------------------------------------------------
  * This is a MFRC522 library example; see https://github.com/miguelbalboa/rfid
  * for further details and other examples.
- *
+ *
  * NOTE: The library file MFRC522.h has a lot of useful info. Please read it.
- *
+ *
  * Released into the public domain.
  * ----------------------------------------------------------------------------
  * This sample shows how to read and write data blocks on a MIFARE Classic PICC
  * (= card/tag).
- *
+ *
  * BEWARE: Data will be written to the PICC, in sector #1 (blocks #4 to #7).
- *
- *
+ *
+ *
  * Typical pin layout used:
  * -----------------------------------------------------------------------------------------
  *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
@@ -24,7 +24,7 @@
  * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
  * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
  * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
- *
+ *
  */

 #include <SPI.h>
@@ -56,7 +56,7 @@
     Serial.print(F("Using key (for A and B):"));
     dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
     Serial.println();
-
+
     Serial.println(F("BEWARE: Data will be written to the PICC, in sector #1"));
 }

@@ -95,8 +95,8 @@
     byte dataBlock[]    = {
         0x01, 0x02, 0x03, 0x04, //  1,  2,   3,  4,
         0x05, 0x06, 0x07, 0x08, //  5,  6,   7,  8,
-        0x08, 0x09, 0xff, 0x0b, //  9, 10, 255, 12,
-        0x0c, 0x0d, 0x0e, 0x0f  // 13, 14,  15, 16
+        0x09, 0x0a, 0xff, 0x0b, //  9, 10, 255, 11,
+        0x0c, 0x0d, 0x0e, 0x0f  // 12, 13, 14, 15
     };
     byte trailerBlock   = 7;
     MFRC522::StatusCode status;
@@ -159,7 +159,7 @@
     }
     Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
     dump_byte_array(buffer, 16); Serial.println();
-
+
     // Check that data in block is what we have written
     // by counting the number of bytes that are equal
     Serial.println(F("Checking result..."));
@@ -177,7 +177,7 @@
         Serial.println(F("  perhaps the write didn't work properly..."));
     }
     Serial.println();
-
+
     // Dump the sector data
     Serial.println(F("Current data in sector:"));
     mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);


made start of "latch pulse" test easier to recognize

--- examples/Tlc59711Test/Tlc59711Test.ino
+++ examples/Tlc59711Test/Tlc59711Test.ino
@@ -30,8 +30,9 @@
   for (int m=0; m<NUM_MODES; m++) {
     bool writeTimeable = setXferMode(m);
     flickerRamp();
-    blink();
+    blink(5);
     flickerConst();
+    blink(1);
     latchPulse(writeTimeable);
     Serial.println();
   }
@@ -104,9 +105,9 @@
   testDone();
 }

-void blink() {
+void blink(int secs) {
   testMessage("blink");
-  for (int i=0; i<50; i++) {
+  for (int i=0, n=10*secs; i<n; i++) {
     int m = i%2;
     tlc.setRGB(32768*m, 6554*m, 655*m);
     tlc.write();


move xbee to hardware serial1, compatible with arduino leonardo and micro more descriptive debug information, including raw gps option

--- onboard_controller/onboard_controller.ino
+++ onboard_controller/onboard_controller.ino
@@ -3,9 +3,10 @@
 #include <SoftwareSerial.h>

 /*--debug macros--*/
-#define readDebug //print xbee reads to console
-//#define writeDebug //print xbee writes to console
+//#define readDebug //print Serial1 reads to console
+//#define writeDebug //print Serial1 writes to console
 #define fakeGPS //fake the presence of a gps
+//#define rawGPSDebug //print raw gps data to console

 //make sure these match on the receiving end
 #define MARKER_LAT 0xFB
@@ -43,9 +44,8 @@

 States state = STOPPED;

-// XBee's DOUT (TX) is connected to pin 10 (Arduino's Software RX)
-// XBee's DIN (RX) is connected to pin 9 (Arduino's Software TX)
-SoftwareSerial XBee(10,9); // RX, TX
+// XBee's DOUT (TX) is connected to pin 0 (Arduino's Hardware RX)
+// XBee's DIN (RX) is connected to pin 1 (Arduino's Hardware TX)

 SoftwareSerial gpsSerial(8, 7);
 Adafruit_GPS GPS(&gpsSerial);
@@ -54,8 +54,8 @@
 {
   pinMode(PIN_PAYLOAD, OUTPUT);

-  //Make sure XBee baud matches hardware config
-  XBee.begin(57600);//115200);
+  //Make sure Serial baud matches hardware config
+  Serial1.begin(57600); //XBee baud rate
   Serial.begin(115200);

   // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
@@ -83,16 +83,14 @@

 void loop()
 {
-  gpsSerial.listen(); //switch to GPS serial
-  delayMicroseconds(150);
-  while (gpsSerial.available()) {
-    char c = GPS.read();
-  // if you want to debug, this is a good time to do it!
-  if ((c))
-    Serial.write(c);
-  }
-
-  XBee.listen();
+  #ifdef rawGPSDebug
+    while (gpsSerial.available()) {
+      char c = GPS.read();
+      if (c) {
+        Serial.write(c);
+      }
+    }
+  #endif

   // if a sentence is received, we can check the checksum, parse it...
   if (GPS.newNMEAreceived()) {
@@ -100,22 +98,26 @@
       return;  // we can fail to parse a sentence in which case we should just wait for another
   }

-     if (XBee.available()) {
-      byte receivedPayload = XBee.read();
-      switch (receivedPayload) {
-        case FLAG_PAYLOAD:
-          digitalWrite(PIN_PAYLOAD,HIGH);
-          break;
-        default:
+  //handle XBee received data
+  if (Serial1.available()) {
+    byte receivedPayload = Serial1.read();
+    switch (receivedPayload) {
+      case FLAG_PAYLOAD:
+        if ( digitalRead(PIN_PAYLOAD) == HIGH )
           digitalWrite(PIN_PAYLOAD,LOW);
-          break;
-      }
-      #ifdef readDebug
-        Serial.print("size: ");
-        Serial.println(XBee.available());
-        Serial.println(receivedPayload, HEX);
-      #endif
+        else digitalWrite(PIN_PAYLOAD,HIGH);
+        break;
+      default:
+        digitalWrite(PIN_PAYLOAD,LOW);
+        break;
     }
+    #ifdef readDebug
+      Serial.print("read size: ");
+      Serial.println(Serial.available());
+      Serial.println(receivedPayload, HEX);
+    #endif
+  }
+
   // if millis() or timer wraps around, reset
   if (timer > millis())  timer = millis();
   if (millis() - timer > 400) {
@@ -159,7 +161,8 @@
       //buffer size is the difference between the current and start pointers
       buf_size = buf_curr - buf_start;

-      XBee.write(buf_start, buf_size);
+      Serial1.write(buf_start, buf_size);
+       delayMicroseconds(50);
       //arduino is little endian (LSB first)

       #ifdef writeDebug
@@ -170,7 +173,7 @@
         }
         //read the contents of the buffer
         byte* bufferReader = buf_start;
-        Serial.print("Size: ");
+        Serial.print("write size: ");
         Serial.println(buf_size);
         while (bufferReader != buf_curr) {
           Serial.print(*bufferReader, HEX);
@@ -178,10 +181,6 @@
           bufferReader++;
         }
         Serial.println();
-
-          if (XBee.overflow()) {
-           Serial.println("XBee serial buffer overflow!");
-          }
       #endif
   }
 }


ファームウェアの修正

ファームウェアの修正

--- GPduinoR3/GPduinoR3.ino
+++ GPduinoR3/GPduinoR3.ino
@@ -49,7 +49,8 @@
 #define LOW_BATTERY    512

 // 四輪操舵のモード
-static int g_mode_4ws;
+static int g_steer_pol_f;
+static int g_steer_pol_b;

 // サーボの調整
 static int g_servo_pol[3]; // 極性
@@ -195,7 +196,8 @@
     g_lr = 0;
     cnt_runaway = 0;
     Vbat_MovingAve.init();
-    g_mode_4ws = 0;
+    g_steer_pol_f = 1;
+    g_steer_pol_b = 0;
 }

 // メインループ
@@ -312,15 +314,28 @@
      */
     case 'T':
         // 4WSモード
-        if(buff[3] == '1'){
-            g_mode_4ws = 1;
-        }
-        else if(buff[3] == '2'){
-            g_mode_4ws = -1;
-        }
-        else{
-            g_mode_4ws = 0;
-        }
+        switch(buff[3]){
+        case '0':// FRONT
+            g_steer_pol_f = 1;
+            g_steer_pol_b = 0;
+            break;
+        case '1':// COMMON
+            g_steer_pol_f = 1;
+            g_steer_pol_b = 1;
+            break;
+        case '2':// REVERSE
+            g_steer_pol_f = 1;
+            g_steer_pol_b = -1;
+            break;
+        case '3':// REAR
+            g_steer_pol_f = 0;
+            g_steer_pol_b = 1;
+            break;
+        default:
+            g_steer_pol_f = 1;
+            g_steer_pol_b = 0;
+            break;
+        }
         // 値の解釈
         if( HexToUint16(&buff[1], &val, 2) != 0 ) break;
         sval = (int)((signed char)val);
@@ -329,8 +344,8 @@
         if(drive_mode == MODE_CAR)
         {
             servo_ctrl(0, sval);
-            servo_ctrl(1, sval);
-            servo_ctrl(2, g_mode_4ws * sval);
+            servo_ctrl(1, g_steer_pol_f * sval);
+            servo_ctrl(2, g_steer_pol_b * sval);
         }
         // 戦車モードの場合
         else


Moved startTime=millis(); to setup instead of loop in fsm.

--- fsm/fsm.ino
+++ fsm/fsm.ino
@@ -40,13 +40,13 @@
   servoArm.write(armUp); // Set the arm in upright position

   currentState = STATE_MOVE_AND_AVOID;
+
+  startTime = millis();

 }

 void loop() {
   Serial.println(currentState); // DEBUG
-
-  startTime = millis();

   if (currentState == STATE_MOVE_AND_AVOID) {


tweak habitat display; -FRU test;

tweak habitat display; -FRU test;

--- examples/MUX_P7_sensors_read/MUX_P7_sensors_read.ino
+++ examples/MUX_P7_sensors_read/MUX_P7_sensors_read.ino
@@ -184,8 +184,8 @@
 	delay(50);

 	//                0123456789ABCDEF0123456789ABCDEF
-	Serial1.printf ("dMUX mfg test    \r");				// in case this code ever ends up in a habitat
-	Serial2.printf ("dMUX mfg test    \r");
+	Serial1.printf ("dMUX P7 sensor rd\r");				// in case this code ever ends up in a habitat
+	Serial2.printf ("dMUX P7 sensor rd\r");

 	pinMode(PERIPH_RST, OUTPUT);						// NOTE: SALT 2.0 resetting the FETs 9557 (U5) allows the gates of the FETs to float; U5 should be immediately initialized following reset
 	pinMode (ETHER_RST, OUTPUT);
@@ -357,7 +357,7 @@

 //============================================================================================================
-
+/*
 	fru.setup (I2C_FRU);								// POWER FRU
 	fru.begin ();
 	ret_val = fru.init ();
@@ -366,8 +366,8 @@
 		if (SUCCESS != fru.pin_mobility_test (0))
 			{
 			display.display_line_write ("FRU mobility failed", ILI9341_RED);
-			fail_led();
-			while (1);
+//			fail_led();
+//			while (1);
 			}
 		display.display_line_write ("FRU mobility OK", ILI9341_GREEN);

@@ -377,8 +377,8 @@
 		{
 		display.display_line_write ("FRU init failed", ILI9341_RED);
 		Serial.printf ("fru ini fail: 0x%.2X\n", ret_val);
-		fail_led();
-		while (1);
+//		fail_led();
+//		while (1);
 		}

 	fru.sensor_reset (true);							// assert reset to the mfg test hardware
@@ -388,7 +388,7 @@
 	fru.update_manual();

 	display.display_line_write ("FRU init OK", ILI9341_GREEN);
-
+*/

 //============================================================================================================
 // setup port7 devices


Added offset functionality

Added offset functionality

--- rocker/rocker.ino
+++ rocker/rocker.ino
@@ -16,6 +16,8 @@
 #define BUFLEN 100
 #define MAXF 5
 #define MAXA 45
+#define OFFSET 10
+
 /*****************/
 /* SERVO OBJECTS */
 /*****************/
@@ -27,14 +29,16 @@
 char buf[BUFLEN+1];
 float freq, amp;
 int pos;
+int maxt = MAX + OFFSET;
+int mint = MIN + OFFSET;

 /*********/
 /* SETUP */
 /*********/
 void setup() {
   Serial.begin(38400);
-  servo.attach(SERVO_PIN, MIN, MAX);
-  servo.writeMicroseconds(pos = (MAX+MIN)/2);
+  servo.attach(SERVO_PIN, mint, maxt);
+  servo.writeMicroseconds(pos = (maxt+mint)/2);
 }

 /********/
@@ -67,8 +71,8 @@
      Serial.print(amp);
      Serial.println("Deg");

-     float ampus = amp*(float)(MAX-MIN)/180.0;
-     float mid = (float)(MAX+MIN)/2.0;
+     float ampus = amp*(float)(maxt-mint)/180.0;
+     float mid = (float)(maxt+mint)/2.0;
      int start = micros();
      while ( Serial.available() == 0 ) {
        pos = round(ampus*sin(2*PI*freq*(micros()-start)/1000000.0) + mid);


libraries: MegaDrive: examples: More rich example.

--- libraries/MegaDrive/examples/megadrive-example/megadrive-example.ino
+++ libraries/MegaDrive/examples/megadrive-example/megadrive-example.ino
@@ -2,6 +2,8 @@

 const int up_led = 13;
 const int left_led = 12;
+const int down_led = 11;
+const int right_led = 10;

 static const struct mg_pin_setup ps = {
   .D0 = 1,     // (UP key)
@@ -15,9 +17,9 @@

 static const struct mg_three_callbacks clbs_up = {
   .up_fnc = &up_keyup,
-  .down_fnc = NULL,
+  .down_fnc = &down_keyup,
   .left_fnc = &left_keyup,
-  .right_fnc = NULL,
+  .right_fnc = &right_keyup,
   .a_fnc = NULL,
   .b_fnc = NULL,
   .c_fnc = NULL,
@@ -26,9 +28,9 @@

 static const struct mg_three_callbacks clbs_down = {
   .up_fnc = &up_keydown,
-  .down_fnc = NULL,
+  .down_fnc = &down_keydown,
   .left_fnc = &left_keydown,
-  .right_fnc = NULL,
+  .right_fnc = &right_keydown,
   .a_fnc = NULL,
   .b_fnc = NULL,
   .c_fnc = NULL,
@@ -47,6 +49,26 @@
   digitalWrite(left_led, HIGH);
 }

+void down_keyup(void)
+{
+  digitalWrite(down_led, LOW);
+}
+
+void right_keydown(void)
+{
+  digitalWrite(right_led, HIGH);
+}
+
+void right_keyup(void)
+{
+  digitalWrite(right_led, LOW);
+}
+
+
+void down_keydown(void)
+{
+  digitalWrite(down_led, HIGH);
+}

 void up_keyup(void)
 {
@@ -62,9 +84,12 @@
 void setup() {
   pinMode(up_led, OUTPUT);
   pinMode(left_led, OUTPUT);
+  pinMode(down_led, OUTPUT);
+  pinMode(right_led, OUTPUT);
 }

 void loop() {
   X->update_states();
   delay(20);
 }
+


Make error messages more descriptive.

Make error messages more descriptive.

--- webservertask.ino
+++ webservertask.ino
@@ -147,11 +147,11 @@
       File root = SPIFFS.open( "/" );
       if ( !root )
       {
-        return request->send( 503, textPlainHeader, "SD card not available." );
+        return request->send( 503, textPlainHeader, "SPIFFS not available." );
       }
       if ( !root.isDirectory() )
       {
-        return request->send( 400, textPlainHeader, "Not a directory");
+        return request->send( 400, textPlainHeader, "No root on SPIFFS.");
       }

       File file = root.openNextFile();


Sleep

Sleep

--- LoRa/LoRa_Garden_TX/LoRa_Garden_TX.ino
+++ LoRa/LoRa_Garden_TX/LoRa_Garden_TX.ino
@@ -4,6 +4,12 @@
 #include <Wire.h>
 #include <OneWire.h>
 #include <DallasTemperature.h>
+#include <avr/wdt.h>
+#include <avr/sleep.h>    // Sleep Modes
+#include <avr/power.h>    // Power management
+
+#define RNG_WATCHDOG 0 // and remove ISR(WDT_vect) from RNG.cpp (line 195)
+
 #include <Crypto.h>
 #include <AES.h>
 #include <RH_RF95.h>
@@ -27,6 +33,7 @@
 // Data wire is plugged into pin 6 on the Arduino
 #define ONE_WIRE_BUS 6

+#define WD_DO_STUFF 1 // How many watchdog interupts before doing real work.

 // Singleton instance of the radio driver
 RH_RF95 rf95(RFM95_CS, RFM95_INT);
@@ -51,7 +58,21 @@
 DallasTemperature onewireSensors(&oneWire);
 DeviceAddress deviceAddress;

+volatile byte wd_isr = WD_DO_STUFF;
+
+ISR(WDT_vect) {
+  // Wake up by watchdog
+  if (wd_isr == 0) {
+      wd_isr = WD_DO_STUFF;
+  } else {
+      --wd_isr;
+      // Go back to sleep.
+      goToSleep();
+  }
+}
+
 void setup() {
+  watchdog_setup();
   Serial.begin(115200);

   ads.setGain(GAIN_TWO); // 2x gain   +/- 2.048V  1 bit = 1mV
@@ -73,8 +94,7 @@
   rf95.setTxPower(10, false);

   pinMode(PIN_SENSOR_VCC, OUTPUT);
-  // Start with no volts to the sensors using this power source.
-  digitalWrite(PIN_SENSOR_VCC, LOW);
+  digitalWrite(PIN_SENSOR_VCC, HIGH);

   // Begin the onwire library.
   onewireSensors.setWaitForConversion(true);
@@ -95,17 +115,20 @@

 void loop() {

+  // Reset watchdog so he knows all is well.
+  wdt_reset();
+
+  // Power up the sensors.
+  digitalWrite(PIN_SENSOR_VCC, HIGH);
+
   tx_payload.setMsgId(++msg_id);

   uint16_t vcc = readVcc();
   tx_payload.setVcc(vcc);

-  // Read the temperature while the aref settles.
+  // Read the temperature.
   tx_payload.setTemperature(readTemperature());

-  // Power up the soil sensor.
-  digitalWrite(PIN_SENSOR_VCC, HIGH);
-
   tx_payload.setChargeMa(readSolarCurrent());
   tx_payload.setChargeMv(readSolarVolts());
   tx_payload.setLight(readLight(vcc));
@@ -146,8 +169,67 @@
     Serial.println("No reply");
   }

-  delay(5000);
-}
+  // Watchdog will wake us up in 8 seconds time.
+  goToSleep();
+}
+
+/**
+ * Watchdog for while awake to ensure things are ticking over.
+ */
+void watchdog_setup() {
+  // Clear any previous watchdog interupt
+  MCUSR = 0;
+
+  // Reset after 8 seconds,
+  // unless wdt_reset(); has been successfully called
+
+  /* In order to change WDE or the prescaler, we need to
+   * set WDCE (This will allow updates for 4 clock cycles).
+   */
+  WDTCSR |= (1<<WDCE) | (1<<WDE);
+
+  /* set new watchdog timeout prescaler value */
+  WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */
+
+  /* Enable the WD interrupt (note no reset). */
+  WDTCSR |= _BV(WDIE);
+
+  //wdt_enable(WDTO_8S);
+  wdt_reset();
+}
+
+void goToSleep() {
+  //digitalWrite(LED_DEBUG, LOW);
+
+
+  cli();
+
+  // disable ADC
+  byte old_ADCSRA = ADCSRA;
+  ADCSRA = 0;
+
+  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+
+  power_all_disable();  // power off ADC, Timer 0 and 1, serial interface
+  sleep_enable();
+  sei();
+
+  // turn off brown-out enable in software
+  MCUCR = bit (BODS) | bit (BODSE);  // turn on brown-out enable select
+  MCUCR = bit (BODS);        // this must be done within 4 clock cycles of above
+  sleep_cpu();              // sleep within 3 clock cycles of above
+
+  sleep_disable();
+  MCUSR = 0; // clear the reset register
+
+  power_all_enable();    // power everything back on
+
+  // put ADC back
+  ADCSRA = old_ADCSRA;
+
+  //digitalWrite(LED_DEBUG, HIGH);
+
+}

 /**
  * Read the internal voltage.
@@ -219,11 +301,8 @@
 }

 uint16_t readTemperature() {
-  if (onewireSensors.isConversionAvailable(deviceAddress)) {
-    // Send the command to get temperatures
-    onewireSensors.requestTemperatures();
-    return onewireSensors.getTempCByIndex(0);
-  }
-  return 99; // Indicates a bad read.
-}
-
+  // Send the command to get temperatures
+  onewireSensors.requestTemperatures();
+  return onewireSensors.getTempCByIndex(0);
+}
+


Fix Arduino build

Fix Arduino build

Change-Id: Ib30d8f56ef92fb347436f452dbf8b2ba30b79bd3
GitOrigin-RevId: 4782b900db6c565f9c0b249cba51624d4d6d941c

--- sketches/CameraPoses/CameraPoses.ino
+++ sketches/CameraPoses/CameraPoses.ino
@@ -1,5 +1,5 @@
-#include <SD.h>
-#include <camera.h>
+#include <coralmicro_SD.h>
+#include <coralmicro_camera.h>

 #include <cstdint>
 #include <memory>
@@ -139,4 +139,4 @@
             Serial.println(score);
         }
     }
-}+}


[cyclop_plus_plus] - remove space before bat percentage text - no need to waste an extra char here

--- src/cyclop_plus_plus/cyclop_plus_plus.ino
+++ src/cyclop_plus_plus/cyclop_plus_plus.ino
@@ -1216,7 +1216,6 @@
     osd_char(OSD_BATTERY_0);

   if (showNumbers) {
-    osd_string(" ");
     osd_int(value);
     osd_string("%");
   }


Added an task to randommly blick an LED

Added an task to randommly blick an LED

--- examples/Blink/Blink.ino
+++ examples/Blink/Blink.ino
@@ -44,7 +44,7 @@
 {
   // Update the LED
   digitalWrite(pin, state);
-
+
   // Update the state
   state = LOW == state ? HIGH : LOW;

@@ -52,10 +52,45 @@
   return delay;
 }

-Blink blink1 = Blink(10, 125);
-Blink blink2 = Blink(11, 250);
-Blink blink3 = Blink(12, 500);
-Blink blink4 = Blink(13, 1000);
+class RandomBlink : public Task
+{
+  private:
+    int state;
+    int pin;
+
+  public:
+    RandomBlink(int pin)
+    {
+      this->state = LOW;
+      this->pin = pin;
+    }
+    void setup();
+    unsigned long loop(WakeReason reason);
+};
+
+void RandomBlink::setup()
+{
+  // initialize the digital pin as an output.
+  pinMode(pin, OUTPUT);
+}
+
+unsigned long RandomBlink::loop(WakeReason reason)
+{
+  // Update the LED
+  digitalWrite(pin, state);
+
+  // Update the state
+  state = LOW == state ? HIGH : LOW;
+
+  // return when we next want to be called
+  return random(1000);
+}
+
+Blink blink1 = Blink(9, 125);
+Blink blink2 = Blink(10, 250);
+Blink blink3 = Blink(11, 500);
+Blink blink4 = Blink(12, 1000);
+RandomBlink randomBlink = RandomBlink(13);

 // the setup function runs once when you press reset or power the board
 void setup() {
@@ -63,6 +98,7 @@
   MicroTasks.startTask(&blink2);
   MicroTasks.startTask(&blink3);
   MicroTasks.startTask(&blink4);
+  MicroTasks.startTask(&randomBlink);
 }

 // the loop function runs over and over again forever


add ugly delay as it seems the publish is asynchronous

--- examples/ECS_therm/ECS_therm.ino
+++ examples/ECS_therm/ECS_therm.ino
@@ -25,8 +25,17 @@
 #define MQTT_SERVER  "192.168.1.27"
 #define MQTT_PORT 1883

+#define ECS_FORCE_DISABLED 	'0'
+#define ECS_FORCE_OFF 		'1'
+#define ECS_FORCE_ON  		'2'
+#define ECS_STATE_ON		'2'
+#define ECS_STATE_OFF		'1'
+

 long lastMsg = 0;
+char ecsForce = ECS_FORCE_DISABLED;
+char ecsState = ECS_STATE_OFF;
+char msg[2];

 void processEcsStateMsg(char* topic, byte* payload, unsigned int length)
 {
@@ -34,18 +43,62 @@
   Serial.print("Checking if state topic");
   if(String(topic) == "ECS/state"){
 	  Serial.println("Received ECS/State change message");
-	  if ((char)payload[0] == '1') {
-		Serial.println("ECS ON received");
-
-	  }
-	  else{
-		  Serial.println("ECS OFF received");
-	  }
+	  if(ecsForce == ECS_FORCE_DISABLED)
+	  {
+		 Serial.println("changing ECS relay state");
+	     if ((char)payload[0] == ECS_STATE_ON) {
+		    Serial.println("ECS ON received");
+			ecsState = ECS_STATE_ON;
+	     }
+	     else{
+		    Serial.println("ECS OFF received");
+			ecsState = ECS_STATE_OFF;
+	     }
+     }
+	  else
+	 {
+			Serial.println("FORCED is set. No action on relay. Rolling back state on MQTT server");
+			//Rewrite current state only if delta with current state. Else we go into infinite loop...
+			  if(ecsState != (char)payload[0])
+			  {
+		              msg[0] = ecsState;
+					  msg[1] = 0;
+					  myMqtt->publish("ECS/state", msg);
+			  }
+	 }

   }
-  else{
+  else if(String(topic) == "ECS/force"){
+	  Serial.println("Received ECS/State change message");
+
+	  if ((char)payload[0] == ECS_FORCE_OFF) {
+		Serial.println("Force OFF received");
+	    msg[0] = ECS_STATE_OFF;
+		msg[1] = 0;
+		myMqtt->publish("ECS/state", msg);
+		//TODO : ugly
+	    delay(1000);
+		ecsForce = ECS_FORCE_OFF;
+
+	  }
+	  else if ((char)payload[0] == ECS_FORCE_ON) {
+		Serial.println("Force ON received");
+		msg[0] = ECS_STATE_ON;
+		msg[1] = 0;
+		myMqtt->publish("ECS/state", msg);
+		//TODO : ugly
+		delay(1000);
+		ecsForce = ECS_FORCE_ON;
+	  }
+	  else
+	  {
+		  Serial.println("Force disabled");
+		  ecsForce = ECS_FORCE_DISABLED;
+	  }
+  }
+  else {
 	  Serial.println("not for me...");
-  }
+  }

 }
@@ -56,7 +109,7 @@
   myMqtt = new MqttConnection(SENSOR_ID, WLAN_SSID, WLAN_PASS, MQTT_SERVER, MQTT_PORT);
   myMqtt->registerCustomProcessing(&processEcsStateMsg);
   myMqtt->addSubscription("state");
-
+  myMqtt->addSubscription("force");
 }

 void loop() {


Fix #419

Fix #419

--- examples/Widgets/Email/Email.ino
+++ examples/Widgets/Email/Email.ino
@@ -42,6 +42,8 @@
 // Go to the Project Settings (nut icon).
 char auth[] = "YourAuthToken";

+unsigned count = 0;
+
 void emailOnButtonPress()
 {
   // *** WARNING: You are limited to send ONLY ONE E-MAIL PER 5 SECONDS! ***
@@ -54,7 +56,12 @@
   if (isButtonPressed) // You can write any condition to trigger e-mail sending
   {
     Serial.println("Button is pressed."); // This can be seen in the Serial Monitor
-    Blynk.email("your_email@mail.com", "Subject: Button Logger", "You just pushed the button...");
+
+    count++;
+
+    String body = String("You pushed the button ") + count + " times.";
+
+    Blynk.email("your_email@mail.com", "Subject: Button Logger", body);

     // Or, if you want to use the email specified in the App (like for App Export):
     //Blynk.email("Subject: Button Logger", "You just pushed the button...");


src/MQTT433gateway.cpp: Simplify statements

Signed-off-by: Jan Losinski <577c4104c61edf9f052c616c0c23e67bef4a9955@wh2.tu-dresden.de>

--- MQTT433gateway.ino
+++ MQTT433gateway.ino
@@ -134,19 +134,11 @@
   }
   if (topic == (mainTopic + F("/set/raw"))) {
     Serial.println(F("Change raw mode."));
-    if (payload[0] == '1') {
-      rawMode = true;
-    } else {
-      rawMode = false;
-    }
+    rawMode = payload[0] == '1';
   }
   if (topic == (mainTopic + F("/set/log"))) {
     Serial.println(F("Change log mode."));
-    if (payload[0] == '1') {
-      logMode = true;
-    } else {
-      logMode = false;
-    }
+    logMode = payload[0] == '1';
   }
   if (topic == (mainTopic + F("/ota/url"))) {
     otaURL = String(payload);


fix small bugs in physical programming example

- add #define around our custom sticker code so the .ino ports
to other arduino platforms more easily

- add support for two neopixels by mirroring the recorded value
to the first pixel in the chain connected to the output.

--- app/examples/chibitronics/PhysicalProgramming/physical-programming.ino
+++ app/examples/chibitronics/PhysicalProgramming/physical-programming.ino
@@ -20,7 +20,7 @@
 uint8_t led_vals[LOOP_LENGTH];
 uint8_t rgb_vals[LOOP_LENGTH];

-Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, LED_BUILTIN_RGB, NEO_GRB + NEO_KHZ800);
+Adafruit_NeoPixel strip = Adafruit_NeoPixel(2, LED_BUILTIN_RGB, NEO_GRB + NEO_KHZ800);

 int led = A2;
 int ledInput = A1;
@@ -112,9 +112,16 @@

   pinMode(A0, OUTPUT);
   digitalWrite(A0, HIGH);  // provide an easy +3V reference for pots on A0
-
+
+  // this example works fine without the following line of code, but
+  // the RGB LED is quite sensitive to noise and activating a hidden pullup
+  // feature on the LTC sticker improves the aesthetics by reducing the idle
+  // noise of the analog input line.
+#ifdef __CHIBITRONICS_LTC__
   // activate a hidden feature pullup on PTB2 to stabilize color when input is floating
-  *((unsigned int *)0x4004A008) |= 0x103;
+  *((unsigned int *)0x4004A008) |= 0x103; // bonus points for figuring out what this bit of magic does!
+#endif
+
 }

@@ -127,6 +134,7 @@
   analogWrite(led, led_vals[index]);
   rgb = hueToRgb(rgb_vals[index]);
   strip.setPixelColor(0, strip.Color(rgb.r, rgb.g, rgb.b));
+  strip.setPixelColor(1, strip.Color(rgb.r, rgb.g, rgb.b));
   strip.show();
 }

@@ -187,6 +195,7 @@
   analogWrite(led, led_vals[index]);
   rgb = hueToRgb(rgb_vals[index]);
   strip.setPixelColor(0, strip.Color(rgb.r, rgb.g, rgb.b));
+  strip.setPixelColor(1, strip.Color(rgb.r, rgb.g, rgb.b));
   strip.show();
 }


update

update

--- jtk/jtk.ino
+++ jtk/jtk.ino
@@ -1,9 +1,9 @@
 /*
 Jhonatan da Silva
 Last Updated version :
-Wed Feb  8 23:39:02 2017
+Thu Feb  9 19:29:43 2017
 Number of code lines:
-41
+47
 */
 #include <LiquidCrystal.h>
 LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
@@ -14,7 +14,6 @@
 long tempoTotal;
 int distancia;
 int serialRead = 0;
-
 float ultrassonic();

 void setup(){
@@ -28,16 +27,23 @@
 }

 void loop(){
-  if (Serial.available() > 0) {
-    serialRead = Serial.read();
-    if (serialRead == 85){ // Letra U
-      distancia = ultrassonic();
-      lcd.clear();
-      lcd.print(distancia);
+    if (Serial.available() > 0) {
+        serialRead = Serial.read();
+        lcd.clear();
+        lcd.print(serialRead);
+        switch(serialRead){
+
+            case 85:
+                distancia = ultrassonic();
+                break;
+
+            case 76:
+                lcd.clear();
+                lcd.print(?);
+                break;
+        }
     }
-  }
 }
-
 float ultrassonic(){
   digitalWrite(disparar, HIGH);
   delayMicroseconds(10);


V2.1: new 3CH configuration

V2.1: new 3CH configuration

--- RC_Transmitter.ino
+++ RC_Transmitter.ino
@@ -513,7 +513,7 @@
   reading[arrayNo] = analogRead(input) + offset[arrayNo]; // read joysticks and add the offset
   reading[arrayNo] = constrain(reading[arrayNo], (1023 - range), range); // then limit the result before we do more calculations below

-#ifdef CONFIG_2_CH // In most "car style" transmitters, less than a half of the throttle potentiometer range is used for the reverse. So we have to enhance this range!
+#ifndef CONFIG_4_CH // In most "car style" transmitters, less than a half of the throttle potentiometer range is used for the reverse. So we have to enhance this range!
   if (reading[2] < (range / 2) ) {
     reading[2] = constrain(reading[2], (range / 3), (range / 2)); // limit reverse range, which will be multiplied later
     reading[2] = map(reading[2], (range / 3), (range / 2), 0, (range / 2)); // reverse range multiplied by 4


Calibrated Vcc to 1.1v bandgap against multimeter


Update sense_your_city.ino

Update sense_your_city.ino

fixed a bug within air quality sensor reading interval 2s

--- sense_your_city/sense_your_city.ino
+++ sense_your_city/sense_your_city.ino
@@ -213,6 +213,7 @@
   //Wait two seconds to evaluate Air Quality sensor's outputs
   if (air_quality_sensor_state == AQ_WORK && (millis() - air_quality_sensor_evaluate_starttime) > 2000)
   {
+    air_quality_sensor_evaluate_starttime = millis();
     air_quality_sensor_evaluation();
   }


Removed include

Removed include

Removed include.  Build doesn't seem to import the libraries when you
choose "use this example".


adding writing capability

adding writing capability

--- Arduino/I2CSensorsMicro/I2CSensorsMicro.ino
+++ Arduino/I2CSensorsMicro/I2CSensorsMicro.ino
@@ -17,6 +17,8 @@

 #include <Wire.h>
 #include "RTClib.h"
+#include <SPI.h>
+#include <SD.h>

 RTC_DS1307 rtc;

@@ -26,10 +28,19 @@
 int atlas[] = {0x61, 0x62, 0x63, 0x64};
 int num_probes = 4;

+// our SS pin on the micro is at output 17
+//byte SS = 17;
+File outputFile;
+
 void setup() {
   Serial.begin(9600);
   Wire.begin();
   rtc.begin();
+  if (!SD.begin(SS)) {
+    Serial.println("SD card initialization failed!");
+    return;
+  }
+  outputFile = SD.open("output.txt", FILE_WRITE);
   Serial.flush();
   Serial.println(F("\n\nDate\tTime\tDO\tORP\tpH\tEC\tTDS\tSAL\tSG"));
 }
@@ -44,6 +55,7 @@
   unsigned long time = millis();
  String date = rtc_time();
  Serial.print(date);
+ outputFile.print(date);

   while ((millis() - time) < 1500) {
     delay(1501-(millis() - time));
@@ -52,9 +64,12 @@
   for (int i=0; i < num_probes; i++) {
     String res = read_atlas(atlas[i]);
     Serial.print("\t" + res);
+    outputFile.print("\t" + res);
   }
   Wire.flush();

+  outputFile.println();
+  outputFile.flush();
   Serial.println();
   delay(5000);
 }


Added MPU 6050 IMU Support

Added MPU 6050 IMU Support

--- telemetryUnit.ino
+++ telemetryUnit.ino
@@ -3,31 +3,44 @@
 #include <SoftwareSerial.h>
 #include <SD.h>
 #include <avr/sleep.h>
-
+#include <Wire.h>
+////////////////////////////
+// MPU 6050 related stuff //
+////////////////////////////
+// MPU 6050 I2C address
+#define MPU 0x68
+//Conversion ratios for accelerometer and gyroscope
+#define A_R 16384.0
+#define G_R 131.0
+//Radion to degree conversion 180/PI
+#define RAD_A_DEG = 57.295779
+//MPU 6050 outputs 16bit integer raw values
+int16_t AcX, AcY, AcZ, GyX, GyY, GyZ;
+float Acc[2];
+float Gy[2];
+float Angle[2];
+///////////////////////
+// GPS related stuff //
+///////////////////////
 SoftwareSerial mySerial(8, 7);
 Adafruit_GPS GPS(&mySerial);
-
 // Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
 // Set to 'true' if you want to debug and listen to the raw GPS sentences
 #define GPSECHO  true
 /* set to true to only log to SD when GPS has a fix, for debugging, keep it false */
 #define LOG_FIXONLY false
-
 void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy
-
 // Set the pins used
 #define chipSelect 10
 #define ledPin 13
-
 ////////////////////////////
-// Lof File related stuff //
+// Log File related stuff //
 ////////////////////////////
 #define LOG_FILE_PREFIX "gpslog"
 #define MAX_LOG_FILES 100
 #define LOG_FILE_SUFFIX "csv"
 char logFileName[13];
-
-#define LOG_COLUMN_COUNT 10
+#define LOG_COLUMN_COUNT 14
 char * log_col_names[LOG_COLUMN_COUNT] = {
   "longitude",
   "latitude",
@@ -38,15 +51,17 @@
   "time",
   "satellites",
   "fix",
-  "fixquality"
+  "fixquality",
+  "Acc1",
+  "Acc2",
+  "Angle1",
+  "Angle2"
 };
-
 //////////////////////
 // Log Rate Control //
 //////////////////////
 #define LOG_RATE 1000 // Log every second
 unsigned long lastLog = 0; // Global var to keep of last time we logged
-
 // blink out an error code
 void error(uint8_t errno) {
   while(1) {
@@ -62,20 +77,19 @@
     }
   }
 }
-
 void setup() {
+  // Initialize MPU
+  setupMPU();
   // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
   // also spit it out
   Serial.begin(115200);
   Serial.println("\r\nTelemetry unit");
   pinMode(ledPin, OUTPUT);
-
   // make sure that the default chip select pin is set to
   // output, even if you don't use it:
   pinMode(10, OUTPUT);
-
   // see if the card is present and can be initialized:
-  if (!SD.begin(chipSelect)) {
+  if (!SD.begin(chipSelect)) {
     Serial.println("Card init. failed!");
     error(2);
   }
@@ -89,7 +103,6 @@
       break;
     }
   }
-
   logfile = SD.open(filename, FILE_WRITE);
   if( ! logfile ) {
     Serial.print("Couldnt create ");
@@ -98,29 +111,21 @@
   }
   Serial.print("Writing to ");
   Serial.println(filename);
-
   // connect to the GPS at the desired rate
   GPS.begin(9600);
-
   // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
   GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
   GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 100 millihertz (once every 10 seconds), 1Hz or 5Hz update rate
-
   // Turn off updates on antenna status, if the firmware permits it
   GPS.sendCommand(PGCMD_NOANTENNA);
-
   // Force usage of interruptions for GPS read
   useInterrupt(true);
-
   Serial.println("Ready!");
 }
-
-
 // Interrupt is called once a millisecond, looks for any new GPS data, and stores it
 SIGNAL(TIMER0_COMPA_vect) {
   char c = GPS.read();
 }
-
 void useInterrupt(boolean v) {
   // v is always true
   if (v) {
@@ -131,19 +136,16 @@
     usingInterrupt = true;
   }
 }
-
 void loop() {
   // If it's been LOG_RATE milliseconds since the last log:
   if ((lastLog + LOG_RATE) <= millis())
   {
     // if a sentence is received, we can check the checksum, parse it...
     if (GPS.newNMEAreceived() && GPS.parse(GPS.lastNMEA())) {
-
       if (LOG_FIXONLY && !GPS.fix) {
         Serial.println("No Fix");
         return;
       }
-
       if (logGPSData()) // Log the GPS data
       {
         lastLog = millis(); // Update the lastLog variable
@@ -152,11 +154,9 @@
       { // Print an error, don't update lastLog
         Serial.println("Failed to log new GPS data.");
       }
-
-    }
-  }
-}
-
+    }
+  }
+}
 byte logGPSData()
 {
   if (GPSECHO)
@@ -185,9 +185,16 @@
     Serial.print((int)GPS.fix);
     Serial.print(',');
     Serial.print((int)GPS.fixquality);
+    Serial.print(',');
+    Serial.print(Acc[0]);
+    Serial.print(',');
+    Serial.print(Acc[1]);
+    Serial.print(',');
+    Serial.print(Angle[0]);
+    Serial.print(',');
+    Serial.print(Angle[1]);
     Serial.println();
   }
-
   File logFile = SD.open(logFileName, FILE_WRITE);
   if (logFile)
   {
@@ -215,20 +222,24 @@
     logFile.print((int)GPS.fix);
     logFile.print(',');
     logFile.print((int)GPS.fixquality);
+    logFile.print(',');
+    logFile.print(Acc[0]);
+    logFile.print(',');
+    logFile.print(Acc[1]);
+    logFile.print(',');
+    logFile.print(Angle[0]);
+    logFile.print(',');
+    logFile.print(Angle[1]);
     logFile.println();
     logFile.close();
-
     return 1; // Return success
   }
-
   return 0; // If we failed to open the file, return fail
 }
-
 // printHeader() - prints our column names to the top of our log file
 void printHeader()
 {
   File logFile = SD.open(logFileName, FILE_WRITE); // Open the log file
-
   if (logFile) // If the log file opened, print our column names to the file
   {
     int i = 0;
@@ -243,7 +254,6 @@
     logFile.close(); // close the file
   }
 }
-
 // updateFileName() - Looks through the log files already present on a card,
 // and creates a new file with an incremented file index.
 void updateFileName()
@@ -267,6 +277,41 @@
   Serial.print("File name: ");
   Serial.println(logFileName); // Debug print the file name
 }
-
-
-/* End code */
+void setupMPU()
+{
+  Wire.begin();
+  Wire.beginTransmission(MPU);
+  Wire.write(0x6B);
+  Wire.write(0);
+  Wire.endTransmission(true);
+}
+void getMPUData()
+{
+  //Read accelerometer data from MPU 6050
+  Wire.beginTransmission(MPU);
+  Wire.write(0x3B); //Read register 0x3B (AcX)
+  Wire.endTransmission(false);
+  Wire.requestFrom(MPU,6,true); //Read 6 register from 0x3B (included)
+  // Each value is 2 register long
+  AcX=Wire.read()<<8|Wire.read();
+  AcY=Wire.read()<<8|Wire.read();
+  AcZ=Wire.read()<<8|Wire.read();
+  //Colculate angles X and Y using the tangent formulae
+  Acc[1] = atan(-1*(AcX/A_R)/sqrt(pow((AcY/A_R),2) + pow((AcZ/A_R),2)))*RAD_TO_DEG;
+  Acc[0] = atan((AcY/A_R)/sqrt(pow((AcX/A_R),2) + pow((AcZ/A_R),2)))*RAD_TO_DEG;
+  //Read gyroscope data from MPU 6050
+  Wire.beginTransmission(MPU);
+  Wire.write(0x43); //Read register 0x43 (GyX)
+  Wire.endTransmission(false);
+  Wire.requestFrom(MPU,4,true); //Read 4 registers from 0x43 (included)
+  GyX=Wire.read()<<8|Wire.read();
+  GyY=Wire.read()<<8|Wire.read();
+  //Apply conversion ratio for Gyro
+  Gy[0] = GyX/G_R;
+  Gy[1] = GyY/G_R;
+  //Apply complementary filter
+  Angle[0] = 0.98 *(Angle[0]+Gy[0]*0.010) + 0.02*Acc[0];
+  Angle[1] = 0.98 *(Angle[1]+Gy[1]*0.010) + 0.02*Acc[1];
+  delay(10); //Delta is 10 milliseconds
+}
+/* End code */


seperator changed

seperator changed

--- sensebox/sensebox.ino
+++ sensebox/sensebox.ino
@@ -31,16 +31,16 @@

 File dataFile;
 String dataRow;
-String seperator = ",";
+String seperator = ";";
 String dattim = "noval";
 int rowCounter = 1;

 SoftwareSerial ss(2, 3);

 //Button variables
-const int buttonPin = 8;
+const int buttonPin = 8;// the number of the pushbutton pin
 int buttonState = 0;
-int lastButtonState = 0; // variable for reading the pushbutton status
+int lastButtonState = 0;
 int isOn;

 /*
@@ -87,7 +87,7 @@
   // If the file opened okay, write to it:
   if (dataFile) {
     //Serial.print("Writing to test.txt...");
-    dataFile.println("Logging: row, lat, lon, time, sound, brightness, vibration, altitude.");
+    dataFile.println("row;lat;lon;timestamp;sound;brightness;vibration;altitude");
     // close the file:
     dataFile.close();
     //Serial.println("done.");
@@ -177,7 +177,7 @@
       // GPS reading done
       newData = false;

-      // Get Accel/Gyro data
+      //Accel/Gyro
       getAccel_Data();
       getGyro_Data();

@@ -216,7 +216,6 @@
   } else {
     digitalWrite(LED, LOW);   // turn the LED on (HIGH is the voltage level)
     Serial.println(F("OFF"));
-
   }

 }


DRYing, adding an a/b blink, adding a repeat command

--- Arduino/linkit_duo_led5/linkit_duo_led5.ino
+++ Arduino/linkit_duo_led5/linkit_duo_led5.ino
@@ -4,7 +4,7 @@

 #define RANDOM_SEED_PIN A1

-#define LED_COUNT 144
+#define LED_COUNT 64
 #define MAX_LED (LED_COUNT)
 rgb_color colors[LED_COUNT];
 rgb_color render[LED_COUNT];
@@ -103,10 +103,11 @@
 }

 #define NO_STATE 0
-#define BLINK_ON 1
-#define BREATHE_ON 2
-
-// blink group
+#define BREATHE_ON 1
+
+#define BLINK_ON 2
+
+// blink group 1-6
 #define BLINK_ON_1 11
 #define BLINK_ON_2 12
 #define BLINK_ON_3 13
@@ -114,7 +115,14 @@
 #define BLINK_ON_5 15
 #define BLINK_ON_6 16

-#define STATIC_ON 21
+// blink group a-b
+#define BLINK_ON_A 21
+#define BLINK_ON_B 22
+
+#define BLINK_MIN BLINK_ON
+#define BLINK_MAX BLINK_ON_B
+
+#define STATIC_ON 101

 void push_color(rgb_color color, bool display = false){
   for(int i = MAX_LED - 1; i >= 1; i--){
@@ -137,43 +145,23 @@
 #define BLINK_4 3999
 #define BLINK_5 4999
 #define BLINK_6 5999
+#define BLINK_A BLINK_1
+#define BLINK_B BLINK_4
 int blink_counter = 0;
 bool blink_state = true; // false means blank

-// blink group
+// blink groups
 bool blink_state_1 = true;
 bool blink_state_2 = true;
 bool blink_state_3 = true;
 bool blink_state_4 = true;
 bool blink_state_5 = true;
 bool blink_state_6 = true;
-
-void start_blinking(){
-  effects[0] = BLINK_ON;
-}
-
-void start_blinking_1(){
-  effects[0] = BLINK_ON_1;
-}
-
-void start_blinking_2(){
-  effects[0] = BLINK_ON_2;
-}
-
-void start_blinking_3(){
-  effects[0] = BLINK_ON_3;
-}
-
-void start_blinking_4(){
-  effects[0] = BLINK_ON_4;
-}
-
-void start_blinking_5(){
-  effects[0] = BLINK_ON_5;
-}
-
-void start_blinking_6(){
-  effects[0] = BLINK_ON_6;
+bool blink_state_a = true;
+bool blink_state_b = true;
+
+void start_effect(int effect){
+  effects[0] = effect;
 }

 void start_blinking_r(){
@@ -214,8 +202,6 @@
   0.0,
   0.0,  // a few extra make it feel more natural
   0.0,
-//  0.0,
-//  0.0,
   0,0
 };

@@ -240,16 +226,21 @@
   colors[1] = colors[0];
 }

+// only works proper used immediately after placing a standard color
 void do_max(){
   colors[0] = scale_color(colors[0], MAX_BRIGHTNESS_PERCENT / 100.0);
 }

 void do_dim(){
-  colors[0] = scale_color(colors[0], DIM_BRIGHTNESS_PERCENT / 100.0);
+  colors[0].red = colors[0].red >> 1;
+  colors[0].green = colors[0].green >> 1;
+  colors[0].blue = colors[0].blue >> 1;
 }

 void do_bright(){
-  colors[0] = scale_color(colors[0], BRIGHT_BRIGHTNESS_PERCENT / 100.0);
+  colors[0].red = colors[0].red << 1;
+  colors[0].green = colors[0].green << 1;
+  colors[0].blue = colors[0].blue << 1;
 }

 void fade(float rate = FADE_RATE){
@@ -279,68 +270,47 @@
   return palette[random(NPRETTY_COLORS)];
 }

-int do_random(){
+void do_random(){
   push_color(random_color());
 }

-int do_mirror(){
+void do_mirror(){
   for(int i = 0; i < LED_COUNT / 2; i++){
     colors[LED_COUNT - i - 1] = colors[i];
     effects[LED_COUNT - i - 1] = effects[i];
   }
 }

+void do_repeat(){
+  push_color(colors[0]);
+  effects[0] = effects[1];
+}
+
 void setup_buffer(){
   for(int i = 0; i < LED_COUNT; i++){
-    if(effects[i] == BLINK_ON){
-      if(blink_state){
-        render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
-      } else {
-        render[i] = scale_color(colors[i], MINIMUM_BRIGHTNESS_SCALE);
-      }
-    } else if(effects[i] == BLINK_ON_1){
-      if(blink_state_1){
-        render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
-      } else {
-        render[i] = scale_color(colors[i], MINIMUM_BRIGHTNESS_SCALE);
-      }
-    } else if(effects[i] == BLINK_ON_2){
-      if(blink_state_2){
-        render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
-      } else {
-        render[i] = scale_color(colors[i], MINIMUM_BRIGHTNESS_SCALE);
-      }
-    } else if(effects[i] == BLINK_ON_3){
-      if(blink_state_3){
-        render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
-      } else {
-        render[i] = scale_color(colors[i], MINIMUM_BRIGHTNESS_SCALE);
-      }
-    } else if(effects[i] == BLINK_ON_4){
-      if(blink_state_4){
-        render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
-      } else {
-        render[i] = scale_color(colors[i], MINIMUM_BRIGHTNESS_SCALE);
-      }
-    } else if(effects[i] == BLINK_ON_5){
-      if(blink_state_5){
-        render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
-      } else {
-        render[i] = scale_color(colors[i], MINIMUM_BRIGHTNESS_SCALE);
-      }
-    } else if(effects[i] == BLINK_ON_6){
-      if(blink_state_6){
-        render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
-      } else {
-        render[i] = scale_color(colors[i], MINIMUM_BRIGHTNESS_SCALE);
-      }
-    } else if(effects[i] == BREATHE_ON){
-      render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE * breathe_steps[BREATHE_MAX_STEP - breathe_step]);
-    } else if(effects[i] == STATIC_ON){
-      render[i] = random_color();
-    } else {
-      render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
-    }
+    int effect = effects[i];
+
+    if(effect ==  STATIC_ON) colors[i] = random_color();
+
+    if(effect >= BLINK_MIN && effect <= BLINK_MAX){
+      if((effect == BLINK_ON && blink_state) ||
+            (effect == BLINK_ON_1 && blink_state_1) ||
+            (effect == BLINK_ON_2 && blink_state_2) ||
+            (effect == BLINK_ON_3 && blink_state_3) ||
+            (effect == BLINK_ON_4 && blink_state_4) ||
+            (effect == BLINK_ON_5 && blink_state_5) ||
+            (effect == BLINK_ON_6 && blink_state_6) ||
+            (effect == BLINK_ON_A && blink_state_a) ||
+            (effect == BLINK_ON_B && blink_state_b)) {
+          render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
+        } else {
+          render[i] = scale_color(colors[i], MINIMUM_BRIGHTNESS_SCALE);
+        }
+    }
+
+    else if(effects[i] == BREATHE_ON) render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE * breathe_steps[BREATHE_MAX_STEP - breathe_step]);
+
+    else render[i] = scale_color(colors[i], DEFAULT_BRIGHTNESS_SCALE);
   }
 }

@@ -378,7 +348,7 @@
   erase(true);
 }

-#define MAX_STRING_LENGTH 10
+#define MAX_STRING_LENGTH 16

 bool is_command(char *str, char *command){
   return strcmp(str, command) == 0;
@@ -386,11 +356,13 @@

 void loop(){
   char str[MAX_STRING_LENGTH];
+  char arg[MAX_STRING_LENGTH];
   rgb_color color;

   if(Serial1.available() > 0){
     int c = Serial1.readBytesUntil('|', str, MAX_STRING_LENGTH);
     str[c] = 0;
+    strcpy(arg, "");

     // reset the effects so the automatic render won't interfere
     blink_state = true;
@@ -400,6 +372,8 @@
     blink_state_4 = false;
     blink_state_5 = false;
     blink_state_6 = false;
+    blink_state_a = false;
+    blink_state_b = false;
     blink_counter = 0;
     breathe_step = 0;
     breathe_counter = 0;
@@ -417,19 +391,27 @@
 // show something if the data hasn't updated in a long time
 // automatically stop and restart the script at night
 // blink a/b
+// show something if the data has been unchanged for some time, like after hours
+// detect if the group of builds has been added to, then do an insertion animation
+// after pause, allow breathing and blinking to come to a halt first
+// rotation
+// transitions
+// if something is not recognized assume it's an argument for the next command

     if     (is_command(str, "pause"))    paused = true;
     else if(is_command(str, "continue")) paused = false;
     else if(is_command(str, "erase"))    erase(true);
-    else if(is_command(str, "blink"))    start_blinking();
-    else if(is_command(str, "blink1"))   start_blinking_1();
-    else if(is_command(str, "blink2"))   start_blinking_2();
-    else if(is_command(str, "blink3"))   start_blinking_3();
-    else if(is_command(str, "blink4"))   start_blinking_4();
-    else if(is_command(str, "blink5"))   start_blinking_5();
-    else if(is_command(str, "blink6"))   start_blinking_6();
+    else if(is_command(str, "blink"))    start_effect(BLINK_ON);
+    else if(is_command(str, "blink1"))   start_effect(BLINK_ON_1);
+    else if(is_command(str, "blink2"))   start_effect(BLINK_ON_2);
+    else if(is_command(str, "blink3"))   start_effect(BLINK_ON_3);
+    else if(is_command(str, "blink4"))   start_effect(BLINK_ON_4);
+    else if(is_command(str, "blink5"))   start_effect(BLINK_ON_5);
+    else if(is_command(str, "blink6"))   start_effect(BLINK_ON_6);
     else if(is_command(str, "blinkr"))   start_blinking_r();
-    else if(is_command(str, "breathe"))  start_breathing();
+    else if(is_command(str, "blinka"))   start_effect(BLINK_ON_A);
+    else if(is_command(str, "blinkb"))   start_effect(BLINK_ON_B);
+    else if(is_command(str, "breathe"))  start_effect(BREATHE_ON);
     else if(is_command(str, "flush"))    flush();
     else if(is_command(str, "blend"))    do_blend();
     else if(is_command(str, "max"))      do_max();
@@ -439,6 +421,7 @@
     else if(is_command(str, "flood"))    do_flood();
     else if(is_command(str, "random"))   do_random();
     else if(is_command(str, "mirror"))   do_mirror();
+    else if(is_command(str, "repeat"))   do_repeat();
     else if(is_command(str, "static"))   start_static();
     else if(is_command(str, "red"))      push_color(red);
     else if(is_command(str, "green"))    push_color(green);
@@ -474,6 +457,8 @@
     if(blink_counter == BLINK_1){
       blink_state_6 = false;
       blink_state_1 = true;
+      blink_state_a = true;
+      blink_state_b = false;
       should_flush = true;
     }

@@ -492,6 +477,8 @@
     if(blink_counter == BLINK_4){
       blink_state_3 = false;
       blink_state_4 = true;
+      blink_state_a = false;
+      blink_state_b = true;
       should_flush = true;
     }


clean up loop code for leo

clean up loop code for leo

--- pi_interrupt_mouse/pi_interrupt_mouse.ino
+++ pi_interrupt_mouse/pi_interrupt_mouse.ino
@@ -11,6 +11,10 @@

 AltSoftSerial mySerial;
 int missedPackets = 0;
+
+// commands from the pi terminate with '.'
+char cmd[11] = "";
+char cmd2[11] = ""; // sse parity \o/

 enum states {
   NO_CLICK,
@@ -45,6 +49,8 @@
   //Serial.println("Ready");
 }

+
+
 void loop() {
   if (state == CLICK){
     delay(500); //delay so if there's another interrupt it will change state
@@ -65,15 +71,10 @@
       break;
   }

-  // commands from the pi terminate with '.'
-  char cmd[11] = "";
-  char cmd2[11] = ""; // sse parity \o/
-
   // check if byte available on the software serial port
   //receives zero-padded string of 16 bit coordinates (xy) ending with a '.'
   if (mySerial.available()) {
     mySerial.readBytesUntil('.', cmd, 11);
-    while (!mySerial.available()) {}
     mySerial.readBytesUntil('.', cmd2, 11);

     String cmdStr = String(cmd);
@@ -93,7 +94,6 @@
       if (missedPackets >= 15){
         missedPackets = 0;
         mySerial.readBytesUntil('.', cmd, 11);
-        loop();
       }
       //Serial.println("Packet miss");
     }


Home function adjustments.  Now ShinkeyBot's arm returns to 90 degrees and sets the encoder at zero when vertical

--- MotorUnitController/MotorUnitController.ino
+++ MotorUnitController/MotorUnitController.ino
@@ -75,19 +75,19 @@
     if (tgtPos != pos)
     {
       //Serial.print(pos);Serial.print("--");
-      //Serial.println(desiredpos);
+      //Serial.println(tgtPos);
       servo.write(pos);

       pos+=direction;

-      if (pos>=minPos)
+      if (pos<minPos)
       {
         //Serial.print("Reset down:");
         //Serial.println(counter++);
         direction=-1;
       }

-      if (pos<=maxPos)
+      if (pos>maxPos)
       {
         //Serial.print("Reset up:");
         //Serial.println(counter++);
@@ -127,7 +127,11 @@
   //AFMS.begin(1000);  // OR with a different frequency, say 1KHz

   wrist.servo.attach(10);
+  wrist.pos=90;
+  wrist.tgtPos=90;
   elbow.servo.attach(9);
+  elbow.pos=90;
+  elbow.tgtPos=90;

   pinMode(laserPin, OUTPUT);

@@ -162,25 +166,29 @@

 // =========== DC Control using the encoder.
 int targetpos = 0;
+int TORQUE=200;

 void setTargetPos(int newtargetpos)
 {
   targetpos = newtargetpos;
 }

-void updatedc(Adafruit_DCMotor *dcmotor, int currentpos)
+bool updatedc(Adafruit_DCMotor *dcmotor, int currentpos)
 {
   if (targetpos != currentpos)
   {
-    dcmotor->setSpeed(90);
+    dcmotor->setSpeed(TORQUE);

     if (targetpos < currentpos)
       dcmotor->run(FORWARD);
     else
       dcmotor->run(BACKWARD);

+    return false;
+
   } else {
     dcmotor->setSpeed(0);
+    return true;
   }

 }
@@ -225,8 +233,9 @@
   // Format A1000 >> A1220   --> Close grip
   // A2255 >> Open Grip
   // A6090 >> 90 deg wrist A6010 --> A6180
-  // A3220 or A4220 Move forward backward shoulder
-  // A7150 will keep the elbow at zero encoder angle arm vertical. So AA140 will pull it up
+  // A3220 or A4220 Move forward backward shoulder NO LONGER
+  // A7150 will keep the shoulder at zero encoder angle arm vertical.
+  //       So AA140 will pull it up
   // A8220 clockwise A9220 counter
   // AA180 -> Elbow is now a degree based encoder.  Not rotational.
   // Format A5000  Reset everything.
@@ -256,6 +265,13 @@
   }
 }

+/**
+ * Homing works by setting servos to 90 degrees, and later to pull
+ * or push the shoulder DC so that the angle on the arm reads 90 degrees
+ *
+ * Then homing is stopped and the encoder is reset to zero.
+ */
+bool homing=false;

 void loop() {
   if (accel.available())
@@ -304,6 +320,10 @@
       case '=':
         resetEncoderPos();
         targetpos=0;
+        setTargetPos(90/10);
+        elbow.tgtPos=90;
+        wrist.tgtPos=90;
+        homing=true;
         break;
       case 'A':
         readcommand(state,controlvalue);
@@ -320,8 +340,18 @@

   updateEncoder();

-  updatedc(shoulder, getEncoderPos());
-
+  if (homing) {
+    homing = !(updatedc(shoulder, (int)((getTilt()*180.0/PI)/(10.0))));
+
+    if (!homing) {
+      resetEncoderPos();
+      setTargetPos(0);
+    }
+
+  }
+  else {
+    updatedc(shoulder, getEncoderPos());
+  }
   //updaterotservo(elbow, getTilt());

   elbow.update();


int x,y,z

int x,y,z

--- xBeeMegaRobot_func/xBeeMegaRobot_func.ino
+++ xBeeMegaRobot_func/xBeeMegaRobot_func.ino
@@ -75,7 +75,7 @@
 int fail = 0;
 float rate;
 */
-
+int x, y, z, emg1, emg2;

 void loop() {
   for(int i = 0; i < 50; i++){


RFduino V0.9.17

RFduino V0.9.17

version number update, .16 simply skipped

--- LBridge_RFduino_V09/LBridge_RFduino_V09.ino
+++ LBridge_RFduino_V09/LBridge_RFduino_V09.ino
@@ -82,6 +82,12 @@
  *  - restart BLE stack if BLE lost during sending the current queue (40 s waiting time)
  *  - testing function result of BLE.send to check proper BLE stack queue filling (currently RFduino only)
  *  - added watchdog again to overcome possible RFduino freezing due to BLE stack overload
+ * V0.9.16
+ *  - skipped
+ * V0.9.17
+ *  - minor changes for correct handling of Simblee (MM)
+ *  - G4 backward compatibility added (Spike, iosxdrip, MM)
+ *  - preparation for detecting new defined poll messages from xDrip+ (MM)
  */

  /*


Start akeru only if required

Start akeru only if required

--- theftprotection.ino
+++ theftprotection.ino
@@ -64,28 +64,25 @@
     p.theftprotection = true;
     p.lat = flat;
     p.lng = flon;
-
-    // Init modem
-    Akeru.begin();
-    // Wait 1 second for the modem to warm up
-    delay(1000);

-    if(!Akeru.isReady()){
-      Serial.println("Modem not ready");
+    if(p.lat != TinyGPS::GPS_INVALID_F_ANGLE &&
+      p.lng != TinyGPS::GPS_INVALID_F_ANGLE){
+      // Init modem
+      Akeru.begin();
+      // Wait 1 second for the modem to warm up
       delay(1000);
-    } else if(
-      p.lat != TinyGPS::GPS_INVALID_F_ANGLE &&
-      p.lng != TinyGPS::GPS_INVALID_F_ANGLE) {
-      Serial.println("Modem ready and coordinates valid");
+      if(!Akeru.isReady()){
+        Serial.println("Modem not ready");
+      } else {
+        delay(1000);
+        Akeru.send(&p, sizeof(p));
+        Serial.println("Message sent");
+      }
+      // end modem to make port listening for gps available
+      ssAkeru.end();
       delay(1000);
-
-      Akeru.send(&p, sizeof(p));
-      Serial.println("Message sent");
-      delay(1000);
     } else {
-      Serial.println("Coordinates not valid");
+        Serial.println("Coordinates not valid");
     }
-    // end modem in order to make port listening for gps available
-    ssAkeru.end();
   }
 }


streamのコマンド構成を変えた.

streamのコマンド構成を変えた.

--- arduino/GeneralIoSerial/GeneralIoSerial.ino
+++ arduino/GeneralIoSerial/GeneralIoSerial.ino
@@ -1,6 +1,26 @@
 #include <avr/pgmspace.h>

 #define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
+
+
+// ポート数の違いを吸収したりするｱﾚ
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
+// Arduino MEGAとか
+
+// A0 - A15
+#define AI_MAX_PORT_NUM 16
+
+// D0 - D49
+#define DI_MAX_PORT_NUM 50
+#else
+// Unoとか
+
+// A0 - A5
+#define AI_MAX_PORT_NUM 6
+
+// D0 - D13
+#define DI_MAX_PORT_NUM 14
+#endif

 const prog_char ILLEGAL_COMMAND[] PROGMEM       = "Illegal command.";
 const prog_char ILLEGAL_TYPE[] PROGMEM          = "Illegal type.";
@@ -31,23 +51,12 @@
   uint8_t value;
 };

-// DI Stream機能の情報.
-struct DI_STREAM_INFO {
-  // 読み込みを行うポート情報
-  uint64_t ports;
-
-  // Stream機能が有効かどうか
-  bool enabled;
-} di_stream_info;
-
-struct AI_STREAM_INFO {
-  // 読み込みを行うポート情報
-  uint16_t ports;
-
-  // Stream機能が有効かどうか
-  bool enabled;
-} ai_stream_info;
-
+
+// DI連続転送の有効・無効を管理する. bitが立っていると有効.
+// megaのポート数に対応するため64bitにする.
+uint64_t di_stream_enable_ports = 0;
+
+uint16_t ai_stream_enable_ports = 0;

 // pinModeの名前と値を保持するテーブル.
@@ -121,11 +130,9 @@

   /*
     DI連続転送ON
-    format   => stream/di/on?{ports}
-    {ports}  => 有効にするポート.対応するbitを1にする. 指定しない場合は前回と同じポートを使う.Defaultは0
-    example  => stream/di/on?240
-     240 = 0xf0 = 7 - 4番ポートを有効化
-
+    format   => stream/di/on/{port}
+    {port} => 連続転送を有効にするポート番号
+    example  => stream/di/on/1

      streamのレスポンス

@@ -138,28 +145,31 @@
         {"msg":"OK","port":[port],"val":[val]}
      ]}
    */
-  {"stream/di/on", &streamDiOnTask},
+  {"stream/di/on/", &streamDiOnTask},

   /*
      DI連続転送OFF
-     format => stream/di/off
-   */
-  {"stream/di/off", &streamDiOffTask},
+     format => stream/di/off/{port}
+
+     但しstream/di/off/allとやった場合は全てのポートの連続転送がOFFになる
+   */
+  {"stream/di/off/", &streamDiOffTask},

   /*
     AI連続転送ON
     format   => stream/ai/on?{ports}
-    {ports}  => 有効にするポート.対応するbitを1にする. 指定しない場合は前回と同じポートを使う.Defaultは0
-    example  => stream/ai/on?15
-     15 = 0xf = 3 - 0番ポートを有効化
-   */
-  {"stream/ai/on", &streamAiOnTask},
+    {port} => 連続転送を有効にするポート番号
+    example  => stream/ai/on/1
+   */
+  {"stream/ai/on/", &streamAiOnTask},

   /*
      AI連続転送OFF
-     format => stream/ai/off
-   */
-  {"stream/ai/off", &streamAiOffTask},
+     format => stream/ai/off/1
+
+     但しstream/ai/off/allとやった場合は全てのポートの連続転送がOFFになる
+   */
+  {"stream/ai/off/", &streamAiOffTask},

   /*
@@ -195,12 +205,6 @@
 void setup() {
   buf_index = 0;
   memset(read_buf,0,128);
-
-  di_stream_info.ports = 0;
-  di_stream_info.enabled = false;
-
-  ai_stream_info.ports = 0;
-  ai_stream_info.enabled = false;

   Serial.begin(115200);
   Serial.println("READY");
@@ -231,12 +235,11 @@

   // enabledがtrueかつ、portsのどれか一つが有効になっていれば
   // 変換を行う
-  if(di_stream_info.enabled &&
-     di_stream_info.ports != 0){
+  if( di_stream_enable_ports != 0){
     Serial.print(eventResponseHeader("di"));
     bool first = true;
-    for(int i = 0; i < 14; i++){
-      if(bitRead(di_stream_info.ports, i) == 1){
+    for(uint8_t i = 0; i < DI_MAX_PORT_NUM; i++){
+      if(bitRead(di_stream_enable_ports, i) == 1){
         if(first){
           first = false;
         }else{
@@ -248,12 +251,11 @@
     Serial.println("]}");
   }

-  if(ai_stream_info.enabled &&
-     ai_stream_info.ports != 0){
+  if( ai_stream_enable_ports != 0){
     Serial.print(eventResponseHeader("ai"));
     bool first = true;
-    for(int i = 0; i < 14; i++){
-      if(bitRead(ai_stream_info.ports, i) == 1){
+    for(uint8_t i = 0; i < AI_MAX_PORT_NUM; i++){
+      if(bitRead(ai_stream_enable_ports, i) == 1){
         if(first){
           first = false;
         }else{
@@ -381,7 +383,7 @@
   }

   analogWrite(port, val);
-  return okIoJson("OK", port, val);
+  return okIoJson(port, val);
 }

@@ -400,7 +402,7 @@
     digitalWrite(port, LOW);
     val = 0;
   }
-  return okIoJson("OK", port, val);
+  return okIoJson(port, val);
 }

@@ -422,7 +424,7 @@

 String diRead(uint8_t port){
   int val = digitalRead(port);
-  return okIoJson("OK", port, val);
+  return okIoJson(port, val);
 }

 /*
@@ -439,7 +441,7 @@

 String aiRead(uint8_t port){
   int val = analogRead(port);
-  return okIoJson("OK", port, val);
+  return okIoJson(port, val);
 }

@@ -467,43 +469,64 @@

 String streamDiOnTask(String query){

-  int at = query.indexOf('?');
-  if(at >= 0){
-    String portsQuery = query.substring(at + 1);
-    if(!isInt(portsQuery)){
-      return NgReturnJson(ILLEGAL_QUERY);
-    }
-    di_stream_info.ports = strToUInt64(portsQuery);
-  }
-  // queryがない場合はportsを変更せずにstreamをenableにする.
-  di_stream_info.enabled = true;
-
-  return okStreamJson(di_stream_info.enabled, di_stream_info.ports);
-}
-
-String streamDiOffTask(String empty){
-  di_stream_info.enabled = false;
-  return okStreamJson(di_stream_info.enabled, di_stream_info.ports);
+  String error = checkPortQuery(query);
+  if(error){
+    return error;
+  }
+
+  uint8_t port = strToInt(query);
+  bitSet(di_stream_enable_ports, port);
+
+  return okIoJson(port, 1);
+}
+
+String streamDiOffTask(String query){
+
+  if(query == "all"){
+    di_stream_enable_ports = 0;
+    return okIoJson(0xff, 0);
+  }
+
+  String error = checkPortQuery(query);
+  if(error){
+    return error;
+  }
+
+  uint8_t port = strToInt(query);
+  bitClear(di_stream_enable_ports, port);
+
+  return okIoJson(port, 0);
 }

 String streamAiOnTask(String query){
-  int at = query.indexOf('?');
-  if(at >= 0){
-    String portsQuery = query.substring(at + 1);
-    if(!isInt(portsQuery)){
-      return NgReturnJson(ILLEGAL_QUERY);
-    }
-    ai_stream_info.ports = strToUInt64(portsQuery);
-  }
-  // queryがない場合はportsを変更せずにstreamをenableにする.
-  ai_stream_info.enabled = true;
-
-  return okStreamJson(ai_stream_info.enabled, ai_stream_info.ports);
-}
-
-String streamAiOffTask(String empty){
-  ai_stream_info.enabled = false;
-  return okStreamJson(ai_stream_info.enabled, ai_stream_info.ports);
+
+  String error = checkPortQuery(query);
+  if(error){
+    return error;
+  }
+
+  uint8_t port = strToInt(query);
+  bitSet(ai_stream_enable_ports, port);
+
+  return okIoJson(port, 1);
+}
+
+String streamAiOffTask(String query){
+
+  if(query == "all"){
+    ai_stream_enable_ports = 0;
+    return okIoJson(0xff, 0);
+  }
+
+  String error = checkPortQuery(query);
+  if(error){
+    return error;
+  }
+
+  uint8_t port = strToInt(query);
+  bitClear(ai_stream_enable_ports, port);
+
+  return okIoJson(port, 0);
 }

@@ -601,18 +624,10 @@
    JSON変換関連
  */

-// portsはDI_STREAM_INFOのportsに合わせてuint64_tにしている
-String okStreamJson(bool enabled, uint64_t ports){
+
+
+String okIoJson(uint8_t port, uint8_t val){
   String body = stringJson("msg", "OK") + ","
-    + boolJson("enabled", enabled) + ","
-    + intJson("ports", ports);
-
-  return wrapBrace(body);
-}
-
-
-String okIoJson(String msg, int port, int val){
-  String body = stringJson("msg", msg) + ","
     + intJson("port", port) + ","
     + intJson("val", val);


reverse z-axis zero switch

reverse z-axis zero switch

--- arrowprint_firmware/arrowprint_firmware.ino
+++ arrowprint_firmware/arrowprint_firmware.ino
@@ -6,7 +6,6 @@
  * Use arduino toolkit version 1.5.2 or later
  * Make sure you use an Arduino DUE (Or Leonardo)
  * Install aJSON library
- * Install AccelStepper library
  */
 #include <aJSON.h>

@@ -32,7 +31,7 @@
 //measured (1000 = 1mm)
 double tablexdistance = 180;    //in microns (158mm )
 double tableydistance = 200.0625;    //in microns (200mm)
-double tablezdistance = 69.2347;    //in microns (96mm)
+double tablezdistance = 70.0;    //in microns (96mm)
 double tableedistance = 1000.000;    //in microns (96mm)

@@ -46,7 +45,7 @@
 double stepperXdestPosition = 0;
 double stepperXtimer = 0;
 int    stepperXtoggle = 0;
-double stepperXspeed = 3200;
+double stepperXspeed = 2560;

 int motorpinYstep = 26;
 int motorpinYdir  = 27;
@@ -54,7 +53,7 @@
 double stepperYdestPosition = 0;
 double stepperYtimer = 0;
 int    stepperYtoggle = 0;
-double stepperYspeed = 3200;  //slower for more power
+double stepperYspeed = 2560;  //slower for more power

 int motorpinZstep = 30;
 int motorpinZdir  = 31;
@@ -62,7 +61,7 @@
 double stepperZdestPosition = 0;
 double stepperZtimer = 0;
 int    stepperZtoggle = 0;
-double stepperZspeed = 3200;
+double stepperZspeed = 2560;

 int motorpinEstep = 28;
 int motorpinEdir  = 29;
@@ -70,7 +69,7 @@
 double stepperEdestPosition = 0;
 double stepperEtimer = 0;
 int    stepperEtoggle = 0;
-double stepperEspeed = 6400;
+double stepperEspeed = 2560;

 // Motor Zero switch pins
@@ -208,16 +207,27 @@
   */

     ////////////////////////////////////////////////////////ZERO Z - UPDOWN
-    while (digitalRead(zZeropin) != zZeroNC) {
-      stepperZdestPosition = stepperZdestPosition + 1;
+
+    //slightly up while on zeroswitch.
+
+   while (digitalRead(zZeropin) == zZeroNC) {
+    stepperZdestPosition = stepperZdestPosition + 200;
       while (stepperZdistanceToGo() != 0) {
         stepperZrun();
       }
+   }
+
+    //back down to zero
+
+   while (digitalRead(zZeropin) != zZeroNC) {
+      stepperZdestPosition = stepperZdestPosition - 1;
+      while (stepperZdistanceToGo() != 0) {
+        stepperZrun();
+      }
     }

     //top most is equal to tablezsteps
-    stepperZcurrPosition = tablezsteps;
-
+    stepperZcurrPosition = 0;
     //moves to zero (table surface)
     stepperZdestPosition = 0;
     while (stepperZdistanceToGo() != 0) {
@@ -307,8 +317,6 @@
      stepperYdestPosition = round(newysteps)*2;
      stepperZdestPosition = round(newzsteps)*2;
      stepperEdestPosition = round(newesteps)*2;
-
-

      while ((stepperXdistanceToGo() != 0) || (stepperYdistanceToGo() != 0) || (stepperZdistanceToGo() != 0) || (stepperEdistanceToGo() != 0)) {
          stepperXrun();


Sleep

Sleep

--- sensor/sensor.ino
+++ sensor/sensor.ino
@@ -120,7 +120,7 @@
         if (awake_tx_count > AWAKE_TX_MAX) {
             awake_tx_count = 0;
             // Watchdog will wake us up in 8 seconds time.
-            //goToSleep(SLEEP_FLAG_IDLE);
+            goToSleep(SLEEP_FLAG_IDLE);
         }
     }
 }


small fix to arduino sketch

small fix to arduino sketch

--- sensor/sensor.ino
+++ sensor/sensor.ino
@@ -2,12 +2,15 @@
 #include <Wire.h>

 unsigned long prevTime;
-int tickInterval = 1000 * 5;
+int tickInterval = 1000 * 2;
 unsigned long currentTicks = 0;
-String reqId = "";
+String reqId = "D";
 int errorState = 0;
 bool high = false;
 bool conf = false;
+
+int error2Temp = 21;
+int error3Temp = 22;

 int redPin = A7;
 int yellowPin = A9;
@@ -29,6 +32,7 @@
   unsigned long currTime = millis();
   if ((currTime - prevTime) > tickInterval){
     prevTime = currTime;
+    currentTicks++;
     return true;
   }

@@ -40,6 +44,7 @@
     analogWrite(greenPin, 0);
     analogWrite(yellowPin, 255);
   } else if (s == 3){
+    analogWrite(greenPin, 0);
     analogWrite(yellowPin, 0);
     analogWrite(redPin,255);
   }
@@ -111,7 +116,8 @@
   pinMode(greenPin, OUTPUT);

   analogWrite(greenPin, 255);
-
+
+  delay(2000);
   prevTime = millis();

 }
@@ -150,17 +156,28 @@
 }

 void loop() {
-  if (nextTick()){
-    readValues();
-   // Serial.println("next tick");
-    //Serial.println(errorState);
-    if (errorState != 3){
-      errorState = checkRequirements();
-      changeStatus(errorState);
-      //Serial.println(errorState);
-    }
-  }
-
+  if (nextTick()){
+      Serial.print("Current ticks: ");
+      Serial.println(currentTicks);
+      Serial.print("Current temp: ");
+      Serial.println(temp);
+      Serial.print("High: ");
+      Serial.println(high);
+
+      readValues();
+      if (errorState != 3){
+
+        errorState = checkRequirements();
+
+        if (errorState == 1){
+          currentTicks = 0;
+        }
+
+        changeStatus(errorState);
+      }
+
+      Serial.println();
+  }

   checkForOperation();
 }
@@ -199,15 +216,16 @@

 int complexCheck(double d1, double d2){
   if (!high){
-    int res = above(temp, 30);
+    int res = above(temp, 22);
     if (res == 3){
+      Serial.println("Set to high");
       high = true;
       return checkRequirements();
     }
     return combine(res, noMore(d1));
   }

-  return combine(above(temp, 30), noMore(d2));
+  return combine(above(temp, 23), noMore(d2));
 }

 int noMore(int numberOfTicks){
@@ -221,18 +239,20 @@
 }

 int checkRequirements(){
+  Serial.println(reqId);
+
   if (reqId == "A"){
-    return complexCheck(10, 7);
+    return complexCheck(5, 3);
   } else if (reqId == "B"){
-    return complexCheck(8, 6);
+    return complexCheck(5, 3);
   } else if (reqId == "C"){
-    return complexCheck(14,11);
+    return complexCheck(5, 3);
   } else if (reqId == "D"){
-    return above(temp, 34);
+    return above(temp, 24);
   } else if (reqId == "E"){
     return isFreeze(temp);
   } else if (reqId == "F"){
-    return above(temp, 8);
+    return above(temp, 25);
   } else if (reqId == "0"){
     return above(temp, 8);
   } else if (reqId == "25"){
@@ -242,9 +262,9 @@
   } else if (reqId == "AF"){
     return combine(complexCheck(3,2), isFreeze(temp));
   } else if (reqId == "BF"){
-    return combine(complexCheck(8,6), isFreeze(temp));
+    return combine(complexCheck(5, 3), isFreeze(temp));
   } else if (reqId == "CF"){
-    return combine(complexCheck(14, 11), isFreeze(temp));
+    return combine(complexCheck(5, 3), isFreeze(temp));
   } else {
     return 0;
   }