Fixed link to library

Fixed link to library

--- examples/g_SDI-12_slave_implementation/g_SDI-12_slave_implementation.ino
+++ examples/g_SDI-12_slave_implementation/g_SDI-12_slave_implementation.ino
@@ -1,230 +1,230 @@
-/*
- * SDI-12_slave_example
- * Example sketch demonstrating how to implement an arduino as a slave on an SDI-12 bus. This may
- * be used, for example, as a middleman between an I2C sensor and an SDI-12 datalogger.
- *
- * Note that an SDI-12 slave must respond to M! or C! with the number of values it will report and
- * the max time until these values will be available.  This example uses 9 values available in
- * 21 s, but references to these numbers and the output array size and datatype should be changed
- * for your specific application.
- *
- * Sketch requires the SDI-12 library from SWRC, modified to add public void forceListen() and
- * public void sendResponse().
- * https://github.com/EnviroDIY/Arduino-SDI-12
- *
- * D. Wasielewski, 2016
- * Builds upon work started by:
- * https://github.com/jrzondagh/AgriApps-SDI-12-Arduino-Sensor
- * https://github.com/Jorge-Mendes/Agro-Shield/tree/master/SDI-12ArduinoSensor
- *
- * Suggested improvements:
- *  - Get away from memory-hungry arduino String objects in favor of char buffers
- *  - Make an int variable for the "number of values to report" instead of the
- *    hard-coded 9s interspersed throughout the code
- */
-
-// Requires modified SDI-12 libary with addition of public forceListen() and public sendResponse()
-#include <SDI12.h>
-#define SDIPIN 7
-
-char sensorAddress = '5';
-int state = 0;
-
-#define WAIT 0
-#define INITIATE_CONCURRENT 1
-#define INITIATE_MEASUREMENT 2
-
-// Create object by which to communicate with the SDI-12 bus on SDIPIN
-SDI12 slaveSDI12(SDIPIN);
-
-void setup() {
-  slaveSDI12.begin();
-  delay(500);
-  slaveSDI12.forceListen();  // sets SDIPIN as input to prepare for incoming message
-}
-
-void loop() {
-
-  static float measurementValues[9]; // 9 floats to hold simulated sensor data
-  static String dValues[10];  // 10 String objects to hold the responses to aD0!-aD9! commands
-  static String commandReceived = "";  // String object to hold the incoming command
-
-
-  // If a byte is available, an SDI message is queued up. Read in the entire message
-  // before proceding.  It may be more robust to add a single character per loop()
-  // iteration to a static char buffer; however, the SDI-12 spec requires a precise
-  // response time, and this method is invariant to the remaining loop() contents.
-  int avail = slaveSDI12.available();
-  if (avail < 0) { slaveSDI12.flush(); } // Buffer full; flush
-  else if (avail > 0) {
-    for(int a = 0; a < avail; a++){
-      char charReceived = slaveSDI12.read();
-      // Character '!' indicates the end of an SDI-12 command; if the current
-      // character is '!', stop listening and respond to the command
-      if (charReceived == '!') {
-        // Command string is completed; do something with it
-        parseSdi12Cmd(commandReceived, dValues);
-        // Clear command string to reset for next command
-        commandReceived = "";
-        // '!' should be the last available character anyway, but exit the "for" loop
-        // just in case there are any stray characters
-        slaveSDI12.flush();
-        break;
-      }
-      // If the current character is anything but '!', it is part of the command
-      // string.  Append the commandReceived String object.
-      else{
-        // Append command string with new character
-        commandReceived += String(charReceived);
-      }
-    }
-  }
-
-  // For aM! and aC! commands, parseSdi12Cmd will modify "state" to indicate that
-  // a measurement should be taken
-  switch (state) {
-    case WAIT:
-      break;
-    case INITIATE_CONCURRENT:
-      // Do whatever the sensor is supposed to do here
-      // For this example, we will just create arbitrary "simulated" sensor data
-      // NOTE: Your application might have a different data type (e.g. int) and
-      //       number of values to report!
-      pollSensor(measurementValues);
-      // Populate the "dValues" String array with the values in SDI-12 format
-      formatOutputSDI(measurementValues, dValues, 75);
-      state = WAIT;
-      break;
-    case INITIATE_MEASUREMENT:
-      // Do whatever the sensor is supposed to do here
-      // For this example, we will just create arbitrary "simulated" sensor data
-      // NOTE: Your application might have a different data type (e.g. int) and
-      //       number of values to report!
-      pollSensor(measurementValues);
-      // Populate the "dValues" String array with the values in SDI-12 format
-      formatOutputSDI(measurementValues, dValues, 35);
-      // For aM!, Send "service request" (<address><CR><LF>) when data is ready
-      slaveSDI12.sendResponse(String(sensorAddress) + "\r\n");
-      state = WAIT;
-      break;
-  }
-}
-
-void pollSensor(float* measurementValues) {
-  measurementValues[0] =  1.111111;
-  measurementValues[1] = -2.222222;
-  measurementValues[2] =  3.333333;
-  measurementValues[3] = -4.444444;
-  measurementValues[4] =  5.555555;
-  measurementValues[5] = -6.666666;
-  measurementValues[6] =  7.777777;
-  measurementValues[7] = -8.888888;
-  measurementValues[8] = -9.999999;
-}
-
-void parseSdi12Cmd(String command, String* dValues) {
-/* Ingests a command from an SDI-12 master, sends the applicable response, and
- * (when applicable) sets a flag to initiate a measurement
- */
-
-  // First char of command is always either (a) the address of the device being
-  // probed OR (b) a '?' for address query.
-  // Do nothing if this command is addressed to a different device
-  if (command.charAt(0) != sensorAddress && command.charAt(0) != '?') {
-    return;
-  }
-
-  // If execution reaches this point, the slave should respond with something in
-  // the form:   <address><responseStr><Carriage Return><Line Feed>
-  // The following if-switch-case block determines what to put into <responseStr>,
-  // and the full response will be constructed afterward. For '?!' (address query)
-  // or 'a!' (acknowledge active) commands, responseStr is blank so section is skipped
-  String responseStr = "";
-  if (command.length() > 1) {
-    switch (command.charAt(1)) {
-    case 'I':
-        // Identify command
-        // Slave should respond with ID message: 2-char SDI-12 version + 8-char
-        // company name + 6-char sensor model + 3-char sensor version + 0-13 char S/N
-        responseStr = "13COMPNAME0000011.0001"; // Substitute proper ID String here
-        break;
-      case 'C':
-        // Initiate concurrent measurement command
-        // Slave should immediately respond with: "tttnn":
-        //    3-digit (seconds until measurement is available) +
-        //    2-digit (number of values that will be available)
-        // Slave should also start a measurment and relinquish control of the data line
-        responseStr = "02109";  // 9 values ready in 21 sec; Substitue sensor-specific values here
-        // It is not preferred for the actual measurement to occur in this subfunction,
-        // because doing to would hold the main program hostage until the measurement
-        // is complete.  Instead, we'll just set a flag and handle the measurement elsewhere.
-        state = INITIATE_CONCURRENT;
-        break;
-        // NOTE: "aC1...9!" commands may be added by duplicating this case and adding
-        //       additional states to the state flag
-      case 'M':
-        // Initiate measurement command
-        // Slave should immediately respond with: "tttnn":
-        //    3-digit (seconds until measurement is available) +
-        //    1-digit (number of values that will be available)
-        // Slave should also start a measurment but may keep control of the data line until
-        // advertised time elapsed OR measurement is complete and service request sent
-        responseStr = "0219";  // 9 values ready in 21 sec; Substitue sensor-specific values here
-        // It is not preferred for the actual measurement to occur in this subfunction,
-        // because doing to would hold the main program hostage until the measurement
-        // is complete.  Instead, we'll just set a flag and handle the measurement elsewhere.
-        // It is preferred though not required that the slave send a service request upon
-        // completion of the measurement.  This should be handled in the main loop().
-        state = INITIATE_MEASUREMENT;
-        break;
-        // NOTE: "aM1...9!" commands may be added by duplicating this case and adding
-        //       additional states to the state flag
-
-      case 'D':
-        // Send data command
-        // Slave should respond with a String of values
-        // Values to be returned must be split into Strings of 35 characters or fewer
-        // (75 or fewer for concurrent).  The number following "D" in the SDI-12 command
-        // specifies which String to send
-        responseStr = dValues[(int)command.charAt(2)-48];
-        break;
-      case 'A':
-        // Change address command
-        // Slave should respond with blank message (just the [new] address + <CR> + <LF>)
-        sensorAddress = command.charAt(2);
-        break;
-      default:
-        // Mostly for debugging; send back UNKN if unexpected command received
-        responseStr = "UNKN";
-        break;
-    }
-  }
-
-  // Issue the response speficied in the switch-case structure above.
-  slaveSDI12.sendResponse(String(sensorAddress) + responseStr + "\r\n");
-}
-
-
-void formatOutputSDI(float* measurementValues, String* dValues, int maxChar) {
-/* Ingests an array of floats and produces Strings in SDI-12 output format */
-
-  dValues[0] = "";
-  int j = 0;
-
-  // upper limit on i should be number of elements in measurementValues
-  for (int i=0; i<9; i++) {
-    // Read float value "i" as a String with 6 deceimal digits
-    // (NOTE: SDI-12 specifies max of 7 digits per value; we can only use 6
-    //  decimal place precision if integer part is one digit)
-    String valStr = String(measurementValues[i],6);
-    // Explictly add implied + sign if non-negative
-    if (valStr.charAt(0) != '-') { valStr = '+' + valStr; }
-    // Append dValues[j] if it will not exceed 35 (aM!) or 75 (aC!) characters
-    if (dValues[j].length() + valStr.length() < maxChar) { dValues[j] += valStr; }
-    // Start a new dValues "line" if appending would exceed 35/75 characters
-    else { dValues[++j] = valStr; }
-  }
-
-  // Fill rest of dValues with blank strings
-  while (j<9) { dValues[++j] = ""; }
-}
+/*
+ * SDI-12_slave_example
+ * Example sketch demonstrating how to implement an arduino as a slave on an SDI-12 bus. This may
+ * be used, for example, as a middleman between an I2C sensor and an SDI-12 datalogger.
+ *
+ * Note that an SDI-12 slave must respond to M! or C! with the number of values it will report and
+ * the max time until these values will be available.  This example uses 9 values available in
+ * 21 s, but references to these numbers and the output array size and datatype should be changed
+ * for your specific application.
+ *
+ * Sketch requires the SDI-12 library from SWRC, modified to add public void forceListen() and
+ * public void sendResponse().
+ * https://github.com/dwasielewski/Arduino-SDI-12
+ *
+ * D. Wasielewski, 2016
+ * Builds upon work started by:
+ * https://github.com/jrzondagh/AgriApps-SDI-12-Arduino-Sensor
+ * https://github.com/Jorge-Mendes/Agro-Shield/tree/master/SDI-12ArduinoSensor
+ *
+ * Suggested improvements:
+ *  - Get away from memory-hungry arduino String objects in favor of char buffers
+ *  - Make an int variable for the "number of values to report" instead of the
+ *    hard-coded 9s interspersed throughout the code
+ */
+
+// Requires modified SDI-12 libary with addition of public forceListen() and public sendResponse()
+#include <SDI12.h>
+#define SDIPIN 7
+
+char sensorAddress = '5';
+int state = 0;
+
+#define WAIT 0
+#define INITIATE_CONCURRENT 1
+#define INITIATE_MEASUREMENT 2
+
+// Create object by which to communicate with the SDI-12 bus on SDIPIN
+SDI12 slaveSDI12(SDIPIN);
+
+void setup() {
+  slaveSDI12.begin();
+  delay(500);
+  slaveSDI12.forceListen();  // sets SDIPIN as input to prepare for incoming message
+}
+
+void loop() {
+
+  static float measurementValues[9]; // 9 floats to hold simulated sensor data
+  static String dValues[10];  // 10 String objects to hold the responses to aD0!-aD9! commands
+  static String commandReceived = "";  // String object to hold the incoming command
+
+
+  // If a byte is available, an SDI message is queued up. Read in the entire message
+  // before proceding.  It may be more robust to add a single character per loop()
+  // iteration to a static char buffer; however, the SDI-12 spec requires a precise
+  // response time, and this method is invariant to the remaining loop() contents.
+  int avail = slaveSDI12.available();
+  if (avail < 0) { slaveSDI12.flush(); } // Buffer full; flush
+  else if (avail > 0) {
+    for(int a = 0; a < avail; a++){
+      char charReceived = slaveSDI12.read();
+      // Character '!' indicates the end of an SDI-12 command; if the current
+      // character is '!', stop listening and respond to the command
+      if (charReceived == '!') {
+        // Command string is completed; do something with it
+        parseSdi12Cmd(commandReceived, dValues);
+        // Clear command string to reset for next command
+        commandReceived = "";
+        // '!' should be the last available character anyway, but exit the "for" loop
+        // just in case there are any stray characters
+        slaveSDI12.flush();
+        break;
+      }
+      // If the current character is anything but '!', it is part of the command
+      // string.  Append the commandReceived String object.
+      else{
+        // Append command string with new character
+        commandReceived += String(charReceived);
+      }
+    }
+  }
+
+  // For aM! and aC! commands, parseSdi12Cmd will modify "state" to indicate that
+  // a measurement should be taken
+  switch (state) {
+    case WAIT:
+      break;
+    case INITIATE_CONCURRENT:
+      // Do whatever the sensor is supposed to do here
+      // For this example, we will just create arbitrary "simulated" sensor data
+      // NOTE: Your application might have a different data type (e.g. int) and
+      //       number of values to report!
+      pollSensor(measurementValues);
+      // Populate the "dValues" String array with the values in SDI-12 format
+      formatOutputSDI(measurementValues, dValues, 75);
+      state = WAIT;
+      break;
+    case INITIATE_MEASUREMENT:
+      // Do whatever the sensor is supposed to do here
+      // For this example, we will just create arbitrary "simulated" sensor data
+      // NOTE: Your application might have a different data type (e.g. int) and
+      //       number of values to report!
+      pollSensor(measurementValues);
+      // Populate the "dValues" String array with the values in SDI-12 format
+      formatOutputSDI(measurementValues, dValues, 35);
+      // For aM!, Send "service request" (<address><CR><LF>) when data is ready
+      slaveSDI12.sendResponse(String(sensorAddress) + "\r\n");
+      state = WAIT;
+      break;
+  }
+}
+
+void pollSensor(float* measurementValues) {
+  measurementValues[0] =  1.111111;
+  measurementValues[1] = -2.222222;
+  measurementValues[2] =  3.333333;
+  measurementValues[3] = -4.444444;
+  measurementValues[4] =  5.555555;
+  measurementValues[5] = -6.666666;
+  measurementValues[6] =  7.777777;
+  measurementValues[7] = -8.888888;
+  measurementValues[8] = -9.999999;
+}
+
+void parseSdi12Cmd(String command, String* dValues) {
+/* Ingests a command from an SDI-12 master, sends the applicable response, and
+ * (when applicable) sets a flag to initiate a measurement
+ */
+
+  // First char of command is always either (a) the address of the device being
+  // probed OR (b) a '?' for address query.
+  // Do nothing if this command is addressed to a different device
+  if (command.charAt(0) != sensorAddress && command.charAt(0) != '?') {
+    return;
+  }
+
+  // If execution reaches this point, the slave should respond with something in
+  // the form:   <address><responseStr><Carriage Return><Line Feed>
+  // The following if-switch-case block determines what to put into <responseStr>,
+  // and the full response will be constructed afterward. For '?!' (address query)
+  // or 'a!' (acknowledge active) commands, responseStr is blank so section is skipped
+  String responseStr = "";
+  if (command.length() > 1) {
+    switch (command.charAt(1)) {
+    case 'I':
+        // Identify command
+        // Slave should respond with ID message: 2-char SDI-12 version + 8-char
+        // company name + 6-char sensor model + 3-char sensor version + 0-13 char S/N
+        responseStr = "13COMPNAME0000011.0001"; // Substitute proper ID String here
+        break;
+      case 'C':
+        // Initiate concurrent measurement command
+        // Slave should immediately respond with: "tttnn":
+        //    3-digit (seconds until measurement is available) +
+        //    2-digit (number of values that will be available)
+        // Slave should also start a measurment and relinquish control of the data line
+        responseStr = "02109";  // 9 values ready in 21 sec; Substitue sensor-specific values here
+        // It is not preferred for the actual measurement to occur in this subfunction,
+        // because doing to would hold the main program hostage until the measurement
+        // is complete.  Instead, we'll just set a flag and handle the measurement elsewhere.
+        state = INITIATE_CONCURRENT;
+        break;
+        // NOTE: "aC1...9!" commands may be added by duplicating this case and adding
+        //       additional states to the state flag
+      case 'M':
+        // Initiate measurement command
+        // Slave should immediately respond with: "tttnn":
+        //    3-digit (seconds until measurement is available) +
+        //    1-digit (number of values that will be available)
+        // Slave should also start a measurment but may keep control of the data line until
+        // advertised time elapsed OR measurement is complete and service request sent
+        responseStr = "0219";  // 9 values ready in 21 sec; Substitue sensor-specific values here
+        // It is not preferred for the actual measurement to occur in this subfunction,
+        // because doing to would hold the main program hostage until the measurement
+        // is complete.  Instead, we'll just set a flag and handle the measurement elsewhere.
+        // It is preferred though not required that the slave send a service request upon
+        // completion of the measurement.  This should be handled in the main loop().
+        state = INITIATE_MEASUREMENT;
+        break;
+        // NOTE: "aM1...9!" commands may be added by duplicating this case and adding
+        //       additional states to the state flag
+
+      case 'D':
+        // Send data command
+        // Slave should respond with a String of values
+        // Values to be returned must be split into Strings of 35 characters or fewer
+        // (75 or fewer for concurrent).  The number following "D" in the SDI-12 command
+        // specifies which String to send
+        responseStr = dValues[(int)command.charAt(2)-48];
+        break;
+      case 'A':
+        // Change address command
+        // Slave should respond with blank message (just the [new] address + <CR> + <LF>)
+        sensorAddress = command.charAt(2);
+        break;
+      default:
+        // Mostly for debugging; send back UNKN if unexpected command received
+        responseStr = "UNKN";
+        break;
+    }
+  }
+
+  // Issue the response speficied in the switch-case structure above.
+  slaveSDI12.sendResponse(String(sensorAddress) + responseStr + "\r\n");
+}
+
+
+void formatOutputSDI(float* measurementValues, String* dValues, int maxChar) {
+/* Ingests an array of floats and produces Strings in SDI-12 output format */
+
+  dValues[0] = "";
+  int j = 0;
+
+  // upper limit on i should be number of elements in measurementValues
+  for (int i=0; i<9; i++) {
+    // Read float value "i" as a String with 6 deceimal digits
+    // (NOTE: SDI-12 specifies max of 7 digits per value; we can only use 6
+    //  decimal place precision if integer part is one digit)
+    String valStr = String(measurementValues[i],6);
+    // Explictly add implied + sign if non-negative
+    if (valStr.charAt(0) != '-') { valStr = '+' + valStr; }
+    // Append dValues[j] if it will not exceed 35 (aM!) or 75 (aC!) characters
+    if (dValues[j].length() + valStr.length() < maxChar) { dValues[j] += valStr; }
+    // Start a new dValues "line" if appending would exceed 35/75 characters
+    else { dValues[++j] = valStr; }
+  }
+
+  // Fill rest of dValues with blank strings
+  while (j<9) { dValues[++j] = ""; }
+}


