Tower now works really well as a drum machine.  Fire and everything.

--- src/Tower/Tower.ino
+++ src/Tower/Tower.ino
@@ -31,7 +31,9 @@
 // but only fire this often.
 Metro flameCoolDownTime(1000UL);
 // there's quite a bit of EMI from the solenoid firing, so we add a cooldown on reading sensors
-Metro sensorEmiCooldown(1000UL);
+#define EMI_COOLDOWN 1000UL
+Metro sensorEmiCooldown(EMI_COOLDOWN);
+boolean emiInterference = true;

 // when we're out of the network, update the lights on this interval (approx)
 #define SOLO_TEST_PATTERN_UPDATE 3000UL // ms
@@ -53,6 +55,8 @@
 #define DEBOUNCE_TIME 50UL // need a long debounce b/c electrical noise from solenoid.
 Bounce systemReset = Bounce(RESET_PIN, DEBOUNCE_TIME);
 Bounce gameEnable = Bounce(GAME_ENABLE_PIN, DEBOUNCE_TIME);
+boolean gameEnableFlag = true;
+boolean systemResetFlag = false;

 // luminosity is not equal among LEDs
 #define RED_MAX 255 // entry 255 in the gamma lookup
@@ -120,14 +124,15 @@
   // SAFETY: do not move this code after any other code.
   if ( flameOnTime.check() ) { // time to turn the flame off
     flameOff();
-    sensorEmiCooldown.reset(); // sensing needs to pause.
-  }
-
-  static boolean gameEnableFlag = gameEnabled();
-  static boolean systemResetFlag = systemReseted();
-
+  }
+
+  // check to see if we can read sensors again after EMI burst.
+  if( sensorEmiCooldown.check() && emiInterference==true ){
+    Serial << F("EMI cooldown ended.") << endl;
+    emiInterference = false;
+  }
   // put all sensor code inside of this cooldown check.
