Final Competition code

Final Competition code

--- firefighter/firefighter.ino
+++ firefighter/firefighter.ino
@@ -32,7 +32,7 @@

 // PID
 #define setpoint 0
-#define kP 0.05
+#define kP 0.002

 Servo extingusher_servo;

@@ -55,8 +55,8 @@
 Ultrasonic leftArrayOutter(32, 33, true);//orange

 Ultrasonic rightArrayInner(36, 37, true);//orange
-Ultrasonic rightArrayOutter(38, 39, true);//black
-
+Ultrasonic rightArrayOutter(38, 39, true);//black
+
 void ultrasonicArrayCheck();

 MPU6050 mpu; // Default address 0x68
@@ -65,6 +65,7 @@
 void driveToWhite();
 void driveThroughRoom();
 void hDrive(double move, double rotate, double strafe);
+void pidMove(double move, double rotate, double strafe);
 void tankDrive(double leftSpeed, double rightSpeed, double strafeSpeed);
 void definedStartSearch();
 double getPercentError(double actual, double target);
@@ -209,6 +210,8 @@
 bool firstStart = false;
 bool foundFlame = false;

+double heading = 0;
+
 void loop() {
   // put your main code here, to run repeatedly:
   if (FreqCount.available()) {
@@ -216,7 +219,7 @@
 	  //Serial.println(count);
   } else {
     count = 0;
-  }
+  }

 //  Serial.println(getAngle('z'));
   if ((count > 3230 && count < 4370) || digitalRead(startSwitch)) {
@@ -236,28 +239,30 @@
   	while(!foundFlame && digitalRead(flame_sensor)) {
 		naviguessMaze(0.3);
 		// Serial.println(getAngle());
-       // ultrasonicCheck();
-	   // ultrasonicArrayCheck();
+       // ultrasonicCheck();
+	   ultrasonicArrayCheck();
       // drivetrainCheck();

-//      if (!pidEnabled) {
-//        pidEnabled = true;
-//        resetGyro('z');
-//      }
-//      hDrive(0.5, getPidOutput(), 0.0);   // Correctional driving
-//      Serial.println(getPidOutput());
-
+		// hDrive(0.3, 0.0, 0.0);
   	}

   	foundFlame = true;
-  	// digitalWrite(FLAME_LED, foundFlame);
+  	// digitalWrite(FLAME_LED, foundFlame);
 	digitalWrite(FLAME_LED, true);
-  	hDrive(0.0, 0.0, 0.0);
-
-	while (true) {
-		pulseFan();
-		digitalWrite(FLAME_LED, !digitalRead(flame_sensor));
-	}
+  	hDrive(0.0, 0.0, 0.0);
+
+  fan_motor.set(1.0);
+
+  	while (true) {
+  //		pulseFan();
+      if (frontUltrasonic.getDistance() > 3) {
+          hDrive(0.3, 0.0, 0.0);
+          delay(200);
+          hDrive(0.0, 0.0, 0.0);
+          delay(400);
+      }
+  		digitalWrite(FLAME_LED, !digitalRead(flame_sensor));
+  	}
   } else{
     digitalWrite(SOUND_LED, LOW);
     firstStart = false;
@@ -265,24 +270,25 @@
   }

 //  delay(100);
-}
-
-void pulseFan() {
-	fan_motor.set(1.0);
-	delay(3000);
-	fan_motor.set(0.0);
-	delay(500);
+}
+
+void pulseFan() {
+	fan_motor.set(1.0);
+	delay(3000);
+	fan_motor.set(0.0);
+
+	delay(500);
 }

 void hDrive(double move, double rotate, double strafe) {
   double leftSpeed, rightSpeed;
-
-  move = constrain(move, -1.0, 1.0);
-  rotate = constrain(rotate, -1.0, 1.0);
-  strafe = constrain(strafe, -1.0, 1.0);
-
+
+	move = constrain(move, -1.0, 1.0);
+	rotate = constrain(rotate, -1.0, 1.0);
+	strafe = constrain(strafe, -1.0, 1.0);
+
   if (move > 0.0) {
-    if (rotate > 0.0) {
+	  if (rotate > 0.0) {
       leftSpeed =  move - rotate;
       rightSpeed = max(move, rotate);
     } else {
@@ -305,6 +311,22 @@
   rightMotor2.set(-constrain(rightSpeed, -1.0, 1.0));
   strafeMotor.set(strafe);
 }
+
+
+//  void pidMove(double move, double rotate, double strafe) {
+//     if (rotate == 0.0 && move != 0.0) {
+//       if (!pidEnabled) {
+//         pidEnabled = true;
+//         heading = getAngle('z');
+//       } else {
+//         hDrive(move, getPidOutput(), 0.0);   // Correctional driving
+//       }
+//     } else {
+//       pidEnabled = false;
+//       hDrive(move, rotate, strafe);
+//     }
+//     }
+//  }

 void drivetrainCheck() {
   hDrive(0.3, 0.0, 0.0); delay(300); hDrive(-0.3, 0.0, 0.0); delay(300);
@@ -323,20 +345,20 @@
 	Serial.print("B: ");
 	Serial.println(backUltrasonic.getDistance());
 	delay(300);
-}
-
-void ultrasonicArrayCheck() {
-	Serial.println("====================================");
-	Serial.print("LI: ");
-	Serial.println(leftArrayInner.getDistance());
-	Serial.print("LO: ");
-	Serial.println(leftArrayOutter.getDistance());
-	Serial.print("RI: ");
-	Serial.println(rightArrayInner.getDistance());
-	Serial.print("RO: ");
-	Serial.println(rightArrayOutter.getDistance());
-	delay(300);
-}
+}
+
+void ultrasonicArrayCheck() {
+	Serial.println("====================================");
+	Serial.print("LI: ");
+	Serial.println(leftArrayInner.getDistance());
+	Serial.print("LO: ");
+	Serial.println(leftArrayOutter.getDistance());
+	Serial.print("RI: ");
+	Serial.println(rightArrayInner.getDistance());
+	Serial.print("RO: ");
+	Serial.println(rightArrayOutter.getDistance());
+	delay(300);
+}

 void driveToWhite() {
@@ -436,12 +458,12 @@
 }

 void turnToAngle(double targetAngle, double speed) {
-  resetGyro('z');
-  // resetEncoders();
+  // resetGyro('z');
+  resetEncoders();
   hDrive(0.0, speed, 0.0);

-  while (abs(getAngle('z')) < abs(targetAngle)) {
-    Serial.println(getAngle('z'));
+  while (abs(getAngle()) < abs(targetAngle)) {
+    Serial.println(getAngle());
   }

   hDrive(0.0, 0.0, 0.0);
@@ -460,7 +482,7 @@
 }

 double getPidOutput() {
-  return (setpoint - getAngle('x')) * kP;
+  return (heading - getAngle('z')) * kP;
 }

 // void extinguish() {
@@ -511,10 +533,13 @@
 	bool rightTriggered = rightUltrasonic.getDistance() < 2;
 	bool backTriggered = backUltrasonic.getDistance() < 2;
   bool rightFavor = rightUltrasonic.getDistance() <7 && rightUltrasonic.getDistance() > 2 && frontUltrasonic.getDistance() < 20;
-  bool rightInner = rightArrayInner.getDistance() < 5;
+  bool rightInner = rightArrayInner.getDistance() < 7;
   bool rightOuter = rightArrayOutter.getDistance() < 5;
-  bool leftInner = leftArrayInner.getDistance() < 5;
+  bool leftInner = leftArrayInner.getDistance() < 7;
   bool leftOuter = leftArrayOutter.getDistance() < 5;
+  int trial = 0;
+
+

 	if (leftTriggered && frontTriggered) {
 		hDrive(-swagSpeed, 0.0, 0.0);
@@ -542,10 +567,10 @@
 		}
 	} else if (leftTriggered && !frontTriggered) {
 		// hDrive(swagSpeed - 0.2, -swagSpeed, 0.0);
-		turnToAngle(2, -swagSpeed);
+		turnToAngle(1, -swagSpeed);
 	} else if (rightTriggered && !frontTriggered) {
 		//hDrive(swagSpeed - 0.2, swagSpeed , 0.0);
-		turnToAngle(-2, swagSpeed);
+		turnToAngle(-1, swagSpeed);
 	} else if (frontTriggered && !rightTriggered & !leftTriggered){
 		hDrive(-swagSpeed, 0.0, 0.0);
 		delay(50);
@@ -564,9 +589,9 @@
 		hDrive(0.0, 0.0, swagSpeed);
 		while (rightUltrasonic.getDistance() > 2.5) { }
 		hDrive(0.0, 0.0, 0.0);
-  // } else if(rightInner || rightOuter && !frontTriggered) {
-		// hDrive(-swagSpeed, 0.0, 0.0);
-		// delay(100);
+   }  if(rightInner  ) {
+		 hDrive(-swagSpeed, 0.0, 0.0);
+		 delay(1000);
     // turnToAngle(-15, swagSpeed);
   // } else if(leftInner || leftOuter && !frontTriggered) {
 		// hDrive(-swagSpeed, 0.0, 0.0);
@@ -585,6 +610,7 @@
 	direction = !direction;

 	delay(50);
+
 }

 void tankDrive(double leftSpeed, double rightSpeed, double strafeSpeed) {
@@ -669,13 +695,13 @@
 void resetGyro(char axis) {
   switch (axis) {
     case 'x':
-      gyroResetValX += getAngle('x');
+      gyroResetValX = getAngle('x');
       break;
     case 'y':
-      gyroResetValY += getAngle('y');
+      gyroResetValY = getAngle('y');
       break;
     case 'z':
-      gyroResetValZ += getAngle('z');
+      gyroResetValZ = getAngle('z');
       break;
-  }
+  }
 }


compass example: removed leftover comment

--- ZumoMotors/examples/CompassExample/CompassExample.ino
+++ ZumoMotors/examples/CompassExample/CompassExample.ino
@@ -157,29 +157,24 @@
   }
   else
   {
-    // To avoid overshooting, the closer the Zumo gets to the target
+    // To avoid overshooting, the closer the Zumo gets to the target
     // heading, the slower it should turn. Set the motor speeds to a
     // minimum base amount plus an additional variable amount based
     // on the heading difference.
-
+
     speed = SPEED*relative_heading/180;
-
+
     if (speed < 0)
       speed -= TURN_BASE_SPEED;
     else
       speed += TURN_BASE_SPEED;
-
+
     motors.setSpeeds(speed, -speed);

     Serial.print("   Turn");
   }
   Serial.println();
 }
-
-// The closer we get to our driving angle, the slower we will turn.
-// We do not want to overshoot our direction.
-// turnLeft() takes the ideal speed and refactors it accordingly to how close
-// the zumo is pointing towards the direction we want to drive.

 // Converts x and y components of a vector to a heading in degrees.
 // This function is used instead of LSM303::heading() because we don't
@@ -201,13 +196,13 @@
 int relativeHeading(int heading_from, int heading_to)
 {
   int relative_heading = heading_to - heading_from;
-
+
   // constrain to -180 to 180 degree range
   if (relative_heading > 180)
     relative_heading -= 360;
   if (relative_heading < -180)
     relative_heading += 360;
-
+
   return relative_heading;
 }


Follow the Arduino Coding Rules #4

Follow the Arduino Coding Rules #4

Follow the Arduino Example Style Guide.

--- sample/blink_3leds.ino
+++ sample/blink_3leds.ino
@@ -1,44 +1,48 @@
 /*
-MIT License
+  Blink 3 LEDs
+  Run the following tasks, concurrently and repeatedly:
+  * blinkLed1: Turns on the LED1 on for 100ms, then off for 100msec, then on for 100ms, then off for 100msec.
+  * blinkLed2: Turns on the LED2 on for 200ms, then off for 200msec.
+  * blinkLed3: Turns on the LED3 off for 200ms, then on for 200msec.

-Copyright (c) 2016 Susumu Yamazaki
+  The circuit:
+  * LED1: pin 9
+  * LED2: pin 10
+  * LED3: pin 11

-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+  Created 1 Sep 2016
+  By Susumu Yamazaki
+  Modified 4 Sep 2016
+  By Susumu Yamazaki
 */

 #include <Zackernel.h>

-#define LED1 9    // I/O Port of LED 1
-#define LED2 10   // I/O Port of LED 2
-#define LED3 11   // I/O Port of LED 3
+const int LED1 = 9;    // I/O Port of LED 1
+const int LED2 = 10;   // I/O Port of LED 2
+const int LED3 = 11;   // I/O Port of LED 3

-#define TIC 100   // Unit Time of Blinking (msec)
+const int TIC = 100;   // Unit Time of Blinking (msec)

 void setup() {
+  // setup pinMode of LEDs
   pinMode(LED1, OUTPUT);
   pinMode(LED2, OUTPUT);
   pinMode(LED3, OUTPUT);
-  Zackernel::init(); // initializing Zackernel
+
+  // initializing Zackernel
+  Zackernel::init();
 }