Arduino : now send ip AND id when registering

--- Arduino/arduino/arduino.ino
+++ Arduino/arduino/arduino.ino
@@ -6,8 +6,9 @@
 byte macArduino[] = { 0x90, 0xA2, 0xDA, 0x00, 0x1D, 0xA7 };
 String strMacArduino="90:A2:DA:00:1D:A7";
 IPAddress ipArduino(192,168,2,3); // l'adresse IP de l'Arduino
-String idArduino="192.168.2.3"; // son identifiant=IP
-String descriptionArduino="Uno_Projet5"; // description de l'Arduino
+String stringIpArduino = "192.168.2.3";
+String idArduino="Baptiste"; // son identifiant=IP
+String descriptionArduino="Baptiste"; // description de l'Arduino
 int portArduino=102; // port du serveur Arduino // le serveur Arduino travaillera sur le port 102
 EthernetServer server(portArduino);
 IPAddress ipServeurEnregistrement(192,168,2,1); // IP du serveur d'enregistrement
@@ -35,7 +36,7 @@
       // suivi
       Serial.println(F("Connecte..."));
       // on envoie l'adresse Mac de l'Arduino, une description de ses fonctionnalités, son port de service
-      String msg="{\"id\":\""+idArduino+"\",\"desc\":\""+descriptionArduino+"\",\"mac\":\""+strMacArduino+"\",\"port\":"+portArduino+"}";
+      String msg="{\"id\":\""+idArduino+"\",\"desc\":\""+descriptionArduino+"\",\"mac\":\""+strMacArduino+"\",\"port\":\""+portArduino+"\",\"ip\":\""+stringIpArduino+"\"}";
       clientArduino.println(msg);
       Serial.print(F("enregistrement : "));
       Serial.println(msg);


implementando ciclo dinâmico, parcialmente funcional


Fixed EEPROM save glitch (bounds checking)


Added some feedback LEDs to see live status of reader pins

--- ReadSensors/ReadSensors.ino
+++ ReadSensors/ReadSensors.ino
@@ -1,4 +1,9 @@
+// ReadSensors.ino  20/06/2015  D.J.Whale
+//
+// (c) 2015 D.J.Whale
+
 #define REGISTRATION A0
+
 #define D7           A1
 #define D6           A2
 #define D5           A3
@@ -8,9 +13,20 @@
 #define D1           A9
 #define D0           A10

-#define REG_STATE_OPEN '.'
-#define REG_STATE_WHITE 'W'
-#define REG_STATE_BLACK 'B'
+#define LED_REG      1 // TX
+#define LED_D7       0 // RX
+#define LED_D6       2
+#define LED_D5       3
+#define LED_D4       5
+#define LED_D3       7
+#define LED_D2       16
+#define LED_D1       14
+#define LED_D0       15
+
+
+#define REG_STATE_OPEN   '.'
+#define REG_STATE_WHITE  'W'
+#define REG_STATE_BLACK  'B'

 #define DATA_STATE_PAPER '.'
 #define DATA_STATE_HOLE  'X'
@@ -18,12 +34,23 @@
 void setup()
 {
   Serial.begin(115200);
+  pinMode(LED_REG, OUTPUT);
+  pinMode(LED_D7,  OUTPUT);
+  pinMode(LED_D6,  OUTPUT);
+  pinMode(LED_D5,  OUTPUT);
+  pinMode(LED_D4,  OUTPUT);
+  pinMode(LED_D3,  OUTPUT);
+  pinMode(LED_D2,  OUTPUT);
+  pinMode(LED_D1,  OUTPUT);
+  pinMode(LED_D0,  OUTPUT);
+
 }

 void loop()
 {
-  delay(250);
+  //delay(250);

+  // Read all 9 inputs (roughly) at same time
   unsigned int reg = analogRead(A0);
   unsigned int d7  = analogRead(D7);
   unsigned int d6  = analogRead(D6);
@@ -34,6 +61,7 @@
   unsigned int d1  = analogRead(D1);
   unsigned int d0  = analogRead(D0);

+  // Generate filtered versions (character states)
   byte freg = getReg(reg);
   byte fd7  = getData(d7);
   byte fd6  = getData(d6);
@@ -45,6 +73,20 @@
   byte fd0  = getData(d0);

+  // Show card data on feedback LEDs
+  digitalWrite(LED_REG, (freg == REG_STATE_BLACK));
+  digitalWrite(LED_D7,  (fd7  == DATA_STATE_HOLE));
+  digitalWrite(LED_D6,  (fd6  == DATA_STATE_HOLE));
+  digitalWrite(LED_D5,  (fd5  == DATA_STATE_HOLE));
+  digitalWrite(LED_D4,  (fd4  == DATA_STATE_HOLE));
+  digitalWrite(LED_D3,  (fd3  == DATA_STATE_HOLE));
+  digitalWrite(LED_D2,  (fd2  == DATA_STATE_HOLE));
+  digitalWrite(LED_D1,  (fd1  == DATA_STATE_HOLE));
+  digitalWrite(LED_D0,  (fd0  == DATA_STATE_HOLE));
+
+
+  // Display card data on serial port
+  #if 0
   Serial.write(freg);
   Serial.write(" ");
   Serial.print(reg);
@@ -58,6 +100,7 @@
   Serial.write(fd1);
   Serial.write(fd0);
   Serial.println();
+  #endif
 }

 byte getReg(unsigned int adc)


Added command to disable I2C between measurements

--- water-sensor.ino
+++ water-sensor.ino
@@ -327,14 +327,20 @@

 // Get the values for each sensor
 void calc_sensors() {
+  Wire.begin();
+  delay(100);
+
   // Calc humidity
   humidity = myHumidity.readHumidity();
-
+
   // Calc temp from pressure sensor
   temp = myPressure.readTemp();

   // Calc pressure
   pressure = myPressure.readPressure();
+
+  //End the I2C Hardware so the temp sensor on the same bys can work
+  TWCR = 0;

   // Calc light level
   //light_lvl = get_light_level();


ls stuff

ls stuff

--- FirmwareManager/src/FirmwareManager.ino
+++ FirmwareManager/src/FirmwareManager.ino
@@ -403,14 +403,14 @@

         root["totalBytes"] = fs_info.totalBytes;
         root["usedBytes"] = fs_info.usedBytes;
-        root["blockSize"] = fs_info.blockSize;
-        root["pageSize"] = fs_info.pageSize;
-        root["maxOpenFiles"] = fs_info.maxOpenFiles;
-        root["maxPathLength"] = fs_info.maxPathLength;
-        root["freeSketchSpace"] = ESP.getFreeSketchSpace();
-        root["maxSketchSpace"] = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
-        root["flashChipSize"] = ESP.getFlashChipSize();
-        root["freeHeapSize"] = ESP.getFreeHeap();
+        // root["blockSize"] = fs_info.blockSize;
+        // root["pageSize"] = fs_info.pageSize;
+        // root["maxOpenFiles"] = fs_info.maxOpenFiles;
+        // root["maxPathLength"] = fs_info.maxPathLength;
+        // root["freeSketchSpace"] = ESP.getFreeSketchSpace();
+        // root["maxSketchSpace"] = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
+        // root["flashChipSize"] = ESP.getFlashChipSize();
+        // root["freeHeapSize"] = ESP.getFreeHeap();

         JsonArray &datas = root.createNestedArray("files");

@@ -421,7 +421,7 @@
             data["size"] = dir.fileSize();
         }

-        //response->setLength();
+        response->setLength();
         request->send(response);
     });


Update MAIN.ino

Update MAIN.ino


servoWrite now calls servoWritePulse

servoWrite now calls servoWritePulse

servoWrite converts angle to pulse

servoWritePulse checks limits and writes to servo

