working state with pin-sleep mode

working state with pin-sleep mode

--- WeatherStation/WeatherStation.ino
+++ WeatherStation/WeatherStation.ino
@@ -25,7 +25,10 @@
 void setup() {
   pinMode( LEDPIN , OUTPUT);
   pinMode( XBEESLEEPPIN , OUTPUT);
-
+
+/* digitalWrite(XBEESLEEPPIN, LOW);  //Wake UP XBEE
+*/
+
   Serial.begin(57600);
   dht.setup(DHTPIN);

@@ -41,16 +44,48 @@
     Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
     while(1);
   }
+
+  configureLightSensor();
+
+  //Delay for 30 sec at startup after a manual RST to allow for the wireless programmer to transition
+  // the board into the bootloader, or change other XBEE settings remotely, c.f. disable pin sleep mode to keep the XBEE up
+  blink(30, 500);
+}
+
+void blink(int times){
+  blink(times, 250);
+}
+
+void blink(int times, int delayValue){
+   for(int i=0; i<times; i++){
+      digitalWrite(LEDPIN, LOW);
+      delay(delayValue);
+      digitalWrite(LEDPIN, HIGH);
+      delay(delayValue);
+   }
 }

 void loop() {
-  digitalWrite(LEDPIN, HIGH);
   digitalWrite(XBEESLEEPPIN, LOW);  //Wake UP XBEE
-
-  configureLightSensor();
-
+  delay(2000);
+
+  blink(25, 50);
+  digitalWrite(LEDPIN, LOW);
+  delay(1000);
+
+  digitalWrite(LEDPIN, HIGH);
+
+  sample += 1;
+
+  if (!pingCoordinator()){          //check if xbee woke up and got its association address. blink LED rapidly and quit loop otherwise
+    blink(10);
+    digitalWrite(LEDPIN, LOW);
+    sleep(10000);
+    return;
+  }
+
   Serial.print("{'_sensor': 'weather', '_sample': {'_id':");
-  Serial.print(sample++);
+  Serial.print(sample);
   Serial.print(", ");

   float h = dht.getHumidity();
@@ -69,14 +104,9 @@
     Serial.print(", ");
    }
   }
-//  else {
-//   Serial.println("Failed to read from DHT");
-//  }
-

   sensors_event_t event;
-  bmp.getEvent(&event);
-
+  bmp.getEvent(&event);
   Serial.print("'AtmoPressure':");
   if (event.pressure)
   {
@@ -99,10 +129,64 @@
   }
   Serial.println("}}");

+  delay(2000);   //Delay at the end to allow xbee to flush its send buffer
+
   digitalWrite(LEDPIN, LOW);
   digitalWrite(XBEESLEEPPIN, HIGH);  //Put XBEE to sleep

-  sleep(30000);
+  sleep(60000);
+}
+
+
+int pingCoordinator(void){
+
+    for(int i = 0; i<10; i++){
+      blink(i);
+      while(getCh() != NULL) ;       //Drain any pending chars on the serial.
+      Serial.println("@PING");
+      int c=0;
+      while(Serial.available()<2 && c++<10){
+          delay(400);
+          blink(2, 50);
+      }
+      if (getCh()=='O' && getCh()=='K'){
+          //while(getCh() != NULL) ;       //Drain any pending messages on the serial.
+          return 1;
+      }
+      delay(500);
+    }
+    return 0;
+}
+/*
+    Wake up the XBEE from sleep.
+    For hibernation periods longer than 10sec, or so, XBee will have to re-join the PAN.
+    Use ATMY command to confirm that the node got its network address before attempting to send data to DH/DL
+*/
+/*
+int wakeUpXbee(void){
+    while(getCh() != NULL) ;       //Drain any pending messages on the serial.
+
+    Serial.print("+++");
+    delay(500);
+    if (getCh()=='O' && getCh()=='K'){
+        for(int j=0; j<5; j++){
+          Serial.println("ATMY");
+          if (!(getCh()=='F' && getCh()=='F' && getCh()=='F' & getCh()=='E')){
+             Serial.println("ATCN");  //Got non-FFFE address. Exit command mode immediately.
+             return 1;
+          }
+          delay(1000);
+        }
+    }
+  return 0;
+}
+*/
+
+char getCh(){
+  if (Serial.available()){
+    return Serial.read();
+  }
+  return NULL;
 }

 void configureLightSensor(void)


Add optional debug output to terminal

Add optional debug output to terminal

--- software/XTendPayloadTeensy/XTendPayloadTeensy.ino
+++ software/XTendPayloadTeensy/XTendPayloadTeensy.ino
@@ -1,8 +1,11 @@
 /*
+ * Serial:  Serial Monitor through USB
  * Serial1: GPS and LOGGER
  * Serial2: RF IN/OUT
  */
 #include <TimeLib.h>
+const boolean DEBUG = false;
+const int GPSLEN = 100; //max length of GPS output to be sent
 char pkt_buffer[200];
 boolean sentencePending, sentenceRdy, sentenceBufRdy;
 boolean txFlag, help;
@@ -18,6 +21,7 @@
 //const int pin2 = 2;

 void setup(){
+  Serial.begin(9600);
   Serial1.begin(9600);
   Serial2.begin(9600);
   setSyncProvider( getTeensy3Time );
@@ -25,7 +29,7 @@
   sentenceRdy = false;
   sentence[0] = 0;
   sentenceIndex = 0;
-  txTimer.begin(transmit, 10000);
+  txTimer.begin(transmit, 10000000);
   pinMode(5,INPUT_PULLUP);
   while( !Serial1 );
   while( !Serial2 );
@@ -39,12 +43,17 @@
     }
     sentenceBufRdy = true;
     sentenceRdy = false;