-  if( sensorEmiCooldown.check() ) {
+  if( !emiInterference ) {
     // check system enable state
     if ( systemReset.update() ) { // reset state change
       Serial << F("Reset state change.  State: ");
@@ -186,11 +191,17 @@
     }
   }

-  if ( networkTimeout.check() ) networkTimedOut = true;
+  if ( networkTimeout.check() ) {
+    Serial << F("Network timeout.") << endl;
+    networkTimedOut = true;
+  }

   if ( systemResetFlag ) {
     // if the reset pin is held, turn to red lighting
     redTestPattern();
+    delay(500);
+    whiteTestPattern();
+    delay(500);
   } else if ( networkTimedOut ) {
     // comms are quiet, so some test patterns are appropriate
     if( !gameEnableFlag ) {
@@ -434,6 +445,11 @@
     // start cooldown counter
     flameCoolDownTime.reset();

+    // when the solenoid closes, there's a lot of EMI that disrupts sensors.  Ignore the sensors for a period of time.
+    sensorEmiCooldown.interval( config.flameCoolDownTime + EMI_COOLDOWN ); // add a little more time.
+    sensorEmiCooldown.reset(); // sensing needs to pause.
+    emiInterference = true;
+
     Serial << F("Flame on! ") << fireLevel << F(" mapped [") << config.minFireTime << F(",") << config.maxFireTime << F("]");
     Serial << F(" -> ") << flameTime << F("ms.  Cooldown: ") << config.flameCoolDownTime << F("ms.") << endl;
   }


Delete ExoEthernetGettingStarted.ino

Delete ExoEthernetGettingStarted.ino

--- examples/ExoEthernetGettingStarted.ino
+++ examples/ExoEthernetGettingStarted.ino
@@ -1,207 +0,0 @@
-//*****************************************************************************
-//
-// ExoEthernetGettingStarted - This example is can be used with the "Arduino
-//   Compatible Device" device available in portals.exosite.com.  It uses
-//   provisioning to activate with Exosite instead of using a hard-coded CIK.
-//   By default it does two things, one is reads the A0 analog   value and sends
-//   this to a dataport called A0.  It also makes a read request for a dataport
-//   called D2 and sets the Digital pin 2 to 1 or 0 based on that value.
-//
-//   Developers can feel free to create new dataports to read and write to on the
-//   Exosite platform for their device's client and also then add the code below to
-//   interact with those dataports.
-//
-//   Tested with Arduino UNO SMD R2 and Arduino Ethernet Shield
-//
-// Copyright (c) 2015 Exosite LLC.  All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-//  * Redistributions of source code must retain the above copyright notice,
-//    this list of conditions and the following disclaimer.
-//  * Redistributions in binary form must reproduce the above copyright
-//    notice, this list of conditions and the following disclaimer in the
-//    documentation and/or other materials provided with the distribution.
-//  * Neither the name of Exosite LLC nor the names of its contributors may
-//    be used to endorse or promote products derived from this software
-//    without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
-// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
-// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
-// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
-// DAMAGES, FOR ANY REASON WHATSOEVER.
-//
-//*****************************************************************************
-
-#include <SPI.h>
-#include <EEPROM.h>
-#include <Ethernet.h>
-#include <Exosite.h>
-
-/*==============================================================================
-* Configuration Variables
-*
-* Change these variables to your own settings.
-*=============================================================================*/
-byte macData[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };        // <-- Fill in your Ethernet shield's MAC address here.
-
-// Enter your Unique Identifier code here
-char unique_id[11] = "0024A3D07D"; // <-- Generated from Adding your device in portals.exosite.com
-
-// Use these variables to customize what datasources are read and written to.
-const String readString = "d2";
-
-// Number of Errors before we try a reprovision.
-const unsigned char reprovisionAfter = 3;
-/*==============================================================================
-* End of Configuration Variables
-*=============================================================================*/
-
-unsigned char errorCount = reprovisionAfter;  // Force Provision On First Loop
-char macString[18];  // Used to store a formatted version of the MAC Address
-
-class EthernetClient client;
-Exosite exosite(&client);
-
-String tempString;
-int index = 0;
-int lastIndex = -1;
-
-
-/*==============================================================================
-* setup
-*
-* Arduino setup function.
-*=============================================================================*/
-void setup() {
-  Serial.begin(115200);
-  Serial.println(F("Boot"));
-
-  pinMode(2, OUTPUT); //assume using D2 as output to control remotely
-
-  // Create MAC Address String in the format FF:FF:FF:FF:FF:FF
-  snprintf(macString, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
-           macData[0], macData[1], macData[2], macData[3], macData[4], macData[5]);
-
-  Serial.println(F("setting up Ethernet Connection..."));
-
-  // Setup Ethernet Connection
-  if (Ethernet.begin(macData) == 0) {
-    Serial.println("Failed to configure Ethernet using DHCP");
-    // no point in carrying on, so do nothing forevermore:
-    for (;;)
-      ;
-  }
-
-
-  // Print Some Useful Info
-  Serial.print(F("MAC Address: "));
-  Serial.println(macString);
-
-  Serial.print(F("IP Address: "));
-  Serial.println(Ethernet.localIP());
-
-  Serial.print(F("Unique Identifier: "));
-  Serial.println(unique_id);
-
-  Serial.print(F("Exo Arduino Lib Ver: "));
-  Serial.println(ACTIVATOR_VERSION);
-}
-
-/*==============================================================================
-* loop
-*
-* Arduino loop function.
-*=============================================================================*/
-void loop() {
-  String writeString = "";
-  String returnString = "";
-  index = 0;
-  lastIndex = -1;
-
-
-  // Check if we should reprovision.
-  if (errorCount >= reprovisionAfter) {
-    if (exosite.provision("exosite", "ard-generic", unique_id)) {
-      errorCount = 0;
-    }
-  }
-    String uptime_str = String(millis()/1000);
-  writeString += "uptime="+ uptime_str;
-
-  //GET ANALOG 0 VALUE
-  //get average of a number of readings
-  int avgValue=0;
-  int readings = 0;
-  unsigned long avgTot = 0;
-  int avgCnt = 0;
-
-  while(readings<10)
-  {
-    avgTot += analogRead(A0);
-    avgCnt += 1;
-    avgValue = avgTot/avgCnt;
-    readings++;
-  }
-  String analog0_str = String(avgValue);
-  writeString += "&a0="+ analog0_str;
-
-
-  //Make Write and Read request to Exosite Platform
-  Serial.println("---- Do Read and Write ----");
-  if (exosite.writeRead(writeString, readString, returnString)) {
-    Serial.println("OK");
-    Serial.print("Returned: ");
-    Serial.println(returnString);
-    Serial.println("Parse out dataport alias values");
-    errorCount = 0;
-    for(;;){
-      index = returnString.indexOf("=", lastIndex+1);
-      if(index != 0){
-        String alias = "";
-        tempString = returnString.substring(lastIndex+1, index);
-        Serial.print(F("Alias: "));
-        Serial.println(tempString);
-        lastIndex = returnString.indexOf("&", index+1);
-        alias = tempString;
-        if(lastIndex != -1){
-          tempString = returnString.substring(index+1, lastIndex);
-        }else{
-          tempString = returnString.substring(index+1);
-        }
-
-
-        if (alias == "d2"){
-          if(tempString == "1"){
-            digitalWrite(2, 1);
-            Serial.println("set Digital2 to 1");
-          }else if(tempString == "0"){
-            digitalWrite(2, 0);
-            Serial.println("set Digital2 to 0");
-          }else{
-            Serial.print(F("Unknown Setting: "));
-            Serial.println(tempString);
-          }
-        } else {
-          Serial.println("Unknown Alias Dataport");
-        }
-
-        if(lastIndex == -1)
-          break;
-
-      }else{
-        Serial.println(F("No Index"));
-        break;
-      }
-    }
-
-  } else {
-    Serial.println("No Connection");
-    errorCount++;
-  }
-
-  delay(2000);
-}


Oversample the speed pot. Even better would be to have true hysteresis.

--- code/MotorController/MotorController.ino
+++ code/MotorController/MotorController.ino
@@ -185,7 +185,15 @@

 int ReadPotentiometer(int pin)
 {
-  int value = analogRead(pin);
+  const int numberOfSamples = 5;
+
+  int valueAccumulator = 0;
+  for (int x = 0; x < numberOfSamples; x++)
+  {
+    valueAccumulator += analogRead(pin);
+  }
+
+  int value = valueAccumulator / numberOfSamples;
   value = constrain(value, 0, potentiometerCeiling);

   return value;


corrected eeprom method used

corrected eeprom method used

--- Arduino/Vendomatic/Vendomatic.ino
+++ Arduino/Vendomatic/Vendomatic.ino
@@ -32,10 +32,10 @@
 //Setup the database for the items
 // The read and write handlers for using the EEPROM Library
 void writer(unsigned long address, byte data) {
-    writeEEPROM(address, data);     //external
+    EEPROM.write(address, data);     //external
 }
 byte reader(unsigned long address) {
-    return readEEPROM(address);     //external
+    return EEPROM.read(address);     //external
 }
 // Create an EDB object with the appropriate write and read handlers
 EDB itemDb(&writer, &reader);


Default to non-debug mode to reduce verbose output

--- arduino/DiskInterface/DiskInterface.ino
+++ arduino/DiskInterface/DiskInterface.ino
@@ -52,7 +52,7 @@
 #include "LEDStrip.h"

 // Set to 1 to start in debug mode
-#define DEBUG_MODE 1
+#define DEBUG_MODE 0

 // Top disk
 const int DISK0_HOME_SENSOR = A0;


change start up "circle" loop. end with "neutral" on the 7segment.

--- arduinoTest/USB_FocusST/USB_FocusST.ino
+++ arduinoTest/USB_FocusST/USB_FocusST.ino
@@ -51,7 +51,6 @@
 String inputString = "";
 boolean stringComplete = false;
 boolean USB_connected = false;
-int c = 0;

 void setup() {
   //set pins to output so you can control the shift register
@@ -69,12 +68,11 @@

 void loop() {
   if (!USB_connected) {
-    sendDigit(circle[c]);
-    c++;
-    if (c == 6) {
-      c = 0;
+    for (int c = 0; c < 6; c++) {
+      sendDigit(circle[c]);
+      delay(50);
     }
-    delay(50);
+    sendDigit(all_digits[0]);
   }

   if (stringComplete) {


Get throttle from the NRF24

Get throttle from the NRF24

--- MotorTestNrf24/MotorTestNrf24.ino
+++ MotorTestNrf24/MotorTestNrf24.ino
@@ -112,13 +112,20 @@

   // Prove the main timer is working
   unsigned long now = millis();
-  Serial.println(now);
+  //Serial.println(now);

-  byte pwm = analogRead(PIN_THROTTLE) / 4;
+  //byte pwm = analogRead(PIN_THROTTLE) / 4;
+
+
+  byte pwm = (tx_payload.yaw -1000) / 4;
+  if (pwm < 15) {
+    // Uncalibrated sticks so just oof at low enough value
+    pwm = 0;
+  }

   analogWrite(PIN_MOTOR, pwm);

-  //Serial.println(pwm);
+  //Serial.println();
   //delay(100);
 }


Designated initializers

Designated initializers

Using designated initializers for config in BasicNode example

--- examples/BasicNode/BasicNode.ino
+++ examples/BasicNode/BasicNode.ino
@@ -7,20 +7,25 @@

 ////////////////////////////////////////////////////////////
 ArtConfig config = {
-  {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}, // MAC
-  {2, 3, 4, 5},                         // IP
-  {255, 0, 0, 0},                       // Subnet mask
-  0x1936,                               // UDP port
-  false,                                // DHCP
-  0, 0,                                 // Net (0-127) and subnet (0-15)
-  "ArtNode",                            // Short name
-  "ArtNode",                            // Long name
-  4,                                    // Number of ports
-  {PortTypeDmx | PortTypeOutput, PortTypeDmx | PortTypeOutput, PortTypeDmx | PortTypeOutput, PortTypeDmx | PortTypeOutput}, // Port types
-  {0, 0, 0, 0},                         // Port input universes (0-15)
-  {0, 1, 2, 3},                         // Port output universes (0-15)
-  VERSION_HI,
-  VERSION_LO
+  .mac =  {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}, // MAC
+  .ip =   {2, 3, 4, 5},                         // IP
+  .mask = {255, 0, 0, 0},                       // Subnet mask
+  .udpPort = 0x1936,
+  .dhcp = false,
+  .net = 0, // Net (0-127)
+  .subnet = 0,  // Subnet (0-15)
+  "ArtNode", // Short name
+  "ArtNode", // Long name
+  .numPorts = 4,
+  .portTypes = {
+    PortTypeDmx | PortTypeOutput,
+    PortTypeDmx | PortTypeOutput,
+    PortTypeDmx | PortTypeOutput,
+    PortTypeDmx | PortTypeOutput},
+  .portAddrIn = {0, 0, 0, 0}, // Port input universes (0-15)
+  .portAddrOut = {0, 1, 2, 3}, // Port output universes (0-15)
+  .verHi = VERSION_HI,
+  .verLo = VERSION_LO
 };
 ////////////////////////////////////////////////////////////
 IPAddress gateway(config.ip[0], 0, 0, 1);


diff intensities for red, green, yellow

diff intensities for red, green, yellow

--- examples/SX_Signal/SX_Signal.ino
+++ examples/SX_Signal/SX_Signal.ino
@@ -32,7 +32,9 @@

 #ifdef PWM_ON
 #include "SoftPWM_SX12.h"
-
+#define RED_ON     100
+#define GREEN_ON   100
+#define YELLOW_ON  255
 #endif

 #include <SX22b.h>   // this is the Selectrix library
@@ -127,7 +129,7 @@
   // switch red(hp0) on for all signals
   for (uint8_t j = 0; j < N_SIG; j++) {
     last[j] = 0;
-    SoftPWMSet(sig[j][0], 255);
+    SoftPWMSet(sig[j][0], RED_ON);
   }

@@ -324,29 +326,29 @@
       if ((last[nsig] == 1) || (last[nsig] == 2) ) {
         SoftPWMSet(sig[nsig][last[nsig]], 0);
       }
-      SoftPWMSet(sig[nsig][state], 255);  // red on
+      SoftPWMSet(sig[nsig][state], RED_ON);  // red on
       break;
     case 1:
       if (last[nsig] ==  2) {
         SoftPWMSet(sig[nsig][last[nsig]], 0);
         delay(200);
         // first switch to red
-        SoftPWMSet(sig[nsig][0], 255);  // red on
+        SoftPWMSet(sig[nsig][0], RED_ON);  // red on
         delay(1000);
       }
       SoftPWMSet(sig[nsig][0], 0);  // red off
-      SoftPWMSet(sig[nsig][state], 255);   // green on
+      SoftPWMSet(sig[nsig][state], GREEN_ON);   // green on
       break;
     case 2:
       if (last[nsig] ==  1) {
         SoftPWMSet(sig[nsig][last[nsig]], 0);
         delay(200);
         // first switch to red
-        SoftPWMSet(sig[nsig][0], 255);  // red on
+        SoftPWMSet(sig[nsig][0], RED_ON);  // red on
         delay(1000);
       }
       SoftPWMSet(sig[nsig][0], 0);  // red off
-      SoftPWMSet(sig[nsig][state], 255);   // yellow on
+      SoftPWMSet(sig[nsig][state], YELLOW_ON);   // yellow on
       break;
     case 3:
       SoftPWMSet(sig[nsig][0], 0);  // red off


Resolved #4 making calls

Resolved #4 making calls

--- telephone/telephone.ino
+++ telephone/telephone.ino
@@ -37,7 +37,6 @@
     Serial.println("Headset down");
     isGettingDigit = false;
     if (isTalking) {
-      gsmVoiceCall.hangCall();
       isTalking = false;
     }
   }
@@ -87,6 +86,9 @@
 }

 void makeCall() {
+  if (isTalking) {
+    return;
+  }
   Serial.println("Making call: " + phoneNumber);
   updatePhoneNumberForRussia();
   phoneNumber.toCharArray(phoneNumberChars, phoneNumber.length() + 1);
@@ -96,12 +98,16 @@
     while (isTalking && (gsmVoiceCall.getvoiceCallStatus() == TALKING)) {
       refreshButtons();
     }
+    gsmVoiceCall.hangCall();
     // ПРОВЕРИТЬ: когда трубку кладут "тут" и когда кладут "там".
     // ПРОВЕРИТЬ: когда занято.
   }
 }

 void sendDigit() {
+  if (gsmVoiceCall.getvoiceCallStatus() != TALKING) {
+    return;
+  }
   if (phoneNumber == "") {
     return;
   }


Update OBJ_Detector.ino

Update OBJ_Detector.ino

--- Arduino/OBJ_Detector.ino
+++ Arduino/OBJ_Detector.ino
@@ -1,118 +1,121 @@
-const int sensor1 = 0;
-const int anPin2 = 3;
-int distance1;
-int i=0,x = 0,num = 0;
-int sum1[100];
-
-
-int sample = 12;// define number of samples when taking a reading -- min 3
-int error = 5; // the % between values that the sample fuction will read as the same
-
-void setup() {
-  Serial.begin (9600);
-  pinMode(anPin2,OUTPUT);
-}
-void calibrate(){
-  Serial.print("C0");
-  Serial.println();
-  digitalWrite(anPin2,LOW);
-  delay(1000);
-  digitalWrite(anPin2,HIGH);
-  read_sensors();
-
-  x = 0;
-}
-
-
-void read_sensors(){
-  //Scale factor is (Vcc/512) per inch. A 5V supply yields ~9.8mV/in
-  //Arduino analog pin goes from 0 to 1024, so the value has to be divided by 2 to get the actual inches
-//----Read sensors------------------------------------------------
-
-  distance1 = 0;
-  num = 0;
-  for(i=0;i<sample;i++){
-  sum1[i] = (analogRead(sensor1)/2);
-  delay(50);
-  }
-//----Sample sensor 1------------------------------------------------
-//Check samples by groups of 3. If the samples are within the % error of eachother they are averaged
-//  and added to the sample distance.
-/*
-  for(i=0;i<sample;i=i+3){
-  if( (sum1[i] - (sum1[i] + error)) <= sum1[i+1] && (sum1[i] + (sum1[i] + error)) >= sum1[i+1]){
-    distance1 = distance1 + ((sum1[i] + sum1[i+1])/2);
-    num++;
-  }
-
-  if( (sum1[i+1] - (sum1[i+1] + error)) <= sum1[i+2] && (sum1[i+1] + (sum1[i+1] + error)) >= sum1[i+2]){
-    distance1 = distance1 + ((sum1[i+1] + sum1[i+2])/2);
-    num++;
-  }
-
-  if( (sum1[i] - (sum1[i] + error)) <= sum1[i+2] && (sum1[i] + (sum1[i] + error) >= sum1[i+2])){
-    distance1 = distance1 + ((sum1[i] + sum1[i+2])/2);
-    num++;
-    }
-
-  }
-  //Take the average of the parts of the sample that are closet together.
-  if(num > 0){
-    distance1 = distance1/num;
-  }
-  else{
-
-    read_sensors();
-
-  }
-*/
-   int maxValue = 0, maxCount = 0, j = 0;
-
-   for (i = 0; i < sample; ++i) {
-      int count = 0;
-
-      for (j = 0; j < sample; ++j) {
-         if (sum1[j]<= sum1[i] + error && sum1[j]>= sum1[i] - error)
-         ++count;
-      }
-
-      if (count > maxCount) {
-         maxCount = count;
-         distance1 = sum1[i];
-      }
-
-   }
-
-
-
-
-
-}
-
-void print_all(){
-  if(distance1 <= 200){
-  Serial.print("SB ");
-  Serial.print(distance1);// in feet
-  Serial.println();
-  }
-
-
-}
-void loop() {
-  read_sensors();
-  if(Serial.available())
-  {
-    x=(Serial.read()-'0');
-  }
-  if(x == 1 || distance1 == 0)
-  {
-    calibrate();
-  }
-  else
-  {
-    print_all();
-  }
-
-
-}
+const int sensor1 = 3;
+int distance1;
+int i=0,x = 0,num = 0;
+int sum1[100];

+
+int sample = 12;// define number of samples when taking a reading -- min 3
+int error = 5; // the % between values that the sample fuction will read as the same
+
+void setup() {
+  Serial.begin (9600);
+  pinMode(sensor1,INPUT);
+}
+void calibrate(){
+  /*
+  Serial.print("C0");
+  Serial.println();
+ // digitalWrite(anPin2,LOW);
+  delay(1000);
+//  digitalWrite(anPin2,HIGH);
+  read_sensors();
+
+  x = 0;
+  */
+}
+
+
+void read_sensors(){
+  //Scale factor is (Vcc/512) per inch. A 5V supply yields ~9.8mV/in
+  //Arduino analog pin goes from 0 to 1024, so the value has to be divided by 2 to get the actual inches
+//----Read sensors------------------------------------------------
+
+  distance1 = 0;
+  num = 0;
+  for(i=0;i<sample;i++){
+  sum1[i] = (analogRead(sensor1)/2);
+  delay(50);
+  }
+//----Sample sensor 1------------------------------------------------
+//Check samples by groups of 3. If the samples are within the % error of eachother they are averaged
+//  and added to the sample distance.
+/*
+  for(i=0;i<sample;i=i+3){
+  if( (sum1[i] - (sum1[i] + error)) <= sum1[i+1] && (sum1[i] + (sum1[i] + error)) >= sum1[i+1]){
+    distance1 = distance1 + ((sum1[i] + sum1[i+1])/2);
+    num++;
+  }
+
+  if( (sum1[i+1] - (sum1[i+1] + error)) <= sum1[i+2] && (sum1[i+1] + (sum1[i+1] + error)) >= sum1[i+2]){
+    distance1 = distance1 + ((sum1[i+1] + sum1[i+2])/2);
+    num++;
+  }
+
+  if( (sum1[i] - (sum1[i] + error)) <= sum1[i+2] && (sum1[i] + (sum1[i] + error) >= sum1[i+2])){
+    distance1 = distance1 + ((sum1[i] + sum1[i+2])/2);
+    num++;
+    }
+  }
+  //Take the average of the parts of the sample that are closet together.
+  if(num > 0){
+    distance1 = distance1/num;
+  }
+  else{
+    read_sensors();
+  }
+*/
+   int maxValue = 0, maxCount = 0, j = 0;
+
+   for (i = 0; i < sample; ++i) {
+      int count = 0;
+
+      for (j = 0; j < sample; ++j) {
+         if (sum1[j]<= sum1[i] + error && sum1[j]>= sum1[i] - error)
+         ++count;
+      }
+
+      if (count > maxCount) {
+         maxCount = count;
+         distance1 = sum1[i];
+      }
+
+   }
+
+
+
+
+
+}
+
+void print_all(){
+  if(distance1 <= 200){
+  Serial.print("SB ");
+  Serial.print(distance1);// in feet
+  Serial.println();
+  }
+  else{
+  Serial.print("SB ");
+  Serial.print("0");// in feet
+  Serial.println();
+  }
+
+
+}
+void loop() {
+  read_sensors();
+  if(Serial.available())
+  {
+    x=(Serial.read()-'0');
+  }
+  if(x == 1 || distance1 == 0)
+  {
+    calibrate();
+  }
+  else
+  {
+    print_all();
+  }
+
+
+}
+


Fix calculation of transmission size

Fix calculation of transmission size

Also transmission size is no longer a constant in case
we need to change it during the run due to low quality
of communication as well as to facilitate testing.

--- ins-node/src/wifi_module/wifi_module.ino
+++ ins-node/src/wifi_module/wifi_module.ino
@@ -1,4 +1,5 @@
 #include <stdint.h>
+#include <math.h>
 #include <vector>
 #include <utility>
 #include <ESP8266WiFi.h>
@@ -8,7 +9,8 @@
 EspClass espPower;
 const uint8_t DEVICE_ID = 1; // The identification for the specific node
 const int8_t CONNECTION_RETRIES = 3; // The maximum amount of wifi connection attempts
-const uint8_t TRANSMISSION_SIZE = 10;
+const uint8_t DEFAULT_TRANSMISSION_SIZE = 10;
+uint8_t currentTransmissionSize = DEFAULT_TRANSMISSION_SIZE;

 const uint8_t TX_PIN = 10;
 const uint8_t RX_PIN = 9;
@@ -133,12 +135,12 @@

   // We need to split the data in groups of 10, as this is the maximum amount
   // we have agreed to send per transmission.
-  uint8_t transmissions = (datapoints.size() / TRANSMISSION_SIZE) + 1;
+  uint8_t transmissions = ceil(datapoints.size() / static_cast<double>(currentTransmissionSize));
   for (auto i = 0; i < transmissions; i++) {
-    // Get the next TRANSMISSION_SIZE elements as a new vector
+    // Get the next currentTransmissionSize elements as a new vector
     std::vector<std::pair<String, int32_t>> transmissionData(
-                                           datapoints.begin() + (i * TRANSMISSION_SIZE),
-                                           datapoints.end() - ((transmissions - (i + 1)) * TRANSMISSION_SIZE));
+                                           datapoints.begin() + (i * currentTransmissionSize),
+                                           datapoints.end() - ((transmissions - (i + 1)) * currentTransmissionSize));
     // Transmit the collected data.
     bool transmissionWasSuccess = transmitData(datapoints);
     if (!transmissionWasSuccess) {


added reference to https://github.com/Makuna/NeoPixelBus

--- Arduino/sketch_jan11a/sketch_jan11a.ino
+++ Arduino/sketch_jan11a/sketch_jan11a.ino
@@ -1,7 +1,9 @@
+/*  https://github.com/Makuna/NeoPixelBus */
 #include <NeoPixelBus.h>
 #include <RgbColor.h>

 /*
+
 #include <ESP8266WiFi.h>
 #include <ESP8266WiFiMulti.h>
 #include <WiFiClient.h>


[avr] Replace decodePowermon()s cases with the appropriate constants

--- arduino/Powermon433/Powermon433.ino
+++ arduino/Powermon433/Powermon433.ino
@@ -440,20 +440,19 @@
 {
   switch (decoder.data[0] & 3)
   {
-  case 0:
-  case 1:
+  case OOK_PACKET_INSTANT:
     // val16 is the number of milliseconds between blinks
     // Each blink is one watt hour consumed
     g_RxWatts = 3600000UL / val16;
     break;

-  case 2:
+  case OOK_PACKET_TEMP:
     //float f = decoder.data[1] * 0.823 - 28.63;
     g_RxTemperature = (int8_t)(decoder.data[1] * 210U / 256U) - 28;
     g_RxFlags = decoder.data[0];
     break;

-  case 3:
+  case OOK_PACKET_TOTAL:
     g_RxWattHours = val16;
     break;
   }


use should_catapult as an indicator whether we should throw

--- gestureDetection/gestureDetection.ino
+++ gestureDetection/gestureDetection.ino
@@ -50,7 +50,7 @@
 const int MPU=0x68;  // I2C address of the MPU-6050
 int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
 int16_t accel_X_reading = 0; //lpf of AcX
-bool indexRelax, middleRelax, ringRelax;
+bool indexRelax, middleRelax, ringRelax, should_catapult;
 enum state {idle,forward_drive, backup, left_turn,right_turn};
 state gestureState = idle;
 uint8_t turning_speed; //in forward drive and backup mode, turning_speed is set to 0
@@ -61,6 +61,7 @@
   /*upon an interrupt, send catapult throw command*/
   /*right now, we can turn on LED to indicate this event*/
   digitalWrite(13,HIGH);
+  should_catapult = true;
   x++;
 }
 void setup(){
@@ -88,7 +89,7 @@
   AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
   AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
   AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
-  accel_X_reading = 0.99 * accel_X_reading + 0.01 * AcX; //LPF here, check if this works since float is involved
+  accel_X_reading = 0.99 * accel_X_reading + 0.01 * AcX;
   //Serial.print("accel_X_reading is ");Serial.println(accel_X_reading);
   //Serial.print("number of interrupts is ");Serial.println(x);
   int indexFingerReading = analogRead(A0);
@@ -123,7 +124,8 @@
   //Serial.print("turningSpeed is "); Serial.println(turning_speed);
   //delay(333);
   /*Xbee send packets to inform*/
-  //send_info(gestureState,turningSpeed);
+  //send_info(gestureState,turningSpeed,should_catapult);
+  //should_catapult = false;

   /*


generate better random colours in the HSV colourspace

--- arduino/src/sketch.ino
+++ arduino/src/sketch.ino
@@ -264,14 +264,15 @@
  */
 void anim_fade()
 {
-    static CHSV target;
+    static CRGB target;

     // If this is the beginning of a fade, pick a random colour.
     if (brand_percent == 0) {
-
-        target.r = random8();
-        target.g = random8();
-        target.b = random8();
+        CHSV rnd;
+        rnd.h = random8();
+        rnd.s = 255;
+        rnd.v = 255;
+        target = rnd;
     }

     // Interpolate the current colour.


Fixed stepper operation.

Fixed stepper operation.

--- software/Arduino/ServoController/ServoController.ino
+++ software/Arduino/ServoController/ServoController.ino
@@ -11,48 +11,74 @@
 #include <SparkFunLSM9DS1.h>
 #include "config.h"

-// Declare global variables
-LSM9DS1 imu; // imu chip
+// ================ SYSTEM PARAMETERS ===================
+// Sample rates
+int motorUpdateRate = 50; // gyro sample rate
+
+int calibrationSamples = 1000;
+
+// Initial calibration values
+float calibratedYOffset = 0;
+float calibratedZOffset = 0;
+
+// Stepper motor
 int stepperPins[] = {9, 10, 11, 12};
 int stepperSteps = 200;
+float stepperStepSize = 9.0/5;
+
+// Servo motor
+float currentServoVal = 90;
+
+// Indicator LED
+const int LED = 13;
+// =======================================================
+
+// ============ Initialize electronic interfaces =========
+// Stepper
 Stepper motor(stepperSteps, stepperPins[0], stepperPins[1], stepperPins[2], stepperPins[3]);
+
+// Servo
 Servo altitude;

-int motorUpdateRate = 50; // gyro sample rate
-int maxSteps = 10; // maximum number of steps per motor update
-int sampleCounter = 0; // keep track of what to sample
-int timer = millis();
-float runningSumAlt = 0;
-float runningSumZ = 0;
+// Gyro
+LSM9DS1 imu;
+
+// ============ Runtime variables ========================
+// Orientation data
 float currentYBodyPosition = 0;
 float currentZBodyPosition = 0;
 float currentYMotorPosition = 0;
 float currentZMotorPosition = 0;
-int calibrationSamples = 1000;
-float calibratedYOffset = 0;
-float calibratedZOffset = 0;
-
-float currentServoVal = 90;
-
+
+// Misc.
+int timer = millis();
 bool update_flag = false; // interrupt flag for executing motor update
-const int LED = 13; // indicator LED
-
+
+// Initialize everything
 void setup() {
+  // Initialize I/O
   Serial.begin(115200);
   pinMode(LED, OUTPUT);
-  setupIMU(); // set up hardware
-  motor.setSpeed(10);
-  altitude.attach(3);
-
+
+  // Setup hardware
+  setupIMU();         // Gyro
+  motor.setSpeed(20); // Stepper
+  altitude.attach(3); // Servo
+
+  // Calibrate the gyro
   zeroGyro();

-  blinkLED(20, 10); // Let the use know everything initialized
-
-  MsTimer2::set(motorUpdateRate, updateMotor); // accepts ms argument
-  MsTimer2::start(); // set up and start a timer interrupt
+  // Setup motor update interval timer
+  MsTimer2::set(motorUpdateRate, updateMotor);
+  MsTimer2::start();
+
+  // Blink LED to indicate that initilization has completed!
+  blinkLED(20, 10);
 }

 void loop() {
+
+  // Accept corrections from serial
   if (Serial.available() == 8) {
     int correctionFactorXY = 0;
     int correctionFactorZ = 0;
@@ -73,19 +99,30 @@
     currentServoVal += correctionFactorZ;
   }

+  // Update orientation data with measurements from gyro
+  // Just using angular rates from gyro and time deltas to track position using a Reimann sum.
   int currentTime = millis();
   int deltaT = currentTime - timer;
-  currentZBodyPosition += deltaT * readGyroZ() / 1000;
+  currentZBodyPosition += deltaT * readGyroZ() / 1000; // Gyro data is given in 1000ths of a degree, so we divide by 1000
   currentYBodyPosition += deltaT * readGyroY() / 1000;
   timer = currentTime;

+  // Update motor positions
   if(update_flag) {
+
+    // Debug output
     Serial.println("SUM: BODY_Y = " + String(currentYBodyPosition) + " | BODY_Z = " + String(currentZBodyPosition) + " | MOTOR_Y: " + String(currentYMotorPosition) + " | MOTOR_Z: " + String(currentZMotorPosition));
+
+    // Update servo position (Y/ALT)
     altitude.write(currentYBodyPosition);
-    rotateStepperBy(currentZBodyPosition - currentZMotorPosition);
     currentYMotorPosition = currentYBodyPosition;
-    currentZMotorPosition = currentZBodyPosition;
-    sampleCounter = 0;
+
+    // Update stepper position (Z/AZM)
+    float difference = currentZBodyPosition - currentZMotorPosition; // we want currentZMotorPosition + currentZBodyPosition = 0
+    int steps = rotateStepperBy(-difference);
+    currentZMotorPosition += -steps * stepperStepSize;
+
+    // Reset flag
     update_flag = false;
   }
 }
@@ -104,9 +141,10 @@
 }

 // For stepper motors
-void rotateStepperBy(float deg) {
-  int steps = deg*5/9;
+int rotateStepperBy(float deg) {
+  int steps = deg/stepperStepSize;
   motor.step(steps);
+  return steps;
 }

 float readGyroZ() {


Using external hardware 1s watchdog timer.

--- software/PlatformComm/PlatformComm.ino
+++ software/PlatformComm/PlatformComm.ino
@@ -38,6 +38,7 @@
 int tempPin = 3;
 int tempSens;
 int lightPin = 0;
+int watchDogPin = 3;
 int lightSens;
 int rcvdRSSI;

@@ -60,6 +61,7 @@
   CC1101.Reset();
   RegConfig();
   pinMode( ledPin, OUTPUT );
+  pinMode( watchDogPin, OUTPUT );
   digitalWrite( ledPin, false );
   //CC1101.WriteSingleReg( RADIO_CHANNR,channel );
   setFreq( baseFreqMHz + channel * chanSpaceHz );
@@ -67,10 +69,18 @@
   // Note: there's no SetReceive() as Master starts with transmit
   rcvdFlag = true;
   index = 0;
-  numMissed = 0;
+  numMissed = 0;
+
+  Serial.println("arduino reset: External 1sec watchdog enabled.");
+  digitalWrite( watchDogPin, HIGH );
 }

 void loop() {
+
+  // Reset external watchdog
+  digitalWrite( watchDogPin, LOW );
+  digitalWrite( watchDogPin, HIGH );
+
   if ( intFlag ) {
     /* Read sensors
          Note temperature converted to integer representing


Added Debug Info & Initial Distance Reading

Set STARTED message to show for 5 x 1 second at start.
Moved sleep to the end of the main loop, meaning we get an initial
distance reading.
Also, serial debug info sent at the start with labels.

--- OxFloodNet_Sensor/OxFloodNet_Sensor.ino
+++ OxFloodNet_Sensor/OxFloodNet_Sensor.ino
@@ -74,7 +74,7 @@
 // Some functions to get the configured node address and polling
 void readJumpers() {
   // Set analog input pins to read digital values, set internal pullup
-  // ugly - refactor in loop.
+  // TODO: ugly - refactor in loop.
   pinMode(A0, INPUT);
   pinMode(A1, INPUT);
   pinMode(A2, INPUT);
@@ -105,12 +105,18 @@
   nodeId[1] = '0' + min(digit2,9);
   pollingInterval = ((PINB & 0x06) >> 1) ^ 0x03;

+  Serial.println("Debug: ");
+  Serial.print("Port B: ");
   Serial.println(PINB,HEX);
+  Serial.print("Port C: ");
   Serial.println(PINC,HEX);

+  Serial.print("Polling Interval: ");
   Serial.println(pollingInterval,DEC);

-  Serial.println(digit1,DEC);
+  Serial.print("Node ID Digits: ");
+  Serial.print(digit1,DEC);
+  Serial.print(" ");
   Serial.println(digit2,DEC);
   // A0, A1 are first part, R, S, T, W
   // A2 - A5 are 0-9, A-F
@@ -389,13 +395,27 @@
     LLAP.sendInt("ERR",val); // Diagnostic
     delay(5000);	// try again in 5 seconds
   }
-  for(int i=0;i<3;i++) {
+
+  // Repeat "STARTED" message 5 times to alert
+  for(int i=0;i<5;i++) {
     LLAP.sendMessage("STARTED");
-  }
-
-
-
-    // Initial Distance reading
+    delay(1000);
+  }
+
+}
+
+// The main loop, we basically wake up the SRF, take a reading, transmit reading then go back to sleep
+void loop() {
+
+  // Determine if we need to send a battery voltage reading or a distance reading
+  if( --batteryCountDown <= 0 ) {
+    int mV = readVcc();
+    LLAP.sendIntWithDP("B", mV, 3 );
+    batteryCountDown = BATTERY_READ_INTERVAL;
+  }
+  else {
+
+    // Distance reading
     uint16_t cm = getRange();
     // Send temperature reading
     if( tempSensorFound ) {
@@ -416,48 +436,14 @@
         LLAP.sendMessage( "UErr" );
       }
     }
-
-}
-
-// The main loop, we basically wake up the SRF, take a reading, transmit reading then go back to sleep
-void loop() {
+  }

   // Short delay to allow reading to be sent then sleep
   delay(50);
   pinMode(SRF_SLEEP, INPUT);                // sleep the radio
   LLAP.sleep(WAKE_INT, RISING, false);      // sleep until woken on pin 2, no pullup (low power)
   pinMode(SRF_SLEEP, OUTPUT);               // wake the radio
-
-  // Determine if we need to send a battery voltage reading or a distance reading
-  if( --batteryCountDown <= 0 ) {
-    int mV = readVcc();
-    LLAP.sendIntWithDP("B", mV, 3 );
-    batteryCountDown = BATTERY_READ_INTERVAL;
-  }
-  else {
-
-    // Distance reading
-    uint16_t cm = getRange();
-    // Send temperature reading
-    if( tempSensorFound ) {
-      int latestTemp = (int)(latestTemperature * 100);
-      LLAP.sendIntWithDP( "T", latestTemp, 2);
-    }
-    // Uncompensated distance
-    LLAP.sendInt( "D", lastUncompDistance);
-    // Send reading 3 times to make sure it gets through
-    for(int n = 0; n<1; n++ ) {
-      if( cm > 17 ) {
-        LLAP.sendInt( "U", cm );
-      }
-      else if( cm == 0 ) {
-        LLAP.sendMessage( "UMax" );
-      }
-      else {
-        LLAP.sendMessage( "UErr" );
-      }
-    }
-  }
+
 }
 // That's all folks


Blynk disconnect counting/reporting

Blynk disconnect counting/reporting

--- hvacMonitor.ino
+++ hvacMonitor.ino
@@ -23,7 +23,7 @@

 char myEmail[] = "email";

-char* hostSF = "raspi";
+char* hostSF = "192.168.0.168";
 char* streamId   = "publicKey";
 char* privateKey = "privateKey";

@@ -81,19 +81,23 @@
 int fanRelay = 16;      // WeMos pin D0.
 int bypassRelay = 0;    // WeMos pin D3.

-int controlSplit = 1;   // Predefined value of how much I want to heat or cool above trigger point.
+int controlSplit = 2;   // Predefined value of how much I want to heat or cool above/below setpoint.
 int controllingTemp;
 int setpointTemp;
 String controllingSpace;
 bool coolingMode;       // 1 = cooling. 0 = heating.
 bool controlMode;
-int tempKK, tempLK;
+int tempKK, tempLK, tempAT;

 long controlStart;
 long controlRuntime;
 long heatControlTimeout = 600000; // 600000 millis = 10 minutes
 long coolControlTimeout = 120000000; // 120000000 millis = 20 minutes
 bool controlLatch = FALSE;
+
+bool blynkFlag;
+int blynkDisconnectCount;
+bool ranOnce;

 void setup()
 {
@@ -168,6 +172,8 @@
   timer.setInterval(30000L, tempUpdater);      // When bypass on, this evaluates controlling space against setpoint.
   timer.setInterval(30000L, tempControl);     // Temps (controlling space) that can control HVAC are synced.
   timer.setInterval(1000L, tempControlSafety);
+  timer.setInterval(250L, disconnectWatcher);     // Watches for a disconnect event
+  timer.setInterval(5000L, disconnectReporter);   // Reports disconnects to the app every 5 seconds

 }

@@ -176,7 +182,27 @@
   Blynk.run();
   timer.run();
   ArduinoOTA.handle();
-}
+
+  if (ranOnce == false && year() != 1970) {
+    Blynk.setProperty(V107, "label", String(hour()) + ":" + minute() + " " + month() + "/" + day() + " HVAC");
+    ranOnce = true;
+  }
+}
+
+void disconnectWatcher() {
+  if (Blynk.connected() == false && blynkFlag == false) {
+    ++blynkDisconnectCount;
+    blynkFlag = true;
+  }
+  else if (Blynk.connected() == true && blynkFlag == true) {
+    blynkFlag = false;
+  }
+}
+
+void disconnectReporter() {
+  Blynk.virtualWrite(V107, blynkDisconnectCount);
+}
+

 // ******************************************************** HVAC CTRL START **********************************************
 BLYNK_WRITE(V40) {
@@ -213,33 +239,31 @@
         digitalWrite(bypassRelay, LOW);
         break;
       }
-    case 4: {                         // Manual cooling
+    case 4: {                         // House t-stat-controlled cooling
+        controlMode = 1;
+        controllingSpace = "AT";
+        coolingMode = 1;
+        controllingTemp = tempAT;
+        Blynk.setProperty(V39, "label", String("Setpoint: ") + setpointTemp + ". Controlled by AT (currently " + tempAT + "F).");
+        digitalWrite(fanRelay, HIGH);
+        digitalWrite(coolingRelay, HIGH);
+        digitalWrite(heatingRelay, HIGH);
+        digitalWrite(bypassRelay, LOW);
+        break;
+      }
+    case 5: {                         // House t-stat controlled heating
         /*
-          controlMode = 0;
-          controllingSpace = "";
-          Blynk.setProperty(V39, "label", "Setpoint");
+          controlMode = 1;
+          controllingSpace = "AT";
+          coolingMode = 0;
+          controllingTemp = tempAT;
+          Blynk.setProperty(V39, "label", String("Setpoint: ") + setpointTemp + ". Controlled by AT (currently " + tempAT + "F).");
           digitalWrite(fanRelay, HIGH);
-          digitalWrite(coolingRelay, LOW);
+          digitalWrite(coolingRelay, HIGH);
           digitalWrite(heatingRelay, HIGH);
           digitalWrite(bypassRelay, LOW);
+          break;
         */
-        controlReset();
-
-        break;
-      }
-    case 5: {                         // Manual heating
-        /*
-          controlMode = 0;
-          controllingSpace = "";
-          Blynk.setProperty(V39, "label", "Setpoint");
-          digitalWrite(fanRelay, HIGH);
-          digitalWrite(coolingRelay, HIGH);
-          digitalWrite(heatingRelay, LOW);
-          digitalWrite(bypassRelay, LOW);
-        */
-        controlReset();
-
-        break;
       }
     case 6: {                                         // Keaton-controlled cooling
         controlMode = 1;
@@ -254,17 +278,19 @@
         break;
       }
     case 7: {                             // Keaton-controlled heating
-        Blynk.syncVirtual(V39);
-        controlMode = 1;
-        controllingSpace = "KK";
-        coolingMode = 0;
-        controllingTemp = tempKK;
-        Blynk.setProperty(V39, "label", String("Setpoint: ") + setpointTemp + "F. Controlled by KK (currently " + tempKK + "F).");
-        digitalWrite(fanRelay, HIGH);
-        digitalWrite(coolingRelay, HIGH);
-        digitalWrite(heatingRelay, HIGH);
-        digitalWrite(bypassRelay, LOW);
-        break;
+        /*
+          Blynk.syncVirtual(V39);
+          controlMode = 1;
+          controllingSpace = "KK";
+          coolingMode = 0;
+          controllingTemp = tempKK;
+          Blynk.setProperty(V39, "label", String("Setpoint: ") + setpointTemp + "F. Controlled by KK (currently " + tempKK + "F).");
+          digitalWrite(fanRelay, HIGH);
+          digitalWrite(coolingRelay, HIGH);
+          digitalWrite(heatingRelay, HIGH);
+          digitalWrite(bypassRelay, LOW);
+          break;
+        */
       }
     case 8: {                             // Liv-controlled cooling
         controlMode = 1;
@@ -279,16 +305,18 @@
         break;
       }
     case 9: {                             // Liv-controlled heating
-        controlMode = 1;
-        controllingSpace = "LK";
-        coolingMode = 0;
-        controllingTemp = tempLK;
-        Blynk.setProperty(V39, "label", String("Setpoint: ") + setpointTemp + ". Controlled by LK (currently " + tempLK + "F).");
-        digitalWrite(fanRelay, HIGH);
-        digitalWrite(coolingRelay, HIGH);
-        digitalWrite(heatingRelay, HIGH);
-        digitalWrite(bypassRelay, LOW);
-        break;
+        /*
+          controlMode = 1;
+          controllingSpace = "LK";
+          coolingMode = 0;
+          controllingTemp = tempLK;
+          Blynk.setProperty(V39, "label", String("Setpoint: ") + setpointTemp + ". Controlled by LK (currently " + tempLK + "F).");
+          digitalWrite(fanRelay, HIGH);
+          digitalWrite(coolingRelay, HIGH);
+          digitalWrite(heatingRelay, HIGH);
+          digitalWrite(bypassRelay, LOW);
+          break;
+        */
       }
     default: {
         break;
@@ -365,8 +393,9 @@
 }

 void tempUpdater() {
-  Blynk.syncVirtual(V4);
-  Blynk.syncVirtual(V6);
+  Blynk.syncVirtual(V3);  // AT
+  Blynk.syncVirtual(V4);  // KK
+  Blynk.syncVirtual(V6);  // LK

   if (controllingSpace == "KK")
   {
@@ -378,6 +407,15 @@
     controllingTemp = tempLK;
     Blynk.setProperty(V39, "label", String("Setpoint: ") + setpointTemp + "F. Controlled by LK (currently " + tempLK + "F).");
   }
+  else if (controllingSpace == "AT")
+  {
+    controllingTemp = tempAT;
+    Blynk.setProperty(V39, "label", String("Setpoint: ") + setpointTemp + "F. Controlled by AT (currently " + tempAT + "F).");
+  }
+}
+
+BLYNK_WRITE(V3) {
+  tempAT = param.asInt();
 }

 BLYNK_WRITE(V4) {
@@ -649,7 +687,7 @@
   {
     Blynk.virtualWrite(0, "ERR");       // ...there's an error, then display ERR, otherwise...
   }
-  else{
+  else {
     Blynk.virtualWrite(0, "OFF");       // ...display OFF.
   }


Remove time-related code from sensor system

--- arduino/sensor_system/sensor_system.ino
+++ arduino/sensor_system/sensor_system.ino
@@ -37,10 +37,6 @@
 bool powerOn = true;
 bool powerToggled = false;

-static unsigned long minuteCounter;
-unsigned long delay_hours;
-unsigned long delay_minutes;
-
 // Serial connections
 SoftwareSerial serialCarSystem(2, 3);  // Pins 2, 3

@@ -48,28 +44,6 @@
 // the given threshold.
 bool SensorGreaterThan(const unsigned int pin, const unsigned int threshold) {
   return analogRead(pin) > threshold;
-}
-
-// This method counts down by a single minute when a minute has passed.
-void MinuteSet() {
-  if(minuteCounter < millis()) {
-
-    if(delay_minutes == 0 && delay_hours > 0) {
-      --delay_hours;
-      delay_minutes = 59;
-    }
-    else if(delay_minutes > 0) {
-      --delay_minutes;
-    }
-
-    minuteCounter = millis()+(60*1000);
-  }
-}
-
-// This method sets a new delay time.
-void SetDelayTime(const unsigned long hours, const unsigned long minutes) {
-  delay_hours = hours;
-  delay_minutes = minutes;
 }

 void setup() {
@@ -93,13 +67,10 @@
   digitalWrite(pinPowerLED, HIGH);
   digitalWrite(pinEssentialLED, LOW);
   digitalWrite(pinGeneralLED, LOW);
-
-  minuteCounter = millis()+(60*1000);
 }

 void loop() {
   delay(300);
-  //MinuteSet();

   // Power on/off
   if(!SensorGreaterThan(pinCapacitive, thresholdCapacitive) &&


ProcessEnergy on fixed interval

ProcessEnergy on fixed interval

--- resilient_network/resilient_network.ino
+++ resilient_network/resilient_network.ino
@@ -102,7 +102,7 @@
     if (!lampState) switchLampOn();
     // send shortest distance to ports with a higher distance
     for (int i =0; i<NUM_CONN; i++) if (distanceToSource[i] > shortestDistanceToSource) txWrite(i, shortestDistanceToSource);
-    addTimer(500, processEnergy);
+    //addTimer(500, processEnergy);
   }
   // if not, switch off the lamp and drop connectors if we were cut out
   else {
@@ -114,7 +114,7 @@
   }

   for (int i=0; i<NUM_CONN; i++) distanceToSource[i] = 99;
-  //addTimer(50, processEnergy);
+  addTimer(200, processEnergy);
 }

 uint8_t rxRead(int busIndex) {
@@ -199,7 +199,7 @@
         // if we are not connected (yet) and a new distance was received start timer to process energy
         // (hopefully this does enhances asynchronous updating between the nodes)
         // ToDo: why use timer here? can't it get triggered to much, shouldn't this simply debounce? why not call on fixed interval?
-        if (shortestDistanceToSource == 99) addTimer(10, processEnergy);
+        //if (shortestDistanceToSource == 99) addTimer(10, processEnergy);
       }
   }
 }


Stream fix that trusts the libs a little more again.

git-svn-id: d8bfcd070c2c81762cca1b3912331324182919ba@19122 0d6f1817-ed0e-0410-87c9-987e46238f29

--- zimodem/zstream.ino
+++ zimodem/zstream.ino
@@ -124,9 +124,9 @@
   {
     current->write(c);
     logSocketOut(c);
-    current->flush(); // rendered safe by available check
-    delay(0);
-    yield();
+    //current->flush(); // rendered safe by available check
+    //delay(0);
+    //yield();
   }
 }


Don't mask global stage.

Don't mask global stage.

--- examples/seq/seq.ino
+++ examples/seq/seq.ino
@@ -166,16 +166,16 @@

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

  private:


change initial led color

change initial led color

--- arduino-neopixel.ino
+++ arduino-neopixel.ino
@@ -21,9 +21,9 @@
 String input_str;   // 文字列格納用
 int i = 0;  // 文字数のカウンタ

-int i_color_r = 0;
-int i_color_g = 0;
-int i_color_b = 0;
+int i_color_r = 255;
+int i_color_g = 255;
+int i_color_b = 255;
 int e_color_r = 0;
 int e_color_g = 0;
 int e_color_b = 0;


Update TODO

Update TODO

--- moros/moros.ino
+++ moros/moros.ino
@@ -1,11 +1,10 @@
 /*
 * TODO:
-* case
-* flag - P0 BLOCKER S0
-* -- have graphical representation of flag
-* wiring diagram - P2 S3
 * reset button (chronos style?) - P1
 * time setting - P1
+* case - P1
+* wiring diagram - P2 S3
+* have graphical representation of flag P3
 * OLEDs
 *
 */


Fix some bugs, add DIAGNOSTICS support

Fix some bugs, add DIAGNOSTICS support

git-svn-id: 464247b772b47fb892ddc6c4a897645d921924ed@99 43b03309-50c7-4bd2-8aa6-20f049331b16

--- src/sketches/OSS_DAQ/OSS_DAQ.ino
+++ src/sketches/OSS_DAQ/OSS_DAQ.ino
@@ -12,7 +12,7 @@
 #include <EEPROM.h>
 #include <alloca.h>
 #include <avr/wdt.h>
-#include <avg/pgmspace.h>
+#include <avr/pgmspace.h>

 /*
  * Hardware identification.
@@ -25,7 +25,7 @@
  *    your product to greenHouse Gas and Electric (CC-BY-SA).
  */

-char copyright_notice[] PROGMEM = "Copyright 2014, greenHouse Gas and Electric, CC-BY-SA 4.0 Intl.";
+const char copyright_notice[] PROGMEM = "Copyright 2014-2015, greenHouse Gas and Electric, CC-BY-SA 4.0 Intl.";

 /*
  * Pin assignments.
@@ -118,27 +118,37 @@
 #define HAS_FILES /* READ/WRITE FILE RECORD */
 #define HAS_COUNTS /* GET COMM EVENT COUNTER */
 #define HAS_LOG /* GET COMM EVENT LOG */
+#define HAS_DIAGS /* DIAGNOSTICS */

 #if defined(HAS_LOG) && !defined(HAS_COUNTS)
 #error Event log depends on event counters.
 #endif

+#if defined(HAS_DIAGS) && !defined(HAS_COUNTS)
+#error Diagnostics depend on event counters.
+#endif
+
 /*
  * Values for READ DEVICE IDENTICATION method.
  */
 #if defined(HAS_MEI) || defined(HAS_SRVR_ID)
 #ifdef HAS_MEI
-char company_name[] PROGMEM = "greenHouse Gas and Electric";
-#endif
-char product_name[] PROGMEM = "OSS_DAQ";
+const char company_name[] PROGMEM = "greenHouse Gas and Electric";
+#endif
+const char product_name[] PROGMEM = "OSS_DAQ";
 #ifdef HAS_MEI
-char version_text[] PROGMEM = "v1.01";
+const char version_text[] PROGMEM = "v1.02";
 #endif
 #endif

 #ifdef HAS_FIFO
 /**
  * get_fifo_count - Return "31" for valid ADC queues, -1 otherwise.
+ *
+ * The FIFO feature allows 4 different ADC values to be read in bursts
+ * of 31 values.  The FIFOs are addressed 0..3, which differs from the
+ * Modbus definition in that FIFOs are mapped into the register map
+ * in other devices.
  */
 char get_fifo_count(char fifo) {
   if (fifo < 0 || fifo > 3)
@@ -162,6 +172,12 @@
 #endif

 #ifdef HAS_FILES
+
+/*
+ * RECORD_SIZE controls both the maximum number of registers in each record as well
+ * as the number of records in the file.  The value should support the largest possible
+ * record, and no more.
+ */
 #define  RECORD_SIZE  64
 #define  FILE_BASE 128

@@ -190,6 +206,14 @@

   write_eeprom_short(address, value);
 }
+#endif
+
+#ifdef HAS_DIAGS
+unsigned short modbus_message_total_count;
+unsigned short modbus_message_crc_error_count;
+unsigned short modbus_message_exception_count;
+unsigned short modbus_message_no_response_count;
+unsigned short modbus_message_overrun_count;
 #endif

 /*
@@ -509,6 +533,9 @@
         FC_READ_INPUT_REGISTERS = 0x04,
         FC_WRITE_SINGLE_COIL = 0x05,
         FC_WRITE_SINGLE_REGISTER  = 0x06,
+#ifdef HAS_DIAGS
+        FC_DIAGNOSTICS = 0x08,
+#endif
 #ifdef HAS_COUNTS
         FC_GET_COMM_EVENT_COUNTER = 0x0B,
 #endif
@@ -717,11 +744,16 @@
 }

 void modbus_exception(unsigned char code) {
+  char is_broadcast = modbus_in[0] == 0;
   /*
    * NEVER report an exception on a broadcast message.
    */
-  if (modbus_in[0] == 0)
-    return;
+  if (is_broadcast) {
+#ifdef HAS_DIAGS
+    modbus_message_no_response_count++;
+#endif
+    return;
+  }

   /*
    * Copy the command code from the input packet to the output packet,
@@ -736,6 +768,9 @@
   modbus_out[modbus_out_cnt++] = function;
   modbus_out[modbus_out_cnt++] = code;

+#ifdef HAS_DIAGS
+  modbus_message_exception_count++;
+#endif
   modbus_write();
 }

@@ -971,6 +1006,56 @@
   modbus_write();
 }

+#ifdef HAS_DIAGS
+void slave_diagnostics() {
+  int function = modbus_get_short(2);
+  int value = modbus_get_short(4);
+  int response_value = 0;
+
+  if (function < 0 || function == 19 || function > 20) {
+    modbus_exception(EX_ILLEGAL_DATA_VALUE);
+    return;
+  }
+  modbus_out_cnt = 0;
+
+  modbus_out[modbus_out_cnt++] = modbus_unit;
+  modbus_out[modbus_out_cnt++] = FC_DIAGNOSTICS;
+  modbus_put_short(function);
+
+  switch(function) {
+    case 0:
+      response_value = value;
+      break;
+    case 11:
+      response_value = modbus_message_total_count;
+      break;
+    case 12:
+      response_value = modbus_message_crc_error_count;
+      break;
+    case 13:
+      response_value = modbus_message_exception_count;
+      break;
+    case 14:
+      response_value = event_count;
+      break;
+    case 15:
+      response_value = modbus_message_no_response_count;
+      break;
+    case 18:
+      response_value = modbus_message_overrun_count;
+      break;
+    default:
+      break;
+  }
+
+  modbus_put_short(response_value);
+#ifdef HAS_COUNTS
+  event_count++;
+#endif
+  modbus_write();
+}
+#endif
+
 #ifdef HAS_COUNTS
 void slave_get_comm_event_counter() {
   modbus_out_cnt = 0;
@@ -1041,17 +1126,13 @@
    */
   for (i = 0;i < coil_count;i++) {
     if (! is_coil_setable(coil_start + i)) {
-      if (! is_broadcast)
-        modbus_exception(EX_ILLEGAL_DATA_ADDRESS);
-
+      modbus_exception(EX_ILLEGAL_DATA_ADDRESS);
       return;
     }
   }

   if ((coil_count + 7) >> 3 != byte_count) {
-    if (! is_broadcast)
-      modbus_exception(EX_ILLEGAL_DATA_VALUE);
-
+    modbus_exception(EX_ILLEGAL_DATA_VALUE);
     return;
   }

@@ -1071,8 +1152,12 @@
 #ifdef HAS_COUNTS
   event_count++;
 #endif
-  if (is_broadcast)
-    return;
+  if (is_broadcast) {
+#ifdef HAS_DIAGS
+    modbus_message_no_response_count++;
+#endif
+    return;
+  }

   modbus_out_cnt = 0;

@@ -1138,8 +1223,12 @@
 #ifdef HAS_COUNTS
   event_count++;
 #endif
-  if (is_broadcast)
-    return;
+  if (is_broadcast) {
+#ifdef HAS_DIAGS
+    modbus_message_no_response_count++;
+#endif
+    return;
+  }

   modbus_out_cnt = 0;
   modbus_out[modbus_out_cnt++] = modbus_unit;
@@ -1154,7 +1243,7 @@
 void slave_write_multiple_registers() {
   unsigned short address = modbus_get_short(2);
   unsigned short count = modbus_get_short(4);
-  unsigned char  bytes = modbus_in_[6];
+  unsigned char  bytes = modbus_in[6];
   unsigned char i;
   unsigned char is_broadcast = modbus_in[0] == 0;

@@ -1162,9 +1251,7 @@
    * Unsigned math means never knowing when you're going to wrap ...
    */
   if (address >= modbus_regs_cnt || (address + count) > modbus_regs_cnt) {
-    if (! is_broadcast)
-      modbus_exception(EX_ILLEGAL_DATA_ADDRESS);
-
+    modbus_exception(EX_ILLEGAL_DATA_ADDRESS);
     return;
   }

@@ -1172,9 +1259,7 @@
    * Verify the byte count against the register count.
    */
   if (count * 2 != bytes) {
-    if (! is_broadcast)
-      modbus_exception(EX_ILLEGAL_DATA_VALUE);
-
+    modbus_exception(EX_ILLEGAL_DATA_VALUE);
     return;
   }

@@ -1184,8 +1269,12 @@
 #ifdef HAS_COUNTS
   event_count++;
 #endif
-  if (is_broadcast)
-    return;
+  if (is_broadcast) {
+#ifdef HAS_DIAGS
+    modbus_message_no_response_count++;
+#endif
+    return;
+  }

   modbus_out_cnt = 0;
   modbus_out[modbus_out_cnt++] = modbus_unit;
@@ -1215,7 +1304,11 @@
   modbus_out[modbus_out_cnt++] = modbus_unit;
   modbus_out[modbus_out_cnt++] = FC_REPORT_SERVER_ID;
   modbus_out[modbus_out_cnt++] = 2 + object_length;
-  modbus_out[modbus_out_cnt++] = modbus_unit;
+
+  /*
+   * greenHouse Modbus products report 99 as their identifier.
+   */
+  modbus_out[modbus_out_cnt++] = 99;
   modbus_out[modbus_out_cnt++] = 0xFF;

   strcpy_P((char *) modbus_out + modbus_out_cnt, product_name);
@@ -1436,11 +1529,17 @@

     return;
   }
+#ifdef HAS_DIAGS
+  modbus_message_total_count++;
+#endif

   /*
    * Ignore packets with CRC errors and those not addressed to us.
    */
   if (! modbus_check_crc()) {
+#ifdef HAS_DIAGS
+    modbus_message_crc_error_count++;
+#endif
 #ifdef HAS_LOG
     if (modbus_in[0] == modbus_unit) {
       unsigned char log_value = 0x82;
@@ -1451,6 +1550,10 @@
       modbus_add_comm_log_entry(log_value);
     }
 #endif
+#ifdef HAS_DIAGS
+    if (modbus_in_cnt == MAX_PDU_IN)
+      modbus_message_overrun_count++;
+#endif
     modbus_in_cnt = 0;
     return;
   }
@@ -1475,27 +1578,41 @@
   switch(modbus_in[1]) {
     case FC_READ_COILS:
     case FC_READ_DISCRETE_INPUTS:
-      if (is_broadcast)
+      if (is_broadcast) {
+#ifdef HAS_DIAGS
+        modbus_message_no_response_count++;
+#endif
         goto done;
-
+      }
       slave_read_multiple_coils();
       break;
     case FC_WRITE_SINGLE_COIL:
       slave_write_single_coil();
       break;
+#ifdef HAS_DIAGS
+    case FC_DIAGNOSTICS:
+      slave_diagnostics();
+      break;
+#endif
 #ifdef HAS_COUNTS
     case FC_GET_COMM_EVENT_COUNTER:
-      if (is_broadcast)
+      if (is_broadcast) {
+#ifdef HAS_DIAGS
+        modbus_message_no_response_count++;
+#endif
         goto done;
-
+      }
       slave_get_comm_event_counter();
       break;
 #endif
 #ifdef HAS_LOG
     case FC_GET_COMM_EVENT_LOG:
-      if (is_broadcast)
+      if (is_broadcast) {
+#ifdef HAS_DIAGS
+        modbus_message_no_response_count++;
+#endif
         goto done;
-
+      }
       slave_get_comm_event_log();
       break;
 #endif
@@ -1506,9 +1623,12 @@
 #endif
     case FC_READ_HOLDING_REGISTERS:
     case FC_READ_INPUT_REGISTERS:
-      if (is_broadcast)
+      if (is_broadcast) {
+#ifdef HAS_DIAGS
+        modbus_message_no_response_count++;
+#endif
         goto done;
-
+      }
       slave_read_registers();
       break;
     case FC_WRITE_SINGLE_REGISTER:
@@ -1525,25 +1645,34 @@
 #endif
 #ifdef HAS_SRVR_ID
     case FC_REPORT_SERVER_ID:
-      if (is_broadcast)
+      if (is_broadcast) {
+#ifdef HAS_DIAGS
+        modbus_message_no_response_count++;
+#endif
         goto done;
-
+      }
       slave_report_server_id();
       break;
 #endif
 #ifdef HAS_FIFO
     case FC_READ_FIFO:
-      if (is_broadcast)
+      if (is_broadcast) {
+#ifdef HAS_DIAGS
+        modbus_message_no_response_count++;
+#endif
         goto done;
-
+      }
       slave_read_fifo();
       break;
 #endif
 #ifdef HAS_FILES
     case FC_READ_FILE_RECORD:
-      if (is_broadcast)
+      if (is_broadcast) {
+#ifdef HAS_DIAGS
+        modbus_message_no_response_count++;
+#endif
         goto done;
-
+      }
       slave_read_file_record();
       break;
     case FC_WRITE_FILE_RECORD:
@@ -1552,13 +1681,20 @@
 #endif
 #ifdef HAS_MEI
     case FC_READ_MEI:
-      if (is_broadcast)
+      if (is_broadcast) {
+#ifdef HAS_DIAGS
+        modbus_message_no_response_count++;
+#endif
         goto done;
-
+      }
       slave_read_device_identification();
       break;
 #endif
     default:
+      /*
+       * Don't count broadcast "illegal function" exceptions towards the
+       * "no response" counter.
+       */
       if (is_broadcast)
         goto done;

@@ -1567,4 +1703,4 @@
   }
 done:
   modbus_in_cnt = 0;
-}
+}


Tidy up

Tidy up

--- examples/RF12/RF12demo/RF12demo.ino
+++ examples/RF12/RF12demo/RF12demo.ino
@@ -41,7 +41,7 @@
 /// Connect Tiny84 PA2 to USB-BUB TXD for serial input to sketch.    // Jeenode DIO2
 /// 9600 or 38400 at present.
 ///
-#define SERIAL_BAUD 9600
+#define SERIAL_BAUD 38400
 #define MAX_NODES 14
 #define _receivePin 8
 static int _bitDelay;
@@ -960,17 +960,16 @@
         // Format is 20,127p where 20 is the node number and 127 is the desired value to be posted
         // stack[0] contains the target node
         // and value contains the command to be posted
-        // Assumed RF12Demo node is node 1
-        if ((stack[0] > 1) && (stack[0] <= MAX_NODES) && (value < 255) && (nodes[stack[0]] == 0)) {   // No posting to self(1), special(31) or overwriting pending post
-          nodes[stack[0]] = value;
-          postingsIn++;            // Count post
+        if ((!stack[0]) && (!value)) {
+          Serial.print((int)postingsIn);
+          showString(COMMA);
+          Serial.println((int)postingsOut);
+          nodesShow();
         }
         else {
-          if ((!stack[0]) && (!value)) {
-            Serial.print((int)postingsIn);
-            showString(COMMA);
-            Serial.println((int)postingsOut);
-            nodesShow();
+          if ((stack[0] !=(config.nodeId & RF12_HDR_MASK)) && (stack[0] <= MAX_NODES) && (value < 255) && (nodes[stack[0]] == 0)) {   // No posting to special(31) or overwriting pending post
+            nodes[stack[0]] = value;
+            postingsIn++;            // Count post
           }
           else
           {


change temperature from int to float to have decimals

--- examples/POOL/POOL.ino
+++ examples/POOL/POOL.ino
@@ -138,7 +138,7 @@
 	  Serial.println("Probig NOW");
 	  lastProbe = now;
 	  DS18B20.requestTemperatures();
-	  int temperature = DS18B20.getTempCByIndex(0);
+	  float temperature = DS18B20.getTempCByIndex(0);
 	  Serial.print("Temperature: ");
 	  Serial.println(temperature);
 	  if (temperature == 85.0 || temperature == (-127.0)) {


Add description for MQTT over TLS

Add description for MQTT over TLS

--- examples/BasicMQTT/BasicMQTT.ino
+++ examples/BasicMQTT/BasicMQTT.ino
@@ -35,6 +35,12 @@
   while (!anto.wifi.begin(ssid, pass));
   Serial.println("\nConnected, trying to connect to broker...");

+  // the last boolean argument is for indicating
+  // that you want this connection to be secured
+  // by TLS or not.
+  //
+  // Secured connection will be
+  // slower than secured one.
   while (!anto.mqtt.connect(user, token, true));
   Serial.println("\nConnected");


adding max waiting for reconnect mqtt

adding max waiting for reconnect mqtt

--- esp8266-anemometer.ino
+++ esp8266-anemometer.ino
@@ -100,6 +100,7 @@
 }

 void reconnect() {
+  int maxWait = 0;
   while (!client.connected()) {
     if(debugOutput) Serial.print("Attempting MQTT connection...");
     if (client.connect(mqtt_id)) {
@@ -111,6 +112,9 @@
         Serial.println(" try again in 5 seconds");
       }
       delay(5000);
+      if(maxWait > 10)
+        ESP.restart();
+      maxWait++;
     }
   }
 }


Update test.ino

Update test.ino

--- examples/test/test.ino
+++ examples/test/test.ino
@@ -51,13 +51,14 @@
 #endif

 // Option 1: use any pins but a little slower
-Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, mosi, sclk, rst);
+//Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, mosi, sclk, rst);

 // Option 2: must use the hardware SPI pins
 // (for UNO thats sclk = 13 and sid = 11) and pin 10 must be
 // an output. This is much faster - also required if you want
 // to use the microSD card (see the image drawing example)
-//Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);
+/ (for Spark Core, cs = A2, dc = D3, rst = D2)
+Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);

 float p = 3.1415926;


Added some internal variables to /esp_status

--- Arduino/McLighting/McLighting.ino
+++ Arduino/McLighting/McLighting.ino
@@ -498,6 +498,15 @@
     json["HOSTNAME"] = HOSTNAME;
     json["version"] = SKETCH_VERSION;
     json["heap"] = ESP.getFreeHeap();
+    json["sketch_size"] = ESP.getSketchSize();
+    json["free_sketch_space"] = ESP.getFreeSketchSpace();
+    json["flash_chip_size"] = ESP.getFlashChipSize();
+    json["flash_chip_real_size"] = ESP.getFlashChipRealSize();
+    json["flash_chip_speed"] = ESP.getFlashChipSpeed();
+    json["sdk_version"] = ESP.getSdkVersion();
+    json["core_version"] = ESP.getCoreVersion();
+    json["cpu_freq"] = ESP.getCpuFreqMHz();
+    json["chip_id"] = ESP.getFlashChipId();
     #ifndef USE_NEOANIMATIONFX
     json["animation_lib"] = "WS2812FX";
     json["pin"] = PIN;
@@ -512,14 +521,32 @@
       json["button_mode"] = "OFF";
     #endif
     #ifdef ENABLE_AMQTT
+      json["amqtt"] = "ON";
+    #endif
+    #ifdef ENABLE_MQTT
       json["mqtt"] = "ON";
-    #else
-      json["mqtt"] = "OFF";
     #endif
     #ifdef ENABLE_HOMEASSISTANT
       json["home_assistant"] = "ON";
     #else
       json["home_assistant"] = "OFF";
+    #endif
+    #ifdef ENABLE_LEGACY_ANIMATIONS
+      json["legacy_animations"] = "ON";
+    #else
+      json["legacy_animations"] = "OFF";
+    #endif
+    #ifdef HTTP_OTA
+      json["esp8266_http_updateserver"] = "ON";
+    #endif
+    #ifdef ENABLE_OTA
+      json["arduino_ota"] = "ON";
+    #endif
+    #ifdef ENABLE_STATE_SAVE_SPIFFS
+      json["state_save"] = "SPIFFS";
+    #endif
+    #ifdef ENABLE_STATE_SAVE_EEPROM
+      json["state_save"] = "EEPROM";
     #endif

     String json_str;


cleaned up

cleaned up

--- Arduino/_firmware3/_firmware3.ino
+++ Arduino/_firmware3/_firmware3.ino
@@ -143,7 +143,7 @@
      double time_delta = millis() - calc_time_ms;
      //Serial.println(water_level_delta);
     // Serial.println(time_delta/1000);
-     flow_rate_cc_per_sec = ( water_level_delta ) / (time_delta/1000);
+     flow_rate_cc_per_sec = ( water_level_delta ) / (time_delta/1000.0);

      //set the last calculation references
      flow_calc_water_level_cm = water_level_cm;
@@ -528,8 +528,20 @@

 double* sensors_list[] = {&shaftTemp, &ambient_temperature, &casing_temperature, &gland_temperature,
 &rpm, &load1_res2, &load2_res2, &flow_rate_cc_per_sec, &flowrate, &position1_mm, &position2_mm};
-
-
+/* 1. NodeID
+ * 2. shaftTemp
+ * 3. ambient_temperature
+ * 4. casing_temperature
+ * 5. gland_temperature
+ * 6. rpm
+ * 7. load1_res2
+ * 8. load2_res2
+ * 9. flow_rate_cc_per_sec
+ * 10.flowrate
+ * 11. posistion1_mm
+ * 12. position2_MM
+ * */
+int i;
 void loop() {
   position_sensors();
   fluid_level_sensor();
@@ -539,7 +551,7 @@
   film_sensor();

-    int i;
+
   if (millis() - last_print_time >= PRINT_DELAY){


Use StringIPaddress() by sticilface

Use StringIPaddress() by sticilface

--- ESP8266HueEmulator/ESP8266HueEmulator.ino
+++ ESP8266HueEmulator/ESP8266HueEmulator.ino
@@ -13,12 +13,6 @@
 #include "ESP8266SSDP.h"
 #include <NeoPixelBus.h> // NeoPixelAnimator branch
 #include <ArduinoJson.h>
-
-// The follwing is needed in order to fill ipString with a String that contains the IP address
-extern "C" {
-#include "ip_addr.h"
-}
-char ipChars[16];

 #include "/secrets.h" // Delete this line and populate the following
 //const char* ssid = "********";
@@ -209,9 +203,7 @@
   }

   macString = String(WiFi.macAddress());
-
-  os_sprintf(ipChars, IPSTR, IP2STR(WiFi.localIP()));
-  ipString = String(ipChars);
+  ipString = StringIPaddress();

   Serial.print("Starting HTTP at ");
   Serial.print(WiFi.localIP());
@@ -297,3 +289,15 @@
   }
   return sub;
 }
+
+String StringIPaddress()
+{
+  String LocalIP = "";
+  IPAddress myaddr = WiFi.localIP();
+  for (int i = 0; i < 4; i++)
+  {
+  LocalIP += String(myaddr[i]);
+  if (i < 3) LocalIP += ".";
+  }
+  return LocalIP;
+}


Made the output format of the Serial example easier to parse by putting all the numbers in consistent columns and right-aligning them.

--- LSM303/examples/Serial/Serial.ino
+++ LSM303/examples/Serial/Serial.ino
@@ -3,31 +3,24 @@

 LSM303 compass;

-void setup() {
+char report[80];
+
+void setup()
+{
   Serial.begin(9600);
   Wire.begin();
   compass.init();
   compass.enableDefault();
 }

-void loop() {
+void loop()
+{
   compass.read();

-  Serial.print("A ");
-  Serial.print("X: ");
-  Serial.print((int)compass.a.x);
-  Serial.print(" Y: ");
-  Serial.print((int)compass.a.y);
-  Serial.print(" Z: ");
-  Serial.print((int)compass.a.z);
-
-  Serial.print(" M ");
-  Serial.print("X: ");
-  Serial.print((int)compass.m.x);
-  Serial.print(" Y: ");
-  Serial.print((int)compass.m.y);
-  Serial.print(" Z: ");
-  Serial.println((int)compass.m.z);
+  snprintf(report, sizeof(report), "%8d%8d%8d%8d%8d%8d",
+    compass.a.x, compass.a.y, compass.a.z,
+    compass.m.x, compass.m.y, compass.m.z);
+  Serial.println(report);

   delay(100);
 }


Update Pegasus_controller.ino

Update Pegasus_controller.ino

-changed throttle to use new Pot class
-added throttleTrim which modifies the min throttle range
-removed global variables scrollPeriod, pidGainStep, and navGainStep in favor of inline values
-changed operator(kill switch) to a capacitive sensor

-changed DEBUG #def to check bool value rather than #ifdef

--- Pegasus_controller/Pegasus_controller.ino
+++ Pegasus_controller/Pegasus_controller.ino
@@ -3,13 +3,15 @@
 #include "ZETA1.h"
 #include "Pegasus_CtrlData.h"
 #include "Stick.h"
+#include "Pot.h"
+#include "CapacitiveSwitch.h"
 #include "Wire.h"
 #include "Pegasus_ConfigMem.h"
 #include <Adafruit_GFX.h>
 #include <Adafruit_SSD1306.h>

-//#define DEBUG
-#ifdef DEBUG
+#define DEBUG false
+#if DEBUG
 #define Serial_begin(x) Serial.begin(x);
 #define print(x) Serial.print(x);
 #else
@@ -29,22 +31,26 @@
 Stick stickYaw;
 Stick stickPitch;
 Stick stickRoll;
-Stick stickThrottle;
-
-byte rollPin = 8;
-byte pitchPin = 7;
-byte yawPin = 6;
-byte throttlePin = 9;
+Pot stickThrottle;
+Pot stickThrottleTrim;
+byte throttleTrimFrac = 4;//4096
+CapacitiveSwitch operatorSwitch;
+
+byte rollPin = 9;//A9
+byte pitchPin = 8;//A8
+byte yawPin = 7;//A7
+byte throttlePin = 2;//A2
+byte throttleTrimPin = 3;//A3

 Adafruit_SSD1306 display(6);

-byte operatorPin = 17;
+byte operatorPin = 3;
 bool operatorButton_PS = false;
-byte enterPin = 3;
+byte enterPin = 0;
 bool enterButton_PS = false;
-byte upPin = 4;
+byte upPin = 1;
 bool upButton_PS = false;
-byte dnPin = 5;
+byte dnPin = 2;
 bool dnButton_PS = false;
 byte edMode = 0;
 bool edModeEntered = false;
@@ -91,14 +97,11 @@
 #define PID_ROLL_I_BIT              19
 #define PID_ROLL_D_BIT              20

-short pidGainStep = 1;
-short navRangeStep = 1;
 bool pendingUpdate_pidYaw = false;
 bool pendingUpdate_pidPitch = false;
 bool pendingUpdate_pidRoll = false;

 void setup() {
-  pinMode(operatorPin, INPUT);
   pinMode(enterPin, INPUT_PULLUP);
   pinMode(upPin, INPUT_PULLUP);
   pinMode(dnPin, INPUT_PULLUP);
@@ -134,19 +137,25 @@
   }
   print("Complete\n");

-  //Stick.config(byte pinX, float outerEdge, float deadZone, float range)
-  stickYaw.config( yawPin, 0.0, 15.0, 2.0);
-  stickPitch.config( pitchPin, 0.0, 15.0, 2.0);
-  stickRoll.config( rollPin, 0.0, 15.0, 2.0);
-  stickThrottle.config( throttlePin, 0.0, 15.0, 2.0);
+  //Stick.config(byte pinX, float outerEdge, float deadZone, float range, invert)
+  stickYaw.config( yawPin, 0.0, 15.0, 2.0, false);
+  stickPitch.config( pitchPin, 0.0, 15.0, 2.0, true);
+  stickRoll.config( rollPin, 0.0, 15.0, 2.0, true);
   stickYaw.calibrate();
   stickPitch.calibrate();
   stickRoll.calibrate();
-  stickThrottle.calibrate();
-  print("stick config complete\n");
+
+  stickThrottle.config( throttlePin, 1024.0, true);
+  stickThrottleTrim.config( throttleTrimPin, 256.0, true);
+
+  //CapacitiveSwitch.config(pin, threshold, offset, countRange)
+  operatorSwitch.config(operatorPin, 1650, 100, 200);
+  operatorSwitch.calibrate();
+
+  print("inputs config complete\n");

   loadConfigFromMem();
-
+
   display.clearDisplay();
   display.println("kk");
   display.display();
@@ -168,11 +177,12 @@
 unsigned long lastScrollTime = millis();
 void pollInputs(){
     // check kill switch
-    bool operatorButton = digitalRead(operatorPin);
+    bool operatorButton = operatorSwitch.check(operatorButton_PS);
     bool operatorOnPress = !operatorButton_PS && operatorButton;
     bool operatorOnRelease = operatorButton_PS && !operatorButton;
     operatorButton_PS = operatorButton;
     if(operatorOnPress){ // on key press
+        //Serial.printf("operatorOnPress:%ld\n", temp);
         display.clearDisplay(); display.setCursor(0,0); display.println("Fly"); display.display();
         pendingUpdate_pidYaw = true;
         pendingUpdate_pidPitch = true;
@@ -180,6 +190,7 @@
         resetNav();
     }
     if(operatorOnRelease){ // on key release
+        //Serial.printf("operatorOnRelease:%ld\n", temp);
         display.clearDisplay(); display.setCursor(0,0); display.println("Kill Power"); display.display();
     }

@@ -216,7 +227,7 @@
         }
     }else{
         if(enterOnRelease){
-            scrollPeriod = 50;
+            setScrollPeriod();
             edModeEntered = true;
             displayEdModeData(true);
         }
@@ -234,6 +245,37 @@
                 lastScrollTime = millis();
             }
         }
+    }
+}
+
+void setScrollPeriod(){
+    switch (edMode){
+        // Nav Mode
+        case ED_MODE_YAW:
+        case ED_MODE_PITCH:
+        case ED_MODE_ROLL:
+        case ED_MODE_THROTTLE:
+            scrollPeriod = 200; break;
+        // Nav Rotation Range
+        case ED_RANGE_YAW:
+        case ED_RANGE_PITCH:
+        case ED_RANGE_ROLL:
+            scrollPeriod = 200; break;
+        case ED_RANGE_THROTTLE:
+            scrollPeriod = 10; break;
+        // PID Yaw
+        case ED_PID_YAW_P:
+        case ED_PID_YAW_I:
+        case ED_PID_YAW_D:
+        // PID Pitch
+        case ED_PID_PITCH_P:
+        case ED_PID_PITCH_I:
+        case ED_PID_PITCH_D:
+        // PID Roll
+        case ED_PID_ROLL_P:
+        case ED_PID_ROLL_I:
+        case ED_PID_ROLL_D:
+            scrollPeriod = 50; break;
     }
 }

@@ -354,7 +396,7 @@
                     ctrl.navRangeYaw = mem.read_NavRange_Yaw_Abs();
                     break;
             }
-            stickYaw.setRange( float(ctrl.navRangeYaw));
+            stickYaw.setOutputRange( float(ctrl.navRangeYaw));
             break;
         case ED_MODE_PITCH:
             print("ED_MODE_PITCH\n");
@@ -368,7 +410,7 @@
                     ctrl.navRangePitch = mem.read_NavRange_Pitch_Abs();
                     break;
             }