--- AL5D/al5d.ino
+++ AL5D/al5d.ino
@@ -468,22 +468,22 @@
 int servoWrite( int id, double angle_d )
 {
    //DEBUG("servoWrite("); DEBUG(id); DEBUG(", "); DEBUG(angle_deg); DEBUGln(")");
-   if (angle_d < SERVO_MIN_D[id]) { DEBUG(angle_d); DEBUG("<"); DEBUGln(SERVO_MIN_D[id]); return -1; }
-   if (angle_d > SERVO_MAX_D[id]) { DEBUG(angle_d); DEBUG(">"); DEBUGln(SERVO_MAX_D[id]); return -2; }
+   //if (angle_d < SERVO_MIN_D[id]) { DEBUG(angle_d); DEBUG("<"); DEBUGln(SERVO_MIN_D[id]); return -1; }
+   //if (angle_d > SERVO_MAX_D[id]) { DEBUG(angle_d); DEBUG(">"); DEBUGln(SERVO_MAX_D[id]); return -2; }

    double gradient = (SERVO_MAX[id]-SERVO_MIN[id])/(SERVO_MAX_D[id]-SERVO_MIN_D[id]);
    double pulseLength = angle_d*gradient + SERVO_MIN[id] - gradient*SERVO_MIN_D[id];// + map(angle_d, SERVO_MIN_D[id], SERVO_MAX_D[id], SERVO_MIN[id], SERVO_MAX[id]);
-
-   pwm.setPWM(id, 0, pulseLength);
-
-   DEBUG("pwm.setPWM("); DEBUG(id); DEBUG(", 0, "); DEBUG(pulseLength); DEBUGln(")");
+
+   int ret_val = servoWritePulse( id, pulseLength );
+
+   if (ret_val != 0 ) return ret_val;

    g_angle_d[id] = angle_d;

    return 0;
 }

