Adjusted tabs for Arduino IDE.

Adjusted tabs for Arduino IDE.

--- arduino/AnalogJoystickControl/AnalogJoystickControl.ino
+++ arduino/AnalogJoystickControl/AnalogJoystickControl.ino
@@ -69,45 +69,45 @@
 Servo thrusterVertical;

 void setup() {
-	// Set up Arduino pins to send servo signals to ESCs
-	thrusterLeft.attach(THRUSTER_LEFT);
-	thrusterRight.attach(THRUSTER_RIGHT);
-	thrusterVertical.attach(THRUSTER_VERTICAL);
+  // Set up Arduino pins to send servo signals to ESCs
+  thrusterLeft.attach(THRUSTER_LEFT);
+  thrusterRight.attach(THRUSTER_RIGHT);
+  thrusterVertical.attach(THRUSTER_VERTICAL);

-	// Set output signal to 1500 microsecond pulse (stopped command)
-	thrusterLeft.setMicroseconds(CENTER_THROTTLE);
-	thrusterRight.setMicroseconds(CENTER_THROTTLE);
-	thrusterVertical.setMicroseconds(CENTER_THROTTLE);
+  // Set output signal to 1500 microsecond pulse (stopped command)
+  thrusterLeft.writeMicroseconds(CENTER_THROTTLE);
+  thrusterRight.writeMicroseconds(CENTER_THROTTLE);
+  thrusterVertical.writeMicroseconds(CENTER_THROTTLE);

-	// Delay to allow time for ESCs to initialize
-	delay(1000);
+  // Delay to allow time for ESCs to initialize
+  delay(1000);
 }

 void loop() {
-	// Read the joysticks and use the Arduino "map" function to map the raw values
-	// to the desired output commands.
-	int forwardCommand  	=	map(analogRead(JS_ADC_0), // Read raw joystick value
-		                       		JS_CENTER_0-JS_DIR_0*JS_RANGE_0, // Joystick low value
-		                       		JS_CENTER_0+JS_DIR_0*JS_RANGE_0, // Joystick high value
-		               		        -MAX_FWD_REV_THROTTLE, // Command low value
-		                  		     MAX_FWD_REV_THROTTLE); // Command high value
-	int turnCommand 	 		=	map(analogRead(JS_ADC_1), // Read raw joystick value
-		                    			JS_CENTER_1-JS_DIR_1*JS_RANGE_1, // Joystick low value
-		      			              JS_CENTER_1+JS_DIR_1*JS_RANGE_1, // Joystick high value
-		            			        -MAX_TURN_THROTTLE, // Command low value
-		                  			  MAX_TURN_THROTTLE); // Command high value
-	int verticalCommand   =	map(analogRead(JS_ADC_2), // Read raw joystick value
-		                      	  JS_CENTER_2-JS_DIR_2*JS_RANGE_2, // Joystick low value
-		                      	  JS_CENTER_2+JS_DIR_2*JS_RANGE_2, // Joystick high value
-		                      	  -MAX_VERTICAL_THROTTLE, // Command low value
-		                      	  MAX_VERTICAL_THROTTLE); // Command high value
+  // Read the joysticks and use the Arduino "map" function to map the raw values
+  // to the desired output commands.
+  int forwardCommand    = map(analogRead(JS_ADC_0), // Read raw joystick value
+                              JS_CENTER_0-JS_DIR_0*JS_RANGE_0, // Joystick low value
+                              JS_CENTER_0+JS_DIR_0*JS_RANGE_0, // Joystick high value
+                              -MAX_FWD_REV_THROTTLE, // Command low value
+                              MAX_FWD_REV_THROTTLE); // Command high value
+  int turnCommand       = map(analogRead(JS_ADC_1), // Read raw joystick value
+                              JS_CENTER_1-JS_DIR_1*JS_RANGE_1, // Joystick low value
+                              JS_CENTER_1+JS_DIR_1*JS_RANGE_1, // Joystick high value
+                              -MAX_TURN_THROTTLE, // Command low value
+                              MAX_TURN_THROTTLE); // Command high value
+  int verticalCommand   = map(analogRead(JS_ADC_2), // Read raw joystick value
+                              JS_CENTER_2-JS_DIR_2*JS_RANGE_2, // Joystick low value
+                              JS_CENTER_2+JS_DIR_2*JS_RANGE_2, // Joystick high value
+                              -MAX_VERTICAL_THROTTLE, // Command low value
+                              MAX_VERTICAL_THROTTLE); // Command high value

-	// Combine the "stopped" command with forward, turn, and vertical and send
-	// to the ESCs.
-	thrusterLeft.setMicroseconds(CENTER_THROTTLE+forwardCommand+turnCommand);
-	thrusterRight.setMicroseconds(CENTER_THROTTLE+forwardCommand-turnCommand);
-	thrusterVertical.setMicroseconds(CENTER_THROTTLE+verticalCommand);
+  // Combine the "stopped" command with forward, turn, and vertical and send
+  // to the ESCs.
+  thrusterLeft.writeMicroseconds(CENTER_THROTTLE+forwardCommand+turnCommand);
+  thrusterRight.writeMicroseconds(CENTER_THROTTLE+forwardCommand-turnCommand);
+  thrusterVertical.writeMicroseconds(CENTER_THROTTLE+verticalCommand);

-	// Delay 1/20th of a second. No need to update at super fast rates.
-	delay(50);
+  // Delay 1/20th of a second. No need to update at super fast rates.
+  delay(50);
 }


Remove old comments

Remove old comments

--- arduino/udp-flippers-serial-switches/udppins-serial.ino
+++ arduino/udp-flippers-serial-switches/udppins-serial.ino
@@ -7,13 +7,6 @@
 #include <Adafruit_MCP23017.h>
 #include <Adafruit_RGBLCDShield.h>

-//BEGIN UDPServer.h
-
-//END UDPServer.h
-
-//BEGIN UDPServer.cpp
-
-// END UDPSERVER.CPP

 // These are the interrupt and control pins
 #define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!


Renaming state variable to applicationState

--- examples/LCDKeyPadShieldAndRadioTEA5767Demo/LCDKeyPadShieldAndRadioTEA5767Demo.ino
+++ examples/LCDKeyPadShieldAndRadioTEA5767Demo/LCDKeyPadShieldAndRadioTEA5767Demo.ino
@@ -14,7 +14,7 @@
    limitations under the License.
 */

-#include <LiquidCrystal.h>  // Insira as chaves menor no inicio e maior no final de LiquidCrystal.h
+#include <LiquidCrystal.h>
 #include <TEA5767N.h>
 #include <Wire.h>
 #include <stdlib.h>
@@ -23,13 +23,13 @@

 // Init radio object
 TEA5767N radio = TEA5767N();
-// Seleciona os pinos utilizados no Painel
+// Init LCD display object
 LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

-// Define as variaveis de botoes
+// LCD key that was pressed
 int lcd_key = 0;
-int adc_key_in = 0;
-
+
+// Buttons codes
 #define btnRIGHT    0
 #define btnUP       1
 #define btnDOWN     2
@@ -37,28 +37,28 @@
 #define btnSELECT   4
 #define btnNONE     5

+// Delay between clock transitions
 #define DELAY_VOLUME_TRANSITION 50

+// Definition of the 3-dimension array
 #define MENU_DEPTH 3
 #define MENU_LINES 8
 #define MENU_TEXT  16

+// Arduino pins
 int backLightPin = 10;
 int upDownPin = 11;
 int incPin = 12;

+// Predefined stations array
 float default_stations[16] = {88.1, 89.1, 89.7, 91.3, 92.5, 93.7, 94.7, 95.3, 96.1, 98.5, 100.1, 100.9, 101.7, 102.1, 102.9, 103.3};
