Changes for readability

Changes for readability

Recommitted changes from 1 month ago

--- OxFloodNet_Sensor/OxFloodNet_Sensor.ino
+++ OxFloodNet_Sensor/OxFloodNet_Sensor.ino
@@ -19,7 +19,7 @@
  * becomes value set on jumpers (5, 10 or 15 mins)
  *
  * NOTE: For initial testing, wakeup time set to 5mins and battery interval to 4 cycles
- * (c) Andrew D Lindsay 2014
+ * (c) 2014 Andrew D Lindsay & Ben Ward
  */

 #include "LLAPSerial.h"	// include the library
@@ -29,7 +29,7 @@
 // Used in START msg to indicate firmware version, 314 = 3.1.4
 #define VERSION_ID 314

-// Hardware pin defines
+// Set RFu hardware pins (not board jumpers)
 // Enable SRF
 #define SRF_RADIO_ENABLE 8
 // Enable the sensor, controlled by FET
@@ -41,7 +41,7 @@
 // Using Sleep Mode 3, SLEEP must be LOW to run, uses interrupt to wakeup
 #define SRF_SLEEP 4
 #define WAKE_INT 2
-// OneWire bus pin for temperature sensor pin
+// Temperature sensor data line connects to pin 5 on the Arduino
 #define ONE_WIRE_BUS 5

 // Software configuration defines
@@ -114,21 +114,43 @@
     digitalWrite( jumperPins[n], HIGH);
   }

-  // Read input and parse value
+  // Set individual registers
+  // TODO: Explain how these relate to the board
   // TODO: These are upside down for the board layout.
   int digit2 = ((PINB & 0x30) >> 4) | ((PINC & 0x03) << 2);
   digit2 ^= 0x0f;
   int digit1 = (PINC & 0x3c) >> 2;
   digit1 ^= 0x0f;
+
+  // Set Node ID from jumper pins
   // Only use digits 0 - 9,
   nodeId[0] = '0' + min(digit1,9);
   nodeId[1] = '0' + min(digit2,9);
+
+  // Set polling interval from jumper pins
   pollingInterval = ((PINB & 0x06) >> 1) ^ 0x03;

   // Reset inputs to set internal pullup off
   for( int n = 0; n < 10; n++ ) {
     digitalWrite( jumperPins[n], LOW);
   }
+
+  // DEBUG to serial port on startup
+  // Print the values of Port B & Port C
+  Serial.println("Debug: ");
+  Serial.print("Port B: ");
+  Serial.println(PINB,HEX);
+  Serial.print("Port C: ");
+  Serial.println(PINC,HEX);
+
+  Serial.print("Polling Interval: ");
+  Serial.println(pollingInterval,DEC);
+
+  Serial.print("Node ID Digits: ");
+  Serial.print(digit1,DEC);
+  Serial.print(" ");
+  Serial.println(digit2,DEC);
+
 }

 // **************************************
@@ -178,13 +200,16 @@
   }
 }

-// Get the range in cm. Need to enable sensor first then wait briefly for it to power up
-// Also request temperture sensor, if previously detected, to take a reading.
-// Disable sensor after use.
-// Returns compensated, uncompensated and temperature values as reference params
-// boolean true returned form function for valid reading. false for <23cm or out of range
-// Calling function can still do checks to determine whether to use reading or not.
+// Start of Ultrasonic sensor code
 boolean getRange( int *outRawDistance, int *outDistance, float *outTemperature ) {
+
+  // Get the range in cm. Need to enable sensor first then wait briefly for it to power up
+  // Also request temperture sensor, if previously detected, to take a reading.
+  // Disable sensor after use.
+  // Returns compensated, uncompensated and temperature values as reference params
+  // boolean true returned form function for valid reading. false for <23cm or out of range
+  // Calling function can still do checks to determine whether to use reading or not.
+
   int16_t pulse;  // number of pulses from sensor
   int i=0;
   // These values are for calculating a mathematical median for a number of samples as
@@ -229,9 +254,8 @@

   return true;
 }
-
-// End of Maxbotix sensor code
-// **************************************
+// End of ultrasonic sensor code
+

 // Battery monitoring
 int readVcc() {
@@ -259,15 +283,16 @@
   result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
   return (int)result; // Vcc in millivolts
 }
