Update Weather_mikroe_SAM3X.ino

Update Weather_mikroe_SAM3X.ino

add Air Quality 4 Click to Slot D

--- Weather_mikroe_SAM3X/Weather_mikroe_SAM3X.ino
+++ Weather_mikroe_SAM3X/Weather_mikroe_SAM3X.ino
@@ -19,7 +19,8 @@
  * 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.
  *
- * Slot: C: Weather Click
+ * Slot: C: Weather Click
+ * Slot: D: Air Quality 4 Click
  *
  ***************************************************************************/

@@ -30,10 +31,14 @@
 #include <Adafruit_Sensor.h>
 #include <Adafruit_BME280.h>

+/* Adafruit SGP30 Sensor: 1.0.5 */
+#include <Adafruit_SGP30.h>
+
 #include "flip_click_defs.h"
 //#include "SparkFun_AS3935.h"

 Adafruit_BME280 bme; // I2C
+Adafruit_SGP30 sgp;

 unsigned long delayTime;

@@ -59,13 +64,30 @@
 int counter=10;

 bool has_bme = true;
+bool has_sgp = true;
+
+volatile float bme_temperature = 0;
+volatile float bme_humidty = 0;
+
+
+/* return absolute humidity [mg/m^3] with approximation formula
+* @param temperature [°C]
+* @param humidity [%RH]
+*/
+uint32_t getAbsoluteHumidity(float temperature, float humidity) {
+    // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
+    const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
+    const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
+    return absoluteHumidityScaled;
+}

 void setup()
 {
-  Serial.begin(57600);
-  Serial.println("MIKROE SAM3X WeatherDemo");
-
-  bme_init();
+	Serial.begin(57600);
+	Serial.println("MIKROE SAM3X WeatherDemo:#");
+
+	bme_init();
+	sgp_init();

 //  SPI.begin();
 //  SPI.setDataMode( SPI_MODE1 );
@@ -77,6 +99,7 @@
 //  tmp116_init();
 }

+int counter_sgp = 0;
 void loop()
 {
 //  double temp = TMP116_ReadTempSensor();
@@ -101,38 +124,89 @@
 //    }
 //  }

-  bme_read();
-
-  counter++;
-  if (counter == 100)
-  {
-    counter = 10;
-  }
-
-  delay(5000); // wait 5 seconds for the next I2C scan
+	if (has_bme) {
+		bme_read();
+	}
+
+	if (has_sgp) {
+		sgp_read();
+	}
+
+	counter++;
+	if (counter == 100) {
+		counter = 10;
+	}
+
+	delay(5000); // wait 5 seconds for the next I2C scan
 }

 void bme_init() {
-   if (! bme.begin(0x76, &Wire)) {
-        Serial.println("Could not find a valid BME280 sensor, check wiring!");
-        has_bme=false;
-    }
+	if (! bme.begin(0x76, &Wire)) {
+		Serial.println("BME280: Sensor not found!:#");
+		has_bme=false;
+	}
 }

 void bme_read() {
-    bme.takeForcedMeasurement(); // has no effect in normal mode
-
-    Serial.print("MIKROESAM3X_WC:");
-    Serial.print(counter);
-    Serial.print(":Temp:");
-    float bme_temp_c = bme.readTemperature();
-    float bme_temp_f = ((bme_temp_c * 1.8) + 32);
-    Serial.print(bme_temp_f);
-    Serial.print("F:Press:");
-    Serial.print(bme.readPressure() / 100.0F);
-    Serial.print("mB:Humidity:");
-    Serial.print(bme.readHumidity());
-    Serial.println("%:#");
+	bme.takeForcedMeasurement(); // has no effect in normal mode
+	Serial.print("MIKROESAM3X_WC:");
+	Serial.print(counter);
+	Serial.print(":Temp:");
+	bme_temperature = bme.readTemperature();
+	float bme_temp_f = ((bme_temperature * 1.8) + 32);
+	Serial.print(bme_temp_f);
+	Serial.print("F:Press:");
+	Serial.print(bme.readPressure() / 100.0F);
+	Serial.print("mB:Humidity:");
+	bme_humidty = bme.readHumidity();
+	Serial.print(bme_humidty);
+	Serial.println("%:#");
+}
+
+void sgp_init() {
+	if (! sgp.begin()) {
+		Serial.println("SGP30: Sensor not found!:#");
+        has_sgp=false;
+    }
+	Serial.print("Found SGP30 serial #");
+	Serial.print(sgp.serialnumber[0], HEX);
+	Serial.print(sgp.serialnumber[1], HEX);
+	Serial.print(sgp.serialnumber[2], HEX);
+	Serial.println(":#");
+}
+
+void sgp_read() {
+	// If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humditiy compensation for the air quality signals
+	//float bme_temperature = 22.1; // [°C]
+	//float bme_humidty = 45.2; // [%RH]
+	if (has_bme) {
+		sgp.setHumidity(getAbsoluteHumidity(bme_temperature, bme_humidty));
+	}
+
+	Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
+	Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");
+
+	if (! sgp.IAQmeasureRaw()) {
+		Serial.println("Raw Measurement failed");
+		return;
+	}
+	Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t");
+	Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println("");
+
+	delay(1000);
+
+	counter_sgp++;
+	if (counter_sgp == 30) {
+		counter_sgp = 0;
+
+		uint16_t TVOC_base, eCO2_base;
+		if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
+			Serial.println("Failed to get baseline readings");
+			return;
+		}
+		Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
+		Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
+	}
 }

 void thunder_init()


Add AutoRun modes to the Arduino Nano MCB test program

--- scripts/McbController.ino
+++ scripts/McbController.ino
@@ -1,54 +1,55 @@
 /*
   MCB Controller That Runs On The Arduino Platform for debug or very very simple controllers

-  A basic MCB speed control for the Ubiquity Robotics Magni Robot is implemented
-  This code is meant for the Arduino Nano model but because of how IDE works can easily be used
-  on other processors as supported by the Arduino IDE board support packages. .
-
-  This is meant as a debug tool for board bringup as well as example code showing how to send
-  Magni commands with the way we do checksum and transmission over serial.
-
-  User needs to power up his Arduino Nano from a usb power source or directly from Magni P508  GND and VCC
-  The Arduino 5V level TX pin goes to the P508 5V RX pin and Arduino Ground goes to P508 ground.
-  Optionally you can power the Arduino all from P508 because there is 5V VCC on P508 as well to go to Nano +5 line.
+  Some basic MCB speed control for the Ubiquity Robotics Magni Robot is implemented
+  This code is meant for the Arduino Nano model.
+
+  This code could be used to build upon a far more complex robot based on the Arduino platform
+  or other platform supported by the Arduino IDE libraries.
+
+  As a minimum the Arduino 5V level TX signal goes to MCB board P508  RX pin and Arduino Ground goes to P508 ground.
+  Optionally you can power the Arduino all from P508 because there is 5V VCC on P508 as well.
   (Note that to do that you must tie MCB Vcc on P508 to Arduino 5V power because the spec for VIN is for 6V or more)

   Usage Instructions
-  - Connect two 1k to 20k linear taper pots with each of the ends on GND and Vcc.
-    Center tap of one pot to Arduino A1 and the center tap of the other pot to Arduino A2.
-  - Default with no jumpers is for each pot to separately control a single wheel.
-  - Optionally ground the ENABLE_JOYSTICK pin to interprit two pots as a simple joystick
+  - Ground the ENABLE_SPEED_PIN (can be used as an ESTOP)
+  - Connect tow 1k to 20k pots with each of the ends on GND and Vcc.
+    Center tap of one pot to A1, center tap of other pot to A2.
+    Default with no jumpers is for each pot to separately control a single wheel.
+  - Optionally ground the ENABLE_JOYSTICK pin to interprit two pots as joystick if you hook up dual pot joystick
   - Optionally a normaly closed switch from ground to ENABLE_SPEED_PIN for switch that must close to run motors
     When the ENABLE_SPEED_PIN is floating motors are enabled. When it goes to ground motors stop
+  - Optionally have a switch to ground for going into AutoRun mode.  (reverses direction on settable time interval)
+
+  Hardware Connections To Ubiquity Robotics MCB board
+  - An Arduino Nano is hooked to 3 lines on the MCB P508 FTDI Jack. No converter is required.
+  - Arduino GND to pin 1 (MCB Ground)
+  - Arduino  5V to pin 3 (MCB 5V+)
+  - Arduino  TX to pin 5 (MCB RX to receive serial at 38.4 kBaud

   Author:  mj@ubiquityrobotics.com
-  Date:    20210103
+  Created: 20210103  Basic constant running with simple pot speed controls
+  Updated: 20210312  Added AutoRun mode for back and forth wheel tests. Added reed relay on when in 'forward'. Cleanup speed set routine

 */

+// Defines for the Arduino Nano.  Use these to hook up the optional jumpers and the required potentiometers
+#define ENABLE_JOYSTICK  2   // Pull to ground to enable interpritation of pots as a joystick. Normally float this pin.
 #define ENABLE_SPEED_PIN 3   // Release from ground to enable speed messages (thus use NC switch to use this feature)
-#define ENABLE_JOYSTICK  2   // Pull to ground to enable interpritation of pots as a joystick
-#define SPEED_POT_RIGHT  A1  // Motor speed control for right wheel
-#define SPEED_POT_LEFT   A2  // Motor speed control for left  wheel
-
-int debugMode = 0;        // set to 1 to use serial monitor but normally 0 for real speed commands out
-
-long loopTimeMs = 50;     // Need to keep repeating speeds or deadman timer kicks in on MCB
-long pulseOnTimeMs;       // On time in millisec
-long pulseOffTimeMs;      // Off time in millisec
-
-int  leftSpeed    = 0;
-int  rightSpeed   = 0;
-int  linearSpeed  = 0;
-int  rotateSpeed  = 0;
-
-int  xmitEnable     = 0; // When non-zero we allow speed messages to be continuously sent. Set to -1 to now use this feature
-int  joystickEnable = 0; // When positive (input pin ground) this interprites pots as from a joystick. Set to -1 for never joystick
-
-// Format a basic speed command.  Bytes 3,4 are MSB,LSB of signed right speed and bytes 5,6 are signed left speed
-byte speedCmd[]={0x7e, 0x3b, 0x2a, 0, 0, 0, 0, 0};
-int  cmdPacketLen = 8;
-int  msgXmitLen   = 0;
+#define VAR_AUTO_RUN     4   // If pulled to ground we are in automatic test mode where one pot is speed, other is time till reverse dir
+#define VIRT_GND_1       5   // A pin set to ground to use for a 2-pin jumper that is adjacent to AUTO_RUN so connect with 0.1" jumper for AutoRun
+#define FIXED_AUTO_RUN   6   // Jumper this to VIRT_GND for fixed speed/duration auto-run thus NO pots. Fixed test, easy with 1 jumper
+#define RELAY_1_DRIVE    7   // We flip a relay when in auto-run mode which may be useful for other purposes. Active Low so relay also to +5
+#define VIRT_VCC_1       8   // A pin driven high to source a low current LED anode with resistor.  This is 'on' for forward in AutoRun
+#define SPEED_POT_RIGHT  A1  // Motor speed control for right wheel in normal mode but in AutoRun this is the interval between reversals
+#define SPEED_POT_LEFT   A2  // Motor speed control for left  wheel or for AutoRun is motor speed for BOTH pins and gets reversed periodically
+
+int  g_debugMode      = 0;  // set to 1 to use serial monitor but normally 0 for real speed commands out
+long g_loopTimeMs     = 50; // Need to keep repeating speeds or deadman timer kicks in on MCB
+int  g_xmitEnable     = 0;  // When non-zero we allow speed messages to be continuously sent. Set to -1 to now use this feature
+int  g_joystickEnable = 0;  // When positive (input pin ground) this interprites pots as from a joystick. Set to -1 for never joystick
+int  g_varAutoRun     = 0;  // When non-zero indicates auto-run mode that runs then reverses diretion with given period till reversal
+int  g_fixedAutoRun   = 0;  // Simplest of all fixed auto-run so no pots are required.  This makes standalone test super easy wiring

 // Calculate a simple single byte checksum from a byte array of given length
