Add encoding of message

Add encoding of message

--- mainWrite.ino
+++ mainWrite.ino
@@ -9,6 +9,7 @@
 Adafruit_TrellisSet trellis =  Adafruit_TrellisSet(&matrix0);

 uint16_t matrixValue;
+uint8_t matrixNibbles[4];

 uint8_t writeArduinoState; //TODO uint8_t?

@@ -26,6 +27,7 @@
   {38505, 6},
   {42405, 8}
 };
+uint8_t authenticatedUser;

 uint8_t userShift;

@@ -58,7 +60,7 @@
 }

 /*
- * Read trellis LEDs
+ * Read & Process trellis LEDs
  */

 void getMatrixInput() {
@@ -72,6 +74,22 @@
   }
 }

+uint32_t encodeNibble(uint16_t val, uint8_t k) {
+  uint8_t shift = validUserIDs[authenticatedUser][1];
+  return (((val >> (4*k)) + shift) % 16) & 0x0F;
+}
+
+uint16_t encodeMessage() {
+  uint16_t encodedMessage;
+
+  for (int i = 0; i < 4 ; i++) {
+    uint8_t position = (4*i);
+    encodedMessage = (encodeNibble(matrixValue, i) << position) | encodedMessage;
+  }
+
+  return encodedMessage;
+}
+
 /*
  *  Big Button Press and Big Button LED control
  */
@@ -97,9 +115,11 @@
   for (uint8_t i=0; i<(sizeof validUserIDs / sizeof validUserIDs[0]); i++) {
     if(matrixValue == validUserIDs[i][0]){
       userShift = validUserIDs[i][1];
+      authenticatedUser = i;
       return true;
     }
   }
+  authenticatedUser = 0;
   return false;
 }

@@ -123,6 +143,7 @@
       Serial.println("STATE_ACK");
       digitalWrite(LED_UID, LOW);
       digitalWrite(LED_MSG, LOW);
+      authenticatedUser = 0;
       break;
     default:
       break;
@@ -177,9 +198,9 @@
           updateReadArduinoStatus(STATE_MSG);
         } else {
           digitalWrite(LED_ERR, HIGH);
-          // updateErrorLED(INPUTSTATE);
-          // resetMatrix();
-          // stay in state 1
+          // updateErrorLED(INPUTSTATE); TODO
+          // resetMatrix(); TODO
+          // stay in state 1 TODO
         }
       }
       break;
@@ -187,10 +208,9 @@
       trellisButtonPress();
         if (isSubmitButtonPressed){
           getMatrixInput();
-        // encodeMessage();
-        // sendMessage();{
-        // updateReadArduinoStatus(INPUTSTATE);
-        // move to state 3
+          Serial.println(encodeMessage(), HEX);
+        // sendMessage();{ TODO
+          updateReadArduinoStatus(STATE_ACK);
         }
       break;
     case STATE_ACK: // Waiting for acknowledge
@@ -201,6 +221,7 @@
         // } else {
           // light error led
           // flash 4x4 a few times
+          updateReadArduinoStatus(STATE_UID);
           // move to state 1
         // }
       // }


Integrated compass code into C6 navigator

--- Elcano_C6_Navigator/Elcano_C6_Navigator.ino
+++ Elcano_C6_Navigator/Elcano_C6_Navigator.ino
@@ -1,11 +1,7 @@
-#include <Common.h>
-#include <IO.h>
-#include <Matrix.h>
-
 /*
 Elcano Module C6: Navigator.
   Includes C5 Obstacle detection.
-
+
 Documentation:
   NavigationSystem (TO DO: Write document, based on these comments).
   Wiring_C6Mega.xls
@@ -16,7 +12,7 @@

 It uses a variety of sensors, some of which may not be present or reliable.

-Yes: S1: Hall Odometer.  This unit gives wheel spin speed feedback.
+Yes: S1: Hall Odometer.  This unit gives wheel spin speed feedback.
 TO DO: Connect hardware and integrate into Kalman Filter

 Future: Visual Odometry from S4 (Smart camera) as passed though C7 (Visual Data
@@ -31,19 +27,19 @@

 Yes: Distance and bearing to landmarks / obstacles.

-Yes: S7: GPS.  GPS should not the primary navigation sensor and the robot should be
+Yes: S7: GPS.  GPS should not the primary navigation sensor and the robot should be
 able to operate indoors, in tunnels or other areas where GPS is not available
 or accurate.

-Sensed navigation information is passed to C3/C4, which use prexisting or SLAM
+Sensed navigation information is passed to C3/C4, which use prexisting or SLAM
 digital maps, intended path to refine the estimated position.
-C3/C4 may use a particle filter.
+C3/C4 may use a particle filter.
 C3/C4 may also receive lateral lane deviation from a camera (C7).

-The odometry sensor is one dimensional and gives the position along the
+The odometry sensor is one dimensional and gives the position along the
 intended path. Lane deviation is also one dimensional and gives position
 normal to the intended path. Odometry, lane following and a digital map
-should be sufficient for localization.  An odometer will drift. This drift
+should be sufficient for localization.  An odometer will drift. This drift
 can be nulled out by landmark recognition or GPS.

 An alternative to the Kalman Filter (KF) is fuzzy numbers.
@@ -54,16 +50,16 @@
 the position is known.

 GPS provides a pyramid aligned north-south and east-west, in contrast to
-odometry / lane deviation, which is a pyramid oriented in the direction of
+odometry / lane deviation, which is a pyramid oriented in the direction of
 vehicle motion. The intersection of two fuzzy sets is their minimum.
 By taking the minima of all position estimate pyramids, we get a surface
-describing the possible positions of the vehicle, whichcan be used by a
+describing the possible positions of the vehicle, whichcan be used by a
 particle filter.

 Serial lines:
 0: Monitor
 1: INU
-2: Tx: Estimated state;
+2: Tx: Estimated state;
       $C6EST,<east_mm>,<north_mm>,<speed_mmPs>,<bearing>,<time_ms><positionStndDev_mm>*CKSUM
       $C6OBS,<number>,<obstacle1_range_mm>,<obstacle1_bearing>, ...*CKSUM
    Rx: Desired course
@@ -76,9 +72,22 @@
   Tx: $PSRF103,...
 */

-/*---------------------------------------------------------------------------------------*/
-
+/*---------------------------------------------------------------------------------------*/
+
+#define MEGA
+#include <Common.h>
+#include <SPI.h>
 #include <SD.h>
+#include <IO.h>
+#include <Matrix.h>
+#include <Wire.h>
+#include "Adafruit_Sensor.h"
+#include "Adafruit_LSM303_U.h"
+
+/* Assign a unique ID to this sensor at the same time */
+Adafruit_LSM303_Mag mag = Adafruit_LSM303_Mag(1366123);
+
+float CurrentHeading = -1;

 // On the Ethernet Shield, CS is pin 4. Note that even if it's not
 // used as the CS pin, the hardware CS pin (10 on most Arduino boards,
@@ -90,10 +99,12 @@
 #endif

-namespace C6_Navigator {
+namespace C6_Navigator
+{
     void setup();
     void loop();
 }
+
 // Set the GPSRATE to the baud rate of the GPS module. Most are 4800
 // but some are 38400 or other. Check the datasheet!
 #define GPSRATE 4800
@@ -117,8 +128,9 @@
 #endif
 // limited to 8+3 characters
 #define FILE_NAME "GPSLog.csv"
+
 File dataFile;
-char GPSfile[BUFFSIZ] = "mmddhhmm.csv";
+char GPSfile[BUFFSIZ] = "mmddhhmm.csv";
 char ObstacleString[BUFFSIZ];
 char StartTime[BUFFSIZ] = "yy,mm,dd,hh,mm,ss,xxx";
 const char TimeHeader[] = "year,month,day,hour,minute,second,msec";
@@ -138,6 +150,7 @@
 waypoint estimated_position;
 //instrument IMU;
 const unsigned long LoopPeriod = 100;  // msec
+
 //---------------------------------------------------------------------------
 char* obstacleDetect()
 {
@@ -147,13 +160,13 @@
     int Range =      analogRead(FRONT) + OFFSET;
     int RightRange = analogRead(RIGHT) + OFFSET;

-  sprintf(ObstacleString,
+  sprintf(ObstacleString,
   "%d.%0.2d,%d.%0.2d,%d.%0.2d,",
   LeftRange/100, LeftRange%100, Range/100, Range%100, RightRange/100, RightRange%100);
-
+
   return ObstacleString;
 }
-/*---------------------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------------------*/
 // WheelRev is called by an interrupt.
 void WheelRev()
 {
@@ -172,7 +185,7 @@
     Odometer_mm += WHEEL_DIAMETER_MM * PI;
     OldTick = TickTime;
 }
-/*---------------------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------------------*/

 void initialize()
 {
@@ -182,13 +195,13 @@
   char* disable =   "$PSRF103,02,00,00,01*26\r\n";
   char* querryGGA = "$PSRF103,00,01,00,01*25";
   bool GPS_available = false;
-  Serial3.begin(GPSRATE);
+  Serial3.begin(GPSRATE);
   digitalWrite(GPS_POWER, LOW);         // pull low to turn on!
   Serial.flush();
   Serial3.flush();
   delay(5000);
-  // prints title with ending line break
-  Serial.println(" GPS parser");
+  // prints title with ending line break
+  Serial.println(" GPS parser");
 //  Serial.print("Acquiring GPS RMC...");
   checksum(protocol);
   Serial3.println(protocol);
@@ -196,7 +209,10 @@
   checksum(disable);
   Serial3.println(disable);   // no GSA

-  GPS_available = estimated_position.AcquireGPRMC(70000);
+  if(estimated_position)
+  {
+    GPS_available = estimated_position.AcquireGPRMC(70000);
+  }
   Serial.println(TimeHeader);
   Serial.println(StartTime);
   Serial.println(RawKF);
@@ -223,7 +239,7 @@
   estimated_position.Evector_x1000 = 1000;  // to be taken from path or set by hand
   estimated_position.Nvector_x1000 = 0;
   GPS_reading = estimated_position;
-  GPSString = estimated_position.formPointString();
+  GPSString = estimated_position.formPointString();
   Serial.println(GPSString);
   // Set Odometer to 0.
   // Set lateral deviation to 0.
@@ -253,12 +269,11 @@
     // ready to roll
     // Fuse all position estimates.
     // Send vehicle state to C3 and C4.
-
-}
-/*---------------------------------------------------------------------------------------*/
-
-void setup()
-{
+}
+/*---------------------------------------------------------------------------------------*/
+
+void setup()
+{
     pinMode(Rx0, INPUT);
     pinMode(Tx0, OUTPUT);
     pinMode(GPS_RX, INPUT);
@@ -268,7 +283,7 @@
     pinMode(INU_RX, INPUT);
     pinMode(INU_TX, OUTPUT);
     pinMode(GPS_POWER, OUTPUT);
-    Serial3.begin(GPSRATE); // GPS
+    Serial3.begin(GPSRATE); // GPS
     Serial.begin(9600);
     digitalWrite(GPS_POWER, LOW);         // pull low to turn on!
     // make sure that the default chip select pin is set to
@@ -277,14 +292,26 @@
     pinMode(53, OUTPUT);  // Unused CS on Mega
     pinMode(GPS_RED_LED, OUTPUT);
     pinMode(GPS_GREEN_LED, OUTPUT);
-    digitalWrite(GPS_GREEN_LED, LOW);
+    digitalWrite(GPS_GREEN_LED, LOW);
     digitalWrite(GPS_RED_LED, LOW);

     initialize();
-//    Serial.print("Initializing GPS SD card...");
-
+    //Serial.print("Initializing GPS SD card...");
+
+
+    //Enable auto-gain
+    mag.enableAutoRange(true);
+
+    //Initialise the sensor
+    if(!mag.begin())
+    {
+        //There was a problem detecting the LSM303 ... check your connections
+        Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
+        while(1);
+    }
+
     // see if the card is present and can be initialized:
-    if (!SD.begin(chipSelect))
+    if (!SD.begin(chipSelect))
     {
       Serial.println("Card failed, or not present");
       digitalWrite(GPS_RED_LED, HIGH);
@@ -294,7 +321,7 @@
       Serial.println("card initialized.\n");
       dataFile = SD.open(GPSfile, FILE_WRITE);
       // if the file is available, write date and time to it:
-      if (dataFile)
+      if (dataFile)
       {
           dataFile.println(TimeHeader);
           dataFile.println(StartTime);
@@ -303,34 +330,33 @@
           dataFile.print(Header);
           dataFile.println(ObstHeader);
           dataFile.close();
-      }
+      }
     }
     pinMode(CYCLOMETER, INPUT);
     attachInterrupt (5, WheelRev, RISING);

 }
-/*---------------------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------------------*/
 void waypoint::SetTime(char *pTime, char * pDate)
 {
-//    GPSfile = "mmddhhmm.CSV";
-     strncpy(GPSfile,   pDate+2, 2);  // month
-     strncpy(GPSfile+2, pDate, 2);    // day
-     strncpy(GPSfile+4, pTime,2);     // GMT hour
-     strncpy(GPSfile+6, pTime+2,2);   // minute
-     Serial.println(GPSfile);
-
-     strncpy(StartTime,     pDate+4, 2);  // year
-     strncpy(StartTime+3,   pDate+2, 2);  // month
-     strncpy(StartTime+6,   pDate, 2);    // day
-     strncpy(StartTime+9,   pTime,2);     // GMT hour
-     strncpy(StartTime+12,  pTime+2,2);   // minute
-     strncpy(StartTime+15,  pTime+4,2);   // second
-     strncpy(StartTime+18,  pTime+7,3);   // millisecond
-
-}
-
-/*---------------------------------------------------------------------------------------*/
-void loop()
+    //GPSfile = "mmddhhmm.CSV";
+    strncpy(GPSfile,   pDate+2, 2);  // month
+    strncpy(GPSfile+2, pDate, 2);    // day
+    strncpy(GPSfile+4, pTime,2);     // GMT hour
+    strncpy(GPSfile+6, pTime+2,2);   // minute
+    Serial.println(GPSfile);
+
+    strncpy(StartTime,     pDate+4, 2);  // year
+    strncpy(StartTime+3,   pDate+2, 2);  // month
+    strncpy(StartTime+6,   pDate, 2);    // day
+    strncpy(StartTime+9,   pTime,2);     // GMT hour
+    strncpy(StartTime+12,  pTime+2,2);   // minute
+    strncpy(StartTime+15,  pTime+4,2);   // second
+    strncpy(StartTime+18,  pTime+7,3);   // millisecond
+}
+
+/*---------------------------------------------------------------------------------------*/
+void loop()
 {
     unsigned long deltaT_ms;
     unsigned long time = millis();
@@ -348,10 +374,10 @@
     ReadINU.
     Set attitude.
     Read Hall Odometer;  */
-//   IMU.Read(GPS_reading);
-
+//   IMU.Read(GPS_reading);
+
 /*  Read Optical Odometer;
-    Read lane deviation;
+    Read lane deviation;
     If (message from C4)
     { */
 //      readline(2);  // C4 Path planner on serial 2 get new route and speed
@@ -362,25 +388,39 @@
 /*    }
     if (landmarks availabe)
     {  // get the position based on bearing and angle to a known location.
-      ReadLandmarks(C4);
+      ReadLandmarks(C4);
     }
     // Fuse all position estimates with a Kalman Filter */
     deltaT_ms = GPS_reading.time_ms - estimated_position.time_ms;
     estimated_position.fuse(GPS_reading, deltaT_ms);
     estimated_position.time_ms = GPS_reading.time_ms;
-/*  Serial.print("time, gps, dt_ms = ");
+/*  Serial.print("time, gps, dt_ms = ");
     Serial.print(time, DEC); Serial.print(", ");
     Serial.print(GPS_reading.time_ms, DEC); Serial.print(", ");
     Serial.println(deltaT_ms, DEC);
-*/
-    // Send vehicle state to C3 and C4.
+*/
+    // Send vehicle state to C3 and C4.
+
+    //Get a new sensor event from the magnitomitor
+    sensors_event_t event;
+    mag.getEvent(&event);
+
+    //Calculate the current heading (angle of the vector y,x)
+    float heading = (atan2(event.magnetic.y, event.magnetic.x) * 180) / M_PI;
+
+    //Normalize the heading
+    if (heading < 0)
+    {
+        heading = 360 + heading;
+    }
+    CurrentHeading = heading;

     // open the file. note that only one file can be open at a time,
     // so you have to close this one before opening another.
     dataFile = SD.open(GPSfile, FILE_WRITE);
-
+
     // if the file is available, write to it:
-    if (GPS_available)
+    if (GPS_available)
     {
         digitalWrite(GPS_GREEN_LED, HIGH);
         pGPS = GPS_reading.formPointString();
@@ -392,21 +432,21 @@
         Serial.print(pData);
         Serial3.print(pData);  // send data to C4 path planner
         pObstacles = obstacleDetect();
-        if (dataFile)
+        if (dataFile)
         {
           dataFile.print(pObstacles);
         }
         Serial.print(pObstacles);
-    }
-    else
+    }
+    else
     {
         digitalWrite(GPS_GREEN_LED, LOW);
         Serial.print("GPS not available");
     }