-// Write to servo using pulse length, USE ONLY FOR TESTING
+// Write to servo using pulse length
 int servoWritePulse( int id, double pulseLength)
 {
   if (pulseLength < min(SERVO_MIN[id], SERVO_MAX[id])) { DEBUGln(min(SERVO_MIN[id], SERVO_MAX[id])); return -1; }


[nibeheatpump] Fixed ProDiNo UDP issue (#10511)

* [nibeheatpump] Arduino nibegw improvements

Signed-off-by: Pauli Anttila <46e7006d7cff4d963e9c971c68d15636d9388b35@gmail.com>

* [nibeheatpump] - more improvements

Signed-off-by: Pauli Anttila <46e7006d7cff4d963e9c971c68d15636d9388b35@gmail.com>

* Merge fixes

Signed-off-by: Pauli Anttila <46e7006d7cff4d963e9c971c68d15636d9388b35@gmail.com>

* Added note about tested KMPDinoEthernet library version

Signed-off-by: Pauli Anttila <46e7006d7cff4d963e9c971c68d15636d9388b35@gmail.com>

--- bundles/org.openhab.binding.nibeheatpump/contrib/NibeGW/Arduino/NibeGW/NibeGW.ino
+++ bundles/org.openhab.binding.nibeheatpump/contrib/NibeGW/Arduino/NibeGW/NibeGW.ino
@@ -20,51 +20,60 @@
  *  27.6.2014   v1.02   Fixed compile error and added Ethernet initialization delay.
  *  29.6.2015   v2.00   Bidirectional support.
  *  18.2.2017   v3.00   Redesigned.
+ *  14.3.2021   v3.01   Fix Prodino build + fixed UDP issue + debug improvements.
  */

 // ######### CONFIGURATION #######################

-#define VERSION                 "3.00"
+#define VERSION                 "3.01"

 // Enable if you use ProDiNo board
+// Have been tested with KMPDinoEthernet v1.6.1 (https://github.com/kmpelectronics/Arduino/tree/master/KMPDinoEthernet/Releases)
 //#define PRODINO_BOARD
+
 // Enable if ENC28J60 LAN module is used
 //#define TRANSPORT_ETH_ENC28J60
+
 // Enable if you use STM32 NUCLEO-F429ZI
 //#define STM32_F429ZI_BOARD

-// Enable debug printouts, listen printouts e.g. via netcat (nc -l -u 50000)
+// Enable debug printouts
 //#define ENABLE_DEBUG
-#define VERBOSE_LEVEL           3
+
+// Enable UDP debug printouts, listen printouts e.g. via netcat (nc -l -u 50000)
+//#define ENABLE_UDP_DEBUG
+
+#define VERBOSE_LEVEL           1

 #define BOARD_NAME              "Arduino NibeGW"
 #define BOARD_MAC               { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }
 #define BOARD_IP                { 192, 168, 1, 50 }
 #define GATEWAY_IP              { 192, 168, 1, 1 }
 #define NETWORK_MASK            { 255, 255, 255, 0 }
-#define INCOMING_PORT_READCMDS  TARGET_PORT
+#define INCOMING_PORT_READCMDS  9999
 #define INCOMING_PORT_WRITECMDS 10000

 #define TARGET_IP               192, 168, 1, 19
 #define TARGET_PORT             9999
-#define TARGER_DEBUG_PORT       50000
+#define TARGET_DEBUG_PORT       50000

 // Delay before initialize ethernet on startup in seconds
-#define ETH_INIT_DELAY          10
+#define ETH_INIT_DELAY          5

 // Used serial port and direction change pin for RS-485 port
+// Note! Select if Serial is SW or HW serial port in NibeGw.h
 #ifdef PRODINO_BOARD
-#define RS485_PORT              Serial1
-#define RS485_DIRECTION_PIN     3
+ #define RS485_PORT              Serial1
+ #define RS485_DIRECTION_PIN     3
 #elif defined STM32_F429ZI_BOARD
-#include <HardwareSerial.h>
-HardwareSerial Serial1(PG9,PG14);
-#define RS485_PORT              Serial1
-#define RS485_DIRECTION_PIN     PF15
-#else
-#define RS485_PORT              Serial
-#define RS485_DIRECTION_PIN     2
+ #include <HardwareSerial.h>
+ HardwareSerial Serial1(PG9,PG14);
+ #define RS485_PORT              Serial1
+ #define RS485_DIRECTION_PIN     PF15
+#else
+ #define RS485_PORT              Serial
+ #define RS485_DIRECTION_PIN     2
 #endif

 #define ACK_MODBUS40            true
@@ -77,26 +86,26 @@
 // ######### INCLUDES #######################

 #ifdef TRANSPORT_ETH_ENC28J60
-#include <UIPEthernet.h>
+ #include <UIPEthernet.h>
 #elif defined STM32_F429ZI_BOARD
-#include <LwIP.h>
-#include <STM32Ethernet.h>
-#include <EthernetUdp.h>
-#else
-#include <SPI.h>
-#include <Ethernet.h>
-#include <EthernetUdp.h>
-#endif
-
-#ifdef PRODINO_BOARD
-#include "KmpDinoEthernet.h"
-#include "KMPCommon.h"
+ #include <LwIP.h>
+ #include <STM32Ethernet.h>
+ #include <EthernetUdp.h>
+#elif defined PRODINO_BOARD
+ #include <SPI.h>
+ #include "KmpDinoEthernet.h"
+ #include "KMPCommon.h"
+ #include "Ethernet/utility/w5100.h"
+#else
+ #include <SPI.h>
+ #include <Ethernet.h>
+ #include <EthernetUdp.h>
 #endif

 #ifdef STM32_F429ZI_BOARD
-#include <IWatchdog.h>
-#else
-#include <avr/wdt.h>
+ #include <IWatchdog.h>
+#else
+ #include <avr/wdt.h>
 #endif

 #include "NibeGw.h"
@@ -120,7 +129,6 @@
 // Target IP address and port where Nibe UDP packets are send
 IPAddress targetIp(TARGET_IP);
 EthernetUDP udp;
-EthernetUDP udp4readCmnds;
 EthernetUDP udp4writeCmnds;

 NibeGw nibegw(&RS485_PORT, RS485_DIRECTION_PIN);
@@ -130,13 +138,13 @@
 #define DEBUG_BUFFER_SIZE       80

 #ifdef ENABLE_DEBUG
-#define DEBUG_PRINT(level, message) if (verbose >= level) { debugPrint(message); }
-#define DEBUG_PRINTDATA(level, message, data) if (verbose >= level) { sprintf(debugBuf, message, data); debugPrint(debugBuf); }
-#define DEBUG_PRINTARRAY(level, data, len) if (verbose >= level) { for (int i = 0; i < len; i++) { sprintf(debugBuf, "%02X", data[i]); debugPrint(debugBuf); }}
-#else
-#define DEBUG_PRINT(level, message)
-#define DEBUG_PRINTDATA(level, message, data)
-#define DEBUG_PRINTARRAY(level, data, len)
+ #define DEBUG_PRINT(level, message) if (verbose >= level) { debugPrint(message); }
+ #define DEBUG_PRINTDATA(level, message, data) if (verbose >= level) { sprintf(debugBuf, message, data); debugPrint(debugBuf); }
+ #define DEBUG_PRINTARRAY(level, data, len) if (verbose >= level) { for (int i = 0; i < len; i++) { sprintf(debugBuf, "%02X", data[i]); debugPrint(debugBuf); }}
+#else
+ #define DEBUG_PRINT(level, message)
+ #define DEBUG_PRINTDATA(level, message, data)
+ #define DEBUG_PRINTARRAY(level, data, len)
 #endif

 #ifdef ENABLE_DEBUG
@@ -145,12 +153,14 @@

 void debugPrint(char* data)
 {
+#ifdef ENABLE_UDP_DEBUG
   if (ethernetInitialized)
   {
-    udp.beginPacket(targetIp, TARGER_DEBUG_PORT);
+    udp.beginPacket(targetIp, TARGET_DEBUG_PORT);
     udp.write(data);
     udp.endPacket();
   }
+#endif

 #ifdef PRODINO_BOARD
   Serial.print(data);
@@ -225,43 +235,49 @@
     } while (nibegw.messageStillOnProgress());
   }

-  if (!ethernetInitialized)
-  {
-    if (now >= ETH_INIT_DELAY)
-    {
-      DEBUG_PRINT(1, "Initializing Ethernet\n");
-      initializeEthernet();
+  if (!ethernetInitialized && now >= ETH_INIT_DELAY)
+  {
+    initializeEthernet();
+  }
+}
+
+// ######### FUNCTIONS #######################
+
+void initializeEthernet()
+{
+  DEBUG_PRINT(1, "Initializing Ethernet\n");
+  Ethernet.begin(mac, ip, gw, mask);
+
+#ifdef PRODINO_BOARD
+  W5100.setRetransmissionCount(1);
+#endif
+
+  ethernetInitialized = true;
+  udp.begin(INCOMING_PORT_READCMDS);
+  udp4writeCmnds.begin(INCOMING_PORT_WRITECMDS);
+
 #ifdef ENABLE_DEBUG
-      DEBUG_PRINTDATA(0, "%s ", BOARD_NAME);
-      DEBUG_PRINTDATA(0, "version %s\n", VERSION);
-      sprintf(debugBuf, "MAC=%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-      DEBUG_PRINT(0, debugBuf);
-      sprintf(debugBuf, "IP=%d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
-      DEBUG_PRINT(0, debugBuf);
-      sprintf(debugBuf, "GW=%d.%d.%d.%d\n", gw[0], gw[1], gw[2], gw[3]);
-      DEBUG_PRINT(0, debugBuf);
-      sprintf(debugBuf, "TARGET IP=%d.%d.%d.%d\n", TARGET_IP);
-      DEBUG_PRINTDATA(0, "TARGET PORT=%d\n", BOARD_NAME);
-      DEBUG_PRINTDATA(0, "ACK_MODBUS40=%s\n", ACK_MODBUS40 ? "true" : "false");
-      DEBUG_PRINTDATA(0, "ACK_SMS40=%s\n", ACK_SMS40 ? "true" : "false");
-      DEBUG_PRINTDATA(0, "ACK_RMU40=%s\n", ACK_RMU40 ? "true" : "false");
-      DEBUG_PRINTDATA(0, "SEND_ACK=%s\n", SEND_ACK ? "true" : "false");
-      DEBUG_PRINTDATA(0, "ETH_INIT_DELAY=%d\n", ETH_INIT_DELAY);
-      DEBUG_PRINTDATA(0, "RS485_DIRECTION_PIN=%d\n", RS485_DIRECTION_PIN);
-#endif
-    }
-  }
-}
-
-// ######### FUNCTIONS #######################
-
-void initializeEthernet()
-{
-  Ethernet.begin(mac, ip, gw, mask);
-  ethernetInitialized = true;
-  udp.begin(TARGET_PORT);
-  udp4readCmnds.begin(INCOMING_PORT_READCMDS);
-  udp4writeCmnds.begin(INCOMING_PORT_WRITECMDS);
+  DEBUG_PRINTDATA(0, "%s ", BOARD_NAME);
+  DEBUG_PRINTDATA(0, "version %s\n", VERSION);
+  sprintf(debugBuf, "MAC=%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+  DEBUG_PRINT(0, debugBuf);
+  sprintf(debugBuf, "IP=%d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
+  DEBUG_PRINT(0, debugBuf);
+  sprintf(debugBuf, "GW=%d.%d.%d.%d\n", gw[0], gw[1], gw[2], gw[3]);
+  DEBUG_PRINT(0, debugBuf);
+  sprintf(debugBuf, "TARGET IP=%d.%d.%d.%d\n", TARGET_IP);
+  DEBUG_PRINT(0, debugBuf);
+  DEBUG_PRINTDATA(0, "TARGET PORT=%d\n", TARGET_PORT);
+  DEBUG_PRINTDATA(0, "INCOMING_PORT_READCMDS=%d\n", INCOMING_PORT_READCMDS);
+  DEBUG_PRINTDATA(0, "INCOMING_PORT_WRITECMDS=%d\n", INCOMING_PORT_WRITECMDS);
+  DEBUG_PRINTDATA(0, "TARGET PORT=%d\n", TARGET_PORT);
+  DEBUG_PRINTDATA(0, "ACK_MODBUS40=%s\n", ACK_MODBUS40 ? "true" : "false");
+  DEBUG_PRINTDATA(0, "ACK_SMS40=%s\n", ACK_SMS40 ? "true" : "false");
+  DEBUG_PRINTDATA(0, "ACK_RMU40=%s\n", ACK_RMU40 ? "true" : "false");
+  DEBUG_PRINTDATA(0, "SEND_ACK=%s\n", SEND_ACK ? "true" : "false");
+  DEBUG_PRINTDATA(0, "ETH_INIT_DELAY=%d\n", ETH_INIT_DELAY);
+  DEBUG_PRINTDATA(0, "RS485_DIRECTION_PIN=%d\n", RS485_DIRECTION_PIN);
+#endif
 }

 void nibeCallbackMsgReceived(const byte* const data, int len)
@@ -280,23 +296,31 @@
   {
     if (token == READ_TOKEN)
     {
-      DEBUG_PRINT(2, "Read token received\n");
-      int packetSize = udp4readCmnds.parsePacket();
+      DEBUG_PRINT(3, "Read token received from nibe\n");
+      int packetSize = udp.parsePacket();
       if (packetSize) {
-        len = udp4readCmnds.read(data, packetSize);
+        len = udp.read(data, packetSize);
+        DEBUG_PRINTDATA(2, "Send read command to nibe, len=%d, ", len);
+        DEBUG_PRINT(1, " data in: ");
+        DEBUG_PRINTARRAY(1, data, len)
+        DEBUG_PRINT(1, "\n");
 #ifdef TRANSPORT_ETH_ENC28J60
-        udp4readCmnds.flush();
-        udp4readCmnds.stop();
-        udp4readCmnds.begin(INCOMING_PORT_READCMDS);
+        udp.flush();
+        udp.stop();
+        udp.begin(INCOMING_PORT_READCMDS);
 #endif
       }
     }
     else if (token == WRITE_TOKEN)
     {
-      DEBUG_PRINT(2, "Write token received\n");
+      DEBUG_PRINT(3, "Write token received from nibe\n");
       int packetSize = udp4writeCmnds.parsePacket();
       if (packetSize) {
         len = udp4writeCmnds.read(data, packetSize);
+        DEBUG_PRINTDATA(2, "Send write command to nibe, len=%d, ", len);
+        DEBUG_PRINT(1, " data in: ");
+        DEBUG_PRINTARRAY(1, data, len)
+        DEBUG_PRINT(1, "\n");
 #ifdef TRANSPORT_ETH_ENC28J60
         udp4writeCmnds.flush();
         udp4writeCmnds.stop();
@@ -315,11 +339,18 @@

 void sendUdpPacket(const byte * const data, int len)
 {
-  DEBUG_PRINTDATA(2, "Sending UDP packet, len=%d\n", len);
-  DEBUG_PRINTARRAY(2, data, len)
-  DEBUG_PRINT(2, "\n");
+#ifdef ENABLE_DEBUG
+  sprintf(debugBuf, "Sending UDP packet to %d.%d.%d.%d:", TARGET_IP);
+  DEBUG_PRINT(2, debugBuf);
+  DEBUG_PRINTDATA(2, "%d", TARGET_PORT);
+  DEBUG_PRINTDATA(2, ", len=%d, ", len);
+  DEBUG_PRINT(1, "data out: ");
+  DEBUG_PRINTARRAY(1, data, len)
+  DEBUG_PRINT(1, "\n");
+#endif

   udp.beginPacket(targetIp, TARGET_PORT);
   udp.write(data, len);
-  udp.endPacket();
-}
+  int retval = udp.endPacket();
+  DEBUG_PRINTDATA(3, "UDP packet sent %s\n", retval == 0 ? "failed" : "succeed");
+}


started using his code.

started using his code.

--- test/mything/mything.ino
+++ test/mything/mything.ino
@@ -1,23 +1,120 @@
+// Libraries
+// Multiple versions of these libraries exist under the same name, but with different licenses.
+// The libraries here are licensed under the "Creative Commons Attribution 3.0" license,
+// which allows commercial use.
+// Other versions of these libraries are licensed under GPL v2.
+// The versions used here also contain performance optimizations.
+#include <TimerOne.h>
 #include <TimerThree.h> // used for ultrasonic PWM motor control
 #include <PID.h>
 #include <EEPROM.h>
 #include <EEPROMAnything.h>
 #include <SerialCommand.h>

-    int rxPin = 0;
-    int txPin = 1;
+int rxPin = 0;
+int txPin = 1;
 char ldsData;
+
+// LDS receive buffer
+#define packet 22 //the lds sends a continuous stream of 22 bytpe packets at 115200 baud.
+#define startOfPacket 0xFA // 0xFA is the start of the packet (FB-FF is reserved for future formats)
+#define indexByte 1
+#define indexBias 0xA0
+#define speedL 2
+#define speedH 3
+#define dataStart 4
+#define CKL 20
+#define CKH 21
+//  RXBUFF_SZ is packet
+// START_CHAr is startOfPacket
+byte packetBuffer[packet];
+int packetChar = 0; // Incoming character.
+
+// Time to display one degree, in microseconds = 200000 / 360
+#define ONE_DEGREE 556
+
+//////////////////
+// Initialization
 void setup() {
-  // put your setup code here, to run once:
- Serial.begin(115200);              // ...set up the serial ouput in 0004 format
- pinMode(rxPin, INPUT);
- pinMode(txPin, OUTPUT);
+  // Initialize Serial port for LDS
+  Serial.begin(115200, SERIAL_8N1);              // ...set up the serial ouput in 0004 format
+
+  // Initialize 16 bit counters for driving LEDs.
+  // The timers run one cycle per degree, so the timer completes 360
+  // cycles in one revolution of the LDS.
+  Timer1.initialize(ONE_DEGREE); // Set period.
+  Timer3.initialize(ONE_DEGREE);
+  Timer1.start(); // Start up the timers.
+  Timer3.start();
+
+  pinMode(rxPin, INPUT);
+  pinMode(txPin, OUTPUT);
+  ldsData = Serial.read();
+  Serial.print(ldsData, BIN);
+
 }

+// Read one 4-degree packet from the LDS into rxbuff.
+// Packet may not be valid; verify with validpacket().
+void getpacket() {
+  int rxp;
+  bool insync = false;
+
+  packetChar = Serial1.read();
+  while (!insync) {
+    while (packetChar != startOfPacket) {
+      packetChar = Serial1.read();
+      packetBuffer[0] = packetChar;
+    }
+    packetChar = Serial1.read();
+    while (packetChar < 0) packetChar = Serial1.read();
+    packetBuffer[indexByte] = packetChar;
+    insync = packetChar >= indexBias;
+  }
+  rxp = 2;
+
+  while (rxp < packet) {
+    packetChar = Serial1.read();
+    while (packetChar < 0) packetChar = Serial1.read();
+    packetBuffer[rxp] = packetChar;
+    rxp++;
+  }
+}
+
+//index byte is the starting angle for the data payload (0xA0-0xF9)
+//Real angle = (index - 0xA0) *4
+int index() {
+  return (packetBuffer[indexByte]-0xA0);
+}
+
+int angle() {
+  return index() << 2;
+}
+
+// returns distance in mm or a negative number on invalid data.
+int dist(int n) {
+  int v = n << 2;
+  return (packetBuffer[dataStart + v]) | ((packetBuffer[dataStart + v + 1] & 0x9f)<<8);
+}
+
+int speed() {
+  return   (packetBuffer[speedL] | (packetBuffer[speedH]<<8));
+}
+
+// Compute checksum over receive buffer. Returns 'true' if packet is valid.
+bool validpacket() {
+  long chk32 = 0;
+  unsigned int t  = 0;
+  for (int i = 0; i < 20; i += 2) {
+    t = packetBuffer[i] + (unsigned int)(packetBuffer[i + 1] << 8);
+    chk32 = (chk32 << 1) + t;
+  }
+  int checksum = (chk32 & 0x7fff) + (chk32 >> 15);
+  checksum = checksum & 0x7fff;
+  return checksum == (packetBuffer[CKL] | (packetBuffer[CKH] << 8));
+}
+
+//Thing to run
 void loop() {
-  // put your main code here, to run repeatedly:
-  ldsData = Serial.read();
-Serial.print(ldsData, BIN);
-
-
+getpacket();
 }


remove unnecessary sprintHex

remove unnecessary sprintHex

--- c_Broadcast.ino
+++ c_Broadcast.ino
@@ -96,7 +96,6 @@
 {
   // for those who requires the slaves to be up-side down
   FIFOCPY_P(0, F("YY000709000102\n"), 15);
-  sprintHex(12, MODE_SETUP);
   FIFO_INC(15);
   startup_exec = millis();
   return true;


L/C corrections. (fix)

L/C corrections. (fix)

--- hal100/hal100.ino
+++ hal100/hal100.ino
@@ -50,6 +50,7 @@
 float PlanckTime;           // Planck constant
 float pi;                   // π constant
 float valueC = 0;           // calculated value C float
+float valueCEffective = 0;  // calculated value C float
 float valueL = 0;           // calculated value L float
 float valueCorr = 0;        // calculated value C float
 float valueLcorr = 0;       // calculated value L float
@@ -307,7 +308,8 @@
   KHz = 1000;
   PlanckTime = 299792458;
   Cmult = 1.5;
-  valueC = PlanckTime / ( tuningFreqCalc * KHz ) * Cmult + valueCorr;
+  valueCEffective = PlanckTime / ( tuningFreqCalc * KHz ) * Cmult;
+  valueC = valueCEffective + valueCorr;
   Serial.print("Value C pF=");
   Serial.println(valueC);
 }
@@ -315,7 +317,7 @@
 void calculateL () {                            // Calculate "L" value from formula L=((1/(2*π*f*C))/(2*π*f))*1000000000000 (where f in KHz and C in pF)
   pi = 3.14159;
   Lmult = 1000000000000;
-  valueL = ((1 / (2 * pi * tuningFreqCalc * valueC)) / (2 * pi * tuningFreqCalc)) * Lmult + valueLcorr;
+  valueL = ((1 / (2 * pi * tuningFreqCalc * (valueCEffective))) / (2 * pi * tuningFreqCalc)) * Lmult + valueLcorr;
   Serial.print("Value L uH=");
   Serial.println(valueL);
 }


Save some SRAM by having rainbow dir name in flash

--- Arduino/LightPlayer/LightPlayer.ino
+++ Arduino/LightPlayer/LightPlayer.ino
@@ -189,7 +189,9 @@
   sd.ls();

   root_dir.openRoot(&sd);
-  rainbows_dir.open(&root_dir, "rainbows", O_READ);
+  char rainbows_dir_name[9];
+  strcpy_P(rainbows_dir_name, PSTR("rainbows"));
+  rainbows_dir.open(&root_dir, rainbows_dir_name, O_READ);
   Serial.println(F("rainbows:"));
   rainbows_dir.ls();


Added code to test function substring_checker

--- Drones/Drones.ino
+++ Drones/Drones.ino
@@ -139,6 +139,7 @@
   }
   Serial.println();
   gpstime=substring_reader(gpsbuffer,MAX_BUFFER_SIZE,',',',');
+  if(gpstime== NULL) Serial.println("NULL");
   //Serial.println();
   array_length = 1;
   free(gpsbuffer);


Fix SendGratuitousARP()

Fix SendGratuitousARP()

--- Computer_Switch/Computer_Switch.ino
+++ Computer_Switch/Computer_Switch.ino
@@ -43,6 +43,10 @@
 // How often to check for power off state
 unsigned long lastPowerCheck = millis();
 #define POWER_CHECK_FREQUENCY 10000
+
+// How often to send the gratutousARP packet
+unsigned long lastGratuitousARP = millis();
+#define GRATUITOUS_ARP_FREQUENCY 10000

 // WiFi parameters
 const char* ssid = "joshua";
@@ -98,19 +102,25 @@
     checkTempHumid();
     lastTempCheck = millis();
   }
+
+  if (millis() > lastGratuitousARP + GRATUITOUS_ARP_FREQUENCY) {
+    SendGratuitousARP();
+    lastGratuitousARP = millis();
+  }
   // Check status to update variables
   computerOn = digitalRead(POWER_LED);
-}
-
-bool GratuitousARPTask(void *) {
+  delay(1);
+}
+
+void SendGratuitousARP() {
   netif *n = netif_list;
   while (n) {
     etharp_gratuitous(n);
     n = n->next;
   }
-  return true; // repeat? true
-}
-
+}
+
+// Set up WiFi
 void initWifi() {
   //Wifi settings
   WiFi.mode(WIFI_STA);


Fix the info button support

Fix the info button support

--- Event_Printer/Event_Printer.ino
+++ Event_Printer/Event_Printer.ino
@@ -160,7 +160,7 @@
                   motorcycle_state.heated_grips = (K25_Heated_Grips_State)new_value;
               }

-              new_value = HI_NIBBLE(data[5]);
+              new_value = LO_NIBBLE(data[5]);
               if ( new_value != motorcycle_state.info_button )
               {
                   status_changed = true;
@@ -239,13 +239,11 @@
   else text += "Unknown";
   text += "       \n";

-  /* INFO BUTTON CURRENTLY NOT WORKING
   text += "Info Button: ";
   if ( motorcycle_state.info_button == K25_Info_Button_State_short_press ) text += "SHORT";
   else if ( motorcycle_state.info_button == K25_Info_Button_State_long_press ) text += "LONG";
   else text += "Unknown";
   text += "\n";
-  */

   text += "Clutch: ";
   if ( motorcycle_state.clutch == K25_Clutch_Lever_State_out ) text += "OUT";


MQTT callback functionality revamped

MQTT callback functionality revamped

MQTT callback functionality revamped in order to make it less custom
and easier to modify going forward

--- Arduino-Cottage-Monitoring-System.ino
+++ Arduino-Cottage-Monitoring-System.ino
@@ -61,7 +61,7 @@
 char subscribeTopic[ ] = MQTT_SUBSCRIBE_TOPIC; // Arduino will listen this topic for incoming MQTT messages from the Domoticz. The MQTT_SUBSCRIBE_TOPIC is defined in Arduino_Cottage_Monitoring_System.h header file

 //MQTT variables
-String topicID = MQTT_TOPIC; // MQTT topic used in data transmission to the Domoticz. The MQTT_TOPIC is defined in Arduino_Cottage_Monitoring_System.h header file
+//String topicID = MQTT_TOPIC; // MQTT topic used in data transmission to the Domoticz. The MQTT_TOPIC is defined in Arduino_Cottage_Monitoring_System.h header file
 int temperatureSensordtype = 80; // dtype (device type for temperature sensor) is used to help creating MQTT payload
 int switchdtype = 32; // dtype (device type for door switches and siren) is used to help creating MQTT payload
 const int temperatureSensorIDX = 18; // IDX number of temperature sensor
@@ -70,6 +70,8 @@
 const int supplyIDX = 19; // IDX number of virtual electricity on/off switch
 const int sirenIDX = 22; // IDX number of virtual electricity on/off switch
 int switchStatus = 0; // Status of switch (0 = Closed/Off & 1 = Open/on)
+int receivedIDX = 0; // Received IDX number will be stored to this variable
+int deviceStatus = 0; // Received status of device will be stored to this variable

 // Variables for supply status function
 const int eepromAddress = 5; // EEPROM address to store status of supplyPin
@@ -414,11 +416,6 @@
 // MQTT server deliveres data to the Domoticz server running on a same Raspberry Pi
 {

-  // Create MQTT topic and convert it to char array
-	String topicStr = "/actions/domoticz/";
-	topicStr.concat(topicID);
-	topicStr.toCharArray(topic, topicStr.length()+1);
-
 	// Convert payload to char array
 	payload.toCharArray(msg, payload.length()+1);

@@ -429,7 +426,7 @@
     }

 	//Publish payload to MQTT broker
-	if (mqttClient.publish(topic, msg))
+	if (mqttClient.publish(MQTT_TOPIC, msg))
 	{
 		Serial.print("Following data published to MQTT broker: ");
 		Serial.print(topic);
@@ -438,43 +435,52 @@
 		Serial.println();
 	}
 	else
-		Serial.println(F("Publishing to MQTT broker failed..."));
+		Serial.println(F("Publishing to MQTT broker failed"));
 }

 // mqttCallback function handles message arrived on subscribed MQTT topic(s)
 void mqttCallback(char* topic, byte* payload, unsigned int length) {
-
-  Serial.println("MQTT callback received");
-
-  //Create a String from the received payload (char array)
-  String callBackPayload = "";
-  int i;
-
-  for (i = 0; i < length; i++)
-	{
-		//Serial.print((char)payload[i]);
-		callBackPayload += (char)payload[i];
-	}
-
-  // Act according to received payload
-  if (callBackPayload == "On") // Siren to be set On
-  {
-	  Serial.println(F("Siren turned On"));
-	  digitalWrite(sirenPin, HIGH);
-	  Alarm.timerOnce(sirenWatchDogTimer, sirenOffFunction); // Timer is set which will turn off siren after sirenWatchDogTimer period has elapsed
-  }
-  else if (callBackPayload == "Off" && digitalRead(sirenPin) == LOW) // No actions needed if siren is already off
-  {
-	  Serial.println(F("Siren is already off. No actions needed!"));
-  }
-  else if (callBackPayload == "Off") // Siren to be set Off
-    {
-  	  sirenOffFunction();
-    }
-  else // Not valid state. No actions to be taken
-  {
-	  Serial.print(F("Following not valid data received. No actions to be taken:"));
-	  Serial.println(callBackPayload);
+  Serial.print(F("MQTT message arrived ["));
+  Serial.print(topic);
+  Serial.print("] ");
+  for (int i = 0; i < length; i++) {
+    Serial.print((char)payload[i]);
+  }
+  Serial.println();
+
+  // Receive data to be parsed
+  Serial.println(F("Starting parsing received data..."));
+  char *rest; // Help variable needed with following iterations
+
+  //  First strtok iteration. Parses IDX number out from the received data.
+  //receivedIDX = atoi (strtok_r((byte*)payload,":",&rest)); // Received IDX is converted to int with atoi function in order to use it as constructor parameter and with switch structure
+  receivedIDX = atoi (strtok_r(payload,":",&rest));
+  Serial.print(F("IDX = "));
+  Serial.println(receivedIDX);
+
+  //  Second strtok iteration. Parses status of device out from the received data.
+  deviceStatus = atoi (strtok_r(NULL,":",&rest)); // Received dtype is converted to int with atoi function in order to use it as constructor parameter and with switch structure
+  Serial.print(F("Status of device = "));
+  Serial.println(deviceStatus);
+
+  //Act according to the received data
+  if (receivedIDX == sirenIDX && deviceStatus == 0) // Siren to be set Off
+  {
+    sirenOffFunction();
+    Serial.println(F("Siren turned off"));
+    sendMQTTPayload("MQTT command executed");
+  }
+  else if (receivedIDX == sirenIDX && deviceStatus == 1) // Siren to be set On
+  {
+    digitalWrite(sirenPin, HIGH);
+    Alarm.timerOnce(sirenWatchDogTimer, sirenOffFunction); // Timer is set which will turn off siren after sirenWatchDogTimer period has elapsed
+    Serial.println(F("Siren turned on"));
+    sendMQTTPayload("MQTT command executed");
+  }
+  else //Not valid state. No actions to be taken
+  {
+    Serial.println(F("Incorrect IDX and/or status received"));
+    sendMQTTPayload("MQTT command failed");
   }
 }


Enable bypass on MPU6050 to be able to read magnetometer according to hint given on Drotek forum http://www.drotek.fr/forum/viewtopic.php?f=10&t=204

--- Arduino/HMC5883L_raw/HMC5883L_raw.ino
+++ Arduino/HMC5883L_raw/HMC5883L_raw.ino
@@ -38,11 +38,18 @@
 // for both classes must be in the include path of your project
 #include "I2Cdev.h"
 #include "HMC5883L.h"
+#include "MPU6050_6Axis_MotionApps20.h"

 // class default I2C address is 0x1E
 // specific I2C addresses may be passed as a parameter here
 // this device only supports one I2C address (0x1E)
 HMC5883L mag;
+// class default I2C address is 0x68
+// specific I2C addresses may be passed as a parameter here
+// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
+// AD0 high = 0x69
+//MPU6050 mpu;
+MPU6050 mpu(0x69); // <-- use for AD0 high

 int16_t mx, my, mz;

@@ -57,6 +64,8 @@
     // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
     // it's really up to you depending on your project)
     Serial.begin(38400);
+    mpu.setI2CMasterModeEnabled(0);
+    mpu.setI2CBypassEnabled(1);

     // initialize device
     Serial.println("Initializing I2C devices...");


Update rs485_smodbus_master.ino

Update rs485_smodbus_master.ino

--- protocol/modbus/lab/rs485_smodbus_master.ino
+++ protocol/modbus/lab/rs485_smodbus_master.ino
@@ -7,9 +7,12 @@
 #define TxEnablePin 2
 #define LED 9
 //ID slave node
-#define ID 10
+#define SLAVEID 10
+#define SLAVEADDREG 1
+#define rnoreg 1

-#define TOTAL_NO_OF_REGISTERS 1
+
+#define TOTAL_NO_OF_REGISTERS 2

 enum
 {
@@ -24,8 +27,8 @@

 void setup()
 {
-  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0);
-  modbus_construct(&packets[PACKET2], ID, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
+  modbus_construct(&packets[PACKET1], SLAVEID, READ_HOLDING_REGISTERS, 0, 1, 0);
+  modbus_construct(&packets[PACKET2], SLAVEID, PRESET_MULTIPLE_REGISTERS, SLAVEADDREG, 1, 0);
   modbus_configure(&Serial, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

   pinMode(LED, OUTPUT);


Made minor changes to the operation of the relay

--- Safety_System_Integration/Safety_System_Integration/Safety_System_Integration.ino
+++ Safety_System_Integration/Safety_System_Integration/Safety_System_Integration.ino
@@ -4,7 +4,7 @@
  * Safety System Integration
  * YCP FSAE Formula Electric Car Team 2017
  * Patrick Hock
- * July 30 2017
+ * July 31 2017
  *
  * For now, this is mostly test code. Follows similar structure to the
  * Super Dooper Looper
@@ -49,7 +49,7 @@
     if(bitRead(lclIntTrack, 0))
     {
       digitalWrite(BSPD_ERR_LED, HIGH); // Turns on BSPD error LED
-      digitalWrite(RELAY_OUT, HIGH);     // Disengages safety system relay
+      digitalWrite(RELAY_OUT, LOW);     // Disengages safety system relay
       bitWrite(lclIntTrack, 0, 0);      // Resets the "interrupt flag" for BSPD Error
     }

@@ -90,7 +90,7 @@
   // Set mode for safety system relay. Set output to high;
   // when output is low, relay will turn off.
   pinMode(RELAY_OUT, OUTPUT);
-  digitalWrite(RELAY_OUT, LOW);
+  digitalWrite(RELAY_OUT, HIGH);

   Serial.begin(9600); // Starts 9600 baud serial connection for ADC reading
   delay(500);


fix mixing bracket

fix mixing bracket

--- dfrdb/dfrdb.ino
+++ dfrdb/dfrdb.ino
@@ -135,7 +135,7 @@
   }
 } // end readWristInterruptPin()

-void readClawInterruptPin()        // works just like wrist interrupt
+void readClawInterruptPin(){        // works just like wrist interrupt
   if(digitalRead(ClawInterruptPin) == HIGH){
     clawTimer = micros();
   }


Add debug stuff

Add debug stuff

--- Segment16Sign.ino
+++ Segment16Sign.ino
@@ -4,10 +4,16 @@
 Segment16 display;

 void setup(){
-   Serial.begin(9600);
+  Serial.begin(9600);
+  while (!Serial) {}  // wait for Leonardo
+  Serial.println("Type any character to start");
+  while (Serial.read() <= 0) {}
+  delay(200);  // Catch Due reset problem
+  // assume the user typed a valid character and no reset happened
 }

 void loop(){
+  Serial.println("LOOP");
   display.show();
-  delay(2);
+  delay(1000);
 }


add Serial1.flush(); for out buffer

add Serial1.flush(); for out buffer

--- Teensy/Teensy.ino
+++ Teensy/Teensy.ino
@@ -91,6 +91,7 @@
   Serial1.print(strTopic);
   Serial1.print(":");
   Serial1.println(strMessage);
+  Serial1.flush();
 }

 // handle received serial data (myqtt messages from ESP8266)


updating RF CS pin to 8 from 10, I will fork this project to nest-mqtt and nest-rest

--- nest.ino
+++ nest.ino
@@ -2,16 +2,16 @@
 #include <NanodeUIP.h>
 #include <NanodeMQTT.h>
 #include <RF22ReliableDatagram.h>
-#include <RF22.h>
+#include <RF22.h>
 #include <SPI.h>

 NanodeMQTT mqtt(&uip);

-//#define CLIENT_ADDRESS 1
 #define SERVER_ADDRESS 0
+
+// Singleton instance of the radio
+RF22ReliableDatagram manager(SERVER_ADDRESS,8,0);

-// Class to manage message delivery and receipt, using the driver declared above
-RF22ReliableDatagram manager(SERVER_ADDRESS);
 const byte macaddr[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
 const char topic[] = "skydome/7469692d3031";
 int a = -1;
@@ -83,14 +83,14 @@
     Serial.println(F("init success"));
   else
     Serial.println(F("init failed"));
-
-  uip.init(macaddr);
-  uip.get_mac_str(buf);
-  Serial.println(buf);
-  uip.wait_for_link();
-  Serial.println(F("Link is up"));
-  uip.init_resolv(resolv_found);
-  uip.start_dhcp(dhcp_status);
+//
+//  uip.init(macaddr);
+//  uip.get_mac_str(buf);
+//  Serial.println(buf);
+//  uip.wait_for_link();
+//  Serial.println(F("Link is up"));
+//  uip.init_resolv(resolv_found);
+//  uip.start_dhcp(dhcp_status);
 }

 void publish(uint8_t data[], uint8_t len ) {
@@ -109,9 +109,10 @@
     uint8_t len = 2;
     uint8_t from;
     if (manager.recvfromAck(buf, &len, &from)) {
+      Serial.print(F("Received :"));
       uint8_t data[10] = { macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5], SERVER_ADDRESS, from, buf[0], buf[1]};
       uint8_t len = 10;
-      publish(data, len);
+      //publish(data, len);
       // Send a reply back to the originator client
       if (!manager.sendtoWait(buf, 2, from)) {
         //// alarm to a red led !!!


Se non ci sono notifiche viene visualizzato orario a schermo intero

--- WerCA_nightly/WerCA_nightly.ino
+++ WerCA_nightly/WerCA_nightly.ino
@@ -407,44 +407,54 @@
                 display.setContrast(25);
                 display.setTextSize(1);

-                //Visualizza ore
-                display.setCursor(54,0);
-                display.print(ELP_data[10], DEC);
-                display.print(ELP_data[11]);
-                if(ELP_data[12] < 10)
-                  display.print("0");
-                display.print(ELP_data[12], DEC);
-
-                if(num_calls > 0){
-                  display.drawBitmap(0, 12, icon_phone_16, 16, 16, BLACK);
-                  display.setCursor(3,30);
+                if(num_sms == 0 && num_calls == 0 && num_email == 0 && num_other == 0){
+                  //se non ci sono notifiche visualizza ore a schermo intero
+                  display.setCursor(13,16);
                   display.setTextSize(2);
-                  display.print(num_calls);
-                }
-
-                if(num_sms > 0){
-                  display.drawBitmap(22, 12, icon_sms_16, 16, 16, BLACK);
-                  display.setCursor(25,30);
-                  display.setTextSize(2);
-                  display.print(num_sms);
+                  display.print(ELP_data[10], DEC);
+                  display.print(ELP_data[11]);
+                  if(ELP_data[12] < 10)
+                    display.print("0");
+                  display.print(ELP_data[12], DEC);
+
+                } else {
+                  //Visualizza ore
+                  display.setCursor(54,0);
+                  display.print(ELP_data[10], DEC);
+                  display.print(ELP_data[11]);
+                  if(ELP_data[12] < 10)
+                    display.print("0");
+                  display.print(ELP_data[12], DEC);
+
+                  if(num_calls > 0){
+                    display.drawBitmap(0, 12, icon_phone_16, 16, 16, BLACK);
+                    display.setCursor(3,30);
+                    display.setTextSize(2);
+                    display.print(num_calls);
+                  }
+
+                  if(num_sms > 0){
+                    display.drawBitmap(22, 12, icon_sms_16, 16, 16, BLACK);
+                    display.setCursor(25,30);
+                    display.setTextSize(2);
+                    display.print(num_sms);
+                  }
+
+                  if(num_email > 0){
+                    display.drawBitmap(44, 12, icon_email_16, 16, 16, BLACK);
+                    display.setCursor(47,30);
+                    display.setTextSize(2);
+                    display.print(num_email);
+                  }
+
+                  if(num_other > 0){
+                    display.drawBitmap(66, 12, icon_web_16, 16, 16, BLACK);
+                    display.setCursor(69,30);
+                    display.setTextSize(2);
+                    display.print(num_other);
+                  }
                 }
-
-                if(num_email > 0){
-                  display.drawBitmap(44, 12, icon_email_16, 16, 16, BLACK);
-                  display.setCursor(47,30);
-                  display.setTextSize(2);
-                  display.print(num_email);
-                }
-
-                if(num_other > 0){
-                  display.drawBitmap(66, 12, icon_web_16, 16, 16, BLACK);
-                  display.setCursor(69,30);
-                  display.setTextSize(2);
-                  display.print(num_other);
-                }
-
                 display.display();
-
               break;

               case 'B':  //Chiamata in arrivo


Minor improvements and docstrings for Arduino code.

--- arduino/moisture-sensor.ino
+++ arduino/moisture-sensor.ino
@@ -10,7 +10,11 @@
 #define MINIMUM_FIRMWARE_VERSION    "0.6.6"
 #define MODE_LED_BEHAVIOUR          "MODE"

-#define NUM_SAMPLES 50
+#define TIME_BETWEEN_READINGS 30 * 60 * 1000
+#define WARMUP_TIME 10 * 1000
+#define NUM_SAMPLES 30
+#define DELAY_BETWEEN_SAMPLES 500
+
 const int sensor_pin = A0;
 const int enable_sensor_pin = 7;

@@ -21,27 +25,24 @@
                               BLUEFRUIT_UART_MODE_PIN,
                               BLUEFRUIT_UART_CTS_PIN,
                               BLUEFRUIT_UART_RTS_PIN);
-
+
+/** Prints an error and ends the execution. */
 void error(const __FlashStringHelper* err) {
   Serial.println(err);
   while (1);
 }

+/** Waits until making a connection with the host. */
 void connect_to_host() {
   ble.reset();
-
   ble.echo(false);
-
   Serial.println(F("Requesting Bluefruit info:"));
   ble.info();
-
   ble.verbose(false);
-
+
   Serial.println(F("Waiting for connection"));
-
   while (!ble.isConnected())
     delay(500);
-
   Serial.println(F("Connected"));

   if (ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION)) {
@@ -52,6 +53,7 @@
   }
 }

+/** Setup method. */
 void setup() {
   while (!Serial);
   delay(500);
@@ -69,17 +71,21 @@
       error(F("Couldn't factory reset"));
     }
   }
-
-  connect_to_host();

   pinMode(enable_sensor_pin, OUTPUT);
 }

-int read_sensor(int samples[]) {
-  Serial.println(F("-- Enabling sensor --"));
+/** Reads samples from the sensor.
+ *
+ *  @param samples The array where to store the samples.
+ */
+void read_sensor(int samples[]) {
+  Serial.println(F("-- Enabling sensor and waiting for warm-up --"));
   digitalWrite(enable_sensor_pin, HIGH);
+  delay(WARMUP_TIME);
+
   for (int i = 0; i < NUM_SAMPLES; i++) {
-    delay(500);
+    delay(DELAY_BETWEEN_SAMPLES);
     samples[i] = analogRead(sensor_pin);
     Serial.print(F("Sensor value: "));
     Serial.println(samples[i]);
@@ -88,30 +94,35 @@
   digitalWrite(enable_sensor_pin, LOW);
 }

+/** Sends a packet containing a sample to the host.
+ *
+ *  @param sample The sample to send.
+ */
 void send_packet(int sample) {
   Serial.print(F("Sending sample: "));
   Serial.println(sample);

   ble.print("AT+BLEUARTTX=");
-  ble.print("B");
+  ble.print("B"); // packet begin
   ble.print(sample);
-  ble.println("E");
+  ble.println("E"); // packet end
   if (!ble.waitForOK())
     Serial.println(F("Failed to send?"));
 }

+/** Loop method. */
 void loop() {
+  if (!ble.isConnected()) {
+    Serial.println(F("Disconnected!"));
+    connect_to_host();
+  }
+
   int samples[NUM_SAMPLES];
   read_sensor(samples);

   for (int i = 0; i < NUM_SAMPLES; i++)
     send_packet(samples[i]);

-  delay(30 * 1000);
-
-  if (!ble.isConnected()) {
-    Serial.println(F("Disconnected!"));
-    connect_to_host();
-  }
+  delay(TIME_BETWEEN_READINGS);
 }


.More

.More

--- examples/extras/SitBit_Debounce/SitBit_Debounce.ino
+++ examples/extras/SitBit_Debounce/SitBit_Debounce.ino
@@ -10,7 +10,7 @@
 // Define the pin that represents the tilt switch
 const int tiltSwitch = 6;
 int stepCount = 0;
-int stepsLabel = 0;
+int stepsLabelId = 0;

 // Define constants for debounce
 const int min_on_time = 5;
@@ -40,7 +40,7 @@
   Serial.println("Press");
   stepCount++;
   if (SimbleeForMobile.updatable) {
-      SimbleeForMobile.updateValue(stepsLabel, stepCount);
+      SimbleeForMobile.updateValue(stepsLabelId, stepCount);
   }
 }

@@ -99,8 +99,6 @@

-
-
 void loop() {
   updateSwitchState();

@@ -112,12 +110,15 @@

 void ui()
 {
-  Serial.println("UI");
   SimbleeForMobile.beginScreen(WHITE);
+
+  // Place a Logo on the screen
+  SimbleeForMobile.drawText(110, 180, "Steps", BLACK, 40);
+
+  // Place an updateable label on the screen
+  stepsLabelId = SimbleeForMobile.drawText(150, 220, stepCount, BLACK, 40);

-  SimbleeForMobile.drawText(60, 90, "Steps");
-
-  stepsLabel = SimbleeForMobile.drawText(60, 310, stepCount);
+  SimbleeForMobile.endScreen();

   SimbleeForMobile.endScreen();
 }


Cleanup and slight modification of grove sensor code.

--- frontbox_solo/frontbox_solo.ino
+++ frontbox_solo/frontbox_solo.ino
@@ -11,7 +11,6 @@
 //  MQ7			A0		23
 //  MQ7_VOLTAGE	        D2		4
 //  TEMP		A1		24
-//  PULSE		A2		25

 // Memory PINOUTS
 // Arduino-- SD shield
@@ -39,7 +38,7 @@
 unsigned long age;
 int gps_year;
 byte gps_month, gps_day, gps_hour, gps_minute, gps_second;
-bool haveClock=false;
+unsigned long gps_start;

 // **************** FOR SD CARD ******************
 #define CHIP_SELECT_PIN 10
@@ -48,27 +47,26 @@

 // **************** FOR GROVE SENSOR ****************
 #define GROVE_READ_PIN 3 // Digital PIN 3 ATMEGA 5
-unsigned long grove_duration;
-unsigned long grove_start_time;
-unsigned long grove_stop_time;
+unsigned long grove_start;
+const unsigned grove_sample_time=1000;   // 1s
 unsigned long lowpulseoccupancy = 0;
 float ratio = 0;
 float concentration = 0;

 // **************** FOR SHARP SENSOR ****************
-#define SHARP_READ_PIN 3 // Analog PIN 3 ATMEGA 26
+#define SHARP_READ_PIN 3     // Analog PIN 3 ATMEGA 26
+#define SHARP_LED_PIN 4      // Digital PIN 4 ATMEGA 6
 int sharp_dust_val = 0;
 float sharp_voltage=0;

-#define SHARP_LED_PIN 4      // Digital PIN 4 ATMEGA 6

 // **************** FOR MQ7 SENSOR ****************
 #define CO_PWR_SEL_PIN 2    // Digital PIN 2 ATMEGA PIN 4
 #define CO_READ_PIN 0       // Analong PIN 0 ATMEGA PIN 23
 #define CO_HEAT_TIME 60000  // 60 seconds heat time
-#define CO_READ_TIME 90000  // 90 seconds reat time
+#define CO_READ_TIME 90000  // 90 seconds read time

 unsigned long CO_timer_start;
 unsigned long CO_switch_time;
@@ -84,13 +82,11 @@

 // **************** RTC ****************
 RTC_DS1307 rtc;
-bool haveRTC=false; // if we have time info from gps
 DateTime now;
-
-// **************** timer for sensor data collection ****************
-unsigned long sensors_read_time_start;
+bool haveClock=false;
+
+// **************** KEEP TRACK OF NUMBER OF RECORDS ****************
 unsigned num_records = 0;
-#define SENSORS_READ_TIME  2000    // ms

 void setup()
@@ -105,13 +101,14 @@
   pinMode(SHARP_LED_PIN, OUTPUT);

   // **************** FOR GROVE SENSOR ****************
-  pinMode(8, INPUT);
-  pinMode(13, OUTPUT);
-  grove_start_time=millis();
+  // nothing, these are not used
+  // pinMode(8, INPUT);
+  // pinMode(13, OUTPUT);
+

   // **************** FOR MQ7 SENSOR ****************
   pinMode(CO_PWR_SEL_PIN, OUTPUT);
-  digitalWrite(CO_PWR_SEL_PIN, LOW);// 5v phase
+  digitalWrite(CO_PWR_SEL_PIN, LOW);// start with 5v (clean) phase
   heaterInHighPhase = true;
   CO_timer_start = millis();
   CO_switch_time = CO_timer_start + CO_HEAT_TIME;
@@ -125,25 +122,20 @@

   // filename will be mm-dd-hh.txt
   DateTime rtc_time=rtc.now();
-  file_name = String( rtc_time.month() ) + '-' + String( rtc_time.day() ) + '-' +
+  file_name = String( rtc_time.month() ) + '-' + String( rtc_time.day() ) + '@' +
       String( rtc_time.hour() ) + ".txt";
 #ifndef DEBUG
   SD.begin(CHIP_SELECT_PIN);
   delay(100); // otherwise open() will fail

   // write header
-
   data_file = SD.open(file_name.c_str(), FILE_WRITE);
   if (data_file) {
     data_file.print("Rec. #\tMM/DD/YYYY\tHH:MM:SS (UTC)\tlatitude\tlongitude\t");
     data_file.println("Sharp\tGrove\tCO read\tCO heat\tHumidity\tTemp (celsius)");
     data_file.close();
   }
-
- #endif
-
-  // **************** FOR SENOR READING TIMER ****************
-  sensors_read_time_start = millis();
+#endif

 } // setup

@@ -157,8 +149,8 @@
   unsigned short sentences, failed;
 #endif

-  // For one second we parse GPS data and report some key values
-  for (unsigned long start = millis(); millis() - start < 1000;) {
+  // For one second we parse GPS data
+  for (gps_start = millis(); millis() - gps_start < 1000;) {
     while (Serial.available()) {
       char c = Serial.read();
       //Serial.write(c); // uncomment this line if you want to see the GPS data flowing
@@ -184,14 +176,11 @@
       }
     }

- #ifdef DEBUG
+#ifdef DEBUG
  gps.stats(&chars, &sentences, &failed);
-  Serial.print(" CHARS=");
-  Serial.print(chars);
-  Serial.print(" SENTENCES=");
-  Serial.print(sentences);
-  Serial.print(" CSUM ERR=");
-  Serial.println(failed);
+  Serial.print(" CHARS=");      Serial.print(chars);
+  Serial.print(" SENTENCES=");  Serial.print(sentences);
+  Serial.print(" CSUM ERR=");   Serial.println(failed);
   Serial.flush();
   if (chars == 0)
     Serial.println("** No characters received from GPS: check wiring **");
@@ -200,11 +189,13 @@
   // **************** FOR SHARP SENSOR ****************
   // nothing

+
   // **************** FOR GROVE SENSOR ****************
-  // continuous reading
-  grove_duration = pulseIn(GROVE_READ_PIN, LOW);
-  lowpulseoccupancy += grove_duration;
-  grove_stop_time=millis();
+  // spend grove_sample_time ms (1000) reading grove sensor
+  // low pulse is 10 to 90 ms in length.
+  for( grove_start=millis(); millis() - grove_start < grove_sample_time;) {
+    lowpulseoccupancy +=  pulseIn(GROVE_READ_PIN, LOW); //  1s timeout
+  }

   // **************** FOR MQ7 SENSOR ****************
   // nothing
@@ -212,17 +203,10 @@
   // **************** FOR TEMP & HUMIDITY SENSOR ****************
   // Be sure to wait 2 seconds between measurements.

-  // **************** READ SENSORS ****************
-#ifdef DEBUG
-    Serial.print("Time since last reading: ");
-    Serial.println(millis() - sensors_read_time_start);
-    Serial.flush();
-#endif
-
-  if( (millis() - sensors_read_time_start) > SENSORS_READ_TIME ) {
-    RecordSensors();
-    sensors_read_time_start = millis();
-  }
+
+  // we've spent 1 second reading gps data and 1 second reading grove data
+  // go ahead and read the remaining sensors and record the data
+  RecordSensors();

 } // void loop()

@@ -276,11 +260,12 @@

   // **************** FOR GROVE SENSOR ****************
     // Integer percentage 0=>100
-  ratio = lowpulseoccupancy / ((grove_stop_time - grove_start_time) * 10.0);
+    // lowpulseoccupancy is in us and grove_sample_time in ms
+  ratio = lowpulseoccupancy / (grove_sample_time * 10.0);
     // using spec sheet curve, gives particles per 0.01 cubic foot
-  concentration = 1.1*pow(ratio, 3) - 3.8*pow(ratio, 2) + 520 * ratio + 0.62;
+  //concentration = 1.1*pow(ratio, 3) - 3.8*pow(ratio, 2) + 520 * ratio + 0.62;
+  concentration = 1.1*ratio*ratio*ratio - 3.8*ratio*ratio + 520*ratio + 0.62;
   lowpulseoccupancy = 0;  // reset
-  grove_start_time=millis();

   // ********** KEEP TRACK OF NUMBER OF RECORDS *********
@@ -358,10 +343,10 @@
   // altitude, speed?

   // sharp sensor value
-  data_file.print(sharp_voltage); data_file.print('\t');
+  data_file.print( (unsigned long)sharp_voltage); data_file.print('\t');

   //  grove sensor value
-  data_file.print(concentration);  data_file.print('\t');
+  data_file.print( (unsigned long)concentration);  data_file.print('\t');

   // MQ7 CO sensor value
    if(heaterInHighPhase) {
@@ -375,13 +360,10 @@

   // DHT22 sensor values
-  data_file.print(h);  data_file.print('\t');
-  data_file.print(f);  data_file.println();
+  data_file.print( (unsigned)h);  data_file.print('\t');
+  data_file.print(f,1);  data_file.println();
   data_file.close();
 #endif

-  // Reset the grove sample time
-  grove_start_time=millis();
-
 } // RecordSensors()


Adding more informative ROS debug output.

--- src/SabertoothDriverROS/SabertoothDriverROS.ino
+++ src/SabertoothDriverROS/SabertoothDriverROS.ino
@@ -14,7 +14,7 @@
  / communications.
  */
 #include <ros.h>
-#include <std_msgs/Int32.h>
+#include <std_msgs/String.h>
 #include <command2ros/ManualCommand.h>
 #include <EncoderFL.h>
 #include <EncoderML.h>
@@ -24,7 +24,7 @@
 #include <EncoderRR.h>
 #include "SabertoothDriverROS.h"

-std_msgs::Int32 msg;
+std_msgs::String msg;
 ros::Publisher pubResults("testing", &msg);
 EncoderFL efl;
 EncoderML eml;
@@ -42,6 +42,7 @@
 bool currentlyRotating = false;
 bool currentlyDriving = false;

+const int ARTICULATION_OFFSET = 6;
 // How long should we drive for (milliseconds)?
 unsigned long driveTimeMillis = 0;
 //DriveUntil: Used when driving forwards.
@@ -56,10 +57,10 @@

 void newManualCommandCallback(const command2ros::ManualCommand& nmc)
 {
- // TODO: Update wheel status info. Determine if we need to rotate.
- currentlyRotating = currentlyRotating || updateTargetWheelStatus(nmc);
- driveTimeMillis = (long)(nmc.drive_duration * 1000);
- emergencyStop = nmc.e_stop;
+  // TODO: Update wheel status info. Determine if we need to rotate.
+  currentlyRotating = currentlyRotating || updateTargetWheelStatus(nmc);
+  driveTimeMillis = (long)(nmc.drive_duration * 1000);
+  emergencyStop = nmc.e_stop;
 }

@@ -75,42 +76,42 @@
     retval = true;
     targetWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].orientation = (int)nmc.fl_articulation_angle;
   }
-
+
   // Check if the middle-left wheel orientation should be changed.
   if(targetWheelStatus[MIDDLE_LEFT_DRIVE_MOTOR_ID].orientation != (int)nmc.ml_articulation_angle)
   {
     retval = true;
     targetWheelStatus[MIDDLE_LEFT_DRIVE_MOTOR_ID].orientation = (int)nmc.ml_articulation_angle;
   }
-
+
   // Check if the rear-left wheel orientation should be changed.
   if(targetWheelStatus[REAR_LEFT_DRIVE_MOTOR_ID].orientation != (int)nmc.rl_articulation_angle)
   {
     retval = true;
     targetWheelStatus[REAR_LEFT_DRIVE_MOTOR_ID].orientation = (int)nmc.rl_articulation_angle;
   }
-
+
   // Check if the front-right wheel orientation should be changed.
   if(targetWheelStatus[FRONT_RIGHT_DRIVE_MOTOR_ID].orientation != (int)nmc.fr_articulation_angle)
   {
     retval = true;
     targetWheelStatus[FRONT_RIGHT_DRIVE_MOTOR_ID].orientation = (int)nmc.fr_articulation_angle;
   }
-
+
   // Check if the middle-right wheel orientation should be changed.
   if(targetWheelStatus[MIDDLE_RIGHT_DRIVE_MOTOR_ID].orientation != (int)nmc.mr_articulation_angle)
   {
     retval = true;
     targetWheelStatus[MIDDLE_RIGHT_DRIVE_MOTOR_ID].orientation = (int)nmc.mr_articulation_angle;
   }
-
+
   // Check if the rear-right wheel orientation should change.
   if(targetWheelStatus[REAR_RIGHT_DRIVE_MOTOR_ID].orientation != (int)nmc.rr_articulation_angle)
   {
     retval = true;
     targetWheelStatus[REAR_RIGHT_DRIVE_MOTOR_ID].orientation = (int)nmc.rr_articulation_angle;
   }
-
+
   // Update target drive speeds.
   targetWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].velocity = (long)nmc.fl_drive_speed;
   targetWheelStatus[FRONT_RIGHT_DRIVE_MOTOR_ID].velocity = (long)nmc.fr_drive_speed;
@@ -119,7 +120,7 @@
   targetWheelStatus[REAR_LEFT_DRIVE_MOTOR_ID].velocity = (long)nmc.rl_drive_speed;
   targetWheelStatus[REAR_RIGHT_DRIVE_MOTOR_ID].velocity = (long)nmc.rr_drive_speed;
   return retval;
-
+
 }

