Another revision of getting the oven to work with a potentiometer

--- oven.ino
+++ oven.ino
@@ -5,15 +5,19 @@
 // Pin number the push button is connected to
 const int buttonPin = 2;

-// Somewhere to store the state of the button
+// The last state the button was in
 int buttonState = 0;
+int lastButtonState = 0;
+
+// This MOD the number of states determines the state we are in
+int buttonPressCounter = 0;

 // Potentiometer PIN
 const int potentiometerPin = A0;

 // Value of the potentiometer
 int potentiometerValue = 0;
-int potentiometerLastValue = 0;
+int lastPotentiometerValue = 0;

 // Pin numbers for the RGB LEB
 const int ledRedPin = 9;
@@ -23,7 +27,9 @@
 // I2C address of our S7S
 const byte s7sAddress = 0x71;

-unsigned int counter = 9900;  // This variable will count up to 65k
+
+
+unsigned int counter = 990;  // This variable will count up to 65k
 char tempString[10];  // Will be used with sprintf to create strings

 void setup()
@@ -47,17 +53,7 @@
   //  The I2C.write function only allows sending of a single
   //  byte at a time.
   s7sSendStringI2C("-HI-");
-  delay(1500);
-  s7sSendStringI2C("HELO");
-  delay(1500);
-  setDecimalsI2C(0b111111);  // Turn on all decimals, colon, apos
-
-  delay(1500);
-  // Flash brightness values at the beginning
-  setBrightnessI2C(0);  // Lowest brightness
-  delay(1500);
-  setBrightnessI2C(255);  // High brightness
-  delay(1500);
+  delay(2000);

   // Clear the display before jumping into loop
   clearDisplayI2C();
@@ -67,42 +63,97 @@
 {
   // Read value of potentiometer
   potentiometerValue = analogRead(potentiometerPin);
-  if (potentiometerValue != potentiometerLastValue) {
+  if (potentiometerValue != lastPotentiometerValue) {
     Serial.println(potentiometerValue);
   }
-  potentiometerLastValue = potentiometerValue;
-
+  lastPotentiometerValue = potentiometerValue;
+
+  if (hasButtonBeenPushed()) {
+    Serial.println("Button Pushed");
+    buttonPressCounter++;
+    Serial.println(buttonPressCounter);
+  }
+
+  switch (buttonPressCounter % 3) {
+    case 0:
+      setColor(0, 255, 0);
+      adjustTime();
+      break;
+    case 1:
+      setColor(255, 0, 0);
+      countDown();
+      break;
+    case 2:
+      setColor(0, 0, 0);
+      clearDisplayI2C();
+      counter = 0;
+      break;
+  }
+}
+
+
+void adjustTime() {
+  counter = potentiometerValue;
+  printCounter();
+}
+
+void countDown() {
+  counter--;
+  printCounter();
+
+  if (counter == 0) {
+    soupsReady();
+  } else {
+    delay(500);
+  }
+}
+
+void soupsReady() {
+  buttonPressCounter = 2;
+  setColor(255, 255, 0);
+  s7sSendStringI2C("   0");
+  delay(500);
+
+  setColor(0, 255, 255);
+  s7sSendStringI2C("  00");
+  delay(500);
+
+  setColor(255, 0, 255);
+  s7sSendStringI2C(" 000");
+  delay(500);
+
+  setColor(255, 255, 255);
+  s7sSendStringI2C("0000");
+  delay(500);
+}
+
+void printCounter() {
+  // Magical sprintf creates a string for us to send to the s7s.
+  //  The %4d option creates a 4-digit integer.
+  sprintf(tempString, "%4d", counter);
+
+  // This will output the tempString to the S7S
+  s7sSendStringI2C(tempString);
+}
+
+/* Interrupt emulation. Detect when the button was pushed once and only once
+ * while it is held down
+ */
+boolean hasButtonBeenPushed() {
+  boolean hasButtonBeenPushed = false;
+
   // Read the state of the button
   buttonState = digitalRead(buttonPin);
   if (buttonState == LOW) {
-    Serial.println("Button pushed ON");
-  }
-
-  // Set color of LED
-  if (buttonState == LOW) {
-    setColor(255, 0, 0);
-  } else {
-    int green = potentiometerValue / 10;
-    setColor(0, green, 0);
-  }
-
-
-  // Magical sprintf creates a string for us to send to the s7s.
-  //  The %4d option creates a 4-digit integer.
-  sprintf(tempString, "%4d", counter);
-
-  // This will output the tempString to the S7S
-  s7sSendStringI2C(tempString);
-
-  // Print the decimal at the proper spot
-  if (counter < 10000)
-    setDecimalsI2C(0b00000100);  // Sets digit 3 decimal on
-  else
-    setDecimalsI2C(0b00001000);
-
-  counter++;  // Increment the counter
-  delay(100);  // This will make the display update at 10Hz.*/
-}
+    if (lastButtonState == HIGH) {
+      hasButtonBeenPushed = true;
+    }
+  }
+  lastButtonState = buttonState;
+
+  return hasButtonBeenPushed;
+}
+

 // Sets the color of the RGB LEB
 void setColor(int red, int green, int blue)


Order matters.

Order matters.