+    if ( DEBUG ) {
+      Serial.print( " BUF:" );Serial.print( sentence );
+      Serial.print( "BUF2:" );Serial.print( sentenceBuf );
+    }
   }
   //RX section, READ from RF
   char lastChar;
   while(Serial2.available()){
     lastChar = Serial2.read();
     if( lastChar == 10 && msgIn != "" ){ //if I get a new line
+      Serial.print( "RX " );digitalClockDisplay( now() );
       Serial.println( msgIn );
       int rcvdNum = (int)msgIn.substring(1 + msgIn.indexOf(' ')).toInt();
       boolean ok = false;
@@ -67,6 +76,7 @@
   }
   //TX
   if ( txFlag ) {
+    Serial.print("TX:");digitalClockDisplay( now() );
     Serial1.print( "TX:" ); // Identifies transmitted packet for log.
     sendData();
     numb++;
@@ -80,6 +90,7 @@
   char c;
   if ( Serial1.available() ) {
     c = Serial1.read();
+    if ( DEBUG ) Serial.write( c );
     if ( !sentenceRdy ) {
       if ( c == 36 ) { //36 is '$', start of GPS statement - KN
         sentenceIndex = 0;


Logic for checking positions

Logic for checking positions

--- SensorShirt/SensorShirt.ino
+++ SensorShirt/SensorShirt.ino
@@ -2,13 +2,38 @@
   Sensor Shirt
   Kylie Dale and Michael Guida
  */
+const int backPin = 0;
+const int shoulderPin = 1;
+const int underarmPin = 2;
+
+int backValue = null;
+int shoulderValue = null;
+int underarmValue = null;
+
+String pos = "Plank";

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

 void loop() {
-  int sensorValue = analogRead(A0);
-  Serial.println(sensorValue);
+  backValue = analogRead(backPin);
+  shoulderValue = analogRead(shoulderPin);
+  underarmValue = analogRead(underarmValue);
+
+  println(checkPosition());
+
   delay(300);
 }
+
+boolean checkPosition(){
+  case(pos) {
+    case "Plank":
+      if (armFwdRight90() && backStraight()){
+        return true;
+      } else { return false; }
+    default:
+      println("Invalid Position");
+      break;
+  }
+}


Kommentare ergänzt

Kommentare ergänzt

--- Software/servo_sweep_90steps/servo_sweep_90steps.ino
+++ Software/servo_sweep_90steps/servo_sweep_90steps.ino
@@ -14,12 +14,12 @@

 void loop()
 {
-  myservo.write(90);
+  myservo.write(90); // central position, Servo library assumes full 0-180° deflection
   delay(1000);
-  myservo.write(180);
+  myservo.write(180); // extended one side
   delay(1000);
   myservo.write(90);
   delay(1000);
-  myservo.write(0);
+  myservo.write(0); // extended other side
   delay(1000);
 }


Improve and prep

Improve and prep

--- Arduino/sensors/sensors.ino
+++ Arduino/sensors/sensors.ino
@@ -35,19 +35,55 @@
 #include "libraries/ITG3701/ITG3701.h"                    // ITG3701
 #include <Wire.h>                                         // I2C
 #include <SPI.h>                                          // SPI
+#include <SdFat.h>                                        // SD Card

 //// Object declarations ////
 LSM9DS1           IMU;    // Declare 9DOF object  (addr 0x1E, 0x6B)
 Adafruit_ADS1115  ADS;    // Declare ADC object   (addr 0x48)
 ITG3701 hDPS(ITG3701_ADDRESS);  // high DPS
+SdFat SD;                 // SD Card
+SdFile file;

 //// Defines ////
 #define LSM9DS1_M   0x1E
 #define LSM9DS1_AG  0x6B
 #define ITG3701_ADDRESS 0x68
+#define SD_CS_PIN 10
+#define FILE_BASE_NAME "Data"
+
+// Write data header.
+void writeHeader() {
+  file.print(F("ms"));
+  file.print(F(",GX"));
+  file.print(F(",GY"));
+  file.print(F(",GZ"));
+  file.print(F(",AX"));
+  file.print(F(",AY"));
+  file.print(F(",AZ"));
+  file.print(F(",MX"));
+  file.print(F(",MY"));
+  file.print(F(",MZ"));
+  file.print(F(",SolarV"));
+  file.print(F(",SolarI1"));
+  file.print(F(",SolarI2"));
+  file.print(F(",HAZ"));
+  file.print(F(",HGX"));
+  file.print(F(",HGY"));
+  file.print(F(",HGZ"));
+  file.println();
+}
+
+const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
+char fileName[13] = FILE_BASE_NAME "00.csv";
+unsigned long last_time = 0;
+unsigned long last_tx = 0;

 void setup() {
-  Serial.begin(19200); // Intialize serial line
+  Serial.begin(9600); // Intialize serial line
+  Serial.println("Loading");
+  pinMode(10, OUTPUT);
+  pinMode(14, OUTPUT);
+  SD.begin(SD_CS_PIN, SPI_FULL_SPEED);
   Wire.begin();
   IMU.settings.device.commInterface = IMU_MODE_I2C;
   IMU.settings.device.mAddress      = LSM9DS1_M;
@@ -55,47 +91,109 @@
   hDPS.begin(ITG3701::GFS_4000DPS, ITG3701::GODR_380Hz, ITG3701::GBW_highest);  // Initialize Gyro
   IMU.begin();          // Initialize the 9DOF
   ADS.begin();          // Initialzie the ADC
+
+  while (SD.exists(fileName)) {
+    if (fileName[BASE_NAME_SIZE + 1] != '9') {
+      fileName[BASE_NAME_SIZE + 1]++;
+    } else if (fileName[BASE_NAME_SIZE] != '9') {
+      fileName[BASE_NAME_SIZE + 1] = '0';
+      fileName[BASE_NAME_SIZE]++;
+    }
+  }
+  file.open(fileName, O_CREAT | O_WRITE | O_EXCL);
+
+  // Write data header.
+  writeHeader();
 }

 void loop() {
-  Serial.println();
-  Serial.println("=== 9DOF ===");
-  Serial.println("== Gyroscope ==");
+  int data[16];
+
+  digitalWrite(14, LOW);
+
   IMU.readGyro();
-  Serial.print(IMU.gx);
-  Serial.print(", ");
-  Serial.print(IMU.gy);
-  Serial.print(", ");
-  Serial.println(IMU.gz);
-  Serial.println("== Accelerometer ==");
   IMU.readAccel();
-  Serial.print(IMU.ax);
-  Serial.print(", ");
-  Serial.print(IMU.ay);
-  Serial.print(", ");
-  Serial.println(IMU.az);
-  Serial.println("== Magnetometer ==");
   IMU.readMag();
-  Serial.print(IMU.mx);
-  Serial.print(", ");
-  Serial.print(IMU.my);
-  Serial.print(", ");
-  Serial.println(IMU.mz);
-  Serial.println("=== ADC ===");
-  Serial.println("== Solar Voltage ==");
-  Serial.println(ADS.readADC_SingleEnded(0));
-  Serial.println("== Solar Current 1 ==");
-  Serial.println(ADS.readADC_SingleEnded(1));
-  Serial.println("== Solar Current 2 ==");
-  Serial.println(ADS.readADC_SingleEnded(2));
-  Serial.println("== High G Accelerometer ==");
-  Serial.println(ADS.readADC_SingleEnded(3));
-  Serial.println("=== High DPS gyro ===");
   hDPS.updateGyro();
-  Serial.print(hDPS.x);
-  Serial.print(", ");
-  Serial.print(hDPS.y);
-  Serial.print(", ");
-  Serial.println(hDPS.z);
-  delay(250);
+
+  data[0] = IMU.gx;
+  data[1] = IMU.gy;
+  data[2] = IMU.gz;
+
+  data[3] = IMU.ax;
+  data[4] = IMU.ay;
+  data[5] = IMU.az;
+
+  data[6] = IMU.mx;
+  data[7] = IMU.my;
+  data[8] = IMU.mz;
+
+  data[9] = ADS.readADC_SingleEnded(0);
+
+  digitalWrite(14, HIGH);
+
+  data[10] = ADS.readADC_SingleEnded(1);
+  data[11] = ADS.readADC_SingleEnded(2);
+  data[12] = ADS.readADC_SingleEnded(3);
+
+  data[13] = hDPS.x;
+  data[14] = hDPS.y;
+  data[15] = hDPS.z;
+
+//  Serial.println();
+//  Serial.println("Data");
+//  Serial.println("=== 9DOF ===");
+//  Serial.println("== Gyroscope ==");
+//  IMU.readGyro();
+//  Serial.print(IMU.gx);
+//  Serial.print(", ");
+//  Serial.print(IMU.gy);
+//  Serial.print(", ");
+//  Serial.println(IMU.gz);
+//  Serial.println("== Accelerometer ==");
+//  IMU.readAccel();
+//  Serial.print(IMU.ax);
+//  Serial.print(", ");
+//  Serial.print(IMU.ay);
+//  Serial.print(", ");
+//  Serial.println(IMU.az);
+//  Serial.println("== Magnetometer ==");
+//  IMU.readMag();
+//  Serial.print(IMU.mx);
+//  Serial.print(", ");
+//  Serial.print(IMU.my);
+//  Serial.print(", ");
+//  Serial.println(IMU.mz);
+//  Serial.println("=== ADC ===");
+//  Serial.println("== Solar Voltage ==");
+//  Serial.println(ADS.readADC_SingleEnded(0));
+//  Serial.println("== Solar Current 1 ==");
+//  Serial.println(ADS.readADC_SingleEnded(1));
+//  Serial.println("== Solar Current 2 ==");
+//  Serial.println(ADS.readADC_SingleEnded(2));
+//  Serial.println("== High G Accelerometer ==");
+//  Serial.println(ADS.readADC_SingleEnded(3));
+//  Serial.println("=== High DPS gyro ===");
+//  hDPS.updateGyro();
+//  Serial.print(hDPS.x);
+//  Serial.print(", ");
+//  Serial.print(hDPS.y);
+//  Serial.print(", ");
+//  Serial.println(hDPS.z);
+//  delay(250);
+
+  last_time = millis();
+  file.open(fileName, FILE_WRITE);
+  file.print(last_time);
+  for (uint8_t i = 0; i < 16; i++) {
+    file.write(',');
+    file.print(data[i]);
+  }
+  file.println();
+  file.close();
+  if(millis() - last_tx > 5000){
+    Serial.write((uint8_t*)data, sizeof(data));
+    last_tx = millis();
+  }
+  while(millis() - last_time < 50);
 }


Got fonts working, started widget classes, did some other things.

--- TUI.ino
+++ TUI.ino
@@ -1,20 +1,30 @@
-double x = 0;
-double y = 0;

+#include "UI.h"
+#include "UILabel.h"

 void setup() {
-  // put your setup code here, to run once:
-  setPinMode(11,HIGH);
-  setPinMode(12,HIGH);
+    analogReadAveraging(32);
+    analogReadResolution(ANALOG_INPUT_BITS);
+    Serial.begin(9600);
+    Wire.begin();
+
+
+
+    Touch::Setup();
+    Screen::Setup();
+    Screen::SetRotation(3);
 }

 void loop() {
   // put your main code here, to run repeatedly:
-
-  x = analogRead(A12);
-  y = analogRead(A13);
+  Touch::Update();
+  Int2 pos = Touch::Position();
+  Serial.print(pos.x);
+  Serial.print(" ");
+  Serial.println(pos.y);
+  delay(10);

-  Serial.print(x);
-  Serial.print(" ");
-  Serial.println(y);
+  UILabel widg = UILabel("stuff",UIP,Int2(pos.x,pos.y),Int2(200,140));
+  widg.Draw();
+
 }


use white light for wand vent light, in normal fire just stop the track. The tail happens if firing a lot.

--- Arduino/Neutrino_Wand/Neutrino_Wand.ino
+++ Arduino/Neutrino_Wand/Neutrino_Wand.ino
@@ -265,7 +265,7 @@
     if( startup == true && safety_switch == 1 ){
       if( venting == false && powerBooted == true ){
         setWandLightState(1, 2, 0);    //  set back light orange
-        setWandLightState(2, 3, 0);    //  set body led blue
+        setWandLightState(2, 1, 0);    //  set body led white
       }else{
         setWandLightState(1, 4, 0);    //  set back light off
         setWandLightState(2, 4, 0);    //  set body led off
@@ -350,8 +350,10 @@
               playAudio(endTrack, playing);
             }
           } else {
-            // otherwise play the standard power down track
-            playAudio(endTrack, playing);
+            // otherwise just shutdown the stream without the powerdown
+            if (playing == 0) {
+              sfx.stop();
+            }
           }
         }
       }


Fixing up the example as it wasn't correct to the latest

--- examples/example.ino
+++ examples/example.ino
@@ -13,18 +13,18 @@

 void setup()
 {
-	Serial.begin(9600);
-	/* Get our time sync started */
-	rtc.begin(&UDPClient, "pool.ntp.org");
-	rtc.setTimeZone(CST_OFFSET);
-	/* Set our position and a default timezone value */
-	sun.setPosition(LATITUDE, LONGITUDE, DST_OFFSET);
+    Serial.begin(9600);
+    /* Get our time sync started */
+    rtc.begin(&UDPClient, "pool.ntp.org");
+    rtc.setTimeZone(CST_OFFSET);
+    /* Set our position and a default timezone value */
+    sun.setPosition(LATITUDE, LONGITUDE, DST_OFFSET);
 }

 void loop()
 {
-	double sunrise;
-	double sunset;
+    double sunrise;
+    double sunset;
     double civilsunrise;
     double civilsunset;
     double astrosunrise;
@@ -32,38 +32,38 @@
     double nauticalsunrise;
     double nauticalsunset;

-	/* Check to see if we have a valid time sync yet, if not, just wait a bit and loop */
-	if (!rtc.hasSynced()) {
-		Particle.publish("No time sync yet");
-		delay(5000);
-		return;
-	}
-	else {
-		/* Get the current time, and set the Sunrise code to use the current date */
-		currentTime = rtc.now();
-		sun.setCurrentDate(rtc.year(currentTime), rtc.month(currentTime), rtc.day(currentTime));
-		/* Check to see if we need to update our timezone value */
-		if (rtc.isUSDST(currentTime))
-			sun.setTZOffset(DST_OFFSET);
-		else
-			sun.setTZOffset(CST_OFFSET);
-	}
+    /* Check to see if we have a valid time sync yet, if not, just wait a bit and loop */
+    if (!rtc.hasSynced()) {
+    	Particle.publish("No time sync yet");
+    	delay(5000);
+    	return;
+    }
+    else {
+    	/* Get the current time, and set the Sunrise code to use the current date */
+    	currentTime = rtc.now();
+    	sun.setCurrentDate(rtc.year(currentTime), rtc.month(currentTime), rtc.day(currentTime));
+    	/* Check to see if we need to update our timezone value */
+    	if (rtc.isUSDST(currentTime))
+    		sun.setTZOffset(DST_OFFSET);
+    	else
+    		sun.setTZOffset(CST_OFFSET);
+    }

-	sunrise = sun.calcSunriseLocal();
-	sunset = sun.calcSunsetLocal();
-	civilsunrise = sun.calcCivlSunriseLocal();
-	civilsunset = sun.calcCivilSunsetLocal();
-	nauticalsunrise = sun.calcNauticalSunriseLocal();
-	nauticalsunset = sun.calcNauticalSunsetLocal();
-	astrosunrise = sun.calcAstronomicalSunriseLocal();
-	astrosunset = sun.calcAstronomicalSunsetLocal();
+    sunrise = sun.calcSunrise();
+    sunset = sun.calcSunset();
+    civilsunrise = sun.calcCivilSunrise();
+    civilsunset = sun.calcCivilSunset();
+    nauticalsunrise = sun.calcNauticalSunrise();
+    nauticalsunset = sun.calcNauticalSunset();
+    astrosunrise = sun.calcAstronomicalSunrise();
+    astrosunset = sun.calcAstronomicalSunset();

-	Serial.print("Sunrise is ");
-	Serial.print(sunrise);
-	Serial.println(" minutes past midnight.");
-	Serial.print("Sunset is ");
-	Serial.print(sunset);
-	Serial.print(" minutes past midnight.");
-	delay(1000);
+    Serial.print("Sunrise is ");
+    Serial.print(sunrise);
+    Serial.println(" minutes past midnight.");
+    Serial.print("Sunset is ");
+    Serial.print(sunset);
+    Serial.print(" minutes past midnight.");
+    delay(1000);
 }


I came up with a way to turn on the LEDs in an iterative way.  I still need to test it out.

--- SunriseAlarm.ino
+++ SunriseAlarm.ino
@@ -10,6 +10,7 @@
 #include "RTClib.h"
 #include "AT24Cxx.h"
 #include <ClickEncoder.h>
+#include <Adafruit_NeoPixel.h>

 // 2013-04-06 TODO:  Add a temperature sensor to the lamp and if it exceeds a particular temperature, then turn it off or down
@@ -168,11 +169,11 @@
   return !(lhs == rhs);
 }

+
 ClickEncoder *encoder;
 #define ENCODER_PIN0 11
 #define ENCODER_PIN1 12

-//const int LEDpinA = 6;

 const int AlarmButton = 7;
 const int AlarmLED = 8;
@@ -180,6 +181,10 @@
 const int TimeLED = 13;
 const int OffButton = A0;
 const int AlarmEnabledButton = 5;
+
+#define NUM_LED 32
+#define LED_PIN 6
+Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LED, LED_PIN, NEO_GRB + NEO_KHZ800);

 bool alarmEnabled = true;
 bool alarmActive = false;
@@ -309,19 +314,19 @@
 }

 void turnLightOn(int currentLevel) {
-  for (int i=currentLevel ; i < maxBright ; ++i) {
-    //timer.pwm(LEDpinA,i);
-    //delay(1);
-  }
-  //digitalWrite(LEDpinA,HIGH);
-}
-
-void turnLightOff(int currentLevel) {
-  for (int i=currentLevel ; i>0 ; --i) {
-    //timer.pwm(LEDpinA,i);
-    //delay(1);
-  }
-  //digitalWrite(LEDpinA,LOW);
+  for (int16_t i=currentDimmerStep; i < totalDimmerSteps; ++i) {
+    linearBrightOfStep(i);
+    delay(1);
+  }
+  linearBrightOfStep(totalDimmerSteps);
+}
+
+void turnLightOff() {
+  for (int16_t i=currentDimmerStep; i>0 ; --i) {
+    linearBrightOfStep(i);
+    delay(1);
+  }
+  linearBrightOfStep(0u);
 }

 void waitForButtonDepress(int pin) {
@@ -337,55 +342,54 @@
 const int minLightLevel = 320;
 const int maxLightLevel = 800;

-// (a1,b1) -> f_1 -> (a2,b2) -> f_2 -> (a3,b3) -> f_3 -> (a4,b4)
-double a1 = 0.0;
-double b1 = minLightLevel;
-double a2 = thirtyminutes-10*60; // 10 minutes before
-double b2 = maxLightLevel*.30; // 30%
-double a3 = thirtyminutes-5*60; // 5 minutes before
-double b3 = maxLightLevel*.40; // 40%
-double a4 = thirtyminutes;
-double b4 = maxLightLevel;
-
-double m1 = (b2-b1)/(a2-a1);
-double c1 = (b1-m1*a1);
-double m2 = (b3-b2)/(a3-a2);
-double c2 = (b2-m2*a2);
-double m3 = (b4-b3)/(a4-a3);
-double c3 = (b3-m3*a3);
-
-// This function maps the visible range of the LED to the time interval 0 to 1800 seconds.
-// Visible range on LED at TimerOne Period of 1000us (1 kHz flicker) is [176,1008] at increment of 16.
-// Therefore the two points are (0,176) and (1800,1008) which results in a slope of 0.4622222 and a y-intercept of 176.
-// 2014-03-11:  (0,minlightLevel) -> (1800,maxLightLevel), slope = (maxLightLevel-minLightLevel)/1800
-int lastAlarmLightLevel = 0;
-int32_t linearBright(int32_t level) {
-  //int linearLevel = ceil(maxBright*1.0/(1.0+exp(-(level*1.0-maxTime*0.5)/(maxTime/16.0))));
-  //int linearLevel = level;
-  //int linearLevel = 36.787944117144235*exp(exp(level*0.00075472484480368113));
-
-  // (0,176) -> (1800,1008)
-  //int linearLevel = 0.46222222*level + 176; // linear
-  //int linearLevel = 176.0*exp(0.000969577*level); // exponential
-  //int linearLevel = 64.746781646173858*exp(exp(0.00056103794655312409*level)); // exp(exp())
-
-  //This method seems to work well for MR16 9W LED
-  int linearLevel = ((maxLightLevel-minLightLevel)/1800.0)*level+minLightLevel;
-  //This method worked well for 10W LED
-//  int linearLevel = 0;
-//  if (level < a2) {
-//    linearLevel = m1*level+c1;
-//  } else if (level < a3) {
-//    linearLevel = m2*level+c2;
-//  } else {
-//    linearLevel = m3*level+c3;
-//  }
-
-  //Serial.print("linearLevel = ");
-  //Serial.println(linearLevel);
-  lastAlarmLightLevel = linearLevel;
-  //timer.pwm(LEDpinA,lastAlarmLightLevel);
-  return linearLevel;
+uint8_t computeMinRGBLevel(int* RGB)
+{
+  uint8_t myRGB[3] = {255, 255, 255};
+  for (uint8_t i=0 ; i<3 ; ++i)
+  {
+    if (RGB[i]>0) myRGB[i] = RGB[i];
+  }
+  return min(min(myRGB[0],myRGB[1]),myRGB[2]);
+}
+
+uint8_t targetColor[3] = {255, 147, 41}; // candle
+//uint8_t targetColor[3] = {255, 255, 255}; // sun
+//uint8_t targetColor[3] = {255, 0, 0}; // red
+unsigned long millisecondsIn30Minutes = 1800000;
+uint8_t minRGBLevel = computeMinRGBLevel(targetColor);
+uint16_t totalDimmerSteps = minRGBLevel*NUM_LED;
+uint16_t currentDimmerStep = 0;
+uint8_t baseRGBColor[3] = {0u, 0u, 0u};
+uint8_t highRGBColor[3] = {0u, 0u, 0u};
+
+void linearBrightOfStep(uint16_t step)
+{
+  currentDimmerStep = step;
+  uint16_t levelForAllLEDs = step / NUM_LED;
+  uint8_t numLEDsAtHigherLevel = step % NUM_LED;
+  for (uint8_t i=0 ; i<3 ; ++i)
+  {
+    baseRGBColor[i] = (targetColor[i]*levelForAllLEDs)/minRGBLevel;
+    highRGBColor[i] = (targetColor[i]*(levelForAllLEDs+1))/minRGBLevel;
+  }
+  for (uint8_t i=0 ; i<NUM_LED ; ++i)
+  {
+    if (i < numLEDsAtHigherLevel)
+    {
+      strip.setPixelColor(i, highRGBColor[0], highRGBColor[1], highRGBColor[2]);
+    }
+    else
+    {
+      strip.setPixelColor(i, baseRGBColor[0], baseRGBColor[1], baseRGBColor[2]);
+    }
+  }
+  strip.show();
+}
+
+unsigned long linearBrightOfMilliseconds(unsigned long milliseconds)
+{
+  uint16_t = stepNumber = (totalDimmerSteps*milliseconds)/millisecondsIn30Minutes;
+  linearBrightOfStep(stepNumber);
 }

 // DONE:  Update to display 12 hr time
@@ -506,6 +510,8 @@
   pinMode(OffButton,INPUT);
   pinMode(AlarmLED, OUTPUT);
   pinMode(TimeLED, OUTPUT);
+  strip.begin();
+  strip.show(); // Initialize all pixels to 'off'
   encoder = new ClickEncoder(ENCODER_PIN0, ENCODER_PIN1, -1, 4);
   Timer1.initialize(1000);
   Timer1.attachInterrupt(timerIsr);
@@ -702,14 +708,12 @@
   unsigned long modeActive = millis();
   bool normalExit = true;
   while (debounceDigitalRead(OffButton)==HIGH) {
-//    if (digitalRead(FwdButton)==LOW) {
-//      forwardSunSet(defaultSunSetDelta);
-//      modeActive = millis();
-//    }
-//    else if (digitalRead(RewButton)==LOW) {
-//      rewindSunSet(defaultSunSetDelta);
-//      modeActive = millis();
-//    }
+    int16_t encoderDelta = encoder->getValue();
+    minutes += encoderDelta;
+    minutes = min(0,minutes);
+    matrix.print(minutes);
+    if (minutes == 0) matrix.writeDigitNum(4,0);
+    matrix.writeDisplay();
     if (static_cast<unsigned long>(millis() - modeActive) > modeInactivePeriod) {
       normalExit = false;
       break;
@@ -744,11 +748,11 @@
   finalMillis *= 1000;
   if (delta > finalMillis) {
     sunSetActive = false;
-    //digitalWrite(LEDpinA,0);
+    linearBrightOfStep(0);
   }
   else {
     double temp = -(1800.0*delta)/(finalMillis*1.0) + 1800.0;
-    linearBright(temp);
+    linearBrightOfMilliseconds(temp);
   }
 }

@@ -760,7 +764,7 @@
     int delta = (encoderDelta>0 ? 1 : -1);
     matrixBrightness = max(min(15,matrixBrightness+delta),0);
     matrix.setBrightness(matrixBrightness); // 0-15
-    //writeBrightnessToEEPROM();
+    writeBrightnessToEEPROM();
   }
 }

@@ -771,22 +775,22 @@
   else if (digitalRead(TimeButton)==LOW && debounceDigitalRead(TimeButton)==LOW) {
     setTime();
   }
-//  else if (digitalRead(OffButton)==HIGH && debounceDigitalRead(OffButton)==HIGH) {
-//    if (alarmActive) {
-//      alarmActive = false;
-//      alarmEnabled = false;
-//      turnLightOff(lastAlarmLightLevel);
-//      waitForButtonDepress(OffButton);
-//    }
-//    else if (sunSetActive) {
-//      sunSetActive = false;
-//      turnLightOff(lastSunSetLightLevel);
-//      waitForButtonDepress(OffButton);
-//    }
-//    else {
-//      setSunSet();
-//    }
-//  }
+  else if (digitalRead(OffButton)==HIGH && debounceDigitalRead(OffButton)==HIGH) {
+    if (alarmActive) {
+      alarmActive = false;
+      alarmEnabled = false;
+      turnLightOff(lastAlarmLightLevel);
+      waitForButtonDepress(OffButton);
+    }
+    else if (sunSetActive) {
+      sunSetActive = false;
+      turnLightOff(lastSunSetLightLevel);
+      waitForButtonDepress(OffButton);
+    }
+    else {
+      setSunSet();
+    }
+  }
   updateBrightness();
 //  updateLight();
   updateCurrentTime();


Increase clock range and use direct BPM to tempo conversion.

--- examples/seq/seq.ino
+++ examples/seq/seq.ino
@@ -268,7 +268,7 @@
     }
     seq_values.slew_rate = params.vals.slew_rate;