-
+
     work_time = millis() - time;
-    PerCentBusy = (100 * work_time) / LoopPeriod;
-    if (dataFile)
+    PerCentBusy = (100 * work_time) / LoopPeriod;
+    if (dataFile)
     {
       dataFile.println(PerCentBusy);
     }
@@ -422,7 +462,7 @@
         digitalWrite(GPS_RED_LED, HIGH);
  //     Serial.println("error opening file");
     }
-
+
   // delay, but don't count time in loop
   while (time < endTime)
   {


Ported to the Teensy 3.5 and 3.6

Ported to the Teensy 3.5 and 3.6

--- RunCPM/RunCPM.ino
+++ RunCPM/RunCPM.ino
@@ -6,7 +6,13 @@
 #define LED 13
 #define sDELAY 50
 #define DELAY 100
-#define SDcs 4  // Pin for the SD chip select signal
+
+// Pin for the SD chip select signal
+#ifdef CORE_TEENSY
+	#define SDcs BUILTIN_SDCARD
+#else
+	#define SDcs 4
+#endif

 #include "abstraction_arduino.h"
 #include "ram.h"
@@ -82,4 +88,8 @@
 	delay(DELAY);
 	digitalWrite(LED, LOW);
 	delay(DELAY);
+	digitalWrite(LED, HIGH);
+	delay(DELAY);
+	digitalWrite(LED, LOW);
+	delay(DELAY * 3);
 }


Finished implementing the SOS button

Finished implementing the SOS button

--- SafePlantOLED.ino
+++ SafePlantOLED.ino
@@ -26,6 +26,7 @@
 int draw_state = 0;

 //SOS button
+static int buttonSOS = 7;

 //pulse sensor variables
@@ -184,6 +185,7 @@

 void setup(void) {
   pinMode(button, INPUT_PULLUP);
+  pinMode(buttonSOS, INPUT_PULLUP);
   Serial.begin(9600);
   BTserial.begin(9600); //start the bluetooth connection

@@ -367,6 +369,8 @@
   BTserial.print(temperature);
   BTserial.print(",");
   BTserial.print(bloodPressure);
+  BTserial.print(",");
+  BTserial.print(getSOSState());
   BTserial.print(",");
   BTserial.print("~");
 }
@@ -420,11 +424,17 @@
     } while (u8g.nextPage());
     delay(100);

+    //Action for the navigation button
     if (digitalRead(button) == HIGH) {
       draw_state++;
       delay(100);
+    } if (digitalRead(button) == LOW) {
+      delay(5000);
     }
     draw_state %= 6;
+
+    //Action for the SOS button
+

     //call the blutooth function to send the message
     sendViaBluetooth();
@@ -617,3 +627,13 @@

 }

+//get the SOS button state
+int getSOSState(){
+
+  if (digitalRead(buttonSOS) == HIGH) {
+    return 1;
+  }else if (digitalRead(buttonSOS) == LOW){
+    return 0;
+  }
+}
+


ClimateMeter: update comments

ClimateMeter: update comments

--- climate_meter/climate_meter.ino
+++ climate_meter/climate_meter.ino
@@ -5,7 +5,7 @@
  * Arduino Nano,
  * BMP280   - 1 unit,
  * DHT11/22 - 1 unit,
- * DS18B20  - 3 units,
+ * DS18B20  - 3 units.
  *
  * Supports Modbus RTU.
  * Holding Registers (4X), function 03H.


- Updated the getTemperature sketch to have a more intuitive serial output

--- examples/LightBlueBean/01.Basics/getTemperature/getTemperature.ino
+++ examples/LightBlueBean/01.Basics/getTemperature/getTemperature.ino
@@ -20,11 +20,8 @@
  {
    temp = newTemp;

-   uint8_t buffer[1];
-   buffer[0] = temp;
-
-
-   Serial.write( buffer, 1 );
+   Serial.print("Temperature: ");
+   Serial.println(temp);
  }

  // Sleep for a second before reading the temperature again


fix off-by-one error

fix off-by-one error

--- espwifisniff.ino
+++ espwifisniff.ino
@@ -28,7 +28,7 @@
     }

     // not found, add it if there's still room