@@ -78,37 +79,125 @@
 // the setup function runs once when you press reset or power the board
 void setup() {
   // initialize digital pin LED_BUILTIN as an output.
-  pinMode(LED_BUILTIN, OUTPUT);
+  pinMode(LED_BUILTIN,      OUTPUT);
+  pinMode(VIRT_GND_1,       OUTPUT);
+  pinMode(RELAY_1_DRIVE,    OUTPUT);
+  pinMode(VIRT_VCC_1,       OUTPUT);
+
   pinMode(ENABLE_SPEED_PIN, INPUT_PULLUP);
   pinMode(ENABLE_JOYSTICK,  INPUT_PULLUP);
   pinMode(SPEED_POT_RIGHT,  INPUT);
   pinMode(SPEED_POT_LEFT,   INPUT);
+  pinMode(VAR_AUTO_RUN,     INPUT_PULLUP);
+  pinMode(FIXED_AUTO_RUN,   INPUT_PULLUP);

   Serial.begin(38400);     // Set to speed for MCB control
-}
-
+
+  digitalWrite(RELAY_1_DRIVE, HIGH);
+  digitalWrite(VIRT_VCC_1,    HIGH);
+  digitalWrite(VIRT_GND_1,    LOW);
+}
+
+// Send out a speed command for both motors
+void setMotorSpeeds(int leftSpeed, int rightSpeed)  {
+  // Format a basic speed command.  Bytes 3,4 are MSB,LSB of signed right speed and bytes 5,6 are signed left speed
+  byte speedCmd[]={0x7e, 0x3b, 0x2a, 0, 0, 0, 0, 0};
+  int  cmdPacketLen = 8;
+  int  msgXmitLen   = 0;
+
+  // Bytes 3,4 are MSB,LSB of signed right speed and bytes 5,6 are signed left speed
+  // Pack in the 2 speed bytes
+  if (rightSpeed < 0) {
+        speedCmd[3] = 0xff;
+        speedCmd[4] = 0xff - ((-1 * rightSpeed) & 0xff);
+  } else {
+        speedCmd[3] = 0;
+        speedCmd[4] = rightSpeed & 0xff;
+  }
+  if (leftSpeed < 0) {
+        speedCmd[5] = 0xff;
+        speedCmd[6] = 0xff - ((-1 * leftSpeed) & 0xff);
+  } else {
+        speedCmd[5] = 0;
+        speedCmd[6] = leftSpeed & 0xff;
+  }
+
+  // The start byte is 0x7E so the cmdPacket where we calculate checksum does not include that
+  cmdPacketLen = 6;
+  speedCmd[cmdPacketLen+1] = calcPacketCksum( &speedCmd[1], cmdPacketLen);
+  msgXmitLen = cmdPacketLen + 2;  // add in start byte and checksum bytes for total xmit length
+
+  // Write out the speed command over serial port
+  Serial.write(speedCmd, msgXmitLen);
+}
+
+
+int  leftSpeed    = 0;
+int  rightSpeed   = 0;
+int  linearSpeed  = 0;
+int  rotateSpeed  = 0;
+int  reversePeriodMs = 1000;
+int  autoDirection = 1;
+int  periodMs     = 30000;  // Make it big to start
+
 // the loop function runs over and over again forever
 void loop() {

   // Setup mode based on pins we see in a given state. If this was set to -1 always enable motors
   // The idea here is that a normally closed deadman switch can be used so motors stop if switch is not pressed
-  if (xmitEnable >= 0) {
-    xmitEnable = digitalRead(ENABLE_SPEED_PIN);
-  }
+  if (g_xmitEnable >= 0) {
+    g_xmitEnable = digitalRead(ENABLE_SPEED_PIN);
+  }
+
+  g_varAutoRun   = digitalRead(VAR_AUTO_RUN);     // See if we are to do variable auto-run mode
+  g_fixedAutoRun = digitalRead(FIXED_AUTO_RUN);   // See if we are to to fixed speed and period auto-run mode

   // Allow two pots to be interprited as a simple joystick control.  Default is each pot controls one motor.
-  if (joystickEnable >= 0) {
-    joystickEnable = 0;
+  if (g_joystickEnable >= 0) {
+    g_joystickEnable = 0;
     if (digitalRead(ENABLE_JOYSTICK) == 0) {
-      joystickEnable = 1;
-    }
-  }
-
-  if (joystickEnable <= 0) {
+      g_joystickEnable = 1;
+    }
+  }
+
+  // Determine motor right and left speed based on mode we are in at the time
+  if ((g_varAutoRun == 0) || (g_fixedAutoRun == 0)) {
+    if (g_fixedAutoRun == 0)  {   // Used constants so no pot is required
+      // Fixed default test where very simple wiring does auto reversing default speeds and reversal time
+      leftSpeed = 20;
+      reversePeriodMs = 4000;
+    } else {
+      // Left pot is speed and right pot is time interval between speed reversals
+      reversePeriodMs = ((long)analogRead(SPEED_POT_RIGHT) * 10) + 500;
+      leftSpeed  = ((long)analogRead(SPEED_POT_LEFT) - 512)  / 8;     // allow signed 0-64
+    }
+
+    // Reversal time has a minimum time and then pot setting adds to that up to 10 sec more
+
+    if (periodMs > reversePeriodMs) {
+      autoDirection = autoDirection * -1;    // Reverse direction
+      periodMs = 0;                          // reset clock for next period
+    }
+    periodMs += g_loopTimeMs;
+
+    // Left pot is signed speed for when autoDirection is 1 and gets reversed when autoDirection = -1
+    leftSpeed = leftSpeed * autoDirection;
+    rightSpeed = leftSpeed;    // In autoRun mode both speeds are the same
+
+    // We drive an optional reed relay that alternates on to off as an extra feature
+    if (autoDirection > 0) {
+      digitalWrite(RELAY_1_DRIVE, LOW);
+    } else {
+      digitalWrite(RELAY_1_DRIVE, HIGH);
+    }
+
+  } else if (g_joystickEnable <= 0) {
+    // Directly determine speeds from two pots in joystick mode
     leftSpeed  = ((long)analogRead(SPEED_POT_LEFT) - 512)  / 8;     // allow signed 0-64
     rightSpeed = ((long)analogRead(SPEED_POT_RIGHT) - 512) / 8;     // allow signed 0-64
+
   } else {
-    // Interprit pots as one is forward/reverse and the other is bias to right or left (rotation)
+    // Joystick mode: Interprit pots as one is forward/reverse and the other is bias to right or left (rotation)
     linearSpeed  = ((long)analogRead(SPEED_POT_LEFT) - 512)  / 8;     // allow signed 0-64
     rotateSpeed  = ((long)analogRead(SPEED_POT_RIGHT) - 512) * 2;     // This is near +- 1024

@@ -124,49 +213,23 @@
     }
   }

-  // Format a basic speed command.  Bytes 3,4 are MSB,LSB of signed right speed and bytes 5,6 are signed left speed
-
-  // Pack in the 2 speed bytes
-  if (rightSpeed < 0) {
-        speedCmd[3] = 0xff;
-        speedCmd[4] = 0xff - ((-1 * rightSpeed) & 0xff);
-  } else {
-        speedCmd[3] = 0;
-        speedCmd[4] = rightSpeed & 0xff;
-  }
-  if (leftSpeed < 0) {
-        speedCmd[5] = 0xff;
-        speedCmd[6] = 0xff - ((-1 * leftSpeed) & 0xff);
-  } else {
-        speedCmd[5] = 0;
-        speedCmd[6] = leftSpeed & 0xff;
-  }
-
-  // The start byte is 0x7E so the cmdPacket where we calculate checksum does not include that
-  cmdPacketLen = 6;
-  speedCmd[cmdPacketLen+1] = calcPacketCksum( &speedCmd[1], cmdPacketLen);
-  msgXmitLen = cmdPacketLen + 2;  // add in start byte and checksum bytes for total xmit length
-
-  if (debugMode == 1) {
-    loopTimeMs = 1000;
-    if (joystickEnable == 0) {
+  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
+
+  // Set motor speeds if enabled
+  // Write out the speed command if transmit is enabled
+  if ((g_xmitEnable != 0) && (g_debugMode == 0)) {
+     setMotorSpeeds(leftSpeed, rightSpeed);
+  }
+
+  if (g_debugMode == 1) {
+    g_loopTimeMs = 1000;
+    if (g_joystickEnable == 0) {
       Serial.print("MotorSpeeds:  Left= "); Serial.print(leftSpeed); Serial.print("  Right= "); Serial.println(rightSpeed);
     } else {
       Serial.print("JoystickSpeeds:  Left= "); Serial.print(leftSpeed); Serial.print("  Right= "); Serial.println(rightSpeed);
     }
-    Serial.print("Msg: ");
-    for (int i = 0; i<msgXmitLen ; i++) {
-      Serial.print("  "); Serial.print( speedCmd[i]);
-    }
-    Serial.println("\n");
-  }
-
-  // Write out the speed command if transmit is enabled
-  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
-  if ((xmitEnable != 0) && (debugMode == 0)) {
-     Serial.write(speedCmd, msgXmitLen);
   }
   digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW

-  delay(loopTimeMs);                 // remain off this long
-}
+  delay(g_loopTimeMs);                 // remain off this long
+}


array of thresh

array of thresh

--- guitar-arduino.ino
+++ guitar-arduino.ino
@@ -26,8 +26,9 @@
 #define TUNING -12

-#define LASER_ANALOG_TH 975 //for analog read of bpw34. 900-1023 means laser is blocked, 0-600 means laser hit diode
-#define LASER_ANALOG_THOLD_US 5000 //[us] fastest accepted laser state change to prevent noise, fast strum may not be accepted
+const int LASER_ANALOG_TH[] = {960, 920, 975, 711, 900, 975}; //for analog read of bpw34. 900-1023 means laser is blocked, 0-600 means laser hit diode
+#define LASER_ANALOG_EMPH 975 //for analog read of bpw34. 900-1023 means laser is blocked, 0-600 means laser hit diode
+#define LASER_ANALOG_THOLD_US 500 //[us] fastest accepted laser state change to prevent noise, fast strum may not be accepted
 //off topic: measured fastest cadence of strumming is 120ms(120000us)
 #define LASER_THOLD 1000 //[us]
 #define STOP_THOLD 500000 //[us]
