Read non-key inputs less often.

Read non-key inputs less often.

--- synth_main/src/main.ino
+++ synth_main/src/main.ino
@@ -30,6 +30,13 @@
 }

 unsigned long last_time = millis();
+
+// Keep track of the frame count so we can read inputs less often.
+byte frameCount = 0;
+
+// How often to read inputs.
+byte frameStep = 8;
+
 void loop() {

   // Change this to if(1) for measurement output every 2 seconds
@@ -51,6 +58,8 @@
   usbMIDI.read();

   readInputs();
+
+  frameCount++;
 }

 void OnNoteOn(byte channel, byte note, byte velocity) {
@@ -202,26 +211,28 @@
   digitalWrite(multiplexCPin, LOW);
   delayMicroseconds(propagationDelay);

-  // Mode depth
-  int value = analogRead(multiplexInputPin1);
-
-  // Amplitude envelope attack
-  value = analogRead(multiplexInputPin2);
-  synth.setAmpEnvAttack(fscale(1, 1023, 1, 2000, value, -5));
-
-  // Filter cutoff
-  value = analogRead(multiplexInputPin3);
-  if (value != p3) {
-   p3 = value;
-   float freq = fscale(1, 1023, 200, 8000, p3, -3);
-   synth.setFilterFrequency(freq);
-  }
-
-  // Preset selector
-  value = readSelectorPin(multiplexInputPin4);
-
   readInputKeyRow(39);

+  if (frameCount % frameStep == 0) {
+    // Mode depth
+    int value = analogRead(multiplexInputPin1);
+
+    // Amplitude envelope attack
+    value = analogRead(multiplexInputPin2);
+    synth.setAmpEnvAttack(fscale(1, 1023, 1, 2000, value, -5));
+
+    // Filter cutoff
+    value = analogRead(multiplexInputPin3);
+    if (value != p3) {
+     p3 = value;
+     float freq = fscale(1, 1023, 200, 8000, p3, -3);
+     synth.setFilterFrequency(freq);
+    }
+
+    // Preset selector
+    value = readSelectorPin(multiplexInputPin4);
+  }
+

   /**
    * Multiplexer pin 1
@@ -229,69 +240,80 @@
   digitalWrite(multiplexAPin, HIGH);
   delayMicroseconds(propagationDelay);

-  // Synth osc 2 voice
-  value = readSelectorPin(multiplexInputPin1);
-  if (value != p1) {
-    p1 = value;
-
-    switch (p1) {
-      case 0:
-        synth.setWaveForm2(WAVEFORM_NOISE);
-        break;
-
-      case 1:
-        synth.setWaveForm2(WAVEFORM_SINE);
-        break;
-
-      case 2:
-        synth.setWaveForm2(WAVEFORM_TRIANGLE);
-        break;
-
-      case 3:
-        synth.setWaveForm2(WAVEFORM_SAWTOOTH);
-        break;
-
-      case 4:
-        synth.setWaveForm2(WAVEFORM_SQUARE);
-        break;
-    }
-  }
-
-  // Filter envelope sustain.
-  value = analogRead(multiplexInputPin2);
-  synth.setFilterEnvelopeSustain(fscale(1, 1023, 0.0, 1.0, value, 0));
-
-  // Sampler selector
-  value = readSelectorPin(multiplexInputPin4);
-
   readInputKeyRow(53);

+  if (frameCount % frameStep == 1) {
+
+    // Synth osc 2 voice
+    int value = readSelectorPin(multiplexInputPin1);
+    if (value != p1) {
+      p1 = value;
+
+      switch (p1) {
+        case 0:
+          synth.setWaveForm2(WAVEFORM_NOISE);
+          break;
+
+        case 1:
+          synth.setWaveForm2(WAVEFORM_SINE);
+          break;
+
+        case 2:
+          synth.setWaveForm2(WAVEFORM_TRIANGLE);
+          break;
+
+        case 3:
+          synth.setWaveForm2(WAVEFORM_SAWTOOTH);
+          break;
+
+        case 4:
+          synth.setWaveForm2(WAVEFORM_SQUARE);
+          break;
+      }
+    }
+
+    // Filter envelope sustain.
+    value = analogRead(multiplexInputPin2);
+    synth.setFilterEnvelopeSustain(fscale(1, 1023, 0.0, 1.0, value, 0));
+
+    // LFO Waveform
+    value = readSelectorPin(multiplexInputPin3);
+    synth.setLFOWaveform(value);
+
+    // Sampler selector
+    value = readSelectorPin(multiplexInputPin4);
+  }
+

   /**
    * Multiplexer pin 3
    */
   digitalWrite(multiplexBPin, HIGH);
   delayMicroseconds(propagationDelay);
+
   readInputKeyRow(74);

-  // Transpose
-  value = analogRead(multiplexInputPin1);
-  synth.setTranspose(map(value, 1, 1022, -12, 12));
-
-  // Amplitude envelope sustain
-  value = analogRead(multiplexInputPin2);
-  synth.setAmpEnvSustain(fscale(1, 1023, 0.0, 1.0, value, 0));
-
-  // Filter envelope amount
-  value = analogRead(multiplexInputPin3);
-  synth.setFilterEnvelopeAmount(fscale(1, 1023, -1.0, 1.0, value, 0));
-
-  // Master volume
-  value = analogRead(multiplexInputPin4);
-  if (value != p7) {
-   p7 = value;
-
-   synth.setMasterVolume((float)p7 / 1023 * 0.8);
+  if (frameCount % frameStep == 2) {
+
+    // Transpose
+    int value = analogRead(multiplexInputPin1);
+    synth.setTranspose(map(value, 1, 1022, -12, 12));
+
+    // Amplitude envelope sustain
+    value = analogRead(multiplexInputPin2);
+    synth.setAmpEnvSustain(fscale(1, 1023, 0.0, 1.0, value, 0));
+
+    // Filter envelope amount
+    value = analogRead(multiplexInputPin3);
+    synth.setFilterEnvelopeAmount(fscale(1, 1023, -1.0, 1.0, value, 0));
+
+    // Master volume
+    value = analogRead(multiplexInputPin4);
+    if (value != p7) {
+     p7 = value;
+
+     synth.setMasterVolume((float)p7 / 1023 * 0.8);
+    }
   }

@@ -301,76 +323,75 @@
   digitalWrite(multiplexAPin, LOW);
   delayMicroseconds(propagationDelay);

-  //  readAdditionalInputs();
-
-  // Synth osc 1
-  value = readSelectorPin(multiplexInputPin1);
-
-  if (value != p0) {
-    p0 = value;
-
-    switch (p0) {
-      case 0:
-        synth.setWaveForm1(WAVEFORM_SINE);
-        break;
-
-      case 1:
-        synth.setWaveForm1(WAVEFORM_TRIANGLE);
-        break;
-
-      case 2:
-        synth.setWaveForm1(WAVEFORM_SAWTOOTH);
-        break;
-
-      case 3:
-        synth.setWaveForm1(WAVEFORM_SQUARE);
-        break;
-
-      case 4:
-        synth.setWaveForm1(WAVEFORM_CELLO);
-        break;
-
-      case 5:
-        synth.setWaveForm1(WAVEFORM_PIANO);
-        break;
-
-      case 6:
-        synth.setWaveForm1(WAVEFORM_EORGAN);
-        break;
-    }
-  }
-
-  // Filter envelope attack
-  value = analogRead(multiplexInputPin2);
-  synth.setFilterEnvelopeAttack(fscale(1, 1023, 1, 2000, value, -5));
-
-  // LFO amplitude
-  value = analogRead(multiplexInputPin3);
-
+  if (frameCount % frameStep == 3) {
+
+    // Synth osc 1
+    int value = readSelectorPin(multiplexInputPin1);
+
+    if (value != p0) {
+      p0 = value;
+
+      switch (p0) {
+        case 0:
+          synth.setWaveForm1(WAVEFORM_SINE);
+          break;
+
+        case 1:
+          synth.setWaveForm1(WAVEFORM_TRIANGLE);
+          break;
+
+        case 2:
+          synth.setWaveForm1(WAVEFORM_SAWTOOTH);
+          break;
+
+        case 3:
+          synth.setWaveForm1(WAVEFORM_SQUARE);
+          break;
+
+        case 4:
+          synth.setWaveForm1(WAVEFORM_CELLO);
+          break;
+
+        case 5:
+          synth.setWaveForm1(WAVEFORM_PIANO);
+          break;
+
+        case 6:
+          synth.setWaveForm1(WAVEFORM_EORGAN);
+          break;
+      }
+    }
+
+    // Filter envelope attack
+    value = analogRead(multiplexInputPin2);
+    synth.setFilterEnvelopeAttack(fscale(1, 1023, 1, 2000, value, -5));
+
+    // LFO amplitude
+    value = analogRead(multiplexInputPin3);
+    synth.setLFOAmplitude(fscale(1, 1023, 0.0, 1.0, value, 0));
+  }

   /**
    * Multiplexer pin 6
    */
   digitalWrite(multiplexCPin, HIGH);
   delayMicroseconds(propagationDelay);
+
   readInputKeyRow(81);

-  // Tap tempo
-  value = analogRead(multiplexInputPin1);
-
-  // Amplitude envelope release
-  value = analogRead(multiplexInputPin2);
-  synth.setAmpEnvRelease(fscale(1, 1023, 1, 2000, value, -5));
-
-  // LFO target
-  value = readSelectorPin(multiplexInputPin3);
-
-//  if (value >= 512) {
-//    synth.setFilterLFOAmount(fscale(512, 1023, 0, 3, value, -3));
-//  }
-//  else {
-//    synth.setAmplitudeModulationLFOAmount(fscale(1, 512, 1.0, 0.0, value, 3));
-//  }
+  if (frameCount % frameStep == 4) {
+
+    // Tap tempo
+    int value = analogRead(multiplexInputPin1);
+
+    // Amplitude envelope release
+    value = analogRead(multiplexInputPin2);
+    synth.setAmpEnvRelease(fscale(1, 1023, 1, 2000, value, -5));
+
+    // LFO target
+    value = readSelectorPin(multiplexInputPin3);
+    synth.setLFOTarget(value);
+  }

   /**
@@ -381,20 +402,23 @@

   readInputKeyRow(67);

-  // Detune
-  value = analogRead(multiplexInputPin1);
-  // 1.0293022 = 24th root of 2 = quarter-step.
-  float detune = fscale(1, 1023, 1, 1.0293022, value, 0);
-  synth.setDetune(detune);
-
-  // Amplitude envelope decay
-  value = analogRead(multiplexInputPin2);
-  synth.setAmpEnvDecay(fscale(1, 1023, 1, 2000, value, -5));
-
-  // Filter resonance
-  value = analogRead(multiplexInputPin3);
-  float res = fscale(1, 1023, 0.0, 5.0, value, 0);
-  synth.setFilterResonance(res);
+  if (frameCount % frameStep == 5) {
+
+    // Detune
+    int value = analogRead(multiplexInputPin1);
+    // 1.0293022 = 24th root of 2 = quarter-step.
+    float detune = fscale(1, 1023, 1, 1.0293022, value, 0);
+    synth.setDetune(detune);
+
+    // Amplitude envelope decay
+    value = analogRead(multiplexInputPin2);
+    synth.setAmpEnvDecay(fscale(1, 1023, 1, 2000, value, -5));
+
+    // Filter resonance
+    value = analogRead(multiplexInputPin3);
+    float res = fscale(1, 1023, 0.0, 5.0, value, 0);
+    synth.setFilterResonance(res);
+  }

   /**
@@ -405,19 +429,20 @@

   readInputKeyRow(60);

-  // Mode selector
-  value = readSelectorPin(multiplexInputPin1);
-
-  // Filter envelope release
-  value = analogRead(multiplexInputPin2);
-  synth.setFilterEnvelopeRelease(fscale(1, 1023, 1, 2000, value, -5));
-
-  // Sustain pedal?
-  value = analogRead(multiplexInputPin3);
-
-  // Sampler velocity
-  value = analogRead(multiplexInputPin4);
-
+  if (frameCount % frameStep == 6) {
+    // Mode selector
+    int value = readSelectorPin(multiplexInputPin1);
+
+    // Filter envelope release
+    value = analogRead(multiplexInputPin2);
+    synth.setFilterEnvelopeRelease(fscale(1, 1023, 1, 2000, value, -5));
+
+    // Sustain pedal?
+    value = analogRead(multiplexInputPin3);
+
+    // Sampler velocity
+    value = analogRead(multiplexInputPin4);
+  }

   /**
    * Multiplexer pin 4
@@ -427,18 +452,20 @@

   readInputKeyRow(46);

-  // Synth mix
-  value = analogRead(multiplexInputPin1);
-  synth.setMix(fscale(1, 1023, 0.0, 1.0, value, 0));
-
-  // Filter envelope decay
-  value = analogRead(multiplexInputPin2);
-  synth.setFilterEnvelopeDecay(fscale(1, 1023, 1, 2000, value, -5));
-
-  // LFO rate
-  value = analogRead(multiplexInputPin3);
-  synth.setLFORate(fscale(1, 1023, 0.05, 10.0, value, -1));
-
-  // Mixer: Synth volume
-  value = analogRead(multiplexInputPin4);
-}
+  if (frameCount % frameStep == 7) {
+    // Synth mix
+    int value = analogRead(multiplexInputPin1);
+    synth.setMix(fscale(1, 1023, 0.0, 1.0, value, 0));
+
+    // Filter envelope decay
+    value = analogRead(multiplexInputPin2);
+    synth.setFilterEnvelopeDecay(fscale(1, 1023, 1, 2000, value, -5));
+
+    // LFO rate
+    value = analogRead(multiplexInputPin3);
+    synth.setLFORate(fscale(1, 1023, 0.05, 20.0, value, -2));
+
+    // Mixer: Synth volume
+    value = analogRead(multiplexInputPin4);
+  }
+}


Implement first control

Implement first control

--- src/livingRoomNode1/livingRoomNode1.ino
+++ src/livingRoomNode1/livingRoomNode1.ino
@@ -8,7 +8,7 @@
 #include <debounced.h>
 #include <controls.h>

-#define OUTDOOE_LIGHT1_ID 0
+#define OUTDOOR_LIGHT1_ID 0

 RFM69 radio;

@@ -28,10 +28,13 @@
   outdoorLight1.loop();
   if (radio.receiveDone()) {
     RadioHeader header;
-    SwitchedToggle value;
-    RadioNode::readRadio(&header, (char *)&value);
-    // TODO get the sensor ID by masking out the nodeid
-    // TODO target the correct controlid
-    // TODO set the state of the control
+    char buff[LBODY];
+    RadioNode::readRadio(&header, buff);
+    uint8_t controlId = header.id & 0x0F;
+    switch (controlId) {
+      case OUTDOOR_LIGHT1_ID:
+        outdoorLight1.setToggleControl((*(SwitchedToggle *)&buff).status);
+        break;
+    }
   }
 }


Led color example updated. Fix #247

Led color example updated. Fix #247

--- examples/Widgets/LED/LED_Color/LED_Color.ino
+++ examples/Widgets/LED/LED_Color/LED_Color.ino
@@ -51,18 +51,25 @@
   Serial.begin(9600); // See the connection status in Serial Monitor
   Blynk.begin(auth);

+  // Turn LED on, so colors are visible
+  led1.on();
+  // Setup periodic color change
   timer.setInterval(1000L, blinkLedWidget);
 }
+
+bool ledStatus = false;

 // V1 LED Widget is blinking
 void blinkLedWidget()
 {
-  if (led1.getValue()) {
+  if (ledStatus) {
     led1.setColor(BLYNK_RED);
     Serial.println("LED on V1: red");
+    ledStatus = false;
   } else {
     led1.setColor(BLYNK_GREEN);
     Serial.println("LED on V1: green");
+    ledStatus = true;
   }
 }


Ensure that pulsing animation only occurs when armed

--- sploder.ino
+++ sploder.ino
@@ -157,8 +157,12 @@
   }
 }
 void updateArmedState() {
-  pulseFiringLED();
   armedStatus();
+
+  if (armed) {
+    pulseFiringLED();
+  }
+
   digitalWrite(ARMED_LED, HIGH);
   if (!armed) {
     blePrint("disarmed");


Helpful wiring hint

Helpful wiring hint

--- examples/XLR8SelfTest/XLR8SelfTest.ino
+++ examples/XLR8SelfTest/XLR8SelfTest.ino
@@ -22,6 +22,7 @@
   EEPROM signals
   IOREF
   decoupling caps are probably untestable
+ Wiring is really simple. Just wire from 3.3V to Aref and that's it.
 */

 #ifndef cbi


add base

add base


Various attempts at implementing TimerOne internally

--- Flameduino/Flameduino.ino
+++ Flameduino/Flameduino.ino
@@ -8,7 +8,8 @@
 Flameduino Controls an ignition coil with a set dwell (compile time)
 and variable spark frequency, specifically for purposes of flamethrowing.
 */
-#include <TimerOne.h>
+//#include <TimerOne.h>
+#define TIMER1_RESOLUTION 65536UL  // Timer1 is 16 bit

 // -------------------------
 //     Pin Definitions
@@ -34,36 +35,41 @@
 // -------------------------
 //        Settings
 // -------------------------
-const bool debug = true;        //true = write to serial monitor, false = bypass
-const int serialOutLoops = 5;   //Number of loops that should execute before a serial write
+const bool debug = true;       //true = write to serial monitor, false = bypass
+const int serialOutLoops = 000; //Number of loops that should execute before a serial write
 //Ignition Settings
 const int dwell = 2500;         //Ignition coil charging dwell in microseconds (2.5ms = 2500us)
-const long periodMax = 1000000; //Maximum period between ignitions, in microseconds (min frequency)
+const long periodMax = 2000000; //Maximum period between ignitions, in microseconds (min frequency)
 const long periodMin = 5000;    //Minimum period between ignitions, in microseconds (max frequency)
 const int periodCorrection = 0; //Variance to period due to loop code execution time (milliseconds)
 const float linearity = 2.5;    //1.0 = linear, 0.5 = more resolution in the high end, 2.0 = more resolution in the low end (exponential)
 const bool triggerHigh = true;  //true = HIGH to fire, false = LOW to fire
 //Multifire Settings
-const bool multiFire = true;    //true = fire [firingCount] times per period, false = fire once per period
+const bool multiFire = false;    //true = fire [firingCount] times per period, false = fire once per period
 const int multiCount = 3;       //Numeber of sparks to fire per event
 const int multiDelay = 2000;    //Delay between multifires in microseconds (2ms = 2000us)
 //Tachometer Settings
 const int tachTrim = -30;        //Ticks to trim off the tach durations
+const long tachStale = 100000;   //Ticks after which the tach signal is 'stale'
+const byte activeState = LOW;    //State of activation pin that determines active

 // -------------------------
 //     Global Variables
 // -------------------------
 volatile bool active = false;
+byte ignitionMode = OFF;
+volatile bool updateTimer = true;
+volatile unsigned long tachPrevious = 0;
+volatile unsigned long tachCurrent = 0;
+unsigned long tachDuration0 = 0;
+unsigned long tachDuration1 = 0;
+unsigned long tachDuration2 = 0;
 unsigned int rpm = 0;
-volatile unsigned long tachDuration0 = 0;
-volatile unsigned long tachDuration1 = 0;
-volatile unsigned long tachDuration2 = 0;
-volatile unsigned long tachLast = 0;
-volatile byte ignitionMode = OFF;
-volatile byte remainingCount = 0;
-volatile bool updateTimer = false;
+byte remainingCount = 0;
 int loopsSinceSerialWrite = 0;
 long period = 0;
+
+int timerCount = 0;

 // -------------------------
 //      Initialization
@@ -79,15 +85,14 @@

   //Use built in pull-up resistor
   digitalWrite(ACTIVATION_PIN, HIGH);
-  active = digitalRead(ACTIVATION_PIN) == LOW;
+
+  active = isActive();
   dischargeCoil();

   attachInterrupt(TACH_PIN - 2, ISR_TACH, RISING);
   attachInterrupt(ACTIVATION_PIN - 2, ISR_ACTIVE, CHANGE);

-  Timer1.initialize();
-  Timer1.attachInterrupt(ISR_IGNITION);
-  Timer1.start();
+  initializeTimer1();

   if (debug)
   {
@@ -105,68 +110,83 @@
   period = getPeriod();
   rpm = getRPM();

-  noInterrupts();
+  if (debug && loopsSinceSerialWrite >= serialOutLoops)
+  {
+    Serial.print("Mode: ");
+    Serial.print(ignitionMode);
+    Serial.print(", ");
+  }
+
   if (active && ignitionMode == OFF)
     enableCoil();
-  else if (!active)
+  else if (!active && ignitionMode != OFF)
     disableCoil();

+  //Fire Ignition
   switch(ignitionMode)
   {
     case FIRE:
       dischargeCoil();
       if (multiFire) remainingCount = multiCount - 1;
-      ignitionMode = nextMode(ignitionMode);
+      updateTimer = true;
       break;
     case MULTIFIRE:
       dischargeCoil();
       remainingCount--;
-      ignitionMode = nextMode(ignitionMode);
+      updateTimer = true;
       break;
   }

-  if (updateTimer)
-  {
+  if (updateTimer == true)
+  {
+    stopTimer1();
+    updateTimer = false;
+    timerCount++;
+
+    if (debug && loopsSinceSerialWrite >= serialOutLoops)
+    {
+      Serial.print("Timer Reached - ");
+      Serial.print(timerCount);
+      Serial.print(", ");
+    }
+
+    ignitionMode = nextMode(ignitionMode);
+
     //Set the delay period (Head of Mode)
-    Timer1.detachInterrupt();
     switch(ignitionMode)
     {
       case OFF:
-        Timer1.stop();
+        dischargeCoil();
         break;
       case DWELL:
         //Charging Coil
         chargeCoil();
-        Timer1.attachInterrupt(ISR_IGNITION, dwell);
-        Timer1.start();
+        startTimer1(dwell);
         break;
       case MF_WAIT:
         //Waiting (MultiFire)
-        Timer1.attachInterrupt(ISR_IGNITION, multiDelay);
-        Timer1.start();
+        startTimer1(multiDelay);
         break;
       case MF_DWELL:
         //Charging Coil
         chargeCoil();
-        Timer1.attachInterrupt(ISR_IGNITION, dwell);
-        Timer1.start();
+        startTimer1(dwell);
         break;
       case WAIT:
         //Waiting (Frequency)
-        Timer1.attachInterrupt(ISR_IGNITION, period);
-        Timer1.start();
+        startTimer1(period);
         break;
     }
-    updateTimer = false;
-  }
-  interrupts();
+  }

   if (debug && loopsSinceSerialWrite >= serialOutLoops)
   {
-    Serial.print("Period: ");
+    Serial.print("Mode: ");
+    Serial.print(ignitionMode);
+    Serial.print(", Period: ");
     Serial.print(period / 1000.0);
-    Serial.print("ms, dwell: ");
-    Serial.print(dwell / 1000.0);
+    //Serial.print("ms, dwell: ");
+    //Serial.print(dwell / 1000.0);
     Serial.print("ms, RPM: ");
     Serial.print(rpm);
     Serial.println();
@@ -181,8 +201,7 @@
 // -------------------------
 bool isActive()
 {
-  //return digitalRead(ACTIVATION_PIN) == LOW;
-  return active;
+  return digitalRead(ACTIVATION_PIN) == activeState;
 }

 long getPeriod()
@@ -206,7 +225,35 @@
 unsigned int getRPM()
 {
   noInterrupts();
-  if (debug  && loopsSinceSerialWrite >= serialOutLoops)
+  unsigned long current = tachCurrent;
+  unsigned long previous = tachPrevious;
+  interrupts();
+
+  if (isStale())
+  {
+    tachDuration0 = 0;
+    tachDuration1 = 0;
+    tachDuration2 = 0;
+    return 0;
+  }
+
+  unsigned long duration;
+  if (current >= previous)
+  {
+    duration = current - previous + tachTrim;
+  }
+  else
+  {
+    //Handle Rollover
+    duration = 0xFFFFFFFFu - previous + current + tachTrim;
+  }
+
+  //Shift the values
+  tachDuration2 = tachDuration1;
+  tachDuration1 = tachDuration0;
+  tachDuration0 = duration;
+
+  if (false && debug && loopsSinceSerialWrite >= serialOutLoops)
   {
     Serial.print("t0: ");
     Serial.print(tachDuration0);
@@ -217,11 +264,19 @@
     Serial.print(", ");
   }

-  //Calculate Weighted Average
+  if (tachDuration0 <= 0 || tachDuration1 <= 0 || tachDuration2 <= 0)
+    return 0;
+
+  //Calculate Weighted Average duration
   unsigned long average = (3*tachDuration0 + 2*tachDuration1 + 1*tachDuration2)/6;
-  interrupts();
-
+
+  //Convert to RPM
   return 60.0 * 1000000 / average;
+}
+
+bool isStale()
+{
+  return (micros() - tachCurrent) > tachStale;
 }

 void enableCoil()
@@ -308,57 +363,116 @@
 // -------------------------
 void ISR_TACH()
 {
-  unsigned long duration;
-  unsigned long previous = tachLast;
   unsigned long current = micros();
-  tachLast = current;
-
-  //Now that tachLast has been set, enable Interrupts
+  tachPrevious = tachCurrent;
+  tachCurrent = current;
+}
+
+void ISR_ACTIVE()
+{
+  //Set the active global variable
+  active = isActive();
+}
+
+void ISR_IGNITION()
+{
+  //Interrupt has fired
+  updateTimer = true;
+}
+
+//Attach ISR to Timer1 Overflow
+ISR(TIMER1_OVF_vect)
+{
+  ISR_IGNITION();
+}
+
+// -------------------------
+// Generic Utility Functions
+// -------------------------
+void delayFixed(long milliseconds)
+{
+  if (milliseconds <= 0)
+    return;
+  else if (milliseconds < 16)
+    delayMicroseconds(milliseconds * 1000);
+  else
+    delay(milliseconds);
+}
+
+void initializeTimer1()
+{
+  noInterrupts();
+  //Set Mode: Phase and Frequency correct PWM (stops the timer)
+  TCCR1A = 0;                 //Set Mode (bit 1A)
+  TCCR1B = bit(WGM13);        //Set Mode (bit 1B)
+  TIMSK1 = bit(TOIE1);        //Enable Overflow ISR
   interrupts();
-
-  if (current >= previous)
-  {
-    duration = current - previous + tachTrim;
-  }
+}
+
+void startTimer1(unsigned long microseconds)
+{
+  char clockSelectBits;
+  short pwmPeriod;
+
+  //Calculate clock select bits
+  const unsigned long cycles = (F_CPU / 2000000) * microseconds;
+  if (cycles < TIMER1_RESOLUTION)
+  {
+    //No Prescaling
+    clockSelectBits = bit(CS10);
+    pwmPeriod = cycles;
+  }
+  else if (cycles < TIMER1_RESOLUTION * 8)
+  {
+    //Prescale by /8
+    clockSelectBits = bit(CS11);
+    pwmPeriod = cycles / 8;
+  }
+  else if (cycles < TIMER1_RESOLUTION * 64)
+  {
+    //Prescale by /64
+    clockSelectBits = bit(CS11) | bit(CS10);
+    pwmPeriod = cycles / 64;
+  }
+  else if (cycles < TIMER1_RESOLUTION * 256)
+  {
+    //Prescale by /256
+    clockSelectBits = bit(CS12);
+    pwmPeriod = cycles / 256;
+  }
+  else if (cycles < TIMER1_RESOLUTION * 1024)
+  {
+    //Prescale by /1024
+    clockSelectBits = bit(CS12) | bit(CS10);
+    pwmPeriod = cycles / 1024;
+  }
   else
   {
-    //Handle Rollover
-    duration = 0xFFFFFFFFu - previous + current + tachTrim;
-  }
-
-  //Shift the values
-  tachDuration2 = tachDuration1;
-  tachDuration1 = tachDuration0;
-  tachDuration0 = duration;
-
-  //Calculate RPM
-  //rpm = getRPM();
-}
-
-void ISR_ACTIVE()
-{
-  //Set the active global variable
-  active = digitalRead(ACTIVATION_PIN) == LOW;
-}
-
-void ISR_IGNITION()
-{
-  //Advance the Mode
-  ignitionMode = nextMode(ignitionMode);
-  updateTimer = true;
-}
-
-// -------------------------
-// Generic Utility Functions
-// -------------------------
-void delayFixed(long ms)
-{
-  if (ms <= 0)
-    return;
-  else if (ms < 16)
-    delayMicroseconds(ms * 1000);
-  else
-    delay(ms);
+    //Out of bounds, use maximum prescaler
+    clockSelectBits = bit(CS12) | bit(CS10);
+    pwmPeriod = TIMER1_RESOLUTION - 1;
+  }
+
+  noInterrupts();
+  TCNT1 = 1;                             //Resets the counter
+  ICR1 = pwmPeriod;                      //Sets the Period
+  //Set Mode: Phase and Frequency correct PWM (Starts the timer)
+  TCCR1A = 0;                            //Set Mode (bit 1A)
+  TCCR1B = bit(WGM13) | clockSelectBits; //Set Mode (bit 1B)
+  //unsigned int tcnt1;
+  //do {  // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt
+  //  tcnt1 = TCNT1;
+  //} while (tcnt1==0);
+  interrupts();
+}
+
+void stopTimer1()
+{
+  noInterrupts();
+  //Set Mode: Phase and Frequency correct PWM (stops the timer)
+  TCCR1A = 0;                 //Set Mode (bit 1A)
+  TCCR1B = bit(WGM13);        //Set Mode (bit 1B)
+  interrupts();
 }

 long readInternalTemp()
@@ -366,7 +480,7 @@
   long result;
   // Read temperature sensor against 1.1V reference
   ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
-  delay(2); // Wait for Vref to settle
+  delayFixed(2); // Wait for Vref to settle
   ADCSRA |= _BV(ADSC); // Convert
   while (bit_is_set(ADCSRA,ADSC));
   result = ADCL;
@@ -380,7 +494,7 @@
   long result;
   // Read 1.1V reference against AVcc
   ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
-  delay(2); // Wait for Vref to settle
+  delayFixed(2); // Wait for Vref to settle
   ADCSRA |= _BV(ADSC); // Convert
   while (bit_is_set(ADCSRA,ADSC));
   result = ADCL;


Minor AP stuff

Minor AP stuff

--- espgc/ESPGC.ino
+++ espgc/ESPGC.ino
@@ -328,22 +328,26 @@
 // **************************************************************************************
 // Wireless Setup

+// MUST access with 192.168.0.1/index.html (NOT 192.168.0.1!!)
 int startAP(String ssid) {
   logger.println("Starting as AP...");
   WiFi.mode(WIFI_AP);
   WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
-  WiFi.softAP(ssid.c_str(), NULL);
-  logger.printf(" SSID: %s\n", ssid.c_str());
-  logger.printf(" IP:   %s\n", ipString(apIP).c_str());
-  return 1;
+  if (WiFi.softAP(ssid.c_str())) {
+    logger.printf(" SSID: %s\n", ssid.c_str());
+    logger.printf(" IP:   %s\n", ipString(apIP).c_str());
+    return 1;
+  } else {
+    logger.printf("*** FAILED ***");
+    return 0;
+  }
 }

 int startInfra(String ssid, String passphrase, int dhcp, IPAddress staticIp, IPAddress gatewayIp, IPAddress subnetMask) {
   IPAddress ipAddr;
   time_t ms;
   bool OK = true;
-
-
+
   WiFi.mode(WIFI_STA);

   if (!WiFi.begin(ssid.c_str(), passphrase.c_str())) {
@@ -562,7 +566,7 @@
       status->set(Status::wifi);
     } else {
       logger.printf("\nCould not connect to network!\n");
-      startAP(config->ssid);
+      startAP("ESP_" + MACString); // don't use ssid; may conflict
       status->set(Status::ap);
     }


Balancer example: Updated the song.

Balancer example: Updated the song.

--- examples/Balancer/Balancer.ino
+++ examples/Balancer/Balancer.ino
@@ -50,7 +50,7 @@
   "a-r gr g-gg-f er e-r d4 e-4"
   "gr msd8d8ml d-4d4"
   "l32efg-gl8r msd8d8ml d-4d4"
-  "cd-de-efg-g l32fg-ga-l8r gr g-4 gr";
+  "<bcd-d e-efg- ga-ab- a4 gr";

 void playSong()
 {


Correct data from accelerometer and magnetometer with gyroscope and a complementary filter

--- Vertex.ino
+++ Vertex.ino
@@ -37,6 +37,14 @@
 SensorError sensorError = {0, 0, 0};
 boolean calibrating = true;

+struct Attitude {
+  float pitch;
+  float roll;
+  float yaw;
+};
+Attitude attitude;
+unsigned long lastAttitudeUpdate = 0;
+
 Adafruit_10DOF                dof   = Adafruit_10DOF();
 Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(30301);
 Adafruit_LSM303_Mag_Unified   mag   = Adafruit_LSM303_Mag_Unified(30302);
@@ -47,10 +55,12 @@
   Serial.begin(115200);

   // Initialize sensors
-  if (!accel.begin() || !mag.begin() || !bmp.begin()) {
+  if (!accel.begin() || !mag.begin() || !bmp.begin() || !gyro.begin()) {
     fatalError();
     while(true);
   }
+  // Enable auto-ranging
+  gyro.enableAutoRange(true);

   ESC1.attach(5);
   ESC2.attach(6);
@@ -93,8 +103,9 @@
   }
   // Calibrate accelerometer
   const unsigned short trials = 20;
+  sensors_vec_t sensorData;
   for (int trial = 0; trial < trials; trial++) {
-    sensors_vec_t sensorData = getOrientation();
+    sensorData = getOrientation();
     sensorError.pitch += (float)sensorData.pitch;
     sensorError.roll += (float)sensorData.roll;
     sensorError.elevation += getAltitude();
@@ -104,6 +115,12 @@
   sensorError.roll /= trials;
   sensorError.elevation /= trials;
   calibrating = false;
+
+  sensorData = getOrientation();
+  attitude.pitch = sensorData.pitch;
+  attitude.roll = sensorData.roll;
+  attitude.yaw = sensorData.heading;
+  lastAttitudeUpdate = millis();

   digitalWrite(armLED, HIGH);
 }
@@ -112,17 +129,42 @@
   setThrottleAll(minThrottle);

   sensors_vec_t orientation = getOrientation();
-  float altitude = getAltitude();
-  Serial.print(F("Roll: "));
-  Serial.print(orientation.roll);
-  Serial.print(F(";\tPitch: "));
-  Serial.print(orientation.pitch);
-  Serial.print(F(";\tHeading: "));
-  Serial.print(orientation.heading);
-  Serial.print(F(";\tAltitude: "));
-  Serial.println(altitude);
-}
-
+  updateAttitude();
+  //float altitude = getAltitude();
+  Serial.print(F("Yaw: "));
+  Serial.print(attitude.yaw);
+  Serial.print(F(";\tRaw heading: "));
+  Serial.println(orientation.heading);
+
+  // When pitch is positive, decrease motors 1 and 4; increase 2 and 3
+
+  // When roll is positive, decrease motors 3 and 4; increase 1 and 2
+}
+
+void updateAttitude() {
+  unsigned int elapsedTime = millis() - lastAttitudeUpdate;
+  float elapsedSeconds = elapsedTime * 0.001;
+  sensors_vec_t orientation = getOrientation();
+  // X corresponds to pitch, Y corresponds to roll, Z corresponds to yaw
+  sensors_vec_t gyroData = getGyro();
+  // Convert rad/s to degrees/s to match accelerometer's units
+  gyroData.x *= (180 / PI);
+  gyroData.y *= (180 / PI);
+  gyroData.z *= (180 / PI);
+
+  // angle = 0.98 * (angle + gyroData * dt) + 0.02 * (accData)
+  attitude.pitch = 0.98 * (attitude.pitch + gyroData.x * elapsedSeconds) + 0.02 * orientation.pitch;
+  attitude.roll = 0.98 * (attitude.roll + gyroData.y * elapsedSeconds) + 0.02 * orientation.roll;
+  // Immediately correct when compass switches between -180 and 180 degrees
+  if (abs(orientation.heading - attitude.yaw) > 100) {
+    attitude.yaw = orientation.heading;
+  }
+  else {
+    attitude.yaw = 0.98 * (attitude.yaw + gyroData.z * elapsedSeconds) + 0.02 * orientation.heading;
+  }
+  lastAttitudeUpdate = millis();
+  delay(5);
+}
 sensors_vec_t getOrientation() {
   sensors_event_t accelEvent;
   sensors_event_t magEvent;
@@ -141,6 +183,14 @@
   orientation.heading = -orientation.heading;
   return orientation;
 }
+sensors_vec_t getGyro() {
+  sensors_event_t gyroEvent;
+  gyro.getEvent(&gyroEvent);
+  gyroEvent.gyro.x = -gyroEvent.gyro.x;
+  gyroEvent.gyro.y = -gyroEvent.gyro.y;
+  gyroEvent.gyro.z = -gyroEvent.gyro.z;
+  return gyroEvent.gyro;
+}
 float getAltitude() {
   sensors_event_t baroEvent;
   bmp.getEvent(&baroEvent);


added restart check and adjusted drift time

--- SprayCan/SprayCanProject/SprayCanProject.ino
+++ SprayCan/SprayCanProject/SprayCanProject.ino
@@ -90,6 +90,42 @@
     rtcStore[2] = 0;
     system_rtc_mem_write(RTC_BASE, rtcStore, 3);
     rtcEndTime = 0;
+  }
+  else {
+    struct rst_info *info;
+    info = system_get_rst_info();
+    int reason = info->reason;
+
+    if (reason == 0) {
+      Serial.println("REASON 0 - REASON_DEFAULT_RST");
+    }
+    if (reason == 1) {
+      Serial.println("REASON 1 - REASON_WDT_RST");
+    }
+    if (reason == 2) {
+      Serial.println("REASON 2 - REASON_EXCEPTION_RST");
+    }
+    if (reason == 3) {
+      Serial.println("REASON 3 - REASON_SOFT_WDT_RST");
+    }
+    if (reason == 4) {
+      Serial.println("REASON 4 - REASON_SOFT_RESTART");
+    }
+    if (reason == 5) {
+      Serial.println("REASON 5 - REASON_DEEP_SLEEP_AWAKE");
+    }
+    if (reason == 6) {
+      Serial.println("REASON 6 - REASON_EXT_SYS_RST ");
+    }
+
+    if (reason == 6) {
+      rtcStore[0] = 123;
+      rtcStore[1] = STATE_HOUSKEEPING;
+      rtcStore[2] = 0;
+      system_rtc_mem_write(RTC_BASE, rtcStore, 3);
+      Serial.println("Reset button press detected.");
+    }
+
   }

   switch (rtcStore[1]) {
@@ -134,7 +170,7 @@
     case STATE_SLEEP_WAKE:
       if (rtcStore[2] < 48) {
         doWork();
-        nextSleep = nextSleep + 26000000;
+        nextSleep = nextSleep + 24000000;

       } else {
         if (connectToInternet()) {
@@ -166,7 +202,7 @@
         }
         nextSleep = ONE_HOU_TIME + 137000000;
       }
-      if (rtcStore[2] >= 59) {
+      if (rtcStore[2] >= 60) {
         rtcStore[1] = STATE_HOUSKEEPING;
         system_rtc_mem_write(RTC_BASE, rtcStore, 3);
         nextSleep = 100;
@@ -204,15 +240,20 @@
         if (ESP.getVcc() < 2650) {
           subject = "WARNING: Battery LOW - " + subject;
         }
+
         Serial.println(subject);
         Serial.println(message);
         sendEmail(subject, message);
         disconnectInternet();
+
         rtcStore[1] = STATE_SLEEP_WAKE;
-        if (rtcStore[2] >= 84) {
+        if (rtcStore[2] >= 60) {
           rtcStore[2] = 255;
         }
+
         system_rtc_mem_write(RTC_BASE, rtcStore, 3);
+        ESP.deepSleep(nextSleep, WAKE_RFCAL);
+
       }
       break;
   }


PID and deadreckoning for turning is fixed, but regression test is not yet done

--- arduino_motor/mains/movements.ino
+++ arduino_motor/mains/movements.ino
@@ -52,7 +52,7 @@

       midPID.Compute();
       const double COEFFICIENT = 1;
-      SetpointRight = PID_SETPOINT * isM2Forward + COEFFICIENT * isM2Forward * map(OutputMid,-PID_SETPOINT/2, PID_SETPOINT/2, -PID_SETPOINT, +PID_SETPOINT);
+      SetpointRight = PID_SETPOINT + COEFFICIENT * map(OutputMid,-PID_SETPOINT/2, PID_SETPOINT/2, -PID_SETPOINT, +PID_SETPOINT);
       rightPID.Compute();
       leftPID.Compute();

@@ -130,8 +130,10 @@
   resetPololuTicks(); theta = 0; // error theta
   const int isLeftForward = 1;
   const int isRightForward = -1;
+  /*
   SetpointLeft *= isLeftForward;
   SetpointRight *= isRightForward;
+  */
   //float noOfTicksForAngle = turnAngleR(angle);
   float noOfTicksForAngle = (WHEELS_INTERVAL/2)*(PI/180)*(angle/DISTANCE_PER_TICK_CM);
   // ------ Angle to ticks formula ------- //
@@ -159,8 +161,10 @@
   retore motor configuration
   */
   resetPololuTicks();
+  /*
   SetpointLeft *= isLeftForward;
   SetpointRight *= isRightForward;
+  */
   /*
   In position turning, deltaY and deltaX suppposed to be 0
   deltaY = 0;


Simplified ScanNetwork example

Simplified ScanNetwork example

Fixes #3629

--- libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino
+++ libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino
@@ -39,17 +39,13 @@

   // Print WiFi MAC address:
   printMacAddress();
+}

+void loop() {
   // scan for existing networks:
   Serial.println("Scanning available networks...");
   listNetworks();
-}
-
-void loop() {
   delay(10000);
-  // scan for existing networks:
-  Serial.println("Scanning available networks...");
-  listNetworks();
 }

 void printMacAddress() {


Setup an AP wit the AT commands.

Setup an AP wit the AT commands.

--- ESP8266_SET_AP.ino
+++ ESP8266_SET_AP.ino
@@ -206,5 +206,3 @@
   digitalWrite(LEDPIN,led_value);
 }

-
-


Update link to ESP8266 article

Update link to ESP8266 article

--- examples/Boards_WiFi/ESP8266_Shield/ESP8266_Shield.ino
+++ examples/Boards_WiFi/ESP8266_Shield/ESP8266_Shield.ino
@@ -22,8 +22,8 @@
   to connect your project to Blynk.

   WARNING!
-    It's rather tricky to get it working, please read this article:
-    https://github.com/blynkkk/blynk-library/wiki/ESP8266-with-AT-firmware
+    It's very tricky to get it working. Please read this article:
+    http://help.blynk.cc/hardware-and-libraries/arduino/esp8266-with-at-firmware

   Change WiFi ssid, pass, and Blynk auth token to run :)
   Feel free to apply it to any other example. It's simple!


Fixed pins

Fixed pins

--- battlestation/arduino/arduino.ino
+++ battlestation/arduino/arduino.ino
@@ -25,7 +25,7 @@
 #define SCORE_STRIP_LEDS 60

 static Adafruit_NeoPixel * score_strips[SCORE_STRIPS];
-static byte score_pins[] = {9, 10, 11, 1};
+static byte score_pins[] = {9, 10, 11, 12};

 #define TEAMS 3
 static uint32_t team_colors[TEAMS];


Remove extraneous #includes

Remove extraneous #includes

--- examples/M41T00S_example/M41T00S_example.ino
+++ examples/M41T00S_example/M41T00S_example.ino
@@ -22,7 +22,6 @@
 */

-#include <Wire.h>
 #include <i2c_rtc_m41t00s.h>


Fixing build issue w/NoisePlayground on due

--- examples/NoisePlayground/NoisePlayground.ino
+++ examples/NoisePlayground/NoisePlayground.ino
@@ -11,7 +11,7 @@
 CRGB leds[kMatrixWidth * kMatrixHeight];

 // x,y, & time values
-uint32_t x,y,time,hue_time;
+uint32_t x,y,v_time,hue_time;

 // Play with the values of the variables below and see what kinds of effects they
 // have!  More octaves will make things slower.
@@ -38,7 +38,7 @@
 void loop() {
   // fill the led array 2/16-bit noise values
   fill_2dnoise16(LEDS.leds(), kMatrixWidth, kMatrixHeight, kMatrixSerpentineLayout,
-                octaves,x,xscale,y,yscale,time,
+                octaves,x,xscale,y,yscale,v_time,
                 hue_octaves,x,hue_scale,y,hue_scale,hue_time, false);
   LEDS.show();
   LEDS.countFPS();
@@ -46,7 +46,7 @@
   // adjust the intra-frame time values
   x += x_speed;
   y += y_speed;
-  time += time_speed;
+  v_time += time_speed;
   hue_time += hue_speed;
 }

@@ -65,7 +65,7 @@

   x = (uint32_t)((uint32_t)random16() << 16) | random16();
   y = (uint32_t)((uint32_t)random16() << 16) | random16();
-  time = (uint32_t)((uint32_t)random16() << 16) | random16();
+  v_time = (uint32_t)((uint32_t)random16() << 16) | random16();
   hue_time = (uint32_t)((uint32_t)random16() << 16) | random16();

 }


workaround change revert

workaround change revert

--- f_ATmegaTimer.ino
+++ f_ATmegaTimer.ino
@@ -29,7 +29,6 @@

 void StartSyncSignal(int vidmode)
 {
-  static boolean firsttime = true;
   noInterrupts();
   // Note: ATmega2560's fast PWM is buggy.
   //   1. fast PWM mode 15 doesn't work unless TOP < 256.
@@ -48,16 +47,11 @@
   ICR5 = syncTime[vidmode][SYNC_TIME_VSYNC] - 1; // TOP
   TCCR5B |= _BV(CS52) | _BV(CS51); // CS5[2:0] = 6 (external clock source on T5. clock on falling edge)

-  if (firsttime) {
-    // * using an external clock source ATmega2560 has a bug that causes the first match ignored
-    // WORKAROUND: toggle T5 to go beyond the first
-    for (int i = 0; i < syncTime[vidmode][SYNC_TIME_VSYNC]; i++) {
-      TCCR4C |= _BV(FOC4C); TCCR4C |= _BV(FOC4C);
-    }
-    firsttime = false;
+  // * using an external clock source ATmega2560 has a bug that causes the first match ignored
+  // WORKAROUND: toggle T5 to go beyond the first
+  for (int i = 0; i < syncTime[vidmode][SYNC_TIME_VSYNC] + 1; i++) {
+    TCCR4C |= _BV(FOC4C); TCCR4C |= _BV(FOC4C);
   }
-
-  TCCR4C |= _BV(FOC4C); TCCR4C |= _BV(FOC4C);

   if (syncTime[vidmode][SYNC_TIME_STRETCH] != 0) {
     // number of ticks the 2nd last HSYNC before VSYNC longer than others
@@ -75,7 +69,7 @@
   // the following registers can be set properly only after WGMn is set
   OCR4B = syncTime[vidmode][SYNC_TIME_HSYNC] - 3; // MATCH
   OCR4C = syncTime[vidmode][SYNC_TIME_HSYNC] - 5; // ADVANCE MATCH
-  TCNT4 = syncTime[vidmode][SYNC_TIME_HSYNC] - 6; // START
+  TCNT4 = syncTime[vidmode][SYNC_TIME_HSYNC] - 7; // START
   ICR4 = syncTime[vidmode][SYNC_TIME_HSYNC] - 1; // TOP
   interrupts();
   TCCR4B |= _BV(CS40); // CS4[2:0] = 1 (no prescaling)


get perlin generator to look cool and glitchy with a few colors chasing eachother

--- src/particle/perlin-noise-ring/perlin-noise-ring.ino
+++ src/particle/perlin-noise-ring/perlin-noise-ring.ino
@@ -20,7 +20,7 @@
 //define LED_PIN D6
 #define LED_PIN 6
 #define NUM_LEDS 24
-int BRIGHTNESS = 96;
+int BRIGHTNESS = BRIGHTNESS_MED;
 #define LED_TYPE WS2812B
 #define COLOR_ORDER GRB

@@ -29,11 +29,11 @@
 float xOffsets[NUM_LEDS];
 float yOffsets[NUM_LEDS];

-const int speedH = 1;   //Hue value is 16-bit
+const int speedH = 2;   //Hue value is 16-bit
 const int scaleH = 10; // 50
 const int speedS = 3;
 const int scaleS = 15;
-const int speedV = 10;
+const int speedV = 1;
 const int scaleV = 50; // 50

 float colorStart = 0;
@@ -41,7 +41,7 @@
 float colorSpeed = .05;    //Speed of color cycling (def: .1)
 const int colorMax = 255;

-String mode = "COMPLEMENTARY"; // options 1: normal, 2: complementary, 3: triad
+String mode = "TRIAD"; // options 1: normal, 2: complementary, 3: triad

 // The leds
 CRGB leds[NUM_LEDS];


Added debug message OTA server started.

Added debug message OTA server started.

--- src/_ota.ino
+++ src/_ota.ino
@@ -20,6 +20,8 @@
   ArduinoOTA.setPort(OTA_PORT);
   ArduinoOTA.setHostname(cfg.hostname);
   ArduinoOTA.setPassword(ADMIN_PASSWORD);
+
+  DEBUGLOG("[OTA] Server running at %s:%u\n", ArduinoOTA.getHostname().c_str(), OTA_PORT);

   ArduinoOTA.onStart([]() { DEBUGLOG("[OTA] Start\n"); });


Fully working version

Fully working version

Auto-Dim issue appears to be caused by voltage drop.   At very low power
there are no issues.  Adding addition power (via potentiometer or
photocell) causes the same issues.

Therefore, I assume the code is fine and that I need to create a 'star'
topology for my power connections.

--- jacksclock12/jacksclock12.ino
+++ jacksclock12/jacksclock12.ino
@@ -2,7 +2,7 @@
 //
 //    Jack's 4:20 Clock
 //    Last Update: 9-7-2014
-//    Version 0.9
+//    Version 0.95
 //    Written for Arduino Uno Rev. 3
 //    Adafruit Hardware: Real Time Clock: DS1307, Neopixel (40 RGB-LED) Shield,
 //    7-Segment Display, 14-Segment Aphanumeric Display, Backlight Module
@@ -125,6 +125,7 @@
   disp.print(getDecimalTime());          // Show 12-Hour Time (7 Segment)
   displayDay();                          // Show Weekday: 14 Segment
   blinkColon();                          // Blink Colon
+  smooth();
   adjustBrightness();                    // Check Switch & Adjust brightness
   fourTwentyCheck();                     // Check if 4:20pm & Run Alarm
   reminderSwitch();                      // LED / Reminder
@@ -156,7 +157,7 @@
   int minPlusState = digitalRead(minPlusButton);
   int minMinusState = digitalRead(minMinusButton);

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

-  if (hourMinusState == HIGH)
+  if (hourMinusState == HIGH)                                   // Hour- Button
   {
     hourCount--;
     adjustedHour = hourCount * 100;
@@ -172,7 +173,7 @@
     delay(bounceDelay);
   }

-  if (minPlusState == HIGH)
+  if (minPlusState == HIGH)                                      // Minute+ Button
   {
     if (now.minute() > 59) minuteCount = 0;
     adjustedMinute = minuteCount + 1;
@@ -181,7 +182,7 @@
   }

-  if (minMinusState == HIGH)
+  if (minMinusState == HIGH)                                     // Minute- Button
   {
     if (now.minute() < 1) minuteCount = 0;
     adjustedMinute = minuteCount - 1;
@@ -192,11 +193,11 @@
 }

-void displayDay ()                                      // Grab Day Number & Display Letters
+void displayDay ()                                // Grab Day Number & Display Letters
 {
   DateTime now = RTC.now();
   int daynumber = now.dayOfWeek();
-  int slot[] = {0, 1, 2, 3};
+  int slot[] = {0, 1, 2, 3};
   char dayLetters[4];

   char sunday[] =     {'S', 'U', 'N', ' '};
@@ -206,14 +207,14 @@
   char thursday[] =   {'T', 'H', 'U', 'R'};
   char friday[] =     {'F', 'R', 'I', ' '};
   char saturday[] =   {'S', 'A', 'T', ' '};
-
+
   if (daynumber == 0) strcpy (dayLetters, sunday);
   if (daynumber == 1) strcpy (dayLetters, monday);
   if (daynumber == 2) strcpy (dayLetters, tuesday);
   if (daynumber == 3) strcpy (dayLetters, wednesday);
   if (daynumber == 4) strcpy (dayLetters, thursday);
   if (daynumber == 5) strcpy (dayLetters, friday);
-  if (daynumber == 6) strcpy (dayLetters, saturday);
+  if (daynumber == 6) strcpy (dayLetters, saturday);

   for (int n = 0; n < 4; n++) alpha4.writeDigitAscii(slot[n], dayLetters[n]);
   alpha4.writeDisplay();
@@ -241,7 +242,7 @@

 void adjustBrightness()                                          // Brightness Check & Adjust
 {
-  smooth();
+

   int clockKnob = analogRead(clockLightIn);                      // Check & Map Potentiometers/Photocell
   int clockBrightness = map(clockKnob, 0, 1023, 1, 15);
@@ -249,8 +250,8 @@
   int lightBrightness = map(lightKnob, 0, 1023, 5, 255);        // Backlight

   photoCellRead = analogRead(photoCellIn);
-  int autoBright1 = map(autoBrightAverage, 300, 1000, 1, 15);
-  int autoBright2 = map(autoBrightAverage, 300, 1000, 1, 255);
+  int autoBright1 = map(autoBrightAverage, 300, 1023, 1, 15);
+  int autoBright2 = map(autoBrightAverage, 300, 1023, 50, 255);

   autoBrightState = digitalRead(brightSwitchIn);                 // Automatically Adjust Brightness (if Switched ON)
   if (autoBrightState == 1)


Updated IoTDataProvider host address & port

--- hack-o-lantern/code/firmware/application.ino
+++ hack-o-lantern/code/firmware/application.ino
@@ -39,8 +39,8 @@
 * HTTP Client variables
 */
 #define WAIT 30000 // delay between requests in ms
-#define HOST "digitaljunky.io"
-#define PORT 3000
+#define HOST "hack.wearhacks.com"
+#define PORT 80
 String API_KEY = "IOTDATAPROVIDER_APIKEY";
 String PATH = "/clients/payload?key=";
 unsigned int nextTime = 0;    // Next time to contact the server


removed deprecated comments

removed deprecated comments

--- heizung.ino
+++ heizung.ino
@@ -1,12 +1,3 @@
-// 1977
-// 2097
-// 2601
-// 2669
-// 2685
-// 2709
-// 2780
-// 2788
-
 #include <DallasTemperature.h>
 #include <EEPROM.h>
 #include <Ethernet.h>
@@ -17,14 +8,6 @@
 #include <Time.h>

 extern EthernetUDP Udp;
-
-// "Zwangspaerchen"
-// OG WC + UG Treppe
-// OG Bad + UG Keller
-// OG Kind 3 + UG Bad / Dusche
-// OG Flur + UG Hobby
-// OG Kind 2 + OG Eltern
-

 // TODO / Fehler
 // - Unterstützung DHT Hygrometer / Temperatursensor
@@ -812,11 +795,9 @@
     DEBUG{ Serial << F("TemperaturesUploader START") << endl; }
     bool success = ftpOpen();
     if ( success ){
-#if 1
       StringStream dir;
       dir << F("Heizung");
       ftpSetMode( dir.c_str(), FTP_MAKEDIR, true );
-#endif
       StringStream fname;
       //fname << year() << lz(month()) << lz(day()) << '/' << lz(hour()) << lz(minute()) << F(".txt");
       fname << F("Heizung/") << year() << lz(month()) << lz(day()) << F(".txt");
@@ -831,7 +812,6 @@
           }
           ftpClient << endl;
         }
-        //TODO: Zeit wird zu Testzwecken falsch geschrieben!
         ftpClient << lz(day()) << '.' << lz(month()) << '.' << year() << ',' << lz(hour()) << ':' << lz(minute()) << ':' << lz(second());
         ftpClient << ',' << g_totalAmperage << ',' << g_requiredAmperage << ',' << FreeRam();
         for( unsigned short i = 0; i < SENSOR_COUNT; ++i ){
@@ -1306,12 +1286,6 @@
   { "S_DG",                0, { 0x28, 0x98, 0x76, 0xE0, 0x04, 0x00, 0x00, 0x28 } }, //
 };

-// elements = new Actor( pin, name, interval )
-// "pin" is the digital IO pin of the arduino board
-// "interval" is the interval used for PWM control of the connected relais. Typically this is 30 min (= 30*60*1000)
-// "switch_on_surge_amperage" is the amperage during the switch on period
-// "switch_on_surge_duration" is the max. duration in milliseconds of the switch on period
-// "working_amperage" is the amperage when the actor is on and the switch on surge time has elapsed
 Actor* g_actors[ ACTOR_COUNT + 1 ] = {
   //new Actor( 22, "a1", ACTOR_CYCLE_INTERVAL, 0.2f, 60000, 0.075f ),
   new Actor(),


Add HVAC mode for tweeting by other device.

--- hvacMonitor.ino
+++ hvacMonitor.ino
@@ -60,6 +60,7 @@
 String currentTimeDate;               // Time formatted as "0:00AM on 0/0"
 String startTimeDate, stopTimeDate, resetTimeDate;
 int runStatus;                        // Used for graphing. 40 == running. NULL == off.
+String currentStatus;                 // What displays in app. Used solely for sync and recover purposes.

 long currentFilterSec;                // Filter age based on unit runtime in seconds (stored in vPin). Seconds used for finer resolution.
 long currentFilterHours;              // Filter age based on unit runtime in hours.
@@ -68,6 +69,11 @@
 const int filterChangeHours = 300L;   // Duration in hours between filter changes. Up for debate and experimentation!
 bool changeFilterAlarm = FALSE;       // TRUE if filter needs to be changed, until reset.

+long todaysAccumRuntimeSecCooling;    // Seconds that system has been cooling.
+long todaysAccumRuntimeSecHeating;    // Seconds that system has been heating.
+bool dominantMode;                    // FALSE = Cooling. TRUE = Heating.
+bool hvacMode;                        // FALSE = Cooling. TRUE = Heating.
+
 double tempRA, tempSA;                // Return and supply air temperatures

 void setup()
@@ -87,7 +93,7 @@
   }

   // START OTA ROUTINE
-  ArduinoOTA.setHostname("esp8266-HVAC");     // Name that is displayed in the Arduino IDE.
+  ArduinoOTA.setHostname("HVAC-WeMosD1mini");     // Name that is displayed in the Arduino IDE.

   ArduinoOTA.onStart([]() {
     Serial.println("Start");
@@ -122,19 +128,11 @@
   timer.setInterval(1000L, countRuntime);     // Counts blower runtime for daily accumulation displays.
   timer.setInterval(1000L, totalRuntime);     // Counts blower runtime.
   timer.setInterval(1000L, setClockTime);     // Creates a current time with leading zeros.
-  timer.setInterval(500L, alarmTimer);        // Track a cycle start/end time for app display.
+  //timer.setInterval(500L, alarmTimer);      // Alarms for low SA/RA split in heating or cooling.
   timer.setInterval(15432L, phantSend);       // ~15 sec run status updates to Phant runnting on a local Raspberry Pi.
-  //timer.setInterval(30000L, debugVpins);
   timer.setTimeout(100, vsync1);              // Syncs back vPins to survive hardware reset.
-  timer.setTimeout(5000, vsync2);             // Syncs back vPins to survive hardware reset.
-}
-
-void debugVpins()
-{
-  Serial.println(String("V110 local variable (hvacTodaysStartCount) is: ") + hvacTodaysStartCount);
-  Serial.println(String("V111 local variable (todaysAccumRuntimeSec) is: ") + todaysAccumRuntimeSec);
-  Serial.println(String("V112 local variable (yesterdayRuntime) is: ") + yesterdayRuntime);
-  Serial.println(String("V11 local variable (currentFilterSec) is: ") + currentFilterSec);
+  timer.setTimeout(2000, vsync2);             // Syncs back vPins to survive hardware reset.
+  timer.setTimeout(4000, vsync3);             // Syncs back vPins to survive hardware reset.
 }

 void loop()  // To keep Blynk happy, keep most tasks out of the loop.
@@ -144,18 +142,23 @@
   ArduinoOTA.handle();
 }

-void vsync1()
+void vsync2()
 {
   Blynk.syncVirtual(V110);    // hvacTodaysStartCount
   Blynk.syncVirtual(V111);    // todaysAccumRuntimeSec
 }

-void vsync2()
+void vsync3()
 {
   Blynk.syncVirtual(V112);    // yesterdayRuntime
   Blynk.syncVirtual(V11);     // currentFilterSec
 }

+void vsync1()
+{
+  Blynk.syncVirtual(V16);    // currentStatus
+}
+
 BLYNK_WRITE(V110)
 {
   hvacTodaysStartCount = param.asInt();
@@ -174,6 +177,11 @@
 BLYNK_WRITE(V11)
 {
   currentFilterSec = param.asLong();
+}
+
+BLYNK_WRITE(V16)
+{
+  currentStatus = param.asStr();
 }

 void phantSend() {
@@ -364,12 +372,12 @@
   tempSplit = tempRA - tempSA;

   // RETURN AIR
-  if (tempRA >= 0 && tempRA <= 120 && digitalRead(blowerPin) == LOW)        // If temp 0-120F and blower running...
+  if (tempRA >= 0 && tempRA <= 150 && digitalRead(blowerPin) == LOW)        // If temp 0-120F and blower running...
   {
     Blynk.virtualWrite(0, tempRA);                                          // ...display the temp...

   }
-  else if (tempRA >= 0 && tempRA <= 120 && digitalRead(blowerPin) == HIGH)  // ...unless it's not running, then...
+  else if (tempRA >= 0 && tempRA <= 150 && digitalRead(blowerPin) == HIGH)  // ...unless it's not running, then...
   {
     Blynk.virtualWrite(0, "OFF");                                           // ...display OFF, unless...
   }
@@ -379,17 +387,49 @@
   }

   // SUPPLY AIR
-  if (tempSA >= 0 && tempSA <= 120 && digitalRead(blowerPin) == LOW)
+  if (tempSA >= 0 && tempSA <= 150 && digitalRead(blowerPin) == LOW)
   {
     Blynk.virtualWrite(1, tempSA);
   }
-  else if (tempSA >= 0 && tempSA <= 120 && digitalRead(blowerPin) == HIGH)
+  else if (tempSA >= 0 && tempSA <= 150 && digitalRead(blowerPin) == HIGH)
   {
     Blynk.virtualWrite(1, "OFF");
   }
   else
   {
     Blynk.virtualWrite(1, "ERR");
+  }
+
+  if (digitalRead(blowerPin) == LOW) {    // If HVAC is running and...
+    if (tempSA > tempRA && hvacMode == FALSE)       // supply air is warmer than return air...
+    {
+      Blynk.setProperty(V1, "color", "#ff0000");    // Supply is RED
+      Blynk.setProperty(V0, "color", "#04C0F8");    // Return is BLUE
+      hvacMode = TRUE;                              // FALSE = cooling, TRUE =  heating.
+
+      todaysAccumRuntimeSecHeating = todaysAccumRuntimeSecHeating + 2.5;
+    }
+    else if (tempSA <= tempRA && hvacMode == TRUE)
+    {
+      Blynk.setProperty(V1, "color", "#04C0F8");    // Supply is BLUE
+      Blynk.setProperty(V0, "color", "#ff0000");    // Return is RED
+      hvacMode = FALSE;                             // FALSE = cooling, TRUE =  heating.
+
+      todaysAccumRuntimeSecCooling = todaysAccumRuntimeSecCooling + 2.5;
+    }
+  }
+
+  if (todaysAccumRuntimeSecHeating == 0 && todaysAccumRuntimeSecCooling == 0)
+  {
+    Blynk.virtualWrite(38, "NONE");
+  }
+  else if (todaysAccumRuntimeSecHeating < todaysAccumRuntimeSecCooling)
+  {
+    Blynk.virtualWrite(38, "COOL");
+  }
+  else if (todaysAccumRuntimeSecHeating > todaysAccumRuntimeSecCooling)
+  {
+    Blynk.virtualWrite(38, "HEAT");
   }
 }

@@ -397,8 +437,9 @@
 {
   if (resetFlag == TRUE && year() != 1970) {                       // Runs once following Arduino reset/start.
     resetTimeDate = currentTimeDate;
-    Blynk.virtualWrite(16, String("SYSTEM RESET at ") + resetTimeDate);
-    Blynk.setProperty(V16, "color", "#D3435C");
+    Blynk.virtualWrite(16, currentStatus);
+    Blynk.setProperty(V16, "label", String("Current Status:                    SYSTEM RESET at ") + resetTimeDate);
+    Blynk.setProperty(V16, "color", "#808080");
   }

   // Purpose: To keep the display showing a system reset state until the HVAC has turned on or off.
@@ -415,6 +456,7 @@
   if (digitalRead(blowerPin) == HIGH && startFlag == TRUE) {          // OFF, but was running
     stopTimeDate = currentTimeDate;                                   // Set off time.
     Blynk.virtualWrite(16, String("HVAC OFF since ") + stopTimeDate); // Write to app.
+    currentStatus = String("HVAC OFF since ") + stopTimeDate;
     Blynk.setProperty(V0, "color", "#808080");
     Blynk.setProperty(V1, "color", "#808080");
     Blynk.setProperty(V16, "color", "#808080");
@@ -430,8 +472,22 @@
   else if (digitalRead(blowerPin) == LOW && stopFlag == TRUE) {    // RUNNING, but was off
     startTimeDate = currentTimeDate;
     Blynk.virtualWrite(16, String("HVAC ON since ") + startTimeDate);
-    Blynk.setProperty(V0, "color", "#D3435C");  // return air text turns red, and...
-    Blynk.setProperty(V1, "color", "#5F7CD8");
+    currentStatus = String("HVAC ON since ") + startTimeDate;
+
+
+    if (tempSA > tempRA)  // Assumed HEATING mode
+    {
+      Blynk.setProperty(V1, "color", "#ff0000");    // Supply is RED
+      Blynk.setProperty(V0, "color", "#04C0F8");    // Return is BLUE
+      hvacMode = FALSE;                             // FALSE = cooling, TRUE =  heating. Logic swapped on purpose.
+    }
+    else                  // Assumed COOLING mode
+    {
+      Blynk.setProperty(V1, "color", "#04C0F8");    // Supply is BLUE
+      Blynk.setProperty(V0, "color", "#ff0000");    // Return is RED
+      hvacMode = TRUE;                              // FALSE = cooling, TRUE =  heating. Logic swapped on purpose.
+    }
+
     Blynk.setProperty(V16, "color", "#23C48E");

     startFlag = TRUE;
@@ -537,11 +593,12 @@
       yesterdayRuntime = (todaysAccumRuntimeSec / 60);  // Moves today's runtime to yesterday for the app display.
       Blynk.virtualWrite(112, yesterdayRuntime);        // Record yesterday's runtime to vPin.
       todaysAccumRuntimeSec = 0;                        // Reset today's sec timer.
+      todaysAccumRuntimeSecHeating = 0;                 // Reset today's heating and cooling timers.
+      todaysAccumRuntimeSecCooling = 0;
       Blynk.virtualWrite(111, todaysAccumRuntimeSec);
       hvacTodaysStartCount = 0;                         // Reset how many times unit has started today.
       todaysDate = day();
     }
-

     if (yesterdayRuntime < 1)               // Displays yesterday's runtime in app, or 'None' is there's none.
     {
@@ -622,7 +679,6 @@
     trackTrendMinuteFlag = 1;
   }

-
   if (minute() == 1 || minute() == 16 || minute() == 31 || minute() == 46)
   {
     trackTrendMinuteFlag = 0;


Add support for an ABS 'button up' event

--- Accessory_Controller/Accessory_Controller.ino
+++ Accessory_Controller/Accessory_Controller.ino
@@ -29,7 +29,7 @@
 Heated_Jacket_State_t heated_jacket_state = Heated_Jacket_State_Off;
 Aux_Light_State_t aux_light_state = Aux_Light_Off;
 bool status_changed = true;
-bool abs_button_pressed = false;
+bool abs_button_up_event = false;

 /* Arduino Functions */
 void setup()
@@ -44,11 +44,15 @@
   if (status_changed)
   {
       set_aux_light_state();
-      set_heated_jacket_state();
-      if (PRINT_STATUS_TO_SERIAL_CONSOLE) print_status();
+
+      if ( abs_button_up_event )
+      {
+          handle_abs_button_event();
+          abs_button_up_event = false;
+      }
+
       status_changed = false;
-      // TODO:There's a bug here. I should only watch for touch down once, then reset when up
-      abs_button_pressed = false;
+      if ( PRINT_STATUS_TO_SERIAL_CONSOLE ) print_status();
   }
 }

@@ -94,8 +98,12 @@
               if ( new_value != motorcycle_state.abs_button )
               {
                 status_changed = true;
+                if ( motorcycle_state.abs_button == K25_ABS_Button_State_on &&
+                     new_value == K25_ABS_Button_State_off )
+                {
+                    abs_button_up_event = true;
+                }
                 motorcycle_state.abs_button = (K25_ABS_Button_State)new_value;
-                if (motorcycle_state.abs_button == K25_ABS_Button_State_on) abs_button_pressed = true;
               }
           } break;

@@ -140,7 +148,7 @@
 }

 /* State Change Functions */
-void set_accessory_states()
+void handle_abs_button_event()
 {
     set_aux_light_state();
     set_heated_jacket_state();


So what's wrong

So what's wrong

--- src/main.ino
+++ src/main.ino
@@ -1,5 +1,4 @@
-#include "Arduino.h"
-
+#include <Arduino.h>

 int ledPin = 13;                 // LED connected to digital pin 13


Closes #16 Clear invalid session vars and join keys

--- MapTheThings-Arduino/MapTheThings-Arduino.ino
+++ MapTheThings-Arduino/MapTheThings-Arduino.ino
@@ -343,7 +343,38 @@
   }
 }

-void loadSettings() {
+static bool checkBytesSameValue(uint8_t *bytes, uint size, uint16_t flag, uint8_t value, const char *name) {
+  bool same = true;
+  for (uint i = 0; i<size; ++i) {
+    same = same && (bytes[i]==value);
+  }
+  if (same) {
+    Log.Warn(F("Removing %s because it is all %d" CR), name, value);
+    settings.flags &= ~flag;
+  }
+  return same;
+}
+
+static bool checkValidSettings() {
+  bool write = false;
+
+  #define CHECK_BYTES(name, flag)   \
+    if (settings.flags & flag) {    \
+      write = write || checkBytesSameValue(settings.name, sizeof(settings.name), flag, 0x00, #name);  \
+      write = write || checkBytesSameValue(settings.name, sizeof(settings.name), flag, 0xFF, #name);  \
+    }
+
+  CHECK_BYTES(DevAddr, FLAG_DEV_ADDR_SET)
+  CHECK_BYTES(NwkSKey, FLAG_NWK_SKEY_SET)
+  CHECK_BYTES(AppSKey, FLAG_APP_SKEY_SET)
+  CHECK_BYTES(AppKey, FLAG_APP_KEY_SET)
+  CHECK_BYTES(AppEUI, FLAG_APP_EUI_SET)
+  CHECK_BYTES(DevEUI, FLAG_DEV_EUI_SET)
+
+  return write;
+}
+
+static void loadSettings() {
   Log.Info(F("Loading saved settings" CR));
   if (readNVBytes(0, (u1_t *)(&settings), sizeof(settings))) {
     debugLogData("Read bytes from NVRAM", (u1_t *)(&settings), sizeof(settings));
@@ -363,6 +394,7 @@
       write = true;
       #endif
     }
+    write = write || checkValidSettings();
     if (write) {
       debugLogData("Writing updated settings", (u1_t *)(&settings), sizeof(settings));
       saveSettingBytes(0, (u1_t *)(&settings), sizeof(settings));


added better follow routine

added better follow routine

--- h_sumo_search.ino
+++ h_sumo_search.ino
@@ -1,3 +1,4 @@
+
 /*
  * autonomous sumo test 1
  * simple h bridge controlling 2-wheel bot
@@ -11,14 +12,14 @@
 int STBY = 10; //standby

 //Motor A
-int PWMA = 3; //Speed control
-int AIN1 = 9; //Direction
-int AIN2 = 8; //Direction
+int PWMA = 3; //Speed control
+int AIN1 = 8; //Direction
+int AIN2 = 9; //Direction

 //Motor B
-int PWMB = 5; //Speed control
-int BIN1 = 11; //Direction
-int BIN2 = 12; //Direction
+int PWMB = 5; //Speed control
+int BIN1 = 12; //Direction
+int BIN2 = 11; //Direction

 #define leftEcho 2  // left Echo Pin
 #define leftTrig 4  // left Trigger Pin
@@ -26,15 +27,38 @@
 #define rightTrig 6 // right Trigger Pin

 // POSSIBLY CHANGE THIS FOR ARENA SIZE
-int maximumRange = 20; // Maximum range needed
-int minimumRange = 0; // Minimum range needed
-long duration, leftDistance, rightDistance; // Duration used to calculate distance
+int maximumRange = 150; // Maximum range needed
+int minimumRange = 1; // Minimum range needed
+long leftDistance = 1000;
+long rightDistance = 1000;
+long prevLeft;
+long prevRight;
+long durationLeft, cmLeft, inchesLeft, cmRight, inchesRight, durationRight;
+long lD[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+long rD[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+int iterator = 0;

 boolean found = false;  // used for search()
+boolean lost = false;

 boolean tagged = false; // used for follow()
 int rightDirMod = 0;
 int leftDirMod = 0;
+
+//------------------------------
+#define baseSpeed 128
+int leftMod = 0;
+int rightMod = 0;
+int leftSpeed = 0;
+int rightSpeed = 0;
+
+int speedModifier;
+int diff;
+int diffMag;
+
+int leftDir = 0;
+int rightDir = 1;
+//-----------------------------

 void setup(){
   Serial.begin (9600);
@@ -58,7 +82,6 @@

 void loop(){
   search();
-  follow();
 }

 void move(int motor, int speed, int direction){
@@ -94,25 +117,67 @@
 }

 void calcDistance() {
+  if (iterator == 20) {
+    iterator = 0;
+  }
+  prevLeft = leftDistance;
+  prevRight = rightDistance;
 /* The following trigPin/echoPin cycle is used to determine the
  distance of the nearest object by bouncing soundwaves off of it. */
- digitalWrite(leftTrig, LOW);
- delayMicroseconds(2);
- digitalWrite(leftTrig, HIGH);
- delayMicroseconds(10);
- digitalWrite(leftTrig, LOW);
- duration = pulseIn(leftEcho, HIGH);
+// digitalWrite(leftTrig, LOW);
+// delayMicroseconds(2);
+// digitalWrite(leftTrig, HIGH);
+// delayMicroseconds(10);
+// digitalWrite(leftTrig, LOW);
+// duration = pulseIn(leftEcho, HIGH);
  //Calculate the distance (in cm) based on the speed of sound.
- leftDistance = duration/58.2;
+ delay(10);
+  digitalWrite(leftTrig, LOW);
+  delayMicroseconds(5);
+  digitalWrite(leftTrig, HIGH);
+  delayMicroseconds(10);
+  digitalWrite(leftTrig, LOW);
+  pinMode(leftEcho, INPUT);
+  durationLeft = pulseIn(leftEcho, HIGH);
+ leftDistance = durationLeft/58.2;
+
+  delay(10);

- digitalWrite(rightTrig, LOW);
- delayMicroseconds(2);
- digitalWrite(rightTrig, HIGH);
- delayMicroseconds(10);
- digitalWrite(rightTrig, LOW);
- duration = pulseIn(rightEcho, HIGH);
+// digitalWrite(rightTrig, LOW);
+// delayMicroseconds(2);
+// digitalWrite(rightTrig, HIGH);
+// delayMicroseconds(10);
+// digitalWrite(rightTrig, LOW);
+// duration = pulseIn(rightEcho, HIGH);
+  digitalWrite(rightTrig, LOW);
+  delayMicroseconds(5);
+  digitalWrite(rightTrig, HIGH);
+  delayMicroseconds(10);
+  digitalWrite(rightTrig, LOW);
+  pinMode(rightEcho, INPUT);
+  durationRight = pulseIn(rightEcho, HIGH);
  //Calculate the distance (in cm) based on the speed of sound.
- rightDistance = duration/58.2;
+ rightDistance = durationRight/58.2;
+
+// if((leftDistance<minimumRange)||(leftDistance>maximumRange)) {
+//  leftDistance = prevLeft;
+// }
+// if((rightDistance<minimumRange)||(rightDistance>maximumRange)) {
+//  rightDistance = prevRight;
+// }
+
+//button
+//esc code
+
+// iterator++;
+// leftDistance = 0;
+// rightDistance = 0;
+// for (int j= 0; j < 20; j++) {
+//  leftDistance += lD[j];
+//  rightDistance += rD[j];
+// }
+// leftDistance = leftDistance/20;
+// rightDistance = rightDistance/20;
 }

 /*
@@ -121,17 +186,29 @@
 void search() {
   while(!found) {
     // 0 is forward, 1 is backward
-    move(1, 128, 1); //right motor
-    move(2, 128, 0); //left motor
+    move(1, 128, rightDir); //right motor
+    move(2, 128, leftDir); //left motor
     calcDistance();
-    Serial.println(leftDistance);
+    //Serial.print("left: ");
+    Serial.print(leftDistance);
+    Serial.print(",");
     Serial.println(rightDistance);
     delay(10);
-    if((leftDistance <= maximumRange && leftDistance >= minimumRange) ||
+    if(lost) {
+      if(diff>0){//turn right
+        rightDir = 0;
+        leftDir = 1;
+      } else {//turn left
+        rightDir = 1;
+        leftDir = 0;
+      }
+    }
+    if((leftDistance <= maximumRange && leftDistance >= minimumRange) &&
        (rightDistance <= maximumRange && rightDistance >=minimumRange)) {
         found = true;
-        Serial.println("FOUND");
+        //Serial.println("FOUND");
       stop();
+      follow();
       //uncomment for looped testing of search function
       //delay(1000);
       //found = false;
@@ -141,38 +218,37 @@

 void follow() {
   while(!tagged) {
-    //happens every loop
-    move(1, 128, rightDirMod); //right motor with rightDirMod
-    move(2, 128, leftDirMod); //left motor with leftDirMod
-
-    Serial.println(leftDistance);
+    calcDistance();
+    diff = leftDistance - rightDistance;
+    diffMag = abs(diff);
+
+    if(!(leftDistance <= maximumRange && leftDistance >= minimumRange) &&
+       !(rightDistance <= maximumRange && rightDistance >=minimumRange)) {
+        found = false;
+        lost = true;
+        search();
+    }
+
+    if(diff > 0 && diffMag > 2) {
+        leftMod = 50*(diffMag/rightDistance);
+        //Serial.println("R");
+    } else if(diff < 0 && diffMag > 2) {
+        rightMod = 50*(diffMag/leftDistance);
+        //Serial.println("L");
+    } else {
+        leftMod = 50;
+        rightMod = 50;
+        //Serial.println("F");
+    }
+    leftSpeed = baseSpeed + leftMod;
+    rightSpeed = baseSpeed + rightMod;
+    //Serial.print("left: ");
+    Serial.print(leftDistance);
+    Serial.print(",");
     Serial.println(rightDistance);

-    //change dir
-    //0 is forward, 1 is backward
-    if((leftDistance - rightDistance) > 10 ) {
-      //if right sensor is closer, slight turn right
-      rightDirMod = 0;
-      leftDirMod = 1;
-    } else if((leftDistance - rightDistance) < -10) {
-      //if left sensor is closer, slight turn left
-      rightDirMod = 1;
-      leftDirMod = 0;
-    } else {
-      rightDirMod = 0;
-      leftDirMod = 0;
-    }
-    calcDistance();
-    if((leftDistance <= 5 && leftDistance >= minimumRange) ||
-         (rightDistance <= 5 && rightDistance >=minimumRange)) {
-          tagged = true;
-          Serial.println("GOTCHA");
-        stop();
-    }
-    delay(10);
-  }
-  while(true) {
-    stop();
+    move(1, leftSpeed, 0);
+    move(2, rightSpeed, 0);
   }
 }


Update sending pattern for Samsung TV on/off button


set debug mode and write score to serial

--- ir_targets/ir_targets.ino
+++ ir_targets/ir_targets.ino
@@ -1,9 +1,10 @@
 #include <IRremote.h>

 // Constants
-#define BASE_COUNT 2
+#define BASE_COUNT 3
 #define BLUE_LASER 0
 #define RED_LASER 1
+#define DEBUG_MODE true

 // Define all the devices as global variables
@@ -93,17 +94,18 @@

 void recordHit(int index) {
   unsigned int rawbuf_last = results.rawbuf[results.rawlen-1];
-  Serial.print(" rawbuf_last: ");
-  Serial.println(rawbuf_last);

-  if(rawbuf_last < 10)
+  if(rawbuf_last < 10){
     scores[BLUE_LASER]++;
-  else
+    Serial.write('B');
+  } else {
     scores[RED_LASER]++;
-
-  String logger = "hit index: " + String(index);
-  Serial.println(logger);
+    Serial.write('R');
+  }
+
   turnOffReceiver(index);
+  printRawbufLast(rawbuf_last);
+  printHit(index);
   printScores();
 }

@@ -115,4 +117,18 @@
   Serial.println(scores[RED_LASER]);
 }

+void printRawbufLast(unsigned int rawbuf_last) {
+  if(DEBUG_MODE) {
+    Serial.print(" rawbuf_last: ");
+    Serial.println(rawbuf_last);
+  }
+}

+void printHit(int index) {
+  if(DEBUG_MODE) {
+     String logger = "hit index: " + String(index);
+    Serial.println(logger);
+  }
+}
+
+


[Arduino] Refactoring.

[Arduino] Refactoring.

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

--- Arduino/vj-flight-controller/vj-flight-controller.ino
+++ Arduino/vj-flight-controller/vj-flight-controller.ino
@@ -118,13 +118,14 @@
 }

 void readData() {
+  mpuIntStatus = mpu.getIntStatus();
+
   if (mpuIntStatus & 0x02) {
+    checkFifo();
     // read a packet from FIFO
     mpu.getFIFOBytes(fifoBuffer, packetSize);

-    // track FIFO count here in case there is > 1 packet available
-    // (this lets us immediately read more without waiting for an interrupt)
-    //fifoCount -= packetSize;
+    // TODO: Read the lastmost packet from FIFO

     // Get Euler angles in degrees and Acceleration in world-frame
     mpu.dmpGetQuaternion(&q, fifoBuffer);
@@ -240,10 +241,6 @@
   // if programming failed, don't try to do anything
   if (!dmpReady) return;

-  mpuIntStatus = mpu.getIntStatus();
-
-  checkFifo();
-
   readData();

   // blink LED to indicate activity


Make some changes to Arduino code

Make some changes to Arduino code

--- arduinoApp/gardenSketch/gardenSketch.ino
+++ arduinoApp/gardenSketch/gardenSketch.ino
@@ -1,7 +1,8 @@
 /*
 Arduino based self regulating kitchen garden
-
- */
+Created by: Jamie Neubert Pedersen
+version: 1.0
+*/
 #include <DHT.h>
 #include <SoftwareSerial.h>
 #include <Sensirion.h>
@@ -18,7 +19,7 @@
 float soilTemperature = 0;
 float soilMoisture = 0;
 float dewpoint;
-float goodSoilTemperature = 25;
+float goodSoilMoisture = 70;

 // air temperature related setup
 #define DHTPIN 2        // Humidity and temperature sensor pin for DHT22
@@ -40,6 +41,12 @@
 // relay related setup
 #define relayPin1 8
 #define relayPin2 9
+#define relayPin3 10
+
+// booleans for checking if automation is required
+boolean autoMoisture = true;
+boolean autoAirTemperature = true;
+boolean autoLight = true;

 // setup sensor reading interval
 unsigned long then = 0; // initialize previous milliseconds variable
@@ -81,33 +88,60 @@
     sensorReadings();

     // React on sensor values
-    if (airTemperature > goodAirTemperature) // activate fan to cool when the temperature is above the defined good temperature in degrees Celsius
-    {
-      digitalWrite(relayPin1, LOW);
-    }
-    else
-    {
-      digitalWrite(relayPin1, HIGH);
-    }
-
-    if (LDRValue < goodLDRValue) // activate relay 2 when the light intensity is below the defined good light intensity
-    {
-      digitalWrite(relayPin2, LOW);
-    }
-    else
-    {
-      digitalWrite(relayPin2, HIGH);
-    }
+    reactAirTemperature();
+    reactLight();
+    reactMoisture();
+
+
+
+

   }

   digitalWrite(ledPin, LOW);

-  if (bluetooth.find("c")) {
-    int data = bluetooth.parseInt();
-
-    Serial.print("Received: ");
-    Serial.println(data);
+  if (bluetooth.find("t")) {
+    int data = bluetooth.parseInt();
+    setGoodAirTemperature(data);
+  }
+  if (bluetooth.find("w")) {
+    int data = bluetooth.parseInt();
+    setGoodSoilMoisture(data);
+  }
+  if (bluetooth.find("l")) {
+    int data = bluetooth.parseInt();
+    setGoodLDRValue(data);
+  }
+
+  if (bluetooth.find("m")) {
+    int data = bluetooth.parseInt();
+    if (data == 0)
+    {
+      autoAirTemperature = false;
+    }
+    if (data == 1)
+    {
+      autoLight = false;
+    }
+    if (data == 2)
+    {
+      autoMoisture = false;
+    }
+  }
+  if (bluetooth.find("a")) {
+    int data = bluetooth.parseInt();
+    if (data == 0)
+    {
+      autoAirTemperature = true;
+    }
+    if (data == 1)
+    {
+      autoLight = true;
+    }
+    if (data == 2)
+    {
+      autoMoisture = true;
+    }
   }

@@ -125,14 +159,55 @@
   goodAirTemperature = value;
 }

-void setGoodSoilTemperature(float value) {
-  goodSoilTemperature = value;
-}
-
 void setGoodSoilMoisture(float value) {
-  goodLDRValue = value;
+  goodSoilMoisture = value;
 }

 void setGoodLDRValue(float value) {
   goodLDRValue = value;
 }
+
+void reactAirTemperature() {
+  if (autoAirTemperature == false)
+  {
+    return;
+  }
+  if (airTemperature > goodAirTemperature) // activate fan to cool when the temperature is above the defined good temperature in degrees Celsius
+    {
+      digitalWrite(relayPin1, LOW);
+    }
+    else
+    {
+      digitalWrite(relayPin1, HIGH);
+    }
+}
+
+void reactLight() {
+  if (autoLight == false)
+  {
+    return;
+  }
+  if (LDRValue < goodLDRValue) // activate relay 2 when the light intensity is below the defined good light intensity
+    {
+      digitalWrite(relayPin2, LOW);
+    }
+    else
+    {
+      digitalWrite(relayPin2, HIGH);
+    }
+}
+
+void reactMoisture() {
+  if (autoMoisture == false)
+  {
+    return;
+  }
+  if (soilMoisture < goodSoilMoisture) // activate relay 2 when the light intensity is below the defined good light intensity
+    {
+      digitalWrite(relayPin3, LOW);
+    }
+    else
+    {
+      digitalWrite(relayPin3, HIGH);
+    }
+}


Ethernet: UdpNtpClient.ino now uses DNS to connect to the NTP server

--- libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino
+++ libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino
@@ -26,9 +26,9 @@
   0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
 };

-unsigned int localPort = 8888;      // local port to listen for UDP packets
+unsigned int localPort = 8888;       // local port to listen for UDP packets

-IPAddress timeServer(192, 43, 244, 18); // time.nist.gov NTP server
+char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server

 const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message

@@ -108,7 +108,7 @@
 }

 // send an NTP request to the time server at the given address
-unsigned long sendNTPpacket(IPAddress& address)
+unsigned long sendNTPpacket(char* address)
 {
   // set all bytes in the buffer to 0
   memset(packetBuffer, 0, NTP_PACKET_SIZE);


Fix OctoTemp, set up to use esp8266 2.0.1-rc2

--- octotemp/code/OctoTemp/OctoTemp/OctoTemp.ino
+++ octotemp/code/OctoTemp/OctoTemp/OctoTemp.ino
@@ -1,10 +1,4 @@
 #include <ESP8266WiFi.h>
-#include <ESP8266WiFiAP.h>
-#include <ESP8266WiFiGeneric.h>
-#include <ESP8266WiFiMulti.h>
-#include <ESP8266WiFiScan.h>
-#include <ESP8266WiFiSTA.h>
-#include <ESP8266WiFiType.h>
 #include <WiFiClient.h>
 #include <WiFiClientSecure.h>
 #include <WiFiServer.h>


Refactor

Refactor

--- mouse_rat.ino
+++ mouse_rat.ino
@@ -4,54 +4,34 @@
 #include <Adafruit_LSM9DS0.h>
 #include "Adafruit_MPR121.h"

-/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
-   which provides a common 'type' for sensor data and some helper functions.
-
-   To use this driver you will also need to download the Adafruit_Sensor
-   library and include it in your libraries folder.
-
-   You should also assign a unique ID to this sensor for use with
-   the Adafruit Sensor API so that you can identify this particular
-   sensor in any data logs, etc.  To assign a unique ID, simply
-   provide an appropriate value in the constructor below (12345
-   is used by default in this example).
-
-   Connections (For default I2C)
-   ===========
-   Connect SCL to analog 5
-   Connect SDA to analog 4
-   Connect VDD to 5V DC
-   Connect GROUND to common ground
-
-   History
-   =======
-   2014/JULY/25  - First version (KTOWN)
-*/
-
-/* Assign a unique base ID for this sensor */
-
-// 9DOF
-Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0(1005);  // Use I2C, ID #1000
 #define LSM9DS0_XM_CS 10
 #define LSM9DS0_GYRO_CS 9
 #define LSM9DS0_SCLK 13
 #define LSM9DS0_MISO 12
 #define LSM9DS0_MOSI 11

-float xNormal = -3.0;
-float yNormal = 1;
+// LSM9DS0, use I2C, ID #1005
+Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0(1005);
+
+// MPR121, use I2C, ID #1000
+Adafruit_MPR121 cap = Adafruit_MPR121();
+
+float xNormal = -3.0,
+      yNormal = 1,
+      // Clamp inputs to this range (m/s^2)
+      accelMax =  20,
+      accelMin = -20,
+      // Map inputs to this range (pixels)
+      outMin   =  200,
+      outMax   = -200;
+
 float xRange[] = {0,0};
 float yRange[] = {0,0};

-// MPR121
-// You can have up to 4 on one i2c bus but one is enough for testing!
-Adafruit_MPR121 cap = Adafruit_MPR121();
-
 uint16_t lasttouched = 0;
 uint16_t currtouched = 0;

 // Configures the gain and integration time for the TSL2561
-
 void configureSensor(void) {
   // 1.) Set the accelerometer range
   //lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_2G);
@@ -103,12 +83,11 @@
 void dof_setup() {
   if(!lsm.begin()) { while(1); }

-  /* Setup the sensor gain and integration time */
+  // Setup the sensor gain and integration time
   configureSensor();

   // Set a max and min value to not do anything
   // calibrate(accel.acceleration.x, accel.acceleration.y);
-
   sensors_event_t accel, mag, gyro, temp;
   lsm.getEvent(&accel, &mag, &gyro, &temp);
 }
@@ -116,61 +95,49 @@
 void dof_loop() {
   /* Get a new sensor event */
   sensors_event_t accel, mag, gyro, temp;
-
   lsm.getEvent(&accel, &mag, &gyro, &temp);

   float mx, my = 0.0;
-  float accel_x = clamp(accel.acceleration.x, -20, 20);
-  float accel_y = clamp(accel.acceleration.y, -20, 20);
+  float accelX = clamp(accel.acceleration.x, accelMin, accelMax);
+  float accelY = clamp(accel.acceleration.y, accelMin, accelMax);

   if (accel.acceleration.x > xRange[1] || accel.acceleration.x < xRange[0]) {
-    my = map(accel_x - xNormal, -20, 20, 200, -200);
-    mx = map(accel_y - yNormal, -20, 20, 200, -200);
+    my = map(accelX, accelMin, accelMax, outMax, outMin);
+    mx = map(accelY, accelMin, accelMax, outMax, outMin);
   }
   else if (accel.acceleration.y > yRange[1] || accel.acceleration.y < yRange[0]) {
-    my = map(accel_x - xNormal, -20, 20, 200, -200);
-    mx = map(accel_y - yNormal, -20, 20, 200, -200);
+    my = map(accelX, accelMin, accelMax, outMax, outMin);
+    mx = map(accelY, accelMin, accelMax, outMax, outMin);
   }
+
   Mouse.move(mx, my, 0);
-  delay(10);
+  delay(5);
 }

 void mpr_loop() {
- // Get the currently touched pads
+  // Get the currently touched pads
   currtouched = cap.touched();
-
+  checkTouch();
+  // reset our state
+  lasttouched = currtouched;
+}
+
+void checkTouch() {
   for (uint8_t i=0; i < 12; i++) {
     // it if *is* touched and *wasnt* touched before, alert!
-    if ((currtouched & _BV(i)) && !(lasttouched & _BV(i)) ) {
-      Serial.print(i); Serial.println(" touched");
-    }
+    if ( (currtouched & _BV(i)) && !(lasttouched & _BV(i)) ) touchHandler(i);
+
     // if it *was* touched and now *isnt*, alert!
-    if (!(currtouched & _BV(i)) && (lasttouched & _BV(i)) ) {
-      Serial.print(i); Serial.println(" released");
-    }
-  }
-
-  // reset our state
-  lasttouched = currtouched;
-
-  // comment out this line for detailed data from the sensor!
-  return;
-
-  // debugging info, what
-  Serial.print("\t\t\t\t\t\t\t\t\t\t\t\t\t 0x"); Serial.println(cap.touched(), HEX);
-  Serial.print("Filt: ");
-  for (uint8_t i=0; i < 12; i++) {
-    Serial.print(cap.filteredData(i)); Serial.print("\t");
-  }
-  Serial.println();
-  Serial.print("Base: ");
-  for (uint8_t i=0; i < 12; i++) {
-    Serial.print(cap.baselineData(i)); Serial.print("\t");
-  }
-  Serial.println();
-
-  // put a delay so it isn't overwhelming
-  delay(100);
+    if ( !(currtouched & _BV(i)) && (lasttouched & _BV(i)) ) releaseHandler(i);
+  }
+}
+
+void touchHandler(int id) {
+  Serial.print(id); Serial.println(" released");
+}
+
+void releaseHandler(int id) {
+  Serial.print(id); Serial.println(" touched");
 }

 void calibrate(float x, float y) {
@@ -188,7 +155,7 @@
 }

 float clamp(float value, float min_, float max_) {
-  return (value < min_)? min_ : (value > max_)? max_ : value;
+  return (value < min_) ? min_ : (value > max_) ? max_ : value;
 }

 void displaySensorDetails(void) {


Improve address to stage conversion.

Improve address to stage conversion.

--- examples/seq/seq.ino
+++ examples/seq/seq.ino
@@ -165,14 +165,14 @@

   uint8_t address_to_stage()
   {
-    int8_t addr_stage = (int8_t)cv_read(CI1) * 1.6;
+    int8_t addr_stage = (int8_t)(cv_read(CI1) * 1.6);
     if(addr_stage < 0)
     {
       addr_stage = 0;
     }
-    else if(stage > 7)
-    {
-      addr_stage = 7;
+    else if(stage > seq_values.stage_count - 1)
+    {
+      addr_stage = seq_values.stage_count - 1;
     }
     return (uint8_t)addr_stage;
   }


Added example code Servo.h reference.

Added example code Servo.h reference.

--- examples/ExampleFirmware/ExampleFirmware.ino
+++ examples/ExampleFirmware/ExampleFirmware.ino
@@ -4,6 +4,7 @@
  * Copyright (c) 2014, Platypus LLC. All rights reserved.
  */
 #include <adk.h>  // Inform Arduino IDE that we internally use the Android ADK.
+#include <Servo.h>  // Inform Arduino IDE that we internally use the Servo API.
 #include <Platypus.h>

 // Create an instance of the Platypus Controller.


Format

Format

--- camera_box/camera_box.ino
+++ camera_box/camera_box.ino
@@ -6,7 +6,6 @@

 #define DHTPIN 4 // DHT Temp & Humidity Pin
 #define DHTTYPE DHT22   // DHT 22  (AM2302)
-

 const int CAM_01_PIN = 5;
 const int CAM_02_PIN = 6;
@@ -56,48 +55,48 @@
   //           4,1   # Turn fan on
   //          13,0   # Turn led off
   while(Serial.available() > 0){
-      int pin_num = Serial.parseInt();
-      int pin_status = Serial.parseInt();
+    int pin_num = Serial.parseInt();
+    int pin_status = Serial.parseInt();

-      switch(pin_num){
-        case CAM_01_PIN:
-          if(pin_status == 1){
-            turn_camera_on(CAM_01_PIN);
-          } else {
-            turn_camera_off(CAM_01_PIN);
-          }
-          break;
+    switch(pin_num){
+      case CAM_01_PIN:
+      if(pin_status == 1){
+        turn_camera_on(CAM_01_PIN);
+        } else {
+          turn_camera_off(CAM_01_PIN);
+        }
+        break;
         case CAM_02_PIN:
-          if(pin_status == 1){
-            turn_camera_on(CAM_02_PIN);
+        if(pin_status == 1){
+          turn_camera_on(CAM_02_PIN);
           } else {
             turn_camera_off(CAM_02_PIN);
           }
           break;
-        case LED_BUILTIN:
+          case LED_BUILTIN:
           digitalWrite(pin_num, pin_status);
           break;
+        }
       }
-  }

-  Serial.print("{");
+      Serial.print("{");

-  read_accelerometer(); Serial.print(',');
+      read_accelerometer(); Serial.print(',');

-  read_dht_temp(); Serial.print(",");
+      read_dht_temp(); Serial.print(",");

-  Serial.print("\"count\":"); Serial.print(millis());
+      Serial.print("\"count\":"); Serial.print(millis());

-  Serial.println("}");
+      Serial.println("}");

-  delay(1000);
-}
+      delay(1000);
+    }

-/* ACCELEROMETER */
-void read_accelerometer() {
-  /* Get a new sensor event */
-  sensors_event_t event;
-  mma.getEvent(&event);
+    /* ACCELEROMETER */
+    void read_accelerometer() {
+      /* Get a new sensor event */
+      sensors_event_t event;
+      mma.getEvent(&event);
   uint8_t o = mma.getOrientation(); // Orientation

   Serial.print("\"accelerometer\":{");


working version july 3rd

working version july 3rd

--- examples/RoboMagellan6x6/RoboMagellan6x6.ino
+++ examples/RoboMagellan6x6/RoboMagellan6x6.ino
@@ -17,9 +17,9 @@
 const uint8_t ServoPin[]  = {12, 11,  8};//drive, steer, backS; APM 1,2,3 resp.
 const uint8_t RadioPin[]  = {2, 3}; //drive, steer
 const int SCHEDULE_DELAY  = 25;
-const int STEERTHROW	  = 30; //degrees from far turn to center
+const int STEERTHROW	  = 25; //degrees from far turn to center
 const int REVTHROW		  = 20;
-const int MIN_FWD		  = 105;
+const int MIN_FWD		  = 107;
 const int MAX_FWD		  = 115;
 const int REVSPEED        = 75;
 const int STOP_TIME       = 1500;//time to coast to stop
@@ -136,8 +136,7 @@
 		outputAngle = toDeg(atan2(y,x))+90;
 		bound(double(90-STEERTHROW), outputAngle, double(90+STEERTHROW));

-		/*int */speed = (distance*5280.l);//from 7.5 feet to 4.7, slow
-		speed *= speed/2;
+		/*int */speed = (distance*5280.l);
 		speed += 90;
 		bound(MIN_FWD, speed, MAX_FWD);

@@ -163,12 +162,17 @@
 		distance = calcDistance(manager.getTargetWaypoint(), location);
 		if(distance > POINT_RADIUS) return;

-		if(manager.getTargetIndex() < manager.numWaypoints()-1)
+		if(manager.getTargetIndex() < manager.numWaypoints()-1){
+			//backWaypoint = manager.getTargetWaypoint();
 			manager.advanceTargetIndex();
-		else if (manager.loopWaypoints())
+		}
+		else if (manager.loopWaypoints()){
+			//backWaypoint = manager.getTargetWaypoint();
 			manager.setTargetIndex(0);
-		else
+		}
+		else{
 			stop = true;
+		}
 	}
 }

@@ -205,21 +209,24 @@
 }

 void extrapPosition(){
-/*	float dT = millis()-nTime;
+	float dT = millis()-nTime;
 	if(dT < 1000 && !nmea.getWarning()){ //ignore irrational values
 		//3600000 = milliseconds per hour
 		float dTraveled = nmea.getGroundSpeed()*dT/3600000.f;
 		location = extrapPosition(location, trueHeading, dTraveled);
 	}
-	positionChanged();*/
+	positionChanged();
 }

 void positionChanged(){
 	nTime = millis();
 	if(manager.numWaypoints() <= 0) return;

+	distance = calcDistance(manager.getTargetWaypoint(), location);
 	pathHeading = calcHeading(location, manager.getTargetWaypoint());
-	distance = calcDistance(manager.getTargetWaypoint(), location);
+	//if there is a waypoint path, find the line to drive from;
+	//either going to waypoint != to the first
+	//or looping is on
 }

 void readAccelerometer(){


Initial mod for radio

Initial mod for radio

--- examples/RoboMagellan6x6/RoboMagellan6x6.ino
+++ examples/RoboMagellan6x6/RoboMagellan6x6.ino
@@ -7,11 +7,11 @@
 #include "DroneUtils.h"
 #include "GreatCircle.h"

-#define DEBUG
+//#define DEBUG
 #define LEARN_COMPASS_ERROR
 #define UBLOX_GPS_FIX

-const double FILTER_PARAM = .988; //closer to 1 is slower "learning"
+const double FILTER_PARAM = .992; //closer to 1 is slower "learning"
 const double POINT_RADIUS = .01; //in miles, margin for error in rover location
 const int BLUE = 25;
 const int YLLW = 26;
@@ -22,6 +22,9 @@
 const int STEERTHROW = 70; //distance in degrees from far left to far right turn
 const int driveSpeed = 120;

+const int driveInput = 2;
+const int steerInput = 3;
+
 short XSHIFT = 50;
 short YSHIFT = 280;
 short XSCALE = 600;
@@ -32,7 +35,8 @@

 double pathHeading; //all headings are Clockwise=+, -179 to 180, 0=north
 double trueHeading;
-double gpsFoundShift=-70;
+double gpsFoundShift=0;
+double compassHeading;
 double distance;
 double gpsHeading;
 double pitch=0, roll=0; //stores the observed angle from horizontal in x, y axis
@@ -70,6 +74,8 @@
 	#ifdef UBLOX_GPS_FIX
 		Serial1.write(GPS_SETUP, sizeof(GPS_SETUP)); //setup 3DR LEA6 GPS module
 	#endif
+
+	getRadio(driveInput);
 }

 void loop() {
@@ -77,22 +83,44 @@
 #ifndef DEBUG
 	updateGPS();
 #endif
-	if(ttime < millis()){
-		ttime = millis()+200;
-		observeHeading();
-		if(manager.numWaypoints() >= 1 && !nmea.getWarning()){
-			distance = calcDistance(manager.getTargetWaypoint(), location);
-			if(distance > POINT_RADIUS)
-				navigate(manager.getTargetWaypoint());
-			else if(manager.getTargetIndex() < manager.numWaypoints()-1)
-				manager.advanceTargetIndex();
-			else if (manager.loopWaypoints())
-				manager.setTargetIndex(0);
-			else
-				stop();
+	if(!isRadioOn(driveInput)){
+
+
+		if(ttime < millis()){
+			ttime = millis()+200;
+			observeHeading();
+			readAccelerometer();
+
+			if(manager.numWaypoints() >= 1 && !nmea.getWarning()){
+				distance = calcDistance(manager.getTargetWaypoint(), location);
+				if(distance > POINT_RADIUS)
+					navigate(manager.getTargetWaypoint());
+				else if(manager.getTargetIndex() < manager.numWaypoints()-1)
+					manager.advanceTargetIndex();
+				else if (manager.loopWaypoints())
+					manager.setTargetIndex(0);
+				else
+					stop();
+			}
+
+			reportLocation();
 		}
-		readAccelerometer();
-		reportLocation();
+
+
+	} else {
+
+		if(ttime < millis()){
+			ttime = millis()+200;
+			observeHeading();
+			readAccelerometer();
+			reportLocation();
+		}
+
+		int tmp = getRadio(steerInput);
+		steer.write( tmp );
+		backSteer.write( 180-tmp );
+		drive.write( getRadio(driveInput) );
+
 	}
 }

@@ -106,9 +134,11 @@
 	trueHeading += atan( float(angularError)*PI/180 )*(20);
 	location = extrapPosition(location, trueHeading, POINT_RADIUS);
 #else
+
 	steer.write( outputAngle );
 	backSteer.write( 180-outputAngle );
 	drive.write( driveSpeed );
+
 #endif
 }

@@ -129,16 +159,17 @@
 }

 void observeHeading(){
-	double CompassHeading = getHeadingTiltComp(XSHIFT, XSCALE,
+	compassHeading = getHeadingTiltComp(XSHIFT, XSCALE,
 											   YSHIFT, YSCALE,
 											   eigenPitch, eigenRoll);
-	if(!nmea.getWarning()) CompassHeading-=nmea.getMagVar();
+	compassHeading *= -1; //because APM 2.5+ mounts the compass upsideDown
+	if(!nmea.getWarning()) compassHeading-=nmea.getMagVar();

 	if(nmea.getCourse() != 0){
 		gpsHeading = nmea.getCourse();
 		gpsHeading = ((int(gpsHeading)+540)%360)-180;

-		int error = CompassHeading-gpsHeading;
+		int error = compassHeading-gpsHeading;
 		error = ((error+540)%360)-180;

 		#ifdef LEARN_COMPASS_ERROR
@@ -150,7 +181,7 @@
 		#endif
 	}
 #ifndef DEBUG
-	trueHeading = CompassHeading+gpsFoundShift;
+	trueHeading = compassHeading+gpsFoundShift;
 #endif
 }

@@ -168,13 +199,12 @@
 void reportLocation(){
 	manager.sendDataMessage(Protocol::DATA_LATITUDE, location.degLatitude());
 	manager.sendDataMessage(Protocol::DATA_LONGITUDE, location.degLongitude());
-	manager.sendDataMessage(Protocol::DATA_DISTANCE, distance);
-	manager.sendDataMessage(Protocol::DATA_HEADING, trueHeading);
-
 	manager.sendDataMessage(Protocol::DATA_ROLL, roll*180/PI);
 	manager.sendDataMessage(Protocol::DATA_PITCH, pitch*180/PI);
+
+	manager.sendDataMessage(Protocol::DATA_HEADING, pathHeading);
+	manager.sendDataMessage(Protocol::DATA_DISTANCE, compassHeading);
 	manager.sendDataMessage(Protocol::DATA_SPEED, gpsFoundShift);
-	// manager.sendDataMessage(Protocol::DATA_SPEED, nmea.getGroundSpeed());
 }

 void calibrateCompass(){


Time v2 - changed RTC control lib, added hello message

--- time2/time2.ino
+++ time2/time2.ino
@@ -1,28 +1,30 @@
 /*
- Time 2
+ Time v2
  Time and date on lcd display (used rtc timer) with control by keypad 4x4

  Hardware:
  Trickle-Charge Timekeeping Chip DS1302
  http://www.maximintegrated.com/en/products/digital/real-time-clocks/DS1302.html
- http://playground.arduino.cc/Main/DS1302
+ http://playground.arduino.cc/Main/DS1302RTC
  LCD I2C PCF8574
  http://habrahabr.ru/post/219137/
  http://arduino-info.wikispaces.com/file/detail/LiquidCrystal_I2C1602V1.zip/341635514
  Keypad 4x4

  created 18.01.2015
+ modifid 24.01.2015
  by Fust Vitaliy
  with Arduino 1.5.8 (tested on Arduino Uno)
 */
 /*
-Sketch uses 7 374 bytes (22%) of program storage space. Maximum is 32 256 bytes.
-Global variables use 460 bytes (22%) of dynamic memory, leaving 1 588 bytes for local variables. Maximum is 2 048 bytes.
+Sketch uses 14 592 bytes (45%) of program storage space. Maximum is 32 256 bytes.
+Global variables use 422 bytes (20%) of dynamic memory, leaving 1 626 bytes for local variables. Maximum is 2 048 bytes.
 */

 #include <Wire.h>
 #include <LiquidCrystal_I2C.h>
-LiquidCrystal_I2C lcd(0x27, 16, 2);
+#include <CyrI2c.h>
+CyrI2c* lcd;

 #include <Keypad.h>
@@ -41,95 +43,54 @@
 Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

-#define DS1302_SCLK_PIN   11    // Arduino pin for the Serial Clock
-#define DS1302_IO_PIN     12    // Arduino pin for the Data I/O
-#define DS1302_CE_PIN     13    // Arduino pin for the Chip Enable
-#define bcd2bin(h,l)    (((h)*10) + (l))
-#define bin2bcd_h(x)   ((x)/10)
-#define bin2bcd_l(x)    ((x)%10)
-#define DS1302_SECONDS           0x80
-#define DS1302_MINUTES           0x82
-#define DS1302_HOURS             0x84
-#define DS1302_DATE              0x86
-#define DS1302_MONTH             0x88
-#define DS1302_DAY               0x8A
-#define DS1302_YEAR              0x8C
-#define DS1302_ENABLE            0x8E
-#define DS1302_TRICKLE           0x90
-#define DS1302_CLOCK_BURST       0xBE
-#define DS1302_CLOCK_BURST_WRITE 0xBE
-#define DS1302_CLOCK_BURST_READ  0xBF
-#define DS1302_RAMSTART          0xC0
-#define DS1302_RAMEND            0xFC
-#define DS1302_RAM_BURST         0xFE
-#define DS1302_RAM_BURST_WRITE   0xFE
-#define DS1302_RAM_BURST_READ    0xFF
-#define DS1302_D0 0
-#define DS1302_D1 1
-#define DS1302_D2 2
-#define DS1302_D3 3
-#define DS1302_D4 4
-#define DS1302_D5 5
-#define DS1302_D6 6
-#define DS1302_D7 7
-#define DS1302_READBIT DS1302_D0
-#define DS1302_RC DS1302_D6
-#define DS1302_CH DS1302_D7
-#define DS1302_AM_PM DS1302_D5
-#define DS1302_12_24 DS1302_D7
-#define DS1302_WP DS1302_D7
-#define DS1302_ROUT0 DS1302_D0
-#define DS1302_ROUT1 DS1302_D1
-#define DS1302_DS0   DS1302_D2
-#define DS1302_DS1   DS1302_D2
-#define DS1302_TCS0  DS1302_D4
-#define DS1302_TCS1  DS1302_D5
-#define DS1302_TCS2  DS1302_D6
-#define DS1302_TCS3  DS1302_D7
-typedef struct ds1302_struct{uint8_t Seconds:4;uint8_t Seconds10:3;uint8_t CH:1;uint8_t Minutes:4;uint8_t Minutes10:3;uint8_t reserved1:1;union{struct{uint8_t Hour:4;uint8_t Hour10:2;uint8_t reserved2:1;uint8_t hour_12_24:1;}h24;struct{uint8_t Hour:4;uint8_t Hour10:1;uint8_t AM_PM:1;uint8_t reserved2:1;uint8_t hour_12_24:1;}h12;};uint8_t Date:4;uint8_t Date10:2;uint8_t reserved3:2;uint8_t Month:4;uint8_t Month10:1;uint8_t reserved4:3;uint8_t Day:3;uint8_t reserved5:5;uint8_t Year:4;uint8_t Year10:4;uint8_t reserved6:7;uint8_t WP:1;};void DS1302_clock_burst_read( uint8_t *p){int i;_DS1302_start();_DS1302_togglewrite( DS1302_CLOCK_BURST_READ, true);for( i=0; i<8; i++){*p++ = _DS1302_toggleread();}_DS1302_stop();}void DS1302_clock_burst_write( uint8_t *p){int i;_DS1302_start();_DS1302_togglewrite( DS1302_CLOCK_BURST_WRITE, false);for( i=0; i<8; i++){_DS1302_togglewrite( *p++, false);}_DS1302_stop();}uint8_t DS1302_read(int address){uint8_t data;bitSet( address, DS1302_READBIT);_DS1302_start();_DS1302_togglewrite( address, true);data = _DS1302_toggleread();_DS1302_stop();return (data);}void DS1302_write( int address, uint8_t data){bitClear( address, DS1302_READBIT);_DS1302_start();_DS1302_togglewrite( address, false);_DS1302_togglewrite( data, false);_DS1302_stop();}void _DS1302_start( void){digitalWrite( DS1302_CE_PIN, LOW);pinMode( DS1302_CE_PIN, OUTPUT);digitalWrite( DS1302_SCLK_PIN, LOW);pinMode( DS1302_SCLK_PIN, OUTPUT);pinMode( DS1302_IO_PIN, OUTPUT);digitalWrite( DS1302_CE_PIN, HIGH);delayMicroseconds( 4);}void _DS1302_stop(void){digitalWrite( DS1302_CE_PIN, LOW);delayMicroseconds( 4);}uint8_t _DS1302_toggleread( void){uint8_t i, data;data = 0;for( i = 0; i <= 7; i++){digitalWrite( DS1302_SCLK_PIN, HIGH);delayMicroseconds( 1);digitalWrite( DS1302_SCLK_PIN, LOW);delayMicroseconds( 1);bitWrite( data, i, digitalRead( DS1302_IO_PIN));}return( data);}void _DS1302_togglewrite( uint8_t data, uint8_t release){int i;for( i = 0; i <= 7; i++){digitalWrite( DS1302_IO_PIN, bitRead(data, i));delayMicroseconds( 1);digitalWrite( DS1302_SCLK_PIN, HIGH);delayMicroseconds( 1);if( release && i == 7){pinMode( DS1302_IO_PIN, INPUT);}else{digitalWrite( DS1302_SCLK_PIN, LOW);delayMicroseconds( 1);}}}void ds1302_init(){DS1302_write (DS1302_ENABLE, 0);DS1302_write (DS1302_TRICKLE, 0x00);}ds1302_struct rtc;
+#include <Time.h>
+#include <DS1302RTC.h>
+// Set pins:  CE, IO,CLK
+DS1302RTC RTC(13, 12, 11);

 void setup() {
-  lcd.init();
-  lcd.backlight();
-  lcd.print("     Hello!     ");
+  lcd = new CyrI2c(0x27, 16, 2);
+  lcd->backlight();

-  ds1302_init();
-
-  delay(1500);
+  tmElements_t tm;
+  RTC.read(tm);
+  hello(tm.Hour);
 }

-unsigned long int cur_sec = 0;
+void loop() {
+  tmElements_t tm;
+  RTC.read(tm);

-void loop() {
-  DS1302_clock_burst_read( (uint8_t *) &rtc);
+  lcd->init(F("Нд\rПн\rВт\rСр\rЧт\rПт\rСб"));
+  lcd->printn(tm.Wday - 1, -1, 0);
+  lcd->init(F("січня\rлютого\rберезня\rквітня\rтравня\rчервня\rлипня\rсерпня\rвересня\rжовтня\rлистопада\rгрудня"));
+  lcd->printn(tm.Month - 1, 3, 0);

-  char buffer[16];
+  char buffer[9];
+  buffer[8] = 0;
+  sprintf(buffer, "%02d", tm.Day);
+  lcd->print(buffer, 0, 0);
+  sprintf(buffer, "%02d:%02d:%02d", tm.Hour, tm.Minute, tm.Second);
+  lcd->print(buffer, 4, 1);

-  sprintf(buffer, "    %02d:%02d:%02d   ",
-    bcd2bin( rtc.h24.Hour10, rtc.h24.Hour),
-    bcd2bin( rtc.Minutes10, rtc.Minutes),
-    bcd2bin( rtc.Seconds10, rtc.Seconds));
-  lcd.setCursor(0, 0);
-  lcd.print(buffer);
-
-  sprintf(buffer, "   %02d.%02d.%04d   ",
-    bcd2bin( rtc.Date10, rtc.Date),
-    bcd2bin( rtc.Month10, rtc.Month),
-    2000 + bcd2bin( rtc.Year10, rtc.Year));
-  lcd.setCursor(0, 1);
-  lcd.print(buffer);
-
-  if(millis() - cur_sec > 1000){
-    cur_sec = millis();
-    lcd.setCursor(15, 0);
-    lcd.print(' ');
-  }
-
-  char keypressed = myKeypad.getKey();
-  if(keypressed != NO_KEY){
-    cur_sec = millis();
-    lcd.setCursor(15, 0);
-    lcd.print(keypressed);
+  unsigned long prevtime = RTC.get();
+  while(prevtime == RTC.get()){
+    char keypressed = myKeypad.getKey();
+    if (keypressed != NO_KEY){
+      if (keypressed != 'A') {
+        hello(tm.Hour);
+        break;
+      }
+    }
   }
 }

+void hello(uint8_t hour){
+  lcd->clear();
+  lcd->init(F("Доброї ночі!\rДоброго ранку!\rДоброго дня!\rДоброго вечора!\rЯ годинник :)"));
+  lcd->printn((hour - 1) / 6, 0, 0);
+  lcd->printn(4, 3, 1);
+  delay(3000);
+  lcd->clear();
+}
+


JL LG updating aquario.ino

JL LG updating aquario.ino

--- Aquario.ino
+++ Aquario.ino
@@ -28,10 +28,10 @@
 #define RELAY_ON 1
 #define RELAY_OFF 0

-#define Relay_1  2
-#define Relay_2  3
-#define Relay_3  4
-#define Relay_4  5
+#define Relay_1  2  // purple
+#define Relay_2  3  // white
+#define Relay_3  4  // orange
+#define Relay_4  5  // yellow

 // set temp
 float temp = 30;