-    if (unique_num < (MAX_MAC - 1)) {
+    if (unique_num < MAX_MAC) {
         memcpy(&unique_mac[unique_num], mac, 6);
         unique_num++;
         return true;


Update FixBrickedUID.ino

Update FixBrickedUID.ino

Updated code to account for serial behavior change in ATMEGA32U4

--- examples/FixBrickedUID/FixBrickedUID.ino
+++ examples/FixBrickedUID/FixBrickedUID.ino
@@ -49,7 +49,8 @@

 void setup() {
         Serial.begin(9600);        // Initialize serial communications with the PC
-        SPI.begin();                // Init SPI bus
+        while (!Serial);           // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
+        SPI.begin();               // Init SPI bus
         mfrc522.PCD_Init();        // Init MFRC522 card
         Serial.println("Warning: this example clears your mifare UID, use with care!");


Reset from anywhere

Reset from anywhere

--- crypt-gears/gear_arduino/gear_arduino.ino
+++ crypt-gears/gear_arduino/gear_arduino.ino
@@ -108,7 +108,7 @@
 // How many frames to wait before toggling blinking lights
 int BLINK_SPEED = 50; // 0.5s
 // How many frames to wait before logging debug data, or 0 for never
-int DEBUG_FREQ = 0; // 2s
+int DEBUG_FREQ = 3000; // 2s

 // MAIN TOPLEVEL STUFF

@@ -239,7 +239,13 @@
   if (state == 2)
   {
     setCalibration(true);
-    if (selector_pos >= 0)
+    if (buttonPressed())
+    {
+      // Button resets.
+      state = 0;
+      resetLights();
+    }
+    else if (selector_pos >= 0)
     {
       // Fill in new connection states.
       // Usually a noop.
@@ -269,13 +275,6 @@
         servo.write(servo_open);
         sendCastleSuccessMessage();
       }
-      else if (buttonPressed())
-      {
-        // Button resets.
-        state = 0;
-        resetLights();
-      }
-
     }
     if (state != 3 && selector_pos < 0)
     {


Updated the ready and armed states

Updated the ready and armed states

--- sploder.ino
+++ sploder.ino
@@ -19,6 +19,9 @@
 // We'll hold timing information about certain states here
 long timerStartupState = 0;
 long timerFiringState = 0;
+
+// Status of the ARMED switch
+boolean armed = false;

 // FSM states
 State startupState = State(enterStartupState,updateStartupState,leaveStartupState);
@@ -71,26 +74,35 @@
 }

 // -------------- Ready State ---------------
-void enterReadyState() {}
-void updateReadyState() {}
+void enterReadyState() {
+  note("ready");
+}
+void updateReadyState() {
+  if (armed) {
+    stateMachine.transitionTo(armedState);
+  }
+}
 void leaveReadyState() {}

 // -------------- Armed State ---------------
 void enterArmedState() {
   note("armed");
 }
-void updateArmedState() {}
+void updateArmedState() {
+  if (!armed) {
+    stateMachine.transitionTo(readyState);
+  }
+}
 void leaveArmedState() {}

 // -------------- Firing State ---------------
 void enterFiringState () {
   note("firing!");
   startTimer(timerStartupState);
-
 }
 void updateFiringState() {
   if(isTimerExpired(timerFiringState, 1000)) {
-    stateMachine.transitionTo(armedState);
+    stateMachine.transitionTo(readyState);
   }
 }
 void leaveFiringState() {


solved problem in example parameters

solved problem in example parameters

--- examples/SIM900/SIM900.ino
+++ examples/SIM900/SIM900.ino
@@ -8,7 +8,7 @@
 void setup()
 {
   // Init SIM900 library ( PinCode, APN, APN_USER, APN_PASSWORD, ENABLE_PIN, SERIAL )
-  SIM900 = new Connection( "1345", "internet", "", "", 2, 0 );
+  SIM900 = new Connection( "1345", "internet", "", "", 2, Serial );

   // Configure SIM900 library
   if ( !SIM900->Configuration() )


Update button order (replaced & resoldiered all of the buttons, order changed)

--- teensy_octo.ino
+++ teensy_octo.ino
@@ -28,7 +28,8 @@
 #define NUMBER_OF_LEDS 6 // 2 RGB LEDs, 3 * 2

 // Define digital pins for the buttons
-const byte BUTTON_PINS[] = { 0, 1, 2, 3, 7, 8, 20, 21 };
+//const byte BUTTON_PINS[] = { 0, 1, 2, 3, 7, 8, 20, 21 };
+const byte BUTTON_PINS[] = { 2, 0, 1, 3,  8, 7,  21, 20};

 // Define PWM pins for the RGB LED
 // Order: LED0-R, LED0-G, LED0-B; LED1-R, LED1-G, LED1-B


Changed firmware in master to use Seakings by default.

--- firmware/firmware.ino
+++ firmware/firmware.ino
@@ -282,8 +282,8 @@
   platypus::sensors[3] = new platypus::ES2(3);

   // Initialize motors
-  platypus::motors[0] = new platypus::VaporPro(0);
-  platypus::motors[1] = new platypus::VaporPro(1);
+  platypus::motors[0] = new platypus::Seaking(0);
+  platypus::motors[1] = new platypus::Seaking(1);

   // Make the ADK buffers into null terminated string.
   debug_buffer[INPUT_BUFFER_SIZE] = '\0';


Increased buffer for MQTT discovery payload. Payload deemed to be too small causing Home Assistant not to recognize all configuration options.

--- src/light.ino
+++ src/light.ino
@@ -29,7 +29,9 @@

     // MQTT discovery for Home Assistant
     if (cfg.mqtt_ha_use_discovery && !cfg.mqtt_ha_is_discovered) {
-      static const int BUFFER_SIZE = JSON_OBJECT_SIZE(8);
+      static const int BUFFER_SIZE =
+          JSON_OBJECT_SIZE(8) + 128; // '128' is an arbritrary number. Increase
+                                     // if required by the payload
       StaticJsonBuffer<BUFFER_SIZE> mqttJsonBuffer;
       JsonObject &md_root = mqttJsonBuffer.createObject();

@@ -37,10 +39,10 @@
       md_root["platform"] = "mqtt_json";
       md_root["state_topic"] = cfg.mqtt_state_topic;
       md_root["command_topic"] = cfg.mqtt_command_topic;
-      md_root["brightness"] = true;
       md_root["rgb"] = true;
-      md_root["white_value"] = true;
-      md_root["color_temp"] = true;
+      md_root[KEY_COLORTEMP] = true;
+      md_root[KEY_BRIGHTNESS] = true;
+      md_root[KEY_WHITE] = true;

       // Build the payload
       char md_buffer[md_root.measureLength() + 1];


Changed r/g/b/brightness types to byte, normalized brightness value, fixed issue with headerByte not being reset before each LED loop, fixed issue with headerByte using & instead of |, added some debugging code

--- ucontroller/ucontroller.ino
+++ ucontroller/ucontroller.ino
@@ -24,10 +24,10 @@

 // An LED on our light strip
 struct LED {
-  unsigned int red        = 0;
-  unsigned int green      = 0;
-  unsigned int blue       = 0;
-  unsigned int brightness = 0;
+  byte red        = 0;
+  byte green      = 0;
+  byte blue       = 0;
+  byte brightness = 0;
 };

 // Current LED state
@@ -47,7 +47,7 @@
   Serial.begin(115200);
   SPI.begin();
   allocateMemory();
-  //updateLeds();
+  updateLeds();
 }

 /**
@@ -127,6 +127,10 @@
   } else if(command[0] == 'S') {
     // Output status - currently for debugging but could be adapted for bidirectional communication
     outputLedState(currentLedCount);
+  } else if(command[0] == 'B') {
+    printByte(0xCD, true);
+  } else if(command[0] == 'T') {
+    simulateTransfer();
   }
   return false;
 }
@@ -134,11 +138,13 @@
 /**
  * Update an LED's state
  */
-boolean updateLed(int ledNumber, int red, int green, int blue, int brightness) {
+boolean updateLed(int ledNumber, int red, int green, int blue, int brightness) {
   if(ledNumber >= currentLedCount) {
     // LED out of bounds
     return false;
   }
+  // Normalize brightness value
+  brightness = min(brightness, 31);
   LED *led = &leds[ledNumber];
   boolean needsUpdate = led->red != red
                           || led->green != green
@@ -201,27 +207,64 @@
   int endLength = round(((float)(currentLedCount - 1) / 16.0) + 0.5F);
   endLength = max(endLength, 4);
   int i;
-  byte headerByte = B11100000;
+  byte headerByte;
   LED *led;
-  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE1));
+  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
   // Start by sending 32 zero bits
   for(i = 0 ; i < 4 ; i++) {
-    SPI.transfer(0x00);
+    SPI.transfer(0x00);
   }
   // Send each LED state, header is 1110 0000 & 5-bit brightness, then b/g/r color channels
   for(i = 0 ; i < currentLedCount ; i++) {
     led = &leds[i];
-    headerByte = headerByte & led->brightness;
+    headerByte = B11100000 | led->brightness;
     SPI.transfer(headerByte);
     SPI.transfer(led->blue);
     SPI.transfer(led->green);
     SPI.transfer(led->red);
   }
   for(i = 0 ; i < endLength ; i++) {
-    SPI.transfer(0x00);
+    SPI.transfer(0xFF);
   }
   SPI.endTransaction();
-  Serial.print("Updated LEDs, endlength: ");
-  Serial.println(endLength);
-}
-
+}
+
+void simulateTransfer() {
+  // For APA102C
+  int endLength = round(((float)(currentLedCount - 1) / 16.0) + 0.5F);
+  endLength = max(endLength, 4);
+  int i;
+  byte headerByte;
+  LED *led;
+  // Start by sending 32 zero bits
+  for(i = 0 ; i < 4 ; i++) {
+    printByte(0x00, false);
+  }
+  Serial.println();
+  // Send each LED state, header is 1110 0000 & 5-bit brightness, then b/g/r color channels
+  for(i = 0 ; i < currentLedCount ; i++) {
+    led = &leds[i];
+    headerByte = B11100000 | led->brightness;
+    printByte(headerByte, false);
+    printByte(led->blue, false);
+    printByte(led->green, false);
+    printByte(led->red, true);
+  }
+  for(i = 0 ; i < endLength ; i++) {
+    printByte(0xFF, false);
+  }
+}
+
+void printByte(byte b, boolean newline) {
+  for(int i = 7 ; i > -1 ; i--) {
+    Serial.print(((b >> i) & B00000001) && 1);
+    if(i == 4) {
+      Serial.print(" ");
+    }
+  }
+  Serial.print("   ");
+  if(newline) {
+    Serial.println();
+  }
+}
+


Changed floats to doubles, added enum

Changed floats to doubles, added enum

-All floats --> doubles
-Added enum for ServoIDs

--- AL5D/al5d.ino
+++ AL5D/al5d.ino
@@ -108,11 +108,14 @@
 #define RIGHT          HIGH

 // Servo IDs used for addressing servos in arrays
-#define BAS 0
-#define SHL 1
-#define ELB 2
-#define WRI 3
-#define GRI 4
+enum ServoID
+{
+  BAS = 0,
+  SHL,
+  ELB,
+  WRI,
+  GRI
+};

 // Depending on your servo make, the pulse width min and max may vary, you
 // want these to be as small/large as possible without hitting the hard stop
@@ -145,6 +148,7 @@
 #define ELB_PARK 180
 #define WRI_PARK 90

+
 /*****************/
 /* SERVO OBJECTS */
 /*****************/
@@ -161,27 +165,27 @@
 int     i,j,count=0;
 int     ret_val, g_moveDelay = 50; // g_moveDelay is defined at global scope and is used to control speed of arm
 char    buf[MAX_BUFFER+1];
-float   number[4], current[4], actual[4], g_angle_d[4];
-float   g_radius_mm, g_height_mm, g_hand_d, g_sliderPos;
-float   g_prevRadius_mm, g_prevHeight_mm, g_prevBase_d, g_prevHand_d;
-
-const float gradient[] = {BAS_GRADIENT, SHL_GRADIENT, ELB_GRADIENT, WRI_GRADIENT, GRI_GRADIENT};
-const float offset[] = {BAS_OFFSET, SHL_OFFSET, ELB_OFFSET, WRI_OFFSET, GRI_OFFSET};
-const float R_PIN[] = {BAS_R_PIN, SHL_R_PIN, ELB_R_PIN, WRI_R_PIN};
-const float H_PIN[] = {BAS_H_PIN, SHL_H_PIN, ELB_H_PIN, WRI_H_PIN};
-const float R_REF[] = {BAS_R_REF, SHL_R_REF, ELB_R_REF, WRI_R_REF};
-const float H_REF[] = {BAS_H_REF, SHL_H_REF, ELB_H_REF, WRI_H_REF};
-
-const float SERVO_MIN_D[] = {BAS_MIN_D, SHL_MIN_D, ELB_MIN_D, WRI_MIN_D, GRI_MIN_D};
-const float SERVO_MAX_D[] = {BAS_MAX_D, SHL_MAX_D, ELB_MAX_D, WRI_MAX_D, GRI_MAX_D};
-const float SERVO_MIN[] = {BAS_MIN, SHL_MIN, ELB_MIN, WRI_MIN, GRI_MIN};
-const float SERVO_MAX[] = {BAS_MAX, SHL_MAX, ELB_MAX, WRI_MAX, GRI_MAX};
+double   number[4], current[4], actual[4], g_angle_d[4];
+double   g_radius_mm, g_height_mm, g_hand_d, g_sliderPos;
+double   g_prevRadius_mm, g_prevHeight_mm, g_prevBase_d, g_prevHand_d;
+
+const double gradient[] = {BAS_GRADIENT, SHL_GRADIENT, ELB_GRADIENT, WRI_GRADIENT, GRI_GRADIENT};
+const double offset[] = {BAS_OFFSET, SHL_OFFSET, ELB_OFFSET, WRI_OFFSET, GRI_OFFSET};
+const double R_PIN[] = {BAS_R_PIN, SHL_R_PIN, ELB_R_PIN, WRI_R_PIN};
+const double H_PIN[] = {BAS_H_PIN, SHL_H_PIN, ELB_H_PIN, WRI_H_PIN};
+const double R_REF[] = {BAS_R_REF, SHL_R_REF, ELB_R_REF, WRI_R_REF};
+const double H_REF[] = {BAS_H_REF, SHL_H_REF, ELB_H_REF, WRI_H_REF};
+
+const double SERVO_MIN_D[] = {BAS_MIN_D, SHL_MIN_D, ELB_MIN_D, WRI_MIN_D, GRI_MIN_D};
+const double SERVO_MAX_D[] = {BAS_MAX_D, SHL_MAX_D, ELB_MAX_D, WRI_MAX_D, GRI_MAX_D};
+const double SERVO_MIN[] = {BAS_MIN, SHL_MIN, ELB_MIN, WRI_MIN, GRI_MIN};
+const double SERVO_MAX[] = {BAS_MAX, SHL_MAX, ELB_MAX, WRI_MAX, GRI_MAX};

 /********************/
 /* PRE CALCULATIONS */
 /********************/
-float HUM_SQ = HUMERUS*HUMERUS;
-float ULN_SQ = ULNA*ULNA;
+double HUM_SQ = HUMERUS*HUMERUS;
+double ULN_SQ = ULNA*ULNA;

 /*****************/
 /* RETURN VALUES */
@@ -196,7 +200,7 @@
 /* FUNCTIONS */
 /*************/
 // Moves arm to specified servo angles
-int moveArm( float basAngle_d, float shlAngle_d, float elbAngle_d, float wriAngle_d )
+int moveArm( double basAngle_d, double shlAngle_d, double elbAngle_d, double wriAngle_d )
 {
    int ret_val;

@@ -215,17 +219,17 @@

 // Moves the arm slowly to a new position, depending on the specified delay
 // If the last input angle is negative, the function will determine the wrist angle required to achieve horizontal position
-int slowMoveArm( float basAngle_d, float shlAngle_d, float elbAngle_d, float wriAngle_d )
+int slowMoveArm( double basAngle_d, double shlAngle_d, double elbAngle_d, double wriAngle_d )
 {
    DEBUG("slowMoveArm("); DEBUG(basAngle_d); DEBUG(","); DEBUG(shlAngle_d); DEBUG(","); DEBUG(elbAngle_d); DEBUG(","); DEBUG(wriAngle_d); DEBUGln(")");

    int ret_val;
-   float bDiff = abs( basAngle_d - g_angle_d[BAS] );
-   float sDiff = abs( shlAngle_d - g_angle_d[SHL] );
-   float eDiff = abs( elbAngle_d - g_angle_d[ELB] );
-   float wDiff = abs( wriAngle_d - g_angle_d[WRI] );
-
-   float steps = max( bDiff, sDiff );
+   double bDiff = abs( basAngle_d - g_angle_d[BAS] );
+   double sDiff = abs( shlAngle_d - g_angle_d[SHL] );
+   double eDiff = abs( elbAngle_d - g_angle_d[ELB] );
+   double wDiff = abs( wriAngle_d - g_angle_d[WRI] );
+
+   double steps = max( bDiff, sDiff );
    steps = max( steps, eDiff );
    steps = max( steps, wDiff );
    steps = round(steps);
@@ -237,15 +241,15 @@
    }
    else
    {
-      float bStep = (basAngle_d - g_angle_d[BAS])/steps;
-      float sStep = (shlAngle_d - g_angle_d[SHL])/steps;
-      float eStep = (elbAngle_d - g_angle_d[ELB])/steps;
-      float wStep = (wriAngle_d - g_angle_d[WRI])/steps;
+      double bStep = (basAngle_d - g_angle_d[BAS])/steps;
+      double sStep = (shlAngle_d - g_angle_d[SHL])/steps;
+      double eStep = (elbAngle_d - g_angle_d[ELB])/steps;
+      double wStep = (wriAngle_d - g_angle_d[WRI])/steps;

-      float bMove = g_angle_d[BAS] + bStep;
-      float sMove = g_angle_d[SHL] + sStep;
-      float eMove = g_angle_d[ELB] + eStep;
-      float wMove = g_angle_d[WRI] + wStep;
+      double bMove = g_angle_d[BAS] + bStep;
+      double sMove = g_angle_d[SHL] + sStep;
+      double eMove = g_angle_d[ELB] + eStep;
+      double wMove = g_angle_d[WRI] + wStep;

       for(int i=0; i<steps; i++)
       {
@@ -259,32 +263,32 @@

 // Arm positioning routine utilizing inverse kinematics in cylindrical coordinates
 // (r = radius, h = height, b = azimuth = base servo angle, handAngle = angle of hand from horizontal)
-int moveArmCoord( float radius_mm, float height_mm, float basAngle_d, float handAngle_d )
+int moveArmCoord( double radius_mm, double height_mm, double basAngle_d, double handAngle_d )
 {
    DEBUG("moveArmCoord("); DEBUG(radius_mm); DEBUG(","); DEBUG(height_mm); DEBUG(","); DEBUG(basAngle_d); DEBUGln(")");
    /* Lengths from shoulder to wrist in cylindrical coordinates */
-   float s2w_h = height_mm - BASE_HEIGHT - HAND*sin( radians( handAngle_d) );
-   float s2w_r = radius_mm - HAND*cos( radians( handAngle_d) );
+   double s2w_h = height_mm - BASE_HEIGHT - HAND*sin( radians( handAngle_d) );
+   double s2w_r = radius_mm - HAND*cos( radians( handAngle_d) );
    /* Shoulder to wrist distance ( AKA s2w ) */
-   float s2w = ( s2w_h * s2w_h ) + ( s2w_r * s2w_r );
-   float s2w_sqrt = sqrt( s2w ); // Length of line from shoulder to wrist (S-W)
+   double s2w = ( s2w_h * s2w_h ) + ( s2w_r * s2w_r );
+   double s2w_sqrt = sqrt( s2w ); // Length of line from shoulder to wrist (S-W)
    /* s2w angle to ground */
-   float a1 = atan2( s2w_h, s2w_r ); // Angle between S-W line and ground
+   double a1 = atan2( s2w_h, s2w_r ); // Angle between S-W line and ground
    /* s2w angle to humerus */
-   float a2 = acos((( HUM_SQ - ULN_SQ ) + s2w ) / ( 2 * HUMERUS * s2w_sqrt )); // Angle between S-W line and humerus
+   double a2 = acos((( HUM_SQ - ULN_SQ ) + s2w ) / ( 2 * HUMERUS * s2w_sqrt )); // Angle between S-W line and humerus
    /* shoulder angle */
-   float shlAngle_r = a1 + a2;
+   double shlAngle_r = a1 + a2;
    /* elbow angle */
-   float elbAngle_r = acos(( HUM_SQ + ULN_SQ - s2w ) / ( 2 * HUMERUS * ULNA )); // Angle between humerus and ulna
+   double elbAngle_r = acos(( HUM_SQ + ULN_SQ - s2w ) / ( 2 * HUMERUS * ULNA )); // Angle between humerus and ulna
    /* wrist angle */
-   float wriAngle_d = 360 - degrees(shlAngle_r + elbAngle_r);
+   double wriAngle_d = 360 - degrees(shlAngle_r + elbAngle_r);

    return ( s2w_sqrt > HUMERUS + ULNA ) ? -3 : slowMoveArm( basAngle_d, degrees(shlAngle_r), degrees(elbAngle_r), wriAngle_d ); // Return -3 if no solution exists (out of range)
 }

 // Moves the arm slowly to a new position, depending on the specified delay using cylindrical coordinates
 // (r = radius, h = height, b = azimuth = base servo angle)
-int slowMoveArmCoord( float radius_mm, float height_mm, float basAngle_d, float handAngle_d )
+int slowMoveArmCoord( double radius_mm, double height_mm, double basAngle_d, double handAngle_d )
 {
    DEBUG("slowMoveArmCoord("); DEBUG(radius_mm); DEBUG(","); DEBUG(height_mm); DEBUG(","); DEBUG(basAngle_d); DEBUG(","); DEBUG(handAngle_d); DEBUGln(")");

@@ -293,25 +297,25 @@
    g_prevRadius_mm = g_radius_mm; g_prevHeight_mm = g_height_mm; g_prevBase_d = g_angle_d[BAS]; g_prevHand_d = g_hand_d;// Use with feedback to allow reversing after a collision

    int ret_val;
-   float rDiff = abs( radius_mm - g_radius_mm );
-   float hDiff = abs( height_mm - g_height_mm );
-   float bDiff = abs( basAngle_d - g_angle_d[BAS] );
-   float dDiff = abs( handAngle_d - g_hand_d );
+   double rDiff = abs( radius_mm - g_radius_mm );
+   double hDiff = abs( height_mm - g_height_mm );
+   double bDiff = abs( basAngle_d - g_angle_d[BAS] );
+   double dDiff = abs( handAngle_d - g_hand_d );

    int steps = max( rDiff, hDiff );
    steps = max( steps, bDiff );
    steps = max( steps, dDiff );
    DEBUG("Steps: "); DEBUGln(steps);

-   float rStep = ( radius_mm - g_radius_mm )/steps;
-   float hStep = ( height_mm - g_height_mm )/steps;
-   float bStep = ( basAngle_d - g_angle_d[BAS] )/steps;
-   float dStep = ( handAngle_d - g_hand_d )/steps;
-
-   float rMove = g_radius_mm + rStep;
-   float hMove = g_height_mm + hStep;
-   float bMove = g_angle_d[BAS] + bStep;
-   float dMove = g_hand_d + dStep;
+   double rStep = ( radius_mm - g_radius_mm )/steps;
+   double hStep = ( height_mm - g_height_mm )/steps;
+   double bStep = ( basAngle_d - g_angle_d[BAS] )/steps;
+   double dStep = ( handAngle_d - g_hand_d )/steps;
+
+   double rMove = g_radius_mm + rStep;
+   double hMove = g_height_mm + hStep;
+   double bMove = g_angle_d[BAS] + bStep;
+   double dMove = g_hand_d + dStep;

    for(int i=0; i<steps; i++)
    {
@@ -400,14 +404,14 @@
     for (int k=6; k<14; k++){      //discard the 6 highest and 6 lowest readings
       mean += reading[k];
     }
-    return round((float)mean/8);   //average useful readings
+    return round((double)mean/8);   //average useful readings
 }

 // Changes the wrist angle until the gripper is level
-float levelGripper()
+double levelGripper()
 {
    int ret_val, stall_count = 0;
-   float h, h_old, servo_angle = actual[WRI], servo_angle_old = servo_angle;
+   double h, h_old, servo_angle = actual[WRI], servo_angle_old = servo_angle;
    h = getFeedback(H_PIN[WRI]) - H_REF[WRI];
    h_old = h;
    DEBUG("servo_angle: "); DEBUG(servo_angle); DEBUG(", h: "); DEBUGln(h);
@@ -438,7 +442,7 @@
 // Use accelerometer feedback to ensure the arm has reached the destination
 int checkPosition()
 {
-   float angle_d = getAngle(SHL);
+   double angle_d = getAngle(SHL);
    if ( abs( angle_d - g_angle_d[SHL] ) > THRESHOLD3 ) return 1;
    DEBUG("Check1: "); DEBUGln(angle_d - g_angle_d[SHL]);
    angle_d = getAngle(ELB) - angle_d;
@@ -447,23 +451,23 @@
 }

 // Read from accelerometers and determine angle from horizontal
-float getAngle(int id)
-{
-   float r = getFeedback(R_PIN[id]) - R_REF[id];
-   float h = getFeedback(H_PIN[id]) - H_REF[id];
-   float angle_d = degrees( id == ELB ? atan2(-h,-r) : atan2(-h,r) );
+double getAngle(int id)
+{
+   double r = getFeedback(R_PIN[id]) - R_REF[id];
+   double h = getFeedback(H_PIN[id]) - H_REF[id];
+   double angle_d = degrees( id == ELB ? atan2(-h,-r) : atan2(-h,r) );
    DEBUG("r: "); DEBUG(r); DEBUG(", h: "); DEBUG(h); DEBUG(", angle_d: "); DEBUGln(angle_d);
    return angle_d;
 }

 // Write angle to servo using microseconds for added precision
-int servoWrite( int id, float angle_d )
+int servoWrite( int id, double angle_d )
 {
 //   DEBUG("servoWrite("); DEBUG(id); DEBUG(", "); DEBUG(angle_deg); DEBUGln(")");
    if (angle_d < SERVO_MIN_D[id]) { DEBUG(angle_d); DEBUG("<"); DEBUGln(SERVO_MIN_D[id]); return -1; }
    if (angle_d > SERVO_MAX_D[id]) { DEBUG(angle_d); DEBUG(">"); DEBUGln(SERVO_MAX_D[id]); return -2; }

-   float pulseLength = map(angle_d, 0, 180, SERVO_MIN[id], SERVO_MAX[id]);
+   double pulseLength = map(angle_d, 0, 180, SERVO_MIN[id], SERVO_MAX[id]);

    pwm.setPWM(id, 0, pulseLength);

@@ -475,7 +479,7 @@
 // Calculates the cylindrical coordinates of the wrist from the servo angles
 void calcPosition()
 {
-   float s = g_angle_d[SHL], e = g_angle_d[ELB] - 180, w = g_angle_d[WRI] - 180;
+   double s = g_angle_d[SHL], e = g_angle_d[ELB] - 180, w = g_angle_d[WRI] - 180;

    g_radius_mm = HUMERUS*cos( radians(s) ) + ULNA*cos( radians(s + e) ) + HAND*cos( radians(s + e + w) );


Add flush.

Add flush.

--- brotherKH930_arduino.ino
+++ brotherKH930_arduino.ino
@@ -50,6 +50,7 @@
     else if (brother.isAtRightMark()) Serial.print(" at R");
     else Serial.print("     ");
     Serial.println();
+    Serial.flush();
   }

   readInput();
@@ -91,9 +92,11 @@
     Serial.print("$\t<\t");
     Serial.write(&buffer[4], len-4);
     Serial.println('\n');
+    Serial.flush();
   } else {
     Serial.print("*\tInvalid input: ");
     Serial.write(buffer, len);
     Serial.println();
+    Serial.flush();
   }
 }


Give feedback if needle pattern is invalid or incomplete.

--- brotherKH930_arduino.ino
+++ brotherKH930_arduino.ino
@@ -84,14 +84,32 @@
 void handleLine(byte* buffer, int len) {
   if (len == 0) return;

-  if (len > 4 && buffer[0] == '$' && buffer[1] == '\t' && buffer[2] == '>' && buffer[3] == '\t') {
-    for (int i=4,n=0; i<len; i++, n++) {
+  if (len > 3 && buffer[0] == '$' && buffer[1] == '\t' && buffer[2] == '>' && buffer[3] == '\t') {
+    if (len < 204) {
+      Serial.print("$\t!\tInvalid needle pattern (too short): ");
+      Serial.write(&buffer[4], len-4);
+      Serial.println();
+      return Serial.flush();
+    }
+    for (int i=4,n=0; n<200; i++, n++) {
       if (buffer[i] == '1') brother.needle(n, true);
       else if (buffer[i] == '0') brother.needle(n, false);
+      else if (buffer[i] == '\t') {
+        Serial.print("$\t!\tInvalid needle pattern (termination): ");
+        Serial.write(&buffer[4], len-4);
+        Serial.println();
+        return Serial.flush();
+      } else {
+        Serial.print("$\t!\tInvalid needle pattern (invalid char): ");
+        Serial.write(&buffer[4], len-4);
+        Serial.println();
+        Serial.flush();
+        return Serial.flush();
+      }
     }
     Serial.print("$\t<\t");
     Serial.write(&buffer[4], len-4);
-    Serial.println('\n');
+    Serial.println();
     Serial.flush();
   } else {
     Serial.print("*\tInvalid input: ");


Deco display changes.

Deco display changes.

--- DiveIno.ino
+++ DiveIno.ino
@@ -459,9 +459,7 @@
 	DiveInfo diveInfo = buhlmann.progressDive(&diveData);
 	view.drawAscend(diveInfo.ascendRate);

-	if (safetyStopState != SAFETY_STOP_IN_PROGRESS) {
-		view.drawDecoArea(diveInfo);
-	}
+	view.drawDecoArea(diveInfo);

 	//Store the current dive data in the dive profile
 	logbook.storeProfileItem(profileFile, pressureInMillibar, depthInMeter, temperatureInCelsius, durationInSeconds);


Update the channels after changing the PWMfrequency.

--- webserver.ino
+++ webserver.ino
@@ -176,6 +176,7 @@
       }
       PWMfrequency = tempPWMfrequency;
       analogWriteFreq( PWMfrequency );
+      updateChannels();
       writeConfigFile();
     }
     webServer.send( 200, FPSTR( textplainHEADER ), String( PWMfrequency ) );


Change ___ to --- in UI

Change ___ to --- in UI

--- Dremelfuge.ino
+++ Dremelfuge.ino
@@ -22,7 +22,6 @@
   variables and functions, as if all were declared `static` (see large comment
   in loop() for details on `static`)
   */
-
 namespace
 {
     LiquidCrystal lcd = LiquidCrystal(12, 11, 5, 4, 3, 6);                       // numbers of the interface pins
@@ -77,7 +76,7 @@
   lcd.setCursor(0, 0);
   lcd.print(F("  Dremel Centrifuge"));
   lcd.setCursor(0, 2);
-  lcd.print(F("Set speed: ___"));
+  lcd.print(F("Set speed: ---"));
   lcd.setCursor(0, 3);
   lcd.print(F("   Push to "));

@@ -245,7 +244,6 @@
         lcd.print(F("  "));

         spinningStartTime = millis();
-
         mode = Mode::SPINNING;
       } // if(wpb.pressed())
       break;


Re-enabled fixation button

Re-enabled fixation button

--- signalboxes/kelberg/kelberg.ino
+++ signalboxes/kelberg/kelberg.ino
@@ -101,6 +101,15 @@
     requirements_fulfilled[ROUTE_P2] = true;
   }

+  // If a route switch is MINUS, it can be fixated.
+  requirements_fulfilled[ROUTE_AP_FIXATION] = false;
+  if (current_position[ROUTE_A1] == MINUS ||
+      current_position[ROUTE_A2] == MINUS ||
+      current_position[ROUTE_P1] == MINUS ||
+      current_position[ROUTE_P2] == MINUS) {
+    requirements_fulfilled[ROUTE_AP_FIXATION] = true;
+  }
+
 }


Added route recall

Added route recall

--- signalboxes/kelberg/kelberg.ino
+++ signalboxes/kelberg/kelberg.ino
@@ -13,6 +13,8 @@
 int PIN_LED_ROUTE_BERENBACH = A14;
 // White LED
 int PIN_LED_ROUTE_A_FIXATION = A15;
+// Blue LED in "route recall" box
+int PIN_LED_ROUTE_A_RECALL = 49;

 // Levers and lock
 int PIN_LEVER_SWITCH_5 = 22;
@@ -27,6 +29,9 @@
 int PIN_LEVER_ROUTE_BERENBACH2 = 42;
 // Push button for route fixing
 int PIN_BUTTON_ROUTE_A_FIXATION = 46;
+// Switch/lock for route recall
+int PIN_LOCK_ROUTE_A_RECALL = 47;
+
 // Output pins (pull to 0 means go out of the ground position)
 int PIN_OUTPUT_SWITCH_1 = A1;
 int PIN_OUTPUT_SWITCH_5 =A2;
@@ -45,17 +50,18 @@
 int ROUTE_A_FIXATION = 7;
 int SIGNAL_A1 = 8;
 int SIGNAL_A2 = 9;
+int ROUTE_A_RECALL = 10;

 // The two possible positions. Plus is the default, minus the actuated state.
 bool PLUS = true;
 bool MINUS = false;

 // The states. All arrays with length 10.
-const int ARRAY_SIZE = 10;
-boolean current_position [ARRAY_SIZE] = { PLUS, PLUS, PLUS, PLUS, PLUS, PLUS, PLUS, PLUS, PLUS, PLUS };
-boolean blocked [ARRAY_SIZE] = { false, false, false, false, false, false, false, false, false, false };
-boolean requirements_fulfilled [ARRAY_SIZE] = { true, true, true, false, false, false, false, false, false, false };
-boolean position_is_ok [ARRAY_SIZE] = { true, true, true, true, true, true, true, true, true, true };
+const int ARRAY_SIZE = 11;
+boolean current_position [ARRAY_SIZE] = { PLUS, PLUS, PLUS, PLUS, PLUS, PLUS, PLUS, PLUS, PLUS, PLUS , PLUS };
+boolean blocked [ARRAY_SIZE] = { false, false, false, false, false, false, false, false, false, false, false};
+boolean requirements_fulfilled [ARRAY_SIZE] = { true, true, true, false, false, false, false, false, false, false, false};
+boolean position_is_ok [ARRAY_SIZE] = { true, true, true, true, true, true, true, true, true, true, true };

 // Actual levers/buttons/locks.
@@ -69,8 +75,7 @@

 void update_requirements() {
   // Requirements flow "upwards". The correct switch positions can enable
-  // routes. Enabled routes can enable the route fixation button. Enabled
-  // routes plus an enabled route fixation can enable signals.
+  // routes. Enabled routes plus an enabled route fixation can enable signals.

   // Requirements fulfilled by the switches.
   requirements_fulfilled[ROUTE_A1] = false;
@@ -96,23 +101,6 @@
     requirements_fulfilled[ROUTE_BERENBACH2] = true;
   }

-  // Requirements fulfilled by the route levers and/or the route fixer.
-  requirements_fulfilled[ROUTE_A_FIXATION] = false;
-  requirements_fulfilled[SIGNAL_A1] = false;
-  requirements_fulfilled[SIGNAL_A2] = false;
-  if (current_position[ROUTE_A1] == MINUS ||
-      current_position[ROUTE_A2] == MINUS) {
-    requirements_fulfilled[ROUTE_A_FIXATION] = true;
-  }
-  if (current_position[ROUTE_A2] == MINUS &&
-      current_position[ROUTE_A_FIXATION] == MINUS) {
-    requirements_fulfilled[SIGNAL_A2] = true;
-  }
-  if (current_position[ROUTE_A1] == MINUS &&
-      current_position[ROUTE_A_FIXATION] == MINUS) {
-    requirements_fulfilled[SIGNAL_A1] = true;
-  }
-
 }

@@ -169,6 +157,12 @@
     // moving a signal back to PLUS).
     blocked[ROUTE_A_FIXATION] = true;
   }
+
+  // Signals also block routes.
+  if (current_position[SIGNAL_A1] == MINUS || current_position[SIGNAL_A2] == MINUS) {
+    blocked[ROUTE_A1] = true;
+    blocked[ROUTE_A2] = true;
+  }
 }

@@ -211,20 +205,35 @@
   update_blocks();
   update_outputs();

-  // Special case: signals going back to PLUS free the route fixation.
-  // It also marks the related route as disallowed so that the handle
-  // shows up as having to change.
-  if (number == SIGNAL_A1 || number == SIGNAL_A2) {
-    if (new_position == PLUS) {
-      if (current_position[ROUTE_A1] == MINUS) {
-        position_is_ok[ROUTE_A1] = false;
-      }
-      if (current_position[ROUTE_A2] == MINUS) {
-        position_is_ok[ROUTE_A2] = false;
-      }
-      change_position(ROUTE_A_FIXATION, PLUS);
-    }
-  }
+  // Special case: fixating a route enables the corresponding signal. This way
+  // it can be thrown once (instead of through normal requirements, then it
+  // would have been possible to throw it multiple times). It also enables the
+  // corresponding route recall.
+  if (number == ROUTE_A_FIXATION && new_position == MINUS) {
+    requirements_fulfilled[ROUTE_A_RECALL] = true;
+    if (current_position[ROUTE_A1] == MINUS) {
+      requirements_fulfilled[SIGNAL_A1] = true;
+    }
+    if (current_position[ROUTE_A2] == MINUS) {
+      requirements_fulfilled[SIGNAL_A2] = true;
+    }
+  }
+
+  // Special case: route recall frees the route fixation.
+  if (number == ROUTE_A_RECALL) {
+    // Any new position is OK, we don't care which way the lock is turned.
+    change_position(ROUTE_A_FIXATION, PLUS);
+  }
+
+  // Special case: signals going back to PLUS remove their own "requirements
+  // fulfilled" marker.
+  if (number == SIGNAL_A1 && new_position == PLUS) {
+      requirements_fulfilled[SIGNAL_A1] = false;
+  }
+  if (number == SIGNAL_A2 && new_position == PLUS) {
+      requirements_fulfilled[SIGNAL_A2] = false;
+  }
+
 }

@@ -305,6 +314,7 @@
   pinMode(PIN_LEVER_SIGNAL_A1, INPUT_PULLUP);
   pinMode(PIN_LEVER_SIGNAL_A2, INPUT_PULLUP);
   pinMode(PIN_BUTTON_ROUTE_A_FIXATION, INPUT_PULLUP);
+  pinMode(PIN_LOCK_ROUTE_A_RECALL, INPUT_PULLUP);

   // Attach the LEDs.
   pinMode(13, OUTPUT);
@@ -316,6 +326,7 @@
   pinMode(PIN_LED_ROUTE_A, OUTPUT);
   pinMode(PIN_LED_ROUTE_BERENBACH, OUTPUT);
   pinMode(PIN_LED_ROUTE_A_FIXATION, OUTPUT);
+  pinMode(PIN_LED_ROUTE_A_RECALL, OUTPUT);

   // Attach the output pins
   pinMode(PIN_OUTPUT_SWITCH_1, OUTPUT);
@@ -340,11 +351,12 @@
   levers[SIGNAL_A1].attach(PIN_LEVER_SIGNAL_A1);
   levers[SIGNAL_A2].attach(PIN_LEVER_SIGNAL_A2);
   levers[ROUTE_A_FIXATION].attach(PIN_BUTTON_ROUTE_A_FIXATION);
+  levers[ROUTE_A_RECALL].attach(PIN_LOCK_ROUTE_A_RECALL);

   for (int number = 0; number < ARRAY_SIZE; number++) {
     levers[number].interval(200);
   }
-  // Special case: route fixation button should take three seconds to activate.
+  // Special case: route fixation button should take some seconds to activate.
   levers[ROUTE_A_FIXATION].interval(2000);

   // look up the initial lever positions and update accordingly.
@@ -384,9 +396,11 @@

   if (current_position[ROUTE_A_FIXATION] == PLUS) {
     digitalWrite(PIN_LED_ROUTE_A_FIXATION, LOW);
+    digitalWrite(PIN_LED_ROUTE_A_RECALL, LOW);
   }
   else {
     digitalWrite(PIN_LED_ROUTE_A_FIXATION, HIGH);
+    digitalWrite(PIN_LED_ROUTE_A_RECALL, HIGH);
   }

   // TODO: update the outgoing pins.


Repaired the format of the different variables to adapt to the standard format

--- OpenRocket.ino
+++ OpenRocket.ino
@@ -120,8 +120,8 @@
 // b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
 // so ...Temperature(...) must be called before ...Pressure(...).
 long b5;
-short temperature;
-long pressure;
+float temperature;
+float pressure;
 float atm; // "standard atmosphere"
 float alti;

@@ -382,29 +382,29 @@
     alti = calcAltitude(pressure);
     //dtostrf(floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, charBuf);
     Serial.print("Temp: ");
-    Serial.print(temperature);
+    Serial.print(temperature, 2);
     Serial.println(" C");
     Serial.print("Pres: ");
-    Serial.print(pressure);
-    Serial.println(" hPa");
+    Serial.print(pressure, 0);
+    Serial.println(" Pa");
     Serial.print("Atmophere: ");
-    Serial.println(atm);
+    Serial.println(atm, 4);
     Serial.print("Altitude: ");
-    Serial.print(alti);
+    Serial.print(alti, 2);
     Serial.println("M");
     Serial.println();

-    if (dataFile) {
-      dataFile.print(timestamp);
-      dataFile.print(",");
-      dataFile.print(temperature);
-      dataFile.print(",");
-      dataFile.println(pressure);
-    }
-    // if the file isn't open, pop up an error:
-    else {
-      Serial.println("error opening datalog.txt");
-    }
+//    if (dataFile) {
+//      dataFile.print(timestamp);
+//      dataFile.print(",");
+//      dataFile.print(temperature);
+//      dataFile.print(",");
+//      dataFile.println(pressure);
+//    }
+//    // if the file isn't open, pop up an error:
+//    else {
+//      Serial.println("error opening datalog.txt");
+//    }
     to_save ++;
   }

@@ -416,7 +416,6 @@
   }
 }

-// BMP085
 // Stores all of the bmp085's calibration values into global variables
 // Calibration values are required to calculate temp and pressure
 // This function should be called at the beginning of the program
@@ -434,123 +433,145 @@
   mc = bmp085ReadInt(0xBC);
   md = bmp085ReadInt(0xBE);
 }