@@ -326,9 +327,10 @@

 inline void laser_common_analog(int l_idx, boolean laser_blocked) {
   unsigned long us = micros();
-  if (laser_blocked != laser_status[l_idx]) { //ISR invoked but status did not change from current, do not know why ISR is called -> ignore
+//  if (laser_blocked != laser_status[l_idx]) { //ISR invoked but status did not change from current, do not know why ISR is called -> ignore

     if (us > (laser_status_last_update_us[l_idx] + LASER_ANALOG_THOLD_US)) {
+      laser_status_last_update_us[l_idx] = us;

       laser_status[l_idx] = laser_blocked;

@@ -337,11 +339,10 @@
         send_stop_tone_event(true, true);
       }

-      laser_status_last_update_us[l_idx] = us;
       send_laser_event((boolean)laser_blocked, l_idx);
     } //else ignore, change was due to jitter, likely

-  }
+//  }
 }

 void laseremphasis_ISR()   {
@@ -429,6 +430,26 @@
 //-------------------------
 void loop()
 {
+
+/* Debugging laser transistor levels
+      int a = analogRead(laser_pins[0]);
+      send_midi_debug(0, (int)((float)a / 8));
+      a = analogRead(laser_pins[1]);
+      send_midi_debug(1, (int)((float)a / 8));
+      a = analogRead(laser_pins[2]);
+      send_midi_debug(2, (int)((float)a / 8));
+      delay(200);
+      a = analogRead(laser_pins[3]);
+      send_midi_debug(3, (int)((float)a / 8));
+      a = analogRead(laser_pins[4]);
+      send_midi_debug(4, (int)((float)a / 8));
+      a = analogRead(laser_pins[5]);
+      send_midi_debug(5, (int)((float)a / 8));
+      delay(200);
+      return;
+*/
+
+
   bool narazil_na_prst = false;
   //scan fret by fret
   for (int f = 0; f <= (NO_FRETS-1); f++) { //f<=12
@@ -455,7 +476,7 @@

   //read analog emphasis
   boolean blocked = false;
-  if (analogRead(emphasis_pin) > LASER_ANALOG_TH)
+  if (analogRead(emphasis_pin) > LASER_ANALOG_EMPH)
     blocked = true;
   if (last_alaser_status[6] != blocked) { //status changed
     last_alaser_status[6] = blocked;
@@ -465,10 +486,17 @@
   //read lasers
   for (int i = 0; i < 6; i++) {
     boolean blocked = false;
-    if (analogRead(laser_pins[i]) > LASER_ANALOG_TH)
+
+    int a = analogRead(laser_pins[i]);
+//    if (i==3){
+//    send_midi_debug(i, (int)((float)a / 8));
+//    delay(100);
+//    }
+    if (a > LASER_ANALOG_TH[i])
       blocked = true;

     if (last_alaser_status[i] != blocked) { //status changed
+//      send_midi_debug(i, (int)((float)a / 8));
       last_alaser_status[i] = blocked;
       laser_common_analog(i, blocked);
     }


Got the Activity class inheritance working and the menus work

--- cyberbracer/cyberbracer/cyberbracer.ino
+++ cyberbracer/cyberbracer/cyberbracer.ino
@@ -86,55 +86,56 @@
 // TO DO make virtual?
 class Activity {
   protected:
-    double currTime;          // Current time in millis, updated every call to update()
-    double lastUpdateTime;    // Last time the update ran
-    double interval;          // How many millis between updates
+    unsigned long currTime = 0;      // Current time in millis, updated every call to update()
+    unsigned long lastUpdateTime = 0; // Last time the update ran
+    unsigned long interval = 0;      // How many millis between updates
+    char* name;                      // Name of the activity
   public:
-    void begin() {
-      lastUpdateTime = millis();
-    }
-
-    void update() {
+    Activity(char* name, unsigned long interval) {
+      this->name = name;
+      this->interval = interval;
+    }
+
+    virtual void update() {
+    }
+
+    char* getName() {
+      return name;
     }

     boolean isTimeToUpdate() {
       currTime = millis();
-      if (currTime - lastUpdateTime > interval) {
+      sprintf(messageBuffer, "Update? %lu %lu %lu", currTime, lastUpdateTime, interval);
+      Serial.println(messageBuffer);
+      if ((lastUpdateTime == 0) || (currTime - lastUpdateTime > interval) ) {
+        lastUpdateTime = currTime;
         return true;
       } else {
         return false;
       }
     }

-    char* getName() {
-      return "Activity";
-    }
 };

 class NullActivity : public Activity {
   private:
   public:
-    void begin() {
-      debug("NulllActivity begins");
-    }
-
+  NullActivity() : Activity("NullActivity", 1000) {
+    }
+
     void update() {
+      Activity::update();
       debug("NulllActivity updates");
     }
-
-    char* getName() {
-      return "NullActivity";
-    }};
+};

 class BlinkActivity : public Activity {
   private:
     boolean isLightOn = false;
-    int interval = 2000;
   public:
-    void begin() {
-      debug("LightActivity begins");
-    }
-
+    BlinkActivity() : Activity("BlinkActivity", 2000) {
+    }
+
     void update() {
       debug("LightActivity updating?");
       if (isTimeToUpdate()) {
@@ -150,10 +151,7 @@
         lastUpdateTime = millis();
       }
     }
-
-    char* getName() {
-      return "BlinkActivity";
-    }};
+};

 // The singletons for each activity
 NullActivity nullActivity;
@@ -244,20 +242,18 @@
   if (strcmp(p_menu_component->get_name(), "Light") == 0) {
     Serial.println("Setting to Light");
     currentActivity = &blinkActivity;
-    currentActivity->begin();
   } else if (strcmp(p_menu_component->get_name(), "Sound") == 0) {
     Serial.println("Setting to Null");
     currentActivity = &nullActivity;
-    currentActivity->begin();
   } else {
     Serial.println("UNKNOWN ACTIVITY");
   }

-  sprintf(messageBuffer,"nullActivity is %p  blinkActivity '%s' is %p current is %p",
-  &nullActivity,
-  blinkActivity.getName(),
-  &blinkActivity,
-  currentActivity);
+  sprintf(messageBuffer, "nullActivity is %p  blinkActivity '%s' is %p current is %p",
+          &nullActivity,
+          blinkActivity.getName(),
+          &blinkActivity,
+          currentActivity);
   Serial.println(messageBuffer);

   Serial.print(" Blink activity is ");
@@ -304,7 +300,6 @@
   mmSetupMenu.add_item(&setupDebugOff);

   currentActivity = &blinkActivity;
-

   Serial.println("Starting");
   //Serial.print("Debug is ");
@@ -374,6 +369,7 @@
     }
   */

+  currentActivity->getName();
   currentActivity->update();

   /*


Cleaning up the VWI receiver example.

Cleaning up the VWI receiver example.

--- examples/VWI/CosaVWIreceiver/CosaVWIreceiver.ino
+++ examples/VWI/CosaVWIreceiver/CosaVWIreceiver.ino
@@ -69,36 +69,32 @@
   static uint32_t err = 0;
   static uint32_t cnt = 0;

-  char buf[VWI::MESSAGE_MAX];
-  int8_t buflen = VWI::MESSAGE_MAX;
+  // Wait for a message
+  rx.await();
+  msg_t msg;
+  int8_t len = rx.recv(&msg, sizeof(msg));
+  cnt += 1;

-  // Receive message and print contents
-  rx.await();
-  buflen = rx.recv(buf, buflen);
-  if (buflen > 0) {
-    cnt += 1;
+  // Check that the correct messaage size was received
+  if (len != sizeof(msg)) {
+    err += 1;
+    return;
+  }

-    // Check that the correct messaage size was received
-    if (buflen != sizeof(msg_t)) {
-      trace.print(buf, buflen, 16);
-      err += 1;
-    }
-    else {
-      // Check message number
-      msg_t* msg = (msg_t*) buf;
-      if (msg->nr != next) {
-	next = msg->nr;
-	err += 1;
-      }
-      // Print message contents
-      trace << hex << msg->id << ':' << msg->nr << ':';
-      trace << hex << msg->data << endl;
-      next += 1;
-    }
-    // Print message count and errors every 256 messages
-    if (next == 0) {
-      trace << PSTR("count = ") << cnt << endl;
-      trace << PSTR("errors = ") << err << endl;
-    }
+  // Check message number
+  if (msg.nr != next) {
+    next = msg.nr;
+    err += 1;
+  }
+
+  // Print message contents
+  trace << hex << msg.id << ':' << msg.nr << ':';
+  trace << hex << msg.data << endl;
+  next += 1;
+
+  // Print message count and errors every 256 messages
+  if (next == 0) {
+    trace << PSTR("count = ") << cnt << endl;
+    trace << PSTR("errors = ") << err << endl;
   }
 }


Reworks how I do scanning to have fewer missed triggers.

--- firmware/firmware.ino
+++ firmware/firmware.ino
@@ -5,13 +5,18 @@
  * The software responds to the following serial commands:
  *
  * - r:  read all 4 channels, return results immediately via serial
- * - sN.: performs N scans of all 4 channels. Results are stored until p is
- *       issued. Note the full stop, this is required!
- * - p: prints the buffer, used to retrive values from sN
+ * - s:  on receiving this command, the arduino will immediately begin to
+ *       capture data into its buffer when triggered, stopping when the
+ *       buffer is filled.
+ *
+ * - p:  prints the current valid contents of the buffer. One line is emitted
+ *       for each scan of 4 channels, each line containing 4 codes separated
+ *       by space. The last line of buffer content is followed by a line
+ *       containing 'END'. All lines are terminated by '\n'.
  */

 #ifndef __builtin_avr_delay_cycles
-void __builtin_avr_delay_cycles(unsigned long __n) {
+inline void __builtin_avr_delay_cycles(unsigned long __n) {
   while(__n) __n--;
 }
 #endif
@@ -85,15 +90,12 @@

   Returned value is 2s complemented 16 bit integer.
   */
-int16_t read_analog(uint8_t next_chan) {
+inline int16_t read_analog(uint8_t next_chan) {

   // select the channel for the next read
   digitalWrite(_A0, next_chan&0x1?HIGH:LOW);
   digitalWrite(_A1, next_chan&0x2?HIGH:LOW);

-  // we really don't need any interrupts messing the timings in here up
-  noInterrupts();
-
   // begin a conversion
   digitalWrite(_RC, LOW);

@@ -104,10 +106,8 @@

   digitalWrite(_RC, HIGH);

-  interrupts();
-
-  // wait for busy to go high
-  wait_busy();
+  // t4, BUSY LOE, is at most 21 us
+  delayMicroseconds(22);

   // select the high byte for reading
   digitalWrite(_BYTE, LOW);
@@ -119,24 +119,32 @@
   // use port manipulation to read the data pins. Note that our pinmapping
   // is such that port C maps exactly onto the parallel output from the
   // ADS7825.
-  uint8_t hbyte = PINC;
+  uint16_t code = PINC;
+  code <<=8;

   // now for the low byte
   digitalWrite(_BYTE, HIGH);
   __builtin_avr_delay_cycles(2);
-  uint8_t lbyte = PINC;
+  code |= PINC;

-  return (hbyte<<8 | lbyte);
-}
-
-volatile uint8_t trigcnt = 0;
-void trig_ISR() {
-  trigcnt += 1;
+  return code;
 }

 // buffer for 16bit values from the ADC
-int16_t buf[_BUF_SIZE];
-uint16_t writepos = 0;
+volatile int16_t buf[_BUF_SIZE];
+volatile uint16_t writepos = 0;
+volatile uint8_t trigcnt = 0;
+void trig_ISR() {
+  if (++trigcnt == _DIVIDER) {
+    trigcnt = 0;
+    if (writepos < _BUF_SIZE) {
+      buf[writepos++] = read_analog(1);
+      buf[writepos++] = read_analog(2);
+      buf[writepos++] = read_analog(3);
+      buf[writepos++] = read_analog(0);
+    }
+  }
+}

 void loop() {
   int c = Serial.read();
@@ -148,18 +156,12 @@
     Serial.print(read_analog(3));Serial.print(" ");
     Serial.print(read_analog(0));Serial.println();
   } else if (c == 's') {
-    // XXX we don't use parseInt beause it takes a second to complete waiting
-    // for more user input
-    uint16_t nscans = 0;
-    while (c != '.') {
-      c = Serial.read();
-      if (c >= '0') {
-        c -= '0';
-        nscans *= 10;
-        nscans += c;
-      }
-    }
-    scan_channels(nscans);
+    noInterrupts();
+    // prime the first channel
+    read_analog(0);
+    trigcnt = 0;
+    writepos = 0;
+    interrupts();
   } else if (c == 'p') {
     for (int idx = 0; idx < writepos; idx += 4) {
       Serial.print(idx/4);Serial.print(" ");
@@ -168,38 +170,6 @@
       Serial.print(buf[idx+2]);Serial.print(" ");
       Serial.print(buf[idx+3]);Serial.println();
     }
+    Serial.println("END");
   } else if (c != -1) Serial.println("???");
 }
-
-/**
-  Performs nscan number of scans of the 4 ADC channels, storing the results
-  into buf.
-
-  Note that if there is insufficient storage space (_BUF_SIZE), scan will be
-  prematurely terminated.
-  */
-void scan_channels(uint16_t nscans) {
-  // prime the ADS7825 to scan channel 0
-  read_analog(0);
-
-  // reset back to start of buffer
-  writepos = 0;
-
-  // reset trigcnt so we don't trigger prematurely
-  trigcnt = 0;
-
-  while (nscans) {
-    if (trigcnt>=_DIVIDER) {
-      trigcnt -= _DIVIDER;
-      if (writepos < _BUF_SIZE) {
-        buf[writepos+0] = read_analog(1);
-        buf[writepos+1] = read_analog(2);
-        buf[writepos+2] = read_analog(3);
-        buf[writepos+3] = read_analog(0);
-
-        writepos += 4;
-        nscans -= 1;
-      } else return;
-    }
-  }
-}


define teensy IR sensor and motor ports, convert to tabs only style

--- firmware/firmware.ino
+++ firmware/firmware.ino
@@ -5,13 +5,14 @@
 #include "Hdlc.h"
 #include "mcdriver.h"

-#define IR_LEFT             A1
-#define IR_RIGHT            A0
-#define IR_FRONT_LEFT       A2
-#define IR_FRONT_RIGHT      A3
+#define IR_LEFT             A9
+#define IR_RIGHT            A8
+#define IR_FRONT_LEFT       A7
+#define IR_FRONT_RIGHT      A6
+#define IR_FRONT            A5

-#define STEERING_PWM_PIN    9
-#define DRIVE_PWM_PIN       11
+#define STEERING_PWM_PIN    4
+#define DRIVE_PWM_PIN       3

 bc_telemetry_packet_t telemetry;

@@ -19,6 +20,7 @@
 IRSharp sharp_right(IR_RIGHT);
 IRSharp sharp_front_left(IR_FRONT_LEFT);
 IRSharp sharp_front_right(IR_FRONT_RIGHT);
+IRSharp sharp_front(IR_FRONT);

 uint8_t m_rx_buffer[64];
 uint8_t m_rx_len = 0;
@@ -36,73 +38,64 @@
 MCDriver driver;

 void send_telemetry() {
-  m_tx_len = hdlc.encode((uint8_t*)&telemetry, sizeof(bc_telemetry_packet_t), m_tx_buffer);
-  Serial.write(m_tx_buffer, m_tx_len);
+	m_tx_len = hdlc.encode((uint8_t*)&telemetry, sizeof(bc_telemetry_packet_t), m_tx_buffer);
+	Serial.write(m_tx_buffer, m_tx_len);
 }

 void setup() {
-  Serial.begin(57600);
+	Serial.begin(57600);

-  steeringservo.attach(STEERING_PWM_PIN);
-  drivingservo.attach(DRIVE_PWM_PIN);
+	steeringservo.attach(STEERING_PWM_PIN);
+	drivingservo.attach(DRIVE_PWM_PIN);

-  analogReference(DEFAULT);
+	analogReference(DEFAULT);

-  telemetry.header = BC_TELEMETRY;
+	telemetry.header = BC_TELEMETRY;
 }

 void loop() {
-  while (Serial.available() > 0)
-  {
-    m_rx_len = hdlc.decode(Serial.read());
+	while (Serial.available() > 0) {
+		m_rx_len = hdlc.decode(Serial.read());

-    // check if HDLC packet is received
-    if (m_rx_len > 0)
-    {
-      uint8_t header = ((uint8_t*)m_rx_buffer)[0];
+		// check if HDLC packet is received
+		if (m_rx_len > 0) {
+			uint8_t header = ((uint8_t*)m_rx_buffer)[0];

-      if (CB_MOTOR_COMMAND == header)
-      {
-        cb_motor_command_packet_t* motor = (cb_motor_command_packet_t*)m_rx_buffer;
-        automatic = motor->automatic != 0;
-        if (!automatic)
-        {
-          steeringservo.write(motor->steering_pwm);
-          drivingservo.write(motor->drive_pwm);
-        }
-      }
-    }
-  }
+			if (CB_MOTOR_COMMAND == header) {
+				cb_motor_command_packet_t* motor = (cb_motor_command_packet_t*)m_rx_buffer;
+				automatic = motor->automatic != 0;
+				if (!automatic) {
+					steeringservo.write(motor->steering_pwm);
+					drivingservo.write(motor->drive_pwm);
+				}
+			}
+		}
+	}

-  telemetry.time = millis();
-  telemetry.ir_left = sharp_left.distance();
-  telemetry.ir_right = sharp_right.distance();
-  telemetry.ir_front_left = sharp_front_left.distance();
-  telemetry.ir_front_right = sharp_front_right.distance();
+	telemetry.time = millis();
+	telemetry.ir_left = sharp_left.distance();
+	telemetry.ir_right = sharp_right.distance();
+	telemetry.ir_front_left = sharp_front_left.distance();
+	telemetry.ir_front_right = sharp_front_right.distance();
+	telemetry.ir_front = sharp_front.distance();

-  drive_cmd_t& driveCmd = driver.drive(telemetry);
-  if (automatic)
-  {
-    if (driveCmd.changeSteering)
-    {
-      steeringservo.write(driveCmd.steeringPwm);
-    }
-    if (driveCmd.changeDriving)
-    {
-      drivingservo.write(driveCmd.drivingPwm);
-    }
-  }
+	drive_cmd_t& driveCmd = driver.drive(telemetry);
+	if (automatic) {
+		if (driveCmd.changeSteering) {
+			steeringservo.write(driveCmd.steeringPwm);
+		}
+		if (driveCmd.changeDriving) {
+			drivingservo.write(driveCmd.drivingPwm);
+		}
+	}

-  if (telemetry.time > last_time + 20)
-  {
-    send_telemetry();
-    last_time = telemetry.time;
-  }
+	if (telemetry.time > last_time + 20) {
+		send_telemetry();
+		last_time = telemetry.time;
+	}

-  //delay(10);
-
-  //Serial.print("left: ");
-  //Serial.println(m_distance_left);
+	//Serial.print("left: ");
+	//Serial.println(m_distance_left);
 }


Here's the other path fix...

Here's the other path fix...

Wooooo!

Thanks Paul!

--- firmware/examples/MPU6050_raw/MPU6050_raw.ino
+++ firmware/examples/MPU6050_raw/MPU6050_raw.ino
@@ -33,8 +33,8 @@

 // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
 // for both classes must be in the include path of your project
-#include "I2Cdev.h"
-#include "MPU6050.h"
+#include "MPU6050/I2Cdev.h"
+#include "MPU6050/MPU6050.h"

 // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
 // is used in I2Cdev.h


Changed to using interrupts to try to stop false resets.

--- FumeHoodWatchDog/FumeHoodWatchDog.ino
+++ FumeHoodWatchDog/FumeHoodWatchDog.ino
@@ -1,32 +1,36 @@
 // This is a watchdog program to be run on an Adafruit Trinket

-#define watchDogPin 1
-#define resetPin 2
+#define watchDogPin 2
+#define resetPin 3
+#define hbPin 1

 unsigned long watchDogInterval = 30000; // Needs to see a pulse at lease every 30 seconds
 unsigned long resetDuration = 5000;
 unsigned long fumeHoodMonitorBootTime = 15000;
-unsigned long watchDogTimer;
-
-bool watchDogIsBeingPet = false;
-bool watchDogHasBeenPet = false;
+volatile unsigned long watchDogTimer;
+volatile bool hbState = false;
+// bool watchDogIsBeingPet = false;
+// bool watchDogHasBeenPet = false;

 void setup() {
   pinMode(watchDogPin, INPUT);
+  attachInterrupt(0, petWatchDog, RISING);
   pinMode(resetPin, OUTPUT);
+  pinMode(hbPin, OUTPUT);
   digitalWrite(resetPin, HIGH);
+  digitalWrite(hbPin, hbState);
   delay(fumeHoodMonitorBootTime);
   watchDogTimer = millis();
 }

 void loop(){
-  watchDogIsBeingPet = digitalRead(watchDogPin) == 1;
-  if (watchDogIsBeingPet) {
-    watchDogHasBeenPet = true;
-  } else if (!watchDogIsBeingPet && watchDogHasBeenPet) {
-    watchDogTimer = millis();
-    watchDogHasBeenPet = false;
-  }
+  // watchDogIsBeingPet = digitalRead(watchDogPin) == 1;
+  // if (watchDogIsBeingPet) {
+  //   watchDogHasBeenPet = true;
+  // } else if (!watchDogIsBeingPet && watchDogHasBeenPet) {
+  //   watchDogTimer = millis();
+  //   watchDogHasBeenPet = false;
+  // }
   unsigned long now = millis();
   if(now - watchDogTimer >= watchDogInterval){
     digitalWrite(resetPin, LOW);
@@ -35,4 +39,10 @@
     delay(fumeHoodMonitorBootTime);
     watchDogTimer = millis();
   }
+  digitalWrite(hbPin, hbState);
 }
+
+void petWatchDog(){
+  watchDogTimer = millis();
+  hbState = !hbState;
+}


test commit 2

test commit 2

--- KeepUntil.ino
+++ KeepUntil.ino
@@ -8,7 +8,7 @@
 #define SET_RTC false
 #define SHOW_TIME false

-//test change test
+//test change test 2

 const byte LOCK_SERVO_PIN = 4;
 const byte LOCK_OPEN = 130;


First full test

First full test

--- Computer_Switch/Computer_Switch.ino
+++ Computer_Switch/Computer_Switch.ino
@@ -18,49 +18,105 @@
   #include "user_interface.h"
 }

-// Create aREST instance
-aREST rest = aREST();
+//------------------------------------------------------------
+//------------------------------------------------------------
+#define RELAY_PIN D1
+#define POWER_BUTTON D4
+#define POWER_LED D2
+
+// The port to listen for incoming TCP connections
+#define LISTEN_PORT 80
+
+// How often to check for power off state
+unsigned long lastPowerCheck = millis();
+unsigned long whenPowerOn = millis();
+unsigned long whenRelayOn = millis();
+#define POWER_CHECK_FREQUENCY 10000

 // WiFi parameters
 const char* ssid = "joshua";
 const char* password = "";
+//------------------------------------------------------------
+//------------------------------------------------------------

-// The port to listen for incoming TCP connections
-#define LISTEN_PORT           80
-
+// Create aREST instance
+aREST rest = aREST();
 // Create an instance of the server
 WiFiServer server(LISTEN_PORT);

 // Variables to be exposed to the API
-int relayOn;
+int           relayOn =               0;
+unsigned long relayOnSince =          0;
+int           computerOn =            0;
+unsigned long computerOnSince =       0;
+int           relayOffWhenPowerDown = 0;

-// Declare functions to be exposed to the API
-int powerOn(String command);
-int flashLed(String command);
-int hardReset(String command);
+// Functions to be exposed to the API
+int flashLed(String command);          // Flash the onboard LED as a test
+int powerOn(String command);           // Press the power button
+int hardPowerOff(String command);      // Hold the power button
+int powerOnGracefully(String command); // Turn on relay, then press power.

 void setup(void)
 {
-  // Start Serial
   Serial.begin(115200);
-  WiFi.mode(WIFI_STA);
-  WiFi.hostname("ESP_EIDOLON_IPMI");
-  wifi_station_set_hostname("ESP_EIDOLON_IPMI");
-  delay(100);
+  initWifi();

-  // Init variables and expose them to REST API
-  relayOn = 0;
+  // Expose variables to REST API
   rest.variable("relayOn",&relayOn);
+  rest.variable("relayOnSince",&relayOnSince);
+  rest.variable("computerOn",&computerOn);
+  rest.variable("computerOnSince",&computerOnSince);
+  rest.variable("relayOffWhenPowerDown",&relayOffWhenPowerDown);

   // Function to be exposed
-  rest.function("power",powerOn);
-  rest.function("led",flashLed);
-  rest.function("reset",hardReset);
+  rest.function("flash",flashLed);
+  rest.function("on",powerOn);
+  rest.function("off",hardPowerOff);
+  rest.function("powerUp",powerOnGracefully);

   // Give name & ID to the device (ID should be 6 characters long)
   rest.set_id("1");
   rest.set_name("ESP_EIDOLON_IPMI");

+  pinMode(LED_BUILTIN,  OUTPUT); //Built in LED for testing
+  pinMode(POWER_BUTTON, INPUT);  //Connected to 'hot' wire of on button (switches between in and out)
+  pinMode(POWER_LED,    INPUT);  //Connected to 'hot' wire of power LED (resistor?)
+}
+
+void loop() {
+  // Handle REST calls
+  WiFiClient client = server.available();
+  if (client && client.available()) {
+    rest.handle(client);
+  }
+  // Check for system power off state
+  if (millis() > lastPowerCheck + POWER_CHECK_FREQUENCY) {
+    if (relayOn && relayOffWhenPowerDown && !computerOn) {
+      //It looks like we're shutdown, but lets make sure.
+      delay(500);
+      if (digitalRead(POWER_LED) == 0) {
+        //OK then, power off Relay.
+        delay(2000);
+		digitalWrite(RELAY_PIN, LOW);
+		relayOn = 0;
+		relayOffWhenPowerDown = 0;
+      }
+    }
+    lastPowerCheck = millis();
+  }
+  // Check status to update variables
+  computerOn = digitalRead(POWER_LED);
+  delay(10);
+}
+
+void initWifi() {
+  //Wifi settings
+  WiFi.mode(WIFI_STA);
+  WiFi.hostname("ESP_EIDOLON_IPMI");
+  wifi_station_set_hostname("ESP_EIDOLON_IPMI");
+  delay(100);
+
   // Connect to WiFi
   WiFi.begin(ssid, password);
   while (WiFi.status() != WL_CONNECTED) {
@@ -76,21 +132,6 @@

   // Print the IP address
   Serial.println(WiFi.localIP());
-
-  pinMode(LED_BUILTIN, OUTPUT);
-  pinMode(D4, INPUT);
-}
-
-void loop() {
-  // Handle REST calls
-  WiFiClient client = server.available();
-  if (!client) {
-    return;
-  }
-  while(!client.available()){
-    delay(1);
-  }
-  rest.handle(client);
 }

 // Custom function accessible by the API
@@ -106,22 +147,43 @@
   return 1;
 }

-// Custom function accessible by the API
+// Powers on the computer by pulling the power button low.
 int powerOn(String command) {
-  pinMode(D4, OUTPUT);
-  digitalWrite(D4,LOW);
-  delay(1500);
-  digitalWrite(D4,HIGH);
-  pinMode(D4, INPUT);
+  pinMode(POWER_BUTTON, OUTPUT);
+  digitalWrite(POWER_BUTTON, LOW);
+  delay(1000);
+  digitalWrite(POWER_BUTTON, HIGH);
+  pinMode(POWER_BUTTON, INPUT);
   return 1;
 }

-// Custom function accessible by the API
-int hardReset(String command) {
-  pinMode(D4, OUTPUT);
-  digitalWrite(D4,LOW);
+// Hard power off computer by holding power button 6 seconds.
+int hardPowerOff(String command) {
+  pinMode(POWER_BUTTON, OUTPUT);
+  digitalWrite(POWER_BUTTON, LOW);
   delay(6000);
-  digitalWrite(D4,HIGH);
-  pinMode(D4, INPUT);
+  digitalWrite(POWER_BUTTON,HIGH);
+  pinMode(POWER_BUTTON, INPUT);
   return 1;
 }
+
+// Turn on relay, then press power.
+// Parameter 0 = just do that.
+// Parameter 1 = also wait until computer shuts down, then automatically flip relay off.
+int powerOnGracefully(String command) {
+  //Relay on
+  digitalWrite(RELAY_PIN, HIGH);
+  relayOn = 1;
+  delay(5000);
+  //Then power computer on as normal
+  powerOn("");
+  computerOn = 1;
+  //Setup auto off if requested
+  int autoOff = command.toInt();
+  if (autoOff == 1) {
+    relayOffWhenPowerDown = 1;
+  } else {
+    relayOffWhenPowerDown = 0;
+  }
+  return 1;
+}


Complete 4x4 keypad library for mega2560 \o/

--- keypad.ino
+++ keypad.ino
@@ -20,6 +20,8 @@
     {'*', '0', '#', 'D'}
 };

+uint16_t buttons_held = 0;
+
 static inline char dequeue_key(void) {
     if (head == tail)
         return '\0';
@@ -37,6 +39,8 @@
     presses[tail] = key;
 }

+#define has_press(row) (!digitalRead(KEYPAD_ROW_PIN_BASE + row))
+#define was_pressed(bitmask) (buttons_held & bitmask)
 void handle_interrupt(void) {
     noInterrupts();
     if (action_function == NULL) {
@@ -49,10 +53,12 @@

     for (uint8_t i = 0; i != KEYPAD_NUM_ROWS_COLS ; i++) {
         digitalWrite(KEYPAD_COL_PIN_BASE + i, LOW);
-        for (uint8_t j = 0; j != KEYPAD_NUM_ROWS_COLS ; j++)
-            if (!digitalRead(KEYPAD_ROW_PIN_BASE + j))
-                // TODO Handle multibutton presses
+        for (uint8_t j = 0; j != KEYPAD_NUM_ROWS_COLS ; j++) {
+            uint16_t bitmask = (1 << (i * 4 + j));
+            if (has_press(j) && !was_pressed(bitmask))
                 queue_key(buttons[i][j]);
+            buttons_held ^= bitmask;
+        }
         digitalWrite(KEYPAD_COL_PIN_BASE + i, HIGH);
     }

@@ -61,7 +67,7 @@
     interrupts();

     char keypress;
-    while (head != tail && (keypress = dequeue_key()) != '\0')
+    while ((keypress = dequeue_key()) != '\0')
         action_function(keypress);
 }

@@ -69,10 +75,8 @@
     for (uint8_t i = 0; i != KEYPAD_NUM_ROWS_COLS ; i++) {
         pinMode(KEYPAD_COL_PIN_BASE + i, OUTPUT);
         digitalWrite(KEYPAD_COL_PIN_BASE + i, LOW);
-        // TODO unsure if INPUT_PULLUP is digital high with high impedance, needs testing.
         pinMode(KEYPAD_ROW_PIN_BASE + i, INPUT_PULLUP);
-        // TODO set to CHANGED and handle multiple buttons!
-        attachInterrupt(INTERRUPT_BASE + i, handle_interrupt, FALLING);
+        attachInterrupt(INTERRUPT_BASE + i, handle_interrupt, CHANGE);
     }
 }


Reset RPM min and max.  clean up commented code.

--- XV_Lidar_Controller.ino
+++ XV_Lidar_Controller.ino
@@ -8,12 +8,7 @@
  Modified to add CRC checking - Doug Hilton, WD0UG November, 2015 mailto: six.speed (at) yahoo (dot) com
  Modified to add ShowErrors / HideErrors - DSH
  Modified to add ShowAngles - DSH
- Modified SerialCommand.h to increase # of characters allowed to be input and command length - DSH
-           #define SERIALCOMMAND_BUFFER 100		// ORIGINAL: 32   MODIFIED BY DSH
-           #define SERIALCOMMAND_MAXCOMMANDLENGTH 20	// ORIGINAL: 8
- ****************************************************************************************
- NOTE: DON'T FORGET TO COPY THE NEW SerialCommand.h TO YOUR ARDUINO LIBRARY DIRECTORY!!!
- ****************************************************************************************
+
  See README for additional information

  The F() macro in the Serial statements tells the compiler to keep your strings in PROGMEM
@@ -157,8 +152,7 @@
   for (ixPacket = 0; ixPacket < PACKET_LENGTH; ixPacket++)  // Initialize
     Packet[ixPacket] = 0;
   ixPacket = 0;
-  setLowRPM(xv_config.rpm_min);                      // Make the motor go as slow as possible
-  //hideRaw();     // DSH ONLY!!!!!!!!!!!!
+
 }
 // Main loop (forever)
 void loop() {
@@ -197,16 +191,15 @@
             if (bShowAnglesFromArray) {                      // we're going to display only angles that are in 'aryAngles'
               for (int ix = 0; ix < N_DATA_QUADS; ix++) {
                 if (aryAngles[startingAngle + ix]) {         // if we're supposed to display that angle
-                  if (aryInvalidDataFlag[ix] == 0) {         // make sure that the 'Invalid Data' flag is clear
+                  if (aryInvalidDataFlag[ix] == 0) {         // make sure that the 'Invalid Data' flag is clear
                     Serial.print(startingAngle + ix);
-                    Serial.print(F(","));
-                    Serial.println(int(aryDist[ix]));
-                    //Serial.print(F(" ("));
-                    //Serial.print(aryQuality[ix]);
-                    //Serial.println(F(")"));
+                    Serial.print(F(": "));
+                    Serial.print(int(aryDist[ix]));
+                    Serial.print(F(" ("));
+                    Serial.print(aryQuality[ix]);
+                    Serial.println(F(")"));
                   }
                   else if (bShowErrors) {
-                    /*
                     Serial.print(startingAngle + ix);
                     Serial.print(F(": "));
                     for (int jx = 0; jx < PACKET_LENGTH; jx++) {
@@ -215,7 +208,6 @@
                       Serial.print(Packet[jx], HEX);
                       Serial.print(F(" "));
                     }
-                    */
                     if (aryInvalidDataFlag[ix] & INVALID_DATA_FLAG)
                       Serial.print(F("{I}"));
                     if (aryInvalidDataFlag[ix] & STRENGTH_WARNING_FLAG)
@@ -231,16 +223,15 @@
               || ((xv_config.show_angle >= startingAngle) && (xv_config.show_angle < startingAngle + N_DATA_QUADS))) {
                 for (int ix = 0; ix < N_DATA_QUADS; ix++) {  // process each of the (4) angles
                   if ((xv_config.show_angle == SHOW_ALL_ANGLES) || (xv_config.show_angle == startingAngle + ix)) {
-                    if (aryInvalidDataFlag[ix] == 0) {       // make sure that the 'Invalid Data' flag is clear
+                    if (aryInvalidDataFlag[ix] == 0) {       // make sure that the 'Invalid Data' flag is clear
                       Serial.print(startingAngle + ix);
-                      Serial.print(F(","));
-                      Serial.println(int(aryDist[ix]));
-                      //Serial.print(F(" ("));
-                      //Serial.print(aryQuality[ix]);
-                      //Serial.println(F(")"));
+                      Serial.print(F(": "));
+                      Serial.print(int(aryDist[ix]));
+                      Serial.print(F(" ("));
+                      Serial.print(aryQuality[ix]);
+                      Serial.println(F(")"));
                     }
                     else if (bShowErrors) {
-                      /*
                       Serial.print(startingAngle + ix);
                       Serial.print(F(": "));
                       for (int jx = 0; jx < PACKET_LENGTH; jx++) {
@@ -249,7 +240,6 @@
                         Serial.print(Packet[jx], HEX);
                         Serial.print(F(" "));
                       }
-                      */
                       if (aryInvalidDataFlag[ix] & INVALID_DATA_FLAG)
                         Serial.print(F("{I}"));
                       if (aryInvalidDataFlag[ix] & STRENGTH_WARNING_FLAG)
@@ -263,8 +253,7 @@
             }  // if (bShowAngles)
           }  // if (xv_config.show_dist)
         }  // if (eValidatePacket() == 0
-        else if (bShowErrors) {
-          /*
+        else if (bShowErrors) {
           for (int ix = 0; ix < PACKET_LENGTH; ix++) {
             if (Packet[ix] < 0x10)
               Serial.print(F("0"));
@@ -272,8 +261,6 @@
             Serial.print(F(" "));
           }
           Serial.println(F(" Bad CRC"));
-          */
-          Serial.println(F("C"));
         }
         // initialize a bunch of stuff before we switch back to State 1
         for (int ix = 0; ix < N_DATA_QUADS; ix++) {
@@ -455,8 +442,8 @@
   xv_config.motor_pwm_pin = 9;  // pin connected N-Channel Mosfet

   xv_config.rpm_setpoint = 300;  // desired RPM
-  xv_config.rpm_min = 180;
-  xv_config.rpm_max = 349;
+  xv_config.rpm_min = 200;
+  xv_config.rpm_max = 300;
   xv_config.pwm_min = 100;
   xv_config.pwm_max = 1023;
   xv_config.sample_time = 20;
@@ -764,9 +751,6 @@
   Serial.println(F(" "));
 }

-void setLowRPM(double sVal) {
-  xv_config.rpm_setpoint = sVal;
-}
 void setRPM() {
   double sVal = 0.0;
   char *arg;
@@ -965,7 +949,7 @@
   Serial.println(F("  ShowConfig    - Show the running configuration"));
   Serial.println(F("  SaveConfig    - Save the running configuration to EEPROM"));
   Serial.println(F("  ResetConfig   - Restore the original configuration"));
-  Serial.println(F("  SetRPM        - Set the desired rotation speed (min: 180, max: 349)"));
+  Serial.println(F("  SetRPM        - Set the desired rotation speed (min: 200, max: 300)"));
   Serial.println(F("  SetKp         - Set the proportional gain"));
   Serial.println(F("  SetKi         - Set the integral gain"));
   Serial.println(F("  SetKd         - Set the derivative gain"));


fixed sVal compile error by initializing as 0.0

--- XV_Lidar_Controller.ino
+++ XV_Lidar_Controller.ino
@@ -233,7 +233,7 @@
 }

 void setRPM() {
-  double sVal;
+  double sVal = 0.0;
   char *arg;
   boolean syntax_error = false;

@@ -263,7 +263,7 @@
 }

 void setKp() {
-  double sVal;
+  double sVal = 0.0;
   char *arg;
   boolean syntax_error = false;

@@ -292,7 +292,7 @@
 }

 void setKi() {
-  double sVal;
+  double sVal = 0.0;
   char *arg;
   boolean syntax_error = false;

@@ -321,7 +321,7 @@
 }

 void setKd() {
-  double sVal;
+  double sVal = 0.0;
   char *arg;
   boolean syntax_error = false;


MQTT433gateway.ino: rename variable hostName to mainTopic

--- MQTT433gateway.ino
+++ MQTT433gateway.ino
@@ -52,7 +52,7 @@
 ESPiLight rf(TRANSMITTER_PIN);
 SHAauth otaAuth(myOTA_PASSWD);

-const String hostName = String("rfESP_")+String(ESP.getChipId(), HEX);;
+const String mainTopic = String("rfESP_")+String(ESP.getChipId(), HEX);;
 const String rfTopic = "rf434";
 boolean logMode = false;
 boolean rawMode = false;
@@ -68,8 +68,8 @@
   rf.setPulseTrainCallBack(rfRawCallback);
   rf.initReceiver(RECEIVER_PIN);
   Serial.println("");
-  Serial.print("Hostname: ");
-  Serial.println(hostName);
+  Serial.print("Name: ");
+  Serial.println(mainTopic);
 }

 void setup_wifi() {
@@ -132,11 +132,11 @@
   if(topic.startsWith(sendTopic)) {
     transmitt(topic.substring(sendTopic.length()), payload);
   }
-  sendTopic = hostName + "/send/";
+  sendTopic = mainTopic + "/send/";
   if(topic.startsWith(sendTopic)) {
     transmitt(topic.substring(sendTopic.length()), payload);
   }
-  if(topic == (hostName + "/set/raw")) {
+  if(topic == (mainTopic + "/set/raw")) {
     Serial.println("Change raw mode.");
     if (payload[0] == '1') {
       rawMode = true;
@@ -145,7 +145,7 @@
       rawMode = false;
     }
   }
-  if(topic == (hostName + "/set/log")) {
+  if(topic == (mainTopic + "/set/log")) {
     Serial.println("Change log mode.");
     if (payload[0] == '1') {
       logMode = true;
@@ -154,11 +154,11 @@
       logMode = false;
     }
   }
-  if(topic == (hostName + "/ota/url")) {
+  if(topic == (mainTopic + "/ota/url")) {
     otaURL = String(payload);
-    mqtt.publish((hostName+ "/ota/nonce").c_str(), otaAuth.nonce().c_str());
-  }
-  if((topic == (hostName + "/ota/passwd")) && (otaURL.length() > 7)) {
+    mqtt.publish((mainTopic+ "/ota/nonce").c_str(), otaAuth.nonce().c_str());
+  }
+  if((topic == (mainTopic + "/ota/passwd")) && (otaURL.length() > 7)) {
     if(otaAuth.verify(payload)) {
       beatLED.on();
       Serial.print("Start OTA update from: ");
@@ -205,7 +205,7 @@
     mqtt.publish(topic.c_str(), message.c_str(), true);
   }
   if(logMode) {
-    String topic = hostName + String("/log/") + String(status) + String('/') + protocol;
+    String topic = mainTopic + String("/log/") + String(status) + String('/') + protocol;
     mqtt.publish(topic.c_str(), message.c_str());
   }
 }
@@ -220,7 +220,7 @@
       Serial.print(data);
       Serial.println();

-      mqtt.publish((hostName + "/recvRaw").c_str(), data.c_str());
+      mqtt.publish((mainTopic + "/recvRaw").c_str(), data.c_str());
     }
   }
 }
@@ -231,12 +231,12 @@
   while (!mqtt.connected()) {
     Serial.print("Attempting MQTT connection...");
     // Attempt to connect
-    if (mqtt.connect(hostName.c_str(), hostName.c_str(), 0, true, "offline")) {
+    if (mqtt.connect(mainTopic.c_str(), mainTopic.c_str(), 0, true, "offline")) {
       Serial.println("connected");
-      mqtt.publish(hostName.c_str(), "online", true);
-      mqtt.subscribe((hostName + "/set/+").c_str());
-      mqtt.subscribe((hostName + "/ota/+").c_str());
-      mqtt.subscribe((hostName + "/send/+").c_str());
+      mqtt.publish(mainTopic.c_str(), "online", true);
+      mqtt.subscribe((mainTopic + "/set/+").c_str());
+      mqtt.subscribe((mainTopic + "/ota/+").c_str());
+      mqtt.subscribe((mainTopic + "/send/+").c_str());
       mqtt.subscribe((rfTopic + "/send/+").c_str());
     } else {
       Serial.print("failed, rc=");


Revert "Use some other registers to free up ram."

This reverts commit 611c59f1ecef0f600e5fafd620059fd245a6d0fb.

--- lampka.ino
+++ lampka.ino
@@ -7,7 +7,7 @@

 // Change this to be at least as long as your pixel string (too long will work fine, just be a little slower)

-#define PIXELS 14  // Number of pixels in the string
+#define PIXELS 12  // Number of pixels in the string

 // These values depend on which pin your string is connected to and what board you are using
 // More info on how to find these at http://www.arduino.cc/en/Reference/PortManipulation
@@ -365,27 +365,17 @@
     PCMSK |= (1<<constantButtonPin); //PCINT[5:0]: Pin Change Enable Mask 5:0
 }

-#define constant_color_index OCR0B
-#define direction OCR0A
-#define set_constant_1 DDRB |= (1<<2)
-#define set_constant_0 DDRB &= ~(1<<2)
-#define constant_eq_1 DDRB & (1<<2)
-#define current_hue EEDR
-
 void setup() {
     interruptSetup();
     ledsetup();
-    direction = 1;
-    constant_color_index = 0;
-    set_constant_0;
 }

 const uint8_t delta = (256/PIXELS); //delta of hue between each pixel, spread out evenly
-//boolean constant=0;
-//int8_t direction = 1;
+boolean constant=0;
+int8_t direction = 1;
 uint8_t led_colors[PIXELS][3];
-//uint8_t constant_color_index=0;
-//uint8_t current_hue=0;
+uint8_t constant_color_index=0;
+uint8_t current_hue=0;

 ISR(PCINT0_vect) {
     cli();
@@ -397,9 +387,7 @@
         direction -= 1;
     }
     if (PINB & 1) { //constant color
-        set_constant_1;
-        //DDRB |= (1<<2); //constant=1
-
+        DDRB |= (1<<2); //constant=1
         constant_color_index++;
         constant_color_index = constant_color_index % 9; //8 is white
     }
@@ -423,7 +411,7 @@
     clear_led_colors();
     uint8_t hue_to_compute = 0;
     for (uint8_t index=0; index < PIXELS; index++) {
-        if (constant_eq_1) {
+        if (DDRB & (1<<2)) {
             if (constant_color_index == 8) { //white
                 led_colors[index][0]=255;
                 led_colors[index][1]=255;


key on starts tempo

key on starts tempo

--- arduino/vk_arp/vk_arp.ino
+++ arduino/vk_arp/vk_arp.ino
@@ -108,13 +108,15 @@
   tempo_pin_value = analogRead(tempo_pin);
   interval = tempo_pin_value;

-  displayNumber(tempo_pin_value);
+  displayNumber(interval);

-  if (timer0 > interval) {
-    timer0 -= interval; //reset the timer
+  if ((!arp_on) || (!pressed_keys) || (timer0 > interval)) {

     if (arp_on) {
+      timer0 -= interval; //reset the timer
       MIDI.sendNoteOff(cur_note, 0, 1);
+    } else {
+      timer0 = 0;
     }

     if (pressed_keys) {


Reminder (front facing LED) added and working

Fully working model / code.  Only issue is when changing the clock
manually, it once in a while displays the calculated time before it
checks the 12 hour constraints.

--- fourtwentyclock/fourtwentyclock.ino
+++ fourtwentyclock/fourtwentyclock.ino
@@ -1,7 +1,8 @@
+
 /* ================================================================================== //
 //
 //    Jack's 4:20 Clock
-//    Last Update: 9-7-2014
+//    Last Update: 9-18-2014
 //    Version 0.95
 //    Written for Arduino Uno Rev. 3
 //    Adafruit Hardware: Real Time Clock: DS1307, Neopixel (40 RGB-LED) Shield,
@@ -18,75 +19,84 @@
 #include "Pitches.h"

 // Smoothing Variables:
-#define DEBOUNCE 10                           // # ms (5+ ms is usually plenty)
-#define NUMBUTTONS sizeof(buttons)            // Macro determines size of array, by checking size
-byte buttons[] = {2, 3, 4, 5};                // Pins of buttons to be doubounced
-byte down[NUMBUTTONS], pressed[NUMBUTTONS], released[NUMBUTTONS];
+#define DEBOUNCE 10                          // # ms (5+ ms is usually plenty)
+#define numBtns sizeof(buttons)              // Macro determines size of array, by checking size
+byte buttons[] = {2, 3, 4, 5, 11};           // Pins of buttons to be doubounced
+
+byte down[numBtns], pressed[numBtns], released[numBtns];

 // Input/Output Pins
-int brightKnob =          A3;      // 7-Sebment
-int minPlusButton =     2;       // Timekeeping
-int minMinusButton =    3;       // Timekeeping
-int hourPlusButton =    4;       // Timekeeping
-int hourMinusButton =   5;       // Timekeeping
-int reminderSwitch =      6;       // Switch: Reminder
-int brightSwitch =        7;
-int piezoOut =            8;       // Speaker
-int neoPixelPin =         10;      // RGB-LED: Green
+int brightKnob =          A3;                // Potentiometer: Brightness
+int minPlusButton =       2;                 // | > For manual time adjustment
+int minMinusButton =      3;                 // | ^
+int hourPlusButton =      4;                 // | ^
+int hourMinusButton =     5;                 // | ^
+int neoPixelSwitch =      6;                 // Switch: Neopixel Matrix
+int brightSwitch =        7;                 // Flip Potentiometer control from displays to matrix
+int piezoSpeaker =        8;                 // Speaker
+int frontLED =            9;                 // Front facing LED (Orange)
+int neoPixelMatrix =      10;                // RGB-LED: Green
+int frontLEDButton =      11;                // Switch for LED

 // Variables
-int reminderState;                 // Switch (Reminder)
-int noteCounter;                   // Counts theme music notes
-boolean running =        false;    // Colon ON/OFF
-int decimalTime;                   // Overall Clock Time
-long previousMillis;
-int neoBrightness;
-
-//Hour Adjustment Variables
-int hourCount;                   // | > For manual time adjustment
-int minuteCount;                 // | ^
-int adjustedHour;                // | ^
-int adjustedMinute;              // | ^
+boolean running =          false;            // Colon ON/OFF
+int pixelSwitchState;                        // Switch state
+int pixelBrightness;                         // Neopixel Matrix Brightness
+int LEDButtonCount;                          // Counter for button presses
+int LEDLastState;                            // Previous state of LED button
+int LEDState;                                // LED Button State
+int noteCounter;                             // Counts theme music notes
+int decimalTime;                             // Calculated Clock Time
+long previousMillis;                         // Delay alternative timer
+
+// Hour Adjustment Variables
+int hourCount;                               // | > For manual time adjustment
+int minuteCount;                             // | ^
+int adjustedHour;                            // | ^
+int adjustedMinute;                          // | ^

 // Setup Components
 RTC_DS1307 RTC;
 Adafruit_7segment disp = Adafruit_7segment();
 Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4();
-Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, neoPixelPin, NEO_GRB + NEO_KHZ800);
+Adafruit_NeoPixel strip = Adafruit_NeoPixel(40, neoPixelMatrix, NEO_GRB + NEO_KHZ800);

 // ================================================================================== //
 //                                  *** SETUP ***
 // ================================================================================== //

+
 void setup()
 {
+  byte btnCount;                               // Debounce (Setup Buttons)
+  for (btnCount = 0; btnCount < numBtns; btnCount++)
+  {
+    pinMode (buttons[btnCount], INPUT);
+    digitalWrite(buttons[btnCount], HIGH);
+  }
+
   pinMode (brightKnob, INPUT);                // Potentiometer
   pinMode (brightSwitch, INPUT);              // Reminder Switch
-  pinMode (reminderSwitch, INPUT);            // Reminder Switch
+  pinMode (neoPixelSwitch, INPUT);            // Reminder Switch
   pinMode (minPlusButton, INPUT);             // Minute +
   pinMode (hourPlusButton, INPUT);            // Hour +
   pinMode (minMinusButton, INPUT);            // Minute -
   pinMode (hourMinusButton, INPUT);           // Hour -
-  pinMode (piezoOut, OUTPUT);                 // Speaker
-  pinMode (neoPixelPin, OUTPUT);              // Neopixel
-
-  // Debounce
-  byte buttonCount;
-  for (buttonCount = 0; buttonCount < NUMBUTTONS; buttonCount++)
-  {
-    pinMode (buttons[buttonCount], INPUT);
-    digitalWrite(buttons[buttonCount], HIGH);
-  }
-
-  Serial.begin(9600);
-  Wire.begin();
-  RTC.begin();                                            // DSC1730 Clock
-  RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));         // Set time at compile
-  disp.begin(0x70);                                       // Start 7 Segment
-  alpha4.begin(0x71);                                     // Start Alphanumeric
-  strip.begin();                                          // Start Neopixel
-  strip.show();                                           // Initialize all pixels to 'off'
+  pinMode (frontLEDButton, INPUT);            // LED Switch
+
+  pinMode (piezoSpeaker, OUTPUT);                 // Speaker
+  pinMode (neoPixelMatrix, OUTPUT);              // Neopixel
+  pinMode (frontLED, OUTPUT);                // Front LED
+
+  Serial.begin(9600);                         // For Serial Debugging
+  Wire.begin();                               // One Wire Library Start
+  RTC.begin();                                // DSC1730 Clock
+  RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));  // Set time at compile
+  disp.begin(0x70);                           // Start 7 Segment
+  alpha4.begin(0x71);                         // Start Alphanumeric
+  strip.begin();                              // Start Neopixel
+  strip.show();                               // Initialize all pixels to 'off'
 }

@@ -94,22 +104,26 @@
 //                                  *** LOOP ***
 // ================================================================================== //

+
 void loop()
 {
-  disp.print(getDecimalTime());          // Show 12-Hour Time (7 Segment)
-  displayDay();                          // Show Weekday: 14 Segment
-  blinkColon();                          // Blink Colon
-  adjustBrightness();                    // Check Switch & Adjust brightness
-  fourTwentyCheck();                     // Check if 4:20pm & Run Alarm
-  reminderSwitchCheck();                      // LED / Reminder
-  debounceSwitches();                    // Debounce (check state of press)
-}
+  disp.print(getDecimalTime());              // Show 12-Hour Time (7 Segment)
+  displayDay();                              // Show Weekday: 14 Segment
+  blinkColon();                              // Blink Colon
+  adjustBrightness();                        // Check Switch & Adjust brightness
+  fourTwentyCheck();                         // Check if 4:20pm & Run Alarm
+  pixelSwitchCheck();                     // LED / Reminder
+  frontLEDCheck();                                // Turns on and off front facing LED
+  debounceSwitches();                        // Debounce (check state of press)
+}
+

 // ================================================================================== //
 //                          *** MAIN CLOCK FUNCTIONS ***
 // ================================================================================== //

-int getDecimalTime()                                    // Calculate and Adjust Hours
+
+int getDecimalTime()  // Calculate and Adjust Hours
 {
   int bounceDelay = 400;

@@ -121,7 +135,7 @@
   int minPlusState = digitalRead(minPlusButton);
   int minMinusState = digitalRead(minMinusButton);

-  if (hourPlusState == HIGH)                                   // Hour+ Button
+  if (hourPlusState == HIGH)                               // Hour+ Button
   {
     adjustedHour = hourCount * 100;
     decimalTime += adjustedHour;
@@ -129,7 +143,7 @@
     delay(bounceDelay);
   }

-  if (hourMinusState == HIGH)                                   // Hour- Button
+  if (hourMinusState == HIGH)                              // Hour- Button
   {
     adjustedHour = hourCount * 100;
     decimalTime += adjustedHour;
@@ -137,14 +151,14 @@
     delay(bounceDelay);
   }

-  if (minPlusState == HIGH)                                      // Minute+ Button
+  if (minPlusState == HIGH)                                 // Minute+ Button
   {
     adjustedMinute = minuteCount + 1;
     minuteCount++;
     delay(bounceDelay);
   }

-  if (minMinusState == HIGH)                                     // Minute- Button
+  if (minMinusState == HIGH)                                 // Minute- Button
   {
     adjustedMinute = minuteCount - 1;
     minuteCount--;
@@ -152,10 +166,10 @@
   }

   decimalTime += adjustedHour + adjustedMinute;
-
+
   if (now.hour() + hourCount * 100 > 1100) hourCount = 0;
   if (now.minute() + minuteCount > 58) minuteCount = 0;
-
+
   if (decimalTime > 1259) decimalTime -= 1200;
   if (decimalTime < 59) decimalTime += 1200;

@@ -163,7 +177,7 @@
 }

-void displayDay ()                                                // Convert Day Number to Display Letters
+void displayDay ()  // Convert Day Number to Display Letters
 {
   DateTime now = RTC.now();
   int daynumber = now.dayOfWeek();
@@ -196,7 +210,7 @@
 // ================================================================================== //

-void blinkColon()                                       // Blinks Colon
+void blinkColon()  // Blink Colon
 {
   long interval = 750;
   unsigned long currentMillis = millis();
@@ -210,11 +224,11 @@
 }

-void adjustBrightness()                                              // Brightness Check & Adjust
+void adjustBrightness()  // Brightness Check & Adjust
 {
   int brightReading = analogRead(brightKnob);                        // Check & Map Potentiometer
   int clockBrightness = map(brightReading, 0, 1023, 1, 15);
-  neoBrightness =  map(brightReading, 0, 1023, 100, 255);
+  pixelBrightness =  map(brightReading, 0, 1023, 100, 255);

   int brightSwitchRead = digitalRead(brightSwitch);
   if (brightSwitchRead == HIGH)
@@ -222,11 +236,11 @@
     disp.setBrightness(clockBrightness);
     alpha4.setBrightness(clockBrightness);
   }
-  else strip.setBrightness(neoBrightness);
-}
-
-
-void fourTwentyCheck()                                 // 420 Check, Blink & Buzz
+  else strip.setBrightness(pixelBrightness);
+}
+
+
+void fourTwentyCheck()  // 420 Check, Blink & Buzz
 {
   int decimalTime = getDecimalTime();
   if (decimalTime == 420)
@@ -240,14 +254,14 @@
   }
   else
   {
-    noTone(piezoOut);
+    noTone(piezoSpeaker);
     disp.blinkRate(0);
     alpha4.blinkRate(0);
   }
 }

-void fourTwentyWords()                                     // Writes "HIGH" & Blinks Alphanumeric Display
+void fourTwentyWords()  // Writes message to alphanumeric & beeps piezo
 {
   beep(NOTE_G4, 500);
   beep(NOTE_G4, 500);
@@ -280,31 +294,51 @@
 // ================================================================================== //

-void ledMatrixOFF()
+int frontLEDCheck()  // Turns front facing LED on/off
+{
+  LEDState = digitalRead(frontLEDButton);
+
+  if (LEDState != LEDLastState)                              // Compare the LEDState to its previous state
+  if (LEDState == HIGH) LEDButtonCount++;
+
+  LEDLastState = LEDState;                                   // Save current state for next loop
+
+  if (LEDButtonCount == 1) digitalWrite(frontLED, HIGH );
+  else
+  {
+  LEDButtonCount = 0;
+  digitalWrite(frontLED, LOW);
+  }
+}
+
+// Turns neomatrix panel off
+void ledMatrixOFF()
 {
   strip.setBrightness(0);
-  strip.show();                                        // ... both of these functions
-}
-
-
-void reminderSwitchCheck()                                   // Checks Switch & Activates LED
-{
-  int reminderState = digitalRead(reminderSwitch);        // Check Reminder Switch
-  if (reminderState == HIGH) rainbowCycle(20);
-  else if ((reminderState == LOW) && (decimalTime != 420)) ledMatrixOFF();
-}
-
-
-void beep(int note, int duration)                        // Creates Individual Notes & Alternates LED's
+  strip.show();
+}
+
+
+void pixelSwitchCheck()   // Checks Switch & Activates LED
+{
+  int pixelSwitchState = digitalRead(neoPixelSwitch);
+  if (pixelSwitchState == HIGH) rainbowCycle(20);
+  else if ((pixelSwitchState == LOW) && (decimalTime != 420)) ledMatrixOFF();
+}
+
+
+void beep(int note, int duration)  // Creates Individual Notes & Alternates LED's for melody
 {
   long interval = 20;
   unsigned long currentMillis = millis();
   if (currentMillis - previousMillis > interval)
   {
     previousMillis = currentMillis;
-    tone(piezoOut, note, duration);                          //Play tone on buzzerPin
-    if (noteCounter % 2 == 0)                                // Alternate Green then UV LED's
+    tone(piezoSpeaker, note, duration);              // Play tone on buzzerPin
+    if (noteCounter % 2 == 0)                    // Alternate Green then Purple
     {
+      digitalWrite(frontLED, LOW);
+
       uint16_t j;
       for (j = 0; j < 40 ; j++)
       {
@@ -315,6 +349,8 @@
     }
     else
     {
+      digitalWrite(frontLED, HIGH);
+
       uint16_t j;
       for (j = 0; j < 40 ; j++)
       {
@@ -323,15 +359,15 @@
       }
       delay(duration);
     }
-    noTone(piezoOut);
+    noTone(piezoSpeaker);
     noteCounter++;
   }
 }

-void rainbowCycle(uint8_t wait)                             // Runs rainbow led fade
-{
-  strip.setBrightness(neoBrightness);
+void rainbowCycle(uint8_t wait)  // Runs rainbow led fade
+{
+  strip.setBrightness(pixelBrightness);
   uint16_t i, j;

   for (j = 0; j < 256 ; j++)
@@ -345,9 +381,9 @@
   }
 }

-// Required for rainbowCycle()
-uint32_t Wheel(byte WheelPos)                                 // Colors transition r - g - b - r - g...
-{
+
+uint32_t Wheel(byte WheelPos)  // Colors transition r - g - b - r - g...
+{                              // (Req'd for rainbowCycle)
   if (WheelPos < 85)
   {
     return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
@@ -370,20 +406,20 @@
 // ================================================================================== //

-void debounceSwitches()
-{
-  for (byte i = 0; i < NUMBUTTONS; i++)
-  {
-    static byte previousstate[NUMBUTTONS];
-    static byte currentstate[NUMBUTTONS];
+void debounceSwitches()  // Smooth button presses
+{
+  for (byte i = 0; i < numBtns; i++)
+  {
+    static byte previousstate[numBtns];
+    static byte currentstate[numBtns];
     static long lasttime;
     byte index;

-    if (millis() < lasttime) lasttime = millis();                                  // we wrapped around, try again
-    if ((lasttime + DEBOUNCE) > millis()) return;                         // not enough time has passed to debounce
+    if (millis() < lasttime) lasttime = millis();                 // we wrapped around, try again
+    if ((lasttime + DEBOUNCE) > millis()) return;                 // not enough time has passed to debounce
     lasttime = millis();                                          // waited DEBOUNCE milliseconds, reset timer

-    for (index = 0; index < NUMBUTTONS; index++)
+    for (index = 0; index < numBtns; index++)
     {
       currentstate[index] = digitalRead(buttons[index]);          // read the button
       if (currentstate[index] == previousstate[index])
@@ -404,7 +440,7 @@
 }

-void themeMusic()                                                // Plays game of thones theme
+void themeMusic()  // Plays game of thones theme
 {
   for (int i = 0; i < 3; i++)
   {


Created MD5 160-bit hash successfully

Created MD5 160-bit hash successfully

--- src/md5_test/md5_test.ino
+++ src/md5_test/md5_test.ino
@@ -34,7 +34,14 @@
         uint8_t *fullMessage = GetFullMessage(correct_key, keyLen, msg, msgLen, fullMsgLen);
         Serial.flush();

+        // Generate hash
+        unsigned char *hash = MD5::make_hash((char *)fullMessage);
+        // Digest
+        char *md5str = MD5::make_digest(hash, 20);
+        Serial.println(md5str);
+
         CAN.sendMsgBuf(id, 0, dlc, msg);
+
     }
 }


new picker stuff

new picker stuff

--- Lifter/Lifter.ino
+++ Lifter/Lifter.ino
@@ -1,7 +1,7 @@
 #include <AccelStepper.h>
 #include <Servo.h>

-// #defines are macros for faster than digitalWrite() read & write.
+// #defines are macros for faster pin access than built-in digitalWrite().
 //  *http://masteringarduino.blogspot.com/2013/10/fastest-and-smallest-digitalread-and.html

 #define portOfPin(P)\
@@ -39,29 +39,34 @@
 const byte ONRESERVE = 32;          // max byte length of serial-delivered string
 const byte PROX_PIN = A0;           // Analog prox. sensor Pin for card-stack-top
 const byte CARD_PIN = A1;           // Analog prox. for 'card on-board'
-const int cardThickness = 141;       // 141 steps to lift a card. 608steps/turn
-                                    // (20 turns per 86 cards, 141.3953 ...
-const int proxSense2 = 800;         // threshold for OPB606A riding on fan housing
-const int liftSenseTop = 500;        // above threshold nothing is close to face of OPB606A
+const int cardThickness = 52;       // calculated 141 steps to lift a card. 608steps/turn
+                                     // (20 turns per 86 cards, 141.3953 ...
+const int proxSense2 = 600;         // threshold for OPB606A riding on fan housing
+const int liftSenseTop = 810;        // above threshold nothing is close to face of OPB606A
 const long int hoverArmPos = 5;      // pick up postion after zeroing against armLimit
 const long int firstArmPos = 142;    // experimentally determined drop-off position
 const long int secondArmPos = 280;   // 2nd drop and max Arm travel
-const byte lowAng = 147;              // servo position: closest approach to card-stack
-const byte midAng = 117;              // servo position: move to clear roller
-const byte highAng = 15;              // servo postion:
-const byte bumpBinSteps = 36;        // for jiggle when grabTryCount goes up.
-const byte servoPosition = 50;      // initial safe servo position
+const byte lowAng = 120;              // servo position: closest approach to card-stack
+const byte highAng = 157;              // servo postion:
+const byte bumpBinSteps = 36;        // for jiggle when grabTryCo17unt goes up.
+const byte servoPosition = 145;      // initial setup() safe servo position
+const byte extraServoBump = 3;      // travel either way a little further then settle back to low or high
 int newAnalog1 = 0;                 // hold value from the PROX_PIN sensor
 int newAnalog2 = 0;                 // hold value from the CARD_PIN sensor
 int oldAnalog1 = 0;                 // discover changes in the PROX_PIN sensor
 int oldAnalog2 = 0;                 // discover changes in the CARD_PIN sensor
-byte grabTryCount = 0;              // bump the bin to help the grabber
+long int destinationArmPos = firstArmPos;  // arm drop-off point (first or second)
+byte grabTryCount = 0;              // bump the bin to help the grabber
+byte oldServoPos = servoPosition;    // for tracking changes is servo. Are they continuous?
 String inputString = "";
 boolean LOADED = false;
 boolean ARMZEROED = false;
 boolean BACKINGOFF = false;
+byte restServoPos = servoPosition;    // used for moving servo back off its maximum travel on either end; set in fanDown()
+boolean stressedServo = false;       // flag for above
 unsigned long timeStart = 0;
 unsigned long timeCurrent = 0;
+boolean UPDATE = true;              // flag for printing updated info to serial monitor

 AccelStepper stepperArm(AccelStepper::DRIVER, PINST1_ST, PINST1_DIR);
 AccelStepper stepperLift(AccelStepper::DRIVER, PINST2_ST, PINST2_DIR);
@@ -73,7 +78,7 @@

 volatile byte liftState = LOW;
 volatile byte armState = LOW;
-volatile boolean UPDATE = true;            // flag for printing updated info
+

 void setup()
 {
@@ -98,9 +103,6 @@
     digitalLow(holdPinArm);                 // HIGH disables driver, LOW enables
     digitalLow(holdPinLift);                // HIGH disables driver, LOW enables

-    // glow red when any stepper is enabled:
-    // digitalWrite(REDLED, (!digitalState(holdPinArm)) | (!digitalState(holdPinLift)));
-
     Serial.begin(115200);
     inputString.reserve(ONRESERVE);
     Serial.println("Setup: liftLimit Switch is " + String(digitalState(LIMIT_SW)) + "\n");
@@ -108,7 +110,7 @@
     Serial.println("A0: " + String(analogRead(PROX_PIN)));
     Serial.println("A1: " + String(analogRead(CARD_PIN)));
     stepperLift.moveTo(liftUpToTop);
-    stepperArm.moveTo(-1023);
+    stepperArm.moveTo(-10234);    // should get Arm to limit-switch under any starting circumstance
     timeStart = millis();
     timeCurrent = millis();
 }
@@ -132,7 +134,7 @@
         liftState = LOW;
       }
     }
-    else if ((!liftState) && ((timeStart - millis()) > 1900))    // deals with switch hysterysis
+    else if ((!liftState) && ((timeStart - millis()) > 1900))    // deals with limit-switch hysterysis
       BACKINGOFF = false;
     else if ((liftState == HIGH) && (!BACKINGOFF)) {          // stopping for unforseen reasons
       delay(4);                                               // de-bounce
@@ -158,7 +160,8 @@
     newAnalog1 = analogRead(PROX_PIN);
     newAnalog2 = analogRead(CARD_PIN);

-    fanDown(lowAng, midAng, highAng, firstArmPos);      // auto-servo position based on bin and sensor threshold
+    // auto-servo position based on bin and sensor threshold
+    fanDown(lowAng, highAng, destinationArmPos);

     // loading by default, so moving down, one card at a time
     if (!LOADED){
@@ -175,40 +178,63 @@
     else if ((grabTryCount % 5) == 4)
         stepperLift.moveTo(stepperLift.currentPosition() + cardThickness);

-    // track the analog sensors avoiding flutter values
-    if (abs(oldAnalog1 - newAnalog1) > 40) {
+    // TRACKING via SERIAL MONITOR without flooding it
+    // analog sensors avoiding flutter values
+   // comment out once everything is working perfectly
+    if (abs(oldAnalog1 - newAnalog1) > 30) {
       UPDATE = true;
       oldAnalog1 = newAnalog1;
-      //myserv.write(map(newAnalog1, 0, 1023, 40, 135));  // servo won't be slaved here unless testing
-    }
-    if (abs(oldAnalog2 - newAnalog2) > 40) {
-      UPDATE = true;
-      oldAnalog2 = newAnalog2;
-    }
-
-    stepperLift.run();
-    stepperArm.run();
-
+    }
+    else if (abs(oldAnalog2 - newAnalog2) > 30)
+
     if (UPDATE) {
         Serial.print("Liftpos: " + String(stepperLift.currentPosition()) + " Armpos: " + String(stepperArm.currentPosition()));
         Serial.println("  A0: " + String(newAnalog1) + "  A1: " + String(newAnalog2) + " srvo: " + String(myserv.read()));
         UPDATE = false;
     }
+
+    stepperLift.run();
+    stepperArm.run(); {
+      UPDATE = true;
+      oldAnalog2 = newAnalog2;
+    }
+    else if (abs(myserv.read() - oldServoPos) > 2) {
+      UPDATE = true;
+      oldServoPos = myserv.read();
+    }
+
+    if (UPDATE) {
+        Serial.print("Liftpos: " + String(stepperLift.currentPosition()) + " Armpos: " + String(stepperArm.currentPosition()));
+        Serial.println("  A0: " + String(newAnalog1) + "  A1: " + String(newAnalog2) + " srvo: " + String(myserv.read()));
+        UPDATE = false;
+    }
+
+    stepperLift.run();
+    stepperArm.run();

     // first character sent switches us into LOADED mode
     // 97="a", 98="b", 99="c", 100="d"
     if (Serial.available() > 0) {
       inputString = String(Serial.read());
-      LOADED = true;
+      if (!LOADED) {
+        LOADED = true;
+        stepperLift.setCurrentPosition(0);
+        UPDATE = true;
+      }
       Serial.println("Rx: " + inputString);
-      if (inputString == "97")
+      if (inputString == "97")               // 'a' hover over input stack
         stepperArm.moveTo(hoverArmPos);
-      else if (inputString == "98")
+      else if (inputString == "98") {        // 'b' ID'd pile
         stepperArm.moveTo(firstArmPos);
-      else if (inputString == "99")
+        destinationArmPos = firstArmPos;
+      }
+      else if (inputString == "99") {        // 'c' unidentified pile
         stepperArm.moveTo(secondArmPos);
-      else if (inputString == "100") {       // Reset into loading mode until another character sent
+        destinationArmPos = firstArmPos;
+      }
+      else if (inputString == "100") {       // 'd' Reset into loading mode until another character sent
         stepperArm.moveTo(firstArmPos);
+        destinationArmPos = firstArmPos;
         LOADED = false;
       }
       inputString = "";
@@ -226,23 +252,28 @@
 }

 // trying for non-blocking servo with delay between actuation attempts...
-void fanDown(byte down, byte mid, byte drop, long int dropZone) {
+void fanDown(byte down, byte drop, long int dropZone) {
   // go down to get card only if stopped in hover position over bin
-  if ((millis() - timeStart) > 800){
-    if ((newAnalog2 > liftSenseTop) && (stepperArm.currentPosition() == hoverArmPos)) {
-      myserv.write(down);
+
+  if (!stressedServo && ((millis() - timeStart) > 700)){
+    if ((stepperArm.currentPosition() == hoverArmPos) && (newAnalog2 > proxSense2)) {
+      myserv.write(down - extraServoBump);
+      restServoPos = down;
+      stressedServo = true;
       timeStart = millis();
       grabTryCount += 1;
     }
     else if ((stepperArm.currentPosition() == dropZone) && (newAnalog2 < proxSense2)) {
-      myserv.write(drop);
+      myserv.write(drop + extraServoBump);
+      restServoPos = drop;
+      stressedServo = true;
       timeStart = millis();
       grabTryCount = 0;
     }
-    else if (myserv.read() != mid) {
-      myserv.write(mid);
-      timeStart = millis();
-    }
+  }
+  else if (stressedServo && ((millis() - timeStart) > 600)) {
+    myserv.write(restServoPos);
+    stressedServo = false;
   }
 }


clean up/bug fix

clean up/bug fix

--- gc3ds.ino
+++ gc3ds.ino
@@ -11,6 +11,8 @@
 {
 	ds_pin_init();
 	map_init();
+	pinMode(CPAD_X_PIN, OUTPUT);
+	pinMode(CPAD_Y_PIN, OUTPUT);
 	analogWrite(CPAD_X_PIN, 127);
 	analogWrite(CPAD_Y_PIN, 127);
 	lcd.clear();
@@ -26,9 +28,6 @@
 	if(Gamecube.read(false) && Gamecube.report.start == 1)
 		do_menu();

-	pinMode(CPAD_X_PIN, OUTPUT);
-	pinMode(CPAD_Y_PIN, OUTPUT);
-
 	lcd.clear();
 	lcd.gotoXY(0, 0);
 	lcd.print("controller");
@@ -37,23 +36,7 @@
 	TCCR0B = TCCR0B & 0b11111000 | 0x01;
 }

-
-void print_xy()
-{
-	lcd.clear();
-	while(1)
-	{
-		read_gc_controller();
-		lcd.gotoXY(0, 0);
-		lcd.print((int)(Gamecube.report.cxAxis));
-		lcd.print("    ");
-		lcd.gotoXY(0, 1);
-		lcd.print((int)(Gamecube.report.cyAxis));
-		lcd.print("    ");
-	}
-}
-
-char is_valid_index(char index)
+char get_3ds_pin(char index)
 {
 	if(ds_button_map[index] >= 0 and ds_button_map[index] <= 7)
 		return ds_pin_map[ds_button_map[index]];
@@ -65,15 +48,16 @@
 {
 	read_gc_controller();

-	button_control(is_valid_index(GC_A_BUTTON), Gamecube.report.a);
-	button_control(is_valid_index(GC_B_BUTTON), Gamecube.report.b);
-	button_control(is_valid_index(GC_X_BUTTON), Gamecube.report.x);
-	button_control(is_valid_index(GC_Y_BUTTON), Gamecube.report.y);
-	button_control(is_valid_index(GC_L_TRIGGER), Gamecube.report.left > 127);
-	button_control(is_valid_index(GC_R_TRIGGER), Gamecube.report.right > 127);
-	button_control(is_valid_index(GC_L_BUTTON), Gamecube.report.l);
-	button_control(is_valid_index(GC_R_BUTTON), Gamecube.report.r);
-	button_control(is_valid_index(GC_START_BUTTON), Gamecube.report.start);
+	button_control(get_3ds_pin(GC_A_BUTTON), Gamecube.report.a);
+	button_control(get_3ds_pin(GC_B_BUTTON), Gamecube.report.b);
+	button_control(get_3ds_pin(GC_X_BUTTON), Gamecube.report.x);
+	button_control(get_3ds_pin(GC_Y_BUTTON), Gamecube.report.y);
+	button_control(get_3ds_pin(GC_L_TRIGGER), Gamecube.report.left > 127);
+	button_control(get_3ds_pin(GC_R_TRIGGER), Gamecube.report.right > 127);
+	button_control(get_3ds_pin(GC_L_BUTTON), Gamecube.report.l);
+	button_control(get_3ds_pin(GC_R_BUTTON), Gamecube.report.r);
+	button_control(get_3ds_pin(GC_Z_BUTTON), Gamecube.report.z);
+	button_control(get_3ds_pin(GC_START_BUTTON), Gamecube.report.start);

 	// for 3ds circle pad
 	if(ds_button_map[GC_MAIN_STICK] == DS_CIRCLE_PAD)


Delete send_recv_led.ino

Delete send_recv_led.ino

--- send_recv_led.ino
+++ send_recv_led.ino
@@ -1,155 +0,0 @@
-#include <nRF24L01.h>
-#include <printf.h>
-#include <RF24.h>
-#include <RF24_config.h>
-
-
-/*
-* Getting Started example sketch for nRF24L01+ radios
-* This is a very basic example of how to send data from one node to another
-* Updated: Dec 2014 by TMRh20
-*/
-
-#include <SPI.h>
-#include "RF24.h"
-
-/****************** User Config ***************************/
-/***      Set this radio as radio number 0 or 1         ***/
-bool radioNumber = 1;
-
-/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
-RF24 radio(9,10);
-/**********************************************************/
-
-byte addresses[][6] = {"1Node","2Node"};
-
-// Used to control whether this node is sending or receiving
-bool role = 0;
-
-void setup() {
-    // the setup function runs once when you press reset or power the board
-
-    pinMode(LED_BUILTIN, OUTPUT);
-
-    Serial.begin(115200);
-    Serial.println(F("RF24/examples/GettingStarted"));
-    Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
-
-    radio.begin();
-
-    // Set the PA Level low to prevent power supply related issues since this is a
-    // getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default.
-    radio.setPALevel(RF24_PA_LOW);
-
-    // Open a writing and reading pipe on each radio, with opposite addresses
-    if(radioNumber){
-        radio.openWritingPipe(addresses[1]);
-        radio.openReadingPipe(1,addresses[0]);
-    }else{
-        radio.openWritingPipe(addresses[0]);
-        radio.openReadingPipe(1,addresses[1]);
-    }
-
-    // Start the radio listening for data
-    radio.startListening();
-}
-
-void loop() {
-
-/****************** Ping Out Role ***************************/
-    if (role == 1)  {
-
-        digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
-        delay(100);                       // wait for a second
-        digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
-        delay(100);
-
-        radio.stopListening();                                    // First, stop listening so we can talk.
-
-
-        Serial.println(F("Now sending"));
-
-        unsigned long start_time = micros();                             // Take the time, and send it.  This will block until complete
-        if (!radio.write( &start_time, sizeof(unsigned long) )){
-        Serial.println(F("failed"));
-        // the loop function runs over and over again forever
-        }
-
-        radio.startListening();                                    // Now, continue listening
-
-        unsigned long started_waiting_at = micros();               // Set up a timeout period, get the current microseconds
-        boolean timeout = false;                                   // Set up a variable to indicate if a response was received or not
-
-        while ( ! radio.available() ){                             // While nothing is received
-            if (micros() - started_waiting_at > 200000 ){            // If waited longer than 200ms, indicate timeout and exit while loop
-              timeout = true;
-              break;
-          }
-        }
-
-        if ( timeout ){                                             // Describe the results
-            Serial.println(F("Failed, response timed out."));
-        }else{
-            unsigned long got_time;                                 // Grab the response, compare, and send to debugging spew
-            radio.read( &got_time, sizeof(unsigned long) );
-            unsigned long end_time = micros();
-
-            // Spew it
-            Serial.print(F("ID sent: "));
-            Serial.print(start_time);
-            Serial.print(F(",ID recv: "));
-            Serial.print(got_time);
-            /*
-            Serial.print(F(", Round-trip delay "));
-            Serial.print(end_time-start_time);
-            Serial.println(F(" microseconds"));*/
-            Serial.println(F("\nSuccess\n"));
-        }
-
-        // Try again 1s later
-        delay(5000);
-
-    }
-
-
-
-/****************** Pong Back Role ***************************/
-
-    if ( role == 0 )
-    {
-        unsigned long got_time;
-
-        if( radio.available()){
-                                                // Variable for the received timestamp
-            while (radio.available()) {                                   // While there is data ready
-                radio.read( &got_time, sizeof(unsigned long) );             // Get the payload
-            }
-
-            radio.stopListening();                                        // First, stop listening so we can talk
-            radio.write( &got_time, sizeof(unsigned long) );              // Send the final one back.
-            radio.startListening();                                       // Now, resume listening so we catch the next packets.
-            Serial.print(F("Sent response "));
-            Serial.println(got_time);
-            }
-    }
-
-
-
-
-/****************** Change Roles via Serial Commands ***************************/
-
-    if ( Serial.available() )
-    {
-        char c = toupper(Serial.read());
-        if ( c == 'T' && role == 0 ){
-            Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
-            role = 1;                  // Become the primary transmitter (ping out)
-        }else if ( c == 'R' && role == 1 ){
-            Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
-            role = 0;                // Become the primary receiver (pong back)
-            radio.startListening();
-
-         }
-    }
-} // Loop
-


make it a bit brighter

make it a bit brighter

--- status.ino
+++ status.ino
@@ -11,7 +11,7 @@
 #define RESPONSE_SCALE_DOWN 3
 #define RESPONSE_RESTART 4

-#define LIGHT_INTENSITY 10 // how bright – 1 to 255
+#define LIGHT_INTENSITY 25 // how bright – 1 to 255

 SparkButton strip = SparkButton();


added comments to Sine generator

added comments to Sine generator

--- Modules/Modifier/SineGenerator/ArduinoCodes/SineGeneratorATtiny/SineGeneratorATtiny.ino
+++ Modules/Modifier/SineGenerator/ArduinoCodes/SineGeneratorATtiny/SineGeneratorATtiny.ino
@@ -30,7 +30,7 @@
 127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,
 21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
 33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
-};
+};                                            //table holding all sine values

 int input_pin = 3;                           //Pin 2 on ATtiny
 int pot_pin = 2;
@@ -52,7 +52,7 @@

 void loop() {

-  if(i >= 256){
+  if(i >= 256){                  //table has 256 values, reset i to 0 to simulate periodicity
     i = 0;
   }
   int input_val = cutAndMap(input.filteredAnalogRead(AVERAGE), 50, 975, 0, 1023);
@@ -63,9 +63,10 @@
   unsigned long currentMillis = millis();

   if (currentMillis - previousMillis >= interval){
-    output_val = cutAndMap(pgm_read_byte(&sinTable[i++]), 0, 254, 0, amplitude);
+    output_val = cutAndMap(pgm_read_byte(&sinTable[i++]), 0, 254, 0, amplitude);     //get next value from table and output it.  254 because that is the largest value in the table
+    previousMillis = currentMillis;                             // save the last time you changed values
   }
-
+  //if it is not time to change values, output will remain the same
   analogWrite(output_pin, output_val);
 }


Updated with descriptions of the pinouts

--- Arduino/GhostPassword/GhostPassword.ino
+++ Arduino/GhostPassword/GhostPassword.ino
@@ -13,6 +13,16 @@
 #include <Adafruit_NeoPixel.h>
 #include <Arduino.h>  // for type definitions

+//Instructions:
+// Plug power and ground into all devices
+// Pin 0: TX-0 on bluetooth
+// Pin 1: RX-0 on bluetooth
+// Pin 2: Input pin on led
+// Pin 3: One side of the button
+// Pin 4: Empty
+// Pin 5: One of the two control pins on the RTC
+// Pin 6: The other control pin on the RTC
+// Pin 7: Other side of the button (This pin provides power)

 #define CONFIG_VERSION 2
 #define CONFIG_START 1
@@ -22,8 +32,9 @@
 #define EEPROM_MAX_ADDR 1024 // Max size on the Teensy 2

-#define BUTTON_PIN 2
-#define LED_PIN 3
+#define BUTTON_PIN 3
+#define BUTTON_PWR_PIN 7
+#define LED_PIN 2
 #define LED_COUNT 1
 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

@@ -85,6 +96,8 @@
   digitalClockDisplay();
   //Prep button
   pinMode(BUTTON_PIN, INPUT);
+  pinMode(BUTTON_PWR_PIN, OUTPUT);
+  digitalWrite(BUTTON_PWR_PIN, HIGH);

   // Prep bluetooth
    setColor('b');
@@ -186,14 +199,18 @@
   if(bluetooth.available() > 0){
     String input = bluetooth.readString();
     Serial.println(input);
+
   }*/

   if (digitalRead(BUTTON_PIN) == HIGH) {
-    //Serial.println("Button is not pressed...");
+    Serial.println("Button pressed!!!");
+    //Keyboard.write(totp.getCode(now()));
+    Serial.print("OTP Code: ");
+    Serial.println(totp.getCode(now()));
+    delay(1500);
   } else {
-    //Keyboard.write(totp.getCode(now()));
-    //Serial.println("Button pressed!!!");
-    delay(1000);
+    Serial.println("Button is not pressed...");
+    delay(100);
   }
 }

@@ -275,10 +292,10 @@
 void initialTimeSet(){
   int year = 2015;
   int month = 10;
-  int day = 1;
-  int hour = 13+6;
-  int minute = 42;
-  int second = 0;
+  int day = 13;
+  int hour = 10+6;
+  int minute = 8;
+  int second = 50;
   setTime(hour, minute, second, day, month, year);   //set the system time to 23h31m30s on 13Feb2009
   RTC.set(now());                     //set the RTC from the system time
 }