-            stickPitch.setRange( float(ctrl.navRangePitch));
+            stickPitch.setOutputRange( float(ctrl.navRangePitch));
             break;
         case ED_MODE_ROLL:
             print("ED_MODE_ROLL\n");
@@ -382,7 +424,7 @@
                     ctrl.navRangeRoll = mem.read_NavRange_Roll_Abs();
                     break;
             }
-            stickRoll.setRange( float(ctrl.navRangeRoll));
+            stickRoll.setOutputRange( float(ctrl.navRangeRoll));
             break;
         case ED_MODE_THROTTLE:
             print("ED_MODE_THROTTLE\n");
@@ -396,14 +438,15 @@
                     ctrl.navRangeThrottle = mem.read_NavRange_Throttle_Abs();
                     break;
             }
-            stickThrottle.setRange( float(ctrl.navRangeThrottle));
+            stickThrottle.setOutputRange( float(ctrl.navRangeThrottle));
+            stickThrottleTrim.setOutputRange( float(ctrl.navRangeThrottle/throttleTrimFrac));
             break;

         // Nav Range
         case ED_RANGE_YAW:
             print("ED_RANGE_YAW\n");
-            ctrl.navRangeYaw += up ? navRangeStep : -navRangeStep;
-            stickYaw.setRange( float(ctrl.navRangeYaw));
+            ctrl.navRangeYaw += up ? 1 : -1;
+            stickYaw.setOutputRange( float(ctrl.navRangeYaw));
             switch(ctrl.navModeYaw){
                 case ctrl.FLY_REL:
                     bitSet(edMode_dirty, NAVRANGE_YAW_REL_BIT);
@@ -415,8 +458,8 @@
             break;
         case ED_RANGE_PITCH:
             print("ED_RANGE_PITCH\n");
-            ctrl.navRangePitch += up ? navRangeStep : -navRangeStep;
-            stickPitch.setRange( float(ctrl.navRangePitch));
+            ctrl.navRangePitch += up ? 1 : -1;
+            stickPitch.setOutputRange( float(ctrl.navRangePitch));
             switch(ctrl.navModePitch){
                 case ctrl.FLY_REL:
                     bitSet(edMode_dirty, NAVRANGE_PITCH_REL_BIT);
@@ -428,8 +471,8 @@
             break;
         case ED_RANGE_ROLL:
             print("ED_RANGE_ROLL\n");
-            ctrl.navRangeRoll += up ? navRangeStep : -navRangeStep;
-            stickRoll.setRange( float(ctrl.navRangeRoll));
+            ctrl.navRangeRoll += up ? 1 : -1;
+            stickRoll.setOutputRange( float(ctrl.navRangeRoll));
             switch(ctrl.navModeRoll){
                 case ctrl.FLY_REL:
                     bitSet(edMode_dirty, NAVRANGE_ROLL_REL_BIT);
@@ -441,8 +484,9 @@
             break;
         case ED_RANGE_THROTTLE:
             print("ED_RANGE_THROTTLE\n");
-            ctrl.navRangeThrottle += up ? navRangeStep : -navRangeStep;
-            stickThrottle.setRange( float(ctrl.navRangeThrottle));
+            ctrl.navRangeThrottle += up ? 64 : -64;
+            stickThrottle.setOutputRange( float(ctrl.navRangeThrottle));
+            stickThrottleTrim.setOutputRange( float(ctrl.navRangeThrottle/throttleTrimFrac));
             switch(ctrl.navModeThrottle){
                 case ctrl.FLY_REL:
                     bitSet(edMode_dirty, NAVRANGE_THROTTLE_REL_BIT);
@@ -456,21 +500,21 @@
         // PID Yaw
         case ED_PID_YAW_P:
             print("ED_PID_YAW_P\n");
-            ctrl.Kp_yaw += up ? pidGainStep : -pidGainStep;
+            ctrl.Kp_yaw += up ? 1 : -1;
             ctrl.Kp_yaw = max(min(32767, ctrl.Kp_yaw), 0);
             bitSet(edMode_dirty, PID_YAW_P_BIT);
             pendingUpdate_pidYaw = true;
             break;
         case ED_PID_YAW_I:
             print("ED_PID_YAW_I\n");
-            ctrl.Ki_yaw += up ? pidGainStep : -pidGainStep;
+            ctrl.Ki_yaw += up ? 1 : -1;
             ctrl.Ki_yaw = max(min(32767, ctrl.Ki_yaw), 0);
             bitSet(edMode_dirty, PID_YAW_I_BIT);
             pendingUpdate_pidYaw = true;
             break;
         case ED_PID_YAW_D:
             print("ED_PID_YAW_D\n");
-            ctrl.Kd_yaw += up ? pidGainStep : -pidGainStep;
+            ctrl.Kd_yaw += up ? 1 : -1;
             ctrl.Kd_yaw = max(min(32767, ctrl.Kd_yaw), 0);
             bitSet(edMode_dirty, PID_YAW_D_BIT);
             pendingUpdate_pidYaw = true;
@@ -479,21 +523,21 @@
         // PID Pitch
         case ED_PID_PITCH_P:
             print("ED_PID_PITCH_P\n");
-            ctrl.Kp_pitch += up ? pidGainStep : -pidGainStep;
+            ctrl.Kp_pitch += up ? 1 : -1;
             ctrl.Kp_pitch = max(min(32767, ctrl.Kp_pitch), 0);
             bitSet(edMode_dirty, PID_PITCH_P_BIT);
             pendingUpdate_pidPitch = true;
             break;
         case ED_PID_PITCH_I:
             print("ED_PID_PITCH_I\n");
-            ctrl.Ki_pitch += up ? pidGainStep : -pidGainStep;
+            ctrl.Ki_pitch += up ? 1 : -1;
             ctrl.Ki_pitch = max(min(32767, ctrl.Ki_pitch), 0);
             bitSet(edMode_dirty, PID_PITCH_I_BIT);
             pendingUpdate_pidPitch = true;
             break;
         case ED_PID_PITCH_D:
             print("ED_PID_PITCH_D\n");
-            ctrl.Kd_pitch += up ? pidGainStep : -pidGainStep;
+            ctrl.Kd_pitch += up ? 1 : -1;
             ctrl.Kd_pitch = max(min(32767, ctrl.Kd_pitch), 0);
             bitSet(edMode_dirty, PID_PITCH_D_BIT);
             pendingUpdate_pidPitch = true;
@@ -502,21 +546,21 @@
         // PID Roll
         case ED_PID_ROLL_P:
             print("ED_PID_ROLL_P\n");
-            ctrl.Kp_roll += up ? pidGainStep : -pidGainStep;
+            ctrl.Kp_roll += up ? 1 : -1;
             ctrl.Kp_roll = max(ctrl.Kp_roll, 0);
             bitSet(edMode_dirty, PID_ROLL_P_BIT);
             pendingUpdate_pidRoll = true;
             break;
         case ED_PID_ROLL_I:
             print("ED_PID_ROLL_I\n");
-            ctrl.Ki_roll += up ? pidGainStep : -pidGainStep;
+            ctrl.Ki_roll += up ? 1 : -1;
             ctrl.Ki_roll = max(ctrl.Ki_roll, 0);
             bitSet(edMode_dirty, PID_ROLL_I_BIT);
             pendingUpdate_pidRoll = true;
             break;
         case ED_PID_ROLL_D:
             print("ED_PID_ROLL_D\n");
-            ctrl.Kd_roll += up ? pidGainStep : -pidGainStep;
+            ctrl.Kd_roll += up ? 1 : -1;
             ctrl.Kd_roll = max(ctrl.Kd_roll, 0);
             bitSet(edMode_dirty, PID_ROLL_D_BIT);
             pendingUpdate_pidRoll = true;
@@ -549,48 +593,53 @@

 void sendPacket_Nav() {
   ctrl.control_code = ctrl.NAV_CODE;
-
-
-
-
   stickYaw.update();
   stickPitch.update();
   stickRoll.update();
   stickThrottle.update();
-  //Serial.printf("left x:%f y:%f\t right x:%f y:%f\n", stickYaw.v, stickPitch.v, stickRoll.v, stickThrottle.v);
+  stickThrottleTrim.update();
+  /*
+  print("roll:");print(stickRoll.v);
+  print(", pitch:");print(stickPitch.v);
+  print(", yaw:");print(stickYaw.v);
+  print(", throttle:");print(stickThrottle.v);
+  print(", throttleTrim:");print(stickThrottleTrim.v);
+  print("\n");
+  */
   switch (ctrl.navModeYaw){
     case ctrl.FLY_ABS:
-        ctrl.yawf = stickYaw.v * -1.0; break;
+        ctrl.yawf = stickYaw.v; break;
     case ctrl.FLY_REL:
-        ctrl.yawf = wrapAngle(ctrl.yawf + (stickYaw.v * -1) ); break;
+        ctrl.yawf = wrapAngle(ctrl.yawf + stickYaw.v ); break;
   }
   ctrl.buf[0] = int(ctrl.yawf * 100.0);

   switch (ctrl.navModePitch){
     case ctrl.FLY_ABS:
-        ctrl.pitchf = stickPitch.v * -1; break;
+        ctrl.pitchf = stickPitch.v; break;
     case ctrl.FLY_REL:
-        ctrl.pitchf = wrapAngle(ctrl.pitchf + (stickPitch.v * -1)); break;
+        ctrl.pitchf = wrapAngle(ctrl.pitchf + stickPitch.v); break;
   }
   ctrl.buf[1] = int(ctrl.pitchf * 100.0);

   switch (ctrl.navModeRoll){
     case ctrl.FLY_ABS:
-        ctrl.rollf = stickRoll.v * -1; break;
+        ctrl.rollf = stickRoll.v; break;
     case ctrl.FLY_REL:
-        ctrl.rollf = wrapAngle(ctrl.rollf + (stickRoll.v * -1)); break;
+        ctrl.rollf = wrapAngle(ctrl.rollf + stickRoll.v); break;
   }
   ctrl.buf[2] = int(ctrl.rollf * 100.0);

   switch (ctrl.navModeThrottle){
     case ctrl.FLY_ABS:
-        ctrl.throttlef = max(stickThrottle.v * 2 * -1, 0.0); break;
+        ctrl.throttlef = stickThrottle.v; break;
     case ctrl.FLY_REL:
-        ctrl.throttlef += stickThrottle.v * -1;
+        ctrl.throttlef += stickThrottle.v;
         ctrl.throttlef = max(ctrl.throttlef, 0.0);
         ctrl.throttlef = min(ctrl.throttlef, 65535.0);
         break;
   }
+  ctrl.throttlef = mapf(ctrl.throttlef, 0.0, 65535.0, stickThrottleTrim.v, 65535.0);
   ctrl.buf[3] = int(ctrl.throttlef);
   ctrl.pack(buf);
   radio.startTX(buf);
@@ -602,6 +651,7 @@
   print(ctrl.rollf); print(" ");
   print(ctrl.throttlef); print(" ");
   print(millis()); print("\n");
+
 }
 void sendPacket_PID_yaw() {
   print("PID_yaw ");
@@ -653,7 +703,7 @@
         case ctrl.FLY_REL:
             ctrl.navRangeYaw = mem.read_NavRange_Yaw_Rel(); break;
     }
-    stickYaw.setRange( float(ctrl.navRangeYaw));
+    stickYaw.setOutputRange( float(ctrl.navRangeYaw));

     switch (ctrl.navModePitch) {
         case ctrl.FLY_ABS:
@@ -661,7 +711,7 @@
         case ctrl.FLY_REL:
             ctrl.navRangePitch = mem.read_NavRange_Pitch_Rel(); break;
     }
-    stickPitch.setRange( float(ctrl.navRangePitch));
+    stickPitch.setOutputRange( float(ctrl.navRangePitch));

     switch (ctrl.navModeRoll) {
         case ctrl.FLY_ABS:
@@ -669,7 +719,7 @@
         case ctrl.FLY_REL:
             ctrl.navRangeRoll = mem.read_NavRange_Roll_Rel(); break;
     }
-    stickRoll.setRange( float(ctrl.navRangeRoll));
+    stickRoll.setOutputRange( float(ctrl.navRangeRoll));

     switch (ctrl.navModeThrottle) {
         case ctrl.FLY_ABS:
@@ -677,7 +727,8 @@
         case ctrl.FLY_REL:
             ctrl.navRangeThrottle = mem.read_NavRange_Throttle_Rel(); break;
     }
-    stickThrottle.setRange( float(ctrl.navRangeThrottle));
+    stickThrottle.setOutputRange( float(ctrl.navRangeThrottle));
+    stickThrottleTrim.setOutputRange( float(ctrl.navRangeThrottle/throttleTrimFrac));

     print("NavRange yaw: "); print(ctrl.navRangeYaw);
     print(" pitch: "); print(ctrl.navRangePitch);
@@ -816,3 +867,7 @@
     }
     return v;
 };
+
+float mapf(float value, float low1, float high1, float low2, float high2){
+  return low2 + (value-low1) * (high2-low2) / (high1-low1);
+}


Prepare digits for inclusion in countdown

--- countdown/digits.ino
+++ countdown/digits.ino
@@ -4,7 +4,8 @@
 #define COLS 10
 #define NUM_LEDS (ROWS*COLS)

-CRGB leds[NUM_LEDS];
+CRGB counter_leds[NUM_LEDS];
+
 // Return 0-based led index for 0-based x and y grid co-ordinate values
 // The LED string snakes through the grid, so every row the positive x direction switches
 uint8_t xy2i(uint8_t x, uint8_t y){
@@ -100,37 +101,36 @@
     Serial.println();
     for(uint8_t x=0; x!=3; ++x){
       if(digits[c][x+3*y]){
-        leds[xy2i(dx+x,dy+y)] = colour;
+        counter_leds[xy2i(dx+x,dy+y)] = colour;
       } else {
-        leds[xy2i(dx+x,dy+y)] = CRGB::Black;
+        counter_leds[xy2i(dx+x,dy+y)] = CRGB::Black;
       }
     }
   }
 }

-uint16_t seconds_left = 90*60;
-void writeDigits(){
+void writeDigits(uint16_t secs){
   // minutes left: seconds / 60 ;
-  uint8_t minutes_left = seconds_left/60;
+  uint8_t mins = secs/60;
   // 10 minutes left: minutes_left / 10
-  writeDigit(minutes_left/10, 0, 0, CRGB::OrangeRed);
+  writeDigit(mins/10, 0, 0, CRGB::Magenta);
   // last digit: minutes left % 10
-  writeDigit(minutes_left % 10, 5, 0, CRGB::OrangeRed);
+  writeDigit(mins % 10, 5, 0, CRGB::Magenta);
   // Seconds left: seconds_left-60*mnutes_left
-  writeDigit((seconds_left-60*minutes_left)/10, 2, 5, CRGB::Cyan);
-  writeDigit((seconds_left-60*minutes_left)%10, 7, 5, CRGB::Cyan);
+  writeDigit((secs-60*mins)/10, 2, 5, CRGB::Cyan);
+  writeDigit((secs-60*mins)%10, 7, 5, CRGB::Cyan);
 }

 void setup(){
   // Delay in case the LEDs draw a lot of current and kill the power supply
   delay(1000);
   // Let the controller know we're using WS2801 leds, and give a pointer to the current colour array
-  LEDS.addLeds<WS2801, RGB>(leds, NUM_LEDS);
+  LEDS.addLeds<WS2801, RGB>(counter_leds, NUM_LEDS);
   // Limit the brightness somewhat (scale is 0-255)
   LEDS.setBrightness(48);

   for(uint8_t i=0; i<NUM_LEDS; ++i){
-    leds[i] = CRGB::Black;
+    counter_leds[i] = CRGB::Black;
   }

   LEDS.show();
@@ -139,10 +139,10 @@
 }

+uint16_t seconds_left = 90*60;

 void loop(){
-  writeDigits();
-  seconds_left--;
+  writeDigits(seconds_left--);
   LEDS.show();
   delay(500);
 }


Show movie with Intent

Show movie with Intent

This script doesn't work correctly.

--- ScriptingAccessory/firmware/play_movie/play_movie.ino
+++ ScriptingAccessory/firmware/play_movie/play_movie.ino
@@ -22,9 +22,11 @@
 // Prints an ever-increasing counter, and writes back anything
 // it receives.
 #define STATE_INIT 0
-#define STATE_WRITE 1
-#define STATE_WRITE_DONE 2
-#define STATE_READ 3
+#define STATE_WRITE_FOR_CONNECT 1
+#define STATE_WRITE_FOR_DISCONNECT 2
+#define STATE_WRITE_DONE_FOR_CONNECT 3
+#define STATE_WRITE_DONE_FOR_DISCONNECT 4
+#define STATE_READ 5

 #define STRING_EOS "#_EOS_EOS_EOS_EOS_EOS_"
 #define COMMAND_START_TO_LOAD 0xFF
@@ -39,24 +41,32 @@
   switch (state) {
     case STATE_INIT:
       if (Serial.peek() == 0xFF ) {
-        state = STATE_WRITE;
+        state = STATE_WRITE_FOR_CONNECT;
       }
       break;

-    case STATE_WRITE:
+    case STATE_WRITE_FOR_CONNECT:
       Serial.println("import android,time");
       Serial.println("droid = android.Android()");
       Serial.println("droid.makeToast('Play Movie')");
-      Serial.println("droid.webViewShow('http://www.youtube.com/watch?v=pdbSLpBgQ2I', True)");
-      //Serial.println("droid.webViewShow('https://docs.google.com/file/d/0B14PZnE7DkYmck9Yc2tlcTZwTnM/edit?usp=sharing', True)");
-
-      state = STATE_WRITE_DONE;
+      Serial.println("droid.startActivityIntent(makeIntent('android.intent.action.VIEW', 'https://docs.google.com/file/d/0B14PZnE7DkYmck9Yc2tlcTZwTnM/edit?usp=sharing'))");
+      //Serial.println("droid.webViewShow('http://youtu.be/0p3vL0zuNYE', True)");
+      state = STATE_WRITE_DONE_FOR_CONNECT;
       break;

-    case STATE_WRITE_DONE:
-     Serial.print(STRING_EOS);
+    case STATE_WRITE_DONE_FOR_CONNECT:
+      Serial.print(STRING_EOS);
+      state = STATE_WRITE_FOR_DISCONNECT;
+      break;

+    case STATE_WRITE_FOR_DISCONNECT:
+      state = STATE_WRITE_DONE_FOR_DISCONNECT;
+      break;
+
+    case STATE_WRITE_DONE_FOR_DISCONNECT:
+      Serial.print(STRING_EOS);
       state = STATE_READ;
+      break;

     case STATE_READ:
     default:


Cleaning

Cleaning

--- Pan_Tilt_laser/Pan_Tilt_laser.ino
+++ Pan_Tilt_laser/Pan_Tilt_laser.ino
@@ -27,6 +27,7 @@
 #include "stuServo.h"
 #include "stuPanTilt.h"
 #include "stuLaser.h"
+#include "missileswitch.h"

 #define BAUD_RATE 115200
@@ -56,9 +57,7 @@

 StuLaser laser(LASER_PIN);

-
-
-mSwitch Missileswitch(MS_SWITCH_PIN, MS_LED_PIN);
+Missileswitch mSwitch(MS_SWITCH_PIN, MS_LED_PIN);

 void setup() {

@@ -73,10 +72,10 @@
     mSwitch.ledState(0);
     sleepState = 1;

-    while(!mSwitch.switchState()){
-      millis();
-    }
-  }
+      while(!mSwitch.switchState()){
+        millis();
+      }
+    }
   else {
     // turn LED on:
     mSwitch.ledState(0);
@@ -105,7 +104,7 @@
   laser.fire(1);
   delay(2000);

-  Serial.println("setup complete");
+  Serial.println(F("setup complete"));
 //  attachInterrupt(0, sleepInt, FALLING);
 }

@@ -113,10 +112,10 @@

 void loop() {

-  if(digitalRead(switchPin) == LOW){
+  if(!mSwitch.switchState()){

     laser.fire(0);
-    digitalWrite(ledPin, HIGH);
+    mSwitch.ledState(0);
     panTiltX.angle = panTiltX.midAngle;
     panTiltY.angle = panTiltY.midAngle;
     panTilt.updateAngles();
@@ -125,11 +124,11 @@
 //    attachInterrupt(0, wake, RISING);

     panTilt.detach();
-    while(digitalRead(switchPin) == LOW){
+    while(!mSwitch.switchState()){
       delay(10);

     }
-    digitalWrite(ledPin, LOW);
+    mSwitch.ledState(1);
     panTilt.begin();
     laser.fire(1);

@@ -289,14 +288,8 @@
   static unsigned long oldTime;
   if(mSeconds - oldTime > hbInterval){

-    pinMode(ledPin, OUTPUT);
-    digitalWrite(ledPin, LOW);
-    delay(100);
-    digitalWrite(ledPin, HIGH);
-    delay(100);
-    digitalWrite(ledPin, LOW);
-    delay(100);
-    digitalWrite(ledPin, HIGH);
+
+    mSwitch.heartBeat(3);
     oldTime = mSeconds;
   }
 }


removing unnecessary defines.

removing unnecessary defines.

--- src/rx5808-pro-diversity-oled/rx5808-pro-diversity-oled.ino
+++ src/rx5808-pro-diversity-oled/rx5808-pro-diversity-oled.ino
@@ -82,10 +82,6 @@
 // NOTE: good values are in the range of 100-200ms
 // shorter values will make it more reactive, but may lead to double trigger
 #define KEY_DEBOUNCE 200
-
-// Set you TV format (PAL = Europe = 50Hz, NTSC = INT = 60Hz)
-//#define TV_FORMAT NTSC
-#define TV_FORMAT PAL

 #define led 13
 // RSSI default raw range
@@ -117,16 +113,6 @@

 #define CHANNEL_MAX 39
 #define CHANNEL_MIN 0
-
-#define TV_COLS 128
-#define TV_ROWS 96
-#define TV_Y_MAX TV_ROWS-1
-#define TV_X_MAX TV_COLS-1
-#define TV_SCANNER_OFFSET 14
-#define SCANNER_BAR_SIZE 52
-#define SCANNER_LIST_X_POS 54
-#define SCANNER_LIST_Y_POS 16
-#define SCANNER_MARKER_SIZE 1

 #define EEPROM_ADR_STATE 0
 #define EEPROM_ADR_TUNE 1
@@ -263,7 +249,7 @@

     // init TV system
-    char retVal = 0;//TV.begin(TV_FORMAT, TV_COLS, TV_ROWS);
+    char retVal = 0;
     // 0 if no error.
     // 1 if x is not divisable by 8.
     // 2 if y is to large (NTSC only cannot fill PAL vertical resolution by 8bit limit)
@@ -550,7 +536,6 @@
                 display.print("5945");
                 // trigger new scan from begin
                 channel=CHANNEL_MIN;
-                writePos=SCANNER_LIST_X_POS; // reset channel list
                 channelIndex = pgm_read_byte_near(channelList + channel);
                 rssi_best=RSSI_MIN_VAL;
                 scan_start=1;
@@ -1018,7 +1003,6 @@
         else
         {
             channel=CHANNEL_MIN;
-            writePos=SCANNER_LIST_X_POS; // reset channel list
             if(state == STATE_RSSI_SETUP)
             {
                 if(!rssi_setup_run--)
@@ -1056,7 +1040,6 @@
             delay(KEY_DEBOUNCE); // debounce
             last_state=255; // force redraw by fake state change ;-)
             channel=CHANNEL_MIN;
-            writePos=SCANNER_LIST_X_POS; // reset channel list
             scan_start=1;
             rssi_best=RSSI_MIN_VAL;
         }


Add the onload stuff

Add the onload stuff

--- Arduino/sketch_mar14b/sketch_mar14b.ino
+++ Arduino/sketch_mar14b/sketch_mar14b.ino
@@ -119,35 +119,21 @@
 bool debug = false;

 String getTD(String id, String value){
-return (""+value+"	");
+return ((String)("") + value + (String)("	"));
 }

 void printCSS(WiFiClient client){
 client.println("");
 }

 void printJavascript(WiFiClient client){
 client.println("");
 }

@@ -155,27 +141,31 @@
   client.println("");
   printCSS(client);
   printJavascript(client);
-  client.println("

"+getTD("*.*","&#x21D8"));
+  client.println("");
+  client.println("Color picker <input type=\"color\" id=\"selcol\" style=\"width: 2em; height: 1em;\">
");
+  client.println("

"+getTD("*.*","&#x21D8"));
   for (int i=0; i<8; i++)
-    client.println(getTD("*."+i, "&#x21D3"));
+    client.println(getTD("*."+String(i), "&#x21D3"));
   client.println(getTD("?.7","&#x25A7"));
   client.println("

");
   client.println("
");
   for (int i=0; i<8; i++) {
-    client.println("
"+getTD(i+".*","&#x21D2"));
+    client.println("
"+getTD(String(i)+".*","&#x21D2"));
     for (int j=0; j<8; j++) {
-      client.println(getTD(i+"."+j,"&#x25C9"));
-    }
-    client.println(getTD("i.-","&#x25A5"));
+      client.println(getTD(String(i)+"."+String(j),"&#x25C9"));
+    }
+    client.println(getTD(String(i)+".-","&#x25A5"));
     client.println("
");
   }
-  client.println("

");
-  client.println("

"+getTD("-.-","&#x25A9"));
+  client.println("
");
+  client.println("
"+getTD("-.-","&#x25A9"));
   for (int i=0; i<8; i++) {
-    client.println(getTD("-."+i, "&#x25A4"));
+    client.println(getTD("-."+String(i), "&#x25A4"));
   }
   client.println(getTD("-?","&#x25A8"));
-  client.println("

");
+  client.println("

<button onclick=\"javascript:sndarr();\" style=\"width: 15em;\">Send matrix. ⇶</button><canvas id=\"canvas1\" width=\"8px\" height=\"8px\" style=\"border: thick; border-color: white\"></canvas>

");
+  client.println("

<input id=\"msg\" type=\"text\" style=\"width: 15em\">

●Fgd	◘Bkg

<button style=\"width: 15em\" onclick=\"sendmsg()\">Send text.⤳</button>

");
+  client.println("");
   client.println("");
 }

@@ -519,7 +509,7 @@
   if (!client) {
     return;
   }
-  client.setTimeout(120000);
+  client.setTimeout(10000);
   // Read the first line of the request
   String req = client.readStringUntil('\r');
   client.flush();


Nam is pretty cool

Nam is pretty cool

--- 2018-FirefighterL1/Left_Right_Follow.ino
+++ 2018-FirefighterL1/Left_Right_Follow.ino
@@ -75,10 +75,19 @@
     turn(90); //turn left
     moveFoward(60); //move back into position for lowerRightRoom
     turn(-90);
-    moveFoward(5);
+    rollForward();
+    while(rightUltrasonic.getDistance() < closeToWall) {
+      delay(50);
+    }
+    stopRobot();
     lowerRightRoom();
   } else {
-    //proceed forward and get to the lower right room the short way
+    rollForward();
+    while (rightUltrasonic.getDistance() < closeToWall) {
+      delay(50);
+    }
+    stopRobot();
+    lowerRightRoom();
   }
   while(followDirection >= 7)
   {


make desktop the default value

make desktop the default value


Fix errors in ColorPicker.ino

Fix errors in ColorPicker.ino

Added proper namespaceing to gamma correction function and added missing
phase variable declaration.

--- TestPrograms/ColorPicker/ColorPicker.ino
+++ TestPrograms/ColorPicker/ColorPicker.ino
@@ -64,6 +64,7 @@

 void colorDemoLoop() {
    static long drawTock = millis();
+   static uint8_t phase = 0;
    long tick = millis();
    if ( tick > drawTock + 40 ) {
       CRGB sky = ColorFromPalette( skyPalette, phase );
@@ -72,7 +73,7 @@
       for ( uint8_t i = 0; i < NUM_COLOR_PICKER_LEDS; ++i ) {
          uint16_t colorIdx = ( i * 255 ) / NUM_COLOR_PICKER_LEDS;
          auto clr = ColorFromPalette( palette, colorIdx );
-         leds[ i ] = gammaCorrect( clr );
+         leds[ i ] = LedUtil::gammaCorrect( clr );
       }
       drawTock = tick;
    }


use window and diff

use window and diff

--- DanceFeather/DanceFeather.ino
+++ DanceFeather/DanceFeather.ino
@@ -11,8 +11,12 @@
 #include <PDM.h>
 #include <KickFFT.h>

-#define ACC_SIZE 128
-#define FFT_SIZE 256
+#define ACC_SIZE 64
+#define FFT_SIZE 512
+#define HANN_SIZE 20
+#define FS (16000.0 / ACC_SIZE)
+#define F2 4.0f
+#define END_INDEX ((uint16_t) (F2 / (FS / FFT_SIZE)))

 #define LED_PIN 13

@@ -31,11 +35,18 @@
 float humidity;
 int32_t mic;

+float fftBuffer[FFT_SIZE]; // fft buffer holds the half rectfifed differences
+float incomingWindow[HANN_SIZE];
+float hannWindow[HANN_SIZE];
+float prevWindowedVal;
+
+// accumulate incoming values to create low pass filter
 extern PDMClass PDM;
+float acc = 0;
+uint16_t numInAcc = 0;
+
+// raw values incoming from PDM
 short tempBuffer[256];  // buffer to read samples into, each sample is 16-bits
-float acc = 0;
-float fftBuffer[FFT_SIZE];
-uint16_t numInAcc = 0;
 volatile int samplesRead; // number of samples read

 void setup(void) {
@@ -58,6 +69,13 @@
   sht30.begin();
   PDM.onReceive(onPDMdata);
   PDM.begin(1, 16000);
+
+  // init hann window
+  for (int i = 0; i < HANN_SIZE ; i++) {
+    float sinVal = sin(PI * (i + HANN_SIZE) / (2.0f * HANN_SIZE));
+    hannWindow[i] = sinVal * sinVal;
+  }
+
 }

 void loop(void) {
@@ -289,20 +307,32 @@

 void addToFFT(float val) {
-  // Serial.println(val);
+  val = abs(val); // rectify val
+  float windowedVal = 0;
+  for (int i = HANN_SIZE - 1; i > 0; i--) {
+    incomingWindow[i] = incomingWindow[i - 1];
+    windowedVal += incomingWindow[i] * hannWindow[i];
+  }
+  windowedVal += val;
+  incomingWindow[0] = val;
+
   for (int i = FFT_SIZE - 1; i > 0; i--) {
     fftBuffer[i] = fftBuffer[i-1];
   }
-  fftBuffer[0] = val;
-  float fs = 16000/ACC_SIZE;
-  float mag[20];
-  float phase[20];
+
+  fftBuffer[0] = max(0, windowedVal - prevWindowedVal); // half recitify difference
+
+  prevWindowedVal = windowedVal;
+
+  float mag[END_INDEX];
+  float phase[END_INDEX];
   uint16_t startIndex, endIndex;
   // KickFFT<int32_t>::fft(fs, 0, 4, FFT_SIZE, fftBuffer, mag, startIndex, endIndex);
-  fft_phase(fs, 0, 4, FFT_SIZE, fftBuffer, mag, phase, startIndex, endIndex);
+  fft_phase(FS, 0, F2, FFT_SIZE, fftBuffer, mag, phase, startIndex, endIndex);
   updatePhase(mag, phase, startIndex, endIndex);
-  float hz = fs * _phaseRateAverage / 2 / PI;
-  // Serial.print("endIndex: "); Serial.println(endIndex);
+  float hz = FS * _phaseRateAverage / 2 / PI;
+  Serial.print("endIndex: "); Serial.println(endIndex);
+  Serial.print("END_INDEX: "); Serial.println(END_INDEX);
   // Serial.print("BPM: "); Serial.println(hz * 60);
   //Serial.print("radsPerUpdate: "); Serial.println(_phaseRateAverage);


Give the system some time to send data

Give the system some time to send data

--- barf_esp8266.ino
+++ barf_esp8266.ino
@@ -313,6 +313,7 @@
 		String("\n");

 	client.write(response.c_str(), response.length());
+	delay(1);
 	client.stop();

 	// Update activity timestamp