-// Calculate temperature given ut.
-// Value returned will be in units of 0.1 deg C
-short bmp085GetTemperature(unsigned int ut)
-{
+
+// Calculate temperature in deg C
+float bmp085GetTemperature(unsigned int ut){
   long x1, x2;
+
   x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
   x2 = ((long)mc << 11)/(x1 + md);
   b5 = x1 + x2;
-  return ((b5 + 8)>>4);
-}
+
+  float temp = ((b5 + 8)>>4);
+  temp = temp /10;
+
+  return temp;
+}
+
 // Calculate pressure given up
 // calibration values must be known
 // b5 is also required so bmp085GetTemperature(...) must be called first.
 // Value returned will be pressure in units of Pa.
-long bmp085GetPressure(unsigned long up)
-{
+long bmp085GetPressure(unsigned long up){
   long x1, x2, x3, b3, b6, p;
   unsigned long b4, b7;
+
   b6 = b5 - 4000;
   // Calculate B3
   x1 = (b2 * (b6 * b6)>>12)>>11;
   x2 = (ac2 * b6)>>11;
   x3 = x1 + x2;
   b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
+
   // Calculate B4
   x1 = (ac3 * b6)>>13;
   x2 = (b1 * ((b6 * b6)>>12))>>16;
   x3 = ((x1 + x2) + 2)>>2;
   b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
+
   b7 = ((unsigned long)(up - b3) * (50000>>OSS));
   if (b7 < 0x80000000)
     p = (b7<<1)/b4;
   else
     p = (b7/b4)<<1;
+
   x1 = (p>>8) * (p>>8);
   x1 = (x1 * 3038)>>16;
   x2 = (-7357 * p)>>16;
   p += (x1 + x2 + 3791)>>4;
+
   return p;
 }
+
 // Read 1 byte from the BMP085 at 'address'
 char bmp085Read(unsigned char address)
 {
   unsigned char data;
+
   Wire.beginTransmission(BMP085_ADDRESS);
   Wire.write(address);
   Wire.endTransmission();
+
   Wire.requestFrom(BMP085_ADDRESS, 1);
-  while(!Wire.available());
+  while(!Wire.available())
+    ;
+
   return Wire.read();
 }
+
 // Read 2 bytes from the BMP085
 // First byte will be from 'address'
 // Second byte will be from 'address'+1
 int bmp085ReadInt(unsigned char address)
 {
   unsigned char msb, lsb;
+
   Wire.beginTransmission(BMP085_ADDRESS);
   Wire.write(address);
   Wire.endTransmission();
+
   Wire.requestFrom(BMP085_ADDRESS, 2);
-  while(Wire.available()<2);
+  while(Wire.available()<2)
+    ;
   msb = Wire.read();
   lsb = Wire.read();
+
   return (int) msb<<8 | lsb;
 }
+
 // Read the uncompensated temperature value
-unsigned int bmp085ReadUT()
-{
+unsigned int bmp085ReadUT(){
   unsigned int ut;
+
   // Write 0x2E into Register 0xF4
   // This requests a temperature reading
   Wire.beginTransmission(BMP085_ADDRESS);
   Wire.write(0xF4);
   Wire.write(0x2E);
   Wire.endTransmission();
+
   // Wait at least 4.5ms
   delay(5);
+
   // Read two bytes from registers 0xF6 and 0xF7
   ut = bmp085ReadInt(0xF6);
   return ut;
 }
+
 // Read the uncompensated pressure value
-unsigned long bmp085ReadUP()
-{
+unsigned long bmp085ReadUP(){
+
   unsigned char msb, lsb, xlsb;
   unsigned long up = 0;
+
   // Write 0x34+(OSS<<6) into register 0xF4
   // Request a pressure reading w/ oversampling setting
   Wire.beginTransmission(BMP085_ADDRESS);
   Wire.write(0xF4);
   Wire.write(0x34 + (OSS<<6));
   Wire.endTransmission();
+
   // Wait for conversion, delay time dependent on OSS
   delay(2 + (3<<OSS));
+
   // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
-  Wire.beginTransmission(BMP085_ADDRESS);
-  Wire.write(0xF6);
-  Wire.endTransmission();
-  Wire.requestFrom(BMP085_ADDRESS, 3);
-  // Wait for data to become available
-  while(Wire.available() < 3);
-  msb = Wire.read();
-  lsb = Wire.read();
-  xlsb = Wire.read();
+  msb = bmp085Read(0xF6);
+  lsb = bmp085Read(0xF7);
+  xlsb = bmp085Read(0xF8);
+
   up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
+
   return up;
 }

-void writeRegisterBMP085(int deviceAddress, byte address, byte val) {
+void writeRegister(int deviceAddress, byte address, byte val) {
   Wire.beginTransmission(deviceAddress); // start transmission to device
   Wire.write(address);       // send register address
   Wire.write(val);         // send value to write
   Wire.endTransmission();     // end transmission
 }

-int readRegisterBMP085(int deviceAddress, byte address){
+int readRegister(int deviceAddress, byte address){

   int v;
   Wire.beginTransmission(deviceAddress);
@@ -568,10 +589,12 @@
 }

 float calcAltitude(float pressure){
+
   float A = pressure/101325;
   float B = 1/5.25588;
   float C = pow(A,B);
   C = 1 - C;
   C = C /0.0000225577;
+
   return C;
 }


implementado acionamento com standby, fixes issue #1

--- EMP-B-Due.ino
+++ EMP-B-Due.ino
@@ -9,58 +9,103 @@
   // Entradas
     const byte bt_geral = 22; // Entrada do botão de Liga/Desliga Geral
     const byte bt_dosador = 26; // Entrada do botão de Liga/Desliga do Dosador
+    const byte bt_datador = 30; // Entrada do botão de Liga/Desliga do Datador
   // Saídas
     const byte led_geral = 25; // Saída Geral
     const byte led_dosador = 29; // Saída do Dosador
+    const byte led_datador = 33; // Saída do Datador

 // Variáveis
   // Botões de Entrada Um Clique
     long atraso = 50;
-    int est_bt_geral;
-    int est_bt_geral_ant = HIGH;
-    long atr_geral_ant = 0;
-    int est_bt_dosador;
-    int est_bt_dosador_ant = HIGH;
+    int estbt_geral;
+    int estbta_geral = HIGH;
+    long atr_geral = 0;
+    int estbt_dosador;
+    int estbta_dosador = HIGH;
     long atr_dosador = 0;
+    int estbt_datador;
+    int estbta_datador = HIGH;
+    long atr_datador = 0;
   // Estado Inicial de Saídas
     int est_led_geral = LOW;
     int est_led_dosador = LOW;
+    int est_led_datador = LOW;
+  // Programa
+    boolean stand_by = false;
+    boolean maquina_ligada = false;

 void setup() {
   pinMode(bt_geral, INPUT_PULLUP);
   pinMode(bt_dosador, INPUT_PULLUP);
+  pinMode(bt_datador, INPUT_PULLUP);

   pinMode(led_geral, OUTPUT);
   pinMode(led_dosador, OUTPUT);
+  pinMode(led_datador, OUTPUT);

   // Define estado inicial das saídas
   digitalWrite(led_geral, est_led_geral);
   digitalWrite(led_dosador, est_led_dosador);
+  digitalWrite(led_datador, est_led_datador);
 }

 void loop() {
-  botaoUmClique(bt_geral, &est_bt_geral, &est_bt_geral_ant, &atr_geral_ant, led_geral, &est_led_geral);
-  botaoUmClique(bt_dosador, &est_bt_dosador, &est_bt_dosador_ant, &atr_dosador, led_dosador, &est_led_dosador);
+  standBy();
 }

+void acionaGeral(){
+  btUmClique(bt_geral, &estbt_geral, &estbta_geral, &atr_geral, led_geral, &est_led_geral);
+}

-void botaoUmClique(byte botao, int *estado, int *est_ant, long *atr_ant, byte saida, int *est_saida ){
-  int reading = digitalRead(botao);
-  if (reading != *est_ant) {
+void acionaDosador(){
+  btUmClique(bt_dosador, &estbt_dosador, &estbta_dosador, &atr_dosador, led_dosador, &est_led_dosador);
+}
+
+void acionaDatador(){
+  btUmClique(bt_datador, &estbt_datador, &estbta_datador, &atr_datador, led_datador, &est_led_datador);
+}
+
+void standBy(){
+  if (stand_by){
+    acionaGeral();
+    acionaDosador();
+    acionaDatador();
+    if (maquina_ligada){
+      iniciaTrabalho();
+    }
+  } else {
+    delay(3000);
+    stand_by = true;
+  }
+}
+
+void iniciaTrabalho(){
+
+}
+
+void btUmClique(byte botao, int *estado, int *est_ant, long *atr_ant, byte saida, int *est_saida ){
+  byte leitura = leEntrada(botao);
+  if (leitura != *est_ant) {
     *atr_ant = millis();
   }

   if ((millis() - *atr_ant) > atraso) {
-    if (reading != *estado) {
-      *estado = reading;
+    if (leitura != *estado) {
+      *estado = leitura;
       if (*estado == LOW) {
         *est_saida = !*est_saida;
       }
     }
   }
   digitalWrite(saida, *est_saida);
-  *est_ant = reading;
+  *est_ant = leitura;
 }
+
+byte leEntrada(byte pino){
+  return digitalRead(pino);
+}
+


Different pitches testing

Different pitches testing

--- Synthduino.ino
+++ Synthduino.ino
@@ -2,9 +2,13 @@
  pinMode(12, OUTPUT);
 }

+// A440 = 2273;
+// Double = 4546
+
 void loop() {
   digitalWrite(12, HIGH);
-  delayMicroseconds(2273);
+  delayMicroseconds(4546);
   digitalWrite(12, LOW);
-  delayMicroseconds(2273);
-}+  delayMicroseconds(4546);
+}
+


Add support for LED indicator

Add support for LED indicator

--- PushStart.ino
+++ PushStart.ino
@@ -20,6 +20,8 @@
 #define pinIG2 7
 #define pinST2 8

+#define pinLed 10
+
 // Slow down the automatic calibration cooldown
 #define offset 2 // <= 6

@@ -31,6 +33,11 @@

 bool pressed = false;
 unsigned long touchStart = 0;
+
+byte ledAmp = 0;
+byte ledShift = 0;
+int ledPeriod = 2000;
+unsigned long fadeStart = 0;

 void setup() {

@@ -64,6 +71,7 @@
   digitalWrite(pinIG1, LOW);  // 2-4
   digitalWrite(pinIG2, LOW);  // 7-6
   digitalWrite(pinST2, LOW);  // 7-8
+  ledShift = 0; ledAmp = 0;
   Serial.println("Mode: off"); Serial.flush();
 }

@@ -72,6 +80,8 @@
   digitalWrite(pinIG1, LOW);  // 2-4
   digitalWrite(pinIG2, LOW);  // 7-6
   digitalWrite(pinST2, LOW);  // 7-8
+  ledShift = 127; ledAmp = 128;
+  ledPeriod = 2000; fadeStart = millis();
   Serial.println("Mode: accessory"); Serial.flush();
 }

@@ -80,6 +90,7 @@
   digitalWrite(pinIG1, HIGH); // 2-4
   digitalWrite(pinIG2, HIGH); // 7-6
   digitalWrite(pinST2, LOW);  // 7-8
+  ledShift = 0; ledAmp = 255;
   Serial.println("Mode: ignition on"); Serial.flush();
 }

@@ -88,6 +99,8 @@
   digitalWrite(pinIG1, HIGH); // 2-4
   digitalWrite(pinIG2, HIGH); // 7-6
   digitalWrite(pinST2, HIGH); // 7-8
+  ledShift = 127; ledAmp = 128;
+  ledPeriod = 250; fadeStart = millis();
   Serial.println("Mode: engine start"); Serial.flush();
 }

@@ -136,6 +149,8 @@
     ST();
   }

+  analogWrite(pinLed, ledShift + ledAmp * cos(2 * PI / ledPeriod * (millis() - fadeStart)));
+
   delay(50);

 }


A bit more debugger info regarding the closing and removing of files.

--- SimpleCSV.ino
+++ SimpleCSV.ino
@@ -192,6 +192,8 @@
   uint32_t primaryIP = getPrimaryServerIP(cc3000);
   //uint32_t secondaryIP = getSecondaryServerIP(cc3000);

+  boolean success = false;
+
   for (uint16_t index = 0; file.readDir(&dir, &index, DIR_ATT_VOLUME_ID); index++) {

     if (!DIR_IS_FILE(&dir)) {
@@ -225,18 +227,31 @@

     //file.rewind();

-    Serial.print(F("http"));
-    if(reportFile(&file, primaryIP, PRIMARY_SERVER) == 0) {
+    Serial.print(F("http"));
+
+    success = (reportFile(&file, primaryIP, PRIMARY_SERVER) == 0);
+
+    Serial.print(F(" close"));
+
+    file.close();
+
+    if(success) {
+      Serial.print(OK_MSG);
+
       // successfully sent the data
       // so we can remove this file
-      file.remove(filename);
-      Serial.print(OK_MSG);
+      Serial.print(F("rm"));
+
+      if (file.remove(filename)) {
+        Serial.print(OK_MSG);
+      } else {
+        Serial.print(FAIL_MSG);
+      }
+
     } else {
       Serial.print(FAIL_MSG);
     }

-    file.close();
-
 nextfile:;
   }


add filter for larger packet in IDLE

add filter for larger packet in IDLE

--- client/client.ino
+++ client/client.ino
@@ -78,32 +78,34 @@
   if(XBee.available()) {
     digitalWrite(ledSignalPin, HIGH);
     signal_time = millis();
-    } else if(millis() - signal_time > 200) {
-      digitalWrite(ledSignalPin, LOW);
-    }
-
-    switch(state) {
-      case IDLE:
+  } else if(millis() - signal_time > 200) {
+    digitalWrite(ledSignalPin, LOW);
+  }
+
+  switch(state) {
+  case IDLE:
     // purely listening and then react by response
     // for now test use random
     // if(irrecv.decode(&results)) {

-      digitalWrite(ledStatePin, LOW);
-
-      if(XBee.available()) {
-
-        delay(5);
-        char packet[50];
-        int len = readXBeeString(packet);
-
-        DEBUG_PRINT("\nPacket received: ");
-        DEBUG_PRINT(packet);
-        DEBUG_PRINT("  Packet len: ");
-        DEBUG_PRINTLN(len);
-
-        randomDelay = random(1000);
-        delay(randomDelay);
+    digitalWrite(ledStatePin, LOW);
+
+    if(XBee.available()) {
+
+      delay(5);
+      char packet[50];
+      int len = readXBeeString(packet);
+
+      DEBUG_PRINT("\nPacket received: ");
+      DEBUG_PRINT(packet);
+      DEBUG_PRINT("  Packet len: ");
+      DEBUG_PRINTLN(len);
+      if (len > 5)
+        break;
+
+      randomDelay = random(1000);
+      delay(randomDelay);

       // send back acknowledge packet
       struct XBeePacket p;
@@ -117,15 +119,15 @@

       DEBUG_PRINTLN("[PENDING] entering PENDING state");
       state = PENDING;
-      } else if(irrecv.decode(&results)) {
-        delay(5);
-
-
-        DEBUG_PRINT("\nIR received: ");
-        DEBUG_PRINTLN(results.value);
-
-        randomDelay = random(1000);
-        delay(randomDelay);
+    } else if(irrecv.decode(&results)) {
+      delay(5);
+
+
+      DEBUG_PRINT("\nIR received: ");
+      DEBUG_PRINTLN(results.value);
+
+      randomDelay = random(1000);
+      delay(randomDelay);

       // send back acknowledge packet

@@ -139,7 +141,7 @@
     }

     break;
-    case PENDING:
+  case PENDING:
     end_time = millis();

     if(end_time - toggle_time > ledStateInterval) {
@@ -216,7 +218,7 @@
       }
     }
     break;
-    case CONNECTED:
+  case CONNECTED:
     // temporarily for debugging
     // turn on the ligth to indicate
     digitalWrite(ledStatePin, HIGH);
@@ -270,7 +272,7 @@
       }
     }
     break;
-    default:
+  default:
     break;
   }

@@ -338,10 +340,10 @@
     char a[2];
     itoa(id, a, 10);
     deviceId[1] = a[0];
-    } else {
-      itoa(id, deviceId, 10);
-    }
-
-    Serial.print("my devide ID: ");
-    Serial.println(deviceId);
-  }
+  } else {
+    itoa(id, deviceId, 10);
+  }
+
+  Serial.print("my devide ID: ");
+  Serial.println(deviceId);
+}