-    if(params.vals.clock_bpm < 0 || params.vals.clock_bpm > 30)
+    if(params.vals.clock_bpm < 0 || params.vals.clock_bpm > 99)
     {
       params.vals.clock_bpm = 0;
     }
@@ -429,9 +429,9 @@
               {
                 params.vals.clock_bpm = 0;
               }
-              else if(params.vals.clock_bpm > 30)
-              {
-                params.vals.clock_bpm = 30;
+              else if(params.vals.clock_bpm > 99)
+              {
+                params.vals.clock_bpm = 99;
               }
               seq_values.clock_period = bpm_to_us(params.vals.clock_bpm);
               seq_values.clock_ext = !(bool)params.vals.clock_bpm;
@@ -590,7 +590,7 @@

   unsigned long bpm_to_us(uint8_t bpm)
   {
-    return 750000 / (unsigned long)bpm;
+    return 3000000 / (unsigned long)bpm;
   }

   void display_slew_rate(int16_t x, int16_t y, uint8_t rate, DUINO_SSD1306::SSD1306Color color)


add tach logging

add tach logging

--- software/bladeBench.ino
+++ software/bladeBench.ino
@@ -38,6 +38,10 @@
 elapsedMicros testTime;
 elapsedMicros commandTime;

+elapsedMicros tachTime;
+volatile unsigned long lastTachPulse = 0;
+uint8_t pulsesPerRev = 2;
+
 elapsedMillis buttonTime;
 bool buttonRunning = false;
 bool buttonLatch = false;
@@ -163,6 +167,14 @@
 	for (unsigned int i=0; i<MAXBUFFERS; i++ ) {
 		memset(writeBuffer[i].data, 0, BUFFERSIZE+1);
 	}
+	pinMode(TACH_PIN, INPUT);
+}
+
+void tachISR() {
+	unsigned long time;
+	time = tachTime;
+	lastTachPulse = time ;
+	tachTime = tachTime - time;
 }

 void buildTest(){
@@ -176,40 +188,46 @@

 	commandBuffer[0].mode = MODE_HOLD;
 	commandBuffer[0].time = 1000;
-	commandBuffer[0].value = 1100;
-	commandBuffer[1].mode = MODE_RAMP;
-	commandBuffer[1].time = 4000;
-	commandBuffer[1].value = 2000;
-	commandBuffer[2].mode = MODE_HOLD;
-	commandBuffer[2].time = 2000;
+	commandBuffer[0].value = 1000;
+	commandBuffer[1].mode = MODE_HOLD;
+	commandBuffer[1].time = 1000;
+	commandBuffer[1].value = 1100;
+	commandBuffer[2].mode = MODE_RAMP;
+	commandBuffer[2].time = 4000;
 	commandBuffer[2].value = 2000;
 	commandBuffer[3].mode = MODE_HOLD;
-	commandBuffer[3].time = 1000;
-	commandBuffer[3].value = 1100;
+	commandBuffer[3].time = 2000;
+	commandBuffer[3].value = 2000;
 	commandBuffer[4].mode = MODE_HOLD;
 	commandBuffer[4].time = 1000;
-	commandBuffer[4].value = 1250;
+	commandBuffer[4].value = 1100;
 	commandBuffer[5].mode = MODE_HOLD;
-	commandBuffer[5].time = 1000;
-	commandBuffer[5].value = 1100;
+	commandBuffer[5].time = 2000;
+	commandBuffer[5].value = 1250;
 	commandBuffer[6].mode = MODE_HOLD;
 	commandBuffer[6].time = 1000;
-	commandBuffer[6].value = 1500;
+	commandBuffer[6].value = 1100;
 	commandBuffer[7].mode = MODE_HOLD;
-	commandBuffer[7].time = 1000;
-	commandBuffer[7].value = 1100;
+	commandBuffer[7].time = 2000;
+	commandBuffer[7].value = 1500;
 	commandBuffer[8].mode = MODE_HOLD;
 	commandBuffer[8].time = 1000;
-	commandBuffer[8].value = 1750;
+	commandBuffer[8].value = 1100;
 	commandBuffer[9].mode = MODE_HOLD;
-	commandBuffer[9].time = 1000;
-	commandBuffer[9].value = 1100;
+	commandBuffer[9].time = 2000;
+	commandBuffer[9].value = 1750;
 	commandBuffer[10].mode = MODE_HOLD;
 	commandBuffer[10].time = 1000;
-	commandBuffer[10].value = 2000;
+	commandBuffer[10].value = 1100;
 	commandBuffer[11].mode = MODE_HOLD;
-	commandBuffer[11].time = 1000;
-	commandBuffer[11].value = 1100;
+	commandBuffer[11].time = 2000;
+	commandBuffer[11].value = 2000;
+	commandBuffer[12].mode = MODE_HOLD;
+	commandBuffer[12].time = 1000;
+	commandBuffer[12].value = 1100;
+	commandBuffer[13].mode = MODE_HOLD;
+	commandBuffer[13].time = 1000;
+	commandBuffer[13].value = 1000;

 }
@@ -222,6 +240,7 @@
 	int commandValue;
 	char str[80];
 	unsigned long time;
+	double RPM=0;

 	//check if we're sitting in an overflow state and dump the sample if needed
 	if (writeBuffer[writeIndex].full==true) {
@@ -246,7 +265,6 @@
     a3 = getVolts( (uint16_t)ADCresult.result_adc0 );
     a4 = getAmps( (uint16_t)ADCresult.result_adc1 );
 	*/
-

 	rawTemp = (uint16_t)adc->analogRead(T1_PIN, ADC_0);
 	a1 = getTemp(rawTemp);
@@ -263,8 +281,11 @@
 	//make note of the current command micros for the ESC
 	commandValue = ESC.readMicroseconds();

+	//RPM
+	RPM = ((1000000.0/lastTachPulse)/pulsesPerRev )*60;
+
 	//format the CSV line
-	sprintf(str, "%lu, %i, %.3f, %.3f, %.3f, %.3f, %.2f\n", time, commandValue, a1, a2, a3, a4, scaleValue);
+	sprintf(str, "%lu, %i, %.3f, %.1f, %.3f, %.3f, %.3f, %.2f\n", time, commandValue, RPM, a1, a2, a3, a4, scaleValue);
 	writeToBuffer(str);

 }
@@ -395,9 +416,13 @@

 	buildTest();

-	writeToBuffer("time, motor, t1, t2, volt, amp, thrust\n");
+	writeToBuffer("time, motor, RPM, t1, t2, volt, amp, thrust\n");

 	// start the log sampling ISR
+	attachInterrupt(TACH_PIN, tachISR, FALLING);
+	tachTime = 0;
+	lastTachPulse = 60000000*pulsesPerRev; //start tach at 1 rpm
+
 	logSampler.priority(200); // set lowish priority.  We want to let regular fast ISRs (like servo timing) to be able to interrupt
 	logSampler.begin(log, 5000); // start logger, 1000 micros = 1khz, 10000micros = 100hz
 	runCurrentCommand();
@@ -453,6 +478,9 @@
 			commandIndex=0;
 			// kill the log sampling ISR
 			logSampler.end();
+			// kill the tach ISR
+			detachInterrupt(TACH_PIN);
+
 			//flag the current write index as full
 			writeBuffer[writeIndex].full = true;
 		}


Maybe not sending data

Maybe not sending data

--- sonarMain/sonarMain.ino
+++ sonarMain/sonarMain.ino
@@ -5,7 +5,7 @@
 #include <Wire.h>

 //Comment out to disable serial debugging
-#define debugOn
+//#define debugOn

 // Sonar ISR
 #include "sonarInterupt.h"
@@ -66,14 +66,14 @@

 void SetupI2C(void){
 	// Enable Wire and set address to 1
-	Wire.begin(1);
+	Wire.begin(0x05);

 	// Set Handler
 	Wire.onReceive(I2C_Request);
 }

 void I2C_Request(int numBytes){
-	// Report Recieving
+	// Report Receiving
 	Serial.print("RCV: ");

 	// Step through commands
@@ -85,22 +85,25 @@

 		// Respond to Command
 		if (cmd == 1){
-			// Convert Sonar Readings to char array
+			// Create Empty buffer for sonar readings
 			char sonar[1028]; memset(&sonar[0], 0, sizeof(sonar));
+
+			// Print sonar readings to array
 			for(int i = 0; i < nSonar; i++){
 				snprintf(sonar+strlen(sonar), sizeof(sonar), "%u ", SonarReading[i]);
 			}

 			// Return Sonar Readings
-			Wire.write(sonar, strlen(sonar));
+			Wire.write(1);
 			#ifdef debugOn
 				Serial.print("\t Sonar:");
 				Serial.print(sonar);
+				Serial.print("\n");
 			#endif
 		}
 		else {
 			// Report Error
-			Wire.write("ERRORL Invalid Command");
+			Wire.write("ERROR: Invalid Command");
 		}

 	}


save before editing

save before editing

--- app/inTheDuck/LoverDuck/LoverDuck.ino
+++ app/inTheDuck/LoverDuck/LoverDuck.ino
@@ -17,9 +17,11 @@
 Adafruit_NeoPixel pixelsA = Adafruit_NeoPixel(ledNumA, ledPinA, NEO_GRB + NEO_KHZ800);
 Adafruit_NeoPixel pixelsB = Adafruit_NeoPixel(ledNumB, ledPinB, NEO_GRB + NEO_KHZ800);
 int color[]={0,250,50};
-int startColor[]={0, 0, 250};
-int endColor[]={0, 250, 0};
-unsigned long mode1Duration=1*60*1000;
+int startColor[]={0, 0, 0};
+int endColor[]={0, 0, 250};
+unsigned long mode1Duration=1*10*1000;
+
+boolean notFirst=false;

 Adafruit_LSM303 lsm;
@@ -62,15 +64,9 @@

   if(comAvailable()>0){
     int data=comRead();
-//    switch(data){
-//      case 1:
-//        changeMode(2);
-//        break;
-//      default:
-//        //do nothing
-//        break;
-//    }
-  changeMode(2);
+    if((0 <= data) && (data <= 5)){
+      changeMode(data);
+    }
   }
   setColors();
 }
@@ -105,7 +101,7 @@
               changeMode(0);
             }
           }
-          else{
+          else if (notFirst){
             // register a short press
             switch (mode) {
               case 1:
@@ -121,6 +117,9 @@
                 break;
             }
           }
+          else{
+            notFirst=true;
+          }
         }
       }
       }
@@ -130,6 +129,9 @@
 unsigned long previousProcess=0;
 unsigned long sendInterval=50;
 void processData(){
+  if(mode==0){
+    return;
+  }
   if((millis()-previousProcess)>sendInterval){
     float data[6];
     getData(data);
@@ -185,14 +187,16 @@
 }

 int comRead(){
-  int value;
+  char value;
   if(isBT){
-    value=BT.parseInt();
-  }
-  else{
-    value=Serial.parseInt();
-  }
-  return value;
+    value=BT.read();
+  }
+  else{
+    value=Serial.read();
+    Serial.print((int)(value-48));
+    //for debug
+  }
+  return (int)(value-48);
 }