-// Blink LED1 using sleep()
-void blink_led1() {
+// Loop and Fork Tasks for blinking LED1, LED2 and LED3
+void loop() {
+  // fork subroutines (blinkLed1, blinkLed2, blinkLed3)
+  // these will be running concurrently.
+  fork(blinkLed1, [&] { fork(blinkLed2, blinkLed3); });
+}
+
+// Blink LED1 with sleeping and awaking
+void blinkLed1() {
   digitalWrite(LED1, HIGH);
   sleep(TIC, [&] {
      digitalWrite(LED1, LOW);
@@ -52,8 +56,8 @@
   });
 }

-// Blink LED2 using sleep()
-void blink_led2() {
+// Blink LED2 with sleeping and awaking
+void blinkLed2() {
   digitalWrite(LED2, HIGH);
   sleep(TIC * 2, [&] {
      digitalWrite(LED2, LOW);
@@ -61,8 +65,8 @@
   });
 }

-// Blink LED3 using sleep()
-void blink_led3() {
+// Blink LED3 with sleeping and awaking
+void blinkLed3() {
   digitalWrite(LED3, LOW);
   sleep(TIC * 2, [&] {
      digitalWrite(LED3, HIGH);
@@ -70,7 +74,3 @@
   });
 }

-// Loop and Fork Tasks for blinking LED1, LED2 and LED3
-void loop() {
-  fork(blink_led1, [&] { fork(blink_led2, blink_led3); });
-}


changed raingauge switch glitch time protection from 10ms to 10ms

--- mwsLRWHFv2/mwsLRWHFv2.ino
+++ mwsLRWHFv2/mwsLRWHFv2.ino
@@ -185,7 +185,7 @@
   raintime = millis(); // grab current time
   raininterval = raintime - rainlast; // calculate interval between this and last event

-  if (raininterval > 10) // ignore switch-bounce glitches less than 10mS after initial edge
+  if (raininterval > 100) // ignore switch-bounce glitches less than 10mS after initial edge
   {
     dailyrainin += rain_bucket_mm;
     rainHour[minutes] += rain_bucket_mm; //Increase this minute's amount of rain


Slow twinkle, fast rainbow.

Slow twinkle, fast rainbow.

--- arduino/rainbow_cloud/rainbow_cloud/rainbow_cloud.ino
+++ arduino/rainbow_cloud/rainbow_cloud/rainbow_cloud.ino
@@ -81,9 +81,9 @@
   strip.show();
 }

-TimedAction ta_updateTwinkle = TimedAction(15, updateTwinkle);
+TimedAction ta_updateTwinkle = TimedAction(10, updateTwinkle);
 TimedAction ta_showStrip = TimedAction(1, show_strip);
-TimedAction ta_updateRainbow = TimedAction(30, updateRainbow);
+TimedAction ta_updateRainbow = TimedAction(10, updateRainbow);
 TimedAction ta_updateTwinkleLocation = TimedAction(1000, updateTwinkleLocation);

@@ -97,7 +97,7 @@

   twinkles[0][0] = random(0,NUM_PIXELS - 3);
   twinkles[0][2] = 1;
-  twinkles[0][3] = 10;
+  twinkles[0][3] = 1;
 }


[LedDude] Process RFID lock onboard.

[LedDude] Process RFID lock onboard.

Signed-off-by: Juri Berlanda <5bfdca9e82c53adb0603ce7083f4ba4f2da5cacf@hotmail.com>

--- laundry-dude-led-sensor/laundry-dude-led-sensor.ino
+++ laundry-dude-led-sensor/laundry-dude-led-sensor.ino
@@ -34,6 +34,12 @@
 uint8_t fifoBuffer[64];

 char rfidTag[TAG_LENGTH + 1];
+char lockTag[TAG_LENGTH + 1];
+bool locked = false;
+unsigned long lastRead = 0;
+
+char buffer[TAG_LENGTH + 1];
+int count = 0;

 // Software serial for XBee module
 SoftwareSerial xbeeSerial(2, 3); // RX, TX
@@ -53,41 +59,123 @@
   initMpu();
 }

-void setLockState(bool locked) {
-  digitalWrite(A0, locked);
-}
-
 bool readRfid() {
-  char buffer[TAG_LENGTH];
-  int count = 0;
   bool tagChanged = false;
-
-  if (rfidSerial.available()) {
-    if (rfidSerial.read() != 2)
-      return false;
-    while (count < TAG_LENGTH && rfidSerial.available()) {
-      buffer[count] = rfidSerial.read();
+  bool ret = false;
+  char tmp;
+
+  while (rfidSerial.available()) {
+    while (rfidSerial.available() && count == -1) {
+      tmp = rfidSerial.read();
+      Serial.println((int)tmp);
+      if (tmp == 2) {
+        count++;
+        buffer[TAG_LENGTH] = 0;
+        Serial.println("Got start");
+      }
+    }
+
+    while (count > -1 && count < TAG_LENGTH && rfidSerial.available()) {
+      tmp = rfidSerial.read();
+      if (tmp == 2) {
+        count = 0;
+        return false;
+      }
+      buffer[count] = tmp;
       count++;
     }

     if (count == TAG_LENGTH) {
       count = 0;
+
       if (rfidSerial.read() != 3)
         return false;
-      for (int i = 0; i < TAG_LENGTH; i++) {
-        tagChanged |= buffer[i] != rfidTag[i];
-      }
-    }
-    if (tagChanged) {
+
+      if (!checkRfidChecksum(buffer))
+        return false;
+
       memcpy(rfidTag, buffer, TAG_LENGTH);
       rfidTag[TAG_LENGTH] = 0;
-      Serial.print("Changed: "); Serial.println(rfidTag);
-    }
+      return true;
+    }
+  }
+  return false;
+}
+
+bool compareReadTag(const char* otherTag) {
+  bool ret = true;
+
+  for (int i = 0; i < TAG_LENGTH; i++) {
+    ret &= otherTag[i] == rfidTag[i];
+  }
+
+  return ret;
+}
+
+bool checkRfidChecksum(const char* buffer) {
+  uint16_t checkSum = 0;
+  char checkSum_L = 0;
+  char checkSum_H = 0;
+  String hexstr = "";
+  uint16_t tmp = 0;
+
+  // Calculate
+  for (int i = 0; i < (TAG_LENGTH - 2) / 2; i++) {
+    hexstr = "0x";
+    hexstr += buffer[2*i];
+    hexstr += buffer[2*i + 1];
+
+    tmp = strtoul(hexstr.c_str(), 0, 16);
+    checkSum = checkSum ^ tmp;
+  }
+
+  // Check
+  hexstr = "0x";
+  hexstr += buffer[TAG_LENGTH - 2];
+  hexstr += buffer[TAG_LENGTH - 1];
+  tmp = strtoul(hexstr.c_str(), 0, 16);//hexstr.toInt();
+  return checkSum == tmp;
+}
+
+void setLockState(bool newState) {
+  digitalWrite(A0, newState);
+  locked = newState;
+
+  // Clear lock Tag
+  if (!newState)
+    for (int i = 0; i < TAG_LENGTH; i++)
+      lockTag[i] = '#';
+
+}
+
+void processRfid() {
+  if (!readRfid())
+    return;
+
+  // FIXME: Runs over after 50 days!
+  if (millis() - lastRead < 1000) {
+    lastRead = millis();
+    return;
+  }
+  lastRead = millis();
+
+  if (locked) {
+    bool tagValid = compareReadTag(lockTag);
+    if (tagValid) {
+      Serial.print("Tag valid: "); Serial.println(rfidTag);
+    } else {
+      Serial.print("Tag invalid: "); Serial.println(rfidTag);
+    }
+    setLockState(!tagValid);
+  } else {
+    setLockState(true);
+    memcpy(lockTag, rfidTag, TAG_LENGTH + 1);
+    Serial.print("Locked with tag: "); Serial.println(lockTag);
   }
 }

 void loop() {
-  readRfid();
+  processRfid();
   readLightsensor();
   readDataFromMpu();

@@ -111,9 +199,8 @@
       }
       break;
     case 'r':
-      xbeeSerial.print("r=");xbeeSerial.println(rfidTag);
-      while (xbeeSerial.available())
-        xbeeSerial.read();
+      // FIXME: This is highly dangerous
+      xbeeSerial.print("r=");xbeeSerial.println(lockTag);
       break;
     }
   }


Implement rainbow mode

Implement rainbow mode

--- main.ino
+++ main.ino
@@ -22,14 +22,13 @@
 CRGB leds[NUM_LEDS];

 /* All the different modes that are available. */
-#define MAX_MODES 1
+#define MAX_MODES 2
 void modeSolid();
+void modeRainbow();
 void (*modes[MAX_MODES])() = {
-    &modeSolid
+    &modeSolid,
+    &modeRainbow
 };
-
-/* Currently active mode. */
-uint8_t activeMode = 0;

 /* Define the different parameters that can be changed using the rotary wheel. */
 #define PARAMETER_MODE 0
@@ -45,7 +44,7 @@
 uint8_t activeParameter = PARAMETER_MODE;

 /* Holds the values of the different parameters. */
-uint8_t parameters[MAX_PARAMETERS] = { 0, 0, 255, 80, 80, 0, 0 };
+uint8_t parameters[MAX_PARAMETERS] = { 0, 146, 255, 180, 128, 0, 0 };

 /* Maximum values of the different parameters, plus one. Zero denotes that a
  * variable can stretch the full range of 0-255. */
@@ -54,12 +53,12 @@
 /* Rainbow colors, used to signify active parameter to the user. */
 CRGB rainbowColors[MAX_PARAMETERS] = {
     CHSV(0,   255, 255),
-    CHSV(36,  255, 255),
-    CHSV(73,  255, 255),
-    CHSV(109, 255, 255),
-    CHSV(146, 255, 255),
-    CHSV(182, 255, 255),
-    CHSV(219, 255, 255)
+    CHSV(21,  255, 255),
+    CHSV(43,  255, 255),
+    CHSV(85,  255, 255),
+    CHSV(170, 255, 255),
+    CHSV(198, 255, 255),
+    CHSV(226, 255, 255)
 };

 /* Initial setup, called once on boot. */
@@ -102,6 +101,29 @@
     return rval;
 }

+/* stepAnimation returns true if it is time for the next step in the animation,
+ * according to the SPEED parameter. */
+bool stepAnimation() {
+    static uint32_t lastClock = 0;
+    uint32_t diff;
+    uint32_t clock;
+    uint32_t expectedDelay;
+
+    /* Animations are disabled when speed is zero */
+    if (parameters[PARAMETER_SPEED] == 0) {
+        return false;
+    }
+
+    clock = millis();
+    diff = clock - lastClock;
+
+    /* Otherwise, delay 1/SPEED milliseconds */
+    lastClock = clock;
+    expectedDelay = 1000 / parameters[PARAMETER_SPEED];
+
+    return diff >= expectedDelay;
+}
+
 /* modeSolid draws a solid color across all LEDs, according to the parameters
  * HUE, SATURATION, VALUE. */
 void modeSolid() {
@@ -112,6 +134,27 @@
     ));
 }

+/* modeRainbow draws an animated rainbow across all LEDs. */
+void modeRainbow() {
+    static uint8_t animation_hue = 0;
+    uint8_t hue;
+    uint8_t step;
+
+    step = 255 / NUM_LEDS;
+
+    for (uint8_t led = 0; led < NUM_LEDS; led++) {
+        hue = animation_hue - parameters[PARAMETER_HUE] - (led * step);
+        leds[led] = CHSV(hue, parameters[PARAMETER_SATURATION], parameters[PARAMETER_VALUE]);
+    }
+
+    if (!stepAnimation()) {
+        return;
+    }
+
+    animation_hue--;
+}
+
+/* loop is called continuously. */
 void loop() {

     /* Increase active parameter if button is pressed. */
@@ -131,6 +174,6 @@
     parameters[activeParameter] %= parameterMax[activeParameter];

     /* Run the currently active mode. */
-    modes[activeMode]();
+    modes[parameters[PARAMETER_MODE]]();
     FastLED.show();
 }


updated welcome trace message

updated welcome trace message

to reflect actual software version

--- SRC/ArincShieldAutoTest.ino
+++ SRC/ArincShieldAutoTest.ino
@@ -73,7 +73,7 @@
 void setup() {
   // open serial port for debug
   Serial.begin(9600);
-  Serial.println(F("\t>> Arinc 429 shield test program V1.01 <<\n"));
+  Serial.println(F("\t>> Arinc 429 shield test program V1.03 <<\n")); // JPP V1.03

   // in/out pins configuration
   pinMode(SS,     OUTPUT);


send receiver readings to host only when changed

--- Arduino/firmware/firmware.ino
+++ Arduino/firmware/firmware.ino
@@ -203,6 +203,8 @@
   static uint8_t rc_outputs_throttle = MOTOR_NEUTRAL;
   static unsigned long dt;
   static unsigned long t0;
+  static uint8_t last_steeringIn;
+  static uint8_t last_throttleIn;
   unsigned long now;
   uint8_t rc_inputs_steering;
   uint8_t rc_inputs_throttle;
@@ -223,15 +225,18 @@
     rc_inputs_throttle = microseconds2PWM(throttleIn);
     rc_inputs_steering = microseconds2PWM(steeringIn);

-    // send readings to the host
-    if (rawOutput) {
-      Serial.print(throttleIn);
-      Serial.print(" ");
-      Serial.println(steeringIn);
-    } else {
-      Serial.print(rc_inputs_throttle);
-      Serial.print("  ");
-      Serial.println(rc_inputs_steering);
+    // send readings to the host only when changed
+    if ((1 < abs(last_throttleIn - throttleIn)) || (1 < abs(last_steeringIn - steeringIn))) {
+      // send readings to the host
+      if (rawOutput) {
+        Serial.print(throttleIn);
+        Serial.print(" ");
+        Serial.println(steeringIn);
+      } else {
+        Serial.print(rc_inputs_throttle);
+        Serial.print("  ");
+        Serial.println(rc_inputs_steering);
+      }
     }
     t0 = millis();
   }


Update Display_Unicode.ino

Update Display_Unicode.ino

--- examples/Advanced/Display_Unicode/Display_Unicode.ino
+++ examples/Advanced/Display_Unicode/Display_Unicode.ino
@@ -4,7 +4,7 @@
   Pls modify <m5stack path>/src/utility/In_eSPI_Setup.h, At the end of the file add "#define USE_M5_FONT_CREATOR"
   if want get customize unicode, try use https://github.com/m5stack/FontCreator, create font file

-  if add "#define USE_M5_FONT_CREATOR" and want to use gfx font, need modify font file
+  if add "#define USE_M5_FONT_CREATOR" and want to use standard gfx font, need modify font file
     #ifdef USE_M5_FONT_CREATOR
     0, 0,
     #endif
@@ -51,4 +51,4 @@
     M5.Lcd.printf("⛣⛤⛥⛦⛧⛨⛩⛪⛫⛬⛭⛮⛯F⛰⛱⛲⛳⛴⛵⛶⛷⛸⛹⛺⛻⛼⛽⛾⛿✀✁✂✃✄✅✆✇✈✉✊✋✌✍✎✏✐✑✒✓✔✕✖✗✘✙✚✛✜✝✞✟✠✡✢✣✤✥✦✧✨✩✪✫✬✭✮✯✰✱✲✳✴✵✶✷✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋❌❍❎❏❐❑❒❓❔❕❖❗❘❙❚❛❜❝❞❟❠❡❢❣❤❥❦❧❨❩❪❫❬❭❮❯❰❱❲❳❴❵❶❷❸❹❺❻❼❽❾❿➀➁➂➃➄➅➆➇➈➉➊➋➌➍➎➏➐➑➒➓➔➕➖➗➘➙➚➛➜➝➞➟A➠➡➢➣➤➥➦➧➨➩➪➫➬➭➮➯B➰➱➲➳➴➵➶➷➸➹➺➻➼➽➾➿");
     delay(3000);

-}+}


Removed delay

Removed delay

--- examples/BoardsAndShields/RN_XV_WiFly/RN_XV_WiFly.ino
+++ examples/BoardsAndShields/RN_XV_WiFly/RN_XV_WiFly.ino
@@ -54,8 +54,6 @@

   WiFly.setUart(&WiFlySerial);

-  delay(10000);
-
   Blynk.begin(auth, "ssid", "pass");
 }


re-factor display test loop into setup()

The idea here is that we can do long-running setup while the display
test is active but we shouldn't actually be responding to user input
during that time.

--- src/monitor-firmware.ino
+++ src/monitor-firmware.ino
@@ -14,9 +14,7 @@
 // Status bits
 byte status_bits;

-// Showing display test and time at which test started
-bool showing_dt;
-unsigned long dt_shown_at;
+// How long to show display test for
 const int DPY_TST_DURATION = 500; // milliseconds

 // Is processor stopped?