Refactored function names to be cammelCase

--- alan/alan.ino
+++ alan/alan.ino
@@ -167,15 +167,10 @@
   Serial.print("Battery tick started id=");
   Serial.println(timer_battery);

-  action_stop();
+  actionStop();
   batteryLevel();
   whiskersCalibrate();
-  //whiskersStart();
-
-
-
-
-
+
 }

 void loop()
@@ -185,7 +180,7 @@
   if (irrecv.decode(&results))
   {
     /* If so get the button name for the received code */
-    ir_handleInput(results.value);
+    irHandleInput(results.value);
     //GetIRIndex(results.value);
     //Serial.println(GetIRIndex(results.value));
     /* Start receiving codes again*/
@@ -194,7 +189,7 @@

   // Let the timers do their thing.
   timer.run();
-  action_run();
+  actionRun();
   snd.update();
 }

@@ -250,23 +245,23 @@
 Ping functions
 ********************************************************************************/

-void ping_start()
+void pingStart()
 {
   if (ping_timer == 0) {
-    ping_timer = timer.setInterval(ping_delay, ping_measure);
+    ping_timer = timer.setInterval(ping_delay, pingMeasure);
   } else {
     timer.enable(ping_timer);
   }
   Serial.println("Ping started");
 }

-void ping_stop()
+void pingStop()
 {
   timer.disable(ping_timer);
   Serial.println("Ping stopped");
 }