@@ -135,7 +136,7 @@
     // short-circuit
     return;
   }
-
+
   if(currentlyRotating)
   {
     // TODO:Rotate
@@ -159,7 +160,7 @@
       stopAllMotors();
     }
   }
-
+
 }

 // A function to articulate the wheels to face the desired orientation.
@@ -167,60 +168,88 @@
 {
   // For now, only articulate the FRONT LEFT wheel.
   int delta = 0;
-
-  // Which direction should we rotate?
-  delta  = targetWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].orientation - currentWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].orientation;
-  if(0==delta)
-  {
-    driveCounterclockwise(0, FRONT_LEFT_ARTICULATION_MOTOR_ID);
-    driveCounterclockwise(0, FRONT_LEFT_DRIVE_MOTOR_ID);
-    // TODO: update this when we have multi-wheel support
+  int motorIDX;
+  static bool currentlyMoving[6];
+  bool stillRotating = false;
+
+  for(motorIDX = 0; motorIDX <= 5; ++motorIDX)
+  {
+    // Which direction should we rotate?
+    delta  = targetWheelStatus[motorIDX].orientation - currentWheelStatus[motorIDX].orientation;
+    if(delta < 3 && delta > -3)
+    {
+      driveCounterclockwise(0, motorIDX + ARTICULATION_OFFSET);
+      driveCounterclockwise(0, motorIDX);
+
+      char* error = "Stopping motor: X";
+      error[16] = '0'+motorIDX;
+      msg.data = error;
+      pubResults.publish(&msg);
+      // TODO: update this when we have multi-wheel support
+      currentlyMoving[motorIDX] = false;
+    }
+    else if (((delta > 0) && (delta < 180)) ||
+      ((delta + 360) < 180 ))
+    {
+      if(!currentlyMoving[motorIDX])
+      {
+        char* error = "Starting motor: X";
+        error[16] = '0'+motorIDX;
+        msg.data = error;
+        pubResults.publish(&msg);
+        driveCounterclockwise(ARTICULATION_SPEED, motorIDX + ARTICULATION_OFFSET);
+        driveCounterclockwise(ARTICULATION_DRIVE_SPEED, motorIDX);
+        stillRotating = true;
+        currentlyMoving[motorIDX] = true;
+      }
+
+    }
+    else
+    {
+      if(!currentlyMoving[motorIDX])
+      {
+        char* error = "Starting motor: X";
+        error[16] = '0'+motorIDX;
+        msg.data = error;
+        pubResults.publish(&msg);
+        driveClockwise(ARTICULATION_SPEED, motorIDX + ARTICULATION_OFFSET);
+        driveClockwise(ARTICULATION_DRIVE_SPEED, motorIDX);
+        stillRotating = true;
+        currentlyMoving[motorIDX] = true;
+      }
+    }
+  }
+
+  if(!stillRotating)
+  {
+    driveUntilTime = millis() + driveTimeMillis;
     currentlyRotating = false;
-    currentlyDriving = false;
-    driveUntilTime = millis() + driveTimeMillis;
-  }
-  else if (((delta > 0) && (delta < 180)) ||
-  ((delta + 360) < 180 ))
-  {
-    if(!currentlyDriving)
-    {
-      driveCounterclockwise(ARTICULATION_SPEED, FRONT_LEFT_ARTICULATION_MOTOR_ID);
-      driveCounterclockwise(ARTICULATION_DRIVE_SPEED, FRONT_LEFT_DRIVE_MOTOR_ID);
-      currentlyDriving = true;
-    }
-
   }
   else
   {
-    if(!currentlyDriving)
-    {
-      driveClockwise(ARTICULATION_SPEED, FRONT_LEFT_ARTICULATION_MOTOR_ID);
-      driveClockwise(ARTICULATION_DRIVE_SPEED, FRONT_LEFT_DRIVE_MOTOR_ID);
-      currentlyDriving = true;
-    }
-  }
-
-
+    currentlyRotating = true;
+  }
+
 }

 // A function that tells all motors to stop moving.
 void stopAllMotors()
 {
-    // send stop-driving commands to all motors
-    for(int i = 0; i < 12; ++i)
-    {
-      driveClockwise(0,i);
-    }
+  // send stop-driving commands to all motors
+  for(int i = 0; i < 12; ++i)
+  {
+    driveClockwise(0,i);
+  }
 }

 // A function to drive all motors at the desired rates.
 void driveAllMotors()
 {
-    // send driving commands to all motors
-    for(int i = 0; i < 6; ++i)
-    {
-      driveClockwise(targetWheelStatus[i].velocity, i);
-    }
+  // send driving commands to all motors
+  for(int i = 0; i < 6; ++i)
+  {
+    driveClockwise(targetWheelStatus[i].velocity, i);
+  }
 }

 // Function to drive a specific motor forward.