-
+// end of battery monitoring code
+
+// Start of SRF Sleep Code
+uint8_t setSRFSleep( int inPolling ) {
+
 /*
  Set the sleep mode on the SRF, this requires AT commands to set sleep interval
  This is not written to permanent store as this resets back to no sleep on power cycle.
  */
-
-// TODO need to be able to set sleep based on current startup sequence and polling interval
-uint8_t setSRFSleep( int inPolling )
-{
+
   //  int selectedPollingInterval = TENMINS;    // Set a default
   if (!enterCommandMode())	// if failed once then try again
   {
@@ -283,8 +308,9 @@
   if (!sendCommand("ATDN")) return 4;
   return 5; // success
 }
-
-
+// end of SRF sleep code
+
+// Start of SRF command functions
 uint8_t enterCommandMode()
 {
   delay(1200);
@@ -317,19 +343,20 @@
   }
   return 0;
 }
-
+// End of SRF command functions

 void setup() {
-  // initialise serial:
+  // initialise serial interface for debugging/SRF communication:
   Serial.begin(115200);
+
   // Get device ID
   readJumpers();

   // Initialise the LLAPSerial library
   LLAP.init( nodeId );
+
+  // Set unused digital pins to input and turn on pull-up resistor
   analogReference(DEFAULT);
-
-  // Set unused digital pins to input and turn on pull-up resistor
   for(int i = 0; i< PIN_COUNT; i++ ) {
     pinMode(inPin[i], INPUT);
     digitalWrite(inPin[i], HIGH);
@@ -341,24 +368,28 @@
   pinMode(SENSOR_PIN, INPUT);

   // Setup the SRF pins
-  pinMode(SRF_RADIO_ENABLE, OUTPUT);    // initialize pin 8 to control the radio
+  pinMode(SRF_RADIO_ENABLE, OUTPUT);    // initialize pin to control the radio
   digitalWrite(SRF_RADIO_ENABLE, HIGH); // select the radio
   pinMode(SRF_SLEEP, OUTPUT);
   digitalWrite( SRF_SLEEP, LOW );

+  // start OneWire sensors
   sensors.begin();
-  tempSensorFound = false;
+  tempSensorFound = false; //clear flag for sensor discovery
+  // Discover OneWire temperature sensor
   if (sensors.getAddress(temperatureSensor, 0)) {
-    // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
+    // If we find a sensor set the resolution to 9 bit
+    // (Each Dallas/Maxim device is capable of several different resolutions)
     sensors.setResolution(temperatureSensor, 9);
-    tempSensorFound = true;
-  }
-
+    tempSensorFound = true; // set discovery flag
+  }
+
+  // Initialise countdown number of sleeps before sending battery reading
   batteryCountDown = BATTERY_READ_INTERVAL;
   // Wait for it to be initialised
   delay(200);

-  // Send START message if successful or ERROR if not able to set SleepMode 3.
+  // Send "START" message if successful or "ERR" if not able to set SleepMode 3.
   // set up sleep mode 3 (low = awake)
   uint8_t val;
   while ((val = setSRFSleep(TWENTYSEC)) != 5) {
@@ -366,7 +397,7 @@
     delay(5000);	// try again in 5 seconds
   }

-  // Send STARTED message upto 5 times if no ACK received.
+  // Send START message + Version ID 5 times
   for(int i = 0; i<5; i++) {
     LLAP.sendInt("START", VERSION_ID);
     // TODO: Wait 100mS for ACK, if received continue, otherwise send next STARTED


deleting bad file

deleting bad file

--- MainBrain/lib/Watchdog/examples/BasicUsage/BasicUsage.ino
+++ MainBrain/lib/Watchdog/examples/BasicUsage/BasicUsage.ino
@@ -1,62 +0,0 @@
-// // Adafruit Watchdog Library Basic Usage Example
-// //
-// // Simple example of how to use the watchdog library.
-// //
-// // Author: Tony DiCola
-
-// #include <Adafruit_SleepyDog.h>
-
-// void setup() {
-//   Serial.begin(115200);
-//   while (!Serial) ; // wait for Arduino Serial Monitor (native USB boards)
-//   Serial.println("Adafruit Watchdog Library Demo!");
-//   Serial.println();
-
-//   // First a normal example of using the watchdog timer.
-//   // Enable the watchdog by calling Watchdog.enable() as below.  This will turn
-//   // on the watchdog timer with a ~4 second timeout before reseting the Arduino.
-//   // The estimated actual milliseconds before reset (in milliseconds) is returned.
-//   // Make sure to reset the watchdog before the countdown expires or the Arduino
-//   // will reset!
-//   int countdownMS = Watchdog.enable(4000);
-//   Serial.print("Enabled the watchdog with max countdown of ");
-//   Serial.print(countdownMS, DEC);
-//   Serial.println(" milliseconds!");
-//   Serial.println();
-
-//   // Now loop a few times and periodically reset the watchdog.
-//   Serial.println("Looping ten times while resetting the watchdog...");
-//   for (int i = 1; i <= 10; ++i) {
-//     Serial.print("Loop #"); Serial.println(i, DEC);
-//     delay(1000);
-//     // Reset the watchdog with every loop to make sure the sketch keeps running.
-//     // If you comment out this call watch what happens after about 4 iterations!
-//     Watchdog.reset();
-//   }
-//   Serial.println();
-
-//   // Disable the watchdog entirely by calling Watchdog.disable();
-//   Watchdog.disable();
-
-//   // Finally demonstrate the watchdog resetting by enabling it for a shorter
-//   // period of time and waiting a long time without a reset.  Notice you can pass
-//   // a _maximum_ countdown time (in milliseconds) to the enable call.  The library
-//   // will try to use that value as the countdown, but it might pick a smaller
-//   // value if the hardware doesn't support it.  The actual countdown value will
-//   // be returned so you can see what it is.
-//   countdownMS = Watchdog.enable(4000);
-//   Serial.print("Get ready, the watchdog will reset in ");
-//   Serial.print(countdownMS, DEC);
-//   Serial.println(" milliseconds!");
-//   Serial.println();
-//   delay(countdownMS+1000);
-
-//   // Execution will never get here because the watchdog resets the Arduino!
-// }
-
-// void loop() {
-//   // We'll never actually get to the loop because the watchdog will reset in
-//   // the setup function.
-//   Serial.println("You shouldn't see this message.");
-//   delay(1000);
-// }


First working release

First working release

a very basic demo with 64 leds and 24 switches

--- examples/basic/basic.ino
+++ examples/basic/basic.ino
@@ -8,45 +8,28 @@
 volatile byte pButton = 0;
 volatile byte pOldButton = 255;

-/* -----------------------SETUP ------------------------*/
 void setup() {
   Serial.begin(38400);
-  //optional:brightness(0:7),displayOn(0=off,1=on)
+  //optional:brightness(0:7))
   tm.begin();
-  //column,row,state(0,1)
-  tm.setLed(0,1,1);
 }

-/* ---------------------- LOOP -------------------------*/
 void loop() {
   randomLed2();
-  if (buttonFired()){
-    Serial.println("Click!");
-  }
-}
-
-
-boolean buttonFired(){
-  uint16_t but = tm.getButtons();
-  if (but != 0) {
-    pButton = tm.decodeButton(but);
-    if (pButton != 0){
-      if (pOldButton != pButton){
-        pOldButton = pButton;
-        Serial.println(pButton,DEC);
-        return true;
+  uint16_t pButton = tm.getButtons(true);
+  if (pButton != 0) {
+    if (pOldButton != pButton){
+      pOldButton = pButton;
+      if (tm.getLed(pButton-1) == 0){
+        tm.setLed(pButton-1,1,true);
+      }
+      else {
+        tm.setLed(pButton-1,0,true);
       }
-    }
-    else {
-      return false;
+      Serial.println(pButton,DEC);
     }
   }
-  else {
-    return false;
-  }
 }
-
-

 //this use column,row led addressing
 void randomLed1(){
@@ -59,7 +42,7 @@
   else {
     val = 1;
   }
-  tm.setLed(col,row,val);
+  tm.setLed(col,row,val,true);
   delay(5);
 }

@@ -70,7 +53,7 @@
  so led 0 to 7 will be in the column 0 and so on.
  */
 void randomLed2(){
-  byte led = random(0,63);
+  byte led = random(24,63);
   byte val = 0;
   if (tm.getLed(led) == 1){
     val = 0;
@@ -78,7 +61,7 @@
   else {
     val = 1;
   }
-  tm.setLed(led,val);
+  tm.setLed(led,val,true);
   delay(5);
 }


Update pll_programmer.ino

Update pll_programmer.ino


Explicitly switch to station mode, fixes #6

--- client_arduino/prikmeter.ino
+++ client_arduino/prikmeter.ino
@@ -213,6 +213,7 @@
   p1.begin(115200);

   Serial.print("Connecting to wifi [");
+  WiFi.mode(WIFI_STA);
   WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
   while (WiFi.status() != WL_CONNECTED) {
     setLed(true);


Don't fade to CHANGE_MIN_VAL if we're only changing the pulse speed

--- arduino/blinkytape_orb.ino
+++ arduino/blinkytape_orb.ino
@@ -119,7 +119,7 @@

     return;
   }
-
+
   int incr;
   long delay_ms;
   long change_delay_ms;
@@ -200,11 +200,14 @@
   }

   if (next != current) {
-    fade(CHANGE_MIN_VAL, CHANGE_DURATION / 2);
-
-    current = next;
-
-    fade(PULSE_MIN_VAL, CHANGE_DURATION / 2);
+    if (next.hue_initialized != current.hue_initialized || next.hue != current.hue) {
+      // if hue is changing, fade to a lower brightness before changing to make the change less jarring
+      fade(CHANGE_MIN_VAL, CHANGE_DURATION / 2);
+      current = next;
+      fade(PULSE_MIN_VAL, CHANGE_DURATION / 2);
+    } else {
+      current = next;
+    }
   }

   fade(PULSE_MAX_VAL, current.pulse_duration / 2);


cosmetic changes

cosmetic changes

--- minimalistthermostat.ino
+++ minimalistthermostat.ino
@@ -96,10 +96,10 @@
            * fixed an issue with targetTempString, when rebooting the photon would not show the
              temperature loaded from the eeprom
  * changes in version 0.23:
-              * Swapped pushbullet notifications with google sheets on thermostat activity
+           * Swapped pushbullet notifications with google sheets on thermostat activity
                  source: https://www.hackster.io/gusgonnet/pushing-data-to-google-docs-02f9c4
  * changes in version 0.24:
-              * Reverting to Heating/Cooling from Winter/Summer modes
+           * Reverting to Heating/Cooling from Winter/Summer modes

 TODO:
   * add multi thread support for photon: SYSTEM_THREAD(ENABLED);


Swap B and D in normal mode for consistency

In video playback mode, D meant 1 minute skip.  In normal mode, B meant
one minute skip.  Use D for 1 minute skip in both by swapping B to skip
to next video in normal mode.

--- Arduino/LightPlayer/LightPlayer.ino
+++ Arduino/LightPlayer/LightPlayer.ino
@@ -386,6 +386,10 @@
         } break;

         case Pressed::b: {
+          GlobalPendingOperations.next_video = 1;
+        } break;
+
+        case Pressed::d: {
           GlobalPendingOperations.skip_forward = 1;
         } break;

@@ -411,10 +415,6 @@

         case Pressed::bc: {
           CurrentMode = Mode::MISC;
-        } break;
-
-        case Pressed::d: {
-          GlobalPendingOperations.next_video = 1;
         } break;
       }
     } break;


Refactor the ring handler.

Refactor the ring handler.

--- gsm_tracker/gsm_tracker.ino
+++ gsm_tracker/gsm_tracker.ino
@@ -46,7 +46,7 @@
 }

-void setup() {
+void setup () {
   pinMode(BUZZER_PIN, OUTPUT);
   digitalWrite(BUZZER_PIN, HIGH);
   delay(500);
@@ -107,7 +107,7 @@
 }

-void loop() {
+void loop () {
   if (ringing && digitalRead(FONA_PS) == HIGH) handleRing();

   if (gps.newNMEAreceived() && gps.parse(gps.lastNMEA())) {
@@ -209,85 +209,78 @@

 void handleRing () {
-  char sms_buffer[140];
-  uint16_t smslen;
-
   Serial.println(F("Ring ring, Neo."));

   fonaSerial.listen();
-
   int8_t sms_num = fona.getNumSMS();

-  if (sms_num == -1) {
-    // This is an error case
-    ringing = true;
+  if (sms_num > -1) {
+    Serial.print(sms_num); Serial.println(" messages waiting.");
+
+    char sms_buffer[9];
+    uint16_t smslen;
+
+    // Read any SMS message we may have...
+    for (int8_t sms_index = 1; sms_index <= sms_num; sms_index++) {
+      Serial.print(F("  SMS #")); Serial.print(sms_index); Serial.print(F(": "));
+
+      if (fona.readSMS(sms_index, sms_buffer, 8, &smslen)) {
+        // if the length is zero, its a special case where the index number is higher
+        // so increase the max we'll look at!
+        if (smslen == 0) {
+          Serial.println(F("[empty slot]"));
+          sms_num++;
+          continue;
+        }
+
+        Serial.println(sms_buffer);
+
+        // If it matches our pre-defined command string...
+        if (strcmp(sms_buffer, "Location") == 0) {
+          Serial.println(F("  Responding with location... "));
+
+          char sms_response[52];
+
+          if (current_location.isValid) {
+            sprintf (sms_response, "https://maps.google.com?q=%s,%s", current_location.latitude_c, current_location.longitude_c);
+          } else {
+            sprintf (sms_response, "I'm lost!");
+          }
+
+          // reply...
+          if (fona.sendSMS(MY_PHONE_NUMBER, sms_response)) {
+            Serial.println(F("reply sent!"));
+          } else {
+            Serial.println(F("reply failed"));
+          }
+
+          // delete this SMS
+          fona.deleteSMS(sms_index);
+        } else if (strcmp(sms_buffer, "Status") == 0) {
+          Serial.println(F("  Responding with status... "));
+
+          char sms_response[8];
+          uint8_t rssi = fona.getRSSI();
+          sprintf (sms_response, "%d bars.", barsFromRSSI(rssi));
+
+          // reply...
+          if (fona.sendSMS(MY_PHONE_NUMBER, sms_response)) {
+            Serial.println(F("reply sent!"));
+          } else {
+            Serial.println(F("reply failed"));
+          }
+
+          // delete this SMS
+          fona.deleteSMS(sms_index);
+        }
+      } else {
+        Serial.println(F("Failed to read SMS messages!"));
+      }
+    }
+
     gpsSerial.listen();
-    return;
-  }
-
-  Serial.print(sms_num); Serial.println(" messages waiting.");
-
-  // Read any SMS message we may have...
-  for (int8_t sms_index = 1; sms_index <= sms_num; sms_index++) {
-    Serial.print(F("  SMS #")); Serial.print(sms_index); Serial.print(F(": "));
-
-    if (fona.readSMS(sms_index, sms_buffer, 140, &smslen)) {
-      // if the length is zero, its a special case where the index number is higher
-      // so increase the max we'll look at!
-      if (smslen == 0) {
-        Serial.println(F("[empty slot]"));
-        sms_num++;
-        continue;
-      }
-
-      Serial.println(sms_buffer);
-
-      // If it matches our pre-defined command string...
-      if (strcmp(sms_buffer, "Location") == 0) {
-        Serial.println(F("  Responding with location... "));
-
-        char sms_response[52];
-
-        if (current_location.isValid) {
-          sprintf (sms_response, "https://maps.google.com?q=%s,%s", current_location.latitude_c, current_location.longitude_c);
-        } else {
-          sprintf (sms_response, "I'm lost!");
-        }
-
-        // reply...
-        if (fona.sendSMS(MY_PHONE_NUMBER, sms_response)) {
-          Serial.println(F("reply sent!"));
-        } else {
-          Serial.println(F("reply failed"));
-        }
-
-        // delete this SMS
-        fona.deleteSMS(sms_index);
-      } else if (strcmp(sms_buffer, "Status") == 0) {
-        Serial.println(F("  Responding with status... "));
-
-        char sms_response[8];
-        uint8_t rssi = fona.getRSSI();
-        sprintf (sms_response, "%d bars.", barsFromRSSI(rssi));
-
-        // reply...
-        if (fona.sendSMS(MY_PHONE_NUMBER, sms_response)) {
-          Serial.println(F("reply sent!"));
-        } else {
-          Serial.println(F("reply failed"));
-        }
-
-        // delete this SMS
-        fona.deleteSMS(sms_index);
-      }
-    } else {
-      Serial.println(F("Failed to read SMS messages!"));
-    }
-  }
-
-  gpsSerial.listen();
-
-  ringing = false;
+    ringing = false;
+  }
 }


Add ip display

Add ip display

--- bullpen_sketch/bullpen_sketch.ino
+++ bullpen_sketch/bullpen_sketch.ino
@@ -55,6 +55,15 @@
  }
 }

+//display local ip
+void printIP() {
+  IPAddress ip = WiFi.localIP();
+  char local_ip[16];
+  sprintf(local_ip,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
+  local_ip[15]= '\0';
+  Serial.println(local_ip);
+}
+
 void setup() {
   // put your setup code here, to run once:

@@ -66,7 +75,7 @@
   p.push_back(Person("Ming"));

   check_wifi();
-
+  printIP();
   s = new State(p);
   c = new Controller(pinButton, pinEncoder, p.size());
   v = new View(port);


Calibration Routines added

Calibration Routines added

--- Elcano_C2_In_Out/Elcano_C2_In_Out.ino
+++ Elcano_C2_In_Out/Elcano_C2_In_Out.ino
@@ -1,7 +1,7 @@
+
+
 /*
-Elcano Contol Module C2: Instrument panel controls and LEDs.
-This routine handles simple drive-by-wire, as well as handing control over to the
-computer based on the state of the enable switches.
+Elcano Contol Module C2: Tests for steering and brake servos
 */

@@ -14,7 +14,7 @@
 #endif

 #ifdef MEGA
-#include <IO_Mega.h>
+#include <IO_PCB.h>
 #else
 #include <IO_2009.h>
 #endif
@@ -38,13 +38,15 @@
 const int Off = 0;
 const int FullThrottle =  179;   // 3.5 V
 const int MinimumThrottle = 39;  // Throttle has no effect until 0.75 V
-const int FullBrake = 255;
-const int MinimumBrake = 127;
-const int HardLeft = 127;
+
+const int FullBrake = 225;  // start with a conservative value; could go as high as 255;
+const int MinimumBrake = 155; // start with a conservative value; could go as low as 127;
+
+const int HardLeft = 159; // start with a conservative value; could go as low as 127;
 const int HalfLeft = 159;
 const int Straight = 191;
 const int HalfRight = 223;
-const int HardRight = 255;
+const int HardRight = 223; // start with a conservative value; could go as high as  255;
 /*  Elcano Servo range is 50 mm for brake, 100 mm for steering.

     Elcano servo has a hardware controller that moves to a
@@ -64,6 +66,7 @@
     White: 0V
     Yellow: 5V
     Blue: 0-5V depending on position of servo.
+    The Blue wire is
     Black: 12V while servo extends; 0V at rest or retracting.
     Red:   12V while retracting; 0V at rest or extending.
     The reading on the Blue line has hysteresis when Elcano sends a PWM signal;
@@ -146,12 +149,12 @@
         pinMode(CruiseReverse, INPUT);
         pinMode(StopButton, INPUT);  // via interrupt
         pinMode(CruiseButton, INPUT); // via interrupt
-        pinMode(EnableMotor, INPUT);
+        pinMode(EnableThrottle, INPUT);
         pinMode(EnableBrake, INPUT);
         pinMode(EnableSteer, INPUT);
         pinMode(StopLED, OUTPUT);
         pinMode(CruiseLED, OUTPUT);
-        pinMode(TractionMotor, OUTPUT);
+        pinMode(Throttle, OUTPUT);
         pinMode(DiskBrake, OUTPUT);
         pinMode(Steer, OUTPUT);
         pinMode(Reverse, OUTPUT);
@@ -176,17 +179,89 @@
         Serial.begin(9600);
 #endif
         initialize();
+
+        CalibrateBrakes();
+
+        CalibrateSteering();
 }

 /*---------------------------------------------------------------------------------------*/
+void CalibrateBrakes()
+{
+  // This routine establishes the correct values for MinimumBrake and FullBrake.
+  // Verify that the value for FullBrake stops the vehicle.
+  // It allows us to establish the constants to map the feedback to the commanded position.
+
+  // PWM signal is only effective from 127 to 255.
+  // Some of the extreme values produce no motion in an unattached servo.
+  // When the servo is atached to the brake lever, pushing too hard can draw too much power and blow a fuse.
+
+  // Perform this test first with an unattached servo.
+  // Repeat with an attached servo.
+
+ // It would be a good idea to put an ammeter on the brake servo to verify that excess current is not being drawn;
+ // In case current gets too high, abort by unplugging the servo.
+
+ // Use the serial monitor, and save the results for analysis.
+
+ // Mechanically adjust the brake cables so that the motion of the servo is appropriate
+       Serial.println("Calibrate brakes");
+       for (int i = MinimumBrake; i < FullBrake; i += 10)
+     {
+       analogWrite(DiskBrake, i);
+//       int current =  analogRead(CurrentBrake);
+       delay(100);  // allow tiime for brake to respond
+       int feedback = analogRead(BrakeFB);
+       // feedback signal may have glitches; use of a 5 point median filter is recommended.
+       Serial.print(i); Serial.print(", ");
+//       Serial.print(current); Serial.print(", ");
+       Serial.println(feedback);
+       delay(900);   // hold each brake position 1 second.
+     }
+}
+/*---------------------------------------------------------------------------------------*/
+void CalibrateSteering()
+{
+  // This routine establishes the correct values for HardLeft, HardRight, Straight, etc.
+  // Verify that the values for left are those that turn the vehicle to the let.
+  // It allows us to establish the constants to map the feedback to the commanded position.
+
+  // PWM signal is only effective from 127 to 255.
+  // Some of the extreme values produce no motion in an unattached servo.
+  // When the servo is atached to the steering link, pushing too hard can draw too much power and blow a fuse.
+
+  // Perform this test first with an unattached servo.
+  // Repeat with an attached servo.
+
+ // It would be a good idea to put an ammeter on the steering servo to verify that excess current is not being drawn;
+ // In case current gets too high, abort by unplugging the servo.
+  // Use the serial monitor, and save the results for analysis.
+
+  // Mechanically position the steering link so that servo motion half-way between extremes is straight ahead.
+
+       Serial.println("Calibrate steering");
+       for (int i = HardLeft; i < HardRight; i += 10)
+     {
+       analogWrite(Steer, i);
+//       int current =  analogRead(CurrentBrake);
+       delay(100);  // allow tiime for brake to respond
+       int feedback = analogRead(SteerFB);
+       // feedback signal may have glitches; use of a 5 point median filter is recommended.
+       Serial.print(i); Serial.print(", ");
+//       Serial.print(current); Serial.print(", ");
+       Serial.println(feedback);
+       delay(900);   // hold each brake position 1 second.
+     }
+}
+/*---------------------------------------------------------------------------------------*/
 void initialize()
 {

         Halt();

-        Instrument[Motor].EnablePin = EnableMotor;
-        Instrument[Motor].SignalPin = TractionMotor;
-        Instrument[Motor].FeedbackPin = FeedbackMotor;
+        Instrument[Motor].EnablePin = EnableThrottle;
+        Instrument[Motor].SignalPin = Throttle;
+ //       Instrument[Motor].FeedbackPin = FeedbackMotor;
         Instrument[Motor].CurrentPin = Current36V;
         Instrument[Motor].StepSize = 20; // max from range of 1023.
         Instrument[Motor].CloseEnough = 1000;  // no feedback
@@ -197,7 +272,7 @@

         Instrument[Steering].EnablePin = EnableSteer;
         Instrument[Steering].SignalPin = Steer;
-        Instrument[Steering].FeedbackPin = FeedbackSteer;
+        Instrument[Steering].FeedbackPin = SteerFB;
         Instrument[Steering].CurrentPin = CurrentSteer;
         Instrument[Steering].StepSize = 20;
         Instrument[Steering].CloseEnough = 1;
@@ -207,7 +282,7 @@

         Instrument[Brakes].EnablePin = EnableBrake;
         Instrument[Brakes].SignalPin = DiskBrake;
-        Instrument[Brakes].FeedbackPin = FeedbackBrake;
+        Instrument[Brakes].FeedbackPin = BrakeFB;
         Instrument[Brakes].CurrentPin = CurrentBrake;
         Instrument[Brakes].StepSize = 50;
         Instrument[Brakes].CloseEnough = 1;
@@ -282,7 +357,7 @@
   static unsigned long OutsideTime;

   OutsideTime = EndTime - TimeNow;
-  Instrument[Motor].Enabled = digitalRead(EnableMotor);
+  Instrument[Motor].Enabled = digitalRead(EnableThrottle);
   Instrument[Brakes].Enabled = digitalRead(EnableBrake);
   Instrument[Steering].Enabled = digitalRead(EnableSteer);
 #ifdef TEST_MODE
@@ -323,7 +398,7 @@
      analogWrite(DiskBrake, i);
      for (int d = 0; d < Delay_ms; d++)
      {
-       int feedback = analogRead(FeedbackBrake);
+       int feedback = analogRead(BrakeFB);
 //       int current =  analogRead(CurrentBrake);
        delay(1);
        Serial.print(d); Serial.print(", ");
@@ -341,7 +416,7 @@
      analogWrite(Steer, i);
      for (int d = 0; d < Delay_ms; d++)
      {
- //      int feedback = analogRead(FeedbackBrake);
+ //      int feedback = analogRead(BrakeFB);
  //      int current =  analogRead(CurrentBrake);
        Serial.print(d); Serial.print(", ");
        Serial.print(i); Serial.print(", ");


Tweaked speed minimum and ramp min/max to match specs

--- MotorController/MotorController.ino
+++ MotorController/MotorController.ino
@@ -61,9 +61,9 @@

 // Settings and limits
 const int switchDebounceTime = 30;
-const int minimumDelay = 5;
-const int maximumDelay = 40;
-const int minimumSpeed = 10;
+const int minimumDelay = 2;
+const int maximumDelay = 15;
+const int minimumSpeed = 26;
 // 10K ohm potentiometers probably won't get all the way to 1024
 // and we want to make sure that max feasible input = max motor speed
 const int potentiometerCeiling = 1000;


Delete C_CDELEM-Industruino.ino

Delete C_CDELEM-Industruino.ino

--- BMS_Francais/Examples/C_CDELEM-Industruino/C_CDELEM-Industruino.ino
+++ BMS_Francais/Examples/C_CDELEM-Industruino/C_CDELEM-Industruino.ino
@@ -1,188 +0,0 @@
-/*-------------------------------------------------------------------------------------------------------------------------------------------*
- * SE2R : C_CDELEM - Fonction de commande de booléen avec prise en compte de forçage et de défaut - Industruino                   12/06/2015 *
- *-------------------------------------------------------------------------------------------------------------------------------------------*
- *        C_CDELEM(boolean CDE, boolean DFT, boolean RES[], int CFG)                                                              12/06/2015 *
- *                CDE : Commande calculée ou donnée par l'utilisateur (peut être le résultat d'une fonction appelée plus haut)               *
- *                DFT : Défaut de l'équipement commandé. True signale un équipement en état normal. Un false signale un défaut               *
- *                RES : [00] Commande de l'équipement - forcément un tableau de taille au moins 1                                            *
- *                CFG : Commande de forçage.                                                                                *
- *                      <0 : RES maintenu à false                                                                                *
- *                      0  : RES figée dans son dernier état connu                                                                           *
- *                      1  : RES soumise à CDE et à DEF                                                                                *
- *                      2  : RES soumise seulement à DEF (comme si CDE était true en permanence)                                             *
- *                      3  : RES  maintenu à true                                                                                *
- *                      >3 : RES maintenu à false                                                                                *
- *-------------------------------------------------------------------------------------------------------------------------------------------*
- * Copyright SE2R under the APACHE Licence                                                                                *
- *-------------------------------------------------------------------------------------------------------------------------------------------*
- * Plate-formes testées : Industruino 32U8 et 1286                                                                                *
- *-------------------------------------------------------------------------------------------------------------------------------------------*
- * 03/06/2015 : DD, SE2R : Testée et validée sur banc                                                                                *
- * 12/06/2015 : DD, SE2R : Ajout des commentaires d'appartenance à C_CDELEM                                                                  *
- *-------------------------------------------------------------------------------------------------------------------------------------------*/
-
-// Déclaration des bibliothèques nécessaires à l'exécution du programme ---------------------------------------------------------------------*
-#include <DIS.h>                        // Biblio   - SE2R - Fonctions de dialogue et d'affichage sur l'écran UC1701 Industruino
-static DIS DIS;                         // Biblio   - Activation du constructeur de la bibliothèque de fonctions d'affichage
-static UC1701 lcd;
-#include <BMS.h>                        // Biblio   - SE2R - Fonctions de contrôle et régulation
-static BMS BMS;                         // Biblio   - Activation du constructeur de la bibliothèque de fonctions d'affichage
-
-// Déclaration des variables nécessaires à l'exécution de la fonction -----------------------------------------------------------------------*
-boolean FCO_XXXX[1];                    // C_CDELEM - [00] Commande de marche depuis l'extérieur
-boolean EDx_TEL_XXXX[9];                // Système  - [00] Inutilisée
-                                        // Système  - [01] Etat de la lecture de la voie digitale 1 si elle est une entrée
-                                        // Système  - [02] Etat de la lecture de la voie digitale 2 si elle est une entrée
-                                        // Système  - [03] Etat de la lecture de la voie digitale 3 si elle est une entrée
-                                        // Système  - [04] Etat de la lecture de la voie digitale 4 si elle est une entrée
-                                        // Système  - [05] Etat de la lecture de la voie digitale 5 si elle est une entrée
-                                        // Système  - [06] Etat de la lecture de la voie digitale 6 si elle est une entrée
-                                        // Système  - [07] Etat de la lecture de la voie digitale 7 si elle est une entrée
-                                        // Système  - [08] Etat de la lecture de la voie digitale 8 si elle est une entrée
-boolean SDx_TSL_XXXX[9];                // Système  - [00] Mémoire temporaire utilisée pour les calculs
-                                        // Système  - [01] Etat de la commande de la voie digitale 1 si elle est une sortie
-                                        // Système  - [02] Etat de la commande de la voie digitale 1 si elle est une sortie
-                                        // Système  - [04] Etat de la commande de la voie digitale 1 si elle est une sortie
-                                        // Système  - [05] Etat de la commande de la voie digitale 1 si elle est une sortie
-                                        // Système  - [07] Etat de la commande de la voie digitale 1 si elle est une sortie
-                                        // Système  - [08] Etat de la commande de la voie digitale 1 si elle est une sortie
-int VCO_XXXX[1];                        // C_CDELEM - [00] Commande de forçage par l'extérieur
-
-// Déclaration des variables nécessaires au fonctionnement de l'écran -----------------------------------------------------------------------*
-String TCM_PRES[11] = {                 // EcranLCD - Table de chaînes de caractères de présentation
-  "                     ", // 00
-  "-  Menu  Principal  -",
-  "Retour Accueil      ",
-  "Demande             ",
-  "forcage             ",
-  "Defaut               ",
-  "Cde M/A              ",
-  " ",
-  "- Selection + Enter -",
-  "- Commande  Mar/Arr -",
-  "-      Forcage      -"}; // 10
-
-String TCM_UNIT[21] = {                 // EcranLCD - Table de chaînes de caractères d'unités standard
-  "        ",  // 00
-  "oC      ",
-  "%       ",
-  "s       ",
-  "V       ",
-  "mV      ",  // 05
-  "",
-  "",
-  "",
-  "",
-  "",          // 10
-  "   Arret ",
-  "  Marche ",
-  " F.Arret ",
-  " Debraye ",
-  "    Auto ", // 15
-  "F.Marche ",
-  "V.Marche ",
-  "  Defaut ",
-  "  Normal ",
-  "  " };      // 20
-
-boolean FCO_PRUP[5];                    // EcranLCD - Information de touche "Up" appuyée
-boolean FCO_PREN[5];                    // EcranLCD - Information de touche "Enter" appuyée
-boolean FCO_PRDN[5];                    // EcranLCD - Information de touche "Down" appuyée
-int VNT_MENU[2];                        // EcranLCD - Table d'adressage des menus
-int VNC_MENU[5];                        // EcranLCD - Table des numéros de menus
-int VNC_PRUP[6];                        // EcranLCD - Table des numéros de menus de destination par la touche "Up"
-int VNC_PREN[5];                        // EcranLCD - Table des numéros de menus de destination par la touche "Enter"
-int VNC_PRDN[5];                        // EcranLCD - Table des numéros de menus de destination par la touche "Down"
-float VTT_SCRN[10];                     // EcranLCD - Table des temporisations
-int VNX_MN02[12];                       // EcranLCD - Table des menus de destimation et des index du menu 02 - Principal
-boolean FCM_XXXX[1];                    // G_MODV1B - Mémoire de la demande de marche
-int VTM_XXXX[7];                        // G_MODV1M - Mémoire de calcul de la commande de la fonction pour VCO_XXXX - Forçage
-
-void setup() {                          // Initialisation -----------------------------------------------------------------------------------*
-Indio.digitalMode(1,INPUT);             // Système  - Affectation de la voie Dx1 en tant qu'entrée digitale
-Indio.digitalMode(5,OUTPUT);            // Système  - Affectation de la voie Dx5 en tant que sortie digitale
-VCO_XXXX[0] = 1;                        // C_CDELEM - Passage du forçage en position auto
-
-VTT_SCRN[1] = 180;                      // G_TOUCHx - Temporisation d'inactivité sur le rétroéclairage
-VTT_SCRN[2] = 240;                      // G_TOUCHx - Temporisation d'inactivité de retour à l'écran principal
-VTT_SCRN[3] = 20;                       // G_TOUCHx - Temporisation d'antirebond de la touche "Enter"
-VTT_SCRN[4] = 15;                       // G_TOUCHx - Temporisation d'antiredond des touches "Up" et "Down"
-VNT_MENU[0] = 4;                        // G_NAVIGM - Taille des tables d'index et de destinations
-VNT_MENU[1] = 1;                        // G_NAVIGM - Initialisation du pointeur de destinations
-
-//                                      // G_NAVIGM - Tables d'adressage de l'écran LCD
-VNC_MENU[0] = 1;
-VNC_MENU[1] = 1;
-VNC_MENU[2] = 2;
-VNC_MENU[3] = 3;
-VNC_MENU[4] = 4;
-VNC_PRUP[1] =   1; VNC_PREN[1] =   2; VNC_PRDN[1] =   2;
-VNC_PRUP[2] =   2; VNC_PREN[2] =   2; VNC_PRDN[2] =   2;
-VNC_PRUP[3] =   3; VNC_PREN[3] =   2; VNC_PRDN[3] =   3;
-VNC_PRUP[4] =   4; VNC_PREN[3] =   2; VNC_PRDN[3] =   4;
-VNC_PRUP[5] =   2;
-
-VNX_MN02[0] = 0;						// G_CHOIX8 - Table des menus de destination et des index du menu 11 - Initialisation index
-VNX_MN02[1] = 1;
-VNX_MN02[2] = 3;
-VNX_MN02[3] = 4;
-VNX_MN02[4] = 0;
-VNX_MN02[5] = 0;
-VNX_MN02[6] = 0;
-VNX_MN02[7] = 0;
-VNX_MN02[8] = 1;
-VNX_MN02[9] = 3;
-VNX_MN02[10] = 1;
-
-VTM_XXXX[1] = 0; VTM_XXXX[2] = 2; VTM_XXXX[3] = 1; VTM_XXXX[4] = VCO_XXXX;
-
-//                                      // EcranLCD - Paramétrage spécifique Industruino 1286
-pinMode(23, INPUT);                     // EcranLCD - Spécifique 1286 - Touche flèche basse
-pinMode(24, INPUT);                     // EcranLCD - Spécifique 1286 - Touche entrée
-pinMode(25, INPUT);                     // EcranLCD - Spécifique 1286 - Touche flèche haute
-pinMode(26, OUTPUT);                    // EcranLCD - Spécifique 1286 - Sortie de commande du rétroéclairage
-
-/*                                      // EcranLCD - Paramétrage spécifique Industruino 32U8
-pinMode(13, OUTPUT);                    // EcranLCD - Spécifique 32U8 - Sortie de commande du rétroéclairage
-*/
-lcd.begin();                            // EcranLCD - Initialisation de l'écran LCD
-lcd.clear();                            // EcranLCD - Effacement de l'écran LCD
-}
-
-void loop() {                            // Exécution ---------------------------------------------------------------------------------------*
-if (Indio.digitalRead(1) == HIGH) { EDx_TEL_XXXX[1] = false; } else { EDx_TEL_XXXX[1] = true; }
-BMS.C_CDELEM(FCO_XXXX[0], EDx_TEL_XXXX[1], SDx_TSL_XXXX, VCO_XXXX[0]);
-if (SDx_TSL_XXXX[0] == true ) { SDx_TSL_XXXX[5] = true; } else  { SDx_TSL_XXXX[5] = false; }
-if (SDx_TSL_XXXX[5] == true ) { Indio.digitalWrite(5,HIGH); } else {Indio.digitalWrite(5,LOW); }
-
-//                                      // EcranLCD - Gestion des touches spécifique Industruino 1286
-DIS.G_TOUCH2(VNC_MENU, VTT_SCRN, FCO_PRUP, FCO_PREN, FCO_PRDN);
-/*                                      // EcranLCD - Gestion des touches spécifique Industruino 32U8
-DIS.G_TOUCH1(VNC_MENU, VTT_SCRN, FCO_PRUP, FCO_PREN, FCO_PRDN);
-*/
-
-if (VNC_MENU[0] ==  1) { lcd.setCursor(0, 0); lcd.clearLine(); }
-DIS.G_MESS1L(VNC_MENU, 1, 1, 0, "   www.eControls.eu  ");
-DIS.G_MESS1L(VNC_MENU, 1, 2, 0, "    SE2R Softwares   ");
-DIS.G_MESS1L(VNC_MENU, 1, 3, 0, "  Industruino  1286  ");
-// DIS.G_MESS1L(VNC_MENU, 1, 3, 0, "  Industruino  32U8  ");
-if (VNC_MENU[0] ==  1) { lcd.setCursor(0, 4); lcd.clearLine(); }
-DIS.G_MESS1L(VNC_MENU, 1, 5, 0, "Fonction BMS.C_CDELEM");
-DIS.G_MESS1L(VNC_MENU, 1, 6, 0, "A# TESTS     C# 00001");
-DIS.G_MESS1L(VNC_MENU, 1, 7, 0, "V.1.01     12/06/2015");
-
-DIS.G_CHOIX8(VNC_MENU, 2, FCO_PRUP, FCO_PREN, FCO_PRDN, VNX_MN02);
-DIS.G_MESS1L(VNC_MENU, 2, 0, 0, TCM_PRES[1]);
-DIS.G_MESS1L(VNC_MENU, 2, 1, 6, TCM_PRES[2]);
-DIS.G_VISV1B(VNC_MENU, 2, 2, 6, FCO_XXXX[0], TCM_PRES[3], TCM_UNIT[11], TCM_UNIT[12]);
-DIS.G_VISV1M(VNC_MENU, 2, 3, 6, VCO_XXXX[0], TCM_PRES[4], TCM_UNIT[14]);
-if (VNC_MENU[0] ==  2) { lcd.setCursor(0, 4); lcd.clearLine(); }
-DIS.G_VISV1B(VNC_MENU, 2, 5, 0, EM1_MII_MPLX[4], TCM_PRES[6], TCM_UNIT[18], TCM_UNIT[19]);
-DIS.G_VISV1B(VNC_MENU, 2, 6, 0, SDx_MPL_XXXX[5], TCM_PRES[7], TCM_UNIT[11], TCM_UNIT[12]);
-DIS.G_MESS1L(VNC_MENU, 2, 7, 0, TCM_PRES[8]);
-
-DIS.G_MODV1B(VNC_MENU, 3, FCO_PRUP, FCO_PREN, FCO_PRDN, FCO_XXXX, 0, FCM_XXXX, TCM_PRES[9] , " Commande operateur ", TCM_UNIT[13], TCM_UNIT[14], true);
-DIS.G_MODV1M(VNC_MENU, 4, FCO_PRUP, FCO_PREN, FCO_PRDN, VCO_XXXX, 0, VTM_XXXX, TCM_PRES[10], "Arr/Deb/Auto/Mar/VMa", TCM_UNIT, 14, true, 0);
-
-DIS.G_NAVIGM(VNC_MENU, VNT_MENU, FCO_PRUP, FCO_PREN, FCO_PRDN , VNC_PRUP, VNC_PREN, VNC_PRDN);
-}


adding up and down  servo movement

adding up and down  servo movement

--- ImageAnalysis/PrinterMechanics_Scanner/PrinterMechanics_Scanner.ino
+++ ImageAnalysis/PrinterMechanics_Scanner/PrinterMechanics_Scanner.ino
@@ -17,10 +17,10 @@
 // Vertical axis
 #define StepPinV_Y                6
 #define DirectionPinV_Y           7
+#define JoyV_SW                   8
 #define JoyV_Y                    A2
 #define JoyV_X                    A3
 #define ServoV                    10
-

 Servo dvd_down;

@@ -61,8 +61,10 @@
 	// DVD
 	pinMode(DirectionPinV_Y, OUTPUT);
 	pinMode(StepPinV_Y, OUTPUT);
+	pinMode(JoyV_SW, INPUT);
+	digitalWrite(DirectionPinV_Y, LOW);
 	digitalWrite(StepPinV_Y, LOW);
-	digitalWrite(DirectionPinV_Y, LOW);
+	digitalWrite(JoyV_SW, HIGH);

 	dvd_down.attach(ServoV);

@@ -121,18 +123,20 @@

 	// Servo

-	if (analogRead(JoyV_X)<400)
+	//if (analogRead(JoyV_X)<400)
+	if (digitalRead(JoyV_SW) == HIGH)
 	{
-		int y = map(analogRead(JoyV_X), 0, 1023, 900, 2100);
-		dvd_down.write(y);
-		delay(1000);
+		//int y = map(analogRead(JoyV_X), 0, 1023, 900, 2100);
+		dvd_down.write(900);
+		delay(20);
 	}

-	if (analogRead(JoyV_X)>600)
+	//if (analogRead(JoyV_X)>600)
+	if (digitalRead(JoyV_SW) == LOW)
 	{
-		int y = map(analogRead(JoyV_X), 0, 1023, 900, 2100);
-		dvd_down.write(y);
-		delay(1000);
+		//int y = map(analogRead(JoyV_X), 0, 1023, 900, 2100);
+		dvd_down.write(2100);
+		delay(20);
 	}

 }


Add the possibility to configure the remote host idaddress and port from the serial interface. For example #H192.168.9.250 sets the host ipaddress and #S8181 sets the host port.

--- EnerginoEthernet/EnerginoEthernet.ino
+++ EnerginoEthernet/EnerginoEthernet.ino
@@ -54,19 +54,16 @@
 #endif

 // Feed id
-long FEED = 0;
+const long FEED = 0;
+const char KEY[] = "-";

 // Cosm configuration
-//IPAddress HOST(216,52,233,121);
-//const long PORT = 80;
-
-// Daemonino configuration
-IPAddress HOST(192,168,9,250);
-const long PORT = 8181;
+IPAddress HOST(216,52,233,121);
+const long PORT = 80;

 // Assign a MAC address for the ethernet controller.
 byte MAC[] = {
-  0x90, 0xA2, 0xDA, 0x0A, 0x00, 0xCC };
+  0x90, 0xA2, 0xDA, 0x0D, 0x1D, 0x95 };

 // This configuration is used when DHCP fails
 IPAddress IP(172,25,18,219);
@@ -112,6 +109,8 @@
   char apikey[49];
   long period;
   long feed;
+  IPAddress host;
+  long port;
 }
 settings;

@@ -126,8 +125,9 @@
   strcpy (settings.magic,MAGIC);
   settings.period = PERIOD;
   settings.feed = FEED;
-  settings.apikey[0] = '-';
-  settings.apikey[1] = '\0';
+  settings.host = HOST;
+  settings.port = PORT;
+  strcpy (settings.apikey,KEY);
 }

 void setup() {
@@ -215,6 +215,27 @@
     strncpy(settings.apikey, inputBytes,49);
     settings.apikey[48] = '\0';
   }
+  else if (cmd == 'H') {
+    byte host[4];
+    char *p = strtok(inputBytes, ".");
+    for (int i = 0; i < 4; i++) {
+        host[i] = atoi(p);
+        p = strtok(NULL, ".");
+    }
+    IPAddress hostIP = IPAddress(host);
+    DBG Serial.print("New host ip address: ");
+    DBG Serial.println(hostIP);
+    settings.host=IPAddress(host);
+  }
+  else if (cmd == 'S') {
+    long value = atol(inputBytesPtr);
+    if (value > 0) {
+      DBG Serial.print("New host port: ");
+      DBG Serial.println(value);
+      settings.port = value;
+    }
+
+  }
   else if (cmd == 'R') {
     reset();
   }
@@ -308,7 +329,7 @@
   char *json = getDatastreams();
   // if there's a successful connection:
   DBG Serial.println("Connecting.");
-  if ((settings.feed != 0) && client.connect(HOST, PORT)) {
+  if ((settings.feed != 0) && client.connect(settings.host, settings.port)) {
     DBG Serial.println("connected.");
     DBG Serial.print("PUT /v2/feeds/");
     DBG Serial.println(settings.feed);
@@ -392,13 +413,13 @@
   Serial.print(",");
   for (byte thisByte = 0; thisByte < 4; thisByte++) {
     // print the value of each byte of the IP address:
-    Serial.print(HOST[thisByte], DEC);
+    Serial.print(settings.host[thisByte], DEC);
     if (thisByte < 3) {
       Serial.print(".");
     }
   }
   Serial.print(",");
-  Serial.print(PORT);
+  Serial.print(settings.port);
   Serial.print(",");
   Serial.print(settings.feed);
   Serial.print(",");


add jacobian, forward and inverse

add jacobian, forward and inverse

--- arduino/opencr_arduino/opencr/libraries/OpenManipulator/example/Arduino/Test/kinematics/kinematics.ino
+++ arduino/opencr_arduino/opencr/libraries/OpenManipulator/example/Arduino/Test/kinematics/kinematics.ino
@@ -29,14 +29,23 @@
   manipulator.addComponent(COMP1, WORLD, COMP2, MATH::makeVector3(-0.100, 0.0, 0.0), IDENTITY_MATRIX, 1, Z_AXIS, 0.5, MATH::makeMatrix3(1, 1, 1, 1, 1, 1, 3, 1, 1));
   manipulator.addComponent(COMP2, COMP1, COMP3, MATH::makeVector3(0.0, 0.0, 0.050), IDENTITY_MATRIX, 2, Y_AXIS, 1.5);
   manipulator.addComponentChild(COMP2, COMP4);
-  manipulator.addComponent(COMP3, COMP2, COMP4, MATH::makeVector3(0.0, 0.050, 0.0), IDENTITY_MATRIX, NONE);
-  manipulator.addComponent(COMP4, COMP2, TOOL, MATH::makeVector3(0.0, 0.0, 0.050), IDENTITY_MATRIX, 3, Y_AXIS, 2.0);
-  manipulator.addTool(TOOL, COMP4, MATH::makeVector3(0.0, 0.0, 0.025), IDENTITY_MATRIX, 4, 0.1);
-
-  // manipulator.checkManipulatorSetting();
+  manipulator.addComponent(COMP3, COMP2, TOOL, MATH::makeVector3(0.0, 0.050, 0.0), IDENTITY_MATRIX, 3, Y_AXIS, 2.0);
+  manipulator.addComponent(COMP4, COMP2, TOOL, MATH::makeVector3(0.0, 0.0, 0.050), IDENTITY_MATRIX, NONE);
+  manipulator.addTool(TOOL, COMP3, MATH::makeVector3(0.0, 0.0, 0.025), IDENTITY_MATRIX, 4, 0.1);

   Eigen::MatrixXf jacobian = KINEMATICS::CHAIN::jacobian(&manipulator, TOOL);
+  LOG::INFO("Jacobian : ");
   PRINT::MATRIX(jacobian);
+
+  KINEMATICS::CHAIN::forward(&manipulator, COMP1);
+  manipulator.checkManipulatorSetting();
+
+  Pose target;
+  target.position = ZERO_VECTOR;
+  target.orientation = IDENTITY_MATRIX;
+  Eigen::VectorXf joint_angle = KINEMATICS::CHAIN::inverse(&manipulator, TOOL, target);
+  LOG::INFO("Result of inverse : ");
+  PRINT::VECTOR(joint_angle);
 }

 void loop()


Workshop update

Workshop update

--- examples/_2000_ESPert_workshop/_2000_ESPert_workshop.ino
+++ examples/_2000_ESPert_workshop/_2000_ESPert_workshop.ino
@@ -75,7 +75,7 @@

     String value = espert.json.get("IFTTT");
     ifttt_key = value;
-    espert.eeprom.write( 200, `ifttt_key );
+    espert.eeprom.write( 200, ifttt_key );
   }
 }


Added debug/development mode to Extend-o-Hand, to make it easier to capture its output for gesture recognition work

--- extendo-hand/src/main/arduino/extendo_hand/extendo_hand.ino
+++ extendo-hand/src/main/arduino/extendo_hand/extendo_hand.ino
@@ -1,5 +1,5 @@
 /*
- * Extend-o-Hand firmware, copyright 2013 by Joshua Shinavier
+ * Extend-o-Hand firmware, copyright 2013-2014 by Joshua Shinavier
  *
  * See: https://github.com/joshsh/extendo
  */
@@ -11,11 +11,11 @@

 ////////////////////////////////////////////////////////////////////////////////

-// if defined, use more straightforward serial output
-//#define DEBUG
-
 // send and receive messages using Bluetooth/Amarino as opposed to plain serial
-#define USE_BLUETOOTH
+//#define USE_BLUETOOTH
+
+// if defined, make serial output more legible
+#define DEBUG

 ////////////////////////////////////////////////////////////////////////////////
@@ -137,9 +137,20 @@
 #endif
 }

-void error(char *message) {
+
+////////////////////////////////////////////////////////////////////////////////
+
+void sendError(char *message) {
     OSCMessage m("/exo/hand/error");
     m.add(message);
+
+    sendOSC(m);
+}
+
+void sendInfo(char *message) {
+    OSCMessage m("/exo/hand/info");
+    m.add(message);
+
     sendOSC(m);
 }

@@ -194,17 +205,27 @@
           state = STATE_ONE;

           // gesture event
+#ifdef DEBUG
+          // tab-separated format for the gesture event, for ease of importing to R and similar tools
+          Serial.print((int32_t) micros()); Serial.print(",");
+          Serial.print(amax); Serial.print(",");
+          Serial.print(ax_max); Serial.print(",");
+          Serial.print(ay_max); Serial.print(",");
+          Serial.println(az_max);
+#else
           OSCMessage m("/exo/hand/raw");
           m.add((int32_t) micros());
-          m.add((int) (amax * 100));
-          m.add((int) (ax_max * 100));
-          m.add((int) (ay_max * 100));
-          m.add((int) (az_max * 100));
-          sendOSC(m);
+          m.add(amax);
+          m.add(ax_max);
+          m.add(ay_max);
+          m.add(az_max);
+          sendOSC(m);
+#endif
         }
         break;
     }
 }
+

 ////////////////////////////////////////////////////////////////////////////////


changed way to read water level

changed way to read water level

--- WaterLevelSensor/WaterLevelSensor.ino
+++ WaterLevelSensor/WaterLevelSensor.ino
@@ -16,9 +16,38 @@
 // the loop routine runs over and over again forever:
 void loop() {
   // read the input on analog pin 0:
+  int waterHeight;
   int sensorValue = analogRead(A0);
+/*
+  if(sensorValue>690)
+    waterHeight = map(sensorValue, 700, 1024, 0, 40);
+  else
+    waterHeight = 0;
   // print out the value you read:
+*/
+  if(sensorValue>700)
+    waterHeight = 1;
+  if(sensorValue>736)
+    waterHeight = 5;
+  if(sensorValue>790)
+    waterHeight = 10;
+  if(sensorValue>827)
+    waterHeight = 15;
+  if(sensorValue>843)
+    waterHeight = 20;
+  if(sensorValue>857)
+    waterHeight = 25;
+  if(sensorValue>870)
+    waterHeight = 3;
+  if(sensorValue>910)
+    waterHeight = 3.5;
+  if(sensorValue>1010)
+    waterHeight = 40;
+
+
   Serial.println(sensorValue);
+  Serial.println(waterHeight);
+
   Serial.println();
   delay(1000);        // delay in between reads for stability
 }


Update GAC.ino

Update GAC.ino

--- GAC/GAC.ino
+++ GAC/GAC.ino
@@ -13,13 +13,15 @@
 int flag =0; //1 if pressure was exceded
 unsigned long LOG_INTERVAL = 15000;
 unsigned long previousMillis = 0;
-int switchPin =19;
+#define switchPin A2
 #define PressureAnalog A0      // analog 1
 float PressureAnalogReading = 0;
 float PressureReadingSUM = 0;
 unsigned long readingCount = 0;

 void setup() {
+  pinMode(switchPin,OUTPUT);
+    digitalWrite(switchPin, HIGH);
     lcd.begin(16, 2);
   lcd.print("start!");
   lcd.setBacklight(WHITE);
@@ -69,11 +71,13 @@
     //reset averaging tools if interval is met
     readingCount=0;
     PressureReadingSUM = 0;
-    if(P <= 20 && flag == 0){
+    if(P <= 20 && flag==0){
     digitalWrite(switchPin, HIGH);
-  }else{
-    flag =1;
-    digitalWrite(switchPin, LOW);
-  }
+    }
+    else if (P>20){ flag ==1;
+      digitalWrite(switchPin, LOW);}
+    while (flag ==1){
+      digitalWrite(switchPin, LOW);
+   }
   }
 }


reorganize compliance example for robustness

--- examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino
+++ examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino
@@ -10,10 +10,6 @@

 Author:
     Terry Moore, MCCI Corporation   March 2019
-
-Description:
-    This sketch demonstrates use of the LMIC compliance-test mode. Tested
-    with an RWC5020A LoRaWAN Tester.

 */

@@ -60,6 +56,15 @@
 lmic_event_cb_t myEventCb;
 lmic_rxmessage_cb_t myRxMessageCb;

+const char * const evNames[] = {
+    "<<zero>>",
+    "EV_SCAN_TIMEOUT", "EV_BEACON_FOUND",
+    "EV_BEACON_MISSED", "EV_BEACON_TRACKED", "EV_JOINING",
+    "EV_JOINED", "EV_RFU1", "EV_JOIN_FAILED", "EV_REJOIN_FAILED",
+    "EV_TXCOMPLETE", "EV_LOST_TSYNC", "EV_RESET",
+    "EV_RXCOMPLETE", "EV_LINK_DEAD", "EV_LINK_ALIVE", "EV_SCAN_FOUND",
+    "EV_TXSTART", "EV_TXCANCELED", "EV_RXSTART", "EV_JOIN_TXCOMPLETE"
+};

 /*

@@ -80,45 +85,166 @@

 */

+static osjobcbfn_t eventjob_cb;
+
+class cEventQueue {
+public:
+    cEventQueue() {};
+    ~cEventQueue() {};
+
+    struct eventnode_t {
+        osjob_t     job;
+        ev_t        event;
+        ostime_t    time;
+        ostime_t    txend;
+        u4_t        freq;
+        rps_t       rps;
+        u2_t        opmode;
+        u1_t        txChnl;
+        u1_t        datarate;
+        u1_t        txrxFlags;
+        u1_t        saveIrqFlags;
+    };
+
+    bool getEvent(eventnode_t &node) {
+        if (m_head == m_tail) {
+            return false;
+        }
+        node = m_queue[m_head];
+        if (++m_head == sizeof(m_queue) / sizeof(m_queue[0])) {
+            m_head = 0;
+        }
+        return true;
+    }
+
+    bool putEvent(ev_t event) {
+        auto i = m_tail + 1;
+        if (i == sizeof(m_queue) / sizeof(m_queue[0])) {
+            i = 0;
+        }
+        if (i != m_head) {
+            auto const pn = &m_queue[m_tail];
+            pn->time = os_getTime();
+            pn->txend = LMIC.txend;
+            pn->event = event;
+            pn->freq = LMIC.freq;
+            pn->txChnl = LMIC.txChnl;
+            pn->rps = LMIC.rps;
+            pn->datarate = LMIC.datarate;
+            pn->opmode = LMIC.opmode;
+            pn->txrxFlags = LMIC.txrxFlags;
+            pn->saveIrqFlags = LMIC.saveIrqFlags;
+            m_tail = i;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+private:
+    unsigned m_head, m_tail;
+    eventnode_t m_queue[16];
+    osjob_t m_job;
+};
+
+cEventQueue eventQueue;
+
 uint8_t lastTxChannel;
 bool lastTxStart;

 void myEventCb(void *pUserData, ev_t ev) {
-    if (ev == EV_TXSTART) {
-        lastTxStart == true;
-        Serial.print(F("."));
+    eventQueue.putEvent(ev);
+
+    if (ev == EV_JOINING) {
+        setupForNetwork(true);
+    } else if (ev == EV_JOINED) {
+        setupForNetwork(false);
+    }
+}
+
+void eventPrint(cEventQueue::eventnode_t &e);
+
+void eventPrintAll(void) {
+    while (eventPrintOne())
+        ;
+}
+
+bool eventPrintOne(void) {
+    cEventQueue::eventnode_t e;
+    if (eventQueue.getEvent(e)) {
+        eventPrint(e);
+        return true;
     } else {
-        if (lastTxStart) {
-            Serial.println();
-            lastTxStart = false;
-        }
-        Serial.print(os_getTime());
-        Serial.print(F(": "));
-    }
+        return false;
+    }
+}
+
+static void eventjob_cb(osjob_t *j) {
+    eventPrintAll();
+}
+
+const char *getSfName(rps_t rps) {
+    const char * const t[] = { "FSK", "SF7", "SF8", "SF9", "SF10", "SF11", "SF12", "SFrfu" };
+    return t[getSf(rps)];
+}
+
+const char *getBwName(rps_t rps) {
+    const char * const t[] = { "BW125", "BW250", "BW500", "BWrfu" };
+    return t[getBw(rps)];
+}
+
+const char *getCrName(rps_t rps) {
+    const char * const t[] = { "CR 4/5", "CR 4/6", "CR 4/7", "CR 4/8" };
+    return t[getCr(rps)];
+}
+
+const char *getCrcName(rps_t rps) {
+    return getNocrc(rps) ? "NoCrc" : "Crc";
+}
+
+void printFreq(u4_t freq) {
+    Serial.print(freq / 1000000);
+    Serial.print(F("."));
+    Serial.print((freq % 1000000) / 100000);
+}
+
+void printRps(rps_t rps) {
+    Serial.print(F(" rps=0x")); Serial.print(unsigned(rps), HEX);
+    Serial.print(F(" (")); Serial.print(getSfName(rps));
+    Serial.print(F(" ")); Serial.print(getBwName(rps));
+    Serial.print(F(" ")); Serial.print(getCrName(rps));
+    Serial.print(F(" ")); Serial.print(getCrcName(rps));
+    Serial.print(F(" IH=")); Serial.print(unsigned(getIh(rps)));
+    Serial.print(F(")"));
+}
+
+void eventPrint(cEventQueue::eventnode_t &e) {
+    ev_t ev = e.event;
+
+    Serial.print(e.time);
+    Serial.print(F(": "));
+    if (ev < sizeof(evNames) / sizeof(evNames[0])) {
+        Serial.print(evNames[ev]);
+    } else {
+        Serial.print(F("Unknown event: "));
+        Serial.print((unsigned) ev);
+    }
+
     switch(ev) {
         case EV_SCAN_TIMEOUT:
-            Serial.println(F("EV_SCAN_TIMEOUT"));
             break;
         case EV_BEACON_FOUND:
-            Serial.println(F("EV_BEACON_FOUND"));
             break;
         case EV_BEACON_MISSED:
-            Serial.println(F("EV_BEACON_MISSED"));
             break;
         case EV_BEACON_TRACKED:
-            Serial.println(F("EV_BEACON_TRACKED"));
-            break;
-
+            break;
         case EV_JOINING:
-            Serial.println(F("EV_JOINING"));
-
-            // this is our moment to set up pre-join network parameters.
-            setupForNetwork();
             break;

         case EV_JOINED:
-            Serial.print(F("EV_JOINED: ch "));
-            Serial.println(lastTxChannel);
+            Serial.print(F(": ch "));
+            Serial.println(unsigned(e.txChnl));
             {
               u4_t netid = 0;
               devaddr_t devaddr = 0;
@@ -142,7 +268,6 @@
                               Serial.print("-");
                       Serial.print(nwkKey[i], HEX);
               }
-              Serial.println("");
             }
             break;
         /*
@@ -154,44 +279,57 @@
         ||     break;
         */
         case EV_JOIN_FAILED:
-            // this event is just advisory (though it looks fearsome) --
-            // we've just wrapped through all our join cycles, and
-            // we will start over. You could use this to disable the radio
-            // for a while.
-            Serial.println(F("EV_JOIN_FAILED"));
+            // print out rx info
+            Serial.print(F(":  freq=")); printFreq(e.freq);
+            printRps(e.rps);
+            Serial.print(F(" opmode=")); Serial.print(e.opmode, HEX);
+            printf(" irqLevel %u", hal_getIrqLevel());
+
+            do {
+                uint8_t regbuf[0x80];
+                regbuf[0] = 0;
+                hal_spi_read(1, regbuf + 1, sizeof(regbuf) - 1);
+
+                for (unsigned i = 0; i < sizeof(regbuf); ++i) {
+                    if (i % 16 == 0) {
+                        printf("\r\n%02x:", i);
+                    }
+                    printf("%s%02x", ((i % 16) == 8) ? " - " : " ", regbuf[i]);
+                }
+
+            hal_pin_rst(0);
+            delay(2);
+            hal_pin_rst(2);
+            delay(6);
+
+            const uint8_t opmode = 0x88;    // LoRa and sleep.
+            hal_spi_write(0x81, &opmode, 1);
+
+            } while (0);
             break;

         case EV_REJOIN_FAILED:
             // this event means that someone tried a rejoin, and it failed.
             // it doesn't really mean anything bad, it's just advisory.
-            Serial.println(F("EV_REJOIN_FAILED"));
             break;

         case EV_TXCOMPLETE:
-            Serial.print(F("EV_TXCOMPLETE: ch "));
-            Serial.print(lastTxChannel);
-            if (LMIC.txrxFlags & TXRX_ACK)
+            Serial.print(F(": ch "));
+            Serial.print(e.txChnl);
+            printRps(e.rps);
+            Serial.print(F(" txrxflags 0x")); Serial.print(e.txrxFlags, HEX);
+            if (e.txrxFlags & TXRX_ACK)
                 Serial.print(F("; Received ack"));
-            Serial.println(F("."));
             break;
         case EV_LOST_TSYNC:
-            Serial.println(F("EV_LOST_TSYNC"));
             break;
         case EV_RESET:
-            // this event means that we saturated the uplink or downlink counter.
-            // this forces the entire LMIC to be reset. A join is necessary. If
-            // join is not configured, then time is up for this device.
-            Serial.println(F("EV_RESET"));
             break;
         case EV_RXCOMPLETE:
-            // data received in ping slot
-            Serial.println(F("EV_RXCOMPLETE"));
             break;
         case EV_LINK_DEAD:
-            Serial.println(F("EV_LINK_DEAD"));
             break;
         case EV_LINK_ALIVE:
-            Serial.println(F("EV_LINK_ALIVE"));
             break;
         /*
         || This event is defined but not used in the code. No
@@ -204,13 +342,32 @@
         case EV_TXSTART:
             // this event tells us that a transmit is about to start.
             // but printing here is bad for timing.
-            lastTxChannel = LMIC.txChnl;
-            break;
+            Serial.print(F(": ch "));
+            Serial.print(unsigned(e.txChnl));
+            printRps(e.rps);
+            Serial.print(F(", datarate ")); Serial.print(unsigned(e.datarate));
+            Serial.print(F(", opmode ")); Serial.print(unsigned(e.opmode), HEX);
+            break;
+
+        case EV_RXSTART:
+            Serial.print(F(": freq="));
+            printFreq(e.freq);
+            printRps(e.rps);
+            Serial.print(F(", datarate ")); Serial.print(unsigned(e.datarate));
+            Serial.print(F(", opmode ")); Serial.print(unsigned(e.opmode), HEX);
+            Serial.print(F(", txend ")); Serial.print(e.txend);
+            Serial.print(F(", delta ms ")); Serial.print(osticks2ms(e.time - e.txend));
+            break;
+
+        case EV_JOIN_TXCOMPLETE:
+            Serial.print(F(": saveIrqFlags 0x"));
+            Serial.print(unsigned(e.saveIrqFlags), HEX);
+            break;
+
         default:
-            Serial.print(F("Unknown event: "));
-            Serial.println((unsigned) ev);
-            break;
-    }
+            break;
+    }
+    Serial.println("");
 }

 /*
@@ -261,7 +418,7 @@
             Serial.println(F("Exit test mode"));
             g_fTestMode = false;
             // we're in the LMIC, we don't want to send from here. Schedule a job.
-            os_setTimedCallback(&sendjob, os_getTime() + ms2osticks(10), do_send);
+            os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
             return;
         }
         case LMIC_COMPLIANCE_RX_ACTION_IGNORE: {
@@ -362,21 +519,30 @@
     // Reset the MAC state. Session and pending data transfers will be discarded.
     LMIC_reset();

-    // do the network-specific setup.
-    setupForNetwork();
+    LMIC_setClockError(5 * MAX_CLOCK_ERROR / 100);
+
+    // do the network-specific setup prior to join.
+    setupForNetwork(false);

     // Start job (sending automatically starts OTAA too)
     do_send(&sendjob);
 }

-void setupForNetwork(void) {
+void setupForNetwork(bool preJoin) {
 #if defined(CFG_us915)
-    LMIC_setLinkCheckMode(0);
-    LMIC_setDrTxpow(DR_SF7, 14);
     LMIC_selectSubBand(1);
+
+    if (! preJoin) {
+//        LMIC_setLinkCheckMode(0);
+//        LMIC_setDrTxpow(DR_SF7, 14);
+    }
 #endif
 }

 void loop() {
     os_runloop_once();
-}
+    while ((LMIC.opmode & OP_TXRXPEND) == 0 &&
+           ! os_queryTimeCriticalJobs(ms2osticks(1000)) &&
+           eventPrintOne())
+        ;
+}


changes for testing

changes for testing

--- robot.ino
+++ robot.ino
@@ -14,111 +14,77 @@
 int STOP_TIME = 200; //ms

 /* Photodiod pins */
-int diod1Pin = A4;
+int diod1Pin = A5;
 int diod2Pin = A5;
-int diod3Pin = A6;
-int diod4Pin = A7;
+int diod3Pin = A5;
+int diod4Pin = A5;

 bool collecting = true;
 int collectedPoints = 0;
-int numberOfCollections = 500;
+int numberOfCollections = 5;
 int numDataPoints = numberOfCollections * 4;
 double** dataPoints;

 enum Direction {FORWARD, BACKWARD};

-int aprintf(char *str, ...) {
-	int i, j, count = 0;
-
-	va_list argv;
-	va_start(argv, str);
-	for(i = 0, j = 0; str[i] != '\0'; i++) {
-		if (str[i] == '%') {
-			count++;
-
-			Serial.write(reinterpret_cast<const uint8_t*>(str+j), i-j);
-
-			switch (str[++i]) {
-				case 'd': Serial.print(va_arg(argv, int));
-					break;
-				case 'l': Serial.print(va_arg(argv, long));
-					break;
-				case 'f': Serial.print(va_arg(argv, double));
-					break;
-				case 'c': Serial.print((char) va_arg(argv, int));
-					break;
-				case 's': Serial.print(va_arg(argv, char *));
-					break;
-				case '%': Serial.print("%");
-					break;
-				default:;
-			};
-
-			j = i+1;
-		}
-	};
-	va_end(argv);
-
-	if(i > j) {
-		Serial.write(reinterpret_cast<const uint8_t*>(str+j), i-j);
-	}
-
-	return count;
-}
+void setup() {
+  Serial.begin(9600);

-void setup() {
-	Serial.begin(9600);
+  pinMode(enablePin_1, OUTPUT);
+  pinMode(in1Pin_1, OUTPUT);
+  pinMode(in2Pin_1, OUTPUT);
+  pinMode(enablePin_2, OUTPUT);
+  pinMode(in3Pin_2, OUTPUT);
+  pinMode(in4Pin_2, OUTPUT);

-	pinMode(enablePin_1, OUTPUT);
-	pinMode(in1Pin_1, OUTPUT);
-	pinMode(in2Pin_1, OUTPUT);
-	pinMode(enablePin_2, OUTPUT);
-	pinMode(in3Pin_2, OUTPUT);
-	pinMode(in4Pin_2, OUTPUT);
+  digitalWrite(diod1Pin, HIGH);
+  digitalWrite(diod2Pin, HIGH);
+  digitalWrite(diod3Pin, HIGH);
+  digitalWrite(diod4Pin, HIGH);

-	digitalWrite(diod1Pin, HIGH);
-	digitalWrite(diod2Pin, HIGH);
-	digitalWrite(diod3Pin, HIGH);
-	digitalWrite(diod4Pin, HIGH);
-
-	dataPoints = (double**)calloc(numDataPoints, sizeof(double*));
-
-	Serial.println("Car initialized, ready to go!");
+  // dataPoints = (double**)calloc(numDataPoints, sizeof(double*));
+  // for (int i = 0; i < numDataPoints; i++)
+  // {
+  //   dataPoints[i] = (double*) calloc(1, sizeof(double));
+  // }
+  dataPoints = (double **)malloc(numDataPoints * sizeof(double *));
+  for (int i = 0; i < numDataPoints; i++) {
+    dataPoints[i] = (double *)malloc(1 * sizeof(double));
+  }
+  Serial.println("Car initialized, ready to go!");
 }

 void loop() {
-	Serial.println("loop");
-	if (collecting && collectedPoints <= numberOfCollections) {
-		/*driveRandom();*/
-		collectIntialData();
-		collectedPoints++;
-		delay(100);
-	} else if (collecting) {
-		computeMeans();
-		collecting = false;
-	} else {
-		mainLoop();
-	}
-
+  if (collecting && collectedPoints <= numberOfCollections) {
+    /*driveRandom();*/
+    collectIntialData();
+    collectedPoints++;
+  } else if (collecting) {
+    computeMeans();
+    collecting = false;
+  } else {
+    mainLoop();
+  }
+  delay(300);
 }

 void mainLoop() {
-	// RotateLeft(1000);
-	// RotateRight(1000);
-	// RotateLeft(1000);
-	// RotateRight(1000);
-	// Stop();
-	// delay(2000);
-	delay(2000);
+  // RotateLeft(1000);
+  // RotateRight(1000);
+  // RotateLeft(1000);
+  // RotateRight(1000);
+  // Stop();
+  // delay(2000);
+  delay(2000);
 }

 void Forward(int time)
 {
   Serial.println("move forward");
-	setMotors(DEFAULT_SPEED, FORWARD);
-	delay(time);
-	Stop();
-	delay(STOP_TIME);
+  setMotors(DEFAULT_SPEED, FORWARD);
+  delay(time);
+  Stop();
+  delay(STOP_TIME);
   /*digitalWrite(motor1PinA, HIGH);
   digitalWrite(motor1PinB, LOW);
   digitalWrite(motor2PinA, HIGH);
@@ -128,10 +94,10 @@
 void Backward(int time) // inverse voltage of both motors
 {
   Serial.println("move backward");
-	setMotors(DEFAULT_SPEED, BACKWARD);
-	delay(time);
-	Stop();
-	delay(STOP_TIME);
+  setMotors(DEFAULT_SPEED, BACKWARD);
+  delay(time);
+  Stop();
+  delay(STOP_TIME);
   /*digitalWrite(motor1PinA, LOW);
   digitalWrite(motor1PinB, HIGH);
   digitalWrite(motor2PinA, LOW);
@@ -141,11 +107,11 @@
 void RotateLeft(int time) // inverse voltage of only one motor
 {
   Serial.println("rotate left");
-	setMotorLeft(DEFAULT_SPEED, BACKWARD);
-	setMotorRight(DEFAULT_SPEED, FORWARD);
-	delay(time);
-	Stop();
-	delay(STOP_TIME);
+  setMotorLeft(DEFAULT_SPEED, BACKWARD);
+  setMotorRight(DEFAULT_SPEED, FORWARD);
+  delay(time);
+  Stop();
+  delay(STOP_TIME);
   /*digitalWrite(motor1PinA, LOW);
   digitalWrite(motor1PinB, HIGH);
   digitalWrite(motor2PinA, HIGH);
@@ -155,11 +121,11 @@
 void RotateRight(int time) // inverse voltage of only one motor
 {
   Serial.println("rotate right");
-	setMotorLeft(DEFAULT_SPEED, FORWARD);
-	setMotorRight(DEFAULT_SPEED, BACKWARD);
-	delay(time);
-	Stop();
-	delay(STOP_TIME);
+  setMotorLeft(DEFAULT_SPEED, FORWARD);
+  setMotorRight(DEFAULT_SPEED, BACKWARD);
+  delay(time);
+  Stop();
+  delay(STOP_TIME);
 }

 void Stop()
@@ -174,52 +140,57 @@
 }

 void setMotors(int speed, int direction) {
-	setMotorLeft(speed, direction);
-	setMotorRight(speed, direction);
+  setMotorLeft(speed, direction);
+  setMotorRight(speed, direction);
 }

 void setMotorLeft(int speed, int direction) {
-	int controlBit = direction == FORWARD ? 1 : 0;
+  int controlBit = direction == FORWARD ? 1 : 0;
   analogWrite(enablePin_1, speed);
   digitalWrite(in1Pin_1, controlBit);
   digitalWrite(in2Pin_1, ! controlBit);
 }

 void setMotorRight(int speed, int direction) {
-	int controlBit = direction == FORWARD ? 1 : 0;
+  int controlBit = direction == FORWARD ? 1 : 0;
   analogWrite(enablePin_2, speed);
   digitalWrite(in3Pin_2, ! controlBit);
   digitalWrite(in4Pin_2, controlBit);
 }

 void computeMeans() {
-	int dimension = 1;
-	int clusters = 3;
-	double errorTolerance = 0.01;
-	double** centroids = (double**)calloc(clusters, sizeof(double*));
+  int dimension = 1;
+  int clusters = 3;
+  double errorTolerance = 0.01;
+  double** centroids = (double**)calloc(clusters, sizeof(double*));

-	int* labels = k_means(dataPoints, numDataPoints, dimension, clusters, errorTolerance, centroids);
-	for (int i = 0; i < numDataPoints; i++) {
-		aprintf("data point %d is in cluster %d\n", dataPoints[i][0]	, labels[i]);
-	}
-	free(labels);
-	free(centroids);
+  int* labels = k_means(dataPoints, numDataPoints, dimension, clusters, errorTolerance, centroids);
+  for (int i = 0; i < numDataPoints; i++) {
+    char string[100];
+    sprintf(string, "data point %f is in cluster %f\n", (float)dataPoints[i][0], (float)labels[i]);
+    Serial.println(string);
+  }
+  free(labels);
+  free(centroids);
 }

 void collectIntialData() {
-	int* values = getSensorValues();
-	dataPoints[collectedPoints][0] = (double) values[0];
-	dataPoints[collectedPoints + 1][0] = (double) values[1];
-	dataPoints[collectedPoints + 2][0] = (double) values[2];
-	dataPoints[collectedPoints + 3][0] = (double) values[3];
+  int* values = getSensorValues();
+  // dataPoints[collectedPoints][0] = (double) values[0];
+  // dataPoints[collectedPoints + 1][0] = (double) values[1];
+  // dataPoints[collectedPoints + 2][0] = (double) values[2];
+  // dataPoints[collectedPoints + 3][0] = (double) values[3];
 }

 int* getSensorValues() {
-	int values[4];
-	values[0] = analogRead(diod1Pin);
-	values[1] = analogRead(diod2Pin);
-	values[2] = analogRead(diod3Pin);
-	values[3] = analogRead(diod4Pin);
-	Serial.println("" + values[0] + values[1] + values[2] + values[3]);
-	return values;
+  int values[4];
+  values[0] = analogRead(diod1Pin);
+  values[1] = analogRead(diod2Pin);
+  values[2] = analogRead(diod3Pin);
+  values[3] = analogRead(diod4Pin);
+
+  char string[100];
+  sprintf(string, "sensor values: %d, %d, %d and %d", values[0], values[1], values[2], values[3]);
+  Serial.println(string);
+  return values;
 }


Finally! found the reason for PWM wave not matching the calculated grid. PWM frequencies are not 500/1000Hz but 488/976Hz so the pulses are longer. Documenting this.

--- tiny_scope.ino
+++ tiny_scope.ino
@@ -2,6 +2,7 @@
  * Tiny Scope for Arduino
  * (C)2015 Laurentiu Badea
  */
+#include <Arduino.h>
 #if 0
 #include <SPI.h>
 #include <Wire.h>
@@ -52,9 +53,17 @@
         display.print(F("Out of memory!"));
     }
     display.display();
-    // set up PWM outputs for testing
-    analogWrite(9, 64); // 500Hz 0.5ms pulse,  2ms period
-    analogWrite(5, 64); // 1KHz  0.25ms pulse, 1ms period
+    /*
+     * set up PWM outputs for testing:
+     * Read http://playground.arduino.cc/Code/PwmFrequency on influence on millis(), delay() etc
+     * short: we should really only change 9 or 10 base freq
+     * pins 3, 9, 10, and 11: base 31250Hz / 64 = 488Hz
+     * pins 5, 6: base 62500 Hz / 64 = 976Hz
+     */
+    pinMode(9, OUTPUT);
+    pinMode(5, OUTPUT);
+    analogWrite(9, 64); // 488Hz 0.512ms pulse, 2.05ms period
+    analogWrite(5, 64); // 976Hz 0.255ms pulse, 1.02ms period
 }

 void loop(){


these are not the correct constants but define them anyway so we might remember to define them

--- arduino/motors_ahrs/motors_ahrs.ino
+++ arduino/motors_ahrs/motors_ahrs.ino
@@ -1,4 +1,14 @@
 // Motor controller and AHRS for Urpobotti
+
+
+// LSM303 magnetometer calibration constants; use the Calibrate example from
+// the Pololu LSM303 library to find the right values for your board
+#define M_X_MIN -421
+#define M_Y_MIN -639
+#define M_Z_MIN -238
+#define M_X_MAX 424
+#define M_Y_MAX 295
+#define M_Z_MAX 472

 // IMU https://www.pololu.com/product/1265 (links to the gyro and compass libs)
 // AHRS library: https://github.com/rambo/MinIMU-9-Arduino-AHRS


Delete arduino_example.ino

Delete arduino_example.ino

--- arduino_example/arduino_example.ino
+++ arduino_example/arduino_example.ino
@@ -1,25 +0,0 @@
-void setup()
-  {
-    //Setting pins
-    pinMode(0,OUTPUT);
-    pinMode(1,OUTPUT);
-    pinMode(3,INPUT);
-  }
-void loop()
-  {
-    //Read value from sensor 2
-    if (digitalRead(3)==1)
-      {
-        //Turn of motor A
-        digitalWrite(1,LOW);
-        //Turn on motor B
-        digitalWrite(0,HIGH);
-      }
-    else
-      {
-        //Turn of motor B
-        digitalWrite(0,LOW);
-        //Turn on motor A
-        digitalWrite(1,HIGH);
-      }
-  }


Demo.ino: Turn on the yellow LED before the user's first button press so that we can tell if this program is running without plugging in an LCD.

--- examples/Demo/Demo.ino
+++ examples/Demo/Demo.ino
@@ -687,6 +687,8 @@
     buzzer.playFromProgramSpace(beepWelcome);
   }

+  ledYellow(1);
+
   lcd.clear();
   lcd.print(F("  Romi"));
   lcd.gotoXY(2, 1);
@@ -712,6 +714,8 @@
   lcd.print(F("-try it!"));

   while (buttonMonitor() != 'B'){}
+
+  ledYellow(0);

   buzzer.playFromProgramSpace(beepThankYou);
   lcd.clear();


Output information on a LEONARDO board by using the #define SERIAL_DEBUG definition.


rewrite

rewrite

--- snake.ino
+++ snake.ino
@@ -1,9 +1,7 @@
-#include <stdlib.h>
-#include <stdio.h>
 #include <SPI.h>
-//#include <SD.h>
 #include <TFT.h>
-
+#include "structworkaround.h"
+
 /* TFT pins */
 #define LCD_CS   10
 #define SD_CS 4
@@ -11,153 +9,38 @@
 #define RESET  8

 /* Pushbutton pins */
-#define pbLeft 7
-#define pbDown 6
-#define pbUp 3
-#define pbRight 2
-
-/***********************************************************************
- * VARIABLES
- */
-
-TFT myScreen = TFT(LCD_CS, DC, RESET);  /* x: 0-160  y: 0-128 */
-
-int screenWidth = myScreen.width();
-int screenHeight = myScreen.height();
-int tileSize = 6;
-
-long timestamp;
-int growBy = 0;
+#define PBLEFT 7
+#define PBDOWN 6
+#define PBUP 3
+#define PBRIGHT 2
+
+#define screenWidth 160
+#define screenHeight 128
+#define tileSize 6
+
+
+TFT screen = TFT(LCD_CS, DC, RESET);
+
+long timestamp = 0;
+int score = 0;
 int collision = 0;
-int score = 0;
-char scoreChars[5];
-
-
-struct colour_struct{
-  int r,g,b;
-};
-typedef struct colour_struct colour;
+int goX = 0;
+int goY = 0;

 colour bgCol = {93,200,255};
 colour snakeCol = {245, 78, 253};
 colour foodCol = {253,230,62};

-struct coord_struct{
-  unsigned char x,y;
-  struct coord_struct *next_ptr;
-};
-typedef struct coord_struct coord;
-
 coord *new_ptr;
 coord *temp;
 coord *head = NULL;

-coord moveTo = {0,0};
-coord foodTile = {5,4};
-
-/***********************************************************************
- * FUNCTIONS
+/*****************************************************************
+ *  FUNCTIONS
  */
-void newFoodTile(){
-
-  foodTile.x = int(5 + (random(0,24)*6));
-  foodTile.y = int(4 + (random(0,19)*6));
-}
-
-void startScreen(){
-  /* Reset variables/everything */
-  foodTile.x = 5;
-  foodTile.y = 4;
-  collision = 0;
-  score = 0;
-  while(head){
-    remLast();
-  }
-  moveTo.x = 0;
-  moveTo.y = 0;
-  int score = 0;
-  int growBy = 0;
-
-  /* Title */
-//  PImage image;
-/*  image = myScreen.loadImage("startscreen.bmp"); */
-//  myScreen.image(image, 0, 0);
-
-  myScreen.background(245, 78, 253);
-  myScreen.setTextSize(4);
-  myScreen.stroke(255,255,255);
-  myScreen.text("Snake",10,10);
-  myScreen.setTextSize(1);
-  myScreen.text("press button to start",10, 80);
-
-  while (moveTo.x == 0 && moveTo.y == 0){
-    getInput();
-    delay(5);
-  }
-
-  /* Background and framing */
-  myScreen.stroke(0,0,0);
-  myScreen.fill(bgCol.r,bgCol.g,bgCol.b);
-  myScreen.rect(3,2,screenWidth-6,screenHeight-4);
-
-  /* The snake and food data before the game starts */
-  for (int i = 29; i<=53; i+=6){
-    addFirst(i,52);
-    drawSegment(head->x, head->y);
-  }
-
-  /* TODO: "random placement, not on forbidden tiles"-function */
-//  foodTile.x = 5;
-//  foodTile.y = 4;
-  newFoodTile();
-  drawFood(foodTile.x, foodTile.y);
-}
-
-
-
-/* Input the incremental move using the pushbuttons */
-void getInput(){
-    if (digitalRead(pbLeft) == HIGH){
-      moveTo.x = -tileSize;
-      moveTo.y = 0;
-    }
-    else if (digitalRead(pbDown) == HIGH){
-      moveTo.x = 0;
-      moveTo.y = tileSize;
-    }
-    else if (digitalRead(pbUp) == HIGH){
-      moveTo.x = 0;
-      moveTo.y = -tileSize;
-    }
-    else if (digitalRead(pbRight) == HIGH){
-      moveTo.x = tileSize;
-      moveTo.y = 0;
-    }
-}
-
-/* Draw a segment of the snake */
-void drawSegment(int x, int y){
-  myScreen.noStroke();
-  myScreen.fill(snakeCol.r, snakeCol.g, snakeCol.b);
-  myScreen.rect(x,y,tileSize,tileSize);
-}
-
-/* Draw a food */
-void drawFood(int x, int y){
-  myScreen.noStroke();
-  myScreen.fill(foodCol.r, foodCol.g, foodCol.b);
-  myScreen.rect(x,y,tileSize,tileSize);
-}
-
-/* "Erase" a segment of the snake */
-void remSegment(int x, int y){
-  myScreen.noStroke();
-  myScreen.fill(bgCol.r, bgCol.g, bgCol.b);
-  myScreen.rect(x,y,tileSize,tileSize);
-}
-
-/* Add x and y as a coord first in the linked list */
-void addFirst(int x, int y){
+
+void
+addFirst(int x, int y){
     new_ptr = (coord *)malloc(sizeof(coord));
     new_ptr->x = x;
     new_ptr->y = y;
@@ -165,8 +48,8 @@
     head = new_ptr;
 }

-/* Remove the last item in the linked list */
-void remLast(){
+void
+remLast(){
   coord *last;
   temp = head;
   last = temp;
@@ -178,113 +61,160 @@
     free(temp);
     head = NULL;
   } else {
-    remSegment(temp->x,temp->y);
+    drawRect(temp->x,temp->y,bgCol); /* draw */
     free(last->next_ptr);
     last->next_ptr = NULL;
   }
 }
-
-/* Check if a coordinate exist in the linked list */
-int isMember(int x, int y){
-   temp = head->next_ptr;
-   while(temp){
-     if (temp->x == x && temp->y ==y){
-       return 1;
-     }
-     temp = temp->next_ptr;
-   }
-   return 0;
-}
-
-/* Check if the snake head is on a foodTile and should grow */
-int isGrow(){
-  if(head->x == foodTile.x && head->y == foodTile.y){
-   return 1;
+
+void
+startScreen(){
+  reset();
+
+  screen.background(245, 78, 253);
+  screen.setTextSize(4);
+  screen.stroke(0,255,0);
+  screen.text("Snake",10,10);
+  screen.setTextSize(1);
+  screen.text("press button to start",10, 80);
+
+  while (goX == 0 && goY == 0){
+    getInput();
+    delay(5);
+  }
+
+  screen.stroke(0,0,0);
+  screen.fill(bgCol.r,bgCol.g,bgCol.b);
+  screen.rect(3,2,screenWidth-6,screenHeight-4);
+
+  for (int i = 29; i<=53; i+=6){
+    addFirst(i,52);
+    drawRect(head->x, head->y,snakeCol);
+  }
+
+  putFood();
+}
+
+void
+reset(){
+  goX = 0;
+  goY = 0;
+  collision = 0;
+  score = 0;
+  while(head){
+    remLast();
+  }
+}
+
+void
+getInput(){
+    if (digitalRead(PBLEFT) == HIGH){
+      goX = -tileSize;
+      goY = 0;
+    }
+    else if (digitalRead(PBDOWN) == HIGH){
+      goX = 0;
+      goY = tileSize;
+    }
+    else if (digitalRead(PBUP) == HIGH){
+      goX = 0;
+      goY = -tileSize;
+    }
+    else if (digitalRead(PBRIGHT) == HIGH){
+      goX = tileSize;
+      goY = 0;
+    }
+}
+
+int
+isGrow(){
+  if(head->x == food.x && head->y == food.y){
+    return 1;
   } else {
     return 0;
   }
 }

-/* Check if the snake head is on a forbidden tile and should die :/ */
-int isCollision(){
-  if (isMember(head->x,head->y)){
-    return 1;
+int
+isCollision(){
+  temp = head->next_ptr;
+  while(temp){
+    if (temp->x == head->x && temp->y == head->y){
+      return 1;
+    }
+    temp = temp->next_ptr;
   }
   if(head->x < 5 || head->x > 149 || head->y < 4 || head->y > 118){
     return 1;
   }
   return 0;
 }
-
-/* Print score etc before starting over */
-void endScreen(){
-  myScreen.background(0, 255, 0);
-  myScreen.stroke(255,255,255);
+
+void
+putFood(){
+  int validPlace = 0;
+  while (!validPlace){
+    food.x = 5 + (int)random(0,24)*6;
+    food.y = 4 + (int)random(0,19)*6;
+    if (food.x != head->x && food.y != head->y){
+      validPlace = 1;
+    }
+  }
+  drawRect(food.x, food.y, foodCol);
+}
+
+void
+drawRect(int x, int y, colour c){
+  screen.noStroke();
+  screen.fill(c.r, c.g, c.b);
+  screen.rect(x,y,tileSize,tileSize);
+}
+
+void
+endScreen(){
+  char scoreChars[5];
+  screen.background(0, 255, 0);
+  screen.stroke(255,255,255);
   String scorestring = String(score);
   scorestring.toCharArray(scoreChars,5);

-  myScreen.text("Game over", 40, 40);
-  myScreen.text("Score:", 40, 50);
-  myScreen.text(scoreChars, 80, 50);
-
-  delay(1000);
-}
-
-/***********************************************************************
- * SETUP
- */
-
-void setup(){
-  myScreen.begin();
-//  SD.begin(SD_CS);
+  screen.text("Game over", 40, 40);
+  screen.text("Score:", 40, 50);
+  screen.text(scoreChars, 80, 50);
+  delay(1000);
+}
+
+void
+setup(){
+  screen.begin();
   randomSeed(analogRead(0));
 }

-/***********************************************************************
- * LOOP
- */
-
-void loop(){
-
+void
+loop(){
   startScreen();
-  /* Main brain game frame */
-  while(!collision){
-
-    /* Pushbutton input */
+  while (!collision){
     getInput();
-    delay(5); /* Just to be kind to the CPU */
-
-    if (millis()-timestamp > 100){
-      /* Update, draw, and check things */
-      coord movetemp;
-      movetemp.x = head->x + moveTo.x;
-      movetemp.y = head->y + moveTo.y;
-
-      addFirst(movetemp.x,movetemp.y);
-
-      /* Draw */
-      drawSegment(head->x, head->y);
-      if (growBy){
-        growBy--;
-        score += 1;
+    delay(5);
+    if (millis()-timestamp > 200){
+      addFirst((head->x + goX), (head->y + goY));
+      drawRect(head->x,head->y,snakeCol);
+      if (food.growBy){
+        food.growBy--;
+        score += 1;
       }
       else {
         remLast();
       }
-
       if (isGrow()){
-        growBy++;
-        newFoodTile();
-        drawFood(foodTile.x, foodTile.y);
-      }
-
+        food.growBy++;
+        putFood();
+      }
       if (isCollision()){
         collision = 1;
       }
       timestamp = millis();
     }
   }
-
-  endScreen();
-  delay(2000); /* TODO: pause until button is pressed */
-}
+  endScreen();
+}


enable stepper step counting and transmit stepper and encoder steps to see if slip detection is practical

--- arduino/motor_driver/motor_driver.ino
+++ arduino/motor_driver/motor_driver.ino
@@ -119,9 +119,11 @@

 unsigned long lastmicros = micros();
+long laststepperpos = 0, lastencoder0Pos = 0;
 int printcounter = 0;

 void loop(){
+  // PID loop
   pidInput = encoder0Pos;
   if (abs(pidInput-pidSetpoint) < CLOSE_ENOUGH) {
     goalSpeed = 0;
@@ -131,19 +133,33 @@
     goalSpeed = pidOutput;
   }

-
+  // update speed taking acceleration limit into account
   unsigned long dt = micros() - lastmicros;
   lastmicros = micros();

   updateSpeed(dt);

+
+  // check for slip
+  long stepper_steps_this_update = stepperpos - laststepperpos;
+  laststepperpos = stepperpos;
+
+  long encoder_steps_this_update = encoder0Pos - lastencoder0Pos;
+  lastencoder0Pos = encoder0Pos;
+
+
+
+
+
+
   // check for incoming messages
   etherOSC.listen();

+  // send updates
   if (printcounter==0) {
-    sendOscStatus();
+    sendOscStatus(stepper_steps_this_update, encoder_steps_this_update);
   }
   if (printcounter++ > 100) printcounter = 0;

@@ -200,7 +216,7 @@
   Timer1.pwm(PULSEPIN, 0);
   Timer1.start();

-  //Timer1.attachInterrupt(countSteps);
+  Timer1.attachInterrupt(countSteps);
 }

@@ -322,13 +338,15 @@

 // send status message

-void sendOscStatus() {
+void sendOscStatus(long stepper, long encoder) {
   OscMessage msg("/status");

   msg.add(MOTOR_ID);
   msg.add("OK");
   msg.add((float)encoder0Pos);
   msg.add(currentSpeed);
+  msg.add(stepper);
+  msg.add(encoder);

   etherOSC.send(msg, destination);
 }


Update ArduCAM_Mini_4CAM_VideoStreaming.ino

--- ArduCAM/examples/mini/ArduCAM_Mini_4CAM_VideoStreaming/ArduCAM_Mini_4CAM_VideoStreaming.ino
+++ ArduCAM/examples/mini/ArduCAM_Mini_4CAM_VideoStreaming/ArduCAM_Mini_4CAM_VideoStreaming.ino
@@ -71,7 +71,24 @@
 digitalWrite(CS4, HIGH);

 // initialize SPI:
-SPI.begin();
+SPI.begin();
+//Reset the CPLD
+myCAM1.write_reg(0x07, 0x80);
+delay(100);
+myCAM1.write_reg(0x07, 0x00);
+delay(100);
+myCAM2.write_reg(0x07, 0x80);
+delay(100);
+myCAM2.write_reg(0x07, 0x00);
+delay(100);
+myCAM3.write_reg(0x07, 0x80);
+delay(100);
+myCAM3.write_reg(0x07, 0x00);
+delay(100);
+myCAM4.write_reg(0x07, 0x80);
+delay(100);
+myCAM4.write_reg(0x07, 0x00);
+delay(100);

 while(1){
   //Check if the 4 ArduCAM Mini 2MP Cameras' SPI bus is OK


taking serial commands for evening or morning mode

--- circadian_hallway_cycle_colors/circadian_hallway_cycle_colors.ino
+++ circadian_hallway_cycle_colors/circadian_hallway_cycle_colors.ino
@@ -96,6 +96,8 @@
   analogWrite(GRN_PIN, 0);
   analogWrite(RED_PIN, 0);
   analogWrite(BLU_PIN, 0);
+
+  Serial.begin(9600);
 }

 void loop()
@@ -114,6 +116,22 @@
     color();
   }

+  while (Serial.available() > 0) {
+    int red = Serial.parseInt();
+    int green = Serial.parseInt();
+    int blue = Serial.parseInt();
+    if (Serial.read() == '\n') {
+      if (red == 255) {
+        turn_on_evening_colors();
+      }
+      if (blue == 255) {
+        turn_on_morning_colors();
+      }
+      Serial.print(red, HEX);
+      Serial.print(green, HEX);
+      Serial.println(blue, HEX);
+    }
+  }
 }

 void LED()


Add switch to override turning off the router

--- RouterReset_Yun/RouterReset_Yun.ino
+++ RouterReset_Yun/RouterReset_Yun.ino
@@ -3,7 +3,9 @@
  * red LED (internet down): pin 3
  * green LED (internet up): pin 5
  * yellow LED (testing):    pin 6
- *
+ * blue LED (router on):    pin 8
+ * power switch tail:       pin 9
+ * switch:                  pin 12
  *
  * needs checkInternet.py installed in /usr/bin in Yun Linino
  */
@@ -15,8 +17,11 @@
 const int yellowLED  = 6;
 const int routerPin1 = 8;
 const int routerPin2 = 9;
-const int resetRouterTime = 30000;
-const int timeBetweenPings = 5000;
+const int resetRouterTimeSec = 30;
+const int secBetweenPings_Up = 5;
+const int secBetweenPings_Down = 1;
+const int startUpDelaySec = 5;
+const int switchPin = 12;

 String internetStatus;

@@ -28,13 +33,15 @@
     pinMode(routerPin2, OUTPUT);
     digitalWrite(routerPin1, HIGH);
     digitalWrite(routerPin2, HIGH);
+    pinMode(switchPin, INPUT);
+    digitalWrite(switchPin, HIGH);

     Bridge.begin();  // make contact with the linux processor

     digitalWrite(redLED, HIGH);
     digitalWrite(greenLED, HIGH);
     digitalWrite(yellowLED, HIGH);
-    delay(5000);
+    delay(startUpDelaySec*1000);
     digitalWrite(redLED, LOW);
     digitalWrite(greenLED, LOW);
     digitalWrite(yellowLED, LOW);
@@ -44,6 +51,7 @@
     Process internetCheck;

     digitalWrite(yellowLED, HIGH);
+
     internetCheck.runShellCommand("/usr/bin/checkInternet.py");

     internetStatus = "";
@@ -65,16 +73,24 @@

     digitalWrite(yellowLED, LOW);

-    if(internetStatus[0] == '0')
+    if(internetStatus[0] == '0') {
         resetRouter();
+        delay(secBetweenPings_Down*1000);
+    }
     else
-        delay(timeBetweenPings);
+        delay(secBetweenPings_Up*1000);
 }

-void resetRouter(void) {
-  digitalWrite(routerPin1, LOW);
-  digitalWrite(routerPin2, LOW);
-  delay(resetRouterTime);
-  digitalWrite(routerPin1, HIGH);
-  digitalWrite(routerPin2, HIGH);
+void resetRouter() {
+  if(digitalRead(switchPin) == HIGH) {
+    digitalWrite(routerPin1, LOW);
+    digitalWrite(routerPin2, LOW);
+    for(int i=0; i<resetRouterTimeSec; i++) {
+      if(digitalRead(switchPin) == LOW) break;
+      delay(1000);
+    }
+    digitalWrite(routerPin1, HIGH);
+    digitalWrite(routerPin2, HIGH);
+    delay(resetRouterTimeSec*1000);
+  }
 }


Turned off autocalibration

Turned off autocalibration


all reads are now prefixed with R

all reads are now prefixed with R


Update plant_emoji.ino

Update plant_emoji.ino

--- projects/arduino/plant_emoji/src/plant_emoji/plant_emoji.ino
+++ projects/arduino/plant_emoji/src/plant_emoji/plant_emoji.ino
@@ -64,6 +64,7 @@
   pinMode(dataIn, OUTPUT);
   pinMode(clock, OUTPUT);
   pinMode(load, OUTPUT);
+  pinMode(A0, INPUT);

   maxAll(max7219_reg_scanLimit, 0x07);
   maxAll(max7219_reg_decodeMode, 0x00);


Use a string generated in a character buffer for the content length so we can use fastrprint. This is another attempt to fix the mysterious freezing.

--- SimpleCSV.ino
+++ SimpleCSV.ino
@@ -110,6 +110,10 @@
     (uint32_t)file->fileSize() + 2 + // file data + crlf
     FORM_BOUNDARY_END_SIZE;

+  char totalContentLengthString[12];
+  byte length = cbPrintInt(totalContentLengthString, (int)totalContentLength, 0);
+  totalContentLengthString[length] = '\0';
+
   if (www.connected()) {
     www.fastrprint(F("POST "));
     www.fastrprint(CSV_WEBPAGE);
@@ -118,7 +122,7 @@
     www.fastrprint(hostname);
     www.fastrprint(F("\r\nAuthorization: Basic a2Vnc2NyaWJlOnRlc3Q="));
     www.fastrprint(F("\r\nContent-Length: "));
-    www.print(totalContentLength);
+    www.fastrprint(totalContentLengthString);
     www.fastrprint(F("\r\nContent-Type: multipart/form-data; boundary="));
     www.fastrprint(FORM_BOUNDARY_BASE);
     www.fastrprint(F("\r\n"));


Fixed query output

Fixed query output

--- arduino/semSim/semSim.ino
+++ arduino/semSim/semSim.ino
@@ -22,6 +22,7 @@
   *************
   Special Chars
   *************
+  TODO: Verify and fix the line feeds with the scope.

   <LF> ('\n') (Line feed, '\n', 0x0A, 10 in decimal <----
   <CR> ('\r') (Carriage return, '\r', 0x0D, 13 in decimal)
@@ -32,7 +33,7 @@
 String inputCommand = ""; // A string to capture the command before the space
 String inputValue = "";  // A string to capture command value after space
 String inputString = ""; // The raw Readline string
-String testString = ""; // Used for string testing/
+String testString = ""; // Used for string testing
 String simVar = "10"; // TODO: Set up a larger bank of sim variables

 boolean stringComplete = false;  // whether the string is complete
@@ -84,7 +85,7 @@
         if (com && val) {
           Serial.println("!0");
         } else {
-          Serial.println("!0 " + simVar);
+          Serial.println("!0 " + inputCommand + " " +  simVar);
         }
         break;
       case 3:   // Format Error


CaptivePortalAdvanced fix #1718

CaptivePortalAdvanced fix #1718

--- libraries/DNSServer/examples/CaptivePortalAdvanced/handleHttp.ino
+++ libraries/DNSServer/examples/CaptivePortalAdvanced/handleHttp.ino
@@ -6,6 +6,7 @@
   server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
   server.sendHeader("Pragma", "no-cache");
   server.sendHeader("Expires", "-1");
+  server.setContentLength(CONTENT_LENGTH_UNKNOWN);
   server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
   server.sendContent(
     ""
@@ -40,6 +41,7 @@
   server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
   server.sendHeader("Pragma", "no-cache");
   server.sendHeader("Expires", "-1");
+  server.setContentLength(CONTENT_LENGTH_UNKNOWN);
   server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
   server.sendContent(
     ""


Better timing using millis()

Better timing using millis()

--- OpenROV.ino
+++ OpenROV.ino
@@ -6,28 +6,53 @@

 int speed_offset = 31, l = 0, MIDPOINT = 128,
     p = MIDPOINT, v = MIDPOINT, s = MIDPOINT, t = MIDPOINT;
-
-int count;
+
+unsigned long startTime = millis();  //  time based on hardware register - Timer #0
+unsigned long interval1 = 1000; // one second interval
+int interval2 = 10; // multiple of interval1
+long count = 0; // counter for interval2
+unsigned long lastTime = 0;  // use for holding time of last interval
+
+int pin_read = 0; //  holds value of analog read
+float voltage = 0;  //  holds scaled value of voltage - adjusted for voltage divider
+float scale = 15.0/1023.0;  // scale factor for 3 to 1 voltage divider - 15V reduced to 5V
+
+// Note - this will not be neede for ROV pc board
+// led on pin 19 of ATmega328 breadboard to indicate if program is running - connected to pin 13 on Arduino boards
+int led = 13;
+int blink = 0;  // toggle to blink on/off - period = interval

 void setup(){
+
+  Serial.begin(9600);
+
+  Serial.println();
+  Serial.println("Begin");

-  Serial.begin(9600);
-
+  // Output elapsed time
+  elapsed_time_output(startTime);
+
   tilt.attach(5);
   light.attach(6);
   port.attach(9);
   vertical.attach(10);
   starbord.attach(11);

-  count = 0;
+
+  // initialize the digital pin as an output for led blink
+  pinMode(led, OUTPUT);
+
 }

 void loop(){
+
+
   // ========================================================================================
   // ========================================================================================
   // Get commands from OpenROV
   // ========================================================================================
   // ========================================================================================
+

   if (Serial.available()) {
     delay(30); // number of characters to be read?  buffer delay (TODO:  affects timing of sensors... fix this?)
@@ -83,18 +108,39 @@
   // Write commands to OpenROV
   // ========================================================================================
   // ========================================================================================
+
+// TODO: make these actually do something, just testing for now
+  // once every interval1
+  if (millis() - lastTime > interval1){
+    lastTime = millis();  // reset interval1 timer
+    count++; // increment interval2 count
+
+    if (blink == 0){
+      digitalWrite(led, HIGH);  // turn the led on (HIGH is the voltage level)
+      blink = 1;  // reset toggle
+    }
+    else{
+      digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
+      blink = 0;  // reset toggle
+    }
+
+    rov_analog_output(1, "float");  // output value
+  }

-  // TODO: make these actually do something, just testing for now
-  // once every 1,300 counts
-  if (count % 1300 == 0){
-    rov_analog_output(1, "float");
+  // once every interval2
+  if (count == interval2){
+    count=0;  // reset interval2 counter
+
+    // Output elapsed time
+    elapsed_time_output(startTime);
+
+    pin_read = analogRead(0);                 //  read voltage on pin 0 and output to serial port
+    voltage=pin_read*scale;                   //  15V will scale to 5V at analog in pin 0 with 3 to 1 voltage divider
+    Serial.print("Battery Voltage:");         //  Connect Battery output to analog pin 0 using voltage divider
+    Serial.println(voltage);                  //  Nominal Battery voltage is 12V - analog pin input 0-5V
+                                              //  Divide by 3 with voltage divider
+
   }
-  // once every 10,000 counts
-  if (count == 10000){
-    rov_analog_output(0, "salinity");
-    count = 0;  // reset counter (this should be done by the longest "running" counter
-  }
-  count++;
 }

 // Actually create and send command
@@ -112,4 +158,18 @@
   Serial.write(cmd_output);
   Serial.write(out);
   Serial.write(";");    // command delimiter
+  Serial.println();     // newline
 }
+
+// Output elapsed time
+void elapsed_time_output(unsigned long sTime){
+ #define SEC_PER_MIN 60
+ #define SEC_PER_HOUR 3600
+ unsigned long elapsedTime = (millis() - sTime)/1000;
+ Serial.print("Elapsed time is ");
+ Serial.print(elapsedTime/SEC_PER_HOUR);
+ Serial.print(":");
+ Serial.print((elapsedTime/SEC_PER_MIN) % SEC_PER_MIN);
+ Serial.print(":");
+ Serial.println(elapsedTime % SEC_PER_MIN);
+}


Added 'User-Agent' header to GitHub API calls.

https://developer.github.com/v3/#user-agent-required