@@ -232,7 +236,7 @@
   return value;
 }
 void setColors(){
-  if(mode==1 || mode ==4 || mode ==5){
+  if((mode==1 || mode ==4) || mode ==5){
     if((millis()-startCurrentMode)<waitDuration(mode)){
       // blink if the current mode just started
       if((millis()-startCurrentMode)%600 < 300){
@@ -247,16 +251,13 @@
       }
     }
     else{
-      float ratio= 0.7+ 0.3 * sin(((millis()/10)%360)*3.14/180);
-      int tmp[3];
       for(int i=0; i<3; i++){
         long a=(endColor[i]-startColor[i])*(millis()-startCurrentMode);
         if(endColor[i]-startColor[i] <0){
           a=-abs(a);
         }
         color[i]=(a/mode1Duration+startColor[i])%256;
-  //        color[i]=startColor[i];
-        color[i]=(int)(color[i]*ratio);
+        color[i]=(int)color[i];
       }
       if(millis()-startCurrentMode>mode1Duration){
         changeMode(3);


small fixes on comment

small fixes on comment

--- Arduino/Arduino.ino
+++ Arduino/Arduino.ino
@@ -126,8 +126,8 @@
 FR_edge;

 void setup() {
-  pinMode(BRAKE_LEFT, OUTPUT);  // Brake pin on channel A
-  pinMode(DIR_LEFT, OUTPUT);    // Direction pin on channel A
+  pinMode(BRAKE_LEFT, OUTPUT);   // Brake pin on channel A
+  pinMode(DIR_LEFT, OUTPUT);     // Direction pin on channel A
   pinMode(BRAKE_RIGHT, OUTPUT);  // Brake pin on channel B
   pinMode(DIR_RIGHT, OUTPUT);    // Direction pin on channel B
   pinMode(LED_GREEN, OUTPUT);


Fixed the change SSID function.

Fixed the change SSID function.

--- BackEnd/BackEnd.ino
+++ BackEnd/BackEnd.ino
@@ -162,7 +162,9 @@
 // Configuration file
 #define CONFIG_FILE_MAX_SIZE WEB_SOCKET_BUFFER_SIZE
 #define CONFIG_FILE_FULL_PATH "/home/root/hardware.conf"
-#define HOSTAPD_CONFIG_FILE_FULL_PATH "/etc/hostapd/hostapd.conf"
+#define HOSTAPD_CONFIG_FILE_FULL_PATH "/etc/hostapd/hostapd_test.conf"
+//#define TEMP_CONFIG_FILE_FULL_PATH "/etc/hostapd/hostapd_tmp.conf"
+#define TEMP_CONFIG_FILE_FULL_PATH "/etc/hostapd/hostapdTest.conf"

 // Scripts
 #define START_ACCESS_POINT_SCRIPT_FULL_PATH "/home/root/startAP"
@@ -1332,52 +1334,52 @@

 int changeSsidName(char *_sSsidName)
 {
-//    char    sSsidName[LOCAL_BUFFER_SIZE];
-
   // Truncate Ssid if it too long
-  // SSID_MAX_LENGTH
+  snprintf(_sSsidName,SSID_MAX_LENGTH,"%s",_sSsidName);

 // We need a buffer to read in data
   char      Buffer[LOCAL_BUFFER_SIZE];
+  char      TempBuffer[LOCAL_BUFFER_SIZE];

   // Open the file for reading/write.
-  FILE     *Input = fopen(HOSTAPD_CONFIG_FILE_FULL_PATH, "r+"); // Read/write
+  FILE     *Input = fopen(HOSTAPD_CONFIG_FILE_FULL_PATH, "r"); // Read/write
+  FILE     *Output = fopen(TEMP_CONFIG_FILE_FULL_PATH, "w"); // Read/write

   // Our find and replace arguments
   char     *Find = "ssid=";
   char    sSsidLine[LOCAL_BUFFER_SIZE];

-//  Serial.println("Create SSID:    ");
   // Create file line
-  sprintf(sSsidLine, "ssid=%s", _sSsidName);
+  sprintf(sSsidLine,"ssid=%s\n", _sSsidName);

   if(NULL == Input)
   {
-      trace_info("%s(): /etc/hostapd/hostapd.conf File not found", __func__);
+      trace_info("%s(): %s file not found", __func__,HOSTAPD_CONFIG_FILE_FULL_PATH);
       return 1;
   }
-
-//  Serial.print("Find:    ");     Serial.println(Find);

   // For each line...
   while(NULL != fgets(Buffer, LOCAL_BUFFER_SIZE, Input))
   {
     char *Start = NULL;    // Where 'ssid=' was found in the line
     char *Line = Buffer; // Start at the beginning of the line, and after each match
-
- //   Serial.print("Line: "); Serial.println(Buffer);
-
-      // Find match
-    Start = strstr(Line, Find);
-    if( Start )
-    {
- //     Serial.print("Write: "); Serial.println(sSsidLine);
-      fwrite(sSsidLine, 1, strlen(sSsidLine), Input);
+
+    // Find match
+    if( strstr(Line, Find) )
+    {
+      fputs(sSsidLine, Output);
+    }
+    else
+    {
+      fputs(Line, Output);
     }
   }

   // Close our files
   fclose(Input);
+  fclose(Output);
+
+  rename(TEMP_CONFIG_FILE_FULL_PATH,HOSTAPD_CONFIG_FILE_FULL_PATH);

   return 0;
 }
@@ -1388,7 +1390,7 @@
 void loop()
 {

-  if (millis() - last_print > 2000) {
+  if (millis() - last_print > 3000) {

     ///////////////////////////////////////
     // Test code
@@ -1396,9 +1398,9 @@
 /*
     g_iCatNumber++;
     char sSsidName[100];
-    sprintf(sSsidName, "CAT%i", g_iCatNumber);
+    sprintf(sSsidName, "CA3333333333333333333333333333344444444444444444444444444444444444444444444T%i", g_iCatNumber);
     changeSsidName(sSsidName);
- */
+ */
     //////////////////////////////////////////

     last_print = millis();
@@ -1413,7 +1415,6 @@
   if (Serial.available() > 0) {
     // get incoming byte:
     g_iByte = Serial.read();
-    //Serial.println(g_iByte);

     switch (g_iByte)
     {


Sketchlist: added swipe distance threshold

Fixes occasional swipes when tapping icons to load

--- examples/SketchList/SketchList.ino
+++ examples/SketchList/SketchList.ino
@@ -13,6 +13,7 @@
 /* Swipe settings and calibration */
 #define SWIPE_FADE          0.05
 #define SWIPE_THRESHOLD     2.0
+#define SWIPE_MIN_DIST      30

 /* Sketches list settings */
 #define SKETCHES_CNT_X      4
@@ -95,6 +96,7 @@
 boolean touch_waitup;      /* Whether we are waiting a cycle */
 uint32_t swipe_last_time;  /* Last known time while swiping */
 uint16_t swipe_last_pos;   /* Last known position while swiping */
+uint16_t swipe_start_pos;  /* Start position of a swipe */
 float swipe_speed;         /* Speed of swiping in pixels/ms */

 /* Sketch information buffer */
@@ -332,13 +334,16 @@
   /* Update the swipe measurements, on release perform action */
   if (!LCD_isTouchedAny()) {
     /* Handle releases, evaluate previously measured swipe speed */
-    if (swipe_speed > SWIPE_THRESHOLD) {
-      sketch_icon_dirty[touchedIndex] = 1;
-      touchedIndex = MENU_IDX_DOWN;
-    }
-    if (swipe_speed < -SWIPE_THRESHOLD) {
-      sketch_icon_dirty[touchedIndex] = 1;
-      touchedIndex = MENU_IDX_UP;
+    /* First check if the swipe distance is long enough */
+    if (abs(swipe_last_pos-swipe_start_pos) > SWIPE_MIN_DIST) {
+      if (swipe_speed > SWIPE_THRESHOLD) {
+        sketch_icon_dirty[touchedIndex] = 1;
+        touchedIndex = MENU_IDX_DOWN;
+      }
+      if (swipe_speed < -SWIPE_THRESHOLD) {
+        sketch_icon_dirty[touchedIndex] = 1;
+        touchedIndex = MENU_IDX_UP;
+      }
     }
     swipe_speed = 0.0F;
   } else if (swipe_last_pos != 0xFFFF) {
@@ -351,6 +356,8 @@
     } else {
       swipe_speed += SWIPE_FADE * (curr_speed - swipe_speed);
     }
+  } else {
+    swipe_start_pos = touch_y;
   }

   /* Update last known swipe position and time */
@@ -1065,4 +1072,4 @@

 uint8_t LCD_isTouched(uint16_t x, uint16_t y, uint8_t w, uint8_t h) {
   return touch_x >= x && touch_y >= y && touch_x < (x + w) && touch_y < (y + h);
-}+}


Split serial comms into receive and loop, changed symantics of mode detector slightly

--- 00_Firmware/Firmware/Firmware.ino
+++ 00_Firmware/Firmware/Firmware.ino
@@ -98,7 +98,7 @@
 #define GREEN(hex) 	hex >>  8 & 0xFF
 #define BLUE(hex) 	hex >>  0 & 0xFF

-/** EEPROM data settings. */
+/** EEPROM data settings. NOTE: Modes cannot be zero - zero is reserved! */
 #define EEMODEADDR 0			// The address of the mode stored in EEPROM.
 #define EEMODE_CHANGETIME 5000  // The number of ms to hold the switch before the clip mode is changed.
 #define EEMODE_SYNCPULSE  45	// The Clip looks for a sync pulse on one of the LDRs.
@@ -452,7 +452,7 @@
 	// Debug Mode
 	//eClipMode = EEMODE_SYNCPULSE;
 	//eRGBMode  = RGBMODE_SCREEN;
-	detectModeChange( 1 );
+	detectAndSetModeChange( -1 );   // -1 == set nothing, blink code; 0 = set nothing, wait for button; >0 == set mode to supplied mode

 	// Wait for a random time so that not all clips zero their motor at the same time.
 	randomSeed(analogRead(PIN_RND));
@@ -471,14 +471,14 @@
  * Press SWBOT to change mode. Cycle through the modes every 1 second.
  * @param skip Set to 1 to emulate SWBOT being pressed.
  */
-void detectModeChange( byte skip ) {
+void detectAndSetModeChange( int skipToMode ) {

 	// If SWBOT is not pressed, skip out.
-	if( digitalRead(PIN_SWBOT) == HIGH && skip != 1 )
+	if( digitalRead(PIN_SWBOT) == HIGH && skipToMode == 0 )
 		return;

 	// While we are still holding SWBOT down.
-	while( digitalRead(PIN_SWBOT) == LOW )
+	while( skipToMode == 0 && digitalRead(PIN_SWBOT) == LOW )
 	{
 		// Swap mode.
 		switch( eClipMode )
@@ -512,6 +512,20 @@
 		delay( 1000 );
 	}

+        if( skipToMode > 0 )
+        {
+          eClipMode = skipToMode;
+          switch( eClipMode )
+          {
+            case EEMODE_HEIGHTONLY:
+            case EEMODE_SERIAL:
+              eRGBMode  = RGBMODE_SCREEN;
+              break;
+            default:
+              eRGBMode  = RGBMODE_NONE;
+          }
+        }
+
 	// Now SWBOT has been released, flicker the colour 3 times.
 	for( int i=0; i<3; i++ )
 	{
@@ -891,12 +905,12 @@
  * This will wait for a pulse, and then display colour and height changes
  * as appropriate.
  */
-void loopSerialMode() {
+static unsigned char cmdBuffer[3] = { 0, 0, 0 };  // The command buffer.
+void screenSerialRead() {

 	// Static variables for the serial mode.
 	static bool flippedRead = false;						// Are we reading in "inverted" LDR mode (ie. LDR1 <> LDR2).
 	static unsigned int bitsSeen = 0;						// The number of valid bits read.
-	static unsigned char cmdBuffer[3] = { 0, 0, 0 };		// The command buffer.
 	static int oldState = 0;								// The last 'state' symbol read by the LDR: SYMB_ZERO, SYMB_LOW, SYMB_HIGH
 	#ifdef SSMODE_8BIT
 	static uint16_t bSerialBuffer = 0x00;					// The buffer to write serial commands into. 16 bit (we need space for frame headers, parity, etc).
@@ -1065,22 +1079,25 @@
 			Serial.print( " " );
 			Serial.println( (unsigned char)cmdBuffer[2] );
 			#endif
-
-			// If we have an 'X' at the end, the command is valid.
-			if( cmdBuffer[2] == 'X' )
-			{
-				switch( cmdBuffer[0] )
-				{
-					case 'R': iTargetR = (unsigned)cmdBuffer[1]; eRGBMode = RGBMODE_SCREEN; break;
-					case 'G': iTargetG = (unsigned)cmdBuffer[1]; eRGBMode = RGBMODE_SCREEN; break;
-					case 'B': iTargetB = (unsigned)cmdBuffer[1]; eRGBMode = RGBMODE_SCREEN; break;
-					case 'H': iTargetPos = map( (unsigned)cmdBuffer[1], 0, 0xFF, 0, MOTOR_TRAVEL ); break;
-					case 'z': zeroMotor(); break;
-				}
-			}
-
-		}
-
+		}
+
+	}
+}
+
+void loopSerialMode()
+{
+	screenSerialRead();
+
+	if( cmdBuffer[2] == 'X' )
+	{
+		switch( cmdBuffer[0] )
+		{
+			case 'R': iTargetR = (unsigned)cmdBuffer[1]; eRGBMode = RGBMODE_SCREEN; break;
+			case 'G': iTargetG = (unsigned)cmdBuffer[1]; eRGBMode = RGBMODE_SCREEN; break;
+			case 'B': iTargetB = (unsigned)cmdBuffer[1]; eRGBMode = RGBMODE_SCREEN; break;
+			case 'H': iTargetPos = map( (unsigned)cmdBuffer[1], 0, 0xFF, 0, MOTOR_TRAVEL ); break;
+			case 'z': zeroMotor(); break;
+		}
 	}

 	// Move the motor and update the colour.
@@ -1096,7 +1113,14 @@
 void loop() {

 	// Listen for a change in mode.
-	detectModeChange( 0 );
+	detectAndSetModeChange( 0 );
+
+	// Attempt to read a serial bit from the screen.
+	screenSerialRead();
+	if( cmdBuffer[2] == 'X' )
+	{
+		switch( cmdBuffer[1] )
+	}

 	// Detect which mode we are in.
 	switch (eClipMode)


Update TestProgram1.ino

Update TestProgram1.ino

give parameters to methods

--- arduino/TestProgram1/TestProgram1.ino
+++ arduino/TestProgram1/TestProgram1.ino
@@ -3,47 +3,53 @@
 Servo right;
 Servo left;

-void Move_Forward()
+void Move_Forward(int speed)
 {
+  //0
+  //from 0-90
   //moves forward
-  right.write(180);
-  left.write(0);
+  right.write(180-speed);
+  left.write(speed);
 }

-void Move_Backward()
+void Move_Backward(int speed)
 {
+  //180
   //moves backward
-  right.write(0);
-  left.write(180);
+  right.write(180-speed);
+  left.write(speed);
 }

-void Move_Right()
+void Move_Right(int speed)
 {
+  //0
   //moves right
-  right.write(180);
+  right.write(180-speed);
   left.write(90);
 }

-void Move_Left()
+void Move_Left(int speed)
 {
+  //0
   //moves left
   right.write(90);
-  left.write(0);
+  left.write(speed);
 }

-void Move_In_circle()
+void Move_In_circle(int speed)
 {
+  //180
   //moves in circle
-  right.write(180);
-  left.write(180);
+  right.write(speed);
+  left.write(speed);
 }

 void setup() {
   // put your setup code here, to run once:
   right.attach(2);
   left.attach(3);
-
-  Move_In_circle();
+
+  Move_In_circle(180);
 }

 void loop() {


CHanged position sensor pin.. to correct

--- Arduino/_firmware2/_firmware2.ino
+++ Arduino/_firmware2/_firmware2.ino
@@ -216,7 +216,7 @@
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                            11. POSITION SENSOR

-int positionSignal1 = A2;
+int positionSignal1 = A0;
 int positionSignal2= A1;
 double position1 = 0;
 double position2 = 0;
@@ -482,9 +482,9 @@
     data += ",";
     data += rpm;
     data += ",";
-    data += load1_in_lbs; //Load Washers
-    data += ",";
-    data += load2_in_lbs; //Load Washers
+//    data += load1_in_lbs; //Load Washers
+    data += ",";
+//    data += load2_in_lbs; //Load Washers
     data += ",";
     data += flow_rate_cc_per_sec; //This is for the level sensor rate
     data += ",";


examples/serial2dmx: increased host timeout

observed partial data loss from host to Arduino for long byte sequences
> increased hostDataGap to have more margin regarding UART synchronization

--- examples/serial2dmx/serial2dmx.ino
+++ examples/serial2dmx/serial2dmx.ino
@@ -16,7 +16,7 @@
  * – wait for the Arduino to reply
  *   > the Arduino reads as much as you send it
  *   > after having received 512 bytes or
- *     after a break of 2 millisecs (see hostDataGap below)
+ *     after a break of few milliseconds (see hostDataGap below)
  *     the Arduino forwards the received data to the DMX bus
  *
  * – the Arduino's response indicates the number of bytes forwarded,
@@ -27,7 +27,7 @@
  * > transmit enable: digital pin 2 (HIGH during transmit)
  *
  * Nick Schwarzenberg,
- * 09/2014, v0.1.0
+ * 09/2014, v0.1.1
  */

@@ -35,14 +35,14 @@
 #include <LeoDMX.class.h>

 // set version
-#define VERSION "0.1.0"
+#define VERSION "0.1.1"

 // host communication speed
 const unsigned long hostBaud = 115200;

 // host data timeout [ms] (gap to identify end of data block)
-const unsigned short hostDataGap = 2;
+const unsigned short hostDataGap = 3;

 // get DMX instance
 LeoDMX DMX;


json parse shcedule add

json parse shcedule add

--- nodmcu.ino
+++ nodmcu.ino
@@ -25,6 +25,7 @@
 const int MOTOR_PIN = D5; //Motor pin
 const String DEV_VERSION = "1.0";
 const int POWERCHECK_INTERVAL = 600000; // 10 min Check battery volage
+const int SCHEDULE_INTERVAL = 60000; // 1 min Check shedule volage
 const float VOLTAGE_THRESHOLD = 2710; // voltage threshold , mv
 const int BROADCAST_INTERVAL = 5000; // 5 sec broadcastinterval, milisecond
 unsigned int UPDPORT = 28031;
@@ -47,6 +48,7 @@
 SimpleTimer timer_remote;
 SimpleTimer timer_vcc;
 SimpleTimer timer_broadcast;
+SimpleTimer timer_schedule;
 WiFiUDP udp;
 RtcDS3231 Rtc;

@@ -103,7 +105,7 @@
           doFeed(portion);
          }
  }
- String getID(){
+String getID(){
   String str = WiFi.macAddress();
   String dev_id;
   for(int i=0; i <17; i++){
@@ -182,8 +184,9 @@
           return "";
      }
 }
-void parseSchedule(){
-       StaticJsonBuffer<200> jsonBuffer;
+void checkShedule(){
+       //json format : {"feed1":{"hour":"10", "minute":"10", "portion":"2"}, "feed2":{"hour":"10", "minute":"10", "portion":"2"}} ...feed5
+       StaticJsonBuffer<1000> jsonBuffer;
        StaticJsonBuffer<200> jsonBufferNested;
        SPIFFS.begin();
        File configFile = SPIFFS.open("/schedule.txt", "r");
@@ -191,10 +194,25 @@
           String line = configFile.readStringUntil('\n');
           configFile.close();
           JsonObject& jdata = jsonBuffer.parseObject(line);
+               if (!jdata.success()){ Serial.println("parseObject() failed on 1 lap checkShedule"); return; }
            for(JsonObject::iterator it=jdata.begin(); it!=jdata.end(); ++it) {
-                //JsonObject& row = jsonBufferNested.parseObject(it->value);
-                      //  const char* key = it->key;
-                     // it->value contains the JsonVariant which can be casted as usual const char* value = it->value;
+               if(it->value.is<JsonObject>()){
+                JsonObject& ndata = it->value;
+                 if (!ndata.success()){ Serial.println("parseObject() failed on 2 lap checkShedule"); return; }
+                   const char* hour;
+                   const char* minute;
+                   const char* portion;
+                   for(JsonObject::iterator it2=ndata.begin(); it2!=ndata.end(); ++it2) {
+                    const char* key = it2->key;
+                    const char* value = it2->value;
+                    if(strcmp(key, "hour") == 0){ hour = value; }
+                    if(strcmp(key, "minute") == 0){ minute = value; }
+                    if(strcmp(key, "portion") == 0){ portion = value;  }
+                   }
+                if(strcmp(hour, getNowHour().c_str()) == 0 && strcmp(minute, getNowMin().c_str()) == 0){
+                         doFeed(portion);
+                   }
+               }
           }
      }
 }
@@ -202,13 +220,13 @@
  DID = getID();
  DHEX = getHex(DID);

-  String rhost = getConfigParam("repository_host");
+String rhost = getConfigParam("repository_host");
   if(rhost != ""){
     char *cstr = new char[rhost.length() + 1];
     rhost.toCharArray(cstr, rhost.length() + 1);
  REPOSITORY_HOST = cstr;
   }
-  String rint = getConfigParam("repository_interval");
+String rint = getConfigParam("repository_interval");
   if(rint != ""){
  REPOSITORY_INTERVAL = rint.toInt()*60*1000;
   }
@@ -263,8 +281,29 @@
            return str;
    }else{
            return "0";
-   }
-
+   }
+}
+String getNowHour(){
+   if (Rtc.IsDateTimeValid()){
+    RtcDateTime currentTime = Rtc.GetDateTime();
+    char str[15];   //declare a string as an array of chars
+    sprintf(str, "%d", currentTime.Hour());
+           return str;
+   }else{
+           return "0";
+   }
+
+}
+String getNowMin(){
+   if (Rtc.IsDateTimeValid()){
+    RtcDateTime currentTime = Rtc.GetDateTime();
+    char str[15];   //declare a string as an array of chars
+    sprintf(str, "%d", currentTime.Minute());
+           return str;
+   }else{
+           return "0";
+   }
+
 }
 //------------- end main functions----------------------------------------
 void setup() {
@@ -307,6 +346,7 @@
     timer_remote.setInterval(REPOSITORY_INTERVAL, checkRepository);
     timer_vcc.setInterval(POWERCHECK_INTERVAL, batteryCheck);
     timer_broadcast.setInterval(BROADCAST_INTERVAL, broadcast);
+    timer_schedule.setInterval(SCHEDULE_INTERVAL, checkShedule);

     Serial.println("Starting http server...");
     server.reset(new ESP8266WebServer(WiFi.localIP(), 80));
@@ -387,5 +427,6 @@
   timer_remote.run();
   timer_vcc.run();
   timer_broadcast.run();
+  timer_schedule.run();
     }
 }


Improve program structure

Improve program structure

--- battery-monitor.ino
+++ battery-monitor.ino
@@ -3,34 +3,39 @@
 #define R1 21440 // Resistor R1 Ohms
 #define R2 3242 // Resistor R2 Ohms
 #define CONNECT_WAIT_MILLIS 5000
-#define SLEEP_SECS 15
+//#define SLEEP_SECS 15
+#define SLEEP_SECS 300
 //#define SLEEP_SECS 3600

+// Set manual mode so that if no network is available at startup, photon can go back to sleep
 SYSTEM_MODE(MANUAL);

-const float DIV_RATIO = (R2 + R1) / (float) R2;
+const float DIV_RATIO = (R1 + R2) / (float) R2;
 const char VOLTAGE_EVENT[11] = "carVoltage";

-volatile bool canSleep = false; // set to true when the photon can sleep
+// set to true when the photon can sleep
+volatile bool canSleep = false;

 void setup() {
     disableLed();
-
-    pinMode(BATTERY_PIN, INPUT);
-
-    Particle.subscribe(VOLTAGE_EVENT, subscribeHandler, MY_DEVICES);
+
     Particle.connect();
     if (waitFor(Particle.connected, CONNECT_WAIT_MILLIS)) {
+        subscribeToVoltageEvent();
         publishVoltageEvent();
+        // Listen for voltage event to make sure it was published before sleeping
         waitForVoltageEvent();
     }
+
     System.sleep(SLEEP_MODE_DEEP, SLEEP_SECS);
 }

-void loop() {}
+void subscribeToVoltageEvent() {
+    Particle.subscribe(VOLTAGE_EVENT, subscribeHandler, MY_DEVICES);
+}

 void publishVoltageEvent() {
-    char mV[20];
+    char mV[8];
     getBatteryMilliVolts();
     delay(10);
     sprintf(mV, "%d", getBatteryMilliVolts());
@@ -60,4 +65,4 @@

 uint16_t readMilliVolts(int pin) {
 	return map(analogRead(pin), 0, 4095, 0, VCC);
-}+}


adding state machine initial structure

adding state machine initial structure

--- core_app/core_app.ino
+++ core_app/core_app.ino
@@ -16,6 +16,15 @@
 #include "MQTTClient.h"
 #include "SIM908Client.h"

+#define ALARM_OFF 0
+#define ALARM_ON 1
+#define ALARM_BUZZ 2
+
+#define GPS_TIME_DFT 30000
+
+int gpsLoopTime = 900000; //15 minutes
+int alarmLoopTime = 30000; //30 seconds
+
 //Host Name  : test.mosquitto.org
 char *server = "85.119.83.194";
 int port = 8080;
@@ -23,6 +32,9 @@
 char *apn = "zap.vivo.com.br";
 char *usr = "vivo";
 char *psw = "vivo";
+
+/* Current State */
+int curState = 0;

 SIM908Client client(0,1,5,4,3);

@@ -46,13 +58,115 @@
 void loop()
 {
   mqttClient.loop();
+
+  Timer gpsTimer(gpsLoopTime);
+  Timer alarmTimer(alarmLoopTime);
+
+  switch(curState){
+    case ALARM_OFF:{
+      handleAlarmOff();
+      break;
+    }
+    case ALARM_ON:{
+      handleAlarmOn(gpsTimer);
+      break;
+    }
+    case ALARM_BUZZ:{
+      handleAlarmBuzz();
+      break;
+    }
+    default:{
+      break;
+    }
+  }
+
 }

 //method for handling messages recieved from the web mosquitto
-void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
-Serial.print("incomming: ");
-Serial.print(topic);
-Serial.print(" - ");
-Serial.print(payload);
-Serial.println();
+void messageReceived(String topic, String payload, char * bytes, unsigned int length)
+{
+  Serial.print("incomming: ");
+  Serial.print(topic);
+  Serial.print(" - ");
+  Serial.print(payload);
+  Serial.println();
+
+  int op = payload[0] - 48;
+
+  switch(op){
+    case ALARM_ON:{
+      activateAlarm();
+      break;
+    }
+    case ALARM_OFF:{
+      deactivateAlarm();
+      break;
+    }
+    case ALARM_BUZZ:{
+      buzzAlarm();
+      break;
+    }
+    default:{
+      //default case
+    }
+  }
 }
+
+//setting states
+void activateAlarm(int dt)
+{
+  if(curState != ALARM_ON)
+  {
+    // deactivate buzz
+    // deactivate ignition/fuel
+    curState = ALARM_ON;
+    gpsLoopTime = dt;
+  }
+}
+
+void deactivateAlarm()
+{
+  if(curState == ALARM_ON)
+  {
+    // deactivate alarm
+    // activate ignition/fuel
+    curState = ALARM_OFF;
+    gpsLoopTime = GPS_TIME_DFT;
+  }
+}
+
+void buzzAlarm()
+{
+  if(curState != ALARM_OFF)
+  {
+    curState = ALARM_BUZZ;
+    // activate buzz and lights
+    // set gps loop interval to zero
+    // send msg
+  }
+}
+
+//handle alarm state
+void handleAlarmOff()
+{
+  // wait for turn on signal
+}
+
+void handleAlarmOn(Timer gpsTimer)
+{
+   if(gpsTimer.expired())
+   {
+    //  reset default gps time
+    //  build msg
+     gpsTimer(gpsLoopTime);
+   }
+}
+
+void handleAlarmBuzz(Timer alarmTimer)
+{
+  if(alarmTimer.expired())
+  {
+    //toogle buzz
+    alarmTimer(alarmLoopTime);
+  }
+}


Adjust to updated TSwitch library

Adjust to updated TSwitch library

--- LEDStripShow.ino
+++ LEDStripShow.ino
@@ -311,10 +311,10 @@
   // Process Application Timer
   LightStripShow.run();
   // Test and debounce button
-  UIButton.run();
+  UIButton.poll();
   // Test and debounce switches
-  UISwitch1.run();
-  UISwitch2.run();
+  UISwitch1.poll();
+  UISwitch2.poll();

 #ifdef DEBUG
   if ( UISwitch1.get() && UISwitch.hasChanged() ) {


decreased delay to 500 ms in setup

decreased delay to 500 ms in setup

--- angu/angu.ino
+++ angu/angu.ino
@@ -11,7 +11,7 @@

 void setup() {
   Serial.begin(9600);
-  delay(1000);
+  delay(500);
   pinMode(ledPin, OUTPUT); // use the LED on pin 13 as an output
   ledSignal(5,200);
   // begin initialization


Try faster comms

Try faster comms

--- arduino/led_matrix/led_matrix.ino
+++ arduino/led_matrix/led_matrix.ino
@@ -6,6 +6,7 @@
 #define NUM_LEDS (WIDTH * HEIGHT)
 #define PIN 6
 #define BAUD 115200
+#define BRIGHTNESS 64

 CGRB leds[NUM_LEDS];
 int r, g, b;
@@ -13,6 +14,7 @@

 void setup() {
   FastLED.addLeds<WS2812B, PIN>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
+  FastLED.setBrightness(BRIGHTNESS);
   Serial.begin(BAUD);
   FastLED.show();
 }


TSTMODE (begin and drop) in arduino

TSTMODE (begin and drop) in arduino

--- arduttons.ino
+++ arduttons.ino
@@ -33,6 +33,11 @@
 const int TSTMODE = 16;
 const int DORESET = 32;
 const int GETSTAT = 64;
+
+const unsigned long MAX_UNSIGNED_LONG = 4294967295;
+const unsigned long TSTLEN = 5*60*1000;
+unsigned long tstbgn = 0;
+boolean iststmode = false;

 //
 EthernetServer server(2323);
@@ -93,10 +98,10 @@
 }

 //
-char getstatus()
+char getstatus(char cmd)
 {
 //
-   char result = 0;
+   char result = cmd;
    for (int i = 0; i < pinc; i++)
       if (pineepromstate[i] == 1) result |= 1 << i;
    return result;
@@ -124,7 +129,7 @@
        if (pinreport[i] == 0 && pineepromstate[i]==1)
          {
       //
-         server.write( getstatus() );
+         server.write( getstatus( iststmode ? GETSTAT|TSTMODE : GETSTAT ) );
          pinreport[i] = 1;
          }
       }
@@ -139,11 +144,14 @@
             {
          //
             cmd |= GETSTAT;
+            tstbgn = millis();
+            iststmode = true;
             }
          //else
          if (cmd & DORESET)
             {
          //
+            iststmode = false;
             for (int i = 0; i < pinc; i++)
                {
             //
@@ -155,7 +163,19 @@
          if (cmd & GETSTAT)
             {
          //
-            server.write(cmd & getstatus());
+            server.write(getstatus( iststmode ? GETSTAT|TSTMODE : GETSTAT ));
             }
          }
+
+   //drop TSTMODE
+   if (iststmode)
+      {
+   //
+      unsigned long currt = millis();
+      unsigned long duration = 0;
+      if (currt < tstbgn) duration = (MAX_UNSIGNED_LONG - tstbgn) + currt;
+      else                duration = currt - tstbgn;
+
+      if (duration > TSTLEN) iststmode = false;
+      }
 }


remove unused code

remove unused code

--- collect_arduino_data/WebControlPER/WebControlPER.ino
+++ collect_arduino_data/WebControlPER/WebControlPER.ino
@@ -407,187 +407,6 @@

-
-
-//void printTwoDigits(char * p, uint8_t v)
-//{
-//
-//  *p   = '0' + v / 10;
-//  *(p + 1) = '0' + v % 10;
-//  *(p + 2) = 0;
-//
-//}
-//
-//
-//
-//void webTime ()
-//{
-//#ifdef __wifisetup__
-//  WiFiClient timeclient;
-//#else
-//  EthernetClient timeclient;
-//#endif
-//  // default values ...
-//  year = 2015;
-//  second = myminute = hour = day = month = 1;
-//
-//  // Just choose any reasonably busy web server, the load is really low
-//  if (timeclient.connect ("www.york.ac.uk", 80))
-//  {
-//    // Make an HTTP 1.1 request which is missing a Host: header
-//    // compliant servers are required to answer with an error that includes
-//    // a Date: header.
-//    timeclient.print(F("GET / HTTP/1.1 \r\n\r\n"));
-//
-//    char buf[5];			// temporary buffer for characters
-//    timeclient.setTimeout(5000);
-//    if (timeclient.find((char *)"\r\nDate: ") // look for Date: header
-//        && timeclient.readBytes(buf, 5) == 5) // discard
-//    {
-//      day = timeclient.parseInt();	   // day
-//      timeclient.readBytes(buf, 1);	   // discard
-//      timeclient.readBytes(buf, 3);	   // month
-//      year = timeclient.parseInt();	   // year
-//      hour = timeclient.parseInt();   // hour
-//      myminute = timeclient.parseInt(); // minute
-//      second = timeclient.parseInt(); // second
-//
-//
-//      switch (buf[0])
-//      {
-//        case 'F': month = 2 ; break; // Feb
-//        case 'S': month = 9; break; // Sep
-//        case 'O': month = 10; break; // Oct
-//        case 'N': month = 11; break; // Nov
-//        case 'D': month = 12; break; // Dec
-//        default:
-//          if (buf[0] == 'J' && buf[1] == 'a')
-//            month = 1;		// Jan
-//          else if (buf[0] == 'A' && buf[1] == 'p')
-//            month = 4;		// Apr
-//          else switch (buf[2])
-//            {
-//              case 'r': month =  3; break; // Mar
-//              case 'y': month = 5; break; // May
-//              case 'n': month = 6; break; // Jun
-//              case 'l': month = 7; break; // Jul
-//              default: // add a default label here to avoid compiler warning
-//              case 'g': month = 8; break; // Aug
-//            }
-//      } // months sorted
-//      //month -- ; // zero based, I guess
-//
-//    }
-//  }
-//  delay(10);
-//  timeclient.flush();
-//  timeclient.stop();
-//
-//  return ;
-//}
-//
-//
-//
-//// find day of week http://stackoverflow.com/questions/6054016/c-program-to-find-day-of-week-given-date
-//int DayOfWeek (int d, int m, int y)
-//{
-//  return (d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400) % 7   ;
-//}
-//
-//void gmdate ( const dir_t & pFile)
-//{
-//  // Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
-//  const char * cDays PROGMEM = "Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun";
-//  const char * cMonths PROGMEM = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,";
-//  char c [55] ;
-//  c [0] = 0;
-//  int iTmp ;
-//  int d = FAT_DAY(pFile.lastWriteDate) ;
-//  int m = FAT_MONTH(pFile.lastWriteDate) ;
-//  int y = FAT_YEAR(pFile.lastWriteDate) ;
-//
-//  iTmp = DayOfWeek (d, m, y) ;
-//  if (iTmp > 6) iTmp = 0;
-//  strncpy(c, cDays + iTmp * 4, 3); // tue
-//  c[3] = 0;
-//  strcat_P(c, PSTR(", "));
-//  //Serial.println (c);
-//
-//  printTwoDigits(c + strlen(c) , FAT_DAY(pFile.lastWriteDate));
-//  strcat_P (c, PSTR(" "));
-//
-//  int iLen = strlen(c);
-//  iTmp = m - 1;
-//  if (iTmp > 11) iTmp = 0;
-//  strncpy(c + iLen, cMonths + iTmp * 4, 3); //nov
-//  c[iLen + 3] = 0;
-//  //Serial.println (c);
-//
-//  strcat_P (c, PSTR(" "));
-//  itoa( y, c + strlen(c), 10);
-//  strcat_P (c, PSTR(" "));
-//  printTwoDigits(c + strlen(c) , FAT_HOUR(pFile.lastWriteTime));
-//  strcat_P (c, PSTR(":"));
-//  printTwoDigits(c + strlen(c) , FAT_MINUTE(pFile.lastWriteTime));
-//  strcat_P (c, PSTR(":"));
-//  printTwoDigits(c + strlen(c) , FAT_SECOND(pFile.lastWriteTime));
-//  strcat_P (c, PSTR(" GMT"));
-//
-//  //Serial.println( c );
-//}
-
-//
-//void AppendFlashReport()
-//{
-//  client.print F("Acquired ") ;
-//  client.print ( nRepeats );
-//  client.print F(" of ");
-//  client.print (maxRepeats);
-//  client.println F(" data blocks so far " );
-//  client.println F("<button onclick=\"myStopFunction()\">Stop Data Acquisition</button>
");
-//  client.println (cInput);
-//  client.println F( "
 ");
-//
-//
-//  if (nRepeats > 0)
-//  {
-//    client.println F("<canvas id=\"myCanvas\" width=\"640\" height=\"520\" style=\"border:1px solid #d3d3d3;\">");
-//    client.println F("Your browser does not support the HTML5 canvas tag.</canvas>");
-//
-//    client.println F("");
-//  }
-//}
-
 void flashLED (int time_on, int time_off, int iTimes) // ms
 {
   for (int i = 0; i < iTimes; i++)


WIP: Minor changes

WIP: Minor changes

--- Arduino/Arduino.ino
+++ Arduino/Arduino.ino
@@ -158,6 +158,9 @@
   Serial.write(pos4);
   Serial.write(pos5);

+  // Update LEDs
+  // Nothing here yet
+
   // Delay
   delay(LOOP_DELAY);
 }


extended the Arduino part by a Timer disable/enable command

--- Arduino/Arduino.ino
+++ Arduino/Arduino.ino
@@ -131,6 +131,14 @@
   sei();
 }

+bool __timerState = true;
+inline bool isTimerEnabled() { return __timerState; }
+
+//! used for enabling Timer1
+void enableTimer() { TIMSK1 |= (1<<TOIE1); sei(); __timerState = true; }
+//! used for disabling Timer1
+void disableTimer() { TIMSK1 &= ~(1<<TOIE1); __timerState = false; }
+
 #define DEVICES 4
 #define DEVICES_ARRAY_SIZES 4
 #define ROWS 8
@@ -374,6 +382,20 @@
   {
     String sbuf(buf);

+    if(sbuf[0] == 'z' && index == 2)
+    {
+      if(isTimerEnabled())
+      {
+        disableTimer();
+      }
+      else
+      {
+        enableTimer();
+      }
+
+      Serial.println(" OK ");
+    }
+
     if(sbuf[0] == 'b' && index == 5)
     {
       String s("");
@@ -429,6 +451,7 @@
 }
 void runGrid()
 {
+
   for(uint8_t x = 0; x < WIDTH; ++x) {
     for(uint8_t y = 0; y < HEIGHT; ++y) {


Some changed

Some changed

--- Arduino/Arduino.ino
+++ Arduino/Arduino.ino
@@ -88,6 +88,7 @@
 void loop()
 {
   if (net.messageReceived()) {
+    digitalWrite(13, HIGH); delay(200); digitalWrite(13, LOW);
     char buf[100];
     if (net.assertCommand("getDistance")) {
       net.sendResponse(itoa(laser.getValue(), buf, 10));
@@ -95,6 +96,8 @@
       net.sendResponse(itoa(laser.percentValid(), buf, 10));
     } else if (net.assertCommandStarts("set", buf)) {
       processSetCommands();
+    } else if (net.assertCommand("getRawLaser")) {
+      net.sendResponse(itoa(sensor.readRangeSingleMillimeters(), buf, 10));
     } else {
       net.sendResponse("Unrecognized command");
     }


The write function is currupting something. We are only keeping the read function for now.

--- BackEnd/BackEnd.ino
+++ BackEnd/BackEnd.ino
@@ -469,7 +469,7 @@
 //------------------------------------------------------------
 void initBoardStateFromFile(char* _sFullFilePath) {

-  Serial.println("Init from board file");
+//  Serial.println("Init from board file");
   // Open File
   FILE *fp;
   char sJsonFile[CONFIG_FILE_MAX_SIZE];
@@ -1723,7 +1723,7 @@

   if (millis() - g_last_print > 1000)
   {
-     writeBoardStateToFile(BOARD_CONFIG_FILE_FULL_PATH);
+     //writeBoardStateToFile(BOARD_CONFIG_FILE_FULL_PATH);
     /*
     if(g_iWriteToFile)
     {


reflected esp8266utils changes; WS event handling still in progress

--- Esp8266/Esp8266.ino
+++ Esp8266/Esp8266.ino
@@ -1,134 +1,178 @@
-#include <Esp8266Utils.h>  // https://github.com/hunsalz/esp8266utils
-#include <Log4Esp.h>       // https://github.com/hunsalz/log4Esp
+#include <ESP8266mDNS.h>        // https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266mDNS/src/ESP8266mDNS.h
+#include <ESP8266WiFiMulti.h>   // https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h
+#include <StreamString.h>       // https://github.com/esp8266/Arduino/blob/master/cores/esp8266/StreamString.h
+
+#include <Esp8266Utils.h>       // https://github.com/hunsalz/esp8266utils

 #include "config.h"
-
-// web server settings
-const static int PORT = 80;

 esp8266utils::MotorDriver _motorA;
 esp8266utils::MotorDriver _motorB;

 esp8266utils::WebSocketListener _wsl;

+unsigned long nextLoopInterval = 0;
+
 void setup() {
-  // logger setup
-  LOG.addLevelToAll(Appender::VERBOSE);
-  LOG.addFormatterToAll(
-      [](Print &output, Appender::Level level, const char *msg, va_list *args) {
-        // output log level
-        output.print(Appender::toString(level, true));
-        output.print(Appender::DEFAULT_SEPARATOR);
-        // output uptime of this program in milliseconds
-        output.print(millis());
-        output.print(Appender::DEFAULT_SEPARATOR);
-        // output free heap space
-        output.print(ESP.getFreeHeap());
-        output.print(Appender::DEFAULT_SEPARATOR);
-        // determine buffer length for formatted data
-        size_t length = vsnprintf(NULL, 0, msg, *args) + 1;
-        char buffer[length];
-        // output formatted data
-        vsnprintf(buffer, length, msg, *args);
-        output.print(buffer);
-      });
-
-  // serial setup
-  Serial.begin(115200);
-  Serial.setDebugOutput(false);
-  while (!Serial && !Serial.available()) {
-  };
-  Serial.println();
-  LOG.verbose(F("Serial baud rate is [%d]"), Serial.baudRate());
+
+  // init Serial with desired baud rate
+  esp8266utils::Logging::init(115200);
+  VERBOSE_FP(F("Serial baud rate is [%lu]"), Serial.baudRate());

   // setup hardware components
-  _motorA.begin(MOTOR_A_PWM, MOTOR_A_DIR),
-      _motorB.begin(MOTOR_B_PWM, MOTOR_B_DIR),
-      esp8266utils::MotorDriver::setPWMRange(PWM_RANGE);
-
-  // WiFi setup
-  WIFI_STA_CFG.addAP(WIFI_SSID_1, WIFI_PSK_1);
-  WIFI_STA_CFG.addAP(WIFI_SSID_2, WIFI_PSK_2);
-  WIFI_STA_CFG.begin();
-
-  WIFI_AP_CFG.begin(WIFI_AP_SSID, WIFI_AP_PSK);
+  _motorA.begin(MOTOR_A_PWM, MOTOR_A_DIR);
+  _motorB.begin(MOTOR_B_PWM, MOTOR_B_DIR);
+  //esp8266utils::setPWMRange(PWM_RANGE);
+
+  // WiFi AP setup
+  esp8266utils::setupWiFiAp(WIFI_AP_SSID, WIFI_AP_PSK);
+
+//  // WiFi station setup
+//  ESP8266WiFiMulti wifiMulti;
+//  wifiMulti.addAP(WIFI_SSID_1, WIFI_PSK_1);
+//  wifiMulti.addAP(WIFI_SSID_2, WIFI_PSK_2);
+//  esp8266utils::setupWiFiSta(wifiMulti);

   // MDNS setup
-  MDNS_CFG.begin("esp8266");
-  MDNS.addService("http", "tcp", PORT);
-
-  // increase loop interval
-  SYS_CFG.setLoopInterval(20000);
+  const char* hostname = "esp8266";
+  if (MDNS.begin(hostname)) {
+    // add service to MDNS-SD
+    MDNS.addService("http", "tcp", 80);
+    VERBOSE_FP(F("MDNS enabled to http://%s.local"), hostname);
+  } else {
+     ERROR_FP(F("MDNS failed for http://%s.local"), hostname);
+  }

   // file system setup to enable static web server content
-  FILESYSTEM.begin();
-
-  // web server setup
-  SERVER.begin();
+  esp8266utils::FileSystem fs;
+  fs.begin();
+
+  // general web server setup
+  esp8266utils::WebService webService(80);
+  webService.begin();
   // rewrite root context
-  SERVER.getWebServer().rewrite("/", "/index.build.html");
+  webService.getWebServer().rewrite("/", "/index.html");
   // handle static web resources
-  SERVER.getWebServer().serveStatic("/", SPIFFS, "/www/", "max-age:15");
-  // cache-control 15 seconds
+  webService.getWebServer().serveStatic("/", SPIFFS, "/www/", "max-age:15");
+
   // add dynamic http resources
-  SERVER.on("/fs", HTTP_GET, [](AsyncWebServerRequest *request) {
-    SERVER.send(request, esp8266utils::APP_JSON, FILESYSTEM.getStorageDetails());
-  });
-  SERVER.on("/files", HTTP_GET, [](AsyncWebServerRequest *request) {
-    SERVER.send(request, esp8266utils::APP_JSON, FILESYSTEM.getFileListing());
-  });
-  SERVER.on("/sta", HTTP_GET, [](AsyncWebServerRequest *request) {
-    SERVER.send(request, esp8266utils::APP_JSON, WIFI_STA_CFG.getDetails());
-  });
-  SERVER.on("/ap", HTTP_GET, [](AsyncWebServerRequest *request) {
-    SERVER.send(request, esp8266utils::APP_JSON, WIFI_AP_CFG.getDetails());
-  });
-  SERVER.on("/esp", HTTP_GET, [](AsyncWebServerRequest *request) {
-    SERVER.send(request, esp8266utils::APP_JSON, SYS_CFG.getDetails());
-  });
-  SERVER.on("/motor_a", HTTP_GET, [](AsyncWebServerRequest *request) {
-    SERVER.send(request, esp8266utils::APP_JSON, _motorA.getDetails());
-  });
-  SERVER.on("/motor_b", HTTP_GET, [](AsyncWebServerRequest *request) {
-    SERVER.send(request, esp8266utils::APP_JSON, _motorB.getDetails());
-  });
+  webService.on("/fs", HTTP_GET, [&fs](AsyncWebServerRequest* request) {
+
+    AsyncResponseStream *response = request->beginResponseStream("application/json");
+    StreamString* payload = new StreamString();
+    size_t size = fs.serializeInfo(*payload);
+    response->print(*payload);
+    request->send(response);
+    delete payload;
+  });
+  webService.on("/files", HTTP_GET, [&fs](AsyncWebServerRequest* request) {
+
+    AsyncResponseStream *response = request->beginResponseStream("application/json");
+    StreamString* payload = new StreamString();
+    size_t size = fs.serializeListing(*payload);
+    response->print(*payload);
+    request->send(response);
+    delete payload;
+  });
+  webService.on("/ap", HTTP_GET, [](AsyncWebServerRequest* request) {
+
+    AsyncResponseStream *response = request->beginResponseStream("application/json");
+    StreamString* payload = new StreamString();
+    size_t size = esp8266utils::serializeWiFiAp(*payload);
+    response->print(*payload);
+    request->send(response);
+    delete payload;
+  });
+//  webService.on("/sta", HTTP_GET, [](AsyncWebServerRequest* request) {
+//
+//    AsyncResponseStream *response = request->beginResponseStream("application/json");
+//    StreamString* payload = new StreamString();
+//    size_t size = esp8266utils::serializeWiFiSta(*payload);
+//    response->print(*payload);
+//    request->send(response);
+//    delete payload;
+//  });
+  webService.on("/esp", HTTP_GET, [](AsyncWebServerRequest* request) {
+
+    AsyncResponseStream *response = request->beginResponseStream("application/json");
+    StreamString* payload = new StreamString();
+    size_t size = esp8266utils::serializeESP(*payload);
+    response->print(*payload);
+    request->send(response);
+    VERBOSE(*payload);
+    delete payload;
+  });
+  webService.on("/motor_a", HTTP_GET, [](AsyncWebServerRequest* request) {
+
+    AsyncResponseStream *response = request->beginResponseStream("application/json");
+    StreamString* payload = new StreamString();
+    size_t size = _motorA.serialize(*payload);
+    response->print(*payload);
+    request->send(response);
+    VERBOSE(*payload);
+    delete payload;
+  });
+  webService.on("/motor_b", HTTP_GET, [](AsyncWebServerRequest* request) {
+
+    AsyncResponseStream *response = request->beginResponseStream("application/json");
+    StreamString* payload = new StreamString();
+    size_t size = _motorB.serialize(*payload);
+    response->print(*payload);
+    VERBOSE(*payload);
+    request->send(response);
+    VERBOSE(*payload);
+    delete payload;
+  });
+
   // add web socket support
   _wsl.onTextMessage([](AsyncWebSocket *ws, AsyncWebSocketClient *client, AwsEventType type, AwsFrameInfo *info, uint8_t *data, size_t len) {

-    DynamicJsonBuffer buffer;
-    JsonObject &json = buffer.parse((char *)data);
-
-    if (json.success() && json["motorA"].success() && json["motorB"].success() && json["mode"].success()) {
-      int speedA = json["motorA"];
-      int speedB = json["motorB"];
-
-      const char *mode = json["mode"];
-
-      LOG.verbose(F("Set motor A = %d and motor B = %d, PWM range = %d"), speedA, speedB, _motorA.getPWMRange());
-
-      // decide which mode to use
-      if (strcmp("absolute", mode) == 0) {
-        _motorA.setSpeed(speedA);
-        _motorB.setSpeed(speedB);
-      } else {
-        _motorA.applySpeed(speedA);
-        _motorB.applySpeed(speedB);
-      }
-
-      // create JSON reply message
-      DynamicJsonBuffer buffer;
-      JsonObject &message = buffer.createObject();
-      message["clientId"] = client->id();
-      message["motorA"] = _motorA.getSpeed();
-      message["motorB"] = _motorB.getSpeed();
-
-      // send reply message
-      uint16_t length = message.measureLength() + 1;
-      char payload[length];
-      message.printTo(payload, length);
-      client->text(payload);
+    // extract request payload
+    char payload[len + 1];
+    snprintf(payload, len + 1, (char*)data);
+    VERBOSE_FP(F("Payload of request is: %s"), payload);
+
+    client->text("DONE");
+    return;
+
+    // try to parse payload as JSON
+    DynamicJsonDocument doc;
+    DeserializationError err = deserializeJson(doc, payload);
+    if (err) {
+      VERBOSE_F("Reading request failed: %s", err.c_str());
+      client->text(F("Received an unexpected message."));
     } else {
-      client->text(F("Received an unexpected message."));
+//      JsonObject request = doc.as<JsonObject>();
+//      int speedA = request["motorA"];
+//      int speedB = request["motorB"];
+//      char* mode = request["mode"];
+//      // decide which process mode to use
+//      if (strcmp("absolute", mode) == 0) {
+//        _motorA.setSpeed(speedA);
+//        _motorB.setSpeed(speedB);
+//      } else {
+//        _motorA.applySpeed(speedA);
+//        _motorB.applySpeed(speedB);
+//      }
+
+
+      // create JSON response
+//      DynamicJsonDocument doc2;
+//      JsonObject response = doc2.to<JsonObject>();
+//      response["clientId"] = client->id();
+//      response["motorA"] = _motorA.getSpeed();
+//      response["motorB"] = _motorB.getSpeed();
+
+//      StreamString* payload = new StreamString();
+//      serializeJson(response, payload);
+//      size_t size = measureJson(response);
+      //client->text(*payload);
+
+//      // send reply message
+//      uint16_t length = message.measureLength() + 1;
+//      char payload[length];
+//      message.printTo(payload, length);
+//      client->text(payload);
     }
   });
   // add web socket
@@ -136,20 +180,21 @@
   webSocket->onEvent([](AsyncWebSocket *ws, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
     _wsl.onEvent(ws, client, type, arg, data, len);
   });
-  SERVER.getWebServer().addHandler(webSocket);
-
-  LOG.verbose(F("========================="));
-  LOG.verbose(F("Setup finished. Have fun."));
-  LOG.verbose(F("========================="));
+  webService.getWebServer().addHandler(webSocket);
+
+  VERBOSE_FP(F("========================="));
+  VERBOSE_FP(F("Setup finished. Have fun."));
+  VERBOSE_FP(F("========================="));
 }

 void loop() {
-
-  ESP.wdtDisable();
-  if (SYS_CFG.nextLoopInterval()) {
+
+  if (millis() > nextLoopInterval) {
+    nextLoopInterval = millis() + 5000;
+
     MDNS.update();
   }
-  ESP.wdtEnable(30000);
+
   // reserve time for core processes
   delay(500);
-}+}


Fix spelling error

Fix spelling error

--- Guzheng/Guzheng.ino
+++ Guzheng/Guzheng.ino
@@ -278,7 +278,7 @@
       // has been pressed
       if (noteButtonState == 0) {
         // Swap the current note set
-        // TODO: FIgure out a better way to do this
+        // TODO: Figure out a better way to do this
         if (noteSet == 1) {
           noteSet = 2;
         } else {


Adapt optimal frequency for FS20

Adapt optimal frequency for FS20

--- ArduinoRFM69/rfm69-RF12demo-ook-TX/rfm69-RF12demo-ook-TX.ino
+++ ArduinoRFM69/rfm69-RF12demo-ook-TX/rfm69-RF12demo-ook-TX.ino
@@ -434,7 +434,7 @@
     setFrequency(434920);
     setBitrate(2667);
   } else {
-    setFrequency(868400);
+    setFrequency(868280);
     setBitrate(5000);
   }
 #else


add tri-state and right 74HC165 to sr0_LED_shiftRegs.ino


Use the NTP epoch instead of the default Y2K

--- examples/Time/CosaNTP/CosaNTP.ino
+++ examples/Time/CosaNTP/CosaNTP.ino
@@ -47,6 +47,13 @@
   trace.begin(&uart, PSTR("CosaNTP: started"));
   Watchdog::begin();
   RTC::begin();
+
+  time_t::epoch_year( NTP_EPOCH_YEAR );
+  time_t::epoch_weekday = NTP_EPOCH_WEEKDAY;
+  time_t::pivot_year = 37; // 1937..2036 range
+
+  // Note: This could also use_fastest_epoch if the clock_t offset was calculated
+  // when the RTC is initiated.  NTP::gettimeofday would need modification.

   // Initiate the Ethernet Controller using DHCP
   ASSERT(ethernet.begin_P(PSTR("CosaNTPclient")));


Refactored state machine Enums

Refactored state machine Enums

--- ppt/ppt.ino
+++ ppt/ppt.ino
@@ -52,10 +52,19 @@
 #define OFF_NUM             9             // number of iterations of off charger state

 #define PIN_LED             13            // LED connected to digital pin 13
+#define BUFF_MAX            16            // Maximum buffer size for receiving from serial

 //------------------------------------------------------------------------------------------------------
 // global variables
-enum charger_mode_t {off, mppt_on, auto_off, bulk, bat_float, const_volt, const_power, const_pwm};
+enum charger_mode_t {MODE_OFF,            // The system is off
+                     MODE_MPPT_ON,        // MPPT mode
+                     MODE_MPPT_OFF,       // MPPT auto-off mode
+                     MODE_MPPT_BULK,      // MPPT bulck charger
+                     MODE_MPPT_BAT_FLOAT, // MPPT batt float mode
+                     MODE_CONST_VOLT,     // Constant voltage mode
+                     MODE_CONST_POWER,    // Constant power mode
+                     MODE_CONST_DUTY      // Constant duty cycle mode
+                    };

 struct system_states_t {
    int sol_amps;                         // solar amps in 10 mV (scaled by 100)
@@ -151,10 +160,10 @@
   power_status.pwm_duty = pwm;                             // store this value in the status

   if (pwm < PWM_MAX) {
-    Timer1.pwm(PWM_PIN,pwm, 20); // use Timer1 routine to set pwm duty cycle at 20uS period
+    Timer1.pwm(PWM_PIN,pwm, 20);                           // use Timer1 routine to set pwm duty cycle at 20uS period
     //Timer1.pwm(PWM_PIN,(PWM_FULL * (long)pwm / 100));
   }
-  else if (pwm == PWM_MAX) {				  // if pwm set to 100% it will be on full but we have
+  else if (pwm == PWM_MAX) {				                      // if pwm set to 100% it will be on full but we have
     Timer1.pwm(PWM_PIN,(PWM_FULL - 1), 1000);             // keep switching so set duty cycle at 99.9% and slow down to 1000uS period
     //Timer1.pwm(PWM_PIN,(PWM_FULL - 1));
   }
@@ -167,7 +176,7 @@

   Serial.print(temp/100,DEC);        // divide by 100 and print interger value
   Serial.print(".");
-  if ((temp%100) < 10) {              // if fractional value has only one digit
+  if ((temp%100) < 10) {             // if fractional value has only one digit
     Serial.print("0");               // print a "0" to give it two digits
     Serial.print(temp%100,DEC);      // get remainder and print fractional value
   }
@@ -184,14 +193,14 @@
   Serial.print("  ");

   Serial.print("charger = ");
-  if (power_status.mode == off)              Serial.print("off    ");
-  else if (power_status.mode == mppt_on)     Serial.print("mppt   ");
-  else if (power_status.mode == auto_off)    Serial.print("autooff");
-  else if (power_status.mode == bulk)        Serial.print("bulk   ");
-  else if (power_status.mode == bat_float)   Serial.print("float  ");
-  else if (power_status.mode == const_volt)  Serial.print("volt   ");
-  else if (power_status.mode == const_power) Serial.print("watt   ");
-  else if (power_status.mode == const_pwm)   Serial.print("pwm    ");
+  if (power_status.mode == MODE_OFF)                 Serial.print("off    ");
+  else if (power_status.mode == MODE_MPPT_ON)        Serial.print("mppton ");
+  else if (power_status.mode == MODE_MPPT_OFF)       Serial.print("autooff");
+  else if (power_status.mode == MODE_MPPT_BULK)      Serial.print("bulk   ");
+  else if (power_status.mode == MODE_MPPT_BAT_FLOAT) Serial.print("float  ");
+  else if (power_status.mode == MODE_CONST_VOLT)     Serial.print("volt   ");
+  else if (power_status.mode == MODE_CONST_POWER)    Serial.print("watt   ");
+  else if (power_status.mode == MODE_CONST_DUTY)     Serial.print("duty   ");
   Serial.print("  ");

   Serial.print("target = ");
@@ -225,14 +234,14 @@
   Serial.print(seconds, DEC);

   Serial.print(", \"state\": ");
-  if (power_status.mode == off)              Serial.print("\"off\",    ");
-  else if (power_status.mode == mppt_on)     Serial.print("\"mppt\",   ");
-  else if (power_status.mode == auto_off)    Serial.print("\"autooff\",");
-  else if (power_status.mode == bulk)        Serial.print("\"bulk\",   ");
-  else if (power_status.mode == bat_float)   Serial.print("\"float\",  ");
-  else if (power_status.mode == const_volt)  Serial.print("\"volt\",   ");
-  else if (power_status.mode == const_power) Serial.print("\"watt\",   ");
-  else if (power_status.mode == const_pwm)   Serial.print("\"pwm\",   ");
+  if (power_status.mode == MODE_OFF)                 Serial.print("\"off\",    ");
+  else if (power_status.mode == MODE_MPPT_ON)        Serial.print("\"mppton\", ");
+  else if (power_status.mode == MODE_MPPT_OFF)       Serial.print("\"autooff\",");
+  else if (power_status.mode == MODE_MPPT_BULK)      Serial.print("\"bulk\",   ");
+  else if (power_status.mode == MODE_MPPT_BAT_FLOAT) Serial.print("\"float\",  ");
+  else if (power_status.mode == MODE_CONST_VOLT)     Serial.print("\"volt\",   ");
+  else if (power_status.mode == MODE_CONST_POWER)    Serial.print("\"watt\",   ");
+  else if (power_status.mode == MODE_CONST_DUTY)     Serial.print("\"duty\",   ");

   Serial.print(" \"target\": ");
   print_int100_dec2(power_status.target);
@@ -306,7 +315,7 @@

   static int old_sol_watts = 0;
   static int off_count = OFF_NUM;
-  static int delta = PWM_INC;                        // variable used to modify pwm duty cycle for the ppt algorithm
+  static int delta = PWM_INC;                   // variable used to modify pwm duty cycle for the ppt algorithm

   int pwm = power_status.pwm_duty;
   int sol_watts = power_status.sol_watts;
@@ -314,50 +323,50 @@
   int sol_volts = power_status.sol_volts;

   switch (power_status.mode) {
-    case mppt_on:
-      if (sol_watts < MIN_SOL_WATTS) {              //if watts input from the solar panel is less than
-        power_status.mode = auto_off;               //the minimum solar watts then it is getting dark so
-        off_count = OFF_NUM;                        //go to the charger off state
+    case MODE_MPPT_ON:
+      if (sol_watts < MIN_SOL_WATTS) {          //if watts input from the solar panel is less than
+        power_status.mode = MODE_MPPT_OFF;      //the minimum solar watts then it is getting dark so
+        off_count = OFF_NUM;                    //go to the charger off state
         TURN_OFF_MOSFETS;
       }
-      else if (bat_volts > MAX_BAT_VOLTS) {        //else if the battery voltage has gotten above the float
-        power_status.mode = bat_float;                 //battery float voltage go to the charger battery float state
-      }
-      else if (sol_watts < LOW_SOL_WATTS) {        //else if the solar input watts is less than low solar watts
-        pwm = PWM_MAX;                             //it means there is not much power being generated by the solar panel
-        set_pwm_duty(pwm);			   //so we just set the pwm = 100% so we can get as much of this power as possible
-      }                                            //and stay in the charger on state
+      else if (bat_volts > MAX_BAT_VOLTS) {       //else if the battery voltage has gotten above the float
+        power_status.mode = MODE_MPPT_BAT_FLOAT;  //battery float voltage go to the charger battery float state
+      }
+      else if (sol_watts < LOW_SOL_WATTS) {     //else if the solar input watts is less than low solar watts
+        pwm = PWM_MAX;                          //it means there is not much power being generated by the solar panel
+        set_pwm_duty(pwm);			                //so we just set the pwm = 100% so we can get as much of this power as possible
+      }                                         //and stay in the charger on state
       else {
         pwm = ((bat_volts * 10) / (sol_volts / 10)) + 5;  //else if we are making more power than low solar watts figure out what the pwm
-        power_status.mode = bulk;                              //value should be and change the charger to bulk state
-      }
-      break;
-    case bulk:
-      if (sol_watts < MIN_SOL_WATTS) {          //if watts input from the solar panel is less than
-        power_status.mode = auto_off;                    //the minimum solar watts then it is getting dark so
-        off_count = OFF_NUM;                    //go to the charger off state
+        power_status.mode = MODE_MPPT_BULK;               //value should be and change the charger to bulk state
+      }
+      break;
+    case MODE_MPPT_BULK:
+      if (sol_watts < MIN_SOL_WATTS) {         //if watts input from the solar panel is less than
+        power_status.mode = MODE_MPPT_OFF;     //the minimum solar watts then it is getting dark so
+        off_count = OFF_NUM;                   //go to the charger off state
         TURN_OFF_MOSFETS;
       }
-      else if (bat_volts > MAX_BAT_VOLTS) {     //else if the battery voltage has gotten above the float
-        power_status.mode = bat_float;              //battery float voltage go to the charger battery float state
-      }
-      else if (sol_watts < LOW_SOL_WATTS) {     //else if the solar input watts is less than low solar watts
-        power_status.mode = mppt_on;                     //it means there is not much power being generated by the solar panel
-        TURN_ON_MOSFETS;                        //so go to charger on state
-      }
-      else {                                    // this is where we do the Peak Power Tracking ro Maximum Power Point algorithm
-        if (old_sol_watts >= sol_watts) {       //   if previous watts are greater change the value of
-          delta = -delta;			// delta to make pwm increase or decrease to maximize watts
+      else if (bat_volts > MAX_BAT_VOLTS) {      //else if the battery voltage has gotten above the float
+        power_status.mode = MODE_MPPT_BAT_FLOAT; //battery float voltage go to the charger battery float state
+      }
+      else if (sol_watts < LOW_SOL_WATTS) {    //else if the solar input watts is less than low solar watts
+        power_status.mode = MODE_MPPT_ON;      //it means there is not much power being generated by the solar panel
+        TURN_ON_MOSFETS;                       //so go to charger on state
+      }
+      else {                                   // this is where we do the Peak Power Tracking ro Maximum Power Point algorithm
+        if (old_sol_watts >= sol_watts) {      // if previous watts are greater change the value of
+          delta = -delta;			                 // delta to make pwm increase or decrease to maximize watts
         }
-        pwm += delta;                           // add delta to change PWM duty cycle for PPT algorythm
-        old_sol_watts = sol_watts;              // load old_watts with current watts value for next time
-        set_pwm_duty(pwm);			// set pwm duty cycle to pwm value
-      }
-      break;
-    case bat_float:
-      if (sol_watts < MIN_SOL_WATTS) {          //if watts input from the solar panel is less than
-        power_status.mode = auto_off;                    //the minimum solar watts then it is getting dark so
-        off_count = OFF_NUM;                    //go to the charger off state
+        pwm += delta;                          // add delta to change PWM duty cycle for PPT algorythm
+        old_sol_watts = sol_watts;             // load old_watts with current watts value for next time
+        set_pwm_duty(pwm);			               // set pwm duty cycle to pwm value
+      }
+      break;
+    case MODE_MPPT_BAT_FLOAT:
+      if (sol_watts < MIN_SOL_WATTS) {         //if watts input from the solar panel is less than
+        power_status.mode = MODE_MPPT_OFF;     //the minimum solar watts then it is getting dark so
+        off_count = OFF_NUM;                   //go to the charger off state
         set_pwm_duty(pwm);
         TURN_OFF_MOSFETS;
       }
@@ -369,28 +378,28 @@
         pwm += 1;                              //increment the pwm to get it back up to the float voltage
         set_pwm_duty(pwm);
         if (pwm >= 100) {                      //if pwm gets up to 100 it means we can't keep the battery at
-          power_status.mode = bulk;                //float voltage so jump to charger bulk state to charge the battery
+          power_status.mode = MODE_MPPT_BULK;  //float voltage so jump to charger bulk state to charge the battery
         }
       }
       break;
-    case auto_off:                                  //when we jump into the charger off state, off_count is set with OFF_NUM
-      if (off_count > 0) {                     //this means that we run through the off state OFF_NUM of times with out doing
-        off_count--;                           //anything, this is to allow the battery voltage to settle down to see if the
-      }                                        //battery has been disconnected
+    case MODE_MPPT_OFF:                           //when we jump into the charger off state, off_count is set with OFF_NUM
+      if (off_count > 0) {                        //this means that we run through the off state OFF_NUM of times with out doing
+        off_count--;                              //anything, this is to allow the battery voltage to settle down to see if the
+      }                                           //battery has been disconnected
       else if ((bat_volts > HIGH_BAT_VOLTS) && (bat_volts < MAX_BAT_VOLTS) && (sol_volts > bat_volts)) {
-        power_status.mode = bat_float;             //if battery voltage is still high and solar volts are high
-        set_pwm_duty(pwm);		       //change charger state to battery float
+        power_status.mode = MODE_MPPT_BAT_FLOAT;  //if battery voltage is still high and solar volts are high
+        set_pwm_duty(pwm);		                    //change charger state to battery float
         TURN_ON_MOSFETS;
       }
       else if ((bat_volts > MIN_BAT_VOLTS) && (bat_volts < MAX_BAT_VOLTS) && (sol_volts > bat_volts)) {
         pwm = PWM_START;                        // if battery volts aren't quite so high but we have solar volts
         set_pwm_duty(pwm);			                // greater than battery volts showing it is day light then
-        power_status.mode = mppt_on;            // change charger state to on so we start charging
+        power_status.mode = MODE_MPPT_ON;       // change charger state to on so we start charging
         TURN_ON_MOSFETS;
       }
       break;
     default:
-      TURN_OFF_MOSFETS;                        //else stay in the off state
+      TURN_OFF_MOSFETS;                         //else stay in the off state
       break;
   }
 }
@@ -421,31 +430,31 @@
 void state_switch(charger_mode_t mode, int target = 0) {

   switch (mode) {
-    case off:
+    case MODE_OFF:
       TURN_OFF_MOSFETS;
       power_status.mode = mode;
       break;

-    case const_volt:
+    case MODE_CONST_VOLT:
       TURN_ON_MOSFETS;
       power_status.mode = mode;
       power_status.target = target;
       break;

-    case const_power:
+    case MODE_CONST_POWER:
       TURN_ON_MOSFETS;
       power_status.mode = mode;
       power_status.target = target;
       break;

-    case const_pwm:
-      TURN_ON_MOSFETS;
+    case MODE_CONST_DUTY:
       power_status.mode = mode;
       power_status.target = target;
       set_pwm_duty((long)target * (PWM_FULL - 1) / 10000);
-      break;
-
-    case mppt_on:
+      TURN_ON_MOSFETS;
+      break;
+
+    case MODE_MPPT_ON:
       TURN_ON_MOSFETS;
       power_status.mode = mode;
       break;
@@ -458,18 +467,17 @@
 // State machine for different modes
 void state_machine(void) {
   switch (power_status.mode) {
-    case const_volt:
+    case MODE_CONST_VOLT:
       adjust_pwm(power_status.target - power_status.bat_volts);
       break;
-    case const_power:
+    case MODE_CONST_POWER:
       adjust_pwm(power_status.target - power_status.sol_watts);
       break;
-    case const_pwm:
-      break; // nothing to be done in constant pwm mode, as it is already set
-    case off:
+    case MODE_CONST_DUTY:
+      break; // nothing to be done in constant duty pwm mode, as duty cycle is already set in "state_switch"
+    case MODE_OFF:
       break; // do nothing if it is in off mode
-    // other cases: call mppt state-machine
-    default:
+    default: // other cases: call mppt state-machine
       MPPT_state_machine();
       break;
   }
@@ -489,19 +497,19 @@
   #define stricmp strcasecmp // strangely, arduino uses a different API

   if(!stricmp(cmd,"P")) {
-    state_switch(const_power,val);
+    state_switch(MODE_CONST_POWER, val);
   }
   else if(!stricmp(cmd,"V")) {
-    state_switch(const_volt,val);
+    state_switch(MODE_CONST_VOLT, val);
   }
   else if(!stricmp(cmd,"PWM")) {
-    state_switch(const_pwm,val);
+    state_switch(MODE_CONST_DUTY, val);
   }
   else if(!stricmp(cmd,"MPPT") && val) {
-    state_switch(mppt_on);
+    state_switch(MODE_MPPT_ON);
   }
   else if(!stricmp(cmd,"OFF") && val) {
-    state_switch(off);
+    state_switch(MODE_OFF);
   }
   else {
     Serial.print("{\"time\": ");
@@ -528,8 +536,8 @@
   lpf_out_volts.Init();
   lpf_in_amps.Init();

-  //state_switch(off);                       // start with charger state as off
-  state_switch(const_volt, 300);                       // start with charger state as off
+  state_switch(MODE_OFF);                     // start with charger state as off
+  //state_switch(MODE_CONST_VOLT, 300);                       // start with charger state as off
 }

 //------------------------------------------------------------------------------------------------------
@@ -558,8 +566,8 @@
       current_target = 400;
     }

-    state_switch(const_power, current_target);
-    //state_switch(const_volt, current_target);
+    state_switch(MODE_CONST_POWER, current_target);
+    //state_switch(MODE_CONST_VOLT, current_target);
   }*/

   if (Serial.available() >= 4) {