@@ -264,35 +293,35 @@
     temp += 400;
   }
   currentWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].orientation = (int)((temp * 9L) / 10L);
-
+
   temp = EncoderML::getPosition();
   if (temp < 0)
   {
     temp += 400;
   }
   currentWheelStatus[MIDDLE_LEFT_DRIVE_MOTOR_ID].orientation = (int)((temp * 9L) / 10L);
-
+
   temp = EncoderRL::getPosition();
   if (temp < 0)
   {
     temp += 400;
   }
   currentWheelStatus[REAR_LEFT_DRIVE_MOTOR_ID].orientation = (int)((temp * 9L) / 10L);
-
+
   temp = EncoderFR::getPosition() - 200;
   if (temp < 0)
   {
     temp += 400;
   }
   currentWheelStatus[FRONT_RIGHT_DRIVE_MOTOR_ID].orientation = (int)((temp * 9L) / 10L);
-
+
   temp = EncoderMR::getPosition() - 200;
   if (temp < 0)
   {
     temp += 400;
   }
   currentWheelStatus[MIDDLE_RIGHT_DRIVE_MOTOR_ID].orientation = (int)((temp * 9L) / 10L);
-
+
   temp = EncoderRR::getPosition() - 200;
   if (temp < 0)
   {
@@ -302,7 +331,7 @@
 }

 void setup(){
-
+
   // Communicate with the computer
   EncoderFL::setupEncoderFL();
   EncoderML::setupEncoderML();
@@ -310,13 +339,13 @@
   EncoderFR::setupEncoderFR();
   EncoderMR::setupEncoderMR();
   EncoderRR::setupEncoderRR();
-
+
   sabertoothDriverNode.initNode();
   sabertoothDriverNode.subscribe(mcSUB);
   sabertoothDriverNode.advertise(pubResults);
   // Communicate with the Sabertooth
   Serial3.begin(9600);
-
+
   // Initialize current wheel status: Assume we're in "closed" position
   currentWheelStatus[0].orientation = 0.0;     //.fl_articulation_angle = 0.0;
   currentWheelStatus[1].orientation = 180.0;   //.fr_articulation_angle = 180.0;
@@ -340,7 +369,8 @@
   updateArticulationValues();
   continueDriving();
   // TODO: Delete this?
-   msg.data = (long)currentWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].orientation;
- pubResults.publish(&msg);
-
-}
+//  msg.data = (long)currentWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].orientation;
+//  pubResults.publish(&msg);
+
+}
+