--- station/station.ino
+++ station/station.ino
@@ -33,12 +33,11 @@
 }

 void loop() {
-  loopNTPClient(conn);
-
   conn->loop();

   loopOTA();

+  loopNTPClient(conn);
   loopSensorDHT(conn);
   loopSensorUltrasonic(conn);
   loopSensorMPXH6300A(conn);


Still working on r/w capabilities. We are either reading or writting errors to the board state configuration file.

--- BackEnd/BackEnd.ino
+++ BackEnd/BackEnd.ino
@@ -478,6 +478,7 @@
   fp = fopen(_sFullFilePath, "r");
 //  Serial.println("File Open");
   fgets(sJsonFile, CONFIG_FILE_MAX_SIZE, fp);
+  Serial.println(sJsonFile);
 //  Serial.println("File Close");
   fclose(fp);

@@ -516,7 +517,7 @@
   else
   {
    // Serial.println("sJsonFile");
-   // Serial.println(sJsonFile);
+//    Serial.println(sJsonFile);
     Serial.println("Couln't update system from file.");
   }

@@ -1376,7 +1377,7 @@

 void writeBoardStateToFile(char* _sFileFullPath)
 {
-  Serial.println("Write state to file");
+//  Serial.println("Write state to file");
   unsigned char buf[WEB_SOCKET_BUFFER_SIZE];

   // Get the state of the board
@@ -1393,13 +1394,13 @@
     if( Output )
     {
       // Write the state
-      Serial.println("Board State:");
-      Serial.println(sTempString);
+//      Serial.println("Board State:");
+ //     Serial.println(sTempString);
       fputs((char *)buf, Output);
     }
     else
     {
-      Serial.println("Nothing found in the board state file.");
+     Serial.println("Nothing found in the board state file.");
     }

     fclose(Output);
@@ -1547,6 +1548,9 @@
   {
     // Save board state every ~1 sec
     writeBoardStateToFile(BOARD_CONFIG_FILE_FULL_PATH);
+
+    // Flush serial buffer
+    Serial.flush();

     last_print = millis();
   }


first working attempt to capture gps data with everything else

--- Balloon/Balloon.ino
+++ Balloon/Balloon.ino
@@ -15,6 +15,8 @@

 // *********************************************************************
 // Pressure Sensor settings/variables
+float RawTemp, CurrentTemp;
+
 #define BMP085_ADDRESS 0x77  // I2C address of BMP085
 const unsigned char OSS = 0;  // Oversampling Setting

@@ -42,52 +44,91 @@

 // *********************************************************************
-// GPS receiver settings
+// GPS receiver settings/variables
 SoftwareSerial gpsSerial(10, 9); // RX, TX (TX not used)
 const int sentenceSize = 80;
 char sentence[sentenceSize];
+float CurrentLatitude;
+float CurrentLongitude;
+boolean ShouldRecordGPSData;

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

   Wire.begin();
+  RawTemp = -1000.0;
+  CurrentTemp = 0.0;
+
   CalibratePressureSensor();

   DataLogger.begin(9600);
-//  gpsSerial.begin(9600);
+
+  gpsSerial.begin(9600);
+  CurrentLatitude = 0.0;
+  CurrentLongitude = 0.0;
+  ShouldRecordGPSData = false;
 }

 void loop(void) {
-  float CurrentTemp = GetTemp();
-  float CurrentPressure = GetPressure(bmp085ReadUT(), bmp085ReadUP());
-  float CurrentAltitude = CalculateAltitude(CurrentPressure);

   // TODO: Get GPS coordinates
-//  float CurrentLatitude, CurrentLongitude;
-//  char field[20];
-//  GetGPSData();
-//  getField(field, 0);
-//  if(strcmp(field, "$GPRMC") == 0)
-//  {
-//    getField(field, 3);
-//    CurrentLatitude = atof(field);
-//
-//    getField(field, 5);
-//    CurrentLongitude = atof(field);
-//  }
-
-//  PrintToSerialOutput(CurrentTemp, CurrentPressure, CurrentAltitude, CurrentLatitude, CurrentLongitude);
-//  WriteDataToLogger(CurrentTemp, CurrentPressure, CurrentAltitude, CurrentLatitude, CurrentLongitude);
-  PrintToSerialOutput(CurrentTemp, CurrentPressure, CurrentAltitude, 0.0, 0.0);
-  WriteDataToLogger(CurrentTemp, CurrentPressure, CurrentAltitude, 0.0, 0.0);
+  static int i = 0;
+  if(!gpsSerial.isListening()) { gpsSerial.listen(); }
+  if (gpsSerial.available())
+  {
+    char ch = gpsSerial.read();
+
+    if(ch == '$' && !ShouldRecordGPSData)
+    {
+      ShouldRecordGPSData = true;
+      i = 0;
+    }
+
+    if(ShouldRecordGPSData) {
+      if (ch != '\n' && i < sentenceSize)
+      {
+        sentence[i] = ch;
+        i++;
+      }
+      else
+      {
+        sentence[i] = '\0';
+        ShouldRecordGPSData = false;
+        i = 0;
+
+        char field[20];
+        getField(field, 0);
+        if(strcmp(field, "$GPRMC") == 0)
+        {
+          getField(field, 3);
+          CurrentLatitude = atof(field);
+          getField(field, 5);
+          CurrentLongitude = atof(field);
+        }
+
+        // Now that we have a good GPS reading, grab the
+        // rest of the data from the other sensors.
+        RawTemp = GetTemp();
+        if(RawTemp > -1000) { CurrentTemp = RawTemp; }
+        float CurrentPressure = GetPressure(bmp085ReadUT(), bmp085ReadUP());
+        float CurrentAltitude = CalculateAltitude(CurrentPressure);
+
+        PrintToSerialOutput(CurrentTemp, CurrentPressure, CurrentAltitude, CurrentLatitude, CurrentLongitude);
+        WriteDataToLogger(CurrentTemp, CurrentPressure, CurrentAltitude, CurrentLatitude, CurrentLongitude);
+
+      }
+    }
+  }
+
+

   // TODO: What data do we write to the radio?
   // TODO: How frequently should we write data to the radio?
   // TODO: Write data to radio

-  delay(SAMPLING_DELAY);
+//  delay(SAMPLING_DELAY);

 }

@@ -114,7 +155,8 @@

 void WriteDataToLogger(float Temperature, float Pressure, float Altitude, float Latitude, float Longitude) {
-  DataLogger.listen();
+  if(!DataLogger.isListening()) { DataLogger.listen(); }
+
   DataLogger.print(Temperature, 2);
   DataLogger.print(",");
   DataLogger.print(Pressure, 0);
@@ -356,21 +398,6 @@

 // *********************************************************************
 // GPS Receiver subroutines
-void GetGPSData()
-{
-  int i = 0;
-  gpsSerial.listen();
-  char ch = gpsSerial.read();
-  while (ch != '\n' && i < sentenceSize)
-  {
-    sentence[i] = ch;
-    i++;
-  }
-
-  sentence[i] = '\0';
-}
-
-
 void getField(char* buffer, int index)
 {
   int sentencePos = 0;


remove references, there's a README file for that

--- play.ino
+++ play.ino
@@ -2,13 +2,6 @@
  * Play example using Time3 library.
  *
  * The sample must be raw 8bits 8KHz, please read README.md.
- *
- * References:
- *
- *  - http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM
- *  - http://www.arduino.cc/playground/Main/TimerPWMCheatsheet
- *  - http://arduino.cc/playground/Code/Timer1
- *  - http://www.pjrc.com/teensy/td_libs_TimerOne.html
  *
  *  Juan J. Martinez <jjm@usebox.net>
  *  https://github.com/reidrac/play-pcm-example


Commented unnecessary serial prints made for debugging

--- ZUArm.ino
+++ ZUArm.ino
@@ -1,13 +1,6 @@
 //Servo.h is the library required to directly deal with servo motors
 #include <Servo.h>

-/* Pinout is as follows, Arm from base to tool-tip
-theta0 => 9
-theta2 => 11
-theta2 Second Motor is connected to same pin => 11
-theta3 => 3
-theta4 => 5
-*/
 int thetaPin[] = {3,5,6,9,10,11};
 const int numberOfMotors = 6;
 //We define a servo instance for each motor
@@ -34,12 +27,12 @@
    if (servoNo < numberOfMotors) {
      Angle = Serial.readStringUntil(':').toInt();
      thetaServo[servoNo].write(Angle);
-     Serial.print("Theta ");
-   Serial.print(servoNo);
-   Serial.print(" Was sent an angle of ");
-   Serial.println(Angle);
+//     Serial.print("Theta ");
+//   Serial.print(servoNo);
+//   Serial.print(" Was sent an angle of ");
+//   Serial.println(Angle);
    } else {
-    Serial.println("HERE");
+//    Serial.println("HERE");
     for (int i = 0; i < numberOfMotors; i++) {
       int val = thetaServo[i].read();
       Serial.println(val);


use software filtering of RSSI by default

--- Arduino/chorus_rf_laptimer/chorus_rf_laptimer.ino
+++ Arduino/chorus_rf_laptimer/chorus_rf_laptimer.ino
@@ -157,7 +157,7 @@
 #define SEND_ALL_DEVICE_STATE       255

 //----- RSSI --------------------------------------
-#define FILTER_ITERATIONS 0 // software filtering iterations; set 0 - if filtered in hardware; set 5 - if not
+#define FILTER_ITERATIONS 5 // software filtering iterations; set 0 - if filtered in hardware; set 5 - if not
 uint16_t rssiArr[FILTER_ITERATIONS + 1];
 uint16_t rssiThreshold = 190;
 uint16_t rssi;


Update MDriver_with_PWM.ino

Update MDriver_with_PWM.ino

--- examples/MDriver_with_PWM/MDriver_with_PWM.ino
+++ examples/MDriver_with_PWM/MDriver_with_PWM.ino
@@ -1,6 +1,9 @@
 #include "MDriver.h"

-/*
+/*
+ * Этот пример управляет двигателями с использованием ШИМ(PWM) сигнала, при этом на пины
+ * ENA и ENB на плате драйвера подключены к цифровым пинам Arduino.
+ *
  * Библиотека MDrive предназначена для управление коллекторными двигателями
  * посредством драйвера двигателе на микросхеме L293 или L298.
  *


Preparations for 16x32 support

Preparations for 16x32 support

--- examples/SpectrumAnalyzer/SpectrumAnalyzer.ino
+++ examples/SpectrumAnalyzer/SpectrumAnalyzer.ino
@@ -14,7 +14,7 @@
 #include <SPI.h>
 #include <SD.h>

-#include <SmartMatrix.h>
+#include <SmartMatrix_32x32.h>
 #include <FastLED.h>

 SmartMatrix matrix;


Update UbidotsSaveValue.ino

Update UbidotsSaveValue.ino

--- examples/UbidotsSaveValue/UbidotsSaveValue.ino
+++ examples/UbidotsSaveValue/UbidotsSaveValue.ino
@@ -7,10 +7,10 @@
 //GPRS Shield is connected to the Software UART

 #define APN "Your_apn_of_your_SIM_here"
-#define USER "Your_username_here"  // if your apn doesnt have username just put ""
-#define PASS "Your_password_here"  // if your apn doesnt have password just put ""
-#define TOKEN "Your_token_here"  // Remplace it with your token
-#define ID "Your_id_here" // Remplace it with your variable ID
+#define USER "Your_username_here"  // If your apn doesnt have username just put ""
+#define PASS "Your_password_here"  // If your apn doesnt have password just put ""
+#define TOKEN "Your_token_here"  // Replace it with your Ubidots token
+#define ID "Your_id_here" // Replace it with your Ubidots' variable ID
 Ubidots client(TOKEN);

 void setup() {
@@ -22,5 +22,5 @@
 void loop() {
   float value = analogRead(A0);  // Reading analog pin A0
   client.saveValue(value,ID);
-  delay(600);  // 600 milliseconds
+  delay(1000);
 }


Added Mecanum Motor Control

Added Mecanum Motor Control


Fix a typo

Fix a typo

--- Accessory_Controller/Accessory_Controller.ino
+++ Accessory_Controller/Accessory_Controller.ino
@@ -83,7 +83,7 @@
   CAN.init_Mask(1, 0, 0xfff);

   // Set filters
-  CAN.init_Filt(0, 0, MSD_ID_BMSK_Control_Module);
+  CAN.init_Filt(0, 0, MSG_ID_BMSK_Control_Module);
   CAN.init_Filt(1, 0, MSG_ID_ZFE_Control_Module);
   CAN.init_Filt(2, 0, MSG_ID_ZFE_Control_Module_2);
   CAN.init_Filt(3, 0, MSG_ID_Instrument_Cluster_2);
@@ -115,7 +115,7 @@
         CAN.readMsgBuf(&length, data);
         switch( CAN.getCanId() )
         {
-          case MSD_ID_BMSK_Control_Module:
+          case MSG_ID_BMSK_Control_Module:
           {
               new_value = LO_NIBBLE(data[5]);
               if ( new_value != motorcycle_state.abs_button )


Complete rewrite of leds.ino

Complete rewrite of leds.ino

-- Animation
-- EEProm
-- HSV Control
-- Serial communication rewrite.

--- leds/leds.ino
+++ leds/leds.ino
@@ -1,144 +1,73 @@
+// LibreLeds
+
 #include <FastLED.h>
+#include <EEPROM.h>
+
 /*
-  Universal USB LED
-  https://github.com/madnerdorg/leds
-  -----------------
-  Components:
-  WS2812b led (NEOPIXEL clone)
-  Arduino Nano (clone)
-
-  Wiring
-  D6 (480Ohm resistor) ---> DI
-
-   Color Table
-   0 Off
-   1 White
-   2 Red
-   3 Green
-   4 Blue
-   5 Yellow
-   6 Orange
-   7 Purple
+  Animation
+  0: No animation
+  1: Blinking (param1:speed in ms)
+  2: Pulsing
+  3: Rainbow mode
+  4: Alternative Blink (param1:master/slave, param2:led/speed in ms)
 */

-//USB Device Type
+// Settings
 const String usb_name = "leds:42001";
+const int NUM_LEDS = 2;

 //Leds Setup
 const int DATA_PIN = 6; //WS2812b led
-const int NUM_LEDS = 5;
-
+
+//Constants animation
+const int STOP = 0;
+const int BLINK = 1;
+const int PULSE = 2;
+const int RAINBOW = 3;
+const int ALTERNATE_BLINK = 4;
+
+const int MASTER = 0;
+const int SLAVE = 1;
+
+//Leds objects
 CRGB leds[NUM_LEDS];

-int leds_state[NUM_LEDS] = {0, 0, 0, 0, 0};
-
-//Serial string buffer
-String readString;
-
-// Serial
-
-//When application asked if this is the correct arduino
-void serialCheck() {
-  if (readString == "/info") {
-    Serial.println(usb_name);
-  } else {
-  for (int i = 0; i < NUM_LEDS; i++) {
-      leds_state[i] = splitString(readString, ';', i).toInt();
-      changeLed(i, leds_state[i]);
-      Serial.print(leds_state[i]);
-      if (i != (NUM_LEDS - 1)) {
-        Serial.print(";");
-      }
-
-    }
-    Serial.println();
-  }
-}
-
-//Convert characters sent by serial to string
-void serialManager() {
-  //Get Serial as a string
-  while (Serial.available()) {
-    delay(3); // Wait for data
-
-    //Convert to String
-    if (Serial.available() > 0) {
-      char c = Serial.read();
-      readString += c;
-    }
-  }
-}
-
-// Leds
-
-//You can change/add color here
-void changeLed(int pos, int color) {
-  switch (color) {
-    case 0:
-      leds[pos] = CRGB::Black;
-      break;
-    case 1:
-      leds[pos] = CRGB::White;
-      break;
-    case 2:
-      leds[pos] = CRGB::Red;
-      break;
-    case 3:
-      leds[pos] = CRGB::Green;
-      break;
-    case 4:
-      leds[pos] = CRGB::Blue;
-      break;
-    case 5:
-      leds[pos] = CRGB::Yellow;
-      break;
-    case 6:
-      leds[pos] = CRGB::Orange;
-      break;
-    case 7:
-      leds[pos] = CRGB::Purple;
-      break;
-  }
-  leds_state[pos] = color;
+//Leds Settings
+int hue[NUM_LEDS];
+int sat[NUM_LEDS];
+int val[NUM_LEDS];
+int brightness;
+
+// Animation Settings
+int anim[NUM_LEDS];
+int params1[NUM_LEDS];
+int params2[NUM_LEDS];
+
+// Leds Status
+int status[NUM_LEDS];
+long timing[NUM_LEDS];
+
+// Serial Settings
+String command;
+String readString; //String Buffer
+
+//Timing
+unsigned long currentTime = 0;
+unsigned long previousTime = 0;
+
+void setup() {
+  // put your setup code here, to run once:
+  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
+  Serial.begin(115200);
+  init_leds();
+}
+
+void loop() {
+  animation_loop();
   FastLED.show();
-}
-
-//Blinks leds
-void BlinkLeds(int color) {
-  for (int i = 0; i < NUM_LEDS; i++) {
-    changeLed(i, color);
-  }
-
-  delay(100);
-  for (int i = 0; i < NUM_LEDS; i++) {
-    changeLed(i, 0);
-  }
-}
-
-void setup() {
-  // Setup Led
-  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
-  // Test Led (All White)
-  for (int i = 0; i < NUM_LEDS; i++) {
-    changeLed(i, 1);
-  }
-
-  //Setup Serial
-  Serial.begin(115200);
-}
-
-void loop() {
   serialManager();
-  //Serial.println(readString); //Show order sent
-
-  //If string received
-  if (readString.length() > 0) {
-    serialCheck();
-
-    //We clean the serial buffer
-    readString = "";
-  }
-}
+}
+

 //Equivalent of explode in PHP (use for serial commands parsing)
 String splitString(String data, char separator, int index) {
@@ -153,11 +82,255 @@
       strIndex[1] = (i == maxIndex) ? i + 1 : i;
     }
   }
-
   return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
 }

-
-
-
-
+void change_color_all(int h, int s, int v) {
+  for (int i = 0; i < NUM_LEDS; i++) {change_color(i, h, s, v);}
+}
+
+void change_color(int led, int h, int s, int v) {
+  leds[led] = CHSV(h, s, v);
+  hue[led] = h;
+  sat[led] = s;
+  val[led] = v;
+}
+
+void change_anim_all(int animation, int parameter1, int parameter2) {
+  for (int led = 0; led < NUM_LEDS; led++) {change_anim(led, animation, parameter1 , parameter2);}
+}
+
+void change_anim(int led, int animation, int parameter1, int parameter2) {
+  anim[led] = animation;
+  params1[led] = parameter1;
+  params2[led] = parameter2;
+  status[led] = 0;
+  timing[led] = 0;
+}
+
+
+void animation_loop() {
+  currentTime = millis();
+  for (int led = 0; led < NUM_LEDS; led++) {
+
+    // Pulse animation
+    if (anim[led] == PULSE) {
+      //Orientation (fading in/fading out)
+      if (val[led] <= 0) {status[led] = 1;}
+      if (val[led] >= 255) {status[led] = 0;}
+      if (status[led] == 0) {val[led]--;} else {val[led]++;}
+      change_color(led, hue[led], sat[led], val[led]);
+      //Serial.println(val[led]);
+    }
+
+    //Blink animation
+    if (anim[led] == BLINK) {
+      //If interval is finish change state
+      if (currentTime - timing[led] > params1[led]) {
+        timing[led] = currentTime;
+        if (val[led] == 255) {val[led] = 0;} else {val[led] = 255;}
+        change_color(led, hue[led], sat[led], val[led]);
+      }
+    }
+
+    if (anim[led] == RAINBOW) {
+      if (hue[led] <= 0) {status[led] = 1;}
+      if (hue[led] >= 255) {status[led] = 0;}
+      if (status[led] == 0) {hue[led]--;} else {hue[led]++;}
+      change_color(led, hue[led], sat[led], val[led]);
+    }
+
+    if (anim[led] == ALTERNATE_BLINK) {
+      //If led is master (ignore if slave)
+      if (params1[led] == 0) {
+        int led2 = params2[led];
+        int interval = params2[led2];
+        if (currentTime - timing[led] > interval) {
+          timing[led] = currentTime;
+          if (val[led] == 255) {
+            val[led] = 0;
+            val[led2] = 255;
+          } else {
+            val[led] = 255;
+            val[led2] = 0;
+          }
+        }
+        change_color(led, hue[led], sat[led], val[led]);
+        change_color(led2, hue[led2], sat[led2], val[led2]);
+      }
+    }
+  }
+}
+
+void init_leds() {
+  int status_eeprom;
+  EEPROM.get(0,status_eeprom);
+  if(status_eeprom != -1){
+    read_eeprom();
+  } else {
+    change_color_all(0, 0, 0);
+    change_anim_all(0, 0, 0);
+    brightness = 255;
+    LEDS.setBrightness(255);
+  }
+}
+
+void read_eeprom(){
+  int address = 0;
+  EEPROM.get(0,brightness);
+  LEDS.setBrightness(brightness);
+  address = 2;
+  for (int led = 0; led < NUM_LEDS; led++) {
+    EEPROM.get(address,hue[led]);
+    address = address + 2;
+    EEPROM.get(address,sat[led]);
+    address = address + 2;
+    EEPROM.get(address,val[led]);
+    address = address + 2;
+    EEPROM.get(address,anim[led]);
+    address = address + 2;
+    EEPROM.get(address,params1[led]);
+    address = address + 2;
+    EEPROM.get(address,params2[led]);
+    address = address + 2;
+    change_color(led, hue[led], sat[led], val[led]);
+    change_anim(led, anim[led], params1[led], params2[led]);
+  }
+}
+
+void save_eeprom(){
+  int address = 0;
+  EEPROM.put(0,brightness);
+  address = 2;
+  for (int led = 0; led < NUM_LEDS; led++) {
+    EEPROM.put(address,hue[led]);
+    address = address + 2;
+    EEPROM.put(address,sat[led]);
+    address = address + 2;
+    EEPROM.put(address,val[led]);
+    address = address + 2;
+    EEPROM.put(address,anim[led]);
+    address = address + 2;
+    EEPROM.put(address,params1[led]);
+    address = address + 2;
+    EEPROM.put(address,params2[led]);
+    address = address + 2;
+  }
+  //Serial.println("Saved eeprom");
+}
+
+void serialManager() {
+  while (Serial.available()) {delay(5);if (Serial.available() > 0) {char c = Serial.read();readString += c;}}
+
+  if (readString.length() > 0) {
+    if (readString[0] == '/'){
+        if (readString == "/info") {
+          Serial.println(usb_name);
+        }
+      //Get status
+        if (readString == "/status") {
+          Serial.print(brightness);
+          Serial.print(";");
+          for (int led = 0; led < NUM_LEDS; led++) {
+           Serial.print(hue[led]);
+           Serial.print(";");
+           Serial.print(sat[led]);
+           Serial.print(";");
+           Serial.print(val[led]);
+           Serial.print(";");
+           Serial.print(anim[led]);
+           Serial.print(";");
+           Serial.print(params1[led]);
+           Serial.print(";");
+           Serial.print(params2[led]);
+           Serial.print(";");
+          }
+          Serial.println();
+        }
+
+
+        if (readString == "/save") {
+          save_eeprom();
+          Serial.println(readString);
+        }
+
+        //Turn off all leds
+        if (readString == "/off") {
+          change_color_all(0, 0, 0);
+          change_anim_all(0, 0, 0);
+          Serial.println(readString);
+        }
+
+        if (readString == "/reset"){
+          read_eeprom();
+        }
+
+        if (readString == "/clear"){
+          change_color_all(0, 0, 0);
+          change_anim_all(0, 0, 0);
+          LEDS.setBrightness(255);
+          save_eeprom();
+          Serial.println(readString);
+        }
+    } else {
+          String command = splitString(readString, ';', 0);
+
+          //Change brightness
+          if (command == "brightness") {
+            brightness = splitString(readString, ';', 1).toInt();
+            LEDS.setBrightness(brightness);
+            Serial.println(readString);
+          }
+
+          //Change color
+          if (command == "color") {
+            int led = splitString(readString, ';', 1).toInt();
+            int h = splitString(readString, ';', 2).toInt();
+            int s = splitString(readString, ';', 3).toInt();
+            int v = splitString(readString, ';', 4).toInt();
+            change_color(led, h, s, v);
+            Serial.println(readString);
+          }
+
+          //Change animation
+          if (command == "animation") {
+            int led = splitString(readString, ';', 1).toInt();
+            int animation = splitString(readString, ';', 2).toInt();
+            int parameter1 = splitString(readString, ';', 3).toInt();
+            int parameter2 = splitString(readString, ';', 4).toInt();
+            change_anim(led, animation, parameter1, parameter2);
+            Serial.println(readString);
+          }
+
+          //Load previous state
+          if (command == "load"){
+             int cursor = 1;
+             brightness = splitString(readString, ';', cursor++).toInt();
+
+             for (int led = 0; led < NUM_LEDS; led++) {
+                  int h = splitString(readString, ';', cursor).toInt();
+                  cursor++;
+                  int s = splitString(readString, ';', cursor).toInt();
+                  cursor++;
+                  int v = splitString(readString, ';', cursor).toInt();
+                  cursor++;
+                  int animation = splitString(readString, ';', cursor).toInt();
+                  cursor++;
+                  int parameter1 = splitString(readString, ';', cursor).toInt();
+                  cursor++;
+                  int parameter2 = splitString(readString, ';', cursor).toInt();
+                  cursor++;
+                  change_color(led,h,s,v);
+                  change_anim(led, animation, parameter1, parameter2);
+             }
+             Serial.println(readString);
+          }
+
+        }
+    readString = "";
+  }
+}
+
+
+
+


Updated the default refresh rate to 10 Hz to cope with default frequenies of sensor update requests and command inputs.

--- ROVMain/ROVMain.ino
+++ ROVMain/ROVMain.ino
@@ -20,7 +20,7 @@
  * 26 Sep 2015 - 2.1.2 - Alek Lidtke - put arming modules into a dedicated function to not freeze the GUI when doing so.
  */

-#define DEBUG_PRINTOUT
+//#define DEBUG_PRINTOUT

 // Custom includes.
 #include "Module.h"
@@ -112,7 +112,7 @@
 /* Prepare to listen to commands over serial and start everything up. */
 {
 	armModulesModule.setValue(0); // Don't arm the modules by default, wait for a command.
-	refreshRate.setValue(100); // Set default delay in milliseconds in the main loop/
+	refreshRate.setValue(10); // Set default delay in milliseconds in the main loop/

 	//TODO: do some system checks, like battery level, connections etc.


reduce code size

reduce code size

--- m190/m190.ino
+++ m190/m190.ino
@@ -28,13 +28,8 @@

 void PROGRESS(float progress){
   static byte flipflop=0;
-  if(flipflop==0){
-    digitalWrite(LEDPIN,HIGH);
-    flipflop=1;
-  }else {
-    digitalWrite(LEDPIN,LOW);
-    flipflop=0;
-  }
+  flipflop++;
+  digitalWrite(LEDPIN,flipflop%2);
 }

 uint8_t PRIVATE[32];
@@ -42,36 +37,6 @@
 WORD ybuf[32];
 struct bigint pubx(xbuf,sizeof(xbuf));
 struct bigint puby(ybuf,sizeof(ybuf));
-
-/*
-const int ringsize=128;
-int ring[ringsize];
-int ringpos=0;
-void recordTick(int val,unsigned long micros){
-  ring[ringpos]=val;
-  ringpos++;
-  ringpos%=ringsize;
-}
-*/
-
-void dumpStats(){
-/*
-  Serial.println("Ring Buf");
-  int last=0;
-  for(int i=0;i<ringsize;i++){
-    int p=i+ringpos;
-    p%=ringsize;
-    int val = ring[p];
-    Serial.print(val);
-    if( val >= last ){
-      Serial.println(" >");
-    } else {
-      Serial.println(" <");
-    }
-    last=val;
-  }
-  */
-}

 const float qrxscale=2.25;
 const int qryscale=2;
@@ -83,7 +48,6 @@
 //const float qrxscale=3.375;

 boolean qrcodesource(void *ctx,int x,int y){
-//  return( x==10 || y==10);
   qrcontext *qr=(qrcontext *)ctx;

   float fx = (float)x/qrxscale;


Send status blocking

Send status blocking

--- mech/mech.ino
+++ mech/mech.ino
@@ -145,7 +145,7 @@
 		{
 			lastRefreshTime = millis();
 			updateStatus();
-			bus.send(ID_HAL100, (char *)&status, sizeof(status));
+			bus.send_packet_blocking(ID_HAL100, (char *)&status, sizeof(status));
 		}
 }


WebHook, overhauled Blynk.syncVirtual

WebHook, overhauled Blynk.syncVirtual

Now it actually works! :) Also moved some other things around. Removed Node01's manual vPin update mode in terminal.

--- hvacMonitor.ino
+++ hvacMonitor.ino
@@ -8,11 +8,10 @@
 #include <BlynkSimpleEsp8266.h> // 6/22/16 Rev: Includes edit of this file to expand virtual pins
 #include <TimeLib.h>            // Used by WidgetRTC.h
 #include <WidgetRTC.h>          // Blynk's RTC
-#include <EEPROM.h>             // EEPROM library - keep HVAC total runtime values to survive restarts

 #include <OneWire.h>            // Temperature sensor library
 #include <DallasTemperature.h>  // Temperature sensor library
-#define ONE_WIRE_BUS 13          // WeMos pin D7
+#define ONE_WIRE_BUS 12         // WeMos pin D6
 OneWire oneWire(ONE_WIRE_BUS);
 DallasTemperature sensors(&oneWire);

@@ -25,9 +24,10 @@

 char myEmail[] = "email";

-char* host = "data.sparkfun.com";
-char* streamId   = "publicKey";
-char* privateKey = "privateKey";
+// All sparkfun updates now handled by Blynk's WebHook widget
+//char* host = "data.sparkfun.com";
+//char* streamId   = "publicKey";
+//char* privateKey = "privateKey";

 SimpleTimer timer;

@@ -35,9 +35,10 @@
 BLYNK_ATTACH_WIDGET(rtc, V8);
 WidgetTerminal terminal(V26);

-const int blowerPin = 12;  // WeMos pin D6. Todo: Change blowerPin to coolingPin (also, fanOnlyPin and heatingPin for future).
+const int blowerPin = 13;  // WeMos pin D7.
 bool daySet = FALSE;       // Sets the day once after reset and RTC is set correctly.

+bool runOnce = TRUE;
 bool resetFlag = TRUE;        // TRUE when the hardware has been reset.
 bool startFlag = FALSE;       // TRUE when the A/C has started.
 bool stopFlag = FALSE;        // TRUE when the A/C has stopped.
@@ -52,13 +53,14 @@
 const int splitAlarmTime = 180;   // If a high split persists for this duration (in seconds), notification is sent.
 int alarmTime;                    // Seconds that high split alarm has been active.

-int todaysAccumRuntimeSec;            // Today's accumulated runtime in seconds - displays in app.
-int todaysAccumRuntimeMin;            // Today's accumulated runtime in minutes - displays in app.
+long todaysAccumRuntimeSec;           // Today's accumulated runtime in seconds - displayed in app as minutes.
 int currentCycleSec, currentCycleMin; // If HVAC is running, the duration of the current cycle (non-accumulating).
 int yesterdayRuntime;                 // Sum of yesterday's runtime in minutes - displays in app.
+int hvacTodaysStartCount;             // Records how many times the unit has started today.
 int todaysDate;                       // Sets today's date related to things that reset at EOD.
 String currentTimeDate;               // Time formatted as "0:00AM on 0/0"
 String startTimeDate, stopTimeDate, resetTimeDate;
+int runStatus;                        // Used for graphing. 40 == running. NULL == off.

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

-double tempRA, tempSA;    // Return and supply air temperatures
-
-const int eeIndex = 0;          // This is the EEPROM address location that keeps track of next EEPROM address available for storing a single blower cycle runtime.
-int eeCurrent = 1;              // This is the next EEPROM address location that cycle runtime will be stored to.
-int eeWBsum;                    // This is the sum of all EEPROM addresses (total runtime stored).
-int eeTodaysStartsCount;        // Records how many times the unit has started today.
+double tempRA, tempSA;                // Return and supply air temperatures

 void setup()
 {
@@ -119,147 +116,83 @@
   // END OTA ROUTINE

   rtc.begin();
-  setSyncInterval(300);
-
-  EEPROM.begin(512); // EEPROM is zero-indexed: means addresses 0 to 200 are available (not 1 to 201 or 0 to 201).
-
-  // 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 to be written back.
-  {
-    for (int i = 1 ; i < 199 ; i++) {
-      eeWBsum += EEPROM.read(i);             // Add up values in addresses 1 through 198 and stick into eeWBsum.
-
-    }
-    eeTodaysStartsCount = EEPROM.read(199);    // Reads how many times the unit has started today (if any runs have been recorded).
-  }
-
-  todaysAccumRuntimeSec = (eeWBsum * 60);         // Writes seconds of today's accumulated runtime back to variable.
-  todaysAccumRuntimeMin = eeWBsum;                // Writes minutes of today's accumulated runtime back to variable (used for app runtime display only).
-  yesterdayRuntime = (EEPROM.read(200) * 4);      // Writes minutes of yesterday's accumulated runtime back to variable (use for app runtime display only).
-  // END EEPROM WRITEBACK ROUTINE
+  //setSyncInterval(120);

   timer.setInterval(2500L, sendTemps);        // Temperature sensor polling and app display refresh interval.
   timer.setInterval(1234L, sendStatus);       // Unit run status polling interval (for app Current Status display only).
   timer.setInterval(1000L, countRuntime);     // Counts blower runtime for daily accumulation displays.
-  timer.setInterval(1000L, totalRuntime);     // Counts blower runtime for daily EEPROM storage.
+  timer.setInterval(1000L, totalRuntime);     // Counts blower runtime.
+  timer.setInterval(1000L, setClockTime);     // Creates a current time with leading zeros.
   timer.setInterval(500L, alarmTimer);        // Track a cycle start/end time for app display.
-  timer.setInterval(15432L, sfUpdate);        // ~15 sec run status updates to data.sparkfun.com
-  timer.setInterval(30000L, halfMinTasks);    // Things here happen once every 30 seconds.
-
-  Blynk.syncVirtual(V11);                     // "Syncs back" pin data holding seconds that filter has been used.
-  Blynk.syncVirtual(V17);                     // "Syncs back" pin data holding Unix time that filter was changed.
-}
-
-void loop()  // To keep Blynk happy, keep Blynk tasks out of the loop.
+  timer.setInterval(15432L, sfWebhook);       // ~15 sec run status updates to data.sparkfun.com.
+  //timer.setInterval(30000L, debugVpins);
+  timer.setTimeout(100, vsync1);              // Syncs back vPins to survive hardware reset.
+  timer.setTimeout(5000, vsync2);             // Syncs back vPins to survive hardware reset.
+}
+
+void debugVpins()
+{
+  Serial.println(String("V110 local variable (hvacTodaysStartCount) is: ") + hvacTodaysStartCount);
+  Serial.println(String("V111 local variable (todaysAccumRuntimeSec) is: ") + todaysAccumRuntimeSec);
+  Serial.println(String("V112 local variable (yesterdayRuntime) is: ") + yesterdayRuntime);
+  Serial.println(String("V11 local variable (currentFilterSec) is: ") + currentFilterSec);
+}
+
+void loop()  // To keep Blynk happy, keep most tasks out of the loop.
 {
   Blynk.run();
   timer.run();
   ArduinoOTA.handle();
 }

-void halfMinTasks() {
-  if (digitalRead(blowerPin) == LOW)
-  {
-    Blynk.virtualWrite(11, currentFilterSec);   // Records how many seconds air has moved through the filter. Used to tecord "milage" in lieu of only time.
-  }
+void vsync1()
+{
+  Blynk.syncVirtual(V110);    // hvacTodaysStartCount
+  Blynk.syncVirtual(V111);    // todaysAccumRuntimeSec
+}
+
+void vsync2()
+{
+  Blynk.syncVirtual(V112);    // yesterdayRuntime
+  Blynk.syncVirtual(V11);     // currentFilterSec
+}
+
+BLYNK_WRITE(V110)
+{
+  hvacTodaysStartCount = param.asInt();
+}
+
+BLYNK_WRITE(V111)
+{
+  todaysAccumRuntimeSec = param.asLong();
+}
+
+BLYNK_WRITE(V112)
+{
+  yesterdayRuntime = param.asInt();
 }

 BLYNK_WRITE(V11)
 {
-  currentFilterSec = param.asLong();       // "Writes back" pin data holding seconds that filter has been used.
-}
-
-BLYNK_WRITE(V17)
-{
-  timeFilterChanged = param.asLong();      // "Writes back" pin data holding Unix time that filter was changed.
-}
-
-void sfUpdate()                           // Send updates to data.sparkfun.com for graphing in analog.io
-{
-  if (digitalRead(blowerPin) == LOW)
-  {
-    int runStatus = 40;
-
-    Serial.print("connecting to ");
-    Serial.println(host);
-
-    // Use WiFiClient class to create TCP connections
-    WiFiClient client;
-    const int httpPort = 80;
-    if (!client.connect(host, httpPort)) {
-      Serial.println("connection failed");
-      return;
-    }
-
-    Serial.print("Requesting...");
-
-    // This will send the request to the server
-    client.print(String("GET ") + "/input/" + streamId + "?private_key=" + privateKey + "&returntemp=" + tempRA + "&runstatus=" + runStatus + "&supplytemp=" + tempSA + " HTTP/1.1\r\n" +
-                 "Host: " + host + "\r\n" +
-                 "Connection: close\r\n\r\n");
-    unsigned long timeout = millis();
-    while (client.available() == 0) {
-      if (millis() - timeout > 10000) {
-        Serial.println(">>> Client Timeout !");
-        client.stop();
-        return;
-      }
-    }
-
-    // Read all the lines of the reply from server and print them to Serial
-    while (client.available()) {
-      String line = client.readStringUntil('\r');
-      Serial.print(line);
-    }
-
-    Serial.println();
-    Serial.println("closing connection");
-  }
-
-  else if (digitalRead(blowerPin) == HIGH)
-  {
-    int runStatus = NULL;
-
-    Serial.print("connecting to ");
-    Serial.println(host);
-
-    // Use WiFiClient class to create TCP connections
-    WiFiClient client;
-    const int httpPort = 80;
-    if (!client.connect(host, httpPort)) {
-      Serial.println("connection failed");
-      return;
-    }
-
-    Serial.print("Requesting...");
-
-    // This will send the request to the server
-    client.print(String("GET ") + "/input/" + streamId + "?private_key=" + privateKey + "&returntemp=" + tempRA + "&runstatus=" + runStatus + "&supplytemp=" + tempSA + " HTTP/1.1\r\n" +
-                 "Host: " + host + "\r\n" +
-                 "Connection: close\r\n\r\n");
-    unsigned long timeout = millis();
-    while (client.available() == 0) {
-      if (millis() - timeout > 5000) {
-        Serial.println(">>> Client Timeout !");
-        client.stop();
-        return;
-      }
-    }
-
-    // Read all the lines of the reply from server and print them to Serial
-    while (client.available()) {
-      String line = client.readStringUntil('\r');
-      Serial.print(line);
-    }
-
-    Serial.println();
-    Serial.println("closing connection");
-  }
+  currentFilterSec = param.asLong();
+}
+
+void sfWebhook() {
+  if (digitalRead(blowerPin) == LOW)        // If HVAC blower motor is running...
+  {
+    runStatus = 40;
+  }
+  else if (digitalRead(blowerPin) == HIGH)  // If HVAC blower motor if off...
+  {
+    runStatus = NULL;
+  }
+
+  Blynk.virtualWrite(67, String("returntemp=") + tempRA + "&runstatus=" + runStatus + "&supplytemp=" + tempSA);
 }

 BLYNK_WRITE(V18)              // App button to display all terminal commands available
 {
-    int pinData = param.asInt();
+  int pinData = param.asInt();

   if (pinData == 0) // Triggers when button is released only
   {
@@ -269,7 +202,6 @@
     terminal.println(" ");
     terminal.println(" filter : HVAC filter menu");
     terminal.println(" WU : Change WU API station");
-    terminal.println(" manual : Manually update V22/V23/V24");
     terminal.println(" ");
     terminal.flush();
   }
@@ -351,27 +283,6 @@
   terminal.flush();
 }

-BLYNK_WRITE(V19) // App button to reset EEPROM 0-200
-{
-  int pinData = param.asInt();
-
-  if (pinData == 0)
-  {
-    Serial.println("EEPROM RESET");
-    for (int i = 0 ; i < 201 ; i++) {
-      EEPROM.write(i, 0);
-    }
-    EEPROM.write(eeIndex, 1); // Define address 1 as the starting location.
-    EEPROM.commit();
-
-    todaysAccumRuntimeSec = 0;  // Also zeros out variables so display is correct.
-    todaysAccumRuntimeMin = 0;
-    yesterdayRuntime = 0;
-    eeTodaysStartsCount = 0;
-    eeWBsum = 0;
-  }
-}
-
 BLYNK_WRITE(V20) // App button to reset hardware
 {
   int pinData = param.asInt();
@@ -393,6 +304,7 @@
   if (tempRA >= 0 && tempRA <= 120 && digitalRead(blowerPin) == LOW)        // If temp 0-120F and blower running...
   {
     Blynk.virtualWrite(0, tempRA);                                          // ...display the temp...
+
   }
   else if (tempRA >= 0 && tempRA <= 120 && digitalRead(blowerPin) == HIGH)  // ...unless it's not running, then...
   {
@@ -423,6 +335,7 @@
   if (resetFlag == TRUE && year() != 1970) {                       // Runs once following Arduino reset/start.
     resetTimeDate = currentTimeDate;
     Blynk.virtualWrite(16, String("SYSTEM RESET at ") + resetTimeDate);
+    Blynk.setProperty(V16, "color", "#D3435C");
   }

   // Purpose: To keep the display showing a system reset state until the HVAC has turned on or off.
@@ -439,6 +352,9 @@
   if (digitalRead(blowerPin) == HIGH && startFlag == TRUE) {          // OFF, but was running
     stopTimeDate = currentTimeDate;                                   // Set off time.
     Blynk.virtualWrite(16, String("HVAC OFF since ") + stopTimeDate); // Write to app.
+    Blynk.setProperty(V0, "color", "#808080");
+    Blynk.setProperty(V1, "color", "#808080");
+    Blynk.setProperty(V16, "color", "#808080");

     if ( (filterChangeHours - currentFilterHours ) <= 0 && changeFilterAlarm == FALSE) {
       Blynk.email(myEmail, "CHANGE A/C FILTER", "Change the A/C filter (20x25x1 1085 microparticle/MERV 11) and reset the timer.");
@@ -451,6 +367,10 @@
   else if (digitalRead(blowerPin) == LOW && stopFlag == TRUE) {    // RUNNING, but was off
     startTimeDate = currentTimeDate;
     Blynk.virtualWrite(16, String("HVAC ON since ") + startTimeDate);
+    Blynk.setProperty(V0, "color", "#D3435C");  // return air text turns red, and...
+    Blynk.setProperty(V1, "color", "#5F7CD8");
+    Blynk.setProperty(V16, "color", "#23C48E");
+
     startFlag = TRUE;
     stopFlag = FALSE;
   }
@@ -460,18 +380,14 @@
 {
   if (digitalRead(blowerPin) == LOW) // If fan is running...
   {
-    ++currentCycleSec;                          // accumulate the running time, however...
+    ++currentCycleSec;               // accumulate the running time, however...
     currentCycleMin = (currentCycleSec / 60);
   }
   else if (digitalRead(blowerPin) == HIGH && currentCycleSec > 0) // if fan is off but recorded some runtime...
   {
-    EEPROM.write(199, ++eeTodaysStartsCount);   // Stores how many times the unit has started today... adds one start.
-    eeCurrent = EEPROM.read(eeIndex);           // Set eeCurrent as the value of the next available register. (Also, allows display of number of runs to survive reset.)
-    EEPROM.write(eeCurrent, currentCycleMin);   // Write runtime to EEPROM
-    EEPROM.write(eeIndex, ++eeCurrent);         // Advance to next EEPROM register (for next run) and write that next register to EEPROM
-    EEPROM.commit();                            // Make it so
-
-    currentCycleSec = 0;                        // Reset the current cycle clock
+    Blynk.virtualWrite(110, ++hvacTodaysStartCount);              // Stores how many times the unit has started today... adds one start.
+
+    currentCycleSec = 0;                                          // Reset the current cycle clock
     currentCycleMin = 0;
   }
 }
@@ -514,7 +430,7 @@
   }
 }

-void countRuntime()
+void setClockTime()
 {
   if (year() != 1970) // Doesn't start until RTC is set correctly.
   {
@@ -532,6 +448,13 @@
     else if (minute() < 10 && hour() < 12) {
       currentTimeDate = String(hourFormat12()) + ":0" + minute() + "AM on " + month() + "/" + day();
     }
+  }
+}
+
+void countRuntime()
+{
+  if (year() != 1970) // Doesn't start until RTC is set correctly.
+  {

     if (daySet == FALSE) {              // Sets the date (once per hardware restart) now that RTC is correct.
       todaysDate = day();
@@ -540,29 +463,21 @@

     if (digitalRead(blowerPin) == LOW && todaysDate == day()) // Accumulates seconds unit is running today.
     {
-      ++todaysAccumRuntimeSec;                                // Counts today's AC runtime in seconds.
-      todaysAccumRuntimeMin = (todaysAccumRuntimeSec / 60);   // Converts those seconds to minutes for display.
-
+      ++todaysAccumRuntimeSec;                          // Counts today's AC runtime in seconds.
+      Blynk.virtualWrite(111, todaysAccumRuntimeSec);
       ++currentFilterSec;                               // Counts how many seconds filter is used based on AC runtime.
+      Blynk.virtualWrite(11, currentFilterSec);
       currentFilterHours = (currentFilterSec / 3600);   // Converts those seconds to hours for display and other uses.
     }
     else if (todaysDate != day())
     {
-      yesterdayRuntime = todaysAccumRuntimeMin; // Moves today's runtime to yesterday for the app display.
-      todaysAccumRuntimeSec = 0; // Reset today's sec timer.
-      todaysAccumRuntimeMin = 0; // Reset today's min timer.
-      eeTodaysStartsCount = 0;   // Reset how many times unit has started today.
+      yesterdayRuntime = (todaysAccumRuntimeSec / 60);  // Moves today's runtime to yesterday for the app display.
+      todaysAccumRuntimeSec = 0;                        // Reset today's sec timer.
+      Blynk.virtualWrite(111, todaysAccumRuntimeSec);
+      hvacTodaysStartCount = 0;                         // Reset how many times unit has started today.
       todaysDate = day();
-
-      // Resets EEPROM at the end of the day (except for yesterday's runtime)
-      for (int i = 0 ; i < 200 ; i++) {
-        EEPROM.write(i, 0);
-      }
-      EEPROM.write(eeIndex, 1);                                   // Define address 1 as the starting location.
-      EEPROM.write(200, (yesterdayRuntime / 4));                  // Write yesterday's runtime to EEPROM
-      EEPROM.write(199, 0);                                       // Resets how many times the unit has started today.
-      EEPROM.commit();
-    }
+    }
+

     if (yesterdayRuntime < 1)               // Displays yesterday's runtime in app, or 'None' is there's none.
     {
@@ -573,22 +488,21 @@
       Blynk.virtualWrite(14, String(yesterdayRuntime) + " minutes");
     }

-    if (todaysAccumRuntimeSec < 1)          // Displays today's runtime in app, or 'None' is there's none.
+    if (todaysAccumRuntimeSec == 0)          // Displays today's runtime in app, or 'None' is there's none.
     {
       Blynk.virtualWrite(15, "None");
     }
-    else if (todaysAccumRuntimeMin > 0 && eeCurrent < 1)
-    {
-      Blynk.virtualWrite(15, String(todaysAccumRuntimeMin) + " minutes");
-    }
-    else if (todaysAccumRuntimeMin > 0 && eeCurrent > 0)
-    {
-      Blynk.virtualWrite(15, String(todaysAccumRuntimeMin) + " mins (" + (eeTodaysStartsCount) + " runs)");
-    }
-  }
-
-  Blynk.virtualWrite(10, String( filterChangeHours - currentFilterHours ) + " hours"); // Displays how many hours are left on the filter.
-
+    else if (todaysAccumRuntimeSec > 0 && hvacTodaysStartCount == 0)
+    {
+      Blynk.virtualWrite(15, String(todaysAccumRuntimeSec / 60) + " minutes");
+    }
+    else if (todaysAccumRuntimeSec > 0 && hvacTodaysStartCount > 0)
+    {
+      Blynk.virtualWrite(15, String(todaysAccumRuntimeSec / 60) + " mins (" + (hvacTodaysStartCount) + " runs)");
+    }
+  }
+
+  Blynk.virtualWrite(10, String( filterChangeHours - (currentFilterSec / 3600) ) + " hours"); // Displays how many hours are left on the filter.

   if (second() >= 0 && second() <= 5)     // Used to monitor uptime. All devices report minute. Another device confirms all reported minutes match.
   {


display host count

display host count

--- _04-mqtt-lcd-dust-sensor/_04-mqtt-lcd-dust-sensor-esp-12/_04-mqtt-lcd-dust-sensor-esp-12.ino
+++ _04-mqtt-lcd-dust-sensor/_04-mqtt-lcd-dust-sensor-esp-12/_04-mqtt-lcd-dust-sensor-esp-12.ino
@@ -43,15 +43,16 @@
 WiFiUDP udp;

 // volatile
-volatile float H  ;
-volatile float T1 ;
-volatile float T2 ;
-volatile float OT ;
-volatile float PW ;
-volatile int NW ;
-volatile int PIR  ;
-
-volatile int sleepmode = LOW ;
+float H  ;
+float T1 ;
+float T2 ;
+float OT ;
+float PW ;
+int NW ;
+int PIR  ;
+String HO  ;
+
+int sleepmode = LOW ;
 int o_sleepmode = LOW ;

 float dustDensity ;
@@ -63,6 +64,8 @@
 float OLD_PW ;
 int OLD_NW ;
 int OLD_PIR  ;
+String OLD_HO  ;
+
 float OLD_dustDensity ;

 int OLD_x ;
@@ -155,7 +158,7 @@
 PubSubClient client(wifiClient, server);

 void callback(const MQTT::Publish& pub) {
-  if (DEBUG_PRINT) {
+  if (1) {
     Serial.print(pub.topic());
     Serial.print(" => ");
     Serial.println(pub.payload_string());
@@ -189,6 +192,7 @@
   // esp8266/arduino/s06 : Scale
   // esp8266/arduino/s02  : T, H
   // esp8266/arduino/aircon : ________
+  // home/check/checkhwmny : host

   if ( receivedtopic == "esp8266/arduino/s02" ) {
     H   = root["Humidity"];
@@ -213,6 +217,11 @@
     PIR = root["DOORPIR"];
   }

+  if ( receivedtopic == "home/check/checkhwmny" )
+  {
+    const char* HOTEMP = root["host"];
+    HO = String(HOTEMP);
+  }
 }

 void setup() {
@@ -381,6 +390,7 @@
   NW = -1000 ;
   PIR = 0 ;
   dustDensity = -1000 ;
+  HO = '0' ;

   OLD_H  = -1000 ;
   OLD_T1 = -1000 ;
@@ -390,6 +400,7 @@
   OLD_NW = -1000 ;
   OLD_PIR = 0 ;
   OLD_dustDensity = -1000 ;
+  OLD_HO = '0';

   OLD_x = 0 ;

@@ -406,6 +417,11 @@
       if ( ( second() % 3 ) == 0 ) {
         requestSharp();
       }
+      /*
+      if ( ( second() % 50 ) == 0 ) {
+        client.subscribe(subtopic);
+      }
+      */
       checkDisplayValue();
     }
   }
@@ -413,14 +429,10 @@
   if (WiFi.status() == WL_CONNECTED) {
     if (!client.connected()) {
       if  (
-        client.connect(MQTT::Connect((char*) clientName.c_str())
-                       .set_clean_session()
-                       .set_will("status", "down")
-                       .set_keepalive(2))
-      ) {
+        client.connect(MQTT::Connect((char*) clientName.c_str()).set_clean_session().set_keepalive(120))) {
+        client.subscribe(subtopic);
         client.publish(hellotopic, "hello from ESP8266 s03");
         client.set_callback(callback);
-        client.subscribe(subtopic);
       }
     }

@@ -437,6 +449,12 @@
     o_sleepmode = sleepmode;
   }

+  if ( HO != OLD_HO )
+  {
+    displayHost(HO);
+    OLD_HO = HO;
+  }
+
   if (( PW != OLD_PW ) && ( 0 <= PW < 10000 ))
   {
     displaypowerAvg(PW);
@@ -447,12 +465,12 @@
   {
     /*
     if ( OLD_NW == -1000 ) {
-      displayNemoWeightAvg(NW);
+      displayNemoWeight(NW);
     } else {
-      displayNemoWeightAvg(NW);
+      displayNemoWeight(NW);
     }
     */
-    displayNemoWeightAvg(NW);
+    displayNemoWeight(NW);
     OLD_NW = NW;
   }

@@ -494,22 +512,30 @@
     Serial.print(" ===> ");
     Serial.print(PW);
     Serial.print(" ===> ");
+    Serial.print(HO);
+    Serial.print(" ===> ");
     Serial.println(NW);
   }

 }

+void displayHost(String HO)
+{
+  lcd.setCursor(18, 2);
+  lcd.print(HO);
+}
+
 void displaysleepmode(int sleepmode)
 {
   if ( sleepmode == HIGH ) {
+    lcd.setCursor(15, 2);
+    lcd.write(3);
     lcd.setCursor(16, 2);
     lcd.write(3);
-    lcd.setCursor(17, 2);
-    lcd.write(3);
   } else {
+    lcd.setCursor(15, 2);
+    lcd.print(" ");
     lcd.setCursor(16, 2);
-    lcd.print(" ");
-    lcd.setCursor(17, 2);
     lcd.print(" ");
   }

@@ -528,7 +554,7 @@

 }

-void displayNemoWeightAvg(int nemoWeight)
+void displayNemoWeight(int nemoWeight)
 {
   String str_nemoWeight = String(nemoWeight);
   int length_nemoWeight = str_nemoWeight.length();


Clean up Sodaq binary example. Disable SF spreading by default.

--- examples/SodaqOne-TTN-Mapper-binary/SodaqOne-TTN-Mapper-binary.ino
+++ examples/SodaqOne-TTN-Mapper-binary/SodaqOne-TTN-Mapper-binary.ino
@@ -29,7 +29,7 @@
 #include <rn2xx3.h>

 //create an instance of the rn2xx3 library,
-//giving the software serial as port to use
+//giving Serial1 as stream to use for communication with the radio
 rn2xx3 myLora(Serial1);

 String toLog;
@@ -47,8 +47,7 @@
     Serial1.begin(57600);

     // make sure usb serial connection is available,
-    // or after 10s go on anyway for 'headless' use of the
-    // node.
+    // or after 10s go on anyway for 'headless' use of the node.
     while ((!SerialUSB) && (millis() < 10000));

     SerialUSB.println("SODAQ LoRaONE TTN Mapper starting");
@@ -64,6 +63,11 @@
     // initialize GPS
     sodaq_gps.init(GPS_ENABLE);

+    // Set the datarate/spreading factor at which we communicate.
+    // DR5 is the fastest and best to use. DR0 is the slowest.
+    myLora.setDR(dr);
+
+    // LED pins as outputs. HIGH=Off, LOW=On
     pinMode(LED_BLUE, OUTPUT);
     digitalWrite(LED_BLUE, HIGH);
     pinMode(LED_RED, OUTPUT);
@@ -124,6 +128,7 @@
   sodaq_gps.scan(true);
   digitalWrite(LED_GREEN, HIGH);

+  // if the latitude is 0, we likely do not have a GPS fix yet, so wait longer
   while(sodaq_gps.getLat()==0.0)
   {
     SerialUSB.println("Latitude still 0.0, doing another scan");
@@ -178,7 +183,8 @@
   digitalWrite(LED_BLUE, HIGH);

   // Cycle between datarate 0 and 5
-  dr = (++dr) % 6;
-  myLora.setDR(dr);
+  //dr = (++dr) % 6;
+  //myLora.setDR(dr);
+
   SerialUSB.println("TX done");
 }


tests made

tests made

code is working
robotic joint needs mapping


code cleaning and preparing for merge

code cleaning and preparing for merge

--- send/send.ino
+++ send/send.ino
@@ -5,12 +5,14 @@

 #include <SPI.h>
 #include "mcp_can.h"
+#include <mcp_can_dfs.h>

 // the cs pin of the version after v1.1 is default to D9
 // v0.9b and v1.0 is default D10
 const int SPI_CS_PIN = 9;
-uint32_t data = 0;
+uint32_t encoder_data = 0;
+uint32_t loadcell_data = 0;

 MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

@@ -39,45 +41,38 @@

     unsigned int canId = CAN.getCanId();

-    Serial.println("-----------------------------");
-    Serial.print("Get data from ID: ");
-    Serial.println(canId, HEX);
+    // encoder information is read from buf[4] and buf[5] and converted to decimal
+    encoder_data = buf[4];
+    encoder_data <<= 8;
+    encoder_data = encoder_data | buf[5];

-    for (int i = 0; i < len; i++) // print the data
-    {
-      Serial.print(buf[i], HEX);
-      Serial.print("\t");
-    }
-    Serial.println();
+    // // load cell information is read from buf[1], buf[2] and buf[3] and converted to decimal
+    // loadcell_data = buf[1];
+    // loadcell_data <<= 8;
+    // loadcell_data = loadcell_data | buf[2];
+    // loadcell_data <<= 8;
+    // loadcell_data = loadcell_data | buf[3];

-    // encoder information is read from buf[4] and buf[5] and converted to decimal
-    enconder_data = buf[4];
-    enconder_data <<= 8;
-    enconder_data = data | buf[5];
+    // if (buf[1] >= 128) {
+    //        loadcell_data = loadcell_data - 16777216;
+    // }
+
+       Serial.print("Encoder: ");
+       Serial.println(encoder_data, DEC);

-    // load cell information is read from buf[1], buf[2] and buf[3] and converted to decimal
-    loadcell_data = buf[1];
-    loadcell_data <<= 8;
-    loadcell_data = data | buf[2];
-    loadcell_data <<= 8;
-    loadcell_data = data | buf[3];
+    // Serial.print("Loadcell: ");
+    // Serial.println(loadcell_data/1000, DEC);

-    if (buf[1] >= 128) {
-           laodcell_data = loadcell_data - 16777216;
-    }
-
-    Serial.print("Encoder: ");
-    Serial.println(encoder_data, DEC);
-
-    Serial.print("Loadcell: ");
-    Serial.println(laodcell_data, DEC);
-
-    delay(400);
+    // delay(400);
   }

 }

+
 /*********************************************************************************************************
   END FILE
 *********************************************************************************************************/
+
+
+


updated parallel out 2

updated parallel out 2

--- proj/parallel_out_test_2/parallel_out_test_2.ino
+++ proj/parallel_out_test_2/parallel_out_test_2.ino
@@ -43,7 +43,6 @@

 void loop() {

-
   for (uint8_t strip = 0; strip < NUM_STRIPS; strip++) {
     for (uint8_t ll = 0; ll < NUM_LED; ll++) {
       leds[strip * NUM_LED + ll] = CHSV(strip*2*16, 192, 255);


added 'I' (=query identification) command which return HW and SW version

--- examples/SxInterface/SxInterface.ino
+++ examples/SxInterface/SxInterface.ino
@@ -34,6 +34,10 @@

 #include <SX22b.h>   // this is the Selectrix library
 #include <SX22Command.h>   // this is the Selectrix Command library
+
+#define HARDWARE_ID  "ID HW: opensx SX-interface 0.1"
+#define SOFTWARE_ID  "ID SW: SxInterface.ino 18 Dec 2016"
+#define SXLIB_ID     "ID LIB: SX22b"

 #define LED_PIN  13   // on most Arduinos there is an LED at pin 13
 #define MAX_SX_CHANNEL   110   // do not read values >= 110
@@ -163,7 +167,11 @@
 				} else {
 					Serial.println("ERR");
 				}
-			} else {
+			} else if (inputString[0] == 'i'){
+        Serial.println(HARDWARE_ID);
+        Serial.println(SOFTWARE_ID);
+        Serial.println(SXLIB_ID);
+      } else {
 				Serial.println("ERR");
 			}
 			//Serial.print("read=");


created a way to measure water level, the water level sensor output is logarithmic graph form

--- WaterLevelSensor/WaterLevelSensor.ino
+++ WaterLevelSensor/WaterLevelSensor.ino
@@ -7,47 +7,81 @@
   This example code is in the public domain.
 */

+#define D0  16
+#define D1  5
+#define D2  4
+#define D3  0
+#define D4  2
+#define D5  14
+#define D6  12
+#define D7  13
+#define D8  15
+#define D9  3
+#define D10 1
+
 // the setup routine runs once when you press reset:
 void setup() {
   // initialize serial communication at 9600 bits per second:
   Serial.begin(115200);
+  pinMode(D5, OUTPUT);
+
 }
+
+
+/*  My measurement
+ *
+ * -------------------------------------------
+ *    Water height(mm)    |   analogRead(A0) |
+ * -------------------------------------------
+ *         0.5            |       532        |
+ *         1.0            |       600        |
+ *         1.5            |       648        |
+ *         2.0            |       700        |
+ *         2.5            |       759        |
+ *         3.0            |       784        |
+ *         3.5            |       792        |
+ *         4.0            |       805        |
+ */

 // the loop routine runs over and over again forever:
 void loop() {
   // read the input on analog pin 0:
   int waterHeight;
-  int sensorValue = analogRead(A0);
-/*
-  if(sensorValue>690)
-    waterHeight = map(sensorValue, 700, 1024, 0, 40);
-  else
-    waterHeight = 0;
-  // print out the value you read:
-*/
-  if(sensorValue>700)
-    waterHeight = 1;
-  if(sensorValue>736)
-    waterHeight = 5;
-  if(sensorValue>790)
-    waterHeight = 10;
-  if(sensorValue>827)
-    waterHeight = 15;
-  if(sensorValue>843)
-    waterHeight = 20;
-  if(sensorValue>857)
-    waterHeight = 25;
-  if(sensorValue>870)
-    waterHeight = 3;
-  if(sensorValue>910)
-    waterHeight = 3.5;
-  if(sensorValue>1010)
-    waterHeight = 40;
+  int sensorValue;
+  digitalWrite(D5, HIGH);
+  delay(500);
+  sensorValue = analogRead(A0);
+  Serial.println(sensorValue);

-
-  Serial.println(sensorValue);
+
+  if( sensorValue >= 0 && sensorValue <= 532 )
+    waterHeight = map(sensorValue, 11 , 532, 0 , 5);
+
+  else if( sensorValue > 532 && sensorValue <= 600 )
+    waterHeight = map(sensorValue, 533 , 600, 5 , 10);
+
+  else if( sensorValue > 600 && sensorValue <= 648 )
+    waterHeight = map(sensorValue, 601 , 648, 10 , 15);
+
+  else if( sensorValue > 648 && sensorValue <= 700 )
+    waterHeight = map(sensorValue, 649 , 700, 15 , 20);
+
+  else if( sensorValue > 700 && sensorValue <= 759 )
+    waterHeight = map(sensorValue, 701 , 759, 20 , 25);
+
+  else if( sensorValue > 759 && sensorValue <= 784 )
+    waterHeight = map(sensorValue, 760 , 784, 25 , 30);
+
+  else if( sensorValue > 784 && sensorValue <= 792 )
+    waterHeight = map(sensorValue, 785 , 792, 30 , 35);
+
+  else waterHeight = map(sensorValue, 793 , 805, 35 , 40);
+
+
+  waterHeight = ( waterHeight > 40 ? 40 : waterHeight);
+
   Serial.println(waterHeight);
-
+  digitalWrite(D5, LOW);
   Serial.println();
   delay(1000);        // delay in between reads for stability
 }


Testing PID function

Testing PID function

--- utils/testSketch/testSketch.ino
+++ utils/testSketch/testSketch.ino
@@ -1,4 +1,5 @@
 #include <TimerOne.h>
+#include <PID_v1.h>

 #define INTERROMPE_DIREITA 3
 #define INTERROMPE_ESQUERDA 2
@@ -42,14 +43,24 @@
 volatile int velocidadeDireita = 800;
 volatile int velocidadeEsquerda = 870;

-volatile int pwmDireita = 0;
-volatile int pwmEsquerda = 0;
+volatile double pwmDireita = 0;
+volatile double pwmEsquerda = 0;

 volatile bool motoresAtivados = false;

 volatile int contador = 0;

 volatile int girosDesejados = 150;
+
+//Define Variables we'll be connecting to
+double entradaEsquerda, entradaDireita;
+double objetivo = 80;
+
+//Specify the links and initial tuning parameters
+PID motorEsquerdo(&entradaEsquerda, &pwmEsquerda, &objetivo,kpEsquerda,0,0, DIRECT);
+
+//Specify the links and initial tuning parameters
+PID motorDireito(&entradaDireita, &pwmDireita, &objetivo,kpDireita,0,0, DIRECT);

 void setup() {
   Serial.begin(115200);
@@ -71,6 +82,12 @@

   Timer1.initialize(1000000 / 10);
   Timer1.attachInterrupt(ajustaMotor);
+
+  motorEsquerdo.SetMode(AUTOMATIC);
+  motorDireito.SetMode(AUTOMATIC);
+  motorEsquerdo.SetOutputLimits(0, 1023);
+  motorDireito.SetSampleTime(1000/10);
+  motorEsquerdo.SetSampleTime(1000/10);
 }

 void loop() {
@@ -98,6 +115,7 @@
           case 'P':
             valor_float = atof(&serialLido[3]);
             kpEsquerda = valor_float;
+            motorEsquerdo.SetTunings(kpEsquerda, 0, 0);
             break;
           case 'S':
             valor_int = atoi(&serialLido[3]);
@@ -114,6 +132,7 @@
           case 'P':
             valor_float = atof(&serialLido[3]);
             kpDireita = valor_float;
+            motorDireito.SetTunings(kpDireita, 0, 0);
             break;
           case 'S':
             valor_int = atoi(&serialLido[3]);
@@ -134,10 +153,14 @@

 void ajustaMotor() {
   if (motoresAtivados) {
-    pwmEsquerda += kpEsquerda * (contaEsquerda - (girosDesejados / 10));
-    //ACELERA_ESQUERDA(pwmEsquerda);
-    pwmDireita += kpDireita * (contaDireita - (girosDesejados / 10));
-    //ACELERA_DIREITA(pwmDireita);
+    //pwmEsquerda += kpEsquerda * (contaEsquerda - (girosDesejados / 10));
+    entradaEsquerda = contaEsquerda;
+    motorEsquerdo.Compute();
+    ACELERA_ESQUERDA(pwmEsquerda);
+    //pwmDireita += kpDireita * (contaDireita - (girosDesejados / 10));
+    entradaDireita = contaDireita;
+    motorDireito.Compute();
+    ACELERA_DIREITA(pwmDireita);
   }
   if (contador == 10) {
     contador = 0;


update example 'CascadedInvert.ino'

update example 'CascadedInvert.ino'

--- examples/CascadedInvert/CascadedInvert.ino
+++ examples/CascadedInvert/CascadedInvert.ino
@@ -1,6 +1,4 @@
 #include "MatrixCascade.h"
-// This time we have more than one device.
-

 // pin 12 is connected to the DataIn
 // pin 11 is connected to the CLK
@@ -8,7 +6,7 @@
 const uint8_t CascadeSize = 3;
 MatrixCascade<CascadeSize> cascade(12, 11, 10);

-unsigned long delaytime = 30;
+unsigned long delaytime = 20;

 void setup()
 {
@@ -18,57 +16,24 @@
     // Rotate some matrixes
     cascade[1].setRotation(2);
     cascade[2].setRotation(2);
+
+    // Init random sequense
+    randomSeed(millis());
 }

-/*
+
 void loop()
 {
     for(auto &matrix: cascade) {
-        matrix.setRotation();
-        for(auto &row: matrix.rows()) {
-            for(auto &col: matrix.cols()) {
-                delay(delaytime);
-                matrix.on(row, col);
-            }
-        }
-        //matrix.clear();
-    }
-
-    for(auto &matrix: cascade) {
-        for(auto &col: matrix.cols()) {
-            for(auto &row: matrix.rows()) {
-                delay(delaytime);
-                matrix.off(row, col);
-            }
-        }
-    }
-
-    cascade.clear();
-    delay(100*delaytime);
-    cascade.fill();
-    delay(100*delaytime);
-    cascade.invert();
-}
-*/
-void loop()
-{
-
-
-    randomSeed(millis());
-
-
-    for(auto &matrix: cascade) {
-        matrix.setRotation();
         for(auto &row: matrix.rows()) {
             for(auto &col: matrix.cols()) {
                 delay(delaytime);
                 matrix.set(row, col, random(2));
             }
         }
-        //matrix.clear();
     }

-    //delay(100*delaytime);
+    // Invert all matrixes on cascade
     cascade.invert();
     delay(50*delaytime);

@@ -79,6 +44,8 @@
                 matrix.set(row, col, random(2));
             }
         }
+        // Rotate matrix
+        matrix.setRotation();
     }
     cascade.invert();
     delay(50*delaytime);
@@ -86,6 +53,5 @@
     cascade.clear();
     delay(50*delaytime);
     cascade.fill();
-
 }


Update sketch_reco.ino

Update sketch_reco.ino

--- dragino/sketch_reco.ino
+++ dragino/sketch_reco.ino
@@ -71,24 +71,51 @@

 }

+long lastReconnectAttempt = 0;
+
+boolean reconnect() {
+  if (client.connect(IOTID, IOTUSERNAME, IOTPASSWORD)) {
+
+    client.publish(STATUS,"hello - re-authenticated!!");
+     client.subscribe(TOPIC);
+  }
+  return client.connected();
+}

 void setup()
 {
   Bridge.begin();
+  client.setCallback(callback);
+  lastReconnectAttempt = 0;
+
   pinMode(out2, OUTPUT);
   pinMode(out3, OUTPUT);
   pinMode(out4, OUTPUT);
   pinMode(out6, OUTPUT);

-  if (client.connect(IOTID, IOTUSERNAME, IOTPASSWORD)) {
-   client.publish(STATUS,"hello world - authenticated!!");
-   client.subscribe(TOPIC);
-  }
+// if (client.connect(IOTID, IOTUSERNAME, IOTPASSWORD)) {
+//   client.publish(STATUS,"hello - authenticated!!");
+//   client.subscribe(TOPIC);
+//  }
 }

 void loop()
 {
-  client.loop();
+  if (!client.connected()) {
+    long now = millis();
+    if (now - lastReconnectAttempt > 5000) {
+      lastReconnectAttempt = now;
+      // Attempt to reconnect
+      if (reconnect()) {
+        lastReconnectAttempt = 0;
+      }
+    }
+  } else {
+    // Client connected
+
+    client.loop();
+  }
+
 }


Whitespace

Whitespace

--- Blink.ino
+++ Blink.ino
@@ -1,8 +1,8 @@
 int led = 13;

-void setup() {
+void setup() {
   Serial.begin(9600);
-  pinMode(led, OUTPUT);
+  pinMode(led, OUTPUT);
 }

 void loop() {


Enable HV wakeup for single wire CAN

Enable HV wakeup for single wire CAN

--- M2RET.ino
+++ M2RET.ino
@@ -733,7 +733,7 @@

     for (int i = 0; i < MARK_LIMIT; i++)
     {
-        if ((lastMarkTrigger + 500) < millis()) //prevent jitter on switch closing
+        if ((lastMarkTrigger + 100) < millis()) //prevent jitter on switch closing
         {
             if (M2IO.GetButton_12VIO(i + 1)) {
     	        if (!markToggle[i]) {
@@ -1040,37 +1040,30 @@
                                 break;
                             }
                         default:{
-                                if(step < build_out_frame.length + 6){
+                                if(step < build_out_frame.length + 6)
+                                {
                                     build_out_frame.data.bytes[step - 6] = in_byte;
-                                } else{
+                                }
+                                else
+                                {
                                     state = IDLE;
                                     //this would be the checksum byte. Compute and compare.
                                     temp8 = checksumCalc(buff, step);
-                                    //if (temp8 == in_byte){
-                                        /*
-                                        if (settings.singleWireMode == 1){
-                                            if (build_out_frame.id == 0x100){
-                                                if (out_bus == 1){
-                                                    setSWCANWakeup();
-                                                    delay(5);
-                                                    }
-                                            }
-                                        }
-                                    */
+                                    if ((build_out_frame.id == 0x100) && (out_bus == 2))
+                                    {
+                                        SWCAN.mode(1);
+                                        delay(1);
+                                    }
                                     build_out_frame.rtr = 0;
                                     if(out_bus == 0) sendFrame(&Can0, build_out_frame);
                                     if(out_bus == 1) sendFrame(&Can1, build_out_frame);
                                     if(out_bus == 2) sendFrame(&SWCAN, build_out_frame);
-                                    /*
-                                    if (settings.singleWireMode == 1){
-                                        if (build_out_frame.id == 0x100){
-                                            if (out_bus == 1){
-                                                delay(5);
-                                                setSWCANEnabled();
-                                                }
-                                            }
-                                        } */
-                                    //}
+
+                                    if ((build_out_frame.id == 0x100) && (out_bus == 2))
+                                    {
+                                        delay(1);
+                                        SWCAN.mode(3);
+                                    }
                                 }
                                 break;
                             }


Shrimp listens now to commands in the console

--- Sources/Shrimp/Shrimp.ino
+++ Sources/Shrimp/Shrimp.ino
@@ -19,14 +19,18 @@

 // Pins
 const int ledPin = 13;
-const int dhc11Pin = 8;
+const int dht11Pin = 8;
+
+// Variables to use for the interval
+unsigned long previousMillis = 0;
+long logInterval = 0; // Hoe vaak willen we loggen?

 // Variables
 dht11 DHT11;
 DB db;
 int travelTime = 0; // Total travel time in s
-int logInterval = 0; // Hoe vaak willen we loggen?
 String msg;
+boolean logData = true;
 struct MyRec {
   int humidity;
   double temperature;
@@ -36,7 +40,9 @@
   // Initialize pins
   pinMode(ledPin, OUTPUT);

-  DHT11.attach(dhc11Pin);
+  logInterval = 2000;
+
+  DHT11.attach(dht11Pin);
   Serial.begin(9600);

   db.create(TABLE, sizeof(myrec));
@@ -44,30 +50,44 @@
 }

 void loop() {
-  // put your main code here, to run repeatedly:
-  if (Serial.available()) {
-   msg = (String) Serial.read();
-   if (msg == "View data") selectAll();
-  }
+   // put your main code here, to run repeatedly:
+   while (Serial.available() > 0) {
+     char recieved = Serial.read();
+     msg += recieved;
+
+     if (msg == "viewData") selectAll();
+     else if (msg == "stopLogging") logData = false;
+   }

+   unsigned long currentMillis = millis();

-//  Serial.print("Humidity (%): ");
-//  Serial.println((int)DHT11.humidity, DEC);
-  myrec.humidity = (int) DHT11.humidity;
-
-//  Serial.print("Temperature (°C): ");
-//  Serial.println((double)DHT11.temperature, DEC);
-  myrec.temperature = (double) DHT11.temperature;
-
-  db.append(DB_REC myrec);
+   if(currentMillis - previousMillis >= logInterval && logData) {
+      previousMillis = currentMillis;
+
+      int chk = DHT11.read();
+//      switch (chk) {
+//         case 0: Serial.println("OK"); break;
+//         case -1: Serial.println("Checksum error"); break;
+//         case -2: Serial.println("Time out error"); break;
+//         default: Serial.println("Unknown error"); break;
+//      }
+
+//      Serial.print("Humidity (%): ");
+//      Serial.println((int) DHT11.humidity, DEC);
+      myrec.humidity = (int) DHT11.humidity;
+
+//      Serial.print("Temperature (°C): ");
+//      Serial.println((double) DHT11.temperature, DEC);
+      myrec.temperature = (double) DHT11.temperature;
+
+      db.append(DB_REC myrec);
+   }
   //selectAll();
-  delay(2000);
 }

 void selectAll() {
   if (db.nRecs()) Serial.println("-----");
-  for (int i = 1; i <= db.nRecs(); i++)
-  {
+  for (int i = 1; i <= db.nRecs(); i++) {
     db.read(i, DB_REC myrec);
     Serial.print("Recnum: "); Serial.println(i);
     Serial.print("Humidity: "); Serial.println(myrec.humidity);


small improvement

small improvement

--- si5351-beacon.ino
+++ si5351-beacon.ino
@@ -70,10 +70,11 @@

 // ---- Arduino pin configuration ---

-const int pinLED = LED_BUILTIN; // out
-const int pin1PPS = 4;
-
-
+const int pinLED = LED_BUILTIN; // duplicate 1pps
+const int pin1PPS = 4; // <-- 1pps signal from ds3231
+
+
+// Active LOW relay pins as on QRP-LABS relay-switched LPF kit
 const int pinBAND0 = 7;
 const int pinBAND1 = A0;
 const int pinBAND2 = 10;
@@ -84,11 +85,11 @@

 // ----- Configure mapping: RF_Band -> Relay_switch_board_LPF  -----
 LPF_Band_Matching relaySwitchBandMatching [] = {
-  {RF_Band_160m, FILTER_BAND_1},
-  {RF_Band_40m, FILTER_BAND_2},
+  {RF_Band_40m, FILTER_BAND_5},
   {RF_Band_30m, FILTER_BAND_3},
-  {RF_Band_20m, FILTER_BAND_4},
-  {RF_Band_15m, FILTER_BAND_5}
+  {RF_Band_20m, FILTER_BAND_2},
+  {RF_Band_15m, FILTER_BAND_1},
+  {RF_Band_15m, FILTER_BAND_1}

 };

@@ -98,11 +99,11 @@

 const int PTTWarmupTimeInSeconds = 2; // Number of seconds prior symbols transmission. It is for activate PTT of Power Amplifer.
 const unsigned TRIntervalMultiplier = 1; // for example: value 1 means TR-TR-TR...   value 3 means: TX-RX-RX-TX...
-bool WorkModeActive = false; // active TX logic at power on
-bool BandHoppingEnabled = true; // band hopping control
+bool WorkModeActive = true; // active TX logic at power-on
+bool BandHoppingEnabled = true; // band hopping state at power-on

 // ------------- Predefined messages JT65,JT9,JT4
-// "HELLO WORLD" encodede message. Please replace to your own.
+// "HELLO WORLD" encoded message. Please replace to your own.
 const PROGMEM unsigned char MSG_JT65[] = {29,23,60,48,34,6,39,9,23,26,55,15,47,12,16,42,11,25,63,63,9,10,60,0,46,21,15,54,54,62,51,48,39,20,56,25,15,62,52,36,3,4,41,13,59,10,41,63,43,39,15,19,32,33,53,25,60,62,4,55,26,42,48};
 const PROGMEM unsigned char MSG_JT9[] = {0,0,3,6,0,7,3,4,7,0,7,3,2,4,8,0,3,2,4,1,6,1,0,5,8,2,2,4,4,2,5,3,0,8,0,4,7,3,7,6,3,4,4,5,3,2,4,3,7,2,0,0,1,2,0,5,5,2,5,0,2,4,8,3,2,0,2,1,3,8,1,8,0,2,2,8,3,1,7,8,1,2,0,1,0};
 const PROGMEM unsigned char MSG_JT4[] = {};
@@ -110,22 +111,21 @@

 //---------- Begin Band Configuration  ----------------------

-size_t currentBandIndex = 0; // <--- Startup band index in the array below (zero-based)
+size_t currentBandIndex = 0; // <--- Band index at power-on in the array below (zero-based)

 //
 // Copy vector-descriptor from web configurator and paste into bandDescrArray.
 // Local configurator:  ./doc/band_configurator.html
 // Configurator in the Net:  http://ra9yer.blogspot.com/p/si5351-configurator.html
 //
+
 JTBandDescr bandDescrArray[] = {
     {Mode_JT65_B, 32, 28943, 836045, 6, 1, 441, 163840, 60} // f=144.1777 MHz; JT65B; step=5.383Hz; 2.692baud; T/R=1m
-  , {Mode_WSPR2, 31, 154287, 614418, 30, 1, 12, 8192, 120} // f=28.126 MHz; WSPR2; step=1.465Hz; 1.465baud; T/R=2m
-
-};
+  , {Mode_WSPR2, 31, 154287, 614418, 30, 1, 12, 8192, 120} // f=28.126 MHz; WSPR2; step=1.465Hz; 1.465baud; T/R=2m};

 //----------  End Configuration ------------------------

-const size_t numBandsTotal = sizeof(bandDescrArray) / sizeof(bandDescrArray[0]); // Auto calc number of bands. Used for band hopping.
+const size_t NumBandsTotal = sizeof(bandDescrArray) / sizeof(bandDescrArray[0]); // Calc number of bands at compile time. Used for band hopping.

 // ------ Message initialize functions -----
@@ -195,7 +195,7 @@
   initializeJT9Coder();
   initializeJT4Coder();

-  currentBandIndex = (currentBandIndex < numBandsTotal)? currentBandIndex : 0;
+  currentBandIndex = (currentBandIndex < NumBandsTotal)? currentBandIndex : 0;
   bandParams.initFromJTBandDescr( bandDescrArray[currentBandIndex] );
   printBandInfo();

@@ -373,6 +373,7 @@
   {
     if( currentState != stateTransmitting )
     {
+      activate_ptt();
       start_tx();
     }
     else
@@ -456,23 +457,22 @@

   RtcDatetime time;
   Ds3231::getTime(time);
-  Serial.print("\nCurrent DateTime = ");
+  Serial.print(F("\nClock  DateTime = "));
   time.formatStr(buf);
   Serial.print(buf);
-  Serial.print("\n");

   if( includeLaunchTime )
   {
-    Serial.print("dataStartTime = ");
+    Serial.print(F("\nPTT    DateTime = "));
+    pttStartTime.formatStr(buf);
+    Serial.print(buf);
+
+    Serial.print(F("\nSymbol DateTime = "));
     symbolsStartTime.formatStr(buf);
     Serial.print(buf);
-
-    Serial.print("\npttStartTime = ");
-    pttStartTime.formatStr(buf);
-    Serial.print(buf);
-    Serial.print("\n");
-  }
-
+  }
+
+  Serial.print(F("\n"));
 }

 //--------------------------------------------------
@@ -480,11 +480,14 @@
 {
   Serial.print(F("\nCurrent band: Index="));
   Serial.print(currentBandIndex);
-  Serial.print(F(" mode="));
+  Serial.print(F("; mode="));
   Serial.print((int)bandParams.getJTMode());
-  Serial.print(F(" F="));
+  Serial.print(F("; F="));
   Serial.print(bandParams.approxFrequencyInMHz());
-  Serial.print(F(" MHz\n"));
+  Serial.print(F(" MHz"));
+  Serial.print(F("; RelayNumber="));
+  Serial.print(convertRFBandToFilterBand(bandParams.getBand())); // 0-means None (FILTER_BAND_None); 1-RL0; 2-RL1; 3-RL2; 4-RL3; 5-RL4; 6-RL5
+  Serial.print(F("\n"));
 }

 //----------------------------------------------------------
@@ -599,7 +602,7 @@
     return;

   currentBandIndex++;
-  if( currentBandIndex >= numBandsTotal )
+  if( currentBandIndex >= NumBandsTotal )
   {
     currentBandIndex = 0;
   }
@@ -628,7 +631,7 @@
   unsigned long stamp = currentTime.stamp();
   stamp += trInterval * TRIntervalMultiplier; // jump to future
   stamp -= (stamp % trInterval); // round down
-  stamp += 1; // JT64,JT9,JT4,WSPR - all start at 01 second
+  stamp += 1; // JT65,JT9,JT4,WSPR - all start at 01 second

   symbolsStartTime.initFromStamp( stamp );
   pttStartTime.initFromStamp( stamp - PTTWarmupTimeInSeconds );
@@ -697,6 +700,9 @@
 //----------------------------------------------------------
 void deactivate_ptt()
 {
+  // TODO: in some cases it is not necessary to switch relay off
+  switchRealyToBand( FILTER_BAND_None );
+
   // turn off ptt key here
 }


Basically revert the previous commit. Turned out to not work out.

--- GVRET.ino
+++ GVRET.ino
@@ -737,7 +737,7 @@
 				   if (build_int > 1000000) build_int = 1000000;
 				   Can0.enable();
 				   Can0.begin(build_int, SysSettings.CAN0EnablePin);
-				   Can0.set_baudrate(build_int);
+				   //Can0.set_baudrate(build_int);
 				   settings.CAN0Speed = build_int;
 				   settings.CAN0_Enabled = true;
 			   }
@@ -765,7 +765,7 @@
 				   Can1.begin(build_int, SysSettings.CAN1EnablePin);
 				   if (settings.singleWireMode) setSWCANEnabled();
 				   else setSWCANSleep();
-				   Can1.set_baudrate(build_int);
+				   //Can1.set_baudrate(build_int);

 				   settings.CAN1Speed = build_int;
 				   settings.CAN1_Enabled = true;


Phil-specific node config.

Phil-specific node config.

--- arduino_repeater/arduino_repeater.ino
+++ arduino_repeater/arduino_repeater.ino
@@ -11,7 +11,7 @@
 #include "RFM69.h"
 #include "LowPower.h"

-#define P01
+#define P5

 //************* Node ID Setup ****************/
 #ifdef P01
@@ -21,7 +21,12 @@
 #endif
 #ifdef P02
 char id[] = "P02";
-char location_string[] = "50.93879,-1.3979";
+char location_string[] = "50.93623,-1.39876";
+#define BATTV_FUDGE 0.943
+#endif
+#ifdef P5
+char id[] = "P5";
+char location_string[] = "50.93897,-1.39774";
 #define BATTV_FUDGE 0.943
 #endif
 #define BEACON_INTERVAL 30


Use macros for better readability.

Use macros for better readability.

--- src/main.ino
+++ src/main.ino
@@ -92,17 +92,21 @@
   sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
 }

+#define DISABLE 0
+#define ENABLE  1
+
 void setup() {
+  // set the WiFi chip to "promiscuous" mode aka monitor mode
   Serial.begin(115200);
   delay(10);
   wifi_set_opmode(STATION_MODE);
   wifi_set_channel(1);
-  wifi_promiscuous_enable(0);
+  wifi_promiscuous_enable(DISABLE);
   delay(10);
   wifi_set_promiscuous_rx_cb(sniffer_callback);
   delay(10);
-  wifi_promiscuous_enable(1);
-	Serial.println("Listening on channel 01");
+  wifi_promiscuous_enable(ENABLE);
+
 }

 void loop() {}


Rebuilt code from begin to work with servo motors

--- src/main.ino
+++ src/main.ino
@@ -1,73 +1,32 @@
-/////////////
-// CONTENT //
-/////////////
-// 1. libraries
-// 2. variables
-// 3. initializes
-// 4. setup function
-// 5. loop function
-// 6. callable functions
+// LIBRARIES //
+#include <Servo.h>

-///////////////
-// LIBRARIES //
-///////////////
-#include <Stepper.h>
-
-/////////////
-// DEFINES //
-/////////////
-// step_mode let us use halfsteps (but we probably don't need that)
-int step_mode = 8; // 4 = full, 8 = half
-
-// number of steps it takes to turn motor 360º
-#define fullRev 2048 * (step_mode/4)
-
-////////////////////////
-// STEPPER INITIALIZE //
-////////////////////////
-// the four integers are the pins the motor is connected to.
-Stepper Digit1(fullRev, 2, 3, 4, 5, step_mode);
-Stepper Digit2(fullRev, 6, 7, 8, 9, step_mode);
-Stepper Digit3(fullRev, 10, 11, 12, 13, step_mode);
+Servo m1;
+Servo m2;
+Servo m3;
+Servo m4;
+Servo m5;

-///////////
 // SETUP //
-///////////
 void setup() {
-  // serial port
-  Serial.begin(9600);
-
-  // Built in led blinks 3 times
-  pinMode(LED_BUILTIN, OUTPUT);
-  blink(3);
-
-  // max is around 160 RPM
-  Digit1.setSpeed(100);
-  Digit2.setSpeed(100);
-  Digit3.setSpeed(100);
-}
-
-///////////////////
-// LOOP FUNCTION //
-///////////////////
-void loop() {
-  Digit1.step(fullRev);
-  delay(100);
-  Digit2.step(fullRev);
-  delay(100);
-  Digit3.step(fullRev);
-  delay(100);
-
-  turnDigit(1, 0.25);
-  turnDigit(2, 0.5);
-  turnDigit(3, 0.75);
+  m1.attach(2);
+  m2.attach(3);
+  m3.attach(4);
+  m4.attach(5);
+  m5.attach(6);
 }

-//////////////
-// CALLABLE //
-//////////////
+// LOOP //
+void loop() {
+  m1.write(90);
+  int val = m1.read();
+  Serial.println(val);
+}
+
+
+// FUNCTIONS //
 void blink(int howManyTimes) {
   int i;
   for (i = 0; i < howManyTimes; i++) {
@@ -78,34 +37,18 @@
   }
 }

-void turnDigit(int digNum, float frac) {
-  if (frac > 0) {
-    int steps = fullRev * frac;
-
-    switch (digNum) {
-      case 1:
-        Digit1.step(steps);
-        break;
-      case 2:
-        Digit2.step(steps);
-      case 3:
-        Digit3.step(steps);
-    }
-  }
-  else {
-    Serial.println("Fraction of rotation can't be negative or 0.");
-    float frac = 1.0;
-    turnDigit(digNum, frac);
-  }
+void pinch() {
+  m1.write(90);
+  m2.write(90);
+  m3.write(180);
+  m4.write(180);
+  m5.write(180);
 }

 void thumbsUp() {
-  turnDigit(1, 5);
-  turnDigit(2, -5);
-  turnDigit(3, -5);
+  m1.write(0);
+  m2.write(180);
+  m3.write(180);
+  m4.write(180);
+  m5.write(180);
 }
-
-void pinch() {
-  turnDigit(1, 5);
-  turnDigit(2, 5);
-}


コンテンツのガイド表示誤りを修正

コンテンツのガイド表示誤りを修正

--- 2_example/example15_jam/html.ino
+++ 2_example/example15_jam/html.ino
@@ -30,7 +30,7 @@
     client.println("
HTTP GET
");
     client.print("
http://");
     client.print(s_ip);
-    client.println("/?TEXT=文字列
");
+    client.println("/?COM=文字列
");
     sprintf(s,"<form method=\"GET\" action=\"http://%s/\">",s_ip);
     client.println(s);
     client.println("<input type=\"submit\" name=\"COM\" value=\"LED 1\">");


Might be done. goint to plug into the sim to find out.

--- firmware.ino
+++ firmware.ino
@@ -1,46 +1,3 @@
-class Oscillator
-{
-  // Class Member Variables
-  // These are initialized at startup
-  int outputPin;      // the number of the output pin
-  long OnTime;     // milliseconds of on-time
-  long Freq;    // frequency of side-tone
-
-  // These maintain the current state
-  volatile int outputState;                // outputState used to set the output
-  volatile unsigned long previousMillis;    // will store last time output was updated
-
-  // Constructor - creates a Oscillator
-  // and initializes the member variables and state
-  public:
-  Oscillator(int pin, long on, long freq)
-  {
-  outputPin = pin;
-  pinMode(outputPin, OUTPUT);
-
-  OnTime = on;
-  FreqTime = freq;
-
-  outputState = LOW;
-  previousMillis = 0;
-  }
-
-  void Update(unsigned long currentMillis)
-  {
-    if((outputState == HIGH) && (currentMillis - previousMillis >= OnTime))
-    {
-      outputState = LOW;  // Turn it off
-      previousMillis = currentMillis;  // Remember the time
-      digitalWrite(outputPin, outputState);  // Update the actual output
-    }
-    else if ((outputState == LOW) && (currentMillis - previousMillis >= FreqTime))
-    {
-      outputState = HIGH;  // turn it on
-      previousMillis = currentMillis;   // Remember the time
-      digitalWrite(outputPin, outputState);   // Update the actual output
-    }
-  }
-};

 // configuration switcher
 int Trinket     = 1;
@@ -59,11 +16,22 @@
 int interToneLength = ditLength;
 int interLetterLength = dahLength;
 int interWordLength = 7 * ditLength;
+boolean iambic = false; // Don't use this yet. There is a timing issue to figure out

-// Key inputs
+// Play() setup
+// map dit to TRUE and dah to FALSE for use in play
+boolean dit = true;
+boolean dah = false;
+boolean last;
+unsigned long now;
+unsigned long interToneLockTimer;
+
+// Key inputs and
+// sound output. Can be a piezo buzzer, speaker (with amp) or 3mm trs or trrs jack
 if (Board == Uno) {
   int ditPin = 2; // Uno 2 has hardware interrupt
   int dahPin = 3; // Uno 3 has hardware interrupt
+  int speakerPin = 4; // Digital pin 4 on uno is basic PWM
 }

 // Trinket and Trinket Pro only have 1 hardware interrupt
@@ -71,28 +39,14 @@
 if (Board == Trinket) {
   int ditPin = 1; // PB1
   int dahPin = 2; // PB2
+  int speakerPin = 0;
 }

 if (Board == TrinketPro) {
   int ditPin = 9;   // PB1
   int dahPin = 10;  // PB2
-}
-
-// sound output. Can be a piezo buzzer, speaker (with amp) or 3mm trs or trrs jack
-if (Board == Uno) {
-  int speakerPin = 4; // Digital pin 4 on uno is basic PWM
-}
-
-if (Board == Trinket) {
-  int speakerPin = 0;
-}
-
-if (Board == TrinketPro) {
   int speakerPin = 9; // Digital pin 9 on Trinket pro should be high speed PWM
 }
-
-// instantiate an oscillator (One for dits and one for dahs? TBD)
-Oscillator output1(speakerPin, ditLength, sideToneFreq);

 // for pin change interrupts we need the following
 void InitialiseInterruptTrinket(){
@@ -109,16 +63,53 @@
   sei();    // turn interrupts back on
 }

+void playDit() {
+  now = millis();
+  if (now > interToneLockTimer) {
+    tone(speakerPin, sideToneFreq, ditLength);
+  }
+  interToneLockTimer = millis() + interToneLength;
+  last = dit;
+}
+
+void playDah() {
+  now = millis();
+  if (now > interToneLockTimer) {
+    tone(speakerPin, sideToneFreq, dahLength);
+  }
+  interToneLockTimer = millis() + interToneLength;
+  last = dah;
+}
+
+void play(sym) {
+  if (sym) {
+    playDit();
+  } else {
+    playDah();
+  }
+}
+
+void diDah() {
+  if (digitalRead(ditPin)==0 && digitalRead(dahPin)==0) {
+    play(!last);
+    pause();  // FIXME. How are you going to handle the timing
+              // between this pause and the lock in play()?
+  }
+}
+
 void setup()
 {
+  pinMode(ditPin, INPUTPULLUP);
+  pinMode(dahPin, INPUTPULLUP);
+
   if (Board = Uno) {
     // set up ditPin to read ditButton on regular Arduinos with 2 hardware interrups
     pinMode(ditPin, INPUT_PULLUP);
-    attachInterrupt(0, PlayDit, FALLING);
+    attachInterrupt(digitalPinToInterrupt(0), playDit, LOW);

     // set up dahPin to read dahButton on regular Arduinos with 2 hardware interrups
     pinMode(dahPin, INPUT_PULLUP);
-    attachInterrupt(1, PlayDah, FALLING);
+    attachInterrupt(digitalPinToInterrupt(1), playDah, LOW);
   }

   if (Board == Trinket) {
@@ -130,8 +121,13 @@
     //always be the same interrupt routine

     ISR(PCINT_vect) {
-    if (digitalRead(ditPin)==0)  Serial.println("dit");
-    if (digitalRead(dahPin)==0)  Serial.println("dah");
+      if (iambic) {
+        diDah(); // pin detection built into diDah()
+      } else if {
+        (digitalRead(ditPin)==0)  play(dit);
+      } else if {
+        (digitalRead(dahPin)==0)  play(dah);
+      }
     }
   }

@@ -144,31 +140,17 @@
     //always be the same interrupt routine

     ISR(PCINT0_vect) {
-    if (digitalRead(ditPin)==0)  Serial.println("dit");
-    if (digitalRead(dahPin)==0)  Serial.println("dah");
+    if (iambic) {
+        diDah();
+      } else if {
+        (digitalRead(ditPin)==0)  play(dit);
+      } else if {
+        (digitalRead(dahPin)==0)  play(dah);
+      }
     }
   }
 }

-/*
-This is vestigial. I may need the update stuff
-as a reminder for the callback to play.
-Once I'm done with those I should delete this.
-
-// Interrupt is called once a millisecond,
-SIGNAL(TIMER0_COMPA_vect)
-{
-  unsigned long currentMillis = millis();
-
-  // if(digitalRead(2) == HIGH)
-  {
-     output1.Update(currentMillis);
-  }
-
-  output2.Update(currentMillis);
-  output3.Update(currentMillis);
-}
- */
 void loop()
 {
 }


Setting up Marquee Music functionality

Setting up Marquee Music functionality

--- color_organ_ledstrip/color_organ_ledstrip.ino
+++ color_organ_ledstrip/color_organ_ledstrip.ino
@@ -7,15 +7,14 @@
 int strobePin=2;
 int resetPin=3;
 int spectrumValue[7];
-int filter=100;
+int filter=90;
 int iteration = 0;
 int marqueeOffset = 0;
+bool forward = true;
+int color = 7;

 void setup(){
-
-  //Serial.begin(9600);
-
   strip.begin();
   strip.show();

@@ -26,140 +25,104 @@
   digitalWrite(strobePin, HIGH);
 }

-void setColors(int bulbsInSet, int totalLEDs) {
-  switch(bulbsInSet){
-    case 7:
-      seven(totalLEDs);
-      break;
-    case 4:
-      four(totalLEDs);
-      break;
-    case 3:
-      three(totalLEDs);
-      break;
-    case 2:
-      two(totalLEDs);
-      break;
-    default:
-      three(totalLEDs);
-      break;
-  }
-}
-
-void two(int totalLEDs) {
-  for (int i = 0; i < totalLEDs; i++){
-    if (i == 0 || (i % 2) == 0) {
-      /* position 1 on strip - Red */
-      strip.setPixelColor(i, spectrumValue[0], spectrumValue[1], spectrumValue[2]);
-    } else {
-      /* position 2 on strip - Blue */
-      strip.setPixelColor(i, spectrumValue[6], spectrumValue[5], spectrumValue[4]);
-    }
+void marqueeMusic(int totalLEDs, int speedFactor) {
+  if ((iteration % speedFactor) == 0) {
+    marqueeOffset++;
   }

-  strip.show();
-}
+  int localOffset = (marqueeOffset % 3);
+
+  for (int i = 0; i < totalLEDs; i++){
+    //if (i > 2) {
+    if (i == 0 || (i % 3) == 0) {
+      /* position 1 on strip */
+      if (i == 0 && localOffset > 0) {
+        if (localOffset == 1) {
+          // Blue
+          strip.setPixelColor(i, 0, 0, ((spectrumValue[4]+spectrumValue[5]+spectrumValue[6])/3));
+        } else {
+          // Green
+         strip.setPixelColor(i, 0, ((spectrumValue[1]+spectrumValue[3])/2), 0);
+        }
+      }

-void three(int totalLEDs) {
-  for (int i = 0; i < totalLEDs; i++){
-    if (i == 0 || (i % 3) == 0) {
-      /* position 1 on strip - Red */
-      strip.setPixelColor(i, spectrumValue[4], spectrumValue[2], spectrumValue[0]);
+      //Red
+      strip.setPixelColor(i + localOffset, ((spectrumValue[0]+spectrumValue[2])/2), 0, 0);
     } else if (i == 1 || (i % 3) == 1) {
-      /* position 2 on strip - Green */
-      strip.setPixelColor(i, spectrumValue[1], spectrumValue[5], spectrumValue[3]);
+      /* position 2 on strip */
+      if (i == 1 && localOffset > 0) {
+        if (localOffset == 1) {
+          // Red
+          strip.setPixelColor(i, ((spectrumValue[0]+spectrumValue[2])/2), 0, 0);
+        } else {
+          // Blue
+          strip.setPixelColor(i, 0, 0, ((spectrumValue[4]+spectrumValue[5]+spectrumValue[6])/3));
+        }
+      }
+
+      //Green
+      strip.setPixelColor(i + localOffset, 0, ((spectrumValue[1]+spectrumValue[3])/2), 0);
     } else {
-      /* position 3 on strip - Blue */
-      strip.setPixelColor(i, spectrumValue[2], spectrumValue[4], spectrumValue[6]);
-    }
-  }
+      /* position 3 on strip */
+      if (i == 2 && localOffset > 0) {
+        if (localOffset == 1) {
+          // Green
+          strip.setPixelColor(i, 0, ((spectrumValue[1]+spectrumValue[3])/2), 0);
+        } else {
+          // Red
+          strip.setPixelColor(i, ((spectrumValue[0]+spectrumValue[2])/2), 0, 0);
+        }
+      }

-  strip.show();
-}
-
-void four(int totalLEDs) {
-  for (int i = 0; i < totalLEDs; i++){
-    if (i == 0 || (i % 3) == 0) {
-      /* position 1 on strip - Red */
-      strip.setPixelColor(i, spectrumValue[1], 0, 0);
-    } else if (i == 1 || (i % 3) == 1) {
-      /* position 2 on strip - Green */
-      strip.setPixelColor(i, 0, ((spectrumValue[2] + spectrumValue[3]) / 2), 0);
-    } else {
-      /* position 3 on strip - Blue */
-      strip.setPixelColor(i, 0, 0, ((spectrumValue[4] + spectrumValue[5] + spectrumValue[6]) / 3));
-    }
-  }
-
-  strip.show();
-}
-
-void seven(int totalLEDs) {
-  for (int i = 0; i < totalLEDs; i++){
-    if (i == 0 || (i % 7) == 0) {
-      /* position 1 on strip */
-      strip.setPixelColor(i, spectrumValue[0], 0, 0);
-    } else if (i == 1 || (i % 7) == 1) {
-      /* position 2 on strip */
-      strip.setPixelColor(i, 0, spectrumValue[1], 0);
-    } else if (i == 2 || (i % 7) == 2) {
-      /* position 3 on strip */
-      strip.setPixelColor(i, 0, 0, spectrumValue[2]);
-    } else if (i == 3 || (i % 7) == 3) {
-      /* position 4 on strip */
-      strip.setPixelColor(i, spectrumValue[3], 0, 0);
-    } else if (i == 4 || (i % 7) == 4) {
-      /* position 5 on strip */
-      strip.setPixelColor(i, 0, spectrumValue[4], 0);
-    } else if (i == 5 || (i % 7) == 5) {
-      /* position 6 on strip */
-      strip.setPixelColor(i, 0, 0, spectrumValue[5]);
-    } else {
-      /* position 7 on strip */
-      strip.setPixelColor(i, spectrumValue[6], 0, 0);
-    }
-  }
-
-  strip.show();
-}
-
-void threeMarquee(int totalLEDs) {
-  if (iteration == 10) {
-    /* ensure that we only change the offset once every 100 iterations, so that you can see the marquee effect */
-    iteration = 0;
-
-    if (marqueeOffset < totalLEDs) {
-      /* we can only offset the count up to the total number of LEDs we're processing */
-      marqueeOffset++;
-    } else {
-      marqueeOffset = 0;
-    }
-  }
-
-  /* Hello world test */
-
-  for (int i = 0; i < totalLEDs; i++){
-    int ledPosition = i + marqueeOffset;
-
-    if (ledPosition > totalLEDs) {
-      ledPosition = ledPosition - totalLEDs;
-    }
-
-    if (ledPosition == 0 || (ledPosition % 3) == 0) {
-      /* position 1 on strip - Red */
-      strip.setPixelColor(ledPosition, spectrumValue[0], 0, 0);
-    } else if (ledPosition == 1 || (ledPosition % 3) == 1) {
-      /* position 2 on strip - Green */
-      strip.setPixelColor(ledPosition, 0, ((spectrumValue[1]+spectrumValue[2])/2), 0);
-    } else {
-      /* position 3 on strip - Blue */
-      strip.setPixelColor(ledPosition, 0, 0, ((spectrumValue[3]+spectrumValue[4]+spectrumValue[5]+spectrumValue[6])/4));
+      // Blue
+      strip.setPixelColor(i + localOffset, 0, 0, ((spectrumValue[4]+spectrumValue[5]+spectrumValue[6])/3));
     }
   }

   strip.show();

   iteration++;
+}
+
+void bouncingRainbow() {
+  if ((color % 7) == 0) {
+    strip.setPixelColor(iteration, 255, 0, 0);
+  } else if ((color % 7) == 1) {
+    strip.setPixelColor(iteration, 255, 127, 0);
+  } else if ((color % 7) == 2) {
+    strip.setPixelColor(iteration, 255, 255, 0);
+  } else if ((color % 7) == 3) {
+    strip.setPixelColor(iteration, 0, 255, 0);
+  } else if ((color % 7) == 4) {
+    strip.setPixelColor(iteration, 0, 0, 255);
+  } else if ((color % 7) == 5) {
+    strip.setPixelColor(iteration, 75, 0, 130);
+  } else {
+    strip.setPixelColor(iteration, 139, 0, 255);
+  }
+
+  if (forward) {
+    strip.setPixelColor(iteration - 1, 0, 0, 0);
+  } else {
+    strip.setPixelColor(iteration + 1, 0, 0, 0);
+  }
+
+  strip.show();
+
+  if (iteration == 59) {
+    forward = false;
+    color++;
+  } else if (iteration == 0 && color != 7) {
+    forward = true;
+    color++;
+  }
+
+
+  if (forward) {
+    iteration++;
+  } else {
+    iteration--;
+  }
 }

 void loop(){
@@ -171,13 +134,10 @@
     spectrumValue[i]=analogRead(analogPin);
     spectrumValue[i]=constrain(spectrumValue[i], filter, 500);
     spectrumValue[i]=map(spectrumValue[i], filter,500,0,255);
-    //Serial.print(spectrumValue[i]);
-    //Serial.print(" ");
     digitalWrite(strobePin, HIGH);
   }

-  //setColors(7, 60);
-  threeMarquee(60);
+  marqueeMusic(60, 5);
 }


speedo.ino : changed some val names to refelect that it is a hall sensor not a reed switch

--- speedo/speedo.ino
+++ speedo/speedo.ino
@@ -16,7 +16,7 @@
 //max speed of 35mph =~ 616inches/second
 //max rps =~7.25

-#define reed A0//pin connected to read switch
+#define hallSensor A0 //pin connected to hall sensor

 //storage variables
 int reedVal;
@@ -33,7 +33,7 @@

   reedCounter = maxReedCounter;
   circumference = 2*3.14*radius;
-  pinMode(reed, INPUT);
+  pinMode(hallSensor, INPUT);

   // TIMER SETUP- the timer interrupt allows precise timed measurements of the reed switch
   //for more info about configuration of arduino timers see http://arduino.cc/playground/Code/Timer1
@@ -60,8 +60,8 @@

 ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
-  reedVal = digitalRead(reed);//get val of A0
-  if (reedVal){//if reed switch is closed
+  hallVal = analogRead(hallSensor);//get val of A0
+  if (reedVal > 520 && reedVal < 575){  // if sensor value is above 520 (510 is value when no magnetic field) and less than 575 (575 is the max value when wheel is parked)
     if (reedCounter == 0){//min time between pulses has passed
       mph = (56.8*float(circumference))/float(timer);//calculate miles per hour
       timer = 0;//reset timer