+// Initialized station arrays
 float stations[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+// Keep the current station index
 byte stationIndex = 0;

-byte state = 0;       //0 -
-                      //1 -
-                      //2 -
-                      //3 -
-                      //4 -
-                      //5 -
-                      //6 -
-                      //7 -
+byte applicationState = 0;
+
 byte selectedMenuItem = 0;
 float selectedStation;
 boolean isStandByOn = false;
@@ -82,7 +82,7 @@
 }

 int read_LCD_buttons(){
-  adc_key_in = analogRead(0);
+  int adc_key_in = analogRead(0);
   if (adc_key_in > 1000) return btnNONE;
   if (adc_key_in < 50) return btnRIGHT;
   if (adc_key_in < 195) return btnUP;
@@ -278,13 +278,10 @@
 void loop(){
   lcd_key = read_LCD_buttons();

-  //Serial.print("Selected button: ");
-  //Serial.println(lcd_key);
-
   //Any button turns the radio on again
   if ((lcd_key != btnNONE) && isStandByOn && wasReleased) {
     wasReleased = false;
-    state = 0;
+    applicationState = 0;
     isStandByOn = false;

     //Necessary to elliminate noise while turning the radio back on
@@ -301,16 +298,13 @@

     // Starts station
     printSelectedFrequency(radio.readFrequencyInMHz());
-    //Serial.println("Consuming button click event");
-    ////Consumes button click event to force to another valid choice
-    //lcd_key = btnNONE;
   }

   switch (lcd_key) {
     case btnRIGHT: {
       if (wasReleased) {
         wasReleased = false;
-        switch (state) {
+        switch (applicationState) {
           case 0: {
             Serial.println(stationIndex);
             Serial.println(stations[stationIndex]);
@@ -368,7 +362,7 @@
     case btnLEFT: {
       if (wasReleased) {
         wasReleased = false;
-        switch (state) {
+        switch (applicationState) {
           case 0: {
             Serial.println(stationIndex);
             if (stationIndex > 0) {
@@ -426,9 +420,9 @@
     case btnUP: {
       //For up and down volume it´s ok let it execute
       //continuously
-      if (wasReleased || (state == 0)) {
+      if (wasReleased || (applicationState == 0)) {
         wasReleased = false;
-        switch (state) {
+        switch (applicationState) {
           //Volume UP
           case 0: {
             digitalWrite(upDownPin, HIGH);
@@ -491,9 +485,9 @@
     case btnDOWN: {
       //For up and down volume it´s ok let it execute
       //continuously
-      if (wasReleased || (state == 0)) {
+      if (wasReleased || (applicationState == 0)) {
         wasReleased = false;
-        switch (state) {
+        switch (applicationState) {
           //Volume DOWN
           case 0: {
             digitalWrite(upDownPin, LOW);
@@ -553,12 +547,12 @@
     case btnSELECT: {
       if (wasReleased) {
         wasReleased = false;
-        switch (state) {
+        switch (applicationState) {
           // Show SELECT menu items
           // >Mute
           //  Search
           case 0: {
-            state = 1;
+            applicationState = 1;
             lcd.clear();
             lcd.setCursor(0,0);
             lcd.print(menu[0][0]);
@@ -573,7 +567,7 @@
             switch(selectedMenuItem) {
               //Mute function
               case 0: {
-                state = 0;
+                applicationState = 0;
                 if (!mute) {
                   mute = true;
                   radio.mute();
@@ -594,7 +588,7 @@
               }
               //Search
               case 1: {
-                state = 5;
+                applicationState = 5;
                 lcd.clear();
                 lcd.setCursor(0, 0);
                 lcd.print("<");
@@ -605,7 +599,7 @@
               }
               //Fine search
               case 2: {
-                state = 6;
+                applicationState = 6;
                 lcd.clear();
                 lcd.setCursor(0, 0);
                 lcd.print("<<");
@@ -619,7 +613,7 @@
               case 3: {
                 byte isBandLimitReached = 0;
                 byte progress = 0;
-                state = 0;
+                applicationState = 0;
                 lcd.clear();
                 radio.mute();
                 radio.selectFrequency(88.0);
@@ -647,7 +641,7 @@
               }
               //Configuration
               case 4: {
-                state = 3;
+                applicationState = 3;
                 lcd.clear();
                 lcd.setCursor(0,0);
                 lcd.print(menu[1][0]);
@@ -660,7 +654,7 @@
               //Puts the radio in standy by mode and turns off
               //the display backlight
               case 5: {
-                state = 2;
+                applicationState = 2;
                 lcd.clear();

                 radio.setStandByOn();
@@ -671,7 +665,7 @@
               }
               //Load default station
               case 6: {
-                state = 0;
+                applicationState = 0;

                 lcd.setCursor(0,0);
                 lcd.print("      MHz        ");
@@ -691,7 +685,7 @@
               }
               //Exit
               case 7: {
-                state = 0;
+                applicationState = 0;

                 lcd.setCursor(0,0);
                 lcd.print("      MHz        ");
@@ -710,7 +704,7 @@
             switch(selectedMenuItem) {
               // Level item selected
               case 0: {
-                state = 4;
+                applicationState = 4;
                 lcd.clear();
                 if (searchLevel < 3) {
                   lcd.setCursor(0,0);
@@ -733,7 +727,7 @@
               }
               // Backlight intensity selected
               case 1: {
-                state = 7;
+                applicationState = 7;

                 lcd.clear();
                 lcd.setCursor(0,0);
@@ -742,7 +736,7 @@
               }
               // Exit
               case 2: {
-                state = 0;
+                applicationState = 0;

                 lcd.setCursor(0,0);
                 lcd.print("      MHz        ");
@@ -758,7 +752,7 @@
           }
           // One of the levels selected
           case 4: {
-            state = 0;
+            applicationState = 0;
             switch(selectedMenuItem+1) {
               case LOW_STOP_LEVEL: {
                 radio.setSearchLowStopLevel();
@@ -787,7 +781,7 @@
             break;
           }
           case 5: {
-            state = 0;
+            applicationState = 0;

             lcd.setCursor(0,0);
             lcd.print("      MHz        ");
@@ -801,7 +795,7 @@
           // Exit
           case 6:
           case 7: {
-            state = 0;
+            applicationState = 0;

             lcd.clear();
             lcd.setCursor(0,0);
@@ -822,7 +816,7 @@
       if (!wasReleased) {
         wasReleased = true;
       }
-      switch (state) {
+      switch (applicationState) {
         case 0: {
           if (!isStandByOn) {
             printStereoStatus();


Clarify handlers.

Clarify handlers.

--- lib-arduino/ACNode/examples/DoorNode/DoorNode.ino
+++ lib-arduino/ACNode/examples/DoorNode/DoorNode.ino
@@ -46,9 +46,9 @@
 static machinestates_t laststate = OUTOFORDER;
 machinestates_t machinestate = BOOTING;

-OTA ota = OTA("FooBar");
+OTA ota = OTA("FooBar");		// Over the air config, passowrd.
 RFID reader(RFID_SELECT_PIN, RFID_RESET_PIN);
-MSL msl = MSL();
+MSL msl = MSL();			// MSL `no security' handler as currently used for the doors.

 void setup() {


Check for MSB in throttle for throttle implausibility

--- TestMule/TestMule.ino
+++ TestMule/TestMule.ino
@@ -187,7 +187,12 @@
     uint16_t profiler = micros();
 #endif

-    requestedThrottle = msg.buf[0] << 8 | msg.buf[1];    // Safe throttle will need a better algorithm to handle noise
+    if (msg.buf[0] & (1 << 7)) {
+        requestedThrottle = 0;
+    }
+    else {
+        requestedThrottle = msg.buf[0] << 8 | msg.buf[1];
+    }

 #ifdef DEBUG_THROTTLE
     Serial.printf("\tRequested: %d\n", requestedThrottle);


Update ArduCAM_Shield_V2_Multi_Capture2SD.ino

--- ArduCAM/examples/Shield_V2/ArduCAM_Shield_V2_Multi_Capture2SD/ArduCAM_Shield_V2_Multi_Capture2SD.ino
+++ ArduCAM/examples/Shield_V2/ArduCAM_Shield_V2_Multi_Capture2SD/ArduCAM_Shield_V2_Multi_Capture2SD.ino
@@ -63,8 +63,16 @@
 Serial.println(F("ArduCAM Start!"));
 // set the CS as an output:
 pinMode(SPI_CS, OUTPUT);
+digitalWrite(SPI_CS, HIGH);
 // initialize SPI:
 SPI.begin();
+
+//Reset the CPLD
+myCAM.write_reg(0x07, 0x80);
+delay(100);
+myCAM.write_reg(0x07, 0x00);
+delay(100);
+
 while(1){
   //Check if the ArduCAM SPI bus is OK
   myCAM.write_reg(ARDUCHIP_TEST1, 0x55);


added ArduinoOTA to sonoff-sc and added CO2 filter for invalid values (when sensor is not initialized)

--- sonoff-homie-sc/esp8266_sketch/esp8266_sketch.ino
+++ sonoff-homie-sc/esp8266_sketch/esp8266_sketch.ino
@@ -1,5 +1,6 @@
 #define MQTT_MAX_PACKET_SIZE 400
 #include <Homie.h>
+#include <ArduinoOTA.h>

 // comment in/out if you want to use a MH-Z14 CO2 Sensor
 #define CO2_ENABLED
@@ -95,13 +96,16 @@
     }

 #ifdef CO2_ENABLED
-     if(co2.length() > 0) {
+     if(co2.length() > 0 && co2 != "0" && co2 != "5000") {
+      // discard values where the sensor is not initialized yet
       sonoffNode.setProperty("co2").send(co2);
     }
 #endif

     lastSent = millis();
   }
+
+  ArduinoOTA.handle();
 }

@@ -117,7 +121,8 @@
   Homie.setSetupFunction(setupHandler).setLoopFunction(loopHandler);

   Homie.setup();
-
+  ArduinoOTA.setHostname(Homie.getConfiguration().deviceId);
+  ArduinoOTA.begin();
 }

 void loop() {


"It's a hardware problem"

"It's a hardware problem"

This version works.  For whatever reason my blue LED is only showing
on/off; this might have to do with the higher voltage drop or something
mysterious.  Gradients have not been implemented/tested.

--- csarc/csarc.ino
+++ csarc/csarc.ino
@@ -9,8 +9,12 @@
 static boolean DEBUGGING_MODE = true; // toggle serial debug text
 static boolean SINGLE_LED = true; // false = Grove LED driver;
                                   // true = RGB LED for at-home testing
+static int R_PIN = 6;   // pins for
+static int G_PIN = 5;   // directly driven
+static int B_PIN = 4;   // test setup
+static int GND = 7;     // (<- so we don't have to split cables)
 #include "RGBdriver.h"
-#define CLK 2 //pin definitions for the driver
+#define CLK 2 //pin definitions for Grove driver
 #define DIO 3

 RGBdriver Driver(CLK,DIO);
@@ -23,11 +27,11 @@
 // leads to a color variable.

 void setup() {
-  if (SINGLE_LED) { // CC on pin 7
-    pinMode(7,OUTPUT);
-    pinMode(6,OUTPUT);
-    pinMode(5,OUTPUT);
-    pinMode(4,OUTPUT);
+  if (SINGLE_LED) {
+    pinMode(R_PIN,OUTPUT);
+    pinMode(G_PIN,OUTPUT);
+    pinMode(B_PIN,OUTPUT);
+    pinMode(GND,OUTPUT);
   }
   Serial.begin(BAUDRATE);
   rgb[4]=0;
@@ -43,8 +47,20 @@
   Serial.readStringUntil('\n').toCharArray(input,255);
   if (input!="") { // if connected
     switch (input[0]) {
+      case 'c' : {
+        sClear();
+        break;
+      }
+      case 'B': {
+        *rgb[0]=0;
+        *rgb[1]=0;
+        *rgb[2]=255;
+        setOutput(rgb);
+        if (SINGLE_LED) { Serial.println(digitalRead(B_PIN)); }
+        break;
+      }
       case 'b': {
-        analogWrite(4,150);
+        analogWrite(B_PIN,127.5);
         break;
       }
       case '1': {
@@ -158,17 +174,17 @@
 }

-  void setOutput( int red, int green, int blue) {
+  void setOutput( int r, int g, int b) {
     //"local variable hides a field" :p

     if (!SINGLE_LED) {
       Driver.begin();
-      Driver.SetColor(red, green, blue);
+      Driver.SetColor(r, g, b);
       Driver.end();
     } else { //testing setup: single RGB led with cathode on 7
-      analogWrite(6,red*.5);
-      analogWrite(5,green*.5);
-      analogWrite(4,blue*.5);
+      analogWrite(R_PIN,r);
+      analogWrite(G_PIN,g);
+      analogWrite(B_PIN,b);
     }
   }

@@ -254,3 +270,7 @@
         Serial.print(buf);
 }

+void sClear() {
+  for (int x=0; x<40; x++) { Serial.println(); }
+}
+


Stable setup so far. Needs the button handling now.

--- src/homie-sonoff-touch.ino
+++ src/homie-sonoff-touch.ino
@@ -1,4 +1,14 @@
 /* WARNING: untested */
+
+/* Some functional ideas
+  Single, double and triple tap.
+  Single and double tap and hold
+  Single tap = regular on/off
+  Single hold = dim up
+  Double tap = Unknown
+  Double tap and hold = dim down
+  Triple tap = toggle state of onboard relay
+*/

 #include <Homie.h>

@@ -19,8 +29,15 @@
 const int PIN_LED = 13;
 const int PIN_BUTTON = 0;

+volatile unsigned long timestamp = 0;
+volatile unsigned long singletimer = 0;
+volatile unsigned long doubletimer = 0;
+volatile unsigned long tripletimer = 0;
+
+
+int lastbuttonState = -1;
+
 Bounce debouncer = Bounce(); // Bounce is built into Homie, so you can use it without including it first
-int lastbuttonState = -1;

 HomieNode relayNode("relay", "relay");
 HomieNode buttonNode("button", "button");
@@ -43,13 +60,19 @@
 }

 void loopHandler() {
+  // Ideally this would be handled by an interrupt, but it seems to make Homie hang.
   int buttonState = debouncer.read();

   if (buttonState != lastbuttonState) {
+     timestamp = millis();
+     singletimer = timestamp;
+     doubletimer = timestamp;
+     tripletimer = timestamp;
+
      Serial.print("Button is now: ");
-     Serial.println(buttonState ? "open" : "close");
+     Serial.println(buttonState ? "pressed" : "released");

-     if (Homie.setNodeProperty(buttonNode, "open", buttonState ? "true" : "false", true)) {
+     if (Homie.setNodeProperty(buttonNode, "state", buttonState ? "pressed" : "released", true)) {
        lastbuttonState = buttonState;
      } else {
        Serial.println("Sending failed");


Update to MySensors 2.x

Update to MySensors 2.x

--- arduino-plantmoisture.ino
+++ arduino-plantmoisture.ino
@@ -1,6 +1,3 @@
-#include <SPI.h>
-#include <MySensor.h>
-
 #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
 #define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))

@@ -11,25 +8,31 @@
 #define STABILIZATION_TIME 1000 // Let the sensor stabilize before reading
 #define BATTERY_FULL 3143 // 2xAA usually give 3.143V when full
 #define BATTERY_ZERO 2340 // 2.34V limit for 328p at 8MHz. 1.9V, limit for nrf24l01 without step-up. 2.8V limit for Atmega328 with default BOD settings.
+#define MY_RADIO_NRF24
 const int SENSOR_ANALOG_PINS[] = {A0, A1}; // Sensor is connected to these two pins. Avoid A3 if using ATSHA204. A6 and A7 cannot be used because they don't have pullups.

-MySensor gw;
+#define MY_SPLASH_SCREEN_DISABLED
+#define MY_TRANSPORT_WAIT_READY_MS (30000) // Don't stay awake for more than 30s if communication is broken
+#define MY_DEBUG
+#include <MySensors.h>
+
 MyMessage msg(CHILD_ID_MOISTURE, V_HUM);
 MyMessage voltage_msg(CHILD_ID_BATTERY, V_VOLTAGE);
 long oldvoltage = 0;
 byte direction = 0;
 int oldMoistureLevel = -1;

+void presentation() {
+  sendSketchInfo("Plant moisture w bat", "1.6");
+  present(CHILD_ID_MOISTURE, S_HUM);
+  delay(250);
+  present(CHILD_ID_BATTERY, S_CUSTOM);
+
+}
+
 void setup()
 {
-  gw.begin();
-
-  gw.sendSketchInfo("Plant moisture w bat", "1.5");
-
-  gw.present(CHILD_ID_MOISTURE, S_HUM);
-  delay(250);
-  gw.present(CHILD_ID_BATTERY, S_CUSTOM);
-  for (int i = 0; i < N_ELEMENTS(SENSOR_ANALOG_PINS); i++) {
+  for (unsigned int i = 0; i < N_ELEMENTS(SENSOR_ANALOG_PINS); i++) {
     pinMode(SENSOR_ANALOG_PINS[i], OUTPUT);
     digitalWrite(SENSOR_ANALOG_PINS[i], LOW);
   }
@@ -49,21 +52,21 @@
     // Measure again, this time with reversed polarity.
     moistureLevel = readMoisture();
   }
-  gw.send(msg.set((moistureLevel + oldMoistureLevel) / 2.0 / 10.23, 1));
+  send(msg.set((moistureLevel + oldMoistureLevel) / 2.0 / 10.23, 1));
   oldMoistureLevel = moistureLevel;
   long voltage = readVcc();
   if (oldvoltage != voltage) { // Only send battery information if voltage has changed, to conserve battery.
-    gw.send(voltage_msg.set(voltage / 1000.0, 3)); // redVcc returns millivolts. Set wants volts and how many decimals (3 in our case)
-    gw.sendBatteryLevel(round((voltage - BATTERY_ZERO) * 100.0 / (BATTERY_FULL - BATTERY_ZERO)));
+    send(voltage_msg.set(voltage / 1000.0, 3)); // redVcc returns millivolts. Set wants volts and how many decimals (3 in our case)
+    sendBatteryLevel(round((voltage - BATTERY_ZERO) * 100.0 / (BATTERY_FULL - BATTERY_ZERO)));
     oldvoltage = voltage;
   }
-  gw.sleep(SLEEP_TIME);
+  sleep(SLEEP_TIME);
 }

 int readMoisture() {
   pinMode(SENSOR_ANALOG_PINS[direction], INPUT_PULLUP); // Power on the sensor
   analogRead(SENSOR_ANALOG_PINS[direction]);// Read once to let the ADC capacitor start charging
-  gw.sleep(STABILIZATION_TIME);
+  sleep(STABILIZATION_TIME);
   int moistureLevel = (1023 - analogRead(SENSOR_ANALOG_PINS[direction]));

   // Turn off the sensor to conserve battery and minimize corrosion


[feat] cross checking of control variables is now possible.

--- heater_control.ino
+++ heater_control.ino
@@ -39,6 +39,11 @@
   float analog;
 };

+struct variable {
+  char *name;
+  float value;
+};
+
 struct ad {
   int port;
   char *name;
@@ -50,11 +55,6 @@
   struct dig2a maxcal;
   struct dig2a measured;
   struct dig2a delta;
-};
-
-struct variable {
-  char *name;
-  float value;
 };

 struct cnt {
@@ -81,21 +81,29 @@
   time_t last_change;
 };

-// simple conditions for logical operations.
+#define METHOD_TURNON      1
+#define METHOD_CHANGELIMIT 2
+
+// simple conditions for operations
 struct condition {
   int id;
   struct ad *source;
-  char op;
-  dig2a value;
-  struct outIo *target;
-  int state;
+  struct variable *limit;
+  struct variable *limit2;
+  void *target;
+  int method;
 };

 struct variable variables[]= {
-  {"boilTemp",60.0},
-  {"radiatorTemp",20.0}
-};
+  {"boilTemp",      24.5},
+  {"boilHysteresis", 1.5},
+  {"boilReduced",   24.0},
+  {"hhboil",        25.0},
+  {"radiatorTemp",  20.0}
+};
+
+struct variable *origVariables;

 // in future this table shall be stored mainly in eeprom.
 // and so is it's size
@@ -122,8 +130,8 @@
 // confitions are kept in array to have a possibility to configure them with tcp/ip telnet style commands
 // and to store them to eeprom.
 struct condition conditions[]= {
-  {0,&adArr[0],'<',0,24.4,&outIoArr[0],1}, // if boiler is under 24.4, turn burnerfeed to 1
-  {0,&adArr[0],'>',0,26.0,&outIoArr[0],0}  // if boiler is over 26, turn burnerfeed to 0
+  {0,&adArr[0],&variables[0],&variables[1],&outIoArr[0] ,1},  // start boiler if it is under 24.5, and off when it has reached 26.0
+  {1,&adArr[2],&variables[3],&variables[0],&variables[2],2}  // if hothousewater is under hhboil, then boilTemp should be boilReduced.
 };

@@ -146,6 +154,8 @@
   pinMode(12, OUTPUT);
   Serial.println("Start");
   eepReadAll();
+  origVariables=(struct variable *) malloc(sizeof(variables));
+  memcpy(origVariables,variables,sizeof(variables));
   // preparing for configurable channels.
   // in future the amount of channels will be specified with config
   // and this amount with channel names are saved to eeprom.
@@ -199,6 +209,18 @@
 void irqh1()
 {
   _counters[1]++;
+}
+
+
+int resetVariable(char *name)
+{
+  for (int i=0;i<sizeof(variables) / sizeof(struct variable);i++) {
+    if (!strcmp(variables[i].name,name)) {
+      variables[i].value=origVariables[i].value;
+      return 0;
+    }
+  }
+  return 1;
 }

 void processSensors()
@@ -239,48 +261,50 @@
 {
   float value;
   float limit;
+  float off;
+  struct outIo *targetIo;
+  struct variable *var;
+

   for (int i=0;i<sizeof(conditions) / sizeof(struct condition);i++) {
     if (conditions[i].source == source) {
       value=source->measured.analog;
-      limit=conditions[i].value.analog;
-      switch (conditions[i].op) {
-      case '<':
-	if (value < limit && conditions[i].target->state != conditions[i].state) {
-	  conditions[i].target->state = conditions[i].state;
-	  conditions[i].target->last_change = ts;
-	  digitalWrite(conditions[i].target->port,conditions[i].target->state);
-	  Serial.print(source->name);
-	  Serial.print(" is smaller than ");
-	  Serial.print(limit);
-          Serial.print(" turning ");
-	  Serial.print(conditions[i].target->name);
-	  Serial.print(" port [");
-	  Serial.print(conditions[i].target->port);
-	  Serial.print("] to ");
-	  Serial.println(conditions[i].state);
+      limit=conditions[i].limit->value;
+      switch (conditions[i].method) {
+      case METHOD_TURNON:
+	targetIo=(struct outIo *) conditions[i].target;
+	off=limit + conditions[i].limit2->value;
+	if (value < limit && targetIo->state == 0) {
+	  targetIo->state = 1;
+	  targetIo->last_change = ts;
+	  digitalWrite(targetIo->port,1);
+	}
+	else if (value > off && targetIo->state == 1 ) {
+	  targetIo->state = 0;
+	  targetIo->last_change = ts;
+	  digitalWrite(targetIo->port,0);
 	}
 	break;

-      case '>':
-	if (value > limit && conditions[i].target->state != conditions[i].state) {
-	  conditions[i].target->state = conditions[i].state;
-	  conditions[i].target->last_change = ts;
-	  digitalWrite(conditions[i].target->port,conditions[i].target->state);
-	  Serial.print(source->name);
-	  Serial.print(" is bigger than ");
-	  Serial.print(limit);
-          Serial.print(" turning ");
-	  Serial.print(conditions[i].target->name);
-	  Serial.print(" port [");
-	  Serial.print(conditions[i].target->port);
-	  Serial.print("] to ");
-	  Serial.println(conditions[i].state);
+      case METHOD_CHANGELIMIT:
+	var=(struct variable *) conditions[i].target;
+	if (value < limit) {
+	  conditions[i].limit2->value=var->value;
+	  Serial.print("changed ");
+	  Serial.print(conditions[i].limit2->name);
+	  Serial.print(" limit to ");
+	  Serial.print(conditions[i].limit2->value);
+          Serial.print(" = ");
+          Serial.println(var->name);
+	}
+	else {
+	  resetVariable(conditions[i].limit2->name);
+	  Serial.print("resetted ");
+	  Serial.print(conditions[i].limit2->name);
+	  Serial.print(" limit to ");
+	  Serial.println(conditions[i].limit2->value);
 	}
 	break;
-
-      default:
-	Serial.println("unknown conditional op");
       }
     }
   }


Housekeeping

Housekeeping

--- PulseSensorAmped_Arduino_1dot4/PulseSensorAmped_Arduino_1dot4.ino
+++ PulseSensorAmped_Arduino_1dot4/PulseSensorAmped_Arduino_1dot4.ino
@@ -46,7 +46,7 @@

     serialOutput() ;

-  if (QS == true){     //  A Heartbeat Was Found
+  if (QS == true){     // A Heartbeat Was Found
                        // BPM and IBI have been Determined
                        // Quantified Self "QS" true when arduino finds a heartbeat
         digitalWrite(blinkPin,HIGH);     // Blink LED, we got a beat.
@@ -54,13 +54,9 @@
                                 // Set 'fadeRate' Variable to 255 to fade LED with pulse
         serialOutputWhenBeatHappens();   // A Beat Happened, Output that to serial.
         QS = false;                      // reset the Quantified Self flag for next time
-       }
-      else {
-
-      digitalWrite(blinkPin,LOW);            // There is not beat, turn off pin 13 LED
-      }
+  }

-   ledFadeToBeat();                      // Makes the LED Fade Effect Happen
+  ledFadeToBeat();                      // Makes the LED Fade Effect Happen
   delay(20);                             //  take a break
 }


implemented blinking

implemented blinking

--- ksp-gegi/ksp-gegi.ino
+++ ksp-gegi/ksp-gegi.ino
@@ -14,10 +14,15 @@
 const int throttlePin = A0;  // P0

 const uint8_t nPins = 7; // długość tabel poniżej
-const uint8_t switchPins[] = {4, 5, 8, 12, 0, 0, 0};	// Dx: stage, RCS, SAS, gear switch, overheat, lowpower, lowfuel
-const uint8_t onPins[] = {0, 13, 9, 0, 0, 0, 0};	// Gx: stage, RCS, SAS, overheat, lowpower, lowfuel ON (green)
-const uint8_t offPins[] = {0, 0, 0, 0, 6, 7, 10};	// Rx: stage, RCS, SAS, overheat, lowpower, lowfuel OFF (red)
+const uint8_t switchPins[] = {4,  5, 8, 12, 0, 0,  0};	// Dx: stage, RCS, SAS, gear switch, overheat, lowpower, lowfuel
+const uint8_t onPins[] =     {0, 13, 9,  0, 0, 0,  0};	// Gx: stage, RCS, SAS, overheat, lowpower, lowfuel ON (green)
+const uint8_t offPins[] =    {0,  0, 0,  0, 6, 7, 10};	// Rx: stage, RCS, SAS, overheat, lowpower, lowfuel OFF (red)
 uint8_t lastPinState[] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
+uint8_t lastLedState[] =  {0, 0, 0, 0, 0, 0, 0};	// bits: 0=GxON, 1=RxON, 2=GxBLINK, 3=RxBLINK
+
+// blinker control
+unsigned long lastBlink = 0;
+const unsigned long blinkInterval = 500;

 // throttle control
 int lastThrottleValue = 0;
@@ -35,6 +40,7 @@
 	// switch pin input
 	if (switchPins[i]>0) { pinMode(switchPins[i],INPUT_PULLUP); }
     // make LED pins outputs+turn off
+	lastLedState[i] = 0;
 	if (onPins[i]>0) {
           pinMode(onPins[i],OUTPUT);
           digitalWrite(onPins[i],LOW);
@@ -48,6 +54,8 @@
   Serial.setTimeout(200);
   // request status update
   Serial.println("I");
+  // start blink counter
+  lastBlink = millis();
 }

 void updateThrottle() {
@@ -93,7 +101,7 @@

 void checkSerialInput() {
   uint8_t c;
-  uint8_t ledPin=0,val=0,id=0;
+  uint8_t val=0,id=0,nval=0;
   // format: "^LG1=0$" turn off green led 1 (RCS), "^LR2=1$" turn off red led 2 (SCS)
   if (Serial.available()>0) {
   if (Serial.find("L")) {
@@ -101,18 +109,55 @@
     id = Serial.parseInt();  // skip '='
     val = Serial.parseInt(); // skip newline
 //    Serial.print(c); Serial.print(id); Serial.println(val);  // echo for ack
-	if (id<nPins) {
-		if (c=='G') { ledPin = onPins[id]; }
-		if (c=='R') { ledPin = offPins[id]; }
-		if (ledPin>0) {
-			if (val==0) {
-				digitalWrite(ledPin,LOW);
-			} else {
-				digitalWrite(ledPin,HIGH);
-			}
-		}
+	if (id>0 && id<=nPins) {
+                nval = lastLedState[id];
+                if (c=='G') {
+                  nval = nval & 0b11111010;
+                  if (val==1) nval=nval | 0x01;
+                  if (val==2) nval=nval | 0x01 | 0x04;
+                }
+                if (c=='R') {
+                  nval = nval & 0b11110101;
+                  if (val==1) nval=nval | 0x02;
+                  if (val==2) nval=nval | 0x02 | 0x08;
+                }
+		lastLedState[id] = nval;
 	}
   }
+  }
+}
+
+// set all LEDs according to state
+void updateLeds() {
+  unsigned long currentMillis = millis();
+  bool blink = false;
+  // is it time for tick?
+  if (((unsigned long)(currentMillis - lastBlink) >= blinkInterval)) {
+	  blink = true;
+	  lastBlink = currentMillis;
+  }
+//  Serial.print("blink="); Serial.println(blink);
+  // update all leds
+  for (uint8_t i=0; i<nPins; i++) {
+	uint8_t nstate;
+	uint8_t gPin = onPins[i];
+	if (gPin!=0) {
+		nstate = (lastLedState[i] & 0x01) ? HIGH : LOW;
+		if (nstate==HIGH && (lastLedState[i] & 0x04) && blink) {
+			nstate = !digitalRead(gPin);
+		}
+//Serial.print("L"); Serial.print(gPin); Serial.print(nstate);
+		digitalWrite(gPin,nstate);
+	}
+	uint8_t rPin = offPins[i];
+	if (rPin!=0) {
+		nstate = (lastLedState[i] & 0x02) ? HIGH : LOW;
+		if (nstate==HIGH && (lastLedState[i] & 0x08) && blink) {
+			nstate = !digitalRead(rPin);
+		}
+//Serial.print("R"); Serial.print(rPin); Serial.print(nstate);
+		digitalWrite(rPin,nstate);
+	}
   }
 }

@@ -120,5 +165,7 @@
   updateThrottle();
   updatePins();
   checkSerialInput();
+  updateLeds();
   delay(200);
 }
+


The sabertooth driver now checks for updated instructions instead of chilling and never checking for commands.

--- src/SabertoothDriverROS/SabertoothDriverROS.ino
+++ src/SabertoothDriverROS/SabertoothDriverROS.ino
@@ -168,9 +168,11 @@
 // This program does whatever ROS directs it to do.
 // So far, it drives the robot forwards and backwards.
 void loop(){
+  sabertoothDriverNode.spinOnce();
   if (new_commands) {
      new_commands = 0;
      driveAllMotors(current_velocity, current_direction);
   }
+  delayMicroseconds(100000);

 }


Added LED functionality

Added LED functionality

--- chillduino.ino
+++ chillduino.ino
@@ -21,12 +21,20 @@
  *
  */

+#include <Adafruit_NeoPixel.h>
 #include "chillduino.h"

 #define DOOR_SWITCH    13
 #define DEFROST_SWITCH 12
 #define THERMISTOR     A0
 #define LEDS           A4
+#define LED_COUNT      60
+#define LED_OFF_R      0
+#define LED_OFF_G      0
+#define LED_OFF_B      0
+#define LED_ON_R       255
+#define LED_ON_G       255
+#define LED_ON_B       255
 #define OFF
 #define COLD           45
 #define COLDER         37
@@ -37,6 +45,7 @@
 #define TICKS_PER_HOUR     (60 * TICKS_PER_MINUTE)

 Chillduino chillduino;
+Adafruit_NeoPixel pixels(LED_COUNT, LEDS, NEO_GRB + NEO_KHZ800);

 SIGNAL(TIMER0_COMPA_vect) {
   chillduino.tick();
@@ -51,6 +60,14 @@
   TIMSK0 &= ~_BV(OCIE0A);
 }

+void setLedColor(int r, int g, int b) {
+  for (int i = 0; i < LED_COUNT; i++) {
+    pixels.setPixelColor(i, pixels.Color(r, g, b));
+  }
+
+  pixels.show();
+}
+
 void setup(void) {
   pinMode(DOOR_SWITCH, INPUT);
   pinMode(DEFROST_SWITCH, INPUT);
@@ -62,6 +79,9 @@
     .setDefrostDurationInTicks(30 * TICKS_PER_MINUTE)
     .setMinimumTicksForCompressorChange(10 * TICKS_PER_MINUTE)
     .setMinimumTicksForDoorClose(100);
+
+  pixels.begin();
+  pixels.show();

   Serial.begin(9600);
   setInterrupt();
@@ -81,5 +101,12 @@

     Serial.println(chillduino.isDefrostRunning()
       ? "Defrost is running" : "Defrost is not running");
+
+    if (chillduino.isDoorOpen()) {
+      setLedColor(LED_ON_R, LED_ON_G, LED_ON_B);
+    }
+    else {
+      setLedColor(LED_OFF_R, LED_OFF_G, LED_OFF_B);
+    }
   }
 }


Fixing  shutdown save [need real time test]

--- MID/MID.ino
+++ MID/MID.ino
@@ -254,7 +254,7 @@
 //    serialInject.listenerSerial();

     //
-    //
+    // Amplitude loop init
     ampInt.listener();

@@ -272,8 +272,8 @@
     }
     //
     // Compare data to detect shutdown and protect multi-records from loop
-    if (curProtectValue < lastProtectRead - 30 || /* Only first initialization will run */
-        curProtectValue < lastProtectRead - 30 &&
+    if (curProtectValue < lastProtectRead - 50 && saveProtectInit == 0 || /* Only first initialization will run */
+        curProtectValue < lastProtectRead - 50 &&
         saveProtectInit + MILLIS_PER_MN < millis()) { /* next record after a minute */
         //
         // Save data to eep rom
@@ -292,12 +292,8 @@

         //
         // Close first initialization
-
-    } else {
-        // TODO
+        saveProtectInit = millis();
     }
-
-    saveProtectInit = millis();
     //
     // Move value to last read
     lastProtectRead = curProtectValue;


Changed to prod lcd

Changed to prod lcd

--- Weight.ino
+++ Weight.ino
@@ -48,8 +48,8 @@
 #define BUTTON_PIN   0

 // initialize the library with the numbers of the interface pins
-LiquidCrystal lcd(13, 12, 8, 9, 10, 11); //PROD
-//LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //DEBUG
+//LiquidCrystal lcd(13, 12, 8, 9, 10, 11); //DEBUG
+LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //PROD
 HX711 scales[] = {
   HX711 (A1, A2), HX711 (A3, A4)}; //A1 = ANALOG1 = DT // A2=SCK
 int eepromAddress[WEIGHT_SENSORS] = {0};


Update arduino.ino

Update arduino.ino

Suppression des variables globales afin que lorsque idCommand = ip le programme ne plante pas lors de la construction de la réponse (problèmes mémoire)

--- Arduino/arduino/arduino.ino
+++ Arduino/arduino/arduino.ino
@@ -1,6 +1,5 @@
 #include <SPI.h>
 #include <Ethernet.h>
-#include <String.h>
 #include <aJSON.h>
 // ---------------------------------- CONFIGURATION DE L'ARDUINO DUEMILANOVE
 // adresse MAC de l'Arduino DUEMILANOVE
@@ -14,8 +13,6 @@
 IPAddress ipServeurEnregistrement(192,168,2,1); // IP du serveur d'enregistrement
 int portServeurEnregistrement=100; // port du serveur d'enregistrement
 EthernetClient clientArduino; // le client Arduino du serveur d'enregistrement
-String commandeGlobal; //commande reçue par le serveur
-String reponseGlobal; //réponse à envoyer au serveur

 // initialisation
 void setup() {
@@ -80,15 +77,15 @@
       Serial.print(F("Memoire disponible debut boucle : "));
       Serial.println(freeRam());
       // on lit la commande de ce client
-      commandeGlobal=lireCommande(&client);
+      String commande=lireCommande(&client);
       // suivi
       Serial.print(F("commande : ["));
-      Serial.print(commandeGlobal);
+      Serial.print(commande);
       Serial.println(F("]"));
       // si la commande est vide, on ne la traite pas
-      if(commandeGlobal.length()==0) continue;
+      if(commande.length()==0) continue;
       // sinon on la traite
-      traiterCommande(&client,&commandeGlobal);
+      traiterCommande(&client,&commande);
       // mémoire disponible
       Serial.print(F("Memoire disponible fin boucle : "));
       Serial.println(freeRam());
@@ -133,6 +130,7 @@
     return;
   }
   // on mémorise l'id
+  //int index = String(id->valuestring).lastIndexOf('.');
   char *strId = id->valuestring;

   // attribut action
@@ -217,12 +215,12 @@

 // lecture d'une commande du serveur
 String lireCommande(EthernetClient *client){
-  commandeGlobal = "";
+  String commande = "";
   while(client->available()) {
     char c = client->read();
-    commandeGlobal += c;
-  }
-  return commandeGlobal; // on rend la commande
+    commande += c;
+  }
+  return commande; // on rend la commande
 }

 // formatage json de la réponse au client
@@ -236,9 +234,9 @@
   if(etat==NULL) etat="{}";

   // construction de la réponse
-  reponseGlobal="{\"id\":\""+id+"\",\"er\":\""+erreur+"\",\"et\":"+etat+"}";
+  String reponse="{\"id\":\""+id+"\",\"er\":\""+erreur+"\",\"et\":"+etat+"}";
   // résultat
-  return reponseGlobal;
+  return reponse;
 }

 // echo
@@ -427,8 +425,8 @@

 // envoi réponse au client
 void sendReponse(EthernetClient *client, String message){
-  Serial.print(F("Memoire disponible : ")); // mémoire disponible
-  Serial.println(freeRam());
+  //Serial.print(F("Memoire disponible : ")); // mémoire disponible
+  //Serial.println(freeRam());
   // envoi de la réponse
   client->println(message);
   // suivi


moving to screen file.

moving to screen file.

--- src/rx5808-pro-diversity/rx5808-pro-diversity.ino
+++ src/rx5808-pro-diversity/rx5808-pro-diversity.ino
@@ -238,8 +238,6 @@
             delay(100);
         }
     }
-    // rodate the display output 180 degrees.
-    // drawScreen.flip(); // OLED only!

 #ifdef USE_IR_EMITTER
     // Used to Transmit IR Payloads


performance verified on breadboard indoors

--- hacks/LibAPRS_test/LibAPRS_test.ino
+++ hacks/LibAPRS_test/LibAPRS_test.ino
@@ -11,7 +11,7 @@
 #define OPEN_SQUELCH true

 //Other
-#define ONE_WIRE_BUS 13 // Data wire is plugged into pin d8 on the Arduino
+#define ONE_WIRE_BUS 8 // Data wire is plugged into pin d8 on the Arduino
 #define BATT_V_PIN 2 // Batt pin wire is plugged into a2 on the Arduino

 TinyGPSPlus gps;
@@ -213,7 +213,7 @@
     Serial.print(commentStringChar);
     Serial.print(F("'"));
     Serial.println();
-    //print_status();
+    print_status();
 }

 void print_status() {
@@ -242,6 +242,8 @@
   if (millis() > 5000 && gps.charsProcessed() < 10) {
     Serial.println(F("No GPS detected: check wiring."));
     while(true);
+  } else {
+    Serial.println(gps.passedChecksum());
   }

   if (gps.location.isValid()) {


add spherical error correction

add spherical error correction

--- spherical_laser_projector/spherical_laser_projector.ino
+++ spherical_laser_projector/spherical_laser_projector.ino
@@ -27,8 +27,9 @@
 | By A.E.TEC (Arad Eizen) 2016.                                                |
 |	                                                                           |
 \******************************************************************************/
-#include "images/cloud.h"
-#include "images/skull.h"
+#include <math.h>					// asin
+#include "paths/cloud.h"
+#include "paths/skull.h"

 #define X_AXIS_LIMIT_MIN			(-1800)
 #define Y_AXIS_LIMIT_MIN			(-1400)
@@ -37,9 +38,10 @@

 #define SERIAL_BAUDRATE				(115200)
 #define SERIAL_BUFFER_SIZE			(60)
-
 #define STEPS_DELAY_MS				(5)
 #define BEZIER_SEGMENTS				(30)
+#define STEPS_PER_RADIAN			(648.68)
+#define Z_SQARE						(10000) // 19600

 #define X_AXIS_A_PIN				(4)
 #define X_AXIS_B_PIN				(5)
@@ -62,7 +64,7 @@
 // uint8_t text_char_sep = 10;
 int16_t draw_x = 0;
 int16_t draw_y = 0;
-float draw_scale = 2;
+double draw_scale = 2;

 /* cuts the power to the motors (they will hold thier positions)
@@ -86,14 +88,6 @@
 		PORTB |= LASER_MASK;
 	else
 		PORTB &= ~LASER_MASK;
-}
-/* go to the given axes position from current motors position */
-void absolute_steps(int16_t x, int16_t y) {
-	if (x < X_AXIS_LIMIT_MIN) return;
-	if (x > X_AXIS_LIMIT_MAX) return;
-	if (y < Y_AXIS_LIMIT_MIN) return;
-	if (y > Y_AXIS_LIMIT_MAX) return;
-	relative_steps(x - current_position_x, y - current_position_y);
 }

 /* add/inc the motors current position by the given steps */
@@ -121,6 +115,22 @@
 	disable_axes();
 }

+/* go to the given axes position from current motors position */
+void absolute_steps(int16_t x, int16_t y) {
+	if (x < X_AXIS_LIMIT_MIN) return;
+	if (x > X_AXIS_LIMIT_MAX) return;
+	if (y < Y_AXIS_LIMIT_MIN) return;
+	if (y > Y_AXIS_LIMIT_MAX) return;
+	relative_steps(x - current_position_x, y - current_position_y);
+}
+
+/* convert absolute point to absolute axes steps */
+void absolute_point(int32_t x, int32_t y) {
+	double n = sqrt(x * x + y * y + Z_SQARE);
+	double a = asin(y / n);
+	absolute_steps(round(STEPS_PER_RADIAN * asin(x / n / cos(a))), round(STEPS_PER_RADIAN * a));
+}
+
 /* set the current laser position to (0, 0) for trigo to work */
 void set_home() {
 	current_position_x = 0;
@@ -136,7 +146,8 @@
 }

 void go_to(int16_t x, int16_t y) {
-	absolute_steps(x * draw_scale + draw_x, y * draw_scale + draw_y);
+	// absolute_steps(x * draw_scale + draw_x, y * draw_scale + draw_y);
+	absolute_point(x * draw_scale + draw_x, y * draw_scale + draw_y);
 }

 void draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
@@ -193,7 +204,7 @@
 	}
 }

-void draw_path(int16_t x, int16_t y, float scale) {
+void draw_path(int16_t x, int16_t y, double scale) {
 	draw_x = x;
 	draw_y = y;
 	draw_scale = scale;
@@ -213,9 +224,9 @@
 	// set_laser(true); delay(100); set_laser(false);

 	// draw_path(0, -180, 3);
-	draw_path(0, 500, 1.5);
-	// draw_cloud();
-	draw_skull();
+	draw_path(-20, 50, 0.5);
+	draw_cloud();
+	// draw_skull();
 	go_home();
 }

@@ -233,8 +244,8 @@
 	corners++;
 	set_laser(true);
 	while (corners) {
-		tmp.x = p->x + round(size * cos(current_angle));
-		tmp.y = p->y + round(size * sin(current_angle));
+		tmp.x = x + round(size * cos(current_angle));
+		tmp.y = y + round(size * sin(current_angle));
 		absolute_steps(&tmp);
 		current_angle += step_angle;
 		corners--;
@@ -249,13 +260,13 @@

 /*void get_text_size(char * text, xy_point * p) {
 	xy_point tmp;
-	p->x = (*text ? -text_char_sep : 0);
-	p->y = 0;
+	x = (*text ? -text_char_sep : 0);
+	y = 0;
 	while (*text) {
 		get_path_size(char_to_path(*text++), &tmp);
-		p->x += tmp->x + text_char_sep;
-		if (p->y < tmp->y)
-			p->y = tmp->y;
+		x += tmx + text_char_sep;
+		if (y < tmy)
+			y = tmy;
 	}
 }*/


small cleanup

small cleanup

--- ArduinoRF24_I2C_DHT11/ArduinoRF24_I2C_DHT11.ino
+++ ArduinoRF24_I2C_DHT11/ArduinoRF24_I2C_DHT11.ino
@@ -19,12 +19,7 @@

 void setup()
 {
-  Serial.begin(115200);
-  Serial.println("DHT TEST PROGRAM ");
-  Serial.print("LIBRARY VERSION: ");
-  Serial.println(DHT_LIB_VERSION);
-  Serial.println();
-  Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)");
+  Serial.begin(9600);

   pinMode(DHT11_POWER_PIN, OUTPUT);
   digitalWrite(DHT11_POWER_PIN, HIGH);
@@ -36,7 +31,6 @@
 void loop()
 {
   // READ DATA
-  Serial.print("DHT11, \t");
   int chk = DHT.read11(DHT11_PIN);
   switch (chk)
   {
@@ -53,11 +47,6 @@
 		Serial.print("Unknown error,\t");
 		break;
   }
-  // DISPLAY DATA
-  Serial.print(DHT.humidity, 1);
-  Serial.print(",\t");
-  Serial.println(DHT.temperature, 1);
-
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print(TEMP_STR);


Fix to trailing DCD signal. :)

Fix to trailing DCD signal. :)

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

--- zimodem/wificlientnode.ino
+++ zimodem/wificlientnode.ino
@@ -361,7 +361,7 @@
     if((conn->isConnected()
      ||(conn->available()>0)
      ||((conn == conns)
-       &&((serialOutBufferBytesRemaining() > 0)
+       &&((serialOutBufferBytesRemaining() <SER_WRITE_BUFSIZE-1)
          ||(HWSerial.availableForWrite()<SER_BUFSIZE))))
     && conn->isAnswered())
       num++;


* Added doc

* Added doc

--- LearnIRCode/LearnIRCode.ino
+++ LearnIRCode/LearnIRCode.ino
@@ -1,5 +1,6 @@
 /*
 Пример программы для управления светодиодом с ИК-пульта.
+https://github.com/altexdim/arduino-learn-ir-code

 Коды команд кнопок пульта сохраняются в памяти Arduino после сброса.
 Для обучения устройства новой команде (кнопке пульта) используется


Changed sequencing principle in loop() function

This enhances the period accuracy (1ms). This was assessed with Naveol AriScope:
http://naveol.com/index.php?menu=product&p=4

--- SRC/ArincShieldAutoTest.ino
+++ SRC/ArincShieldAutoTest.ino
@@ -9,8 +9,11 @@
 //
 // Version V1.02 (18/01/2018) : added a test step for RS422 loopback check
 //
-// Version V1.03 (14/05/2019) : added "volatile" attribute to RINT1Trigd & RINT2Trigd variables
-//                              to fix some occurences of failed interrupts tests
+// Version V1.03 (14/05/2019) : - added "volatile" attribute to RINT1Trigd & RINT2Trigd variables
+//                                to fix some occurrences of failed interrupts tests
+//                              - changed sequencing principle in loop() function for periodic ARINC emission
+//                                to enhance 1ms period accuracy. This was verified with an AriScope from Naveol:
+//             http://naveol.com/index.php?menu=product&p=4
 //
 // This program is distributed in the hope that it will be useful, but without any
 // warranty; without even the implied warranty of merchantability or fitness for a
@@ -44,6 +47,9 @@
 //#define ClkDiv 0x0C
    // for serial production (dedicated 16MHz oscillator on the shield)
 #define ClkDiv 0x10
+
+// next timer rendez-vous
+unsigned long int prevTime; // JPP V1.03

 SPISettings HI3593SpiSettings(
   // for arduino, SPI clock will be @16MHz/2 = 8MHz (the nearest from 10MHz)
@@ -240,6 +246,8 @@
   // JPP V1.02 (... end)

   Serial.println(F("\t\tThat's all folks !"));
+
+  prevTime = micros(); // JPP V1.03
 }

 void loop() {
@@ -248,5 +256,7 @@
   ArincWord.w = 0x40302010;
   digitalWrite(SS, LOW); SPI.transfer(0x0C); for (int i=0; i<4; i++) SPI.transfer(ArincWord.b[i]); digitalWrite(SS, HIGH);
   // waits 1ms to ensure FIFO is flushed
-  delay(1);
-}
+  unsigned long int nextTime = prevTime + 1000;       // JPP V1.03
+  while((signed long int)(micros() - nextTime) <= 0); // JPP V1.03
+  prevTime = nextTime;                                // JPP V1.03
+}


Add SimCommand Channel (4) see https://github.com/c0nnex/SPAD.neXt/wiki/Command-4

--- Scripts/serialdemo_spad.ino
+++ Scripts/serialdemo_spad.ino
@@ -2,7 +2,7 @@

 // This example shows how to autoconnect between the SPAD.neXt and Arduino.
 //
-// SPAD.neXt >= 0.9.7.3 required
+// SPAD.neXt >= 0.9.7.5 required
 //
 // It demonstrates how to
 // - Respond to a connection request from SPAD.neXt
@@ -27,6 +27,7 @@
   kCommand = 1, // Command to SPAD.neXt
   kEvent = 2, // Events from SPAD.neXt
   kDebug = 3, // Debug strings to SPAD.neXt Logfile
+  kSimCommand = 4, // Send Event to Simulation
   kLed = 10, // CMDID for exposed data to SPAD.neXt
   kHeading = 11, // CMDID for data updates from SPAD.neXt
 };
@@ -118,6 +119,11 @@
 	// If we received a LED ON command, we set the heading in the sim to 180
 	messenger.sendCmd(kHeading,180);

+	// New in 0.9.7.5
+	// For Demo purpose:
+	// Send FLAPS_UP command to simulation
+	messenger.sendCmd(kSimCommand,"SIMCONNECT:FLAPS_UP");
+
   }
   else
   {


Update Timer_Interrupt_Notes.ino

Update Timer_Interrupt_Notes.ino

--- PulseSensorAmped_Arduino_1.5.0/Timer_Interrupt_Notes.ino
+++ PulseSensorAmped_Arduino_1.5.0/Timer_Interrupt_Notes.ino
@@ -175,22 +175,33 @@

   So many new micros are coming out that it's kind of mind boggling. We will add to this list with
   code that uses interupts when we can, but if your micro is not listed here, and you are not willing
-  or able to grab a hardware timer yourself, here is a shortcut that will 'work'.
+  or able to grab a hardware timer yourself, here is a shortcut that will work.
   It won't have the tight timing of a hardware interrupt, but it just might be good enough.
+  We are calling this the 'Software Interrupt' version.
   The code below will set up a microsecond timer and 'trigger' every 2mS (or so).
+
+  FIRST:
   You will need to change the name of the funcion in the Interrupts tab from
   'ISR(TIMER2_COMPA_vect)'
   to
   'void getPulse()'
-  and also comment out the entire interruptSetup() function in the interrupts tab in order for this to work.
+
+  THEN:
+  Comment out the entire interruptSetup() function in the interrupts tab in order for this to work.
+
+  USE:
+  The code example below. Notice that we are using the micros() and the millis() to time the sample rate and the fade rate.
+  DO NOT put any delays in the loop, or it will break the sample timing!

   Happy Hacking!

-  // FIRST, CREATE VARIABLES TO PERFORM THE SAMPLE TIMING FUNCTION
-  unsigned long lastTime;
-  unsigned long thisTime;
+  // FIRST, CREATE VARIABLES TO PERFORM THE SAMPLE TIMING AND LED FADE FUNCTIONS
+  unsigned long lastTime; // used to time the Pulse Sensor samples
+  unsigned long thisTime; // used to time the Pulse Sensor samples
+  unsigned long fadeTime; // used to time the LED fade
+
   void setup(){
     pinMode(blinkPin,OUTPUT);         // pin that will blink to your heartbeat!
     pinMode(fadePin,OUTPUT);          // pin that will fade to your heartbeat!
@@ -202,7 +213,7 @@
     //   analogReference(EXTERNAL);
   } //end of setup()

-  //IN THE LOOP, ADD THE CODE THAT WILL DO THE 2mS TIMING, AND CALL THE getPulse() routine.
+  //IN THE LOOP, ADD THE CODE THAT WILL DO THE 2mS TIMING, AND CALL THE getPulse() FUNCTION.
   void loop(){

     serialOutput() ;
@@ -218,13 +229,17 @@
                        // Quantified Self "QS" true when arduino finds a heartbeat
         fadeRate = 255;         // Makes the LED Fade Effect Happen
                                 // Set 'fadeRate' Variable to 255 to fade LED with pulse
+        fadeTime = millis();    // Set the fade timer to fade the LED
         serialOutputWhenBeatHappens();   // A Beat Happened, Output that to serial.
         QS = false;                      // reset the Quantified Self flag for next time
   }
-
-  ledFadeToBeat();                      // Makes the LED Fade Effect Happen
-  delay(20);                             //  take a break
-}
+
+  if(millis() - fadeTime > 20){
+    fadeTime = millis();
+    ledFadeToBeat();                      // Makes the LED Fade Effect Happen
+    }
+
+} // end of loop


Add #include <SPI.h> to rekam1.ino to support all platforms

--- build/shared/examples/04.Communication/rekam1/rekam1.ino
+++ build/shared/examples/04.Communication/rekam1/rekam1.ino
@@ -53,6 +53,7 @@
 #define CCx 1

 //Uncomment these lines if using CC3200 Launchpad
+#include <SPI.h>
 #include <WiFi.h>
 #include <WiFiClient.h>


Arduino keep alive.

Arduino keep alive.

--- arduino/arduino_md03_v_5_0/arduino_md03_v_5_0.ino
+++ arduino/arduino_md03_v_5_0/arduino_md03_v_5_0.ino
@@ -58,6 +58,7 @@
 int lowBattCon = 0; //
 int battReading1 = 0;
 int battReading2 = 0;
+int keepAlive = 0;

 struct Status {
   int yaw_pos;
@@ -80,9 +81,9 @@
   boolean lid_brake;

 };
-
+
 Status stat = { 0, 0, 0 };
-Command cmd = { 0, true, 0, true, 0, true, LOW };
+Command cmd = { 0, HIGH, 0, HIGH, 0, HIGH, LOW };

 //struct Joint {
 //  String name;
@@ -119,6 +120,9 @@
   pinMode(rlyPin1,OUTPUT); // Setup pins
   pinMode(rlyPin2,OUTPUT); // Setup pins
   pinMode(rlyPin3,OUTPUT); // Setup pins
+  pinMode(motorPinSpeed1,OUTPUT); // Setup pins
+  pinMode(motorPinSpeed2,OUTPUT); // Setup pins
+  pinMode(motorPinSpeed3,OUTPUT); // Setup pins
   pinMode(motorPinDir1,OUTPUT); // Setup pins
   pinMode(motorPinDir2,OUTPUT); // Setup pins
   pinMode(motorPinDir3,OUTPUT); // Setup pins
@@ -208,6 +212,9 @@
         case 8:
           cmd.lid_brake = (value == "1" ? HIGH : LOW);
           break;
+        case 9:
+          keepAlive = value.toInt();
+          break;
         default:
           break;
       }
@@ -230,12 +237,15 @@

 // Send command to the motors
 void do_command() {
-  analogWrite(motorPinSpeed1, cmd.pitch_pwm);
-  digitalWrite(motorPinDir1, cmd.pitch_direction);
-  analogWrite(motorPinSpeed2, cmd.yaw_pwm);
-  digitalWrite(motorPinDir2, cmd.yaw_direction);
-  analogWrite(motorPinSpeed3, cmd.lid_pwm);
-  digitalWrite(motorPinDir3, cmd.lid_direction);
+  if (keepAlive == 42) {
+    analogWrite(motorPinSpeed1, cmd.pitch_pwm);
+    digitalWrite(motorPinDir1, cmd.pitch_direction);
+    analogWrite(motorPinSpeed2, cmd.yaw_pwm);
+    digitalWrite(motorPinDir2, cmd.yaw_direction);
+    analogWrite(motorPinSpeed3, cmd.lid_pwm);
+    digitalWrite(motorPinDir3, cmd.lid_direction);
+    keepAlive = 0;
+  }

   // Brakes
   digitalWrite(rlyPin2, cmd.yaw_brake);


Simplify handleServo responsibilities

Simplify handleServo responsibilities

Signed-off-by: Rick Waldron dd8fdbe95c7f81f312b273ef8860922803e9ef16@gmail.com <dd8fdbe95c7f81f312b273ef8860922803e9ef16@gmail.com>

--- src/du.ino
+++ src/du.ino
@@ -179,8 +179,8 @@
     Serial.println("writing to servo");
     Serial.println(atoi(aux));

-    // servo.write(atoi(aux));
-    moveTo( atoi(aux) );
+    servo.write(atoi(aux));
+    // moveTo( atoi(aux) );

   } else if (atoi(val) == 3) {
     Serial.println("reading servo");
@@ -189,33 +189,32 @@
     sprintf(m, "%s::%03d::read", pin, sval);
     Serial.println(m);
   }
-  //delay(15);
-}
-
-// move to the given position
-void moveTo(int pos) {
-  int step = 4;  // decrease this to slow movement
-  int current = servo.read();
-  int movement = pos - current; // the  number of degrees to move
-
-  Serial.println(movement);
-  if (movement < 0) {
-    while (current > pos) {
-      current = current - step;
-      if (current < pos)
-        current = pos;
-
-      servo.write( current);
-      delay(15);
-    }
-  } else {
-    while (current < pos) {
-      current = current + step;
-      if (current > pos)
-        current = pos;
-
-      servo.write( current);
-      delay(15);
-    }
-  }
-}
+}
+
+// // move to the given position
+// void moveTo(int pos) {
+//   int step = 4;  // decrease this to slow movement
+//   int current = servo.read();
+//   int movement = pos - current; // the  number of degrees to move
+
+//   Serial.println(movement);
+//   if (movement < 0) {
+//     while (current > pos) {
+//       current = current - step;
+//       if (current < pos)
+//         current = pos;
+
+//       servo.write( current);
+//       delay(15);
+//     }
+//   } else {
+//     while (current < pos) {
+//       current = current + step;
+//       if (current > pos)
+//         current = pos;
+
+//       servo.write( current);
+//       delay(15);
+//     }
+//   }
+// }


remove oled stuff

remove oled stuff

--- examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino
+++ examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino
@@ -19,7 +19,6 @@
 unsigned long mtime = 0;

-
 WiFiManager wm;

 // TEST OPTION FLAGS
@@ -34,20 +33,6 @@
 // char ssid[] = "*************";  //  your network SSID (name)
 // char pass[] = "********";       // your network password

-// OLED TEST , ssd1306
-// #define WM_OLED
-#ifdef WM_OLED
-#include <Wire.h>
-#include <Adafruit_GFX.h>
-#include <Adafruit_SSD1306.h>
-#define SCREEN_WIDTH 128 // OLED display width, in pixels
-#define SCREEN_HEIGHT 32 // OLED display height, in pixels
-
-// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
-#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
-Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
-#endif
-
 void saveWifiCallback(){
   Serial.println("[CALLBACK] saveCallback fired");
 }
@@ -55,9 +40,6 @@
 //gets called when WiFiManager enters configuration mode
 void configModeCallback (WiFiManager *myWiFiManager) {
   Serial.println("[CALLBACK] configModeCallback fired");
-  #ifdef ESP8266
-    // print_oled("WiFiManager Waiting\nIP: " + WiFi.softAPIP().toString() + "\nSSID: " + WiFi.softAPSSID(),1);
-  #endif
   // myWiFiManager->setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
   // Serial.println(WiFi.softAPIP());
   //if you used auto generated SSID, print it
@@ -91,12 +73,13 @@

   Serial.println("\n Starting");
   // WiFi.setSleepMode(WIFI_NONE_SLEEP); // disable sleep, can improve ap stability
-
-  #ifdef WM_OLED
-    init_oled();
-  #endif
-
-  print_oled(F("Starting..."),2);
+
+  Serial.println("Error - TEST");
+  Serial.println("Information- - TEST");
+
+  Serial.println("[ERROR]  TEST");
+  Serial.println("[INFORMATION] TEST");
+
   wm.debugPlatformInfo();

   //reset settings - for testing
@@ -201,10 +184,8 @@

   wifiInfo();

-  print_oled(F("Connecting..."),2);
   if(!wm.autoConnect("WM_AutoConnectAP","12345678")) {
     Serial.println("failed to connect and hit timeout");
-    print_oled("Not Connected",2);
   }
   else if(TEST_CP) {
     // start configportal always
@@ -216,7 +197,6 @@
   else {
     //if you get here you have connected to the WiFi
      Serial.println("connected...yeey :)");
-      print_oled("Connected\nIP: " + WiFi.localIP().toString() + "\nSSID: " + WiFi.SSID(),1);
   }

   wifiInfo();
@@ -225,6 +205,7 @@
   #ifdef USEOTA
     ArduinoOTA.begin();
   #endif
+
 }

 void wifiInfo(){
@@ -258,7 +239,6 @@
     else {
       //if you get here you have connected to the WiFi
       Serial.println("connected...yeey :)");
-      print_oled("Connected\nIP: " + WiFi.localIP().toString() + "\nSSID: " + WiFi.SSID(),1);
       getTime();
     }
   }
@@ -317,31 +297,3 @@
   // 507726A4AE30
   // ESP32 Chip ID = 507726A4AE30
 }
-
-#ifdef WM_OLED
-void init_oled(){
-  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
-    Serial.println(F("SSD1306 allocation failed"));
-  }
-
-  display.clearDisplay();
-  display.setTextSize(1);             // Normal 1:1 pixepl scale
-  display.setTextColor(WHITE);        // Draw white text
-  display.setCursor(0,0);             // Start at top-left corner
-  display.display();
-}
-
-void print_oled(String str,uint8_t size){
-  display.clearDisplay();
-  display.setTextSize(size);
-  display.setTextColor(WHITE);
-  display.setCursor(0,0);
-  display.println(str);
-  display.display();
-}
-#else
-  void print_oled(String str,uint8_t size){
-    (void)str;
-    (void)size;
-  }
-#endif


Cleaned up loop startup serial print

Cleaned up loop startup serial print

--- firmware/firmware.ino
+++ firmware/firmware.ino
@@ -59,9 +59,7 @@
  */
 void loop(){
 	// time stamp each iteration
-	Serial.print("************ Time now in millis: ");
-	Serial.print(millis());
-	Serial.println(" ************");
+	Serial.println("\n\n************ loop() starting at millis: " + String(millis()) + " ************");

 	// Read our s.
 	Sensor_data sensor_data = sensors.read_sensors();


Fix boot settle happening after trying to configure the modules.

--- firmware/firmware.ino
+++ firmware/firmware.ino
@@ -51,6 +51,9 @@
     #endif

     EepromSettings.load();
+
+    // Wait for modules to settle.
+    delay(BOOT_DELAY_MS);

     // Configure receivers.
     for (uint8_t i = 0; i < RECEIVER_COUNT; i++) {
@@ -66,9 +69,6 @@
         receivers[i].setFrequency(EepromSettings.frequency[i]);
     }

-    // Wait for modules to settle.
-    delay(BOOT_DELAY_MS);
-
     rssiTimer.reset();
     #ifdef MONITORING_ENABLED
         monitorTimer.reset();


lines fill and circles scenes

lines fill and circles scenes

--- taurus.ino
+++ taurus.ino
@@ -73,12 +73,14 @@
 		FADE_IN,
 		WHITE_BEAR,
 		PARTY_WORDS,
+		FILL_LINES,
+		CIRCLES,
 		TOTAL
 };

 //TODO: Re-enable "verify code" in Arduino IDE

-Scene currentScene = PARTY_WORDS;
+Scene currentScene = CIRCLES;
 Scene lastScene = -1;
 TVout TV;
 unsigned long startTime = 0;
@@ -801,6 +803,62 @@
 		}
 }

+int fillLinesDirection = 0;
+void fillLinesScene(bool changed) {
+		if (changed) {
+				TV.bitmap(BMP_X, BMP_Y, getRandomSymbol());
+				screenToBackBuffer();
+				TV.clear_screen();
+				fillLinesDirection = random(4);
+		}
+
+		int x = random(WIDTH);
+		int y = random(HEIGHT);
+
+		while (!backBufferGet(x, y)) {
+				TV.set_pixel(x, y, 1);
+
+				switch (fillLinesDirection) {
+						case UP:
+								y--;
+								break;
+						case DOWN:
+								y++;
+								break;
+						case RIGHT:
+								x++;
+								break;
+						case LEFT:
+								x--;
+								break;
+				}
+
+				if (x < 0 || x > WIDTH - 1 || y < 0 || y > HEIGHT - 1) {
+						break;
+				}
+		}
+
+		TV.delay_frame(1);
+
+		checkSceneEnded(25);
+}
+
+unsigned int circleCounter = 0;
+void circlesScene(bool changed) {
+		if (changed) {
+
+		}
+
+		for (int i = 0; i < HEIGHT / 2; i++) {
+				TV.draw_circle(WIDTH / 2, HEIGHT / 2, i, (i + circleCounter) % 2);
+				TV.delay_frame(1);
+		}
+
+		circleCounter++;
+
+		checkSceneEnded(15);
+}
+
 void loop() {
 		bool changed = false;
 		if (currentScene != lastScene) {
@@ -893,6 +951,12 @@
 				case PARTY_WORDS:
 						partyWordsScene();
 						break;
+				case FILL_LINES:
+						fillLinesScene(changed);
+						break;
+				case CIRCLES:
+						circlesScene(changed);
+						break;
 				default:
 						TV.print("Invalid scene. ");
 						TV.delay(1000);


Terminal prints IP address w/ uptime.

Terminal prints IP address w/ uptime.

--- hvacMonitor.ino
+++ hvacMonitor.ino
@@ -19,7 +19,7 @@
 DeviceAddress ds18b20RA = { 0x28, 0xEF, 0x97, 0x1E, 0x00, 0x00, 0x80, 0x54 }; // Return air probe - Device address found by going to File -> Examples -> DallasTemperature -> oneWireSearch
 DeviceAddress ds18b20SA = { 0x28, 0xF1, 0xAC, 0x1E, 0x00, 0x00, 0x80, 0xE8 }; // Supply air probe

-char auth[] = "fromBlynkApp";
+char auth[] = "fromBlynkApp"; // HVAC Production
 char ssid[] = "ssid";
 char pass[] = "pw";

@@ -66,12 +66,11 @@
 int eeWBsum;              // This is the sum of all EEPROM addresses (total runtime stored).
 int eeTodaysStartsCount;  // Records how many times the unit has started today.

-
 void setup()
 {
   Serial.begin(9600);
-   WiFi.mode(WIFI_STA);
-
+  WiFi.mode(WIFI_STA);
+
   //WiFi.softAPdisconnect(true); // Per https://github.com/esp8266/Arduino/issues/676 this turns off AP
   Blynk.begin(auth, ssid, pass);

@@ -83,7 +82,8 @@
     // Wait until connected
   }

-    ArduinoOTA.onStart([]() {
+  // START OTA ROUTINE
+  ArduinoOTA.onStart([]() {
     Serial.println("Start");
   });
   ArduinoOTA.onEnd([]() {
@@ -104,7 +104,8 @@
   Serial.println("Ready");
   Serial.print("IP address: ");
   Serial.println(WiFi.localIP());
-
+  // END OTA ROUTINE
+
   rtc.begin();

   EEPROM.begin(201); // EEPROM is zero-index: means addresses 0 to 200 are available (not 1 to 201 or 0 to 201).
@@ -221,7 +222,6 @@

     Serial.println();
     Serial.println("closing connection");
-
   }
 }

@@ -239,11 +239,13 @@

     if (minDur < 121)
     {
-      terminal.println(String("HVAC: ") + minDur + " mins ");
+      terminal.print(String("HVAC: ") + minDur + " mins @ ");
+      terminal.println(WiFi.localIP());
     }
     else if (minDur > 120)
     {
-      terminal.println(String("HVAC: ") + hourDur + " hours ");
+      terminal.print(String("HVAC: ") + hourDur + " hrs @ ");
+      terminal.println(WiFi.localIP());
     }
     terminal.flush();
   }
@@ -531,7 +533,6 @@
       EEPROM.commit();
     }

-
     if (yesterdayRuntime < 1)
     {
       Blynk.virtualWrite(14, "None");


onHour24 & offHour24 tweaks.

onHour24 & offHour24 tweaks.

--- hvacMonitor.ino
+++ hvacMonitor.ino
@@ -93,7 +93,7 @@
     // Wait until connected
   }

-  // EEPROM WRITEBACK AFTER RESET (if required)
+  // START EEPROM WRITEBACK ROUTINE
   if (EEPROM.read(eeIndex) > 1) // If this is true, than the index has advanced beyond the first position (meaning something was stored there (and maybe higher) to be written back.
   {
     for (int i = 1 ; i < 200 ; i++) {
@@ -244,7 +244,6 @@
   else {
     delay(DELAY_ERROR);
   }
-
 }

 bool showWeather(char *json)
@@ -342,38 +341,38 @@
   }
   else if (digitalRead(blowerPin) == HIGH && resetTattle == 1) // Runs when blower is OFF.
   {
-    if (offHour < 12 && offMinute > 9)
+    if (offHour24 < 12 && offMinute > 9)
     {
       Blynk.virtualWrite(16, String("HVAC OFF since ") + offHour + ":" + offMinute + "AM on " + offMonth + "/" + offDay);
     }
-    else if (offHour < 12 && offMinute < 10)
+    else if (offHour24 < 12 && offMinute < 10)
     {
       Blynk.virtualWrite(16, String("HVAC OFF since ") + offHour + ":0" + offMinute + "AM on " + offMonth + "/" + offDay);
     }
-    else if (offHour > 11 && offMinute > 9)
+    else if (offHour24 > 11 && offMinute > 9)
     {
       Blynk.virtualWrite(16, String("HVAC OFF since ") + offHour + ":" + offMinute + "PM on " + offMonth + "/" + offDay);
     }
-    else if (offHour > 11 && offMinute < 10)
+    else if (offHour24 > 11 && offMinute < 10)
     {
       Blynk.virtualWrite(16, String("HVAC OFF since ") + offHour + ":0" + offMinute + "PM on " + offMonth + "/" + offDay);
     }
   }
   else if (digitalRead(blowerPin) == LOW && resetTattle == 1)
   {
-    if (onHour < 12 && onMinute > 9)
+    if (onHour24 < 12 && onMinute > 9)
     {
       Blynk.virtualWrite(16, String("HVAC ON since ") + onHour + ":" + onMinute + "AM on " + onMonth + "/" + onDay);
     }
-    else if (onHour < 12 && onMinute < 10)
+    else if (onHour24 < 12 && onMinute < 10)
     {
       Blynk.virtualWrite(16, String("HVAC ON since ") + onHour + ":0" + onMinute + "AM on " + onMonth + "/" + onDay);
     }
-    else if (onHour > 11 && onMinute > 9)
+    else if (onHour24 > 11 && onMinute > 9)
     {
       Blynk.virtualWrite(16, String("HVAC ON since ") + onHour + ":" + onMinute + "PM on " + onMonth + "/" + onDay);
     }
-    else if (onHour > 11 && onMinute < 10)
+    else if (onHour24 > 11 && onMinute < 10)
     {
       Blynk.virtualWrite(16, String("HVAC ON since ") + onHour + ":0" + onMinute + "PM on " + onMonth + "/" + onDay);
     }


reqair the library of DStepper

reqair the library of DStepper

--- driver_mega.ino
+++ driver_mega.ino
@@ -1,9 +1,9 @@
-#include <DStepper.h>
+#include <Stepper.h>

 const int stepPer = 200;

-DStepper stepper1(stepPer, 4, 5, 6, 7);
-DStepper stepper2(stepPer, 8, 9, 10, 11);
+Stepper stepper1(stepPer, 4, 5, 6, 7);
+Stepper stepper2(stepPer, 8, 9, 10, 11);

 int begin;
 char ins[2];


Added Galvanic Skin Response Read-in

Added Galvanic Skin Response Read-in

--- acelaso.ino/acelaso.ino.ino
+++ acelaso.ino/acelaso.ino.ino
@@ -88,6 +88,8 @@
   float diet = tmp006.readDieTempC();
   Serial.print("Die Temperature: "); Serial.print(diet); Serial.println("*C");

+  //Galvanic Skin Response Read
+  float gsr = analogRead(4);

   Wire.beginTransmission(ExpAddress);// transmit to GPIIO device #32 (0x20)


New (Smoother?) Method

New (Smoother?) Method

Manually sends pulses to servo as servo library can be unreliable
(interrupted by other services).

--- rocker/rocker.ino
+++ rocker/rocker.ino
@@ -45,6 +45,7 @@
 /* LOOP */
 /********/
 void loop() {
+  cli();
   Serial.println("Enter frequency, amplitude");
   while ( Serial.available() == 0 ) {}
    int n = Serial.readBytesUntil(',',buf,BUFLEN);
@@ -73,12 +74,17 @@

      float ampus = amp*(float)(maxt-mint)/180.0;
      float mid = (float)(maxt+mint)/2.0;
-     long int start = micros();
+     long start = micros();
+     //cli();
      while ( Serial.available() == 0 ) {
-       long int time = micros();
+       long time = micros();
+       digitalWrite(SERVO_PIN, HIGH);
        pos = round(ampus*sin(2*PI*freq*(time-start)/1000000.0) + mid);
-       servo.writeMicroseconds(pos);
+       while (micros() - time < pos) {}
+       digitalWrite(SERVO_PIN, LOW);
+       while (micros() - time < 20000) {}
      }
+     //sei();
      while( pos != round(mid))
      {
        pos = round(ampus*sin(2*PI*freq*(micros()-start)/1000000.0) + mid);
@@ -86,3 +92,13 @@
      }
    }
 }
+
+/*void servoWrite(int us)
+{
+  cli();
+  long start = micros();
+  digitalWrite(SERVO_PIN, HIGH);
+  while (micros() - start < duration) {}
+  digitalWrite(SERVO_PIN, LOW);
+  sei();
+}*/


Adding Nuke.YKT's protocol as an option

Adding Nuke.YKT's protocol as an option

This provides a basic packet validation to avoid syncronisation issues and is compatible with Wohlstand's OPL3BankEditor.

--- examples/OPL3Duo/SerialPassthrough/SerialPassthrough.ino
+++ examples/OPL3Duo/SerialPassthrough/SerialPassthrough.ino
@@ -20,6 +20,8 @@
 #include <SPI.h>
 #include <OPL3Duo.h>

+//#define NUKEYKTPROTO
+
 OPL3Duo opl3Duo;

 void setup() {
@@ -28,6 +30,7 @@
 }

 void loop() {
+#ifndef NUKEYKTPROTO
 	while (Serial.available() > 2) {
 		byte bank = Serial.read() & 0x03;
 		byte reg = Serial.read();
@@ -35,4 +38,24 @@

 		opl3Duo.write(bank, reg, val);
 	}
+#else
+	// If NUKEYKTPROTO is defined then Nuke.YKT's protocol is used.
+	// It provides a basic packet validation to avoid syncronisation issues.
+	// Also it's implemented and ready to use with Wohlstand's OPL3BankEditor.
+
+	if(Serial.available()) {
+		int x1 = Serial.read();
+		if(x1&0x80) { // Check if first byte of the transferred packet is valid
+			while(!Serial.available());
+				byte x2= Serial.read();
+			while(!Serial.available());
+				byte x3 = Serial.read();
+			byte bank = (x1>>2);
+			byte reg = ((x1<<6)&0x0c0)|((x2>>1)&0x3f);
+			byte data = ((x2<<7)&0x80)|(x3&0x7f);
+			opl3.write(bank, reg, data);
+		}
+	}
+#endif
+
 }


IFTT name length

IFTT name length

--- examples/_2000_ESPert_workshop/_2000_ESPert_workshop.ino
+++ examples/_2000_ESPert_workshop/_2000_ESPert_workshop.ino
@@ -75,7 +75,7 @@

     String value = espert.json.get("IFTTT");
     ifttt_key = value;
-    espert.eeprom.write( 200, ifttt_key );
+    espert.eeprom.write( 150, ifttt_key );
   }
 }

@@ -86,7 +86,7 @@
   espert.dht.init();
   espert.mqtt.init(mqtt_server, 1883, callback);

-  ifttt_key = espert.eeprom.read( 200, 32 );
+  ifttt_key = espert.eeprom.read( 150, 80 );

   button2.init( 0 );


Update SterlitechDroprateTests.ino

Update SterlitechDroprateTests.ino

--- SterlitechDroprateTests/SterlitechDroprateTests.ino
+++ SterlitechDroprateTests/SterlitechDroprateTests.ino
@@ -38,8 +38,8 @@
    Serial.begin(9600);
    attachInterrupt(0, dropcount_fun, RISING);  //pin 2 tr reciever
    pinMode(feedppin,INPUT);//pin A0
-   drop_num = 5;
-   dropcount = 0;
+   drop_num = 2;
+   dropcount = 3;
    dropcount2 = 0;
    strokerate = 118;
    lowflowtime = 0;
@@ -56,7 +56,7 @@
    totalvol = 0;

    //make sure this is correct!
-   dropsize = 0.023;//how to find this
+   dropsize = 0.017;//how to find this
    //make sure this is correct!

    flowrate = 0;
@@ -69,7 +69,7 @@
   Serial.print("Time");Serial.print("\t");
   Serial.print("PSI");Serial.print("\t");
   Serial.print("Drops");Serial.print("\t");
-  Serial.print("Vol L");Serial.print("\t");
+  Serial.print("Vol mL");Serial.print("\t");
   Serial.println("flowrate mL/min");
 }

@@ -82,7 +82,7 @@
      timeold = millis();
      totaldrops = totaldropsold + dropcount;
      totaldropsold = totaldrops;
-     totalvol = totaldrops * dropsize; //reports in L
+     totalvol = totaldrops * dropsize; //reports in mL
      flowrate = dropcount * dropsize / time_int * 1000 * 60; //report in mL per min
      flowratehigh = flowtarget * 1.03;
      flowratelow = flowtarget * 0.97;
@@ -100,7 +100,7 @@
      Serial.print(sfeedp);Serial.print("\t");
      //Serial.print(" Drops: ");
      Serial.print(totaldrops);Serial.print("\t");
-     //Serial.print(" Volume (L): ");
+     //Serial.print(" Volume (mL): ");
      Serial.print(totalvol);Serial.print("\t");
      //Serial.print(" FlowRate (mL/min): ");
      Serial.println(flowrate);}
@@ -128,6 +128,6 @@
 }
 void pressures(){//read and average pressure values
   int junk = analogRead(feedppin);
-  feedp = analogRead(feedppin)*.21-16.5;
+  feedp = analogRead(feedppin)*.7-54;
   sfeedp = (sfeedp+feedp)/2;
 }


Fixes Yun example to work in case Bridge isn't up.

--- examples/arduino/BasicIobeamYun/BasicIobeamYun.ino
+++ examples/arduino/BasicIobeamYun/BasicIobeamYun.ino
@@ -16,12 +16,12 @@
 #include <YunClient.h>

 #define API_DEFAULT_SERVER "api.iobeam.com"
-#define DEBUG_LEVEL 2
+#define DEBUG_LEVEL 0
 #include <Iobeam.h>

 // Necessary for iobeam. The project token should be PROGMEM to save RAM.
 #define PROJECT_ID -1  // YOUR PROJECT ID
-PROGMEM const char token[] = {"YOUR PROJECT TOKEN HERE"};
+PROGMEM const char token[] = {"YOUR PROJECT TOKEN"};

 // Initialize the network and iobeam libraries.
 YunClient client;
@@ -62,10 +62,23 @@

 void setupNetwork() {
   Bridge.begin();
+  int tries = 0;
+  while (1) {
+    int ret = client.connect("iobeam.com", 80);
+    client.stop();
+    if (ret > 0)
+      break;
+    delay(1000);
+    IOBEAM_ERR("Failed to connect, retry...\n");
+    tries++;
+    if (tries > 30)
+      break;
+  }
   delay(1000);  // give Client a moment to init
 }

 void errorForever() {
+  IOBEAM_ERR("Error, looping forever.\n");
   while(1);
 }


simplify cursor blink

simplify cursor blink

--- vfobox.ino
+++ vfobox.ino
@@ -67,7 +67,6 @@
 long lastBlink = 0;
 long lastStatus = 0;

-boolean blinkState = false;
 boolean statusDisplayed = false;

 int eeAddressStart = 0;
@@ -306,12 +305,16 @@
       }
     }
     lcd.setCursor(freqCursorPosition,0);
-    if(blinkState) {
+    lcd.blink();
+
+    /*
       lcd.noBlink();
     } else {
       lcd.blink();
     }
-    blinkState = !blinkState;
+
+
+    */
     lastBlink = millis();
   }


Add pressure support with BMP180.

Add pressure support with BMP180.

--- arduino/monitor/monitor.ino
+++ arduino/monitor/monitor.ino
@@ -9,7 +9,8 @@

 #include <Wire.h>
 #include <SoftwareSerial.h>
-#include "HTU21D.h"
+#include <HTU21D.h>
+#include <SFE_BMP180.h>

 const byte AIO_WIND_DIRECTION = A0;

@@ -22,6 +23,8 @@

 //

+const float ALTITUDE = 254.8;
+
 const byte BOUNCE_DELAY_MS = 10;
 const int UPDATE_RATE_MS = 1000;
 const byte WIND_SPEED_SAMPLE_COUNT = 5;
@@ -33,6 +36,7 @@

 SoftwareSerial xbeeSerial(DIO_XBEE_RX, DIO_XBEE_TX);
 HTU21D htuSensor;
+SFE_BMP180 bmpSensor;

 // Arduino //

@@ -52,6 +56,10 @@

   xbeeSerial.begin(9600);
   Serial.begin(9600);
+
+  if(!bmpSensor.begin()) {
+    sendError(xbeeSerial, "Could not initialize BMP180.");
+  }
 }

 void loop()
@@ -111,8 +119,17 @@
   out.print(getWindDirection());
   out.print("&t=");
   out.print(htuSensor.readTemperature());
+  out.print("&p=");
+  out.print(getPressure());
   out.print("&h=");
   out.print(htuSensor.readHumidity());
+  out.println("]");
+}
+
+void sendError(Stream &out, String error)
+{
+  out.print("[e=");
+  out.print(error);
   out.println("]");
 }

@@ -160,6 +177,45 @@
   return windSpeed;
 }

+double getBmpSensorTemp()
+{
+  byte wait = bmpSensor.startTemperature();
+  if(wait == 0) {
+    return -1;
+  }
+
+  delay(wait);
+  double temperature;
+  wait = bmpSensor.getTemperature(temperature);
+  if(wait == 0) {
+    return -2;
+  }
+
+  return temperature;
+}
+
+double getPressure()
+{
+  byte wait = bmpSensor.startPressure(3);
+  if(wait == 0) {
+    return -10;
+  }
+
+  delay(wait);
+  double pressure=0;
+  double temp = getBmpSensorTemp();
+  if(temp == 0) {
+    return temp;
+  }
+
+  wait = bmpSensor.getPressure(pressure, temp);
+  if(wait == 0) {
+    return -20;
+  }
+
+  return bmpSensor.sealevel(pressure, ALTITUDE);
+}
+
 int averageAnalogRead(int pinToRead)
 {
   byte numberOfReadings = 8;


Reduce memory usage

Reduce memory usage

--- Arduino/arduino/arduino.ino
+++ Arduino/arduino/arduino.ino
@@ -14,6 +14,7 @@
 IPAddress ipServeurEnregistrement(192,168,2,1); // IP du serveur d'enregistrement
 int portServeurEnregistrement=100; // port du serveur d'enregistrement
 EthernetClient clientArduino; // le client Arduino du serveur d'enregistrement
+

 // initialisation
 void setup() {
@@ -111,6 +112,8 @@
   int l = commande.length();
   char cmd[l+1];
   commande.toCharArray(cmd, l+1);
+
+
   // on parse la commande JSON
   aJsonObject *json = aJson.parse(cmd);

@@ -131,7 +134,7 @@
     return;
   }
   // on mémorise l'id
-  char strId[sizeof(id->valuestring)*2];
+  /*char strId[sizeof(id->valuestring)*2];
   String(id->valuestring).toCharArray(strId, sizeof(strId));
   /* get last digit if id is an ip => causes problems because of lack of memory
   int index = String(id->valuestring).lastIndexOf('.');
@@ -141,6 +144,7 @@
   Serial.print("Debug: id = ");
   Serial.println(strId);
   */
+  char* strId = id->valuestring;

   // attribut action
   aJsonObject *action = aJson.getObjectItem(json, "ac");
@@ -263,8 +267,9 @@
     return;
   }
   // valeur de la pin à eteindre
-  String strLed = pin->valuestring;
-  int led = strLed.toInt();
+  /*String strLed = pin->valuestring;
+  int led = strLed.toInt();*/
+  int led = atoi(pin->valuestring);
   Serial.print(F("clignoter led="));
   Serial.println(led);

@@ -276,8 +281,9 @@
     return;
   }
   // valeur de la durée
-  String strDuree = dur->valuestring;
-  int duree = strDuree.toInt();
+  /*String strDuree = dur->valuestring;
+  int duree = strDuree.toInt();*/
+  int duree = atoi(dur->valuestring);
   Serial.print(F("duree="));
   Serial.println(duree);

@@ -289,8 +295,9 @@
     return;
   }
   // valeur du nombre de clignotements
-  String strNbClignotements = nb->valuestring;
-  int nbClignotements = strNbClignotements.toInt();
+  /*String strNbClignotements = nb->valuestring;
+  int nbClignotements = strNbClignotements.toInt();*/
+  int nbClignotements = atoi(nb->valuestring);
   Serial.print(F("nb="));
   Serial.println(nbClignotements);

@@ -299,12 +306,12 @@
   // on opère le clignotement
   int i = 0;
   pinMode(led, OUTPUT);
-  while(i < nbClignotements) {
+
+  for(int i=0; i < nbClignotements; ++i) {
     digitalWrite(led, HIGH);
     delay(duree);
     digitalWrite(led, LOW);
-    delay(duree);
-    ++i;
+    delay(duree);
   }
 }

@@ -317,8 +324,9 @@
     return;
   }
   // numéro de la pin à écrire
-  String strPin = pin->valuestring;
-  int pin2 = strPin.toInt();
+  /*String strPin = pin->valuestring;
+  int pin2 = strPin.toInt();*/
+  int pin2 = atoi(pin->valuestring);
   // suivi
   Serial.print(F("pw pin="));
   Serial.println(pin2);
@@ -329,8 +337,9 @@
     return;
   }
   // valeur à écrire
-  String strVal = val->valuestring;
-  int val2 = strVal.toInt();
+  /*String strVal = val->valuestring;
+  int val2 = strVal.toInt();*/
+  int val2 = atoi(val->valuestring);
   // suivi
   Serial.print(F("pw val="));
   Serial.println(val2);
@@ -373,8 +382,9 @@
     return;
   }
   // numéro de la pin à lire
-  String strPin = pin->valuestring;
-  int pin2 = strPin.toInt();
+  /*String strPin = pin->valuestring;
+  int pin2 = strPin.toInt();*/
+  int pin2 = atoi(pin->valuestring);
   // suivi
   Serial.print(F("pr pin="));
   Serial.println(pin2);
@@ -413,6 +423,7 @@
   // suivi
   Serial.print(F("reponse="));
   Serial.println(message);
+  //clear reponse string
 }

 // mémoire libre


Heartbeat and minor stuff

Heartbeat and minor stuff

--- hvacMonitor.ino
+++ hvacMonitor.ino
@@ -88,7 +88,7 @@
   Serial.begin(9600);
   Blynk.begin(auth, "ssid", "pw");

-  EEPROM.begin(201); // Reminder: "201" means addresses 0 to 200 are available (not 1 to 201 or 0 to201).
+  EEPROM.begin(201); // Reminder: "201" means addresses 0 to 200 are available (not 1 to 201 or 0 to 201).

   sensors.begin();
   sensors.setResolution(ds18b20RA, 10);
@@ -119,9 +119,8 @@

   timer.setInterval(2500L, sendTemps); // Temperature sensor polling interval
   timer.setInterval(2500L, sendBlowerStatus); // Blower fan status polling interval
-  timer.setInterval(5000L, sendHeartbeat); // Blinks Blynk LED to reflect online status
+  timer.setInterval(5000L, heartbeatOn); // Blinks Blynk LED to reflect online status
   timer.setInterval(180000L, sendWU); // 3 minutes between Wunderground API calls.
-  //timer.setInterval(330000L, sendWUtoBlynk); // 5ish minutes between API data updates to Blynk.
   timer.setInterval(1000L, countRuntime);  // Counts blower runtime for daily accumulation displays.
   timer.setInterval(1000L, totalRuntime);  // Counts blower runtime for daily EEPROM storage.
   timer.setInterval(500L, timeKeeper);
@@ -131,6 +130,17 @@
 {
   Blynk.run();
   timer.run();
+}
+
+void heartbeatOn()  // Blinks a virtual LED in the Blynk app to show the ESP is live and reporting.
+{
+  led1.on();
+  timer.setTimeout(2500L, heartbeatOff);
+}
+
+void heartbeatOff()
+{
+  led1.off();  // The OFF portion of the LED heartbeat indicator in the Blynk app
 }

 BLYNK_WRITE(V19) // App button to reset EEPROM stored total and address
@@ -326,7 +336,6 @@
   {
     Blynk.virtualWrite(1, "ERR");
   }
-  led1.off();  // The OFF portion of the LED heartbeat indicator in the Blynk app
 }

 void sendBlowerStatus()
@@ -393,30 +402,7 @@
     {
       Blynk.virtualWrite(16, String("HVAC ON since ") + onHour + ":0" + onMinute + "PM on " + onMonth + "/" + onDay);
     }
-
-    /*
-    {
-      // Create runTimeMin and runTimeHour variables (look at hours floating point)
-      runTimeMin = ( (onNow - offNow) / 60 ); // Still need to make this report 'right' time on first run!
-      runTimeHour = ( runTimeMin / 60 );
-      if (runTimeMin > splitAlarmTime)
-      {
-      Blynk.tweet(String("A/C ON after ") + runTimeHour + " hours of inactivity. " + hour() + ":" + minute() + ":" + second() + " " + month() + "/" + day() + "/" + year());
-      xStart++;
-      }
-      else
-      {
-      Blynk.tweet(String("A/C ON after ") + runTimeMin + " minutes of inactivity. " + hour() + ":" + minute() + ":" + second() + " " + month() + "/" + day() + "/" + year());
-      xStart++;
-      }
-    }
-    */
-  }
-}
-
-void sendHeartbeat()  // Blinks a virtual LED in the Blynk app to show the ESP is live and reporting.
-{
-  led1.on();
+  }
 }

 void totalRuntime() // Counts the current blower run session.
@@ -518,7 +504,7 @@
     if (tempSplit <= 15 && secondsCount > alarmTime && alarmFor == 1)
     {
       Blynk.tweet(String("Low split (") + tempSplit + "°F) " + "recorded at " + hour() + ":" + minute() + ":" + second() + " " + month() + "/" + day() + "/" + year());
-      Blynk.notify(String("Low HVAC split: ") + tempSplit + "°F");
+      Blynk.notify(String("Low HVAC split: ") + tempSplit + "°F. Call Cool Guys @ 480-313-8893");
       //terminal.println(String("Low HVAC split: ") + tempSplit + "°F");
       alarmFor = 5; // Arbitrary value indicating notification sent and locking out repetitive notifications.
     }