@@ -65,20 +63,14 @@
     pinMode(MOSI, INPUT);   // NB: (1)
     pinMode(SCLK, OUTPUT);
     pinMode(DLOAD, OUTPUT);
-
     pinMode(BTN_MODE, INPUT_PULLUP);
     pinMode(BTN_SELECT, INPUT_PULLUP);
-
-    // Initial pin values
-    digitalWrite(SCLK, LOW);
-    digitalWrite(MISO, LOW);
-    digitalWrite(DLOAD, LOW);

     // Set up MX7219 with display test on
     setupMX7219();
     setMX7219Reg(MX7219_SCN_LIMIT, 0x06);   // Scan digits 0-6
     setMX7219Reg(MX7219_DPLY_TEST, 0x01);   // Enable display test
-    showing_dt = true; dt_shown_at = millis();
+    unsigned long dt_shown_at = millis();   // Record display test time

     // Initial address/data bus values
     address_bus = data_bus = 0;
@@ -91,15 +83,15 @@

     next_demo_loop_at = millis() + DEMO_LOOP_PERIOD;
     demo_loop_count = 0;
+
+    // OK, all done, just wait for display test to time out
+    while(millis() - dt_shown_at < DPY_TST_DURATION) {
+        // NOP
+    }
+    setMX7219Reg(MX7219_DPLY_TEST, 0x00);
 }

 void loop() {
-    // Display test off after DPY_TST_DURATION milliseconds
-    if(showing_dt && (millis() - dt_shown_at > DPY_TST_DURATION)) {
-        showing_dt = false;
-        setMX7219Reg(MX7219_DPLY_TEST, 0x00);
-    }
-
     // Poll switches
     mode_switch.poll();
     select_switch.poll();


Staff pattern back to normal

Staff pattern back to normal

--- staff/z_loop.ino
+++ staff/z_loop.ino
@@ -1,14 +1,14 @@
 void (*patterns[])() = {
 //  solid,
-//  beautifulSparkles,
-//  discoBarber1,
-//  discoBarber2,
-//  rain,
-//  sparkles,
+  beautifulSparkles,
+  discoBarber1,
+  discoBarber2,
+  rain,
+  sparkles,
   dave,
-//  shootingGradients,
-//  discoTwirl,
-//  discoTwirl2,
+  shootingGradients,
+  discoTwirl,
+  discoTwirl2,
 };

 int patternId = 0;


Added updated LED driver arduino code

Added updated LED driver arduino code

--- Arduino_LEDs/Arduino_LEDs.ino
+++ Arduino_LEDs/Arduino_LEDs.ino
@@ -2,125 +2,47 @@
 #include <string.h>

 // CHANGE this number for each fiducial
-#define FIDUCIAL_ID 3

 #define PIN 6
-#define NUMPIXELS 28
-#define ARRAYSIZE 38
-#define MAXWIDTH 4
-#define MINWIDTH 1
-#define MAXDIST 1000
+#define MAXLEDS 56

-Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);
+Adafruit_NeoPixel pixels = Adafruit_NeoPixel(MAXLEDS, PIN, NEO_RGB + NEO_KHZ800);