Adjust temperature print-out.

Adjust temperature print-out.

--- libraries/DS3231/examples/CosaDS3231/CosaDS3231.ino
+++ libraries/DS3231/examples/CosaDS3231/CosaDS3231.ino
@@ -62,6 +62,8 @@
   // Start trace output stream on the serial port
   uart.begin(9600);
   trace.begin(&uart, PSTR("CosaDS3231: started"));
+  trace.precision(2);
+  trace.width(4);

   // Check amount of free memory
   TRACE(free_memory());
@@ -90,23 +92,32 @@

   // Set square-wave output
   TRACE(rtc.square_wave(true));
+  trace.flush();
 }

 void loop()
 {
   // Wait for rising clock signal
+  uart.powerdown();
+  uint8_t mode = Power::set(SLEEP_MODE_PWR_DOWN);
   while (clkPin.is_clear()) yield();
+  Power::set(mode);
+  uart.powerup();
   ledPin.toggle();

   // Read the time from the rtc device and print
   time_t now;
   ASSERT(rtc.get_time(now));
   now.to_binary();
-  trace << now << ' ';
-  int16_t temp = rtc.get_temperature();
-  trace << (temp >> 2) << '.' << (25 * (temp & 0x3)) << PSTR(" C") << endl;
+  float temp = rtc.get_temperature() * 0.25;
+  trace << now << ' ' << temp << PSTR(" C") << endl;

   // Wait for falling clock signal
   ledPin.toggle();
+  trace.flush();
+  uart.powerdown();
+  mode = Power::set(SLEEP_MODE_PWR_DOWN);
   while (clkPin.is_set()) yield();
+  Power::set(mode);
+  uart.powerup();
 }