-void ping_measure()
+void pingMeasure()
 {
   unsigned int cm = sonar.ping_cm(); // Send a ping, get ping distance in cm.
   //unsigned int cm = 0;
@@ -283,19 +278,19 @@
       Serial.println("Too close!");

       // No more pinging for now.
-      ping_stop();
+      pingStop();

       // Don't hit the obstacle.
-      motion_stop();
+      motionStop();

       // Make sure it's safe to play sounds
-      servo_detach_all();
+      servoDetachAll();

       // play sound
       playMelody();

-      action_pingSearch();
+      actionPingSearch();

     }
     /*
@@ -314,7 +309,7 @@
 /**
  * The "state machine" that handles action.
  */
-void action_run()
+void actionRun()
 {
   /*
   Serial.print("action_run ");
@@ -336,8 +331,8 @@
       switch (motion_state) {
         case M_STOP:
            // reverse for 1 second
-           action_timeoutStart(1000);
-           motion_rev();
+           actionTimeoutStart(1000);
+           motionRev();
            Serial.println("SEARCH REVERSE");
           break;

@@ -345,18 +340,18 @@
           if (action_done) {
             Serial.println("SEARCH LEFT");
             // Start pinging
-            ping_start();
+            pingStart();

-            action_timeoutStart(500); //@todo not fake the search!
-            motion_rotateLeft();
+            actionTimeoutStart(500); //@todo not fake the search!
+            motionRotateLeft();
           }
           break;

         case M_ROTATE_LEFT:
           if (action_done) {
             Serial.println("SEARCH RIGHT");
-            action_timeoutStart(2000); //@todo not fake the search!
-            motion_rotateRight();
+            actionTimeoutStart(2000); //@todo not fake the search!
+            motionRotateRight();
           }
           break;

@@ -364,15 +359,14 @@
           if (action_done) {
             Serial.println("SEARCH DONE");
             // Done the sweep, stop.
-            action_stop();
+            actionStop();

             // Stop pinging
-            ping_stop();
+            pingStop();

             // Trundle away
-            action_trundle();
-            //experimental_servoMove();
+            actionTrundle();
           }
           break;
       }
@@ -400,18 +394,18 @@
   }
 }

-void action_stop()
+void actionStop()
 {
   action_state = A_STOPPED;
-  motion_stop();
-  ping_stop();
+  motionStop();
+  pingStop();
   whiskersStop();
 }

 /**
  * Moves forward avoiding obstacles.
  */
-void action_trundle()
+void actionTrundle()
 {
   if (action_state != A_TRUNDLE) {
     Serial.println("TRUNDLING...");
@@ -419,35 +413,35 @@
     action_state = A_TRUNDLE;

     // Start pinging
-    ping_start();
+    pingStart();

     // Start feeling
     whiskersStart();

-    motion_fwd();
+    motionFwd();
   }
 }

 /**
  * Look for somewhare to go.
  */
-void action_pingSearch()
+void actionPingSearch()
 {
   Serial.println("SEARCHING");
   // Set the state, so the action can be handeled by the state machine.
   action_state = A_PINGSEARCH;
 }

-void action_timeoutStart(int duration)
+void actionTimeoutStart(int duration)
 {
   action_done = 0;
   // Delete the previous timer, so we can use it's slot.
   timer.deleteTimer(timer_action);
   // Start a new one.
-  timer_action = timer.setTimeout(duration, action_timeoutDone);
-}
-
-void action_timeoutDone()
+  timer_action = timer.setTimeout(duration, actionTimeoutDone);
+}
+
+void actionTimeoutDone()
 {
   action_done = 1;
 }