-
-  int b[ARRAYSIZE];
-  int c[ARRAYSIZE];
-  int d[ARRAYSIZE];
-
+String inputString ="";
+boolean stringComplete = false;

 void setup() {
   Serial.begin(115200);
   pixels.begin();
-
-    //lazy array initialization - fix hacked bounds
-  for(int i=0; i<ARRAYSIZE; i++) {
-    d[i] = c[i] = b[i] = 0;
+  inputString.reserve((3*MAXLEDS)+3);
+}
+
+void loop() {
+  if (stringComplete) {
+
+ //   Serial.println(inputString);
+
+    int ledindex = 0;
+    for(int i=0; i<(inputString.length()-1); i=i+3) {
+      int R = (inputString.charAt(i)-'0')*28;
+      int G = (inputString.charAt(i+1)-'0')*28;
+      int B = (inputString.charAt(i+2)-'0')*28;
+      pixels.setPixelColor(ledindex++,R,G,B);
+    }
+
+    pixels.show(); // This sends the updated pixel color to the hardware.
+    inputString = "";
+    stringComplete = false;
+
   }
 }

-void loop() {
-  int angle = 0;
-  int distance = 1000;
-  int centreled;
-  String marker_id;
-  float dist;
-  String  inputstring;
-  String dist_string;
-  String angle_string;
-  int refresh=1;
-
-//these for loops are for testing only, they'll be replaced with a Serial.read() when connected to the other thing
-//
-//for(distance=1000; distance > 50; distance=distance-100){
-//  for(angle=0;angle<360;angle=angle+10){
-
-do {
-
-while (Serial.available()){
-  inputstring = Serial.readStringUntil('A');
-//  refresh = 1;
+void serialEvent() {
+  while (Serial.available()) {
+    char inChar = (char)Serial.read();
+    inputString += inChar;
+    if(inChar == '\n') {
+      stringComplete = true;
+    }
+  }
 }
-
-
-    marker_id = inputstring.substring(0,2);
-    dist_string = inputstring.substring(2,6);
-    angle_string = inputstring.substring(6,10);
-    angle = angle_string.toInt();
-    distance = dist_string.toInt();
-
-} while(marker_id.toInt() != FIDUCIAL_ID);
-
-if(distance==0){
-  distance = 1000;
-}
-    //lazy array initialization - fix hacked bounds
-     for(int i=0; i<ARRAYSIZE; i++) {
-    d[i] = c[i] = b[i] = 0;
-  }
-
-//  Serial.print("Distance: ");
-//  Serial.print(distance);
-//  Serial.print(" Angle: ");
-//  Serial.print(angle);
-//  Serial.print(" Refresh: ");
-//  Serial.println(refresh);
-
-  centreled = map(angle,0,360,0,NUMPIXELS);
-
-  delay(40);
-
-  dist = map(distance,0,MAXDIST,MAXWIDTH,MINWIDTH);
-
-
-
-
-    //make the ramp one-sided
-    for(int i=0; i<(dist+1); i++) {
-      b[i] = 255*float(i/dist);
-      if(distance==1000){
-        b[i] = 0;
-      }
-    }
-
-
-
-    //make the ramp two sided
-    for(int i=0; i<(2*dist)+1; i++) {
-      int disti = dist-(i-dist);
-      if(i<dist) c[i] = b[i];
-      if(i>=dist & i<(2*dist)+1) c[i] = b[disti];
-      if(i>=(2*dist)+1) c[i] = 0;
-    }
-
-
-    //centre the ramp around the right pixel and set the pixel colour
-    for(int i=0; i<NUMPIXELS; i++) {
-      int index = (centreled-i+int(dist)) % (NUMPIXELS);
-      pixels.setPixelColor(i,0,c[index],c[index]);
-    }
-
-    if(angle==9999){
-      for(int i=0; i<NUMPIXELS; i++) {
-        pixels.setPixelColor(i,0,255,0);
-      }
-    }
-
-  if(refresh == 1){
-          pixels.show(); // This sends the updated pixel color to the hardware.
-//      refresh = 0;
-  }
-
-  }
-//}
-//}


switched line in OLED display from showing windowSize variable back to saying 'TargetTemp: ' -- no need to keep that bit of printf debugging.

--- sous_vide_arduino_with_OLED_and_PID/sous_vide_arduino_with_OLED_and_PID.ino
+++ sous_vide_arduino_with_OLED_and_PID/sous_vide_arduino_with_OLED_and_PID.ino
@@ -254,8 +254,8 @@

 //        dtostrf(freeMemory(),7,0,ab);
 //        dtostrf((onTime/WindowSize),4,3,ab);
-          dtostrf(windowStartTime,7,0,ab);
-          sendStrXY(ab,4,4);
+//          dtostrf(windowStartTime,7,0,ab);
+//          sendStrXY(ab,4,4);

           unsigned long t = millis()/1000;
           int h = t/3600; //(hours)
@@ -266,7 +266,7 @@
           sendStrXY(ab,2,4);

-//        sendStrXY("Target:",4,4);
+        sendStrXY("Target:",4,4);

         //digitalWrite(PWR_ON, LOW); //Display EN Off
         //Bean.sleep(2);


Minor updates to comments.

Minor updates to comments.

Removed commented-out deep-sleep call with bad "mode" option.
Updated a couple of other comments to clarify meaning.

--- DHT_Test.ino
+++ DHT_Test.ino
@@ -146,7 +146,6 @@
 #ifdef DEBUG
     Serial.println(F("Zzzz..."));
 #endif
-    // ESP.deepSleep(DSLEEP_SECS * 1000 * 1000, WAKE_RF_DISABLED);
     ESP.deepSleep(DSLEEP_SECS * 1000 * 1000);

     /*
@@ -178,7 +177,10 @@
     float vdd = ESP.getVcc() / 1000.0;	// Grab the current battery voltage.
     dtostrf(vdd, 4, 2, vbuff);	// Convert to ASCII and store.

-    /* This delay is for use when testing without deep-sleep. */
+    /*
+     *This delay is for use when testing =without= using deep-sleep
+     * and should normally be commented-out.
+     */
 //    delay(LDELAY);    // Disable this loop delay if using deep-sleep.

     getSensorData();


Added void * type size check

Added void * type size check

--- tests/TestSystemInfo/TestSystemInfo.ino
+++ tests/TestSystemInfo/TestSystemInfo.ino
@@ -14,6 +14,7 @@
   RASSERT_MORE(sizeof(rsize), 0);
   RASSERT_MORE(sizeof(rnumber), 0);
   RASSERT_MORE(sizeof(ruint), 0);
+  RASSERT_MORE(sizeof(void *), 0);
 };

 void


ExamplesIntermediate: update WDRC_SingleBand

--- examples/03-Intermediate/WDRC_SingleBand/WDRC_SingleBand.ino
+++ examples/03-Intermediate/WDRC_SingleBand/WDRC_SingleBand.ino
@@ -19,49 +19,46 @@
 #include <Tympan_Library.h>

-// GUItool: begin automatically generated code
-Tympan						audioHardware(TympanRev::D);  //TympanRev::D or TympanRev::C
-AudioInputI2S_F32        i2sAudioIn1;    //xy=136,112
-AudioFilterBiquad_F32       iir1;           //xy=233,172
-AudioEffectCompWDRC_F32  compWDRC1;      //xy=427,172
-AudioOutputI2S_F32       i2sAudioOut1;   //xy=630,174
-AudioConnection_F32         patchCord1(i2sAudioIn1, 0, iir1, 0);
-AudioConnection_F32         patchCord2(iir1, compWDRC1);
-AudioConnection_F32         patchCord3(compWDRC1, 0, i2sAudioOut1, 0);
-AudioConnection_F32         patchCord4(compWDRC1, 0, i2sAudioOut1, 1);
-// GUItool: end automatically generated code
+//create audio library objects for handling the audio
+Tympan						      myTympan(TympanRev::D);  //TympanRev::D or TympanRev::C
+AudioInputI2S_F32       i2s_in;
+AudioFilterBiquad_F32   iir1;
+AudioEffectCompWDRC_F32  compWDRC1;
+AudioOutputI2S_F32       i2s_out;
+AudioConnection_F32     patchCord1(i2s_in, 0, iir1, 0);
+AudioConnection_F32     patchCord2(iir1, compWDRC1);
+AudioConnection_F32     patchCord3(compWDRC1, 0, i2s_out, 0);
+AudioConnection_F32     patchCord4(compWDRC1, 0, i2s_out, 1);

-//I have a potentiometer on the Teensy Audio Board
-#define POT_PIN A20  //potentiometer is tied to this pin

 //define a function to setup the Teensy Audio Board how I like it
-void setupMyAudioBoard(void) {
+void setupTympanHardware(void) {
   // Setup the Tympan audio hardware
-  audioHardware.enable(); // activate AIC
+  myTympan.enable(); // activate AIC

   // Choose the desired input
-  audioHardware.inputSelect(TYMPAN_INPUT_ON_BOARD_MIC); // use the on board microphones // default
-  //  audioHardware.inputSelect(TYMPAN_INPUT_JACK_AS_MIC); // use the microphone jack - defaults to mic bias 2.5V
-  //  audioHardware.inputSelect(TYMPAN_INPUT_JACK_AS_LINEIN); // use the microphone jack - defaults to mic bias OFF
-  //  audioHardware.inputSelect(TYMPAN_INPUT_LINE_IN); // use the line in pads on the TYMPAN board - defaults to mic bias OFF
+  myTympan.inputSelect(TYMPAN_INPUT_ON_BOARD_MIC); // use the on board microphones // default
+  //  myTympan.inputSelect(TYMPAN_INPUT_JACK_AS_MIC); // use the microphone jack - defaults to mic bias 2.5V
+  //  myTympan.inputSelect(TYMPAN_INPUT_JACK_AS_LINEIN); // use the microphone jack - defaults to mic bias OFF
+  //  myTympan.inputSelect(TYMPAN_INPUT_LINE_IN); // use the line in pads on the TYMPAN board - defaults to mic bias OFF

   //Adjust the MIC bias, if using TYMPAN_INPUT_JACK_AS_MIC
-  //  audioHardware.setMicBias(TYMPAN_MIC_BIAS_OFF); // Turn mic bias off
-  audioHardware.setMicBias(TYMPAN_MIC_BIAS_2_5); // set mic bias to 2.5 // default
+  //  myTympan.setMicBias(TYMPAN_MIC_BIAS_OFF); // Turn mic bias off
+  myTympan.setMicBias(TYMPAN_MIC_BIAS_2_5); // set mic bias to 2.5 // default

   // VOLUMES
-  audioHardware.volume_dB(0);  // -63.6 to +24 dB in 0.5dB steps.  uses float
-  audioHardware.setInputGain_dB(10); // set MICPGA volume, 0-47.5dB in 0.5dB setps
+  myTympan.volume_dB(0.0);  // -63.6 to +24 dB in 0.5dB steps.  uses float
+  myTympan.setInputGain_dB(10.0); // set MICPGA volume, 0-47.5dB in 0.5dB setps
 }

 //The setup function is called once when the system starts up
 void setup(void) {
-  //Start the USB serial link (to enable debugging)
-  Serial.begin(115200); delay(500);
-  Serial.println("Setup starting...");
+    //begin the serial comms (for debugging)
+  myTympan.beginBothSerial(); delay(1000); //let's use the print functions in "myTympan" so it goes to BT, too!
+  myTympan.println("Setup starting...");

-  //Allocate dynamically shuffled memory for the audio subsystem
-  AudioMemory(10);  AudioMemory_F32(10);
+  //allocate the dynamic memory for audio processing blocks
+  AudioMemory_F32(20);

   //setup high-pass IIR...[b,a]=butter(2,750/(44100/2),'high')
   float32_t hp_b[]={ 0.927221242739230,  -1.854442485478460,   0.927221242739230};
@@ -69,10 +66,10 @@
   iir1.setFilterCoeff_Matlab(hp_b, hp_a); //one stage of N=2 IIR

   // Enable the audio shield, select input, and enable output
-  setupMyAudioBoard();
+  setupTympanHardware();

   //End of setup
-  Serial.println("Setup complete.");
+  myTympan.println("Setup complete.");
 };

@@ -82,15 +79,17 @@
 void loop(void) {

   //service the potentiometer...if enough time has passed
-  servicePotentiometer(millis());
+  servicePotentiometer(millis(),100); //update every 100msec
+
+  //update the memory and CPU usage...if enough time has passed
+  myTympan.printCPUandMemory(millis(),3000); //print every 3000 msec

 };

 //servicePotentiometer: listens to the blue potentiometer and sends the new pot value
 //  to the audio processing algorithm as a control parameter
-void servicePotentiometer(unsigned long curTime_millis) {
-  static unsigned long updatePeriod_millis = 100; //how many milliseconds between updating the potentiometer reading?
+void servicePotentiometer(unsigned long curTime_millis,unsigned long updatePeriod_millis) {
   static unsigned long lastUpdate_millis = 0;
   static float prev_val = -1.0;

@@ -99,24 +98,23 @@
   if ((curTime_millis - lastUpdate_millis) > updatePeriod_millis) { //is it time to update the user interface?

     //read potentiometer
-    float val = float(analogRead(POT_PIN)) / 1024.0; //0.0 to 1.0
+    float val = float(myTympan.readPotentiometer()) / 1023.0; //0.0 to 1.0
     val = 0.1 * (float)((int)(10.0 * val + 0.5)); //quantize so that it doesn't chatter...0 to 1.0

     //send the potentiometer value to your algorithm as a control parameter
-    //float scaled_val = val / 3.0; scaled_val = scaled_val * scaled_val;
     if (abs(val - prev_val) > 0.05) { //is it different than befor?
       prev_val = val;  //save the value for comparison for the next time around

       float min_mic_dB = +10.0f;
       float fixed_hp_dB = 00.0f;
       float vol_dB = min_mic_dB +10.0f + 20.0f * ((val - 0.5) * 2.0); //set volume as 10dB +/- 25 dB
-      Serial.print("Changing input gain = "); Serial.print(vol_dB); Serial.println(" dB");
+      myTympan.print("Changing input gain = "); myTympan.print(vol_dB); myTympan.println(" dB");
       if (vol_dB  < min_mic_dB) {
-        audioHardware.setInputGain_dB(min_mic_dB);
-        audioHardware.volume_dB(vol_dB-min_mic_dB+fixed_hp_dB);
+        myTympan.setInputGain_dB(min_mic_dB);
+        myTympan.volume_dB(vol_dB-min_mic_dB+fixed_hp_dB);
       } else {
-        audioHardware.setInputGain_dB(vol_dB);
-        audioHardware.volume_dB(fixed_hp_dB);
+        myTympan.setInputGain_dB(vol_dB);
+        myTympan.volume_dB(fixed_hp_dB);
       }
     }
     lastUpdate_millis = curTime_millis;


Fixed compile error due to missing scope

    * examples/ArduinoUnoNano-downlink/ArduinoUnoNano-downlink.ino:

--- examples/ArduinoUnoNano-downlink/ArduinoUnoNano-downlink.ino
+++ examples/ArduinoUnoNano-downlink/ArduinoUnoNano-downlink.ino
@@ -1,22 +1,22 @@
 /*
  * Author: Dennis Ruigrok and JP Meijers
  * Date: 2017-01-16
- *
+ *
  * This program is meant to be used with an Arduino UNO or NANO, conencted to an RNxx3 radio module.
- * It will most likely also work on other compatible Arduino or Arduino compatible boards,
+ * It will most likely also work on other compatible Arduino or Arduino compatible boards,
  * like The Things Uno, but might need some slight modifications.
- *
- * Transmit a one byte packet via TTN, using confirmed messages,
+ *
+ * Transmit a one byte packet via TTN, using confirmed messages,
  * waiting for an acknowledgement or a downlink message.
- *
+ *
  * CHECK THE RULES BEFORE USING THIS PROGRAM!
- *
+ *
  * CHANGE ADDRESS!
- * Change the device address, network (session) key, and app (session) key to the values
+ * Change the device address, network (session) key, and app (session) key to the values
  * that are registered via the TTN dashboard.
  * The appropriate line is "myLora.initABP(XXX);" or "myLora.initOTAA(XXX);"
  * When using ABP, it is advised to enable "relax frame count".
- *
+ *
  * Connect the RN2xx3 as follows:
  * RN2xx3 -- Arduino
  * Uart TX -- 10
@@ -24,32 +24,32 @@
  * Reset -- 12
  * Vcc -- 3.3V
  * Gnd -- Gnd
- *
- * If you use an Arduino with a free hardware serial port, you can replace
+ *
+ * If you use an Arduino with a free hardware serial port, you can replace
  * the line "rn2xx3 myLora(mySerial);"
  * with     "rn2xx3 myLora(SerialX);"
  * where the parameter is the serial port the RN2xx3 is connected to.
  * Remember that the serial port should be initialised before calling initTTN().
  * For best performance the serial port should be set to 57600 baud, which is impossible with a software serial port.
  * If you use 57600 baud, you can remove the line "myLora.autobaud();".
- *
+ *
  */
 #include <rn2xx3.h>
 #include <SoftwareSerial.h>

 SoftwareSerial mySerial(10, 11); // RX, TX

-//create an instance of the rn2xx3 library,
+//create an instance of the rn2xx3 library,
 //giving the software serial as port to use
 rn2xx3 myLora(mySerial);

 // the setup routine runs once when you press reset:
-void setup()
+void setup()
 {
   //output LED pin
   pinMode(13, OUTPUT);
   led_on();
-
+
   // Open serial communications and wait for port to open:
   Serial.begin(57600); //serial port to computer
   mySerial.begin(9600); //serial port to radio
@@ -97,10 +97,10 @@
   //configure your keys and join the network
   Serial.println("Trying to join TTN");
   bool join_result = false;
-
+
   //ABP: initABP(String addr, String AppSKey, String NwkSKey);
   join_result = myLora.initABP("02017201", "8D7FFEF938589D95AAD928C2E2E7E48F", "AE17E567AECC8787F749A62F5541D522");
-
+
   //OTAA: initOTAA(String AppEUI, String AppKey);
   //join_result = myLora.initOTAA("70B3D57ED00001A6", "A23C96EE13804963F8C2BD6285448198");

@@ -111,11 +111,11 @@
     join_result = myLora.init();
   }
   Serial.println("Successfully joined TTN");
-
+
 }

 // the loop routine runs over and over again forever:
-void loop()
+void loop()
 {
     led_on();

@@ -124,20 +124,23 @@

     switch(myLora.txCnf("!")) //one byte, blocking function
     {
-      case TX_FAIL:
-        Serial.println("TX unsuccessful or not acknowledged");
+      case TX_FAIL:
+        {
+          Serial.println("TX unsuccessful or not acknowledged");
+        }
         break;
-
       case TX_SUCCESS:
-        Serial.println("TX successful and acknowledged");
+        {
+          Serial.println("TX successful and acknowledged");
+          break;
+        }
+      case TX_WITH_RX:
+        {
+          String received = myLora.getRx();
+          received = myLora.base16decode(received);
+          Serial.print("Received downlink: " + received);
+        }
         break;
-
-      case TX_WITH_RX:
-        String received = myLora.getRx();
-        received = myLora.base16decode(received);
-        Serial.print("Received downlink: " + received);
-        break;
-
       default:
         Serial.println("Unknown response from TX function");
     }


Added port io (in, out) Added 'break' support for autobaud tests.


alternative init of v1 board

alternative init of v1 board

--- OpenDeck_MCU/OpenDeck_MCU.ino
+++ OpenDeck_MCU/OpenDeck_MCU.ino
@@ -7,6 +7,34 @@
 */

 #include "OpenDeck.h"
+
+#ifdef BOARD_OPENDECK_1
+
+//atmega328
+//arduino adds some unnecessary stuff in setup/loop
+
+int main()  {
+
+    openDeck.init();
+
+    while(1)    {
+
+        //check incoming MIDI messages
+        openDeck.checkMIDIIn();
+
+        //check buttons
+        openDeck.readButtons();
+
+        //check analog inputs
+        openDeck.readAnalog();
+
+        //check encoders
+        openDeck.readEncoders();
+
+    }   return 0;
+
+}
+#else

 void setup()    {

@@ -33,4 +61,5 @@
         uart.releaseTX();
     #endif

-}+}
+#endif


Added stimulus trigger to arduino script

--- quick_release.ino
+++ quick_release.ino
@@ -10,9 +10,11 @@

 // Timing variables
-const int PREDELAY  = 100;    // in ms
-const int STEPDELAY = 10;     // in µs
-const int EXPOSUREDUR = 100;  // in µs
+const int PREDELAY  = 10;     // in ms
+const int STIMDELAY = 200;    // in ms
+const int SHUTTERDELAY = 3;   // in ms
+const int STEPDELAY = 200;    // in µs
+const int EXPOSUREDUR = 500;  // in µs
 const int POSTEXPOSURE = 100; // in ms

 // Non-global variable declaration
@@ -26,6 +28,8 @@
 int SHUT_LED   = 5;
 int EXPOSE_OUT = 6; // to exposure trigger
 int EXPOSE_LED = 7;
+int STIM_OUT   = 8; // to stimulus trigger
+int STIM_LED   = 9;

 // Begin setup of board
 void setup()
@@ -43,6 +47,8 @@
     pinMode(SHUT_LED, OUTPUT);
     pinMode(EXPOSE_OUT, OUTPUT);
     pinMode(EXPOSE_LED, OUTPUT);
+    pinMode(STIM_OUT, OUTPUT);
+    pinMode(STIM_LED, OUTPUT);
     // Initial pin states
     digitalWrite(LEN_OUT, LOW);
     digitalWrite(LEN_LED, LOW);
@@ -50,6 +56,8 @@
     digitalWrite(SHUT_LED, LOW);
     digitalWrite(EXPOSE_OUT, LOW);
     digitalWrite(EXPOSE_LED, LOW);
+    digitalWrite(STIM_OUT, LOW);
+    digitalWrite(STIM_LED, LOW);
     // Close out setup
     Serial.println("Setup complete");
 }
@@ -59,7 +67,7 @@
 {
     check_serial(); // read input if it exists
     if (run_now) {
-        run(PREDELAY, stepdelay, EXPOSUREDUR, POSTEXPOSURE);
+        run(PREDELAY, STIMDELAY, SHUTTERDELAY, stepdelay, EXPOSUREDUR, POSTEXPOSURE);
         Serial.println("Run complete"); // tag that we've done a run
         run_now = false; // reset the run flag
     }
@@ -79,17 +87,23 @@
 }

 // Control a run
-void run(int predelay, int stepdelay, int exposureduration, int postexposure)
+void run(int predelay, int stimdelay, int shutterdelay, int stepdelay, int exposureduration, int postexposure)
 {
     delay(predelay);
+    digitalWrite(STIM_OUT, HIGH);
+    digitalWrite(STIM_LED, HIGH);
+    delay(stimdelay);
     digitalWrite(SHUT_OUT, HIGH); // shutter opened before step delay
     digitalWrite(SHUT_LED, HIGH); // may open during pre-delay in future
+    delay(shutterdelay);
     digitalWrite(LEN_OUT, HIGH);
     digitalWrite(LEN_LED, HIGH);
     delayMicroseconds(stepdelay);
     digitalWrite(EXPOSE_OUT, HIGH);
     digitalWrite(EXPOSE_LED, HIGH);
     delayMicroseconds(exposureduration);
+    digitalWrite(STIM_OUT, LOW);
+    digitalWrite(STIM_LED, LOW);
     digitalWrite(EXPOSE_OUT, LOW);
     digitalWrite(EXPOSE_LED, LOW);
     digitalWrite(SHUT_OUT, LOW);


Add custom TimeZone

Add custom TimeZone


Fixed HTTP request result not properly showing.

Signed-off-by: Cellie <5a95f66c4e447827a8bbc001563710c0caf0a1f7@wasietsmet.nl>

--- versioncheck.ino
+++ versioncheck.ino
@@ -39,7 +39,7 @@
     HTTPClient http;

     http.begin( latestReleaseAPI, github_root_ca );
-    uint8_t httpCode = http.GET();
+    int httpCode = http.GET();

     if ( httpCode == 200 )
     {
@@ -63,6 +63,7 @@
         }

         ESP_LOGI( TAG, "Local release: '%s'", installedRelease );
+
         strncpy( newRelease, root["tag_name"], sizeof( newRelease ) );
         if ( strcmp ( installedRelease, newRelease) != 0 )
         {
@@ -73,7 +74,7 @@
     }
     else
     {
-      ESP_LOGI( TAG, "Error %i on HTTPS request.", httpCode );
+      ESP_LOGI( TAG, "Error %i on HTTPS request '%s'.", httpCode, latestReleaseAPI );
     }
     http.end();
     vTaskDelay( versionCheckDelayTime );


automatic arm power on/off

automatic arm power on/off

--- robik_arduino.ino
+++ robik_arduino.ino
@@ -409,6 +409,7 @@
 		status_msg.ultrasound_Back = ultrasoundBack;

 		//arm
+		status_msg.arm_enabled = getArmPower();
 		status_msg.arm_yaw = servoSenseMedian_yaw.getMedian();
 		status_msg.arm_shoulder = servoSenseMedian_shoulder.getMedian();
 		status_msg.arm_elbow = servoSenseMedian_elbow.getMedian();
@@ -441,8 +442,8 @@
 		pub_status.publish(&status_msg);
 		status_msg_clean();

-		//check arm power timeout
-		if (arm_enabled_time != 0 && (arm_enabled_time + ARM_TIME_MAX_ENABLED) < millis()) {
+		//check arm power timeout to prevent overheat
+		if ( (getArmPower() == true) && ((arm_enabled_time + ARM_TIME_MAX_ENABLED) < millis()) ) {
 			setArmPower(false);
 		}

@@ -654,7 +655,7 @@
 }

 bool getArmPower() {
-	return (digitalRead(PIN_RELAY) == HIGH) ? true : false;
+	return (arm_enabled_time != 0) ? true : false;
 }
 void setArmPower(bool state) {
 	if (state) {
@@ -774,16 +775,21 @@
 	String arm_yaw = "";

 	//if arm power is off but a move request is received, enable power
-	if (!getArmPower() &&
+	if ( (getArmPower() == false) &&
 		(old_clamp != clamp ||
 		old_roll != roll ||
 		old_elbow != elbow ||
 		old_shoulder != shoulder ||
 		old_yaw != yaw)
-		)
+	    )
 	{
-		setArmPower(true);
-	}
+		setArmPower(true);
+	}
+	old_clamp = clamp;
+	old_roll = roll;
+	old_elbow = elbow;
+	old_shoulder = shoulder;
+	old_yaw = yaw;

 	String time_to_complete_str = String(time_to_complete, DEC);
 	if (clamp != 0) {


Updated POST message to follow protocol specification

--- water-sensor.ino
+++ water-sensor.ino
@@ -43,6 +43,8 @@
 const byte MULT_B = 43;
 const byte MULT_C = 40;

+const int id = 1;
+
 // Analog I/O pins
 const byte LIGHT = A13; // Not currently used
 const byte REFERENCE_3V3 = A3; // Not currently used
@@ -77,6 +79,7 @@

 // Message buffer
 char buffer[161];
+char buffer2[201];

 // Destination number of the message
 char destination[] = "5511947459448";
@@ -276,7 +279,7 @@
       Serial.println(F("Sent!"));
     }

-    if (!send_http_post(http_post_url, buffer)) {
+    if (!send_http_post(http_post_url, id, buffer)) {
       Serial.println(F("HTTP POST Failed"));
     } else {
       Serial.println(F("HTTP POST Send!"));
@@ -288,7 +291,7 @@
   delay(1000);
 }

-boolean send_http_post(char *url, char *data) {
+boolean send_http_post(char *url, int id, char *data) {
   uint16_t statuscode;
   uint16_t response_length;
   boolean post_success;
@@ -298,8 +301,14 @@
   {
     Serial.read();
   }
+
+  sprintf(buffer2, "{\"sensorIdentifier\":\"%d\",\"data\":\"%s\"}",
+                    id, data);
+
+  Serial.print("POST message: ");
+  Serial.println(buffer2);

-  fona.HTTP_POST_start(url, F("text/plain"), (uint8_t *)data, strlen(data), &statuscode, &response_length);
+  fona.HTTP_POST_start(url, F("application/json"), (uint8_t *)buffer2, strlen(buffer2), &statuscode, &response_length);

   Serial.print("Status: ");
   Serial.println(statuscode);


BabelFish: replace typecast with logical-AND

An AND is (marginally) clearer than a typecast.

[ The warning is "large integer implicitly truncated to unsigned
type".  It's a bit of GCC weirdness that this is needed for silencing
the warning for passing ~128 as a byte/uint_8 value, but not required
for ~64, ~32 etcetera. ]

--- Utils/BabelFish/BabelFish.ino
+++ Utils/BabelFish/BabelFish.ino
@@ -295,7 +295,7 @@
 #define buttonSelect 32
 #define buttonB      64
 #define buttonA      128
-// Note: The kit's controller gives inverted signals.
+// Note: The kit's game controller gives inverted signals.

 /*
  *  Font data
@@ -514,7 +514,7 @@
   case 'H': doHelp();                         break;
   case 'R': doReset(arg);                     break;
   case 'L': doLoader();                       break;
-  case 'M': doMapping();                   break;
+  case 'M': doMapping();                      break;
   case 'P': if (0 <= arg && arg < arrayLen(gt1Files))
               doTransfer(gt1Files[arg].gt1);  break;
   case 'U': doTransfer(NULL);                 break;
@@ -525,7 +525,7 @@
   case 'A': sendController(~buttonLeft,   2); break;
   case 'S': sendController(~buttonDown,   2); break;
   case 'D': sendController(~buttonRight,  2); break;
-  case 'Z': sendController((byte)~buttonA,2); break;
+  case 'Z': sendController(~buttonA & 255,2); break;
   case 'X': sendController(~buttonB,      2); break;
   case 'Q': sendController(~buttonSelect, 2); break;
   case 'E': sendController(~buttonStart,  2); break;
@@ -649,7 +649,7 @@
   }

   // Start 'Loader' application on Gigatron
-  sendController((byte)~buttonA, 2);
+  sendController(~buttonA & 255, 2);

   // Wait for Loader to be running
   delay(1000);
@@ -961,7 +961,7 @@
 }

 // Pretend to be a game controller
-// Send the same byte a few frames like a human user
+// Send the same byte a few frames, just like a human user
 void sendController(byte value, int n)
 {
   // Send controller code for n frames


Added water pattern. Refactored/simplified patterns and names.

--- Firmware/spark-ring/spark-ring.ino
+++ Firmware/spark-ring/spark-ring.ino
@@ -13,9 +13,35 @@
 #define NUM_LEDS    60
 CRGB leds[NUM_LEDS];

+#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
+
+// List of patterns to cycle through.  Each is defined as a separate function below.
+
+typedef uint8_t (*SimplePattern)();
+typedef SimplePattern SimplePatternList[];
+typedef struct { SimplePattern drawFrame;  char name[32]; } PatternAndName;
+typedef PatternAndName PatternAndNameList[];
+
+// These times are in seconds, but could be changed to milliseconds if desired;
+// there's some discussion further below.
+
+const PatternAndNameList patterns = {
+  { rainbow,            "Rainbow" },
+  { rainbowWithGlitter, "Rainbow With Glitter" },
+  { confetti,           "Confetti" },
+  { sinelon,            "Sinelon" },
+  { bpm,                "Beat" },
+  { juggle,             "Juggle" },
+  { fire,               "Fire" },
+  { water,              "Water" },
+  { analogClock,        "Analog Clock" },
+  { fastAnalogClock,    "Fast Analog Clock Test" },
+  { showSolidColor,     "Solid Color" }
+};
+
 uint8_t brightness = 32;

-int patternCount = 10;
+int patternCount = ARRAY_SIZE(patterns);
 int patternIndex = 0;
 char patternName[32] = "Rainbow";
 int power = 1;
@@ -57,6 +83,8 @@
         brightness = 1;
     else if(brightness > 255)
         brightness = 255;
+
+    FastLED.setBrightness(brightness);

     uint8_t timezoneSign = EEPROM.read(1);
     if(timezoneSign < 1)
@@ -125,51 +153,7 @@
       return;
   }

-  uint8_t delay = 8;
-
-  switch(patternIndex)
-  {
-      case 0:
-      default:
-      delay = rainbow();
-      break;
-
-      case 1:
-      delay = rainbowWithGlitter();
-      break;
-
-      case 2:
-      delay = confetti();
-      break;
-
-      case 3:
-      delay = sinelon();
-      break;
-
-      case 4:
-      delay = bpm();
-      break;
-
-      case 5:
-      delay = juggle();
-      break;
-
-      case 6:
-      delay = fire();
-      break;
-
-      case 7:
-      delay = analogClock();
-      break;
-
-      case 8:
-      delay = fastAnalogClock();
-      break;
-
-      case 9:
-      delay = showSolidColor(solidColor);
-      break;
-  }
+  uint8_t delay = patterns[patternIndex].drawFrame();

   // send the 'leds' array out to the actual LED strip
   FastLED.show();
@@ -298,57 +282,15 @@

 int setPatternName(String args)
 {
-    int pattern = args.toInt();
-    if(pattern < 0)
-        pattern = 0;
-    else if (pattern >= patternCount)
-        pattern = patternCount - 1;
-
-    switch(pattern)
-    {
-        case 0:
-        strcpy(patternName, "Rainbow");
-        break;
-
-        case 1:
-        strcpy(patternName, "Rainbow With Glitter");
-        break;
-
-        case 2:
-        strcpy(patternName, "Confetti");
-        break;
-
-        case 3:
-        strcpy(patternName, "Sinelon");
-        break;
-
-        case 4:
-        default:
-        strcpy(patternName, "BPM");
-        break;
-
-        case 5:
-        strcpy(patternName, "Juggle");
-        break;
-
-        case 6:
-        strcpy(patternName, "Fire");
-        break;
-
-        case 7:
-        strcpy(patternName, "Analog Clock");
-        break;
-
-        case 8:
-        strcpy(patternName, "Fast Analog Clock");
-        break;
-
-        case 9:
-        strcpy(patternName, "Solid Color");
-        break;
-  }
-
-    return pattern;
+    int index = args.toInt();
+    if(index < 0)
+        index = 0;
+    else if (index >= patternCount)
+        index = patternCount - 1;
+
+    strcpy(patternName, patterns[index].name);
+
+    return index;
 }

 uint8_t rainbow()
@@ -409,53 +351,18 @@
 }

 uint8_t fire() {
-    // Add entropy to random number generator; we use a lot of it.
-    random16_add_entropy(random(256));
-
-    uint8_t cooling = 55;
-    uint8_t sparking = 120;
-
-    // Array of temperature readings at each simulation cell
-    static const uint8_t fireLedCount = NUM_LEDS / 2;
-    static byte heat[fireLedCount];
-
-    // Step 1.  Cool down every cell a little
-    for( int i = 0; i < fireLedCount; i++) {
-      heat[i] = qsub8( heat[i],  random8(0, ((cooling * 10) / fireLedCount) + 2));
-    }
-
-    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
-    for( int k= fireLedCount - 1; k >= 2; k--) {
-      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
-    }
-
-    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
-    if( random8() < sparking ) {
-      int y = random8(7);
-      heat[y] = qadd8( heat[y], random8(160,255) );
-    }
-
-    byte colorindex = scale8(heat[0], 240);
-
-    leds[fireLedCount] = ColorFromPalette(HeatColors_p, colorindex);
-
-    // Step 4.  Map from heat cells to LED colors
-    for( int j = 0; j < fireLedCount; j++) {
-      // Scale the heat value from 0-255 down to 0-240
-      // for best results with color palettes.
-      colorindex = scale8(heat[j], 240);
-      leds[(fireLedCount - 1) - j] = ColorFromPalette(HeatColors_p, colorindex);
-      leds[(fireLedCount - 1) + j] = ColorFromPalette(HeatColors_p, colorindex);
-    }
-
-    colorindex = scale8(heat[fireLedCount - 1], 240);
-    leds[NUM_LEDS - 1] = ColorFromPalette(HeatColors_p, colorindex);
+    heatMap(HeatColors_p, true);

     return 15;
 }

-int oldSecTime = 0;
-int oldSec = 0;
+CRGBPalette16 icePalette = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White);
+
+uint8_t water() {
+    heatMap(icePalette, false);
+
+    return 30;
+}

 uint8_t analogClock() {
     dimAll(220);
@@ -495,11 +402,74 @@
     return 125;
 }

-uint8_t showSolidColor(CRGB color) {
-    fill_solid(leds, NUM_LEDS, color);
+uint8_t showSolidColor() {
+    fill_solid(leds, NUM_LEDS, solidColor);

     return 30;
 }
+
+void heatMap(CRGBPalette16 palette, bool up) {
+    fill_solid(leds, NUM_LEDS, CRGB::Black);
+
+    // Add entropy to random number generator; we use a lot of it.
+    random16_add_entropy(random(256));
+
+    uint8_t cooling = 55;
+    uint8_t sparking = 120;
+
+    // Array of temperature readings at each simulation cell
+    static const uint8_t halfLedCount = NUM_LEDS / 2;
+    static byte heat[2][halfLedCount];
+
+    byte colorindex;
+
+    for(uint8_t x = 0; x < 2; x++) {
+        // Step 1.  Cool down every cell a little
+        for( int i = 0; i < halfLedCount; i++) {
+          heat[x][i] = qsub8( heat[x][i],  random8(0, ((cooling * 10) / halfLedCount) + 2));
+        }
+
+        // Step 2.  Heat from each cell drifts 'up' and diffuses a little
+        for( int k= halfLedCount - 1; k >= 2; k--) {
+          heat[x][k] = (heat[x][k - 1] + heat[x][k - 2] + heat[x][k - 2] ) / 3;
+        }
+
+        // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
+        if( random8() < sparking ) {
+          int y = random8(7);
+          heat[x][y] = qadd8( heat[x][y], random8(160,255) );
+        }
+
+        // Step 4.  Map from heat cells to LED colors
+        for( int j = 0; j < halfLedCount; j++) {
+            // Scale the heat value from 0-255 down to 0-240
+            // for best results with color palettes.
+            colorindex = scale8(heat[x][j], 240);
+
+            CRGB color = ColorFromPalette(palette, colorindex);
+
+            if(up) {
+                if(x == 0) {
+                    leds[(halfLedCount - 1) - j] = color;
+                }
+                else {
+                    leds[halfLedCount + j] = color;
+                }
+            }
+            else {
+                if(x == 0) {
+                    leds[j] = color;
+                }
+                else {
+                    leds[(NUM_LEDS - 1) - j] = color;
+                }
+            }
+        }
+    }
+}
+
+int oldSecTime = 0;
+int oldSec = 0;

 void drawAnalogClock(byte second, byte minute, byte hour, boolean drawMillis, boolean drawSecond) {
     if(Time.second() != oldSec){


SD card file name is the GMT date and time.

--- Elcano_C6_Navigator.ino
+++ Elcano_C6_Navigator.ino
@@ -116,9 +116,9 @@
 namespace C6_Navigator {
 #endif
 // limited to 8+3 characters
-#define FILE_NAME "GPS_Log.csv"
+#define FILE_NAME "GPSLog.csv"
 File dataFile;
-char GPSfile[BUFFSIZ] = "GPS_yymmdd_hhmmss.csv";
+char GPSfile[BUFFSIZ] = "mmddhhmm.csv";
 String formDataString();

 int waypoints;
@@ -248,7 +248,7 @@
       return;
     }
     Serial.println("card initialized.\n");
-    dataFile = SD.open(FILE_NAME, FILE_WRITE);
+    dataFile = SD.open(GPSfile, FILE_WRITE);
     // if the file is available, write date and time to it:
     if (dataFile)
     {
@@ -260,11 +260,14 @@
 /*---------------------------------------------------------------------------------------*/
 void waypoint::SetTime(char *pTime, char * pDate)
 {
-//     GPSfile = "GPS_yymmdd_hhmmss.CSV";
-     strncpy(GPSfile+4,  pDate+4, 2);
-     strncpy(GPSfile+6,  pDate+2, 2);
-     strncpy(GPSfile+8,  pDate, 2);
-     strncpy(GPSfile+11, pTime,6);
+//     was: GPSfile = "GPS_yymmdd_hhmmss.CSV";
+//     now: GPSfile = "mmddhhmm.CSV";
+//   strncpy(GPSfile+4,  pDate+4, 2);  // year
+     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
+//   strncpy(GPSfile+11, pTime+4,2);     // second
      Serial.println(GPSfile);
 }

@@ -307,7 +310,7 @@

     // 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(FILE_NAME, FILE_WRITE);
+    dataFile = SD.open(GPSfile, FILE_WRITE);

     // if the file is available, write to it:
     if (GPS_available && dataFile)


Update OnewireKeypad_Final.ino

Update OnewireKeypad_Final.ino

Removed Precision

--- Examples/OnewireKeypad_Final/OnewireKeypad_Final.ino
+++ Examples/OnewireKeypad_Final/OnewireKeypad_Final.ino
@@ -1,3 +1,5 @@
+// Creator: Andrew Mascolo
+//
 //#include <Wire.h>
 //#include <LiquidCrystal_I2C.h>
 #include <OnewireKeypad.h>
@@ -12,7 +14,7 @@
 //LiquidCrystal_I2C Lcd(0x20,20,4);
 //OnewireKeypad <LiquidCrystal_I2C, 12> KP( Lcd, KEYS, 4, 3, A0, 4700, 1000 );

-OnewireKeypad <Print, 16 > KP2(Serial, KEYS, 4, 4, A0, 4700, 1000, ExtremePrec );
+OnewireKeypad <Print, 16 > KP2(Serial, KEYS, 4, 4, A0, 4700, 1000 );

 void setup () {
   Serial.begin(115200);
@@ -26,8 +28,8 @@
   //KP.SetKeypadVoltage(5.0);
   KP2.SetKeypadVoltage(5.0);
 }
-void loop()
-{
+
+void loop() {
   //  if( KP.Getkey() )
   //  {
   //    Lcd.clear();


extracted Update Method

extracted Update Method

--- IoTSolution/app/app.ino
+++ IoTSolution/app/app.ino
@@ -62,7 +62,8 @@
         digitalWrite(LED_SIGNAL, HIGH);
         SaveUpdateFlag(false);
         UpdateIt();
-    }else
+    }
+    else
     {
         digitalWrite(LED_SIGNAL, LOW);
     }
@@ -80,6 +81,24 @@
     Serial.println("Free heap memory: " + String(ESP.getFreeHeap()) + " Bytes.");
     Serial.println("Chip speed:       " + String(ESP.getFlashChipSpeed()) + " Hz.");

+    HandleUpdate();
+
+    char deviceId[21];
+    strcpy(deviceId, "ESP");
+    strcat(deviceId, MAC_char);
+
+    simplesample_http_run(A0, connectionString, deviceId);
+
+    updateUrl = simplesample_http_getUrl();
+    if (updateUrl != 0)
+    {
+        SaveUpdateFlag(true);
+        ESP.restart();
+    }
+}
+
+void HandleUpdate()
+{
     if (updateUrl != 0)
     {
         t_httpUpdate_return ret = ESPhttpUpdate.update(updateUrl);
@@ -98,18 +117,6 @@
             Serial.println("HTTP_UPDATE_OK");
             break;
         }
-    }
-
-    char deviceId[21];
-    strcpy(deviceId,"ESP");
-    strcat(deviceId, MAC_char);
-
-    simplesample_http_run(A0, connectionString, deviceId);
-    updateUrl = simplesample_http_getUrl();
-    if (updateUrl != 0)
-    {
-        SaveUpdateFlag(true);
-        ESP.restart();
     }
 }


Now need to use server.send_P with html stored in PROGMEM

--- Receiver/rx_monitor/rx_monitor.ino
+++ Receiver/rx_monitor/rx_monitor.ino
@@ -112,8 +112,8 @@

   // handle index
   server.on("/", []() {
-    // send index.html
-    server.send(200, "text/html", index_html);
+    // send PROGMEM index html.
+    server.send_P(200, "text/html", index_html);
   });

   server.begin();


Cleaned up includes in main .ino file

Cleaned up includes in main .ino file

--- firmware/firmware.ino
+++ firmware/firmware.ino
@@ -1,18 +1,11 @@
-#include "Arduino.h"
-#include "Heartbeat.h"
-#include "TimerOne.h"
-#include "Sensors.h"
-#include "Network.h"
-
-#include <EtherCard.h>
-#include <DHT.h>
-
 // Gotta include this because the arduino IDE does some magic including nonsense.
 #include <SoftwareSerial.h>

 #include "Sensors.h"
 #include "Heartbeat.h"
 #include "Network.h"
+#include "DHT.h"
+#include "TimerOne.h"

 void setup(){
 	// Start up the serial communication.


Added some info printf()'s

Added some info printf()'s

--- slaves/slaves.ino
+++ slaves/slaves.ino
@@ -3,39 +3,33 @@
 #include "RF24.h"
 #include "printf.h"

+#define ADDR_OFFSET 3 // Listeningt address offset
+
+
 RF24 radio(9,10);

-// Single radio pipe address for the 2 nodes to communicate.
+// The base of the listening address. The real one will have an offset of ADDR_OFFSET
 const uint64_t pipe = 0xE8E8F0F0E1LL;
-
-//
-// Payload
-//

 uint8_t state;
 uint8_t state_size = sizeof(state);

-void setup(void)
-{
+void setup(void) {
   Serial.begin(9600);
   printf_begin();

+  printf("Booting up...\n\r");
   radio.begin();

-  // This simple sketch opens a single pipes for these two nodes to communicate
-  // back and forth.  One listens on it, the other talks to it.
-  radio.openReadingPipe(1,pipe+3);
+  radio.openReadingPipe(1,pipe+ADDR_OFFSET);
   radio.startListening();

   radio.printDetails();
+  printf("Booted !\n\r");
 }

-//
-// Loop
-//

-void loop(void)
-{
+void loop(void) {
   // if there is data ready
   if ( radio.available() ) {
     // Dump the payloads until we've gotten everything
@@ -44,9 +38,8 @@

       // Fetch the payload, and see if this was the last one.
       done = radio.read( &state, state_size );
-
       // Spew it
-      printf("%d",state);
+      printf("Got state : %hhd\n\r", state);
     }
     printf("\r\n");
   }


fixed compiler warning

fixed compiler warning

--- Arduino/hardware/REV10/REV10MessagePathTest/REV10SecureBHR/REV10SecureBHR.ino
+++ Arduino/hardware/REV10/REV10MessagePathTest/REV10SecureBHR/REV10SecureBHR.ino
@@ -410,7 +410,7 @@
             constexpr uint8_t valvePC = 0x7f;
             const uint8_t bodylen = OTRadioLink::SimpleSecureFrame32or0BodyTXV0p2::getInstance().generateSecureOFrameRawForTX(
                   realTXFrameStart - offset, TX_MSG_BUF_SIZE - (realTXFrameStart-sW.buf) + offset,
-                  txIDLen, valvePC, (const char *)ptextBuf, eW, subScratch, key);
+                  txIDLen, valvePC, ptextBuf, eW, subScratch, key);
             sendingJSONFailed = (0 == bodylen);
             wrote = bodylen - offset;
             if (sendingJSONFailed) OTV0P2BASE::serialPrintlnAndFlush(F("!TX Enc")); // Know why TX failed.


Update src.ino

Update src.ino

--- src/src.ino
+++ src/src.ino
@@ -1,4 +1,3 @@
-/* サーボのヘッダファイルを準備 */
 #include "Control.h"

 Control ctrl;


removed extra IP address stuff (decided to only have boxes broadcast. May add a way to configure the output IP for UDP/OSC as part of the API later)


Remove change history to make room for documentation.

--- build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino
+++ build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino
@@ -1,4 +1,4 @@
-// ArduinoISP version 04m3
+// ArduinoISP
 // Copyright (c) 2008-2011 Randall Bohn
 // If you require a license, see
 //     http://www.opensource.org/licenses/bsd-license.php
@@ -6,42 +6,31 @@
 // This sketch turns the Arduino into a AVRISP
 // using the following arduino pins:
 //
-// pin name:    not-mega:         mega(1280 and 2560)
-// slave reset: 10:               10
-// MOSI:        11:               51
-// MISO:        12:               50
-// SCK:         13:               52
+// Pin 10 is used to reset the target microcontroller.
+//
+// The MISO, MOSI and SCK pins are used to communicate with the target,
+// on all Arduinos, these pins can be found on the ICSP header:
+//
+//               MISO °. . 5V (!) Avoid this pin on Due, Zero...
+//               SCK   . . MOSI
+//                     . . GND
+//
+// On some Arduinos (Uno,...), pins MOSI, MISO and SCK are the same pins
+// as digital pin 11, 12 and 13, respectively. That is why many tutorials
+// instruct you to hook up the target to these pins. If you find this wiring
+// more practical, have a define USE_OLD_STYLE_WIRING. This will work even
+// even when not using an Uno. (On an Uno this is not needed).
+//
+// IMPORTANT: When using an Arduino that is not 5V tolerant (Due, Zero, ...)
+// as the programmer, make sure to not expose any of the programmer's pins to 5V.
+// A simple way to accomplish this is to power the complete system (programmer
+// and target) at 3V3.
 //
 // Put an LED (with resistor) on the following pins:
 // 9: Heartbeat   - shows the programmer is running
 // 8: Error       - Lights up if something goes wrong (use red if that makes sense)
 // 7: Programming - In communication with the slave
 //
-// 23 July 2011 Randall Bohn
-// -Address Arduino issue 509 :: Portability of ArduinoISP
-// http://code.google.com/p/arduino/issues/detail?id=509
-//
-// October 2010 by Randall Bohn
-// - Write to EEPROM > 256 bytes
-// - Better use of LEDs:
-// -- Flash LED_PMODE on each flash commit
-// -- Flash LED_PMODE while writing EEPROM (both give visual feedback of writing progress)
-// - Light LED_ERR whenever we hit a STK_NOSYNC. Turn it off when back in sync.
-// - Use pins_arduino.h (should also work on Arduino Mega)
-//
-// October 2009 by David A. Mellis
-// - Added support for the read signature command
-//
-// February 2009 by Randall Bohn
-// - Added support for writing to EEPROM (what took so long?)
-// Windows users should consider WinAVR's avrdude instead of the
-// avrdude included with Arduino software.
-//
-// January 2008 by Randall Bohn
-// - Thanks to Amplificar for helping me with the STK500 protocol
-// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
-// - The SPI functions herein were developed for the AVR910_ARD programmer
-// - More information at http://code.google.com/p/mega-isp

 #include "Arduino.h"
 #undef SERIAL


updated animations and support for going all blank


Restoring conditional to RTC initialization

--- arduino/autofowl/autofowl.ino
+++ arduino/autofowl/autofowl.ino
@@ -165,8 +165,11 @@
   // Start the Real Time Clock
   Wire.begin();
   RTC.begin();
-  // This will reflect the time that your sketch was compiled
-  RTC.adjust(DateTime(__DATE__, __TIME__));
+  // Check to see if the RTC is keeping time.  If it is, load the time from your computer.
+  if (! RTC.isrunning()) {
+    // This will reflect the time that your sketch was compiled
+    RTC.adjust(DateTime(__DATE__, __TIME__));
+  }

   // Read clock settings from EEPROM
   byte clockHourThreshUp = EEPROM.read(CLOCK_HOUR_THRESH_UP_ADDRESS);


adds heartbeat print statement

adds heartbeat print statement

--- robots/maproom/maproom.ino
+++ robots/maproom/maproom.ino
@@ -1,4 +1,6 @@
 #include "Robot.h"
+
+#define ROBOT_ID 1

 #define LOGGING 1

@@ -32,7 +34,7 @@
 bool bufDone;

 void setup() {
-  warby = Robot(0, dirA, pwmA, dirB, pwmB, dirC, pwmC, true);
+  warby = Robot(ROBOT_ID, dirA, pwmA, dirB, pwmB, dirC, pwmC, true);
   warby.stop();

   bufLen = 0;
@@ -121,6 +123,7 @@

     if (bufLen >= BUF_SIZE - 1) {
       Serial.println("BUF OVERRUN");
+      bufLen = 0;
       continue;
     }

@@ -133,9 +136,9 @@
   }

   if (bufDone) {
-    Serial.print("buf: ");
-    Serial.write(buf, bufLen);
-    Serial.println();
+    // Serial.print("buf: ");
+    // Serial.write(buf, bufLen);
+    // Serial.println();
     handleMessage(buf);

     bufDone = false;
@@ -144,10 +147,7 @@

   wait++;
   if (wait > 5000) {
-//    warby.getYaw();
-//    warby.setHeading(0, 300);
-//    warby.rotate(-100.0);
-//    warby.rotateSpecific(45.00);
+    Serial.println("SENRB0" + String(ROBOT_ID) + "HB");
     warby.cycle();
     wait = 0;
   }


Added titles to credits

Added titles to credits

--- arduboy-game/arduboy-game.ino
+++ arduboy-game/arduboy-game.ino
@@ -158,9 +158,9 @@

 void creditsScreen() {
   // TODO, this is placeholder
-  const char* credits[] = {"CREDITS", "Jay Garcia", "Simon Prickett", "Stan Bershadskiy", "Andrew Owen",
-                           "Andy Dennis", "Timothy Eagan", "Drew Griffith", "JD Jones",
-                           "Jon Van Dalen", "Lucas Still", "Matt McCants"};
+  const char* credits[] = {"CREDITS", "Captain: Jay Garcia", "Medic: Simon Prickett", "Lt: Stan Bershadskiy", "Helmsman: Andrew Owen",
+                           "Hologram: Andy Dennis", "Gunner: Timothy Eagan", "Tech: Drew Griffith", "Loadmaster: JD Jones",
+                           "Purser: Jon Van Dalen", "Mechanic: Lucas Still", "Comms: Matt McCants"};
   unsigned short arrsize = sizeof(credits) / sizeof(int);
   scrollCredits(4, arrsize, credits, false);
 }
@@ -182,7 +182,7 @@
       textSize = 1;
       y = origY;
     }
-    printText(credits[i], 20, y + padding, textSize);
+    printText(credits[i], 2, y + padding, textSize);
     arduboy.display();
     padding = padding + 15;
     if ( i + 1 == arrsize && y + padding < 0) {


changed button direction type from byte to int

--- jenny5-firmware/jenny5-firmware.ino
+++ jenny5-firmware/jenny5-firmware.ino
@@ -345,7 +345,8 @@
         }
         else if (tmp_str[i + 1] == 'B' || tmp_str[i + 1] == 'b') { // get button pin direction
           int button_index;
-          byte _pin, _dir;
+          byte _pin;
+          int _dir;
           sscanf(tmp_str + i + 2, "%d", &button_index);
           buttons_controller.get_params(button_index, &_pin, &_dir);
           //Serial.print(_pin);


Tweak to code so it will use the builtin LED on any board

--- simple_photoresistor/simple_photoresistor.ino
+++ simple_photoresistor/simple_photoresistor.ino
@@ -1,12 +1,12 @@
 #define thresh 600 // If our analogRead is less than this we will blink

 void setup() {
-  pinMode(13,OUTPUT); // On board LED in Arduino Micro is 13
+  pinMode(LED_BUILTIN,OUTPUT); // On board LED in Arduino Micro is 13
 }

 void loop() {
   int sensorValue = analogRead(A0); // read the voltage from the sensor on A0
   Serial.println(sensorValue,DEC);  // print the value
-  digitalWrite(13,sensorValue<500); // Light LED if sensorValue is under thresh, else dark
+  digitalWrite(LED_BUILTIN,sensorValue<500); // Light LED if sensorValue is under thresh, else dark
   delay(1000); // sleep for 1 second
 }


Update pin Lacet

Update pin Lacet

--- Arduino/config/ArduinoPWM/ArduinoPWM.ino
+++ Arduino/config/ArduinoPWM/ArduinoPWM.ino
@@ -31,7 +31,7 @@
   tanguage.attach(11);
   tanguage.writeMicroseconds(MIDDLE_TANGUAGE);

-  lacet.attach(12);
+  lacet.attach(9);
   lacet.writeMicroseconds(MIDDLE_LACET);
 }


Added wheel encoder code and ISR and also xbee button to start/stop crawler

--- LIDAR_withPIDs/LIDAR_withPIDs.ino
+++ LIDAR_withPIDs/LIDAR_withPIDs.ino
@@ -5,6 +5,8 @@
 #include <math.h>
 #include <PID_v1.h>
 #include <Servo.h>
+#include <Xbee.h>
+#include "XbeeApiStream.h"

 #define LIDARLITE_ADDR 0x62
 #define LIDARLITE_CMD_CTRL_ADDR 0x00
@@ -23,20 +25,14 @@
 double dist[2];

 //set up servos
-Servo steeringServo;
-Servo motorServo;
-const int steeringPin = 9;
-const int motorPin = 8;
+Servo steeringServo, motorServo;
+const int steeringPin = 9, motorPin = 8;

 //define PID variables
-double Setpoint_theta, Input_theta, Output_theta, Setpoint_dist, Input_dist, Output_dist;
+double Setpoint_theta = 0, Input_theta, Output_theta, Setpoint_dist = 90, Input_dist, Output_dist;
 //specify initial PID links and tuning
-int KpT = 1.7;    //1.7
-int KiT = 0;      //0
-int KdT = 0.01;   //0.01
-int KpD = 1.1;      //1
-int KiD = 0.075;    //0
-int KdD = 0.97;   //0
+int KpT = 1.7, KiT = 0, KdT = 0.01;  // {1.7, 0, 0.01}
+int KpD = 1.1, KiD = 0.075, KdD = 0.97;   // {1, 0, 0}
 PID PID_theta(&Input_theta, &Output_theta, &Setpoint_theta, KpT, KiT, KdT, DIRECT);
 PID PID_dist(&Input_dist, &Output_dist, &Setpoint_dist, KpD, KiD, KdD, DIRECT);

@@ -46,14 +42,18 @@
 // Set pi
 const float pi = 3.142;

+// Wheel encoder pulse counter variable
+const int encoder_pin = 2;
+volatile int encoder_count = 0;
+double wheel_rpm;
+#define ENCODER_SCALING 1
+
+XbeeApiStream xbeeStream = XbeeApiStream();
+bool state_paused = true;
+
+
 //---------------------------------------------------------//
 void setup() {
-  // Initialize linked variables
-  Input_theta = 0;
-  Input_dist = 100;
-  Setpoint_theta = 0;
-  Setpoint_dist = 90;
-
   PID_theta.SetMode(AUTOMATIC);
   PID_dist.SetMode(AUTOMATIC);

@@ -65,12 +65,19 @@
   motorServo.attach(motorPin);

   // Begin serial
-  Serial.begin(57600);
-  Serial.println("Serial begin");
+  Serial.begin(9600);
+  xbeeStream.begin(Serial);
+  xbeeStream.write("Serial begin");
   // Open and join irc bus as master
   Wire.begin();
   delay(100);

+  // Set encoder pin as input and enable internal pull-up resistor
+  pinMode(encoder_pin, INPUT);
+  digitalWrite(encoder_pin, HIGH);
+  attachInterrupt(digitalPinToInterrupt(encoder_pin), encoder_ISR, CHANGE);
+
+  // Set up the lidar pins and change the lidar acquisition count register value
   for (int i = 0; i < 2; i++)   pinMode(lidar_pwr_en[i], OUTPUT);
   for (int i = 0; i < 2; i++) {
     for (int j = 0; j < 2; j++)  digitalWrite(lidar_pwr_en[j], LOW);
@@ -86,30 +93,29 @@
 }

 void loop() {
-  now = millis();
-  read_lidars();
-  if (now - timestamp > 40) {
-    timestamp = now;
-//    dist[0] = 4.5 + dist[0] * (0.98); //scaling equation
-    Input_theta = calcAngle(dist[0], dist[1]);
-    Input_dist = calcPerpDist(dist[0], dist[1], Input_theta);
-    Input_theta = Input_theta * 180 / pi;
-//    Setpoint_theta = constrain(0.5*(Input_dist - Setpoint_dist), -45, 45);
+  if(xbeeStream.available() && xbeeStream.read() == 0x00)  state_paused = !state_paused;
+  if (!state_paused) {
+    now = millis();
+    read_lidars();
+    if (now - timestamp > 40) {
+      wheel_rpm = ENCODER_SCALING * encoder_count / (now - timestamp);
+      encoder_pin = 0;
+      timestamp = now;
+      //    dist[0] = 4.5 + dist[0] * (0.98); //scaling equation
+      Input_theta = calcAngle(dist[0], dist[1]);
+      Input_dist = calcPerpDist(dist[0], dist[1], Input_theta);
+      Input_theta = Input_theta * 180 / pi;
+      //    Setpoint_theta = constrain(0.5*(Input_dist - Setpoint_dist), -45, 45);

-    // Run the PID loops
-    Serial.print(dist[0]);
-    Serial.print(", ");
-    Serial.print(dist[1]);
-    Serial.print(", ");
-    Serial.print(Input_theta);
-    Serial.print(", ");
-    Serial.println(Input_dist);
-    PID_theta.Compute();
-    PID_dist.Compute();
+      // Run the PID loops
+      xbeeStream.write(String(String(dist[0], 1) + ',' + String(dist[1], 1) + ',' + String(Input_theta, 1) + ',' + String(Input_dist, 1)));
+      PID_theta.Compute();
+      PID_dist.Compute();

-    motorServo.write(90  - 20 );
-    steeringServo.write(90 + (Output_theta) - Output_dist); // + Output_theta - Output_dist
-  } // (50/abs(Input_dist - Setpoint_dist)) *
+      motorServo.write(90  - 20 );
+      steeringServo.write(90 + (Output_theta) - Output_dist); // + Output_theta - Output_dist
+    } // (50/abs(Input_dist - Setpoint_dist)) *
+  }
   delay(2);
 }

@@ -122,6 +128,10 @@

 double calcPerpDist(double dist0, double dist1, double angle) {
   return ((dist0 + dist1) * cos(angle)) / 2;
+}
+
+void encoder_ISR() {
+  encoder_count++;
 }

@@ -151,7 +161,7 @@
       if (Wire.requestFrom(LIDARLITE_ADDR, 2) >= 2) {
         uint16_t val = Wire.read() << 8 | Wire.read();
         if (val < 500 && val > 10) dist[enabled_lidar] = 0.2 * dist[enabled_lidar] + 0.8 * val;
-
+
         enabled_lidar = 1 - enabled_lidar;
         lidar_state = 0;
       } else state_cycle_count++;


Use only uint16_t for touch and tft coordinates.

Added and fixed some comments.

--- tfttask.ino
+++ tfttask.ino
@@ -8,7 +8,7 @@
 const uint16_t TFT_BUTTON_HEIGHT      =  40;

 const bool     TFT_SHOW_RAW           = false;            /* show raw PWM values */
-const bool     HIGH_VIZ_PERCENTAGE    = true;             /* show channel percent values in TFT_BACK_COLOR instead of the channel color to improve visibility */
+const bool     HIGH_VIZ_PERCENTAGE    = true;             /* show channel percent values in TFT_TEXT_COLOR instead of the channel color to improve visibility */

 enum tftFontsize_t
 {
@@ -32,8 +32,8 @@

     struct button_t
     {
-      int16_t        x;
-      int16_t        y;
+      uint16_t       x;
+      uint16_t       y;
       uint16_t       w;
       uint16_t       h;
       uint16_t       color;
@@ -184,6 +184,7 @@
     displayedLightStatus = lightStatus;
   }

+  /* process touch screen input */
   if ( touch.tirqTouched() )
   {
     TS_Point p = touch.getPoint();
@@ -442,41 +443,37 @@
   button.draw( EXIT_BUTTON );
 }

+
+static inline __attribute__((always_inline)) uint16_t mapUint16( const uint16_t &x, const uint16_t &in_min, const uint16_t &in_max, const uint16_t &out_min, const uint16_t &out_max)
+{
+  return ( x - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min;
+}
+
 static inline __attribute__((always_inline)) struct tftPoint_t mapToTft( const uint16_t &touchX, const uint16_t &touchY )
 {
   const uint16_t XPT_RES = 4096;
-  uint16_t x, y;

   if ( !TOUCH_IS_INVERTED )
   {
     if (  tftOrientation == TFT_ORIENTATION_UPSIDEDOWN )
-    {
-      x = map( touchX, 0, XPT_RES, 0, 320 );
-      y = map( touchY, 0, XPT_RES, 0, 240 );
-    }
+      return { mapUint16( touchX, 0, XPT_RES, 0, 320 ),
+               mapUint16( touchY, 0, XPT_RES, 0, 240 ) };
+
     else if ( tftOrientation == TFT_ORIENTATION_NORMAL )
-    {
-      x = map( touchX, 0, XPT_RES, 320, 0 );
-      y = map( touchY, 0, XPT_RES, 240, 0 );
-    }
+      return { mapUint16( touchX, 0, XPT_RES, 320, 0 ),
+               mapUint16( touchY, 0, XPT_RES, 240, 0 ) };
   }
   else
   {
     if (  tftOrientation == TFT_ORIENTATION_UPSIDEDOWN )
-    {
-      x = map( touchX, 0, XPT_RES, 320, 0 );
-      y = map( touchY, 0, XPT_RES, 240, 0 );
-    }
+      return { mapUint16( touchX, 0, XPT_RES, 320, 0 ),
+               mapUint16( touchY, 0, XPT_RES, 240, 0 ) };
+
     else if ( tftOrientation == TFT_ORIENTATION_NORMAL )
-    {
-      x = map( touchX, 0, XPT_RES, 0, 320 );
-      y = map( touchY, 0, XPT_RES, 0, 240 );
-    }
-  }
-  return { x, y };
-}
-
-
+      return { mapUint16( touchX, 0, XPT_RES, 0, 320 ),
+               mapUint16( touchY, 0, XPT_RES, 0, 240 ) };
+  }
+}

 static inline __attribute__((always_inline)) void showIPAddress( )
 {


this is the main file.

this is the main file.

--- MyBlinkySketch/MyBlinkySketch.ino
+++ MyBlinkySketch/MyBlinkySketch.ino
@@ -35,7 +35,7 @@
 uint8_t brightnesSteps[brightnessCount] = {93,70,40,15,5,15,40,70,93};
 uint8_t currentBrightness;
 uint8_t lastBrightness;
-
+//
 // For fading in a new sketch
 long lastTime;


Changed sleep angle

Changed sleep angle

--- Pan_Tilt_laser/Pan_Tilt_laser.ino
+++ Pan_Tilt_laser/Pan_Tilt_laser.ino
@@ -112,8 +112,8 @@

     laser.fire(0);
     mSwitch.ledState(0);
-    panTiltX.angle = panTiltX.midAngle - panTiltX.midOffset;
-    panTiltY.angle = panTiltY.midAngle - panTiltY.midOffset;
+    panTiltX.angle = 90;
+    panTiltY.angle = 90;
     panTilt.updateAngles();

     delay(50);


Update Fi-DEL.ino

Update Fi-DEL.ino

--- Arduino/Fi-DEL/Fi-DEL.ino
+++ Arduino/Fi-DEL/Fi-DEL.ino
@@ -4,6 +4,7 @@
 #include <ESP8266mDNS.h>
 #include <Adafruit_NeoPixel.h>

+#define BlueLed 2

 #define PIN   0 // GPIO.2 reservé a la led bleu du ESP
 #define NbLED 4
@@ -335,7 +336,8 @@

 void setup ( void ) {
     digitalWrite(2, LOW);
-
+    pinMode(BlueLed, OUTPUT);
+    digitalWrite(BlueLed, LOW); //Allumage de la LED Bleu du ESP
     strip.begin();
     strip.show();

@@ -361,11 +363,16 @@
         Serial.println ( "MDNS responder started" );
     }
     server.on ( "/", []() {handleRoot();} );
-    server.on ( "/rainbow", []()  {Choix = "Rainbow"; handleRoot(); } );
-    server.on ( "/theatre", []()  {Choix = "theaterChaseRainbow"; handleRoot();} );
-    server.on ( "/neige", []()    {Choix = "neige"; handleRoot();} );
-    server.on ( "/Gyro", []()    {Choix = "Gyro"; handleRoot();} );
-    server.on ( "/color", []()    {Choix = "color"; handleRoot();} );
+    server.on ( "/rainbow", []()  {Choix = "Rainbow";
+    digitalWrite(BlueLed, LOW); handleRoot(); } );
+    server.on ( "/theatre", []()  {Choix = "theaterChaseRainbow";
+    digitalWrite(BlueLed, LOW); handleRoot();} );
+    server.on ( "/neige", []()    {Choix = "neige";
+    digitalWrite(BlueLed, LOW); handleRoot();} );
+    server.on ( "/Gyro", []()    {Choix = "Gyro";
+    digitalWrite(BlueLed, LOW); handleRoot();} );
+    server.on ( "/color", []()    {Choix = "color";
+    digitalWrite(BlueLed, LOW); handleRoot();} );
     server.onNotFound ( handleNotFound );
     server.begin();
     Serial.println ( "HTTP server started" );
@@ -377,6 +384,8 @@
 void loop ( void ) {
   unsigned char rainbowIndex;
   unsigned char theaterChaseRainbowIndex;
+
+  digitalWrite(BlueLed, HIGH);

     mdns.update();
     server.handleClient();


Changed Serial timeout to 100ms

Changed Serial timeout to 100ms

--- ad9833/ad9833.ino
+++ ad9833/ad9833.ino
@@ -43,8 +43,7 @@
   10,// Coil 5
   9, // Coil 6
   8, // Coil 7
-  7  // Coil 8
-
+  7  // Coil 8
 };

 // Input serial buffer and size holder
@@ -60,18 +59,22 @@

 void setup()
 {
-	// Set states for the SPI enable pins
+	  // Set states for the SPI enable pins
     for (int i = 0; i < NUMCOILS; i++){
     	pinMode(coilEnable[i], INPUT);
     }

-    // wake up the SPI bus and set SPI mode and SCLK divisor.
+    // Start Serial and reduce timeout to 100ms
+    Serial.begin(115200);
+    Serial.setTimeout(100);
+
+    // wake up the SPI bus and set SPI mode and SCLK divisor
     SPI.begin();

     // Allow some time for power-on
     delay(200);

-    // Program each AD9833 waveform generator
+    // Program each AD9833 waveform generator with default frequencies
     sendAllFreqs();

@@ -185,6 +188,8 @@
 	}
 }

+
+
 int processFreqs(char *cmd)
 {
 	char *separator = 0;


added capacitivePin-feature

added capacitivePin-feature

--- sketches/prototype/prototype.ino
+++ sketches/prototype/prototype.ino
@@ -26,6 +26,71 @@

 void Version(){
   Serial.println("version");
+}
+
+uint8_t readCapacitivePin(String data) {
+  int pinToMeasure = Str2int(data);
+  // readCapacitivePin
+  //  Input: Arduino pin number
+  //  Output: A number, from 0 to 17 expressing
+  //  how much capacitance is on the pin
+  //  When you touch the pin, or whatever you have
+  //  attached to it, the number will get higher
+  //  http://playground.arduino.cc/Code/CapacitiveSensor
+  //
+  // Variables used to translate from Arduino to AVR pin naming
+  volatile uint8_t* port;
+  volatile uint8_t* ddr;
+  volatile uint8_t* pin;
+  // Here we translate the input pin number from
+  //  Arduino pin number to the AVR PORT, PIN, DDR,
+  //  and which bit of those registers we care about.
+  byte bitmask;
+  port = portOutputRegister(digitalPinToPort(pinToMeasure));
+  ddr = portModeRegister(digitalPinToPort(pinToMeasure));
+  bitmask = digitalPinToBitMask(pinToMeasure);
+  pin = portInputRegister(digitalPinToPort(pinToMeasure));
+  // Discharge the pin first by setting it low and output
+  *port &= ~(bitmask);
+  *ddr  |= bitmask;
+  delay(1);
+  // Make the pin an input with the internal pull-up on
+  *ddr &= ~(bitmask);
+  *port |= bitmask;
+
+  // Now see how long the pin to get pulled up. This manual unrolling of the loop
+  // decreases the number of hardware cycles between each read of the pin,
+  // thus increasing sensitivity.
+  uint8_t cycles = 17;
+       if (*pin & bitmask) { cycles =  0;}
+  else if (*pin & bitmask) { cycles =  1;}
+  else if (*pin & bitmask) { cycles =  2;}
+  else if (*pin & bitmask) { cycles =  3;}
+  else if (*pin & bitmask) { cycles =  4;}
+  else if (*pin & bitmask) { cycles =  5;}
+  else if (*pin & bitmask) { cycles =  6;}
+  else if (*pin & bitmask) { cycles =  7;}
+  else if (*pin & bitmask) { cycles =  8;}
+  else if (*pin & bitmask) { cycles =  9;}
+  else if (*pin & bitmask) { cycles = 10;}
+  else if (*pin & bitmask) { cycles = 11;}
+  else if (*pin & bitmask) { cycles = 12;}
+  else if (*pin & bitmask) { cycles = 13;}
+  else if (*pin & bitmask) { cycles = 14;}
+  else if (*pin & bitmask) { cycles = 15;}
+  else if (*pin & bitmask) { cycles = 16;}
+
+  // Discharge the pin again by setting it low and output
+  //  It's important to leave the pins low if you want to
+  //  be able to touch more than 1 sensor at a time - if
+  //  the sensor is left pulled high, when you touch
+  //  two sensors, your body will transfer the charge between
+  //  sensors.
+  *port &= ~(bitmask);
+  *ddr  |= bitmask;
+
+  //return cycles;
+  Serial.println(cycles);
 }

 void Tone(String data){
@@ -274,8 +339,10 @@
   else if (cmd == "nto") {
       ToneNo(data);
   }
-}
-
+  else if (cmd == "cap") {
+      readCapacitivePin(data);
+  }
+}

 void setup()  {
   Serial.begin(9600);


- add pin out comments for physical web beacon example

--- examples/physical_web_beacon/physical_web_beacon.ino
+++ examples/physical_web_beacon/physical_web_beacon.ino
@@ -1,10 +1,15 @@
 // Import libraries (BLEPeripheral depends on SPI)
 #include <SPI.h>
 #include <BLEPeripheral.h>
-
-#include "URIBeacon.h"
+#include <URIBeacon.h>

 // define pins (varies per shield/board)
+//
+//   Adafruit Bluefruit LE   10, 2, 9
+//   Blend                    9, 8, UNUSED
+//   Blend Micro              6, 7, 4
+//   RBL BLE Shield           9, 8, UNUSED
+
 #define URI_BEACON_REQ   10
 #define URI_BEACON_RDY   2
 #define URI_BEACON_RST   9


Digital stuff is (basically) feature complete, but buggy.

--- teensy-stim/teensy-stim.ino
+++ teensy-stim/teensy-stim.ino
@@ -151,7 +151,7 @@
   }

   bool parse_all(byte *input) {
-    for (int i = 1; i < 5; i++) if (input[i*8] != ';') return false;
+    for (int i = 1; i < 6; i++) if (input[i*8] != ';') return false;
     Dura x; x = {0, 0};
     // Manually unrolled loop
     x.parse(input, 0*9); if (!x.is_valid()) return false; t = x;
@@ -163,24 +163,26 @@
     return true;
   }

+  void solo(Protocol *ps, int &pi) {
+    int i = 0;
+    ps[i] = *this;
+    while (i+1 < PROT && ps[i].next < PROT) {
+      ps[i+1] = ps[ps[i].next];
+      ps[i].next = (byte)(i+1);
+      i++;
+    }
+    pi = i;
+  }
+
   static void init(Protocol *ps, int &pi) {
     for (int i = 0; i < DIG+ANA; i++) ps[i].init();
     for (int i = DIG; i < DIG+ANA; i++) ps[i].j = 'l';
-    pi = DIG+ANA;
-  }
-
-  byte append(int &pi) {
-    if (pi < PROT) {
-      next = (byte)pi;
-      pi++;
-      return next;
-    }
-    else return 255;
+    pi = 0;
   }
 };

 Protocol protocols[PROT];
-int proti = DIG+ANA;
+int proti = 0;
 Protocol not_a_protocol = (Protocol){{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, ' ', ' ', 255, 255};

@@ -220,6 +222,7 @@

 #define ANALOG_ZERO 2047
 #define ANALOG_AMPL 2047
+#define ANALOG_DIVS 16384

 #define CHAN (DIG+ANA)

@@ -236,7 +239,7 @@
   void init(int index) {
     *this = (Channel){ {0, 0}, {0, 0}, {0, 0}, C_ZZZ, 0, 255, 255, {0, 0, 0, 0, 0, 0, 0, 0} };
     pin = (index < DIG) ? digi[index] : 255;
-    zero = (index < CHAN) ? index : 255;
+    zero = 255;
   }

   void refresh(Protocol *ps) {
@@ -272,6 +275,7 @@
       runlevel = C_WAIT;
       t = p->t; t += d;
       yn = p->d; yn += d;
+      return true;
     }
     else {
       who = 255;
@@ -359,14 +363,28 @@

   static void refresh(Channel *cs, Protocol *ps) { for (int i = 0; i < CHAN; i++) cs[i].refresh(ps); }

-  static Dura advance(Channel *cs, Dura d, Protocol *ps) {
+  static void solo(Channel *cs, int it, Protocol *ps, int &pi) {
+    for (int i = 0; i < CHAN; i++) {
+      if (i == it) {
+        if (cs[i].who < PROT) ps[cs[i].who].solo(ps, pi);
+        cs[i].refresh(ps);
+      }
+      else cs[i].init(i);
+    }
+  }
+
+  static Dura advance(Channel *cs, Dura d, Protocol *ps, int &living) {
     Dura x = (Dura){0, 0};
+    int a = 0;
     for (int i = 0; i < DIG; i++) if (cs[i].alive()) {
+      a += 1;
       Dura y = cs[i].advance(d, ps);
       if (!y.is_empty()) {
         if (x.is_empty() || y < x) x = y;
       }
-    }
+      else if (!cs[i].alive()) a -= 1;
+    }
+    living = a;
     return x;
   }
 };
@@ -541,7 +559,7 @@
 }

 void init_analog() {
-  for (int i = 0; i < 256; i++) wave[i] = (int16_t)(ANALOG_ZERO + (short)round(ANALOG_AMPL*sin(i * 2 * M_PI)));
+  for (int i = 0; i < 256; i++) wave[i] = (int16_t)round(ANALOG_DIVS*sin(i * 2 * (M_PI / 256)));
   analogWriteResolution(12);
   analogWrite(A14, ANALOG_ZERO);
 }
@@ -571,6 +589,7 @@
 #define RUNSET   1
 #define GOGOGO   2
 volatile int runlevel;   // -2 error; -1 stopping to error; 0 ran; 1 accepting commands; 2 running
+volatile int alive;      // Number of channels alive and running

 volatile bool led_is_on;

@@ -605,6 +624,7 @@
 void go_go_go() {
   if (runlevel == RUNSET) {
     runlevel = LOCKED;
+    alive = 0;
     if (led_is_on) {
       led_is_on = false;
       digitalWrite(LED_PIN, LOW);
@@ -614,6 +634,7 @@
       Channel *c = channels + i;
       c->who = c->zero;
       if (c->who == 255) continue;
+      alive += 1;
       Protocol *p = protocols + c->who;
       c->pin_off(p);
       c->t = p->t;
@@ -632,6 +653,14 @@
   else if (runlevel != ERRDONE && runlevel != ERRSTOP) {
     error_with_message("Attempt to start running from invalid state.", "");
   }
+}
+
+bool run_iteration() {
+  // Can't pass volatile as reference, so buffer it
+  int living = alive;
+  next_event = Channel::advance(channels, global_clock, protocols, living);
+  alive = living;
+  return alive != 0;
 }

@@ -667,31 +696,96 @@
   }
 }

+Protocol* process_ensure_protocol(byte ch) {
+  Channel *c = process_get_channel(ch);
+  if (c->who != 255) return protocols + c->who;
+  else if (c->zero != 255) {
+    c->refresh(protocols);
+    return protocols + c->who;
+  }
+  else if (proti < PROT) {
+    c->zero = proti;
+    c->who = c->zero;
+    protocols[proti].init();
+    proti++;
+    return protocols + c->who;
+  }
+  else return process_get_protocol(ch);   // Defer to get for error handling
+}
+
+Protocol* process_new_protocol(byte ch) {
+  Channel *c = process_get_channel(ch);
+  if (proti < PROT) {
+    byte old = c->who;
+    while (c->who != 255) { old = c->who; c->who = protocols[c->who].next; }
+    protocols[old].next = (byte)proti;
+    c->who = (byte)proti;
+    protocols[proti].init();
+    proti++;
+    return protocols + c->who;
+  }
+  else {
+    c->who = 255;
+    return process_get_protocol(ch);    // Defer to get for error handling
+  }
+}
+
 void process_reset() {
   Protocol::init(protocols, proti);
   Channel::init(channels);
   erri = 0;
+  alive = 0;
   runlevel = RUNSET;
 }

 void process_refresh() {
-  Channel::refresh(channels, protocols);
+  if (runlevel == RUNSTOP) {
+    Channel::refresh(channels, protocols);
+    runlevel = RUNSET;
+  }
 }

 void process_start_running() {
-  // TODO - write me
+  go_go_go();
 }

 void process_start_running(byte who) {
-  // TODO - write me
+  if (who >= 'A' && who <= 'Z' && who != 'Y') {
+    int i = who - 'A';
+    if (who == 'Z') i -= 1;
+    Channel::solo(channels, i, protocols, proti);
+    process_start_running();
+  }
+  else {
+    char tiny[3]; tiny[0] = who; tiny[1] = '\n'; tiny[2] = 0;
+    error_with_message("Trying to run on unknown channel", tiny);
+  }
 }

 void process_stop_running(byte who) {
-  // TODO - write me
+  Channel *c = process_get_channel(who);
+  if (runlevel == GOGOGO) {
+    if (c->who != 255) {
+      c->pin_low();
+      c->runlevel = C_ZZZ;
+      c->who = 255;
+      if (alive > 0) alive -= 1;
+      if (alive == 0) runlevel = RUNSTOP;
+    }
+  }
 }

 void process_stop_running() {
-  // TODO - write me
+  for (int i = 0; i < DIG; i++) {
+    Channel *c = channels + i;
+    if (c->who != 255) {
+      c->pin_low();
+      c->runlevel = C_ZZZ;
+      c->who = 255;
+    }
+  }
+  alive = 0;
+  runlevel = RUNSTOP;
 }

 void process_say_the_time() {
@@ -773,7 +867,7 @@
       case '@': Serial.write("~."); Serial.send_now(); break;
       case '*': process_start_running(ch); break;
       case '/': break;
-      case '&': /* TODO */ break;
+      case '&': process_new_protocol(ch); break;
       case '=':
       case ':':
         if (bufi < 56) return;
@@ -781,18 +875,18 @@
           error_with_message("Cannot set all on channel Z: ", (char*)buf, 12);
         }
         else {
-          if (!process_get_protocol(ch)->parse_all(buf+3)) {
-            error_with_message("Bad =: ", (char*)buf, 53);
+          if (!process_ensure_protocol(ch)->parse_all(buf+3)) {
+            error_with_message("Bad =: ", (char*)buf, 56);
           }
         }
         discard_buf(56);
         if (b == ':') process_start_running(ch);
         return;
         break;
-      case 'u': process_get_protocol(ch)->i = 'u'; break;
-      case 'i': process_get_protocol(ch)->i = 'i'; break;
-      case 'l': if (ch != 'Z') error_with_message("Analog required: ", (char*)buf, 3); else process_get_protocol(ch)->j = 'l'; break;
-      case 'r': if (ch != 'Z') error_with_message("Analog required: ", (char*)buf, 3); else process_get_protocol(ch)->j = 'r'; break;
+      case 'u': process_ensure_protocol(ch)->i = 'u'; break;
+      case 'i': process_ensure_protocol(ch)->i = 'i'; break;
+      case 'l': if (ch != 'Z') error_with_message("Analog required: ", (char*)buf, 3); else process_ensure_protocol(ch)->j = 'l'; break;
+      case 'r': if (ch != 'Z') error_with_message("Analog required: ", (char*)buf, 3); else process_ensure_protocol(ch)->j = 'r'; break;
       case 't':
       case 'd':
       case 's':
@@ -805,7 +899,7 @@
           error_with_message("Bad command for channel: ", (char*)buf, 11);
         }
         else {
-          if (!process_get_protocol(ch)->parse_labeled(b, buf+3)) {
+          if (!process_ensure_protocol(ch)->parse_labeled(b, buf+3)) {
             error_with_message("Bad duration format: ", (char*)buf, 11);
           }
         }
@@ -883,6 +977,7 @@
 // Setup runs once at reset / power on
 void setup() {
   runlevel = RUNSTOP;
+  alive = 0;
   init_eeprom();
   init_digital();
   init_analog();
@@ -912,8 +1007,9 @@
   bool urgent = false;
   if (next_event < global_clock) {
     urgent = true;
-    if (runlevel == GOGOGO) {
-      /* TODO */
+    if (runlevel == GOGOGO) {
+      bool complete = run_iteration();
+      if (complete) process_stop_running();
     }
     else {
       if (led_is_on) digitalWrite(LED_PIN, LOW);