Arduino Secure: added configuration management into sketch

--- reference-realtime/arduino-secure/sketch/MQTTClient_sec/MQTTClient_sec.ino
+++ reference-realtime/arduino-secure/sketch/MQTTClient_sec/MQTTClient_sec.ino
@@ -48,6 +48,9 @@
 #include <aJSON.h>
 #include <sdppublishmsg.h>

+#include <stringparser.h>
+#include <csvline.h>
+
 #include <avr/pgmspace.h>

@@ -60,6 +63,8 @@
 #ifdef DEBUG_MEMORY
 #include <MemoryFree.h>
 #endif
+
+#define CFG_FILENAME "config.csv"

 /******************************************************************************************
@@ -85,6 +90,7 @@
  *                     to use standard SDP JSON.
  *                      to use standard SDP JSON.
  * CONFIGURATION      : change configuration runtime receiving the new one from the broker
+ *                      MQTT (work in progress)
  ******************************************************************************************/
 //! Global macro value to define if network connection is cable or Wi-Fi
 #define WIFI 1
@@ -420,7 +426,6 @@
 #ifdef WIFI

 //! Wireless network SSID (name)
-//! Wireless network SSID (name)
 const char w_ssid[] PROGMEM = WIRELESS_SSID;

 //! Wireless network password
@@ -557,6 +562,12 @@
 //! Read sensor period
 Interval tReadTime; //(READ_SENSOR_PERIOD + 1);

+// Read interval (in ms)
+unsigned long tRead = 0;
+
+// NTP update  interval (in ms)
+unsigned long tNtpUpdate = 0;
+

 /*------------------------------------------------------------------------------------
 /* FUNCTION PROTOTYPEs
@@ -686,8 +697,41 @@
  *
  * \param[in] board type of board (Mega, Uno, ...)
  * \param[in] shield type of shield (Ethernet, Wifi,...)
+ *
+ * \return true: opened, false: error while opening SD
  */
 bool openSD(uint8_t board, uint8_t shield);
+
+/**
+ * checkNewConfig
+ * Checks if there isa new node configuration (received from the broker MQTT).
+ *
+ * \return true: it is received a new configuration, false: no new configuration
+ */
+bool checkNewConfig();
+
+/**
+ * updateConfig
+ * Loads the new configuration and save it on SD card.
+ *
+ * \return true: if no errors, false: othewise
+ */
+bool updateConfig();
+
+/**
+ * updateConfig
+ * Loads the new configuration and save it on SD card.
+ *
+ * \return true: if no errors, false: othewise
+ */
+bool updateConfig();
+
+/**
+ * loadConfig
+ * Loads configuration from SD card, if #CFG_FILENAME file is not present, it will be use the default values.
+ *
+ */
+void loadConfig();

@@ -712,6 +756,15 @@
   {
     Serial.println( F(" done.") );
   }
+
+#ifdef CONFIGURATION
+  Serial.println( );
+  Serial.println( F("Load Configuration...") );
+  loadConfig();
+#else
+  tRead = READ_SENSOR_PERIOD;
+  tNtpUpdate = UPDATE_TIME_PERIOD;
+#endif

   Serial.println( );
   Serial.println( F("Configure smart object...") );
@@ -883,16 +936,23 @@
     case IDLE :
     {
       // Do nothing and check the following state
-      if (tReadTime.residualTime(READ_SENSOR_PERIOD) == 0)
+      if (tReadTime.residualTime(tRead /*READ_SENSOR_PERIOD*/) == 0)
       {
         state = READ_SENSORS;
       }
-      else if (tNtpUpdateTime.residualTime(UPDATE_TIME_PERIOD) == 0)
+      else if (tNtpUpdateTime.residualTime(tNtpUpdate/*UPDATE_TIME_PERIOD*/) == 0)
       {
         state = NTPUPDATE;
       }
       MTTQClient.loop();
-
+#ifdef CONFIGURATION
+      if ( checkNewConfig() )
+      {
+        updateConfig();
+        loadConfig();
+      }
+#endif
+
     } break;

     default :
@@ -1052,13 +1112,13 @@
   Serial.println(F("Network configuration: "));
 #ifdef STATIC_NETWORK_CFG
   Serial.print( F("\tIP Address: ") );
-  Serial.println(IPAddress(ip));
+  Serial.println(IPAddress( netConfig.ip() ));
   Serial.print( F("\tNetmask   : ") );
-  Serial.println(IPAddress(subnet));
+  Serial.println(IPAddress( netConfig.netmask() ));
   Serial.print( F("\tGateway   : ") );
-  Serial.println(IPAddress(gateway));
+  Serial.println(IPAddress( netConfig.gateway() ));
   Serial.print( F("\tDNS       : ") );
-  Serial.println(IPAddress(mydns));
+  Serial.println(IPAddress( netConfig.dns() ));
 #else
   Serial.print( F("\tIP Address: ") );

@@ -1226,3 +1286,141 @@
   return true;
 }

+#ifdef CONFIGURATION
+bool checkNewConfig()
+{
+  return (sdp::client::SDPSource::getConfiguration() != 0);
+}
+
+bool updateConfig()
+{
+  if ( checkNewConfig() )
+  {
+    Serial.println( F("New configuration") );
+
+    // Save new configuration
+//    Serial.println( F("Save on SD") );
+    if (SD.exists(CFG_FILENAME))
+    {
+      // Delete old configuration
+      SD.remove(CFG_FILENAME);
+    }
+
+    File myFile = SD.open(CFG_FILENAME, FILE_WRITE);
+    // if the file opened okay, write to it:
+    if (myFile)
+    {
+      for (size_t i = 0; i < sdp::client::SDPSource::getConfiguration()->NF(); i++)
+      {
+        myFile.print(sdp::client::SDPSource::getConfiguration()->getItem(i));
+        myFile.print(";");
+      }
+      // close the file:
+      myFile.close();
+//      Serial.println();
+    }
+    else
+    {
+      // if the file didn't open, print an error:
+      Serial.println( F("Error opening") );
+    }
+    sdp::client::SDPSource::deleteConfiguration();
+  }
+
+  return true;
+}
+
+
+
+#define RBUF_SIZE 128
+const uint8_t cfgNF = 2;
+
+void loadConfig()
+{
+  if (SD.exists(CFG_FILENAME))
+  {
+//    Serial.println( F("Load from SD") );
+
+    File myFile = SD.open(CFG_FILENAME, FILE_READ);
+    // if the file opened okay, write to it:
+    if (myFile)
+    {
+      char rBuffer[RBUF_SIZE] = {0};
+      size_t i = 0;
+      bool endline = false;
+      while ( myFile.available() && ! endline)
+      {
+        rBuffer[i] = myFile.read();
+        if ( rBuffer[i] =='\n' || i == RBUF_SIZE )
+        {
+          endline = true;
+        }
+        i++;
+      }
+      myFile.close();
+
+      sdp::message::CSVLine conf;
+      conf.set(rBuffer, RBUF_SIZE);
+
+
+      //check number of fields
+      if ( conf.NF() == cfgNF)
+      {
+        for (i = 0; i < cfgNF; i++)
+        {
+          switch (i)
+          {
+            case 0 : {
+              int n = 0;
+
+              if ( conf.getItemAsInt(i, n) )
+              {
+                tRead = ( (unsigned long) n) * 1000;
+              }
+              else
+              {
+                tRead = READ_SENSOR_PERIOD;
+              }
+
+              Serial.print( F("\ttRead: ") );
+              Serial.println(tRead);
+
+            } break;
+
+            case 1 : {
+              int n = 0;
+
+              if ( conf.getItemAsInt(i, n) )
+              {
+                tNtpUpdate = ( (unsigned long) n) * 1000;
+              }
+              else
+              {
+                tNtpUpdate = UPDATE_TIME_PERIOD;
+              }
+
+              Serial.print( F("\ttNtpUpdate: ") );
+              Serial.println(tNtpUpdate);
+            } break;
+            default : {} break;
+
+          }
+        }
+
+        return ;
+      }
+      else
+      {
+        Serial.println( F("Invalid config file!") );
+      }
+      // close the file:
+    }
+    // if the file didn't open, print an error:
+      Serial.println( F("error opening") );
+  }
+  else
+  {
+    Serial.println( F("Default values") );
+  }
+}
+#endif


Refactoring

Refactoring

--- arduino/rcController/rcController.ino
+++ arduino/rcController/rcController.ino
@@ -16,7 +16,6 @@

 int side = SIDE_RIGHT;
 int angle = 0;
-
 int servoFix = 50;

 const int DIRECTION_FORWARD = 1;
@@ -25,9 +24,7 @@
 int direction = DIRECTION_FORWARD;
 int speed = 0;

-int enginePwm = 0;
-int servoPwm = 90;
-const int MIN_ENGINE_PWM = 0;
+const int MIN_ENGINE_SPEED = 80;

 // cmd:
 // ^ [1|2] [0-100] | [1|2] [0-100] [0-100]$
@@ -39,15 +36,16 @@
 void setup() {
   pinMode(engineForwardPin, OUTPUT);
   pinMode(engineBackwardPin, OUTPUT);
+  pinMode(enginePowerPin, OUTPUT);
+  pinMode(servoPin, OUTPUT);

   Serial.begin(9600);
   bluetooth.begin(9600);
   servo.attach(servoPin);

-  digitalWrite(engineForwardPin, HIGH);
-  digitalWrite(engineBackwardPin, LOW);
-  analogWrite(servoPin, getServoPwm(side, angle, servoFix));
-  analogWrite(enginePowerPin, getEnginePwm(direction, speed));
+  setServo(side, angle);
+  setDirectionPins(direction);
+  setEnginePower(direction, speed);
 }

 void loop() {
@@ -86,47 +84,55 @@
   Serial.print(servoFix);
   Serial.println(END_CMD_CHAR);

-  // Handle servo data
-  int newServoPwm = getServoPwm(newSide, newAngle, servoFix);
-  if (servoPwm != newServoPwm) {
-    servoPwm = newServoPwm;
-    servo.write(servoPwm);
+  // Side or angle has changed
+  if (side != newSide || angle != newAngle) {
+    setServo(newSide, newAngle);
+
+    side = newSide;
+    angle = newAngle;
     Serial.println("Servo moved");
   }
-
-  // Handle engine data
+
+   // Direction has changed
   if (direction != newDirection) {
-    // slow down
-    for (int i = speed ; i >= MIN_ENGINE_PWM ; i--) {
+    // Slow down
+    for (int speedIterator = speed ; speedIterator >= MIN_ENGINE_SPEED ; setEnginePower(direction, --speedIterator)) {
       delay(10);
-      enginePwm = getEnginePwm(direction, i);
-      analogWrite(enginePowerPin, enginePwm);
     }

-    // set direction
-    digitalWrite(engineForwardPin, newDirection == DIRECTION_FORWARD ? HIGH : LOW);
-    digitalWrite(engineBackwardPin, newDirection == DIRECTION_BACKWARD ? HIGH : LOW);
+    // Change direction
+    setDirectionPins(newDirection);
+
+    // Speed up
+    for (int speedIterator = MIN_ENGINE_SPEED ; speedIterator <= newSpeed ; setEnginePower(newDirection, speedIterator++)) {
+      delay(10);
+    }
+
+    speed = newSpeed;
     direction = newDirection;
-
-    // speed up
-    for (int i = MIN_ENGINE_PWM ; i <= newSpeed ; i++) {
-      delay(10);
-      enginePwm = getEnginePwm(newDirection, i);
-      analogWrite(enginePowerPin, enginePwm);
-    }
+    Serial.println("Direction changed");
+
+  // Only speed has changed
+  } else if (speed != newSpeed) {
+    setEnginePower(direction, newSpeed);
+
     speed = newSpeed;
-
-    Serial.println("Direction changed");
+    Serial.print("Speed changed");
   }
+}

-  // Changed speed only
-  if (speed != newSpeed) {
-    speed = newSpeed;
-    enginePwm = getEnginePwm(direction, speed);
-    analogWrite(enginePowerPin, enginePwm);
-    Serial.print("Speed changed: ");
-    Serial.println(enginePwm);
-  }
+void setServo(int side, int angle) {
+  int servoPwm = getServoPwm(side, angle, servoFix);
+  servo.write(servoPwm);
+}
+
+void setDirectionPins(int direction) {
+    digitalWrite(engineForwardPin, direction == DIRECTION_FORWARD ? HIGH : LOW);
+    digitalWrite(engineBackwardPin, direction == DIRECTION_BACKWARD ? HIGH : LOW);
+}
+
+void setEnginePower(int direction, int speed) {
+    analogWrite(enginePowerPin, getEnginePwm(speed >= MIN_ENGINE_SPEED ? speed : 0));
 }

 // Returns [0 - 180]
@@ -146,7 +152,7 @@
 }

 // Returns [0 - 255]
-int getEnginePwm(int direction, int speed) {
+int getEnginePwm(int speed) {
   return speed * 2.55;
 }