@@ -456,7 +450,7 @@
 Motion functions
 ********************************************************************************/

-void motion_stop()
+void motionStop()
 {

     analogWrite(motorA_pwm, 0); // Channel A at max speed
@@ -465,7 +459,7 @@

 }

-void motion_fwd()
+void motionFwd()
 {
 //@todo: set speed
   digitalWrite(motorA_direction, HIGH); // Channel A forward
@@ -475,7 +469,7 @@
   motion_state = M_FWD;
 }

-void motion_rev()
+void motionRev()
 {

     digitalWrite(motorA_direction, LOW); // Channel A backward
@@ -486,7 +480,7 @@

 }

-void motion_rotateLeft()
+void motionRotateLeft()
 {

     Serial.println("LEFT");
@@ -498,7 +492,7 @@

 }

-void motion_rotateRight()
+void motionRotateRight()
 {

     Serial.println("RIGHT");
@@ -555,9 +549,9 @@
        Serial.println("BUMP!");

       // Don't hit the obstacle.
-      motion_stop();
-
-      action_pingSearch();
+      motionStop();
+
+      actionPingSearch();
   }

 }
@@ -568,7 +562,7 @@
 ********************************************************************************/

 /* Function returns the button name relating to the received code */
-void ir_handleInput(unsigned long code){
+void irHandleInput(unsigned long code){
   /* Character array used to hold the received button name */
   char CodeName[3];
   /* Is the received code is a repeat code (NEC protocol) */
@@ -606,7 +600,7 @@
     /* Received code is for the FAST FORWARD button */
   case 0xFFC23D:
     strcpy (CodeName, "PL");
-    action_trundle();
+    actionTrundle();
     break;
     /* Received code is for the EQ button */
   case 0xFFE01F:
@@ -634,7 +628,7 @@
     /* Received code is for the number 1 button */
   case 0xFF30CF:
     strcpy (CodeName, "1");
-    action_stop();
+    actionStop();
     break;
     /* Received code is for the number 2 button */
   case 0xFF18E7:
@@ -681,7 +675,7 @@
 Experimental functions
 ********************************************************************************/

-void experimental_servoMove()
+void servoMove()
 {
   Serial.println("experimental_servoMove");

@@ -691,17 +685,17 @@

   servo_pinger.attach(6);
   servo_pinger.write(random(1100, 1800));
-  timer.setTimeout(500, servo_detach);
-}
-
-void servo_detach()
+  timer.setTimeout(500, servoDetach);
+}
+
+void servoDetach()
 {
   servo_pinger.detach();
   //EXPERIMENTAL!!
-  action_trundle();
-}
-
-void servo_detach_all()
+  actionTrundle();
+}
+
+void servoDetachAll()
 {
   servo_pinger.detach();
 }


correct accelstepper stuff

correct accelstepper stuff

--- KineticLicht.ino
+++ KineticLicht.ino
@@ -8,13 +8,15 @@

 // two stepper motors one on each port
-Adafruit_MotorShield AFMS_a(0x60);
-Adafruit_MotorShield AFMS_b(0x61);
-
+Adafruit_MotorShield AFMS_a = Adafruit_MotorShield(0x60);
+Adafruit_MotorShield AFMS_b = Adafruit_MotorShield(0x61);
+/*
 Adafruit_StepperMotor *motor1 = AFMS_a.getStepper(200, 1);
 Adafruit_StepperMotor *motor2 = AFMS_a.getStepper(200, 2);
 Adafruit_StepperMotor *motor3 = AFMS_b.getStepper(200, 1);
 Adafruit_StepperMotor *motor4 = AFMS_b.getStepper(200, 2);
+*/
+

 #define data   4
 #define clock  5
@@ -85,11 +87,17 @@
   {7000, BLUE}
 };

-
+/*
 KeyFrameStepper  stepper1 = KeyFrameStepper(motor1, 1, motor1_kf, 2);
 KeyFrameStepper  stepper2 = KeyFrameStepper(motor2, 2, motor2_kf, 2);
 KeyFrameStepper  stepper3 = KeyFrameStepper(motor3, 3, motor3_kf, 2);
 KeyFrameStepper  stepper4 = KeyFrameStepper(motor4, 4, motor4_kf, 2);
+*/
+Adafruit_StepperMotor *stepper1 = AFMS_a.getStepper(200, 1);
+Adafruit_StepperMotor *stepper2 = AFMS_a.getStepper(200, 2);
+Adafruit_StepperMotor *stepper3 = AFMS_b.getStepper(200, 1);
+Adafruit_StepperMotor *stepper4 = AFMS_b.getStepper(200, 2);
+
 KeyFrameRgbLED      rgb1o = KeyFrameRgbLED (&tlc, 0, rgb1u_kf, 3);
 KeyFrameRgbLED      rgb1u = KeyFrameRgbLED (&tlc, 1, rgb1o_kf, 3);
 KeyFrameRgbLED      rgb2o = KeyFrameRgbLED (&tlc, 2, rgb2u_kf, 3);
@@ -98,40 +106,69 @@
 KeyFrameRgbLED      rgb3u = KeyFrameRgbLED (&tlc, 5, rgb3o_kf, 3);
 KeyFrameRgbLED      rgb4o = KeyFrameRgbLED (&tlc, 6, rgb4u_kf, 3);
 KeyFrameRgbLED      rgb4u = KeyFrameRgbLED (&tlc, 7, rgb4o_kf, 3);
+// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
+void forwardstep1() {
+  stepper1->onestep(FORWARD, DOUBLE);
+}
+void backwardstep1() {
+  stepper1->onestep(BACKWARD, DOUBLE);
+}
+AccelStepper astepper1(forwardstep1, backwardstep1); // use functions to step
+
+void forwardstep2() {
+  stepper2->onestep(FORWARD, DOUBLE);
+}
+void backwardstep2() {
+  stepper2->onestep(BACKWARD, DOUBLE);
+}
+
+AccelStepper astepper2(forwardstep2, backwardstep2); // use functions to step
+
+void forwardstep3() {
+  stepper3->onestep(FORWARD, DOUBLE);
+}
+void backwardstep3() {
+  stepper3->onestep(BACKWARD, DOUBLE);
+}
+
+AccelStepper astepper3(forwardstep3, backwardstep3); // use functions to step
+
+void forwardstep4() {
+  stepper4->onestep(FORWARD, DOUBLE);
+}
+void backwardstep4() {
+  stepper4->onestep(BACKWARD, DOUBLE);
+}
+
+AccelStepper astepper4(forwardstep4, backwardstep4); // use functions to step

 RgbLED led = RgbLED( &tlc, 4);
-
-AccelStepper astepper1(motor1->onestep(FORWARD, SINGLE), motor1->onestep(BACKWARD, SINGLE)); // use functions to step
-AccelStepper astepper2(motor2->onestep(FORWARD, SINGLE), motor2->onestep(BACKWARD, SINGLE)); // use functions to step
-AccelStepper astepper3(motor3->onestep(FORWARD, SINGLE), motor3->onestep(BACKWARD, SINGLE)); // use functions to step
-AccelStepper astepper4(motor4->onestep(FORWARD, SINGLE), motor4->onestep(BACKWARD, SINGLE)); // use functions to step
-

 void setup()
 {
   Serial.begin(9600);
   Serial.println("start");
-
+
   AFMS_a.begin();
   AFMS_b.begin();
-
+/*
   stepper1.start();
   stepper2.start();
   stepper3.start();
   stepper4.start();
-
+*/
   astepper1.setSpeed(50);
   astepper2.setSpeed(100);
   astepper3.setSpeed(200);
-  astepper4.setSpeed(50);
-
+  astepper4.setSpeed(4000);
+/*
   astepper1.moveTo(300);
   astepper2.moveTo(500);
   astepper3.moveTo(200);
   astepper4.moveTo(300);
-
+*/
   tlc.begin();
-  led.doFineSerialOutput(true);
+  //led.doFineSerialOutput(true);

   rgb1o.start();
   rgb1u.start();
@@ -150,11 +187,11 @@
  //stepper3.loop();
  //stepper4.loop();

-  astepper1.runSpeed();
+  //astepper1.runSpeed();
   astepper2.runSpeed();
-  astepper3.runSpeed();
+  //astepper3.runSpeed();
   astepper4.runSpeed();
-
+
   //rgb1o.loop();
   //rgb1u.loop();
   //rgb2o.loop();


Add new animation, change delay loop

Add new animation, change delay loop

--- BlinkenScreen.ino
+++ BlinkenScreen.ino
@@ -19,6 +19,16 @@
   char b[BUFFER_SIZE];
   uint64_t i;
 };
+
+enum modes {
+  RAW_WIPE,
+  WIPE,
+  BUMP,
+  MODE_SENTINAL
+};
+
+
+screen s;

 const uint64_t conversion_table[] = {
   // Row 1
@@ -54,14 +64,6 @@
   // Sentinal
   0x00
 };
-
-enum modes {
-  RAW_WIPE,
-  WIPE,
-  MODE_SENTINAL
-};
-
-screen s;

 uint64_t massage(uint64_t data) {
   uint64_t scratch = 0;
@@ -116,7 +118,7 @@
   return val;
 }

-inline void wipe() {
+inline void animation_wipe() {
   static uint64_t i = 0;

   i = i == 0 ? 1 : i << 1;
@@ -124,9 +126,27 @@
   s.i = massage(i);
 }

-inline void raw_wipe() {
+inline void animation_raw_wipe() {
   // Show single pixel walking across the display
   s.i = s.i == 0 ? 1 : s.i << 1;
+}
+
+inline void animation_bump() {
+  static unsigned char i = 64;
+  static unsigned char dir = 0;
+
+  i = dir == 0 ? i >> 1 : i << 1;
+
+  if (i == 1 || i == 128)
+    dir ^= 1;
+
+  s.b[0] = i;
+  s.b[1] = i;
+  s.b[2] = i;
+  s.b[3] = i;
+  s.b[4] = i;
+  s.b[5] = i;
+  s.i = massage(s.i);
 }

 // NOTE: We want to pass a copy because SPI.transfer is destructive
@@ -140,18 +160,28 @@
 }

 // Unsigned allows us to modulo to correct value on overflow
-unsigned char mode = WIPE;
+unsigned char mode = BUMP;
 void loop() {
-  char button = read_buttons();
+  char button;
+
+  // TODO: Account for processing time in delay
+  for (int i = 0; i < 50; i++) {
+    button = read_buttons();
+    delay(10);
+  }

   switch (mode)
   {
     case RAW_WIPE:
-      raw_wipe();
+      animation_raw_wipe();
       break;

     case WIPE:
-      wipe();
+      animation_wipe();
+      break;
+
+    case BUMP:
+      animation_bump();
       break;

     // Outside range, correct it
@@ -160,8 +190,6 @@
   }

   print_framebuffer(s);
-
-  delay(10);

   if (button == B1)
     mode++;


adding water pump turn on and water level percent

--- plantstation.ino
+++ plantstation.ino
@@ -42,24 +42,25 @@
 AirMeasurement am;

 //===== For photoresistor =======================
+boolean lightIsOn = false;
 byte lightPercent;
 const byte lightOnThreshold = 90;
 const byte lightPin = A0;
-boolean lightIsOn = false;
-int lightMaxVal = 550;
-int lightMinVal = 6;
+const int lightMaxVal = 550;
+const int lightMinVal = 6;
 int lightResistorVal;

 //===== For hygrometer ==========================
 byte moisturePercent;
 const byte hygroPin = A1;
 // todo - find right value for this
-const int moistureThreshold = 1000; // <- made this up
-int moistureMaxVal = 960;
-int moistureMinVal = 50;
+const int moistureMaxVal = 960;
+const int moistureMinVal = 50;
 int moistureSensorVal;
+int moistureThreshold = 1000; // <- made this up

 //===== For water level sensor ===================
+byte waterLevelPercent;
 const byte waterSensorPin = A2;
 // todo - find right value for this
 const int waterLevelThreshold = 300; // <- made this up
@@ -69,13 +70,15 @@
 String waterLevelStatus = "OK";

 //===== For water pump ===========================
+#define WaterPump 5
+const byte waterPumpPin = A3;
 boolean waterPumpIsOn = false;
 unsigned long wateringSeconds = 61000;
 unsigned long prevWatering = 0;

 //===== For timed events =========================
 // todo - timed events use regule marers for 1 min 1 hour etc and divide blah
-unsigned long prevMinOneMillis = 0;
+unsigned long prevMinOneMillis = 0;
 unsigned long minOneInterval = 60000;
 unsigned long prevMinFiveMillis = 0;
 unsigned long minFiveInterval = 300000;
@@ -84,6 +87,7 @@

 void setup() {
   pinMode(LightSwitch, OUTPUT);
+  pinMode(WaterPump, OUTPUT);

   myDHT.begin();
   Bridge.begin();
@@ -135,6 +139,7 @@
   if (!waterPumpIsOn && waterLevelStatus == "OK" && moistureThreshold > moistureSensorVal) {
     prevWatering = millis();
     waterPumpIsOn = true;
+    digitalWrite(WaterPump, HIGH);
     Console.println("Watering started");
   }
 }
@@ -142,12 +147,15 @@
 void waterPlantStops(unsigned long currentMillis) {
     if (waterPumpIsOn && currentMillis >= prevWatering + wateringSeconds) {
     waterPumpIsOn = false;
+    digitalWrite(WaterPump, LOW);
     Console.println("Watering stopped");
   } else if (waterPumpIsOn && moistureThreshold < moistureSensorVal) {
     waterPumpIsOn = false;
+    digitalWrite(WaterPump, LOW);
     Console.println("Watering stopped");
   } else if (waterPumpIsOn && waterLevelStatus == "LOW") {
     waterPumpIsOn = false;
+    digitalWrite(WaterPump, LOW);
     Console.println("Watering stopped");
   }
 }
@@ -174,10 +182,10 @@
 }

 void readWaterLevelSensor() {
-  int val = analogRead(waterSensorPin);
-  waterLevelVal = map(val, waterMinVal, waterMaxVal, 0, 100);
-
-  if (val < waterLevelThreshold) {
+  waterLevelVal = analogRead(waterSensorPin);
+  waterLevelPercent = map(waterLevelVal, waterMinVal, waterMaxVal, 0, 100);
+
+  if (waterLevelVal < waterLevelThreshold) {
    waterLevelStatus = "LOW";
   } else {
    waterLevelStatus = "OK";
@@ -255,6 +263,7 @@
   my_output += ",\"MoistureValue\":";               my_output += moistureSensorVal;
   my_output += ",\"ProbeTemperatureCelcius\":";     my_output += sm.tempSoilC;
   my_output += ",\"ProbeTemperatureFahrenheit\":";  my_output += sm.tempSoilF;
+  my_output += ",\"WaterLevelPercent\":";           my_output += waterLevelPercent;
   my_output += ",\"WaterLevelValue\":";             my_output += waterLevelVal;
   my_output += ",\"WaterPumptIsOn\":";              my_output += waterPumpIsOn;
   my_output += "}";
@@ -295,6 +304,7 @@
   my_output += ";MoistureValue:";               my_output += moistureSensorVal;
   my_output += ";ProbeTemperatureCelcius:";     my_output += sm.tempSoilC;
   my_output += ";ProbeTemperatureFahrenheit:";  my_output += sm.tempSoilF;
+  my_output += ";WaterLevelPercent:";           my_output += waterLevelPercent;
   my_output += ";WaterLevelValue:";             my_output += waterLevelVal;
   my_output += ";WaterPumptIsOn:";              my_output += waterPumpIsOn;


Update FastLED sketch

Update FastLED sketch

--- FastLED/Arduino_Ethernet.ino
+++ FastLED/Arduino_Ethernet.ino
@@ -1 +1,303 @@
+/*
+ CheerLights!
+
+ CheerLights Channel --> Arduino Ethernet --> FastLED
+
+ This sketch subscribes to the CheerLights ThingSpeak Channel and relays the
+ last color from the Internet to a FastLED compatible RGB Light like Neopixels
+ or RGB-123 light panels. This sketch uses DHCP to obtain an IP address
+ automatically and requires Arduino 1.0+.
+
+ Arduino Requirements:
+
+ * Arduino Ethernet (or Arduino + Ethernet Shield)
+ * Arduino 1.0+ IDE
+ * FastLED Library
+ https://github.com/FastLED/FastLED/releases
+
+ Network Requirements:
+ * Ethernet port on Router
+ * DHCP enabled on Router
+ * Unique MAC Address for Arduino
+
+ Created: December 19, 2014 by Hans Scharler - http://nothans.com
+
+ Additional Credits:
+ Example sketches from FastLED
+
+ To join the CheerLights project, visit http://www.cheerlights.com
+
+ */
+
+#include <SPI.h>
+#include <Ethernet.h>
 #include "FastLED.h"
+
+// Define the number of LED in strip or on panel
+#define NUM_LEDS 8
+
+// For LED chips like Neopixels, which have a data line, ground, and power, you just
+// need to define DATA_PIN.  For LED chipsets that are SPI based (four wires - data, clock,
+// ground, and power), like the LPD8806, define both DATA_PIN and CLOCK_PIN
+#define DATA_PIN 6
+#define CLOCK_PIN 13
+
+// Define the array of LEDs
+CRGB leds[NUM_LEDS];
+
+// Local Network Settings
+byte mac[] = {
+  0xD4, 0x28, 0xB2, 0xFF, 0xA0, 0xA1 }; // Must be unique on local network
+
+// ThingSpeak / CheerLights Settings
+char thingSpeakAddress[] = "api.thingspeak.com";
+String thingSpeakChannel = "1417";                // Channel number of the CheerLights Channel
+String thingSpeakField = "1";                     // Field number of the CheerLights Colors
+const int thingSpeakInterval = 6 * 1000;         // Time interval in milliseconds to get data from ThingSpeak (number of seconds * 1000 = interval)
+
+// Variable Setup
+long lastConnectionTime = 0;
+String lastCommand = "";
+boolean lastConnected = false;
+int failedCounter = 0;
+
+// Initialize Arduino Ethernet Client
+EthernetClient client;
+
+void setup() {
+  // Setup Serial
+  Serial.begin(9600);
+  delay(100);
+
+  Serial.flush();
+  delay(100);
+
+  // Start Ethernet on Arduino
+  startEthernet();
+
+  // Setup FastLED
+  FastLED.addLeds<NEOPIXEL,DATA_PIN>(leds, NUM_LEDS);
+}
+
+void loop() {
+
+  // Process CheerLights Commands
+  if(client.available() > 0)
+  {
+    delay(100);
+
+    String response;
+    char charIn;
+
+    do {
+      charIn = client.read(); // read a char from the buffer
+      response += charIn; // append that char to the string response
+    }
+    while (client.available() > 0);
+
+    // Send matching commands to the GE-35 Color Effect Lights
+    if (response.indexOf("white") > 0)
+    {
+      lastCommand = "white";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::White;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("red") > 0)
+    {
+      lastCommand = "red";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Red;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("green") > 0)
+    {
+      lastCommand = "green";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Green;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("blue") > 0)
+    {
+      lastCommand = "blue";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Blue;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("cyan") > 0)
+    {
+      lastCommand = "cyan";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Cyan;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("magenta") > 0)
+    {
+      lastCommand = "magenta";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Magenta;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("yellow") > 0)
+    {
+      lastCommand = "yellow";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Yellow;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("purple") > 0)
+    {
+      lastCommand = "purple";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Purple;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("orange") > 0)
+    {
+      lastCommand = "orange";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Orange;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("warmwhite") > 0)
+    {
+      lastCommand = "warmwhite";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::OldLace;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("oldlace") > 0)
+    {
+      lastCommand = "oldlace";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::OldLace;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else if (response.indexOf("pink") > 0)
+    {
+      lastCommand = "pink";
+
+      for(int i = 0; i < NUM_LEDS; i++) {
+        leds[i] = CRGB::Pink;
+        FastLED.show();
+        delay(30);
+      }
+    }
+    else
+    {
+      lastCommand = "(no match)";
+    }
+
+    // Echo command
+    delay(200);
+    Serial.println("CheerLight Command Received: "+lastCommand);
+    Serial.println();
+    delay(200);
+  }
+
+  // Disconnect from ThingSpeak
+  if (!client.connected() && lastConnected)
+  {
+    Serial.println("...disconnected");
+    Serial.println();
+
+    client.stop();
+  }
+
+  // Subscribe to ThingSpeak Channel and Field
+  if(!client.connected() && (millis() - lastConnectionTime > thingSpeakInterval))
+  {
+    subscribeToThingSpeak(thingSpeakChannel, thingSpeakField);
+  }
+
+  // Check if Arduino Ethernet needs to be restarted
+  if (failedCounter > 3) {
+    startEthernet();
+  }
+
+  lastConnected = client.connected();
+
+} // End loop
+
+void subscribeToThingSpeak(String tsChannel, String tsField)
+{
+  if (client.connect(thingSpeakAddress, 80))
+  {
+    Serial.println("Connecting to ThingSpeak...");
+    Serial.println();
+
+    failedCounter = 0;
+
+    client.println("GET /channels/"+tsChannel+"/field/"+tsField+"/last.txt HTTP/1.0");
+    client.println();
+
+    lastConnectionTime = millis();
+  }
+  else
+  {
+    failedCounter++;
+
+    Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");
+    Serial.println();
+
+    lastConnectionTime = millis();
+  }
+}
+
+void startEthernet()
+{
+
+  client.stop();
+
+  Serial.println("Connecting Arduino to network...");
+  Serial.println();
+
+  delay(1000);
+
+  // Connect to network amd obtain an IP address using DHCP
+  if (Ethernet.begin(mac) == 0)
+  {
+    Serial.println("DHCP Failed, reset Arduino to try again");
+    Serial.println();
+  }
+  else
+  {
+    Serial.println("Arduino connected to network using DHCP");
+    Serial.println();
+  }
+
+  delay(1000);
+}


Added logic to display the door status on the LCD if we detect that they are opened

--- garage/garage.ino
+++ garage/garage.ino
@@ -74,22 +74,30 @@
   lcd.print(clock.dateFormat("m/d/y h:iA", dt));

   lcd.setCursor(0,1);
-  String alarmString = "ALARM: " + String(triggerHour-12) + ":" + String(triggerMinute) + " " + triggerAMPM;
-  lcd.print(alarmString);
+
+  // Display the door status on the LCD if we detect one of the doors opened.
+  if (door1SensorState == true || door2SensorState == true) {
+    String door1Status = (door1SensorState) ? "OPN" : "CLD";
+    String door2Status = (door2SensorState) ? "OPN" : "CLD";
+    lcd.print("D1:" + door1Status + "    D2:" + door2Status);
+  } else {
+    String alarmString = "ALARM: " + String(triggerHour-12) + ":" + String(triggerMinute) + " " + triggerAMPM + " ";
+    lcd.print(alarmString);
+  }
 }

 void displayDoorStatus(){

   lcd.clear();

-  String door1Status = (door1SensorState) ? "OPEN" : "CLOSED";
-  String door2Status = (door2SensorState) ? "OPEN" : "CLOSED";
+  String door1Status = (door1SensorState) ? "OPN" : "CLD";
+  String door2Status = (door2SensorState) ? "OPN" : "CLD";

   lcd.setCursor(0,0);
-  lcd.print("DOOR #1 IS " + door1Status);
+  lcd.print("WARNING CHK DOOR");

   lcd.setCursor(0,1);
-  lcd.print("DOOR #2 IS " + door2Status);
+  lcd.print("D1:" + door1Status + "    D2:" + door2Status);
 }

 void checkSensorState() {


modified:   mcu_main/mcu_main.ino

modified:   mcu_main/mcu_main.ino

--- mcu_main/mcu_main.ino
+++ mcu_main/mcu_main.ino
@@ -28,7 +28,7 @@
 {

   State state;
-  state.spd = 200;
+  state.spd = 10;
   state.steps = 150;
   state.running = true;
   state.cw = false;
@@ -67,15 +67,15 @@
     delay(10000/(state->spd));
   }
 }
-
+//!  speed range: [10,500]
 void full_step(const State* state)
 {
   //!  specify the starting index according to the direction
   unsigned a,b,c,d;
-  b = 3;
-  d = 2;
   a = state->cw?  1  :  0;
-  c = state->cw?  0  :  1;
+  c = state->cw?  0  :  1;
+  b = state->cw?  3  :  2;
+  d = state->cw?  2  :  3;

   //!  move steps as specified if running == true.
   boolean arr[4] = {1,1,0,0};


Fixed missing semicolon

Fixed missing semicolon

--- examples/ComplementaryFilter/ComplementaryFilter.ino
+++ examples/ComplementaryFilter/ComplementaryFilter.ino
@@ -82,7 +82,7 @@
                       mag_event.magnetic.z);

   // Process the sensor data
-  filter.update()
+  filter.update();

   // Send out the now up-to-date quaternion
   Serial.print(filter.orientation.w()); Serial.print(',');