Added better power management.  Cleaned up code and added comments.

--- modules/doorbellunit/doorbellunit.ino
+++ modules/doorbellunit/doorbellunit.ino
@@ -38,15 +38,16 @@
 // Define the NRF24L01+ radio object
 RF24 radio(CE_PIN, CSN_PIN);

-const int button = 3;
-const int led = 4;
-const int debounceDelay = 500;
-const int activityTimeout = 30000;
+const int button            = 3;
+const int led               = 4;
+const int nrfModulePowerPin = 6;
+const int debounceDelay     = 500;
+const int activityTimeout   = 10000;

 volatile bool ringRequested = false;
-volatile int lastPressed = 0;
-
-bool ledOn = false;
+volatile int lastPressed    = 0;
+
+bool ledOn                  = false;
 bool startingUp;

@@ -55,9 +56,17 @@
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void initializeComm()
 {
+    // We're powering the radio through digital pin 6 so that we can totally
+    // turn off power to it during sleep cycle.
+    // Set the pin high to turn on power to the NRF24L01+.
+    digitalWrite( nrfModulePowerPin, HIGH );
+
+    // Set up the message that we will be sending to the base station when someone
+    // presses the doorbell button.
     message[0] = 517;       // Network ID
     message[1] = 1;         // Unit ID

+    // Fire up the layzar!!
     radio.begin();
     radio.openWritingPipe( pipe );

@@ -65,12 +74,12 @@
 }

 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Flashes the LED, and sends a ring message to the base station.
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void sendNotify()
 {
     radio.write( message, sizeof( message ) );
-
-    flashLed(4);
+    flashLed( 1 );
 }

 /* ------------------- MAIN HANDLERS & LOOP -------------------------------- */
@@ -81,19 +90,20 @@
 {
     for (byte i = 0; i < repeat; i++)
     {
-        digitalWrite(led, LOW);
-        delay(100);
-        digitalWrite(led, HIGH);
-        delay(100);
-    }
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+        digitalWrite( led, LOW );
+        delay( 100 );
+        digitalWrite( led, HIGH );
+        delay( 100 );
+    }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Handle the button pressed event
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void buttonPressed()
 {
     // Handle button debouncing by not handling a button press within 1 second of the previous press.
-    if ( !startingUp && !ringRequested && (millis() - lastPressed > debounceDelay) )
+    if ( !startingUp && !ringRequested && ( millis() - lastPressed > debounceDelay) )
     {
         ringRequested = true;
         ledOn = true;
@@ -104,6 +114,7 @@
 }

 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// The interrupts to wake us up has been triggered by a button press
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void wakeUp()
 {
@@ -117,18 +128,18 @@
         Serial.println("wake!");
     #endif

-    // Restore AVR peripherals used elsewhere in the code
-    power_usart0_enable(); // Enable Serial
-    power_timer0_enable(); // Enable millis() etc.
-    power_spi_enable();    // Enable SPI
+//    // Restore AVR peripherals used elsewhere in the code
+//    power_usart0_enable(); // Enable Serial
+//    power_timer0_enable(); // Enable millis() etc.
+//    power_spi_enable();    // Enable SPI
+
+    // Set up button to trigger an interrupt.
+    attachInterrupt( INT1, buttonPressed, FALLING );
+
+    delay(50);

     // Turn on the NRF24L01+ radio.
-    radio.powerUp();
-
-    // Set up button to trigger an interrupt.
-    attachInterrupt(INT1, buttonPressed, FALLING);
-
-    delay(50);
+    initializeComm();

     // Simulate button press to set the correct flags
     buttonPressed();
@@ -143,26 +154,27 @@
 void goToSleep(void)
 {
     noInterrupts();
-    detachInterrupt(INT1);
-    delay(50);
-    attachInterrupt(INT1, wakeUp, LOW);
+    detachInterrupt( INT1 );
+    attachInterrupt( INT1, wakeUp, LOW );
+    delay(50);
     interrupts();
-    delay(50);
-
-    digitalWrite(led, LOW);
-
-    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
-    sleep_enable();
-
-    radio.powerDown();
-
-    power_spi_disable();    // Disable SPI
-    delay(50);              // Stall for last serial output
-    power_timer0_disable(); // Disable millis() etc.
-    power_usart0_disable(); // Disable Serial
+
+    // Ensure that the LED is off
+    digitalWrite( led, LOW );
+
+    // Disconnect power to the NRF24L01+ radio
+    digitalWrite( nrfModulePowerPin, LOW );
+
+    // Initialize sleep mode
+    SMCR |= (1 << 2);  // Power down mode
+    SMCR |= 1;        // Enable sleep
+
+    // Disable brownout detection
+    MCUCR |= (3 << 5);
+    MCUCR = (MCUCR & ~(1 << 5)) | (1 << 6);

     // Go to sleep
-    sleep_mode();
+    __asm__ __volatile("sleep");

     /* The program will continue from here. */
     // ....
@@ -188,17 +200,33 @@
         Serial.print("Configuring...");
     #endif

-    pinMode(button, INPUT_PULLUP);
-    pinMode(led, OUTPUT);
-
+    // Set all pins as output by default.  This reduces power.
+    for ( int pin = 1; pin <= 20; pin++ )
+    {
+        if ( pin != button )
+        {
+            pinMode( pin, OUTPUT );
+            digitalWrite( pin, LOW );
+        }
+    }
+
+
+    // Disable the Analog/Digital Converter.  Don't need it.
+    ADCSRA &= ~(1 << 7);
+
+    // Now let's set only the button pin differently.
+    pinMode( button, INPUT_PULLUP );
+
+    // Set up the NRF24L01+ radio to be ready to communicate
     initializeComm();

-    flashLed(3);
+    // Flash things to let the doorbell user know that something is going on
+    flashLed(2);
     ledOn = true;

     // Set up button to trigger an interrupt.
     noInterrupts();
-    attachInterrupt(INT1, buttonPressed, FALLING);
+    attachInterrupt( INT1, buttonPressed, FALLING );
     interrupts();
     delay(50);

@@ -238,8 +266,8 @@

     if ( timePassed > activityTimeout )
     {
-        flashLed(4);
-        digitalWrite(led, LOW);
+        flashLed(2);
+        digitalWrite( led, LOW );
         ledOn = false;

         goToSleep();
@@ -248,7 +276,7 @@
     {
         // When the button is pressed, flash the LED every half a second for 2 seconds
         // to let the user know that something is happening.
-        if ( timePassed < 2000 && (0 < (timePassed % 500) < 10) )
+        if ( timePassed < 1500 && (0 < (timePassed % 500) < 10) )
         {
             flashLed(1);
         }


Delete Arduino_RTC_example1.ino

Delete Arduino_RTC_example1.ino

--- Arduino_RTC_example1.ino
+++ Arduino_RTC_example1.ino
@@ -1,79 +0,0 @@
-// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
-#include <Wire.h>
-#include "RTClib.h"
-
-#if defined(ARDUINO_ARCH_SAMD)
-// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
-   #define Serial SerialUSB
-#endif
-
-RTC_PCF8523 rtc;
-
-char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
-
-void setup () {
-
-#ifndef ESP8266
-  while (!Serial); // for Leonardo/Micro/Zero
-#endif
-
-  Serial.begin(57600);
-  if (! rtc.begin()) {
-    Serial.println("Couldn't find RTC");
-    while (1);
-  }
-
-  if (! rtc.initialized()) {
-    Serial.println("RTC is NOT running!");
-    // following line sets the RTC to the date & time this sketch was compiled
-    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
-    // This line sets the RTC with an explicit date & time, for example to set
-    // January 21, 2014 at 3am you would call:
-    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
-  }
-}
-
-void loop () {
-    DateTime now = rtc.now();
-
-    Serial.print(now.year(), DEC);
-    Serial.print('/');
-    Serial.print(now.month(), DEC);
-    Serial.print('/');
-    Serial.print(now.day(), DEC);
-    Serial.print(" (");
-    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
-    Serial.print(") ");
-    Serial.print(now.hour(), DEC);
-    Serial.print(':');
-    Serial.print(now.minute(), DEC);
-    Serial.print(':');
-    Serial.print(now.second(), DEC);
-    Serial.println();
-
-    Serial.print(" since midnight 1/1/1970 = ");
-    Serial.print(now.unixtime());
-    Serial.print("s = ");
-    Serial.print(now.unixtime() / 86400L);
-    Serial.println("d");
-
-    // calculate a date which is 7 days and 30 seconds into the future
-    DateTime future (now + TimeSpan(7,12,30,6));
-
-    Serial.print(" now + 7d + 30s: ");
-    Serial.print(future.year(), DEC);
-    Serial.print('/');
-    Serial.print(future.month(), DEC);
-    Serial.print('/');
-    Serial.print(future.day(), DEC);
-    Serial.print(' ');
-    Serial.print(future.hour(), DEC);
-    Serial.print(':');
-    Serial.print(future.minute(), DEC);
-    Serial.print(':');
-    Serial.print(future.second(), DEC);
-    Serial.println();
-
-    Serial.println();
-    delay(3000);
-}


fix arduino bugs...

fix arduino bugs...

--- spherical_laser_projector/spherical_laser_projector.ino
+++ spherical_laser_projector/spherical_laser_projector.ino
@@ -27,7 +27,7 @@
 | By A.E.TEC (Arad Eizen) 2016.                                                |
 |	                                                                           |
 \******************************************************************************/
-#include "arial_font.h"
+// #include "arial_font.h"

 #define X_AXIS_LIMIT_MIN			(-200)
 #define Y_AXIS_LIMIT_MIN			(-100)
@@ -38,9 +38,7 @@
 #define SERIAL_BUFFER_SIZE			(60)

 #define STEPS_PER_RADIAN			(648.68)
-#define STEP_DELAY_MS				(20)
-#define LASER_POINTS_COUNT			(256)
-#define LASER_MASKS_COUNT			(LASER_POINTS_COUNT / 8)
+#define STEP_DELAY_MS				(4)

 #define X_AXIS_A_PIN				(4)
 #define X_AXIS_B_PIN				(5)
@@ -86,9 +84,9 @@
 /* turn laser on or off (pull mosfet gate down to turn the laser on) */
 void set_laser(bool is_on) {
 	if (is_on)
-		DDRB &= ~LASER_MASK;
+		PORTB |= LASER_MASK;
 	else
-		DDRB |= LASER_MASK;
+		PORTB &= ~LASER_MASK;
 }

 /* go to the given axes position from current motors position */
@@ -101,7 +99,7 @@
 void relative_steps(xy_point * p) {
 	int32_t steps, err, e;
 	xy_point delta = {abs(p->x), abs(p->y)};
-	xy_point step = {(p->x > 0 ? 1 : (p->x < 0 ? -1 : 0)), (p->y > 0 ? 1 : (p->y < 0 ? -1 : 0)};
+	xy_point step = {(p->x > 0 ? 1 : (p->x < 0 ? -1 : 0)), (p->y > 0 ? 1 : (p->y < 0 ? -1 : 0))};

 	steps = max(delta.x, delta.y);
 	err = (delta.x > delta.y ? delta.x : -delta.y) / 2;
@@ -130,7 +128,7 @@
 /* turn laser off and put projector in home position */
 void go_home() {
 	xy_point p = {0, 0};
-	set_laser(0);
+	set_laser(false);
 	absolute_steps(&p);
 }

@@ -152,7 +150,7 @@
 	disable_axes();
 }

-void get_path_size(char * path, xy_point * p) {
+/*void get_path_size(char * path, xy_point * p) {

 }

@@ -170,10 +168,10 @@

 void draw_path(char * path, xy_point * p) {

-}
+}*/

 /* draw a NULL terminated string */
-void draw_text(char * text, xy_point * p) {
+/*void draw_text(char * text, xy_point * p) {
 	xy_point tmp;

 	if (text_right_diraction) {
@@ -183,19 +181,20 @@
 	draw_path
 	while (*text)
 		x += draw_char(x, y, *text++, scale) + 1;
-}
+}*/

 /* called once at power-on */
 void setup() {
 	Serial.begin(SERIAL_BAUDRATE);
 	DDRD |= 0xF0;				// (4 - 7) OUTPUTS
 	DDRC |= 0x0F;				// (A0 - A3) OUTPUTS
-	PORTB &= ~LASER_MASK;		// (8) LOW for laser outputs
-	set_laser(0);				// turn off laser
+	DDRB |= LASER_MASK;			// (8) OUTPUT
+	set_laser(false);			// turn off laser
 	set_home();
 }

 /* called repeatedly after "setup" */
-void loop() {
-
-}
+void loop() {
+	xy_point tmp = {0, 0};
+	draw_polygon(&tmp, 4, 100, 0);
+}


Update Razor_AHRS.ino

Update Razor_AHRS.ino

--- sandbox/Razor_AHRS/Razor_AHRS.ino
+++ sandbox/Razor_AHRS/Razor_AHRS.ino
@@ -550,7 +550,7 @@

           output_mode = OUTPUT__MODE_BOTH_CALIB;
           if (format_param == 't') // Output values in _t_ext format
-            output_format = OUTPUT__FORMAT_BINARY;
+            output_format = OUTPUT__FORMAT_TEXT;
           else if (format_param == 'b') // Output values in _b_inary format
             output_format = OUTPUT__FORMAT_BINARY;
         }


Fix to allow non-binary console logging of incoming canbus messages

--- GVRET.ino
+++ GVRET.ino
@@ -211,7 +211,7 @@
 {
 	uint8_t buff[18];
 	uint8_t temp;
-	if (binaryComm) {
+	if (settings.useBinarySerialComm) {
 		if (frame.extended) frame.id |= 1 << 31;
 		buff[0] = 0xF1;
 		buff[1] = 0; //0 = canbus frame sending


fixing breaking arduino code

fixing breaking arduino code

--- arduino/OpenROV.ino
+++ arduino/OpenROV.ino
@@ -24,7 +24,6 @@

   motors.reset();
   led.reset();
-  count = 0;
 }

 void loop(){


AlAlAl

AlAlAl

--- arduino/arduino.ino
+++ arduino/arduino.ino
@@ -6,18 +6,21 @@
 #include "HMC5883L.h"
 #include "BMP085.h"
 #include "ArduinoJson.h"
-
-int N_SAMPLE = 1;
+#include "Servo.h"

 MPU6050 mpu6050;
 HMC5883L hmc5883l;
 BMP085 bmp085;
 Measure meas;
+Servo servo[4];
+const int SERVO_PIN[4] = {9, 10, 11, 12};
 int64_t lastMicros = 0;
+double global_time_offset = 0;
 /* SoftwareSerial piSerial(10, 11); */
 #define piSerial Serial
-char indata[100];
-float testval;
+char indata[256];
+int motor[4];
+int pos;

 void setup() {
   // put your setup code here, to run once:
@@ -38,6 +41,16 @@

   bmp085.setControl(BMP085_MODE_TEMPERATURE);

+  for(int i=0; i<4; i++)
+  {
+    servo[i].attach(SERVO_PIN[i]);
+    servo[i].writeMicroseconds(0);
+  }
+}
+
+double gettime()
+{
+  return global_time_offset + micros() * 1E-6;
 }

 Measure& read_data() {
@@ -83,33 +96,63 @@
 {
   if(piSerial.available() == 0)
     return;
-  int pos = 0;
+  int cnt = 0;
   while(piSerial.available() > 0)
   {
+    cnt++;
     int c = piSerial.read();
-    /* piSerial.print((unsigned int8_t)(c)); */
-    /* piSerial.print(","); */
     indata[pos] = c;
     pos += 1;
-    if(c == '\n' || piSerial.available() <= 0)
+    if(c == '\n')
     {
       indata[pos-1] = '\0';
       pos = 0;
     }
   }

+  if(pos > 0) return;
+
+  /* piSerial.print("Total Cnt = "); */
+  /* piSerial.println(cnt); */
+  /* piSerial.print("Raw data = "); */
+  /* piSerial.println(indata); */
+
+  piSerial.println(indata);
+  piSerial.flush();
+
+  //Parse Json
+  StaticJsonBuffer<256> jsonBuffer;
+  JsonObject& root = jsonBuffer.parseObject(indata);
+  if(!root.success()) return;
+  if(!root.containsKey("motor")) return;
+  if(!root["motor"].is<JsonArray&>()) return;
+  JsonArray& marr = root["motor"];
+  for(int i=0; i<4; i++)
+    motor[i] = marr[i];
+
+  /* for(int i=0; i<4; i++) */
+  /* { */
+    /* piSerial.print(motor[i]); */
+    /* piSerial.print(","); */
+  /* } */
   /* piSerial.println(""); */
-  /* piSerial.println(cnt); */
-  piSerial.print("Data : ");
-  piSerial.println(indata);
-
+  /* piSerial.flush(); */
+}
+
+void set_motor()
+{
+  for(int i=0; i<4; i++)
+  {
+    servo[i].writeMicroseconds(motor[i]);
+  }
 }

 void print_json(Measure &meas)
 {
   StaticJsonBuffer<256> jsonBuffer;
   JsonObject& root = jsonBuffer.createObject();
-  root["time"] = micros();
+  root["time"].set(gettime(), 6);
+  root["timez"].set(global_time_offset, 6);

   JsonArray& arr_acc = root.createNestedArray("accel");
   arr_acc.add(meas.accel.x, 3);
@@ -130,15 +173,15 @@
   root["pressure"].set(meas.pressure, 0);

   root.printTo(piSerial);
-  /* piSerial.print(micros()); */
   piSerial.println("");
+
+  piSerial.flush();
 }

 void print_data(Measure &meas)
 {
-
   Serial.print(F("Time : "));
-  Serial.print(micros());
+  Serial.print(gettime(), 6);
   Serial.println(F(""));

   Serial.print(F("accel : "));
@@ -174,20 +217,12 @@
   Serial.println(F(""));
 }

-int scnt = 0;
-Measure ms;
 void loop()
 {
-  piSerial.println("\"A\"");
   read_json();
-  ms += read_data();
-  scnt++;
-  if(scnt == N_SAMPLE)
-  {
-    scnt = 0;
-    ms *= 1.0 / N_SAMPLE;
-    /* print_json(ms); */
-    ms = Measure();
-    delay(1000);
-  }
-}
+  set_motor();
+  Measure ms = read_data();
+  print_json(ms);
+  ms = Measure();
+  /* delay(1000); */
+}


Implement HASP support for subscribing to group commands

--- Arduino_Sketch/HASwitchPlate/HASwitchPlate.ino
+++ Arduino_Sketch/HASwitchPlate/HASwitchPlate.ino
@@ -37,6 +37,7 @@
 char mqttUser[32] = "";
 char mqttPassword[32] = "";
 char haspNode[16] = "plate01";
+char groupName[16] = "plates";
 char configUser[32] = "admin";
 char configPassword[32] = "";
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -100,6 +101,7 @@
 String mqttGetSubtopic;                          // MQTT subtopic for incoming commands requesting .val
 String mqttStateTopic;                           // MQTT topic for outgoing panel interactions
 String mqttCommandTopic;                         // MQTT topic for incoming panel commands
+String mqttGroupCommandTopic;                    // MQTT topic for incoming group panel commands
 String mqttStatusTopic;                          // MQTT topic for publishing device connectivity state
 String mqttSensorTopic;                          // MQTT topic for publishing device information in JSON format
 String mqttLightCommandTopic;                    // MQTT topic for incoming panel backlight on/off commands
@@ -255,6 +257,7 @@
   // MQTT topic string definitions
   mqttStateTopic = "hasp/" + String(haspNode) + "/state";
   mqttCommandTopic = "hasp/" + String(haspNode) + "/command";
+  mqttGroupCommandTopic = "hasp/" + String(groupName) + "/command";
   mqttStatusTopic = "hasp/" + String(haspNode) + "/status";
   mqttSensorTopic = "hasp/" + String(haspNode) + "/sensor";
   mqttLightCommandTopic = "hasp/" + String(haspNode) + "/light/switch";
@@ -263,6 +266,7 @@
   mqttLightBrightStateTopic = "hasp/" + String(haspNode) + "/brightness/status";

   const String mqttCommandSubscription = mqttCommandTopic + "/#";
+  const String mqttGroupCommandSubscription = mqttGroupCommandTopic + "/#";
   const String mqttLightSubscription = "hasp/" + String(haspNode) + "/light/#";
   const String mqttLightBrightSubscription = "hasp/" + String(haspNode) + "/brightness/#";

@@ -288,9 +292,17 @@
       {
         debugPrintln(String(F("MQTT: subscribed to ")) + mqttCommandTopic);
       }
+      if (mqttClient.subscribe(mqttGroupCommandTopic))
+      {
+        debugPrintln(String(F("MQTT: subscribed to ")) + mqttGroupCommandTopic);
+      }
       if (mqttClient.subscribe(mqttCommandSubscription))
       {
         debugPrintln(String(F("MQTT: subscribed to ")) + mqttCommandSubscription);
+      }
+      if (mqttClient.subscribe(mqttGroupCommandSubscription))
+      {
+        debugPrintln(String(F("MQTT: subscribed to ")) + mqttGroupCommandSubscription);
       }
       if (mqttClient.subscribe(mqttStatusTopic))
       {
@@ -342,39 +354,56 @@

   // Incoming Namespace:
   // '[...]/device/command' -m '' = undefined
+  // '[...]/group/command' -m '' = undefined
   // '[...]/device/command' -m 'dim 50' = sendNextionCmd("dim 50")
   // '[...]/device/command/page' -m '1' = sendNextionCmd("page 1")
+  // '[...]/group/command/page' -m '1' = sendNextionCmd("page 1")
   // '[...]/device/command/lcdupdate' -m 'http://192.168.0.10/local/HASwitchPlate.tft' = startNextionOtaDownload("http://192.168.0.10/local/HASwitchPlate.tft")
+  // '[...]/group/command/lcdupdate' -m 'http://192.168.0.10/local/HASwitchPlate.tft' = startNextionOtaDownload("http://192.168.0.10/local/HASwitchPlate.tft")
   // '[...]/device/command/lcdupdate' -m '' = startNextionOtaDownload("lcdFirmwareUrl")
+  // '[...]/group/command/lcdupdate' -m '' = startNextionOtaDownload("lcdFirmwareUrl")
   // '[...]/device/command/espupdate' -m 'http://192.168.0.10/local/HASwitchPlate.ino.d1_mini.bin' = startEspOTA("http://192.168.0.10/local/HASwitchPlate.ino.d1_mini.bin")
+  // '[...]/group/command/espupdate' -m 'http://192.168.0.10/local/HASwitchPlate.ino.d1_mini.bin' = startEspOTA("http://192.168.0.10/local/HASwitchPlate.ino.d1_mini.bin")
   // '[...]/device/command/espupdate' -m '' = startEspOTA("espFirmwareUrl")
+  // '[...]/group/command/espupdate' -m '' = startEspOTA("espFirmwareUrl")
   // '[...]/device/command/p[1].b[4].txt' -m '' = getNextionAttr("p[1].b[4].txt")
+  // '[...]/group/command/p[1].b[4].txt' -m '' = getNextionAttr("p[1].b[4].txt")
   // '[...]/device/command/p[1].b[4].txt' -m '"Lights On"' = setNextionAttr("p[1].b[4].txt", "\"Lights On\"")
+  // '[...]/group/command/p[1].b[4].txt' -m '"Lights On"' = setNextionAttr("p[1].b[4].txt", "\"Lights On\"")

   debugPrintln(String(F("MQTT IN:  '")) + strTopic + "' : '" + strPayload + "'");

-  if ((strTopic == mqttCommandTopic) && (strPayload == ""))
+  if (((strTopic == mqttCommandTopic) || (strTopic == mqttGroupCommandTopic)) && (strPayload == ""))
   { // '[...]/device/command' -m '' = undefined
+    // '[...]/group/command' -m '' = undefined
     // currently undefined
   }
-  else if (strTopic == mqttCommandTopic)
+  else if (strTopic == mqttCommandTopic
+        || strTopic == mqttGroupCommandTopic)
   { // '[...]/device/command' -m 'dim 50' == sendNextionCmd("dim 50")
+    // '[...]/group/command' -m 'dim 50' == sendNextionCmd("dim 50")
     sendNextionCmd(strPayload);
   }
-  else if (strTopic == (mqttCommandTopic + "/page"))
+  else if (strTopic == (mqttCommandTopic + "/page")
+        || strTopic == (mqttGroupCommandTopic + "/page"))
   { // '[...]/device/command/page' -m '1' == sendNextionCmd("page 1")
+    // '[...]/group/command/page' -m '1' == sendNextionCmd("page 1")
     if (nextionActivePage != strPayload.toInt())
     { // Hass likes to send duplicate responses to things like page requests and there are no plans to fix that behavior, so try and track it locally
       nextionActivePage = strPayload.toInt();
       sendNextionCmd("page " + strPayload);
     }
   }
-  else if (strTopic == (mqttCommandTopic + "/statusupdate"))
-  {                     // '[...]/device/command/statusupdate' == mqttStatusUpdate()
+  else if (strTopic == (mqttCommandTopic + "/statusupdate")
+        || strTopic == (mqttGroupCommandTopic + "/statusupdate"))
+  { // '[...]/device/command/statusupdate' == mqttStatusUpdate()
+    // '[...]/group/command/statusupdate' == mqttStatusUpdate()
     mqttStatusUpdate(); // return status JSON via MQTT;
   }
-  else if (strTopic == (mqttCommandTopic + "/lcdupdate"))
+  else if (strTopic == (mqttCommandTopic + "/lcdupdate")
+        || strTopic == (mqttGroupCommandTopic + "/lcdupdate"))
   { // '[...]/device/command/lcdupdate' -m 'http://192.168.0.10/local/HASwitchPlate.tft' == startNextionOtaDownload("http://192.168.0.10/local/HASwitchPlate.tft")
+    // '[...]/group/command/lcdupdate' -m 'http://192.168.0.10/local/HASwitchPlate.tft' == startNextionOtaDownload("http://192.168.0.10/local/HASwitchPlate.tft")
     if (strPayload == "")
     {
       startNextionOtaDownload(lcdFirmwareUrl);
@@ -384,8 +413,10 @@
       startNextionOtaDownload(strPayload);
     }
   }
-  else if (strTopic == (mqttCommandTopic + "/espupdate"))
+  else if (strTopic == (mqttCommandTopic + "/espupdate")
+        || strTopic == (mqttGroupCommandTopic + "/espupdate"))
   { // '[...]/device/command/espupdate' -m 'http://192.168.0.10/local/HASwitchPlate.ino.d1_mini.bin' == startEspOTA("http://192.168.0.10/local/HASwitchPlate.ino.d1_mini.bin")
+    // '[...]/group/command/espupdate' -m 'http://192.168.0.10/local/HASwitchPlate.ino.d1_mini.bin' == startEspOTA("http://192.168.0.10/local/HASwitchPlate.ino.d1_mini.bin")
     if (strPayload == "")
     {
       startEspOTA(espFirmwareUrl);
@@ -395,13 +426,17 @@
       startEspOTA(strPayload);
     }
   }
-  else if (strTopic == (mqttCommandTopic + "/reboot"))
+  else if (strTopic == (mqttCommandTopic + "/reboot")
+        || strTopic == (mqttGroupCommandTopic + "/reboot"))
   { // '[...]/device/command/reboot' == reboot microcontroller)
+    // '[...]/group/command/reboot' == reboot microcontroller)
     debugPrintln(F("MQTT: Rebooting device"));
     espReset();
   }
-  else if (strTopic == (mqttCommandTopic + "/factoryreset"))
+  else if (strTopic == (mqttCommandTopic + "/factoryreset")
+        || strTopic == (mqttGroupCommandTopic + "/factoryreset"))
   { // '[...]/device/command/factoryreset' == clear all saved settings)
+    // '[...]/group/command/factoryreset' == clear all saved settings)
     clearSavedConfig();
   }
   else if (strTopic.startsWith(mqttCommandTopic) && (strPayload == ""))
@@ -410,9 +445,20 @@
     mqttGetSubtopic = "/" + subTopic;
     getNextionAttr(subTopic);
   }
+  else if (strTopic.startsWith(mqttGroupCommandTopic) && (strPayload == ""))
+  { // '[...]/group/command/p[1].b[4].txt' -m '' == getNextionAttr("p[1].b[4].txt")
+    String subTopic = strTopic.substring(mqttGroupCommandTopic.length() + 1);
+    mqttGetSubtopic = "/" + subTopic;
+    getNextionAttr(subTopic);
+  }
   else if (strTopic.startsWith(mqttCommandTopic))
   { // '[...]/device/command/p[1].b[4].txt' -m '"Lights On"' == setNextionAttr("p[1].b[4].txt", "\"Lights On\"")
     String subTopic = strTopic.substring(mqttCommandTopic.length() + 1);
+    setNextionAttr(subTopic, strPayload);
+  }
+  else if (strTopic.startsWith(mqttGroupCommandTopic))
+  { // '[...]/group/command/p[1].b[4].txt' -m '"Lights On"' == setNextionAttr("p[1].b[4].txt", "\"Lights On\"")
+    String subTopic = strTopic.substring(mqttGroupCommandTopic.length() + 1);
     setNextionAttr(subTopic, strPayload);
   }
   else if (strTopic == mqttLightBrightCommandTopic)
@@ -722,6 +768,7 @@
     // id/name, placeholder/prompt, default value, length, extra tags
     WiFiManagerParameter custom_haspNodeHeader("

HASP Node Name");
     WiFiManagerParameter custom_haspNode("haspNode", "HASP Node (required)", haspNode, 15, " maxlength=15 required");
+    WiFiManagerParameter custom_groupName("groupName", "Group Name (required)", groupName, 15, " maxlength=15 required");
     WiFiManagerParameter custom_mqttHeader("

MQTT Broker");
     WiFiManagerParameter custom_mqttServer("mqttServer", "MQTT Server", mqttServer, 63, " maxlength=39");
     WiFiManagerParameter custom_mqttPort("mqttPort", "MQTT Port", mqttPort, 5, " maxlength=5 type='number'");
@@ -742,6 +789,7 @@
     // Add all your parameters here
     wifiManager.addParameter(&custom_haspNodeHeader);
     wifiManager.addParameter(&custom_haspNode);
+    wifiManager.addParameter(&custom_groupName);
     wifiManager.addParameter(&custom_mqttHeader);
     wifiManager.addParameter(&custom_mqttServer);
     wifiManager.addParameter(&custom_mqttPort);
@@ -782,6 +830,7 @@
     strcpy(mqttUser, custom_mqttUser.getValue());
     strcpy(mqttPassword, custom_mqttPassword.getValue());
     strcpy(haspNode, custom_haspNode.getValue());
+    strcpy(groupName, custom_groupName.getValue());
     strcpy(configUser, custom_configUser.getValue());
     strcpy(configPassword, custom_configPassword.getValue());

@@ -1059,6 +1108,10 @@
           {
             strcpy(haspNode, configJson["haspNode"]);
           }
+          if (configJson["groupName"].success())
+          {
+            strcpy(groupName, configJson["groupName"]);
+          }
           if (configJson["configUser"].success())
           {
             strcpy(configUser, configJson["configUser"]);
@@ -1102,6 +1155,7 @@
   json["mqttUser"] = mqttUser;
   json["mqttPassword"] = mqttPassword;
   json["haspNode"] = haspNode;
+  json["groupName"] = groupName;
   json["configUser"] = configUser;
   json["configPassword"] = configPassword;

@@ -1193,6 +1247,7 @@
   httpMessage += String(F("WiFi SSID (required)<input id='wifiSSID' required name='wifiSSID' maxlength=32 placeholder='WiFi SSID' value='")) + String(WiFi.SSID()) + "'>";
   httpMessage += String(F("
WiFi Password (required)<input id='wifiPass' required name='wifiPass' type='password' maxlength=64 placeholder='WiFi Password' value='")) + String("********") + "'>";
   httpMessage += String(F("

HASP Node Name (required)<input id='haspNode' required name='haspNode' maxlength=15 placeholder='HASP Node Name' value='")) + String(haspNode) + "'>";
+  httpMessage += String(F("

Group Name (required)<input id='groupName' required name='groupName' maxlength=15 placeholder='Group Name' value='")) + String(groupName) + "'>";
   httpMessage += String(F("

MQTT Broker (required)<input id='mqttServer' required name='mqttServer' maxlength=63 placeholder='mqttServer' value='")) + String(mqttServer) + "'>";
   httpMessage += String(F("
MQTT Port (required)<input id='mqttPort' required name='mqttPort' type='number' maxlength=5 placeholder='mqttPort' value='")) + String(mqttPort) + "'>";
   httpMessage += String(F("
MQTT User (optional)<input id='mqttUser' name='mqttUser' maxlength=31 placeholder='mqttUser' value='")) + String(mqttUser) + "'>";
@@ -1284,6 +1339,11 @@
   { // Handle haspNode
     shouldSaveConfig = true;
     webServer.arg("haspNode").toCharArray(haspNode, 16);
+  }
+  if (webServer.arg("groupName") != "" && webServer.arg("groupName") != String(groupName))
+  { // Handle groupName
+    shouldSaveConfig = true;
+    webServer.arg("groupName").toCharArray(groupName, 16);
   }
   // Check optional values
   if (webServer.arg("mqttUser") != String(mqttUser))
@@ -1905,4 +1965,4 @@
     handleTelnetClient();
   }
 #endif
-}+}


Work with ten pixels right now

Work with ten pixels right now

--- VideoDisplay/VideoDisplay.ino
+++ VideoDisplay/VideoDisplay.ino
@@ -73,7 +73,7 @@
 // Since the receiving program on the host is slicing the image,
 // only the width matters.  The height is always 8.
 //
-#define LED_WIDTH      60   // number of LEDs horizontally
+#define LED_WIDTH      10   // number of LEDs horizontally
 #define LED_HEIGHT     8    // number of LEDs vertically (must be 8)
 #define LED_LAYOUT     0    // 0 = even rows left->right, 1 = even rows right->left


maybe last?

maybe last?

--- little-switches/arduino/galoppo/galoppo.ino
+++ little-switches/arduino/galoppo/galoppo.ino
@@ -67,16 +67,12 @@
   Serial.print("weight: ");
   Serial.println(w);

-  volo *= w;
-  attesaAppoggio *= w;
-  attesaAllungo *= w;
-
   if (keyboard.available()) {

     char c = keyboard.read();

     if (c == '1') {
-      galoppo();
+      galoppo(w);
     }
     else if (c == 'p') {
       digitalWrite(piede,HIGH);
@@ -102,22 +98,22 @@
   }
 }

-void galoppo() {
+void galoppo(float w) {
   for (int i=0; i<10; i++) {
   digitalWrite(zampaPS,HIGH);
-  delay(attesaAppoggio);
+  delay(attesaAppoggio*w);
   digitalWrite(zampaPD,HIGH);
-  delay(attesaAllungo);
+  delay(attesaAllungo*w);
   digitalWrite(zampaAS,HIGH);
-  delay(attesaAppoggio);
+  delay(attesaAppoggio*w);
   digitalWrite(zampaAD,HIGH);
-  delay(volo);
+  delay(volo*w);
   digitalWrite(zampaPS,LOW);
-  delay(attesaAppoggio);
+  delay(attesaAppoggio*w);
   digitalWrite(zampaPD,LOW);
-  delay(attesaAllungo);
+  delay(attesaAllungo*w);
   digitalWrite(zampaAS,LOW);
-  delay(attesaAppoggio);
+  delay(attesaAppoggio*w);
   digitalWrite(zampaAD,LOW);
   }
 }


added some serial debugging and initialization code

--- controller/firmware/firmware.ino
+++ controller/firmware/firmware.ino
@@ -1,4 +1,7 @@
 #include <Adafruit_MCP23017.h>
+
+#undef DEBUG
+#define DEBUG

 Adafruit_MCP23017 mcp0, mcp1;

@@ -72,6 +75,11 @@
 void setup() {
 	int i;

+#ifdef DEBUG
+	Serial1.begin(115200);
+	Serial1.print("setup...");
+#endif
+
 	// intialize the i2c devices
 	mcp0.begin(0);
 	mcp1.begin(1);
@@ -82,6 +90,9 @@
 		encoders[i].mcpX->pinMode(encoders[i].pinA, INPUT);
 		encoders[i].mcpX->pinMode(encoders[i].pinB, INPUT);
 		encoders[i].mcpX->pinMode(encoders[i].pinSW, INPUT);
+		encoders[i].A = encoders[i].mcpX->digitalRead(encoders[i].pinA);
+		encoders[i].B = encoders[i].mcpX->digitalRead(encoders[i].pinB);
+		encoders[i].sw = encoders[i].mcpX->digitalRead(encoders[i].pinSW);
 	}

 	// setup input pins and enable pullups
@@ -89,8 +100,10 @@
 		if (buttons[i].mcpX) {
 			buttons[i].mcpX->pinMode(buttons[i].pin, INPUT);
 			buttons[i].mcpX->pullUp(buttons[i].pin, HIGH);
+			buttons[i].sw = buttons[i].mcpX->digitalRead(buttons[i].pin);
 		} else {
 			pinMode(buttons[i].pin, INPUT_PULLUP);
+			buttons[i].sw = digitalRead(buttons[i].pin);
 		}
 	}

@@ -98,6 +111,18 @@
 	for (i = 0; i < STRINGS; ++i) {
 		strings[i].value = analogRead(strings[i].pin);
 	}
+
+#ifdef DEBUG
+	Serial1.println("done");
+
+	Serial1.println("analog values for air strings:");
+	for (i = 0; i < STRINGS; ++i) {
+		Serial1.print("string ");
+		Serial1.print(i, DEC);
+		Serial1.print(": ");
+		Serial1.println(strings[i].value, DEC);
+	}
+#endif
 }

 uint16_t gpioAB[2];


OLED moved to TX module

OLED moved to TX module

--- crossbow.ino
+++ crossbow.ino
@@ -17,8 +17,8 @@
 // #define LORA_HARDWARE_SERIAL
 #define LORA_HARDWARE_SPI

-// #define DEVICE_MODE_TX
-#define DEVICE_MODE_RX
+#define DEVICE_MODE_TX
+// #define DEVICE_MODE_RX

 #define DEBUG_SERIAL
 #define DEBUG_LED
@@ -33,7 +33,6 @@
 #define LORA32U4_RST_PIN    4
 #define LORA32U4_DI0_PIN    7

-
 int ppm[PPM_CHANNEL_COUNT] = {0};

 /*
@@ -41,8 +40,12 @@
  */
 #ifdef DEVICE_MODE_TX

+#define OLED_RESET -1
 #include <PPMReader.h>
+#include <Adafruit_SSD1306.h>
+
 PPMReader ppmReader(PPM_INPUT_PIN, PPM_INPUT_INTERRUPT);
+Adafruit_SSD1306 display(OLED_RESET);

 #endif

@@ -50,11 +53,6 @@
  * Main defines for device working in RX mode
  */
 #ifdef DEVICE_MODE_RX
-
-// #include <Adafruit_SSD1306.h>
-
-// #define OLED_RESET 4
-// Adafruit_SSD1306 display(OLED_RESET);

 #endif


Replaced all tabs and standardized indents to 2 spaces

--- ArduinoWeatherStation.ino
+++ ArduinoWeatherStation.ino
@@ -401,22 +401,22 @@
     }

     // Check EEPROM to see if we should be in power save mode. If so, shut some stuff off immediately.
-	  Serial.print("Reading EEPROM to see power save state: ");
+    Serial.print("Reading EEPROM to see power save state: ");

     pinMode(30, OUTPUT);     //             common GND source for "YYD-3" FET switches.
     digitalWrite(30, LOW);   //             must always be low

     if (EEPROM.read(eePowerSave)) {
-  	  Serial.print("Shutting off Eth and Ubiquity... ");
+      Serial.print("Shutting off Eth and Ubiquity... ");
       powerSave = true;
-  	  disableEthernet();
+      disableEthernet();

     } else {
-	    Serial.print("Turning on Eth and Ubiquity... ");
-  	  powerSave = false;
+      Serial.print("Turning on Eth and Ubiquity... ");
+      powerSave = false;
       enableEthernet();

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

@@ -832,48 +832,48 @@
       // Check every minute that we know sunrise/sunset for today. If not, calc it.
       if (day() > sunriseDay) getRiseSet();

-
+
       /* * * * * * * * * * * * * * * * * *
-	   *  P O W E R   S A V E
-	   *  P O W E R   S A V E
-	   * * * * * * * * * * * * * * * * * */
+     *  P O W E R   S A V E
+     *  P O W E R   S A V E
+     * * * * * * * * * * * * * * * * * */
       // Turn off / on some peripherals at night & morning
       int minutesToday = hour() * 60 + minute();
-	  Serial.print("Minute of day is: ");
-	  Serial.print(minutesToday);
+      Serial.print("Minute of day is: ");
+      Serial.print(minutesToday);
       if ( (minutesToday < sunrise) or (minutesToday > sunset - 60) ) {     // jjj removed 60 to save even more   if ( (minutesToday < sunrise - 60) or (minutesToday > sunset - 60) ) {

         Serial.print(", which is Night time. We will switch to day at minute #");
-		Serial.println(sunrise);     // jjj removed 60 to save even more     Serial.println(sunrise - 60);
+        Serial.println(sunrise);     // jjj removed 60 to save even more     Serial.println(sunrise - 60);
         // We're not between "half an hour before sunrise" and sunset, so turn stuff off.
         // First set variables and record in eeprom that we're in power save mode.
         if (!powerSave) {
           powerSave = true;
           if (!EEPROM.read(eePowerSave)) EEPROM.update(eePowerSave, true);
         }
-
+
         disableEthernet();

       } else {
-	    Serial.print(", which is Day time. We will switch to night at minute #");
-		Serial.println(sunset - 60);
-	    // Otherwise, make sure things are TURNED ON
+        Serial.print(", which is Day time. We will switch to night at minute #");
+        Serial.println(sunset - 60);
+        // Otherwise, make sure things are TURNED ON
         if (powerSave) {
           powerSave = false;
           if (EEPROM.read(eePowerSave)) EEPROM.update(eePowerSave, false);
-
-		  //if powerSave was set, that means we're transitioning to daytime now.
-		  // Until I figure out how to restart the Ethernet, just force a watchdog timeout with delays.
-		    enableEthernet();
-
-		  Serial.println(F("   ! ! !   We just switched to DAY. Since we can't reset ETHERNET very well, we are rebooting soon!!! ! ! "));
-		  delay(10000);
-		  delay(20000);
-		  delay(30000);
+
+          //if powerSave was set, that means we're transitioning to daytime now.
+          // Until I figure out how to restart the Ethernet, just force a watchdog timeout with delays.
+          enableEthernet();
+
+          Serial.println(F("   ! ! !   We just switched to DAY. Since we can't reset ETHERNET very well, we are rebooting soon!!! ! ! "));
+          delay(10000);
+          delay(20000);
+          delay(30000);
         }
-
-		//This below kind of doesn't count, because of the reboot above. We really should never get here.
-		    enableEthernet();
+
+        //This below kind of doesn't count, because of the reboot above. We really should never get here.
+        enableEthernet();

       } // End of night/day figuring out (for power save)

@@ -1438,117 +1438,117 @@

 byte uploadWeather()
 {
-    if (powerSave) {
-	  Serial.println("UploadWeather() called, but NO DATA SENT because of Power Save mode.");
-	  return 50;
-	}
-
-	// Connect to CSS website, do a PUT with weather values. Should be called once for every minute of weather data.
-    logSome(F("  uploadWeather called, building string. Bytes free: "));
-    logOneLine(freeRam());
-    byte uploadStatus = 90; //90 = haven't tried stopping the client yet.
-
-    // Preemptively close any open connections, to keep sockets available.
-    client.stop();
-    while (client.available()) { //read return from socket
-      Serial.write(client.read());
-    }
-
-    uploadStatus = 100; //100 = stopped client, but haven't tried connecting.
+  if (powerSave) {
+    Serial.println("UploadWeather() called, but NO DATA SENT because of Power Save mode.");
+    return 50;
+  }
+
+  // Connect to CSS website, do a PUT with weather values. Should be called once for every minute of weather data.
+  logSome(F("  uploadWeather called, building string. Bytes free: "));
+  logOneLine(freeRam());
+  byte uploadStatus = 90; //90 = haven't tried stopping the client yet.
+
+  // Preemptively close any open connections, to keep sockets available.
+  client.stop();
+  while (client.available()) { //read return from socket
+    Serial.write(client.read());
+  }
+
+  uploadStatus = 100; //100 = stopped client, but haven't tried connecting.
+
+  String strPut = makeUploadWeatherPut(getWeatherString());
+
+  //Serial.print(F(" before strPut, after strPut: "));
+  //Serial.println(freeRam());
+
+  char charPut[300];
+  for (int i = 0; i < 300; i++) {
+    charPut[i] = 'x';
+  }
+  charPut[299] = '\0';
+  int strPutLength = strPut.length() + 1;
+  Serial.print("strPut len: ");
+  Serial.println(strPutLength);
+  if (strPutLength > 298) strPutLength = 298;
+  strPut.toCharArray(charPut, strPutLength);
+
+  client.setTimeout(600);
+  int clientConnectStatus;
+  clientConnectStatus = client.connect(server, 80);
+  if (clientConnectStatus) {
+    logSome(F("Ether client connected for uploadWeather. Mem: "));
+    logSome(freeRam());
+    logSome(", connect status: ");
+    logOneLine(clientConnectStatus);
+    ethStopped = false;

-    String strPut = makeUploadWeatherPut(getWeatherString());
-
-    //Serial.print(F(" before strPut, after strPut: "));
-    //Serial.println(freeRam());
-
-    char charPut[300];
-    for (int i = 0; i < 300; i++) {
-      charPut[i] = 'x';
-    }
-    charPut[299] = '\0';
-    int strPutLength = strPut.length() + 1;
-    Serial.print("strPut len: ");
-    Serial.println(strPutLength);
-    if (strPutLength > 298) strPutLength = 298;
-    strPut.toCharArray(charPut, strPutLength);
-
-    client.setTimeout(600);
-    int clientConnectStatus;
-    clientConnectStatus = client.connect(server, 80);
-    if (clientConnectStatus) {
-      logSome(F("Ether client connected for uploadWeather. Mem: "));
-      logSome(freeRam());
-      logSome(", connect status: ");
-      logOneLine(clientConnectStatus);
-      ethStopped = false;
-
-      // Make an HTTP request:
+    // Make an HTTP request:
     //logSome(strPut);
     //client.print(strPut);  //Single print so hopefully it goes out in one packet.
-      Serial.write(charPut, strPutLength); //for debugging
-      client.write(charPut, strPutLength); //Better chance of a single packet by using a char[].
-      ethLastMillis = millis();
-      uploadStatus = 0;
-      ethConnFails = 0;
-      ethTimeouts = 0;
-
-    } else {
-      // if you didn't get a connection to the server:
-      logSome(F("connection failed, status: "));
-      logOneLine(clientConnectStatus);
-      ethLastFailureCode = clientConnectStatus;
-      client.stop();
-      ethStopped = true;
-      ethConnFails++;
-      uploadStatus = 200; // connection failed
-    }
-
-    logSome(F("  uploadWeather() finished, free mem: "));
-    logOneLine(freeRam());
-    return uploadStatus;
+    Serial.write(charPut, strPutLength); //for debugging
+    client.write(charPut, strPutLength); //Better chance of a single packet by using a char[].
+    ethLastMillis = millis();
+    uploadStatus = 0;
+    ethConnFails = 0;
+    ethTimeouts = 0;
+
+  } else {
+    // if you didn't get a connection to the server:
+    logSome(F("connection failed, status: "));
+    logOneLine(clientConnectStatus);
+    ethLastFailureCode = clientConnectStatus;
+    client.stop();
+    ethStopped = true;
+    ethConnFails++;
+    uploadStatus = 200; // connection failed
+  }
+
+  logSome(F("  uploadWeather() finished, free mem: "));
+  logOneLine(freeRam());
+  return uploadStatus;
 }

 // Test with building strings, to use for the website request.
 String getWeatherString() {
-    String weatherString = "";
-    int tempc = RTC.temperature();
-
-    // 1: time
-    if (hour() < 10) weatherString += String('0');
-    weatherString += String(hour());
-    weatherString += ":";
-    if (minute() < 10) weatherString += String('0');
-    weatherString += String(minute());
-
-    // 2: date
-    weatherString += String(charComma);
-    weatherString += String(month());
-    weatherString += String(("/"));
-    weatherString += String(day());
-    weatherString += String(("/"));
-    weatherString += String(year());
-
-    // 3: Wind speed, mph, 1 minute average
-    weatherString += String(charComma);
-    if (windSpeedAvg < 9.5) weatherString += String('0');
-    weatherString += String(windSpeedAvg, 2);
-
-    // 4: wind speed, mph, 5 minute max (gust)
-    weatherString += String(charComma);
-    if (windgustmph_5m < 9.5) weatherString += String('0');
-    weatherString += String(windgustmph_5m, 1);
-
-    // 5: wind direction, 1 minute average
-    weatherString += String(charComma);
-    if ((winddir < 10 ) and (winddir >= 0)) weatherString += String("0"); //pad with zeros to keep formatting nicer
-    if ((winddir < 100) and (winddir >= 0)) weatherString += String("0"); //pad with zeros to keep formatting nicer
-    weatherString += String(winddir);
-    //weatherString += String(",windgustdir=");
-    //weatherString += String(windgustdir);
-
-    // 6: temperature, F, outside, instant
-    weatherString += String(charComma);
-    weatherString += String(bme280a.readTempF(), 2);
+  String weatherString = "";
+  int tempc = RTC.temperature();
+
+  // 1: time
+  if (hour() < 10) weatherString += String('0');
+  weatherString += String(hour());
+  weatherString += ":";
+  if (minute() < 10) weatherString += String('0');
+  weatherString += String(minute());
+
+  // 2: date
+  weatherString += String(charComma);
+  weatherString += String(month());
+  weatherString += String(("/"));
+  weatherString += String(day());
+  weatherString += String(("/"));
+  weatherString += String(year());
+
+  // 3: Wind speed, mph, 1 minute average
+  weatherString += String(charComma);
+  if (windSpeedAvg < 9.5) weatherString += String('0');
+  weatherString += String(windSpeedAvg, 2);
+
+  // 4: wind speed, mph, 5 minute max (gust)
+  weatherString += String(charComma);
+  if (windgustmph_5m < 9.5) weatherString += String('0');
+  weatherString += String(windgustmph_5m, 1);
+
+  // 5: wind direction, 1 minute average
+  weatherString += String(charComma);
+  if ((winddir < 10 ) and (winddir >= 0)) weatherString += String("0"); //pad with zeros to keep formatting nicer
+  if ((winddir < 100) and (winddir >= 0)) weatherString += String("0"); //pad with zeros to keep formatting nicer
+  weatherString += String(winddir);
+  //weatherString += String(",windgustdir=");
+  //weatherString += String(windgustdir);
+
+  // 6: temperature, F, outside, instant
+  weatherString += String(charComma);
+  weatherString += String(bme280a.readTempF(), 2);
 // All this was before the BME280
 //    if (tempf < -1000) {
 //      weatherString += String((tempc * 0.45) + 32, 1);
@@ -1556,9 +1556,9 @@
 //      weatherString += String(tempf, 0);
 //    }

-    // 7: humidity, %, outside, instant from bme280a
-    weatherString += String(charComma);
-    weatherString += String(bme280a.readFloatHumidity(), 0);
+  // 7: humidity, %, outside, instant from bme280a
+  weatherString += String(charComma);
+  weatherString += String(bme280a.readFloatHumidity(), 0);
 // All this was before the BME280
 //    if (humidity < 200) {
 //      //weatherString += String(humidity, 1);
@@ -1566,9 +1566,9 @@
 //      weatherString += "0";
 //    }

-    // 8: Barometric pressure, hPa, outside, instant from bme280a
-    weatherString += String(charComma);
-    weatherString += String(bme280a.readFloatPressure() / 100.0, 2);
+  // 8: Barometric pressure, hPa, outside, instant from bme280a
+  weatherString += String(charComma);
+  weatherString += String(bme280a.readFloatPressure() / 100.0, 2);
 // All this wasbefore the BME280
 //    if (pressure > 0) {
 //      weatherString += String(pressure / 100.0, 1);
@@ -1576,329 +1576,329 @@
 //      weatherString += "0";
 //    }

-    // 9: Barometric pressure delta from previous reading
-    weatherString += String(charComma);
-    //if (pressure >= oldPressure) weatherString += String("+"); //can't have spaces in the URL, but using the + makes columns line up nicer.
-    //weatherString += String((pressure - oldPressure) / 100.0, 2);
+  // 9: Barometric pressure delta from previous reading
+  weatherString += String(charComma);
+  //if (pressure >= oldPressure) weatherString += String("+"); //can't have spaces in the URL, but using the + makes columns line up nicer.
+  //weatherString += String((pressure - oldPressure) / 100.0, 2);
+  weatherString += "0";
+
+  // 10: rain so far today
+  //weatherString += String(",rainin=");
+  //weatherString += String(rainin, 2);
+  weatherString += String(charComma);
+//    weatherString += String(0.0, 2);
+  weatherString += String(wxOwner);
+
+  // 11: rain long term? Maybe it's supposed to be last 24h, but it's always zero.
+  //weatherString += String(",dailyrainin=");
+  //weatherString += String(dailyrainin, 2);
+  weatherString += String(charComma);
+//    weatherString += String(0.0, 2);
+  weatherString += String(wxVersion);
+
+  // 11: wind speed, mph, instant (instead of 24h rain)
+  //weatherString += String(charComma);
+  //if (windspeedmph < 10) weatherString += String('0');
+  //weatherString += String(windspeedmph, 1);
+
+  // 12: temperature in the enclosure or 2nd sensor if we get one. In Celcius for Jimmy.
+  weatherString += String(charComma);
+  if (tempc) {
+    weatherString += String(tempc / 4.0, 2); //Dja
+  } else {
     weatherString += "0";
-
-    // 10: rain so far today
-    //weatherString += String(",rainin=");
-    //weatherString += String(rainin, 2);
-    weatherString += String(charComma);
-//    weatherString += String(0.0, 2);
-    weatherString += String(wxOwner);
-
-    // 11: rain long term? Maybe it's supposed to be last 24h, but it's always zero.
-    //weatherString += String(",dailyrainin=");
-    //weatherString += String(dailyrainin, 2);
-    weatherString += String(charComma);
-//    weatherString += String(0.0, 2);
-    weatherString += String(wxVersion);
-
-    // 11: wind speed, mph, instant (instead of 24h rain)
-    //weatherString += String(charComma);
-    //if (windspeedmph < 10) weatherString += String('0');
-    //weatherString += String(windspeedmph, 1);
-
-    // 12: temperature in the enclosure or 2nd sensor if we get one. In Celcius for Jimmy.
-    weatherString += String(charComma);
-    if (tempc) {
-      weatherString += String(tempc / 4.0, 2); //Dja
-    } else {
-      weatherString += "0";
-    }
-
-    // 13: Current on ina219 sensor A (raw battery @ 12v maybe?)
-    weatherString += String(charComma);
-    weatherString += String(ina219a_current, 2);
-    weatherString += String("mA");
-
-    // 14: Voltage on ina219 sensor A (raw battery @ 12v maybe?)
-    weatherString += String(charComma);
-    weatherString += String(ina219a_volts, 2);
-    weatherString += String("v");
-    //weatherString += String(batt_lvl, 2);
-
-    // 15: Power on ina219 sensor A (watts battery)
-    weatherString += String(charComma);
-    weatherString += String(ina219a_volts * ina219a_current / 1000, 2);
-    weatherString += String("w");
-
-
-    // 16: Current on ina219 sensor B (after buck to 5v maybe?)
-    weatherString += String(charComma);
-    weatherString += String(ina219b_current, 2);
-    weatherString += String("mA");
-
-    // 17: Voltage on ina219 sensor A (after buck to 5v maybe?)
-    weatherString += String(charComma);
-    weatherString += String(ina219b_volts, 2);
-    weatherString += String("v");
-    //weatherString += String(batt_lvl, 2);
-
-    // 18: Power on ina219 sensor A (watts battery)
-    weatherString += String(charComma);
-    weatherString += String(ina219b_volts * ina219b_current / 1000, 2);
-    weatherString += String("w");
-
-
-
-    // 19: light level, referenced to voltage I think
-    weatherString += String(charComma);
+  }
+
+  // 13: Current on ina219 sensor A (raw battery @ 12v maybe?)
+  weatherString += String(charComma);
+  weatherString += String(ina219a_current, 2);
+  weatherString += String("mA");
+
+  // 14: Voltage on ina219 sensor A (raw battery @ 12v maybe?)
+  weatherString += String(charComma);
+  weatherString += String(ina219a_volts, 2);
+  weatherString += String("v");
+  //weatherString += String(batt_lvl, 2);
+
+  // 15: Power on ina219 sensor A (watts battery)
+  weatherString += String(charComma);
+  weatherString += String(ina219a_volts * ina219a_current / 1000, 2);
+  weatherString += String("w");
+
+
+  // 16: Current on ina219 sensor B (after buck to 5v maybe?)
+  weatherString += String(charComma);
+  weatherString += String(ina219b_current, 2);
+  weatherString += String("mA");
+
+  // 17: Voltage on ina219 sensor A (after buck to 5v maybe?)
+  weatherString += String(charComma);
+  weatherString += String(ina219b_volts, 2);
+  weatherString += String("v");
+  //weatherString += String(batt_lvl, 2);
+
+  // 18: Power on ina219 sensor A (watts battery)
+  weatherString += String(charComma);
+  weatherString += String(ina219b_volts * ina219b_current / 1000, 2);
+  weatherString += String("w");
+
+
+
+  // 19: light level, referenced to voltage I think
+  weatherString += String(charComma);
 //    weatherString += String(light_lvl, 2);
-    weatherString += "0";
-
-    // 20: run time in days.HH:MM:SS
-    weatherString += String(charComma);
-    weatherString += String(days);
-    weatherString += String(".");
-    if (hours < 10) weatherString += String('0');
-    weatherString += String(hours);
-    weatherString += String(":");
-    if (minutes < 10) weatherString += String('0');
-    weatherString += String(minutes);
-    weatherString += String(":");
-    if (seconds < 10) weatherString += String('0');
-    weatherString += String(seconds);
-
-    /* 18: loop counter. For diagnostics, mostly useless.
-    weatherString += String(charComma);
-    weatherString += String(loopCounter);
-    weatherString += String(charComma);
-    weatherString += String(loopCounter - loopDelta);
-    loopDelta = loopCounter; */
-
-    // 18: print free memory? Interesting...
+  weatherString += "0";
+
+  // 20: run time in days.HH:MM:SS
+  weatherString += String(charComma);
+  weatherString += String(days);
+  weatherString += String(".");
+  if (hours < 10) weatherString += String('0');
+  weatherString += String(hours);
+  weatherString += String(":");
+  if (minutes < 10) weatherString += String('0');
+  weatherString += String(minutes);
+  weatherString += String(":");
+  if (seconds < 10) weatherString += String('0');
+  weatherString += String(seconds);
+
+  /* 18: loop counter. For diagnostics, mostly useless.
+  weatherString += String(charComma);
+  weatherString += String(loopCounter);
+  weatherString += String(charComma);
+  weatherString += String(loopCounter - loopDelta);
+  loopDelta = loopCounter; */
+
+  // 18: print free memory? Interesting...
 //    weatherString += String(charComma);
 //    weatherString += String(freeRam());

-    // 21: print raw wind direction ADC reading, to see why 270 degree sometimes comes back as "invalid"
-    if (true) {
-      weatherString += String(charComma);
-      weatherString += String("wd=");
-      weatherString += String(winddirRaw);
-    }
-    if (true) {
-      weatherString += String(charComma);
-      if (strWindDir.length() < 3) weatherString += String("_");
-      if (strWindDir.length() < 2) weatherString += String("_");
-      weatherString += strWindDir;
-    }
-
-    // 22+: Assorted info and error values
-    // Tack on a ,R if we've rebooted to make it easier to spot them
-    if(justRestarted) {
-      weatherString += ",R";
-    }
-
-    // add socket status as 8 hex chars
-    bool reportSockets = false;
+  // 21: print raw wind direction ADC reading, to see why 270 degree sometimes comes back as "invalid"
+  if (true) {
+    weatherString += String(charComma);
+    weatherString += String("wd=");
+    weatherString += String(winddirRaw);
+  }
+  if (true) {
+    weatherString += String(charComma);
+    if (strWindDir.length() < 3) weatherString += String("_");
+    if (strWindDir.length() < 2) weatherString += String("_");
+    weatherString += strWindDir;
+  }
+
+  // 22+: Assorted info and error values
+  // Tack on a ,R if we've rebooted to make it easier to spot them
+  if(justRestarted) {
+    weatherString += ",R";
+  }
+
+  // add socket status as 8 hex chars
+  bool reportSockets = false;
+  for (int i = 0; i < MAX_SOCK_NUM; i++) {
+    if (ethSockStatus[i] > 0) reportSockets = true;
+  }
+  if (reportSockets) {
+    weatherString += String(charComma);
     for (int i = 0; i < MAX_SOCK_NUM; i++) {
-      if (ethSockStatus[i] > 0) reportSockets = true;
-    }
-    if (reportSockets) {
-      weatherString += String(charComma);
-      for (int i = 0; i < MAX_SOCK_NUM; i++) {
-        if (ethSockStatus[i] < 17) weatherString += String("0");
-        weatherString += String(ethSockStatus[i], 16);
-      }
-    }
-
-    // If there have been failures, tack them on:
-    if (ethConnFails) {
-      weatherString += String(F(",EthConnFails="));
-      weatherString += String(ethConnFails);
-    }
-    if (ethTimeouts) {
-      weatherString += String(F(",Timeouts="));
-      weatherString += String(ethTimeouts);
-    }
-    if (ethLastFailureCode) {
-      weatherString += String(F(",failCode="));
-      weatherString += String(ethLastFailureCode);
-    }
-    if(reportWatchdog) {
-      weatherString += ",W-";
-      weatherString += String(year(reportWatchdog));
-      weatherString += String(("/"));
-      weatherString += String(month(reportWatchdog));
-      weatherString += String(("/"));
-      weatherString += String(day(reportWatchdog));
-      weatherString += String("@");
-      weatherString += String(hour(reportWatchdog));
-      weatherString += String((":"));
-      weatherString += String(minute(reportWatchdog));
-    }
-
-    //Serial.println(weatherString);
-	weatherString.replace(" ", "");
-    return weatherString;
+      if (ethSockStatus[i] < 17) weatherString += String("0");
+      weatherString += String(ethSockStatus[i], 16);
+    }
+  }
+
+  // If there have been failures, tack them on:
+  if (ethConnFails) {
+    weatherString += String(F(",EthConnFails="));
+    weatherString += String(ethConnFails);
+  }
+  if (ethTimeouts) {
+    weatherString += String(F(",Timeouts="));
+    weatherString += String(ethTimeouts);
+  }
+  if (ethLastFailureCode) {
+    weatherString += String(F(",failCode="));
+    weatherString += String(ethLastFailureCode);
+  }
+  if(reportWatchdog) {
+    weatherString += ",W-";
+    weatherString += String(year(reportWatchdog));
+    weatherString += String(("/"));
+    weatherString += String(month(reportWatchdog));
+    weatherString += String(("/"));
+    weatherString += String(day(reportWatchdog));
+    weatherString += String("@");
+    weatherString += String(hour(reportWatchdog));
+    weatherString += String((":"));
+    weatherString += String(minute(reportWatchdog));
+  }
+
+  //Serial.println(weatherString);
+  weatherString.replace(" ", "");
+  return weatherString;
 }

 //Prints the various variables directly to the port
 //I don't like the way this function is written but Arduino doesn't support floats under sprintf
 void printWeather()
 {
-    //calcWeather(); //Go calc all the various sensors; except now call it directly from loop()
-    timeStatus();             //check the time status now to force a sync if needed.
-
-    // 1: time
-    printDigits(hour());
-    Serial.print((":"));
-    printDigits(minute());
-
-    // 2: date
-    Serial.print(charComma);
-    Serial.print(month());
-    Serial.print(("/"));
-    Serial.print(day());
-    Serial.print(("/"));
-    Serial.print(year());
-
-    // 3: Wind speed, mph, 1 minute average
-    Serial.print(charComma);
-    if (windSpeedAvg < 10) Serial.print('0');
-    Serial.print(windSpeedAvg, 2);
-
-    // 4: wind speed, mph, 5 minute max (gust)
-    Serial.print(charComma);
-    if (windgustmph_5m < 10) Serial.print('0');
-    Serial.print(windgustmph_5m, 1);
-
-    // 5: wind direction, 1 minute average
-    Serial.print(charComma);
-    if (winddir == 0 ) Serial.print(" ");
-    if (winddir < 100) Serial.print(" ");
-    Serial.print(winddir);
-    //Serial.print(",windgustdir=");
-    //Serial.print(windgustdir);
-    //Serial.print(F(",wAvg="));
-    //Serial.print(windspdmph_avg2m, 2);
-
-    // 6: temperature, F, outside, instant
-    Serial.print(charComma);
-    Serial.print(tempf, 1);
-
-    // 7: humidity, %, outside, instant
-    Serial.print(charComma);
-    Serial.print(humidity, 1);
-
-    // 8: Barometric pressure, hPa, outside, instant
-    Serial.print(charComma);
-    Serial.print(pressure / 100.0, 1);
-
-    // 9: Barometric pressure delta from previous reading
-    Serial.print(charComma);
-    if (pressure >= oldPressure) Serial.print(" ");
-    Serial.print((pressure - oldPressure) / 100.0, 2);
-
-    // 10: rain so far today
-    //Serial.print(",rainin=");
-    //Serial.print(rainin, 2);
-    Serial.print(charComma);
-    Serial.print(0.0, 2);
-
-    // 11: rain long term? Maybe it's supposed to be last 24h, but it's always zero.
-    //Serial.print(",dailyrainin=");
-    //Serial.print(dailyrainin, 2);
-    //Serial.print(",");
-    //Serial.print(0.0, 2);
-
-    // 11: wind speed, mph, instant (instead of 24h rain)
-    Serial.print((","));
-    if (windspeedmph < 10) Serial.print('0');
-    Serial.print(windspeedmph, 1);
-
-    // 12: temperature in the enclosure or 2nd sensor if we get one
-    Serial.print(charComma);
-    //Serial.print(tempf, 1); //(FIXME: same as ext sensor since we only have one)
-    Serial.print(RTC.temperature() / 4);
-
-    // 13: current in mA
-    //(FIXME: same as ext sensor since we only have one)
-    Serial.print(charComma);
-    Serial.print(ina219a_current, 2);
-    Serial.print("mA");
-
-    // 14: voltage onboard, ~5v source
-    Serial.print(charComma);
-    Serial.print(batt_lvl, 2);
-
-    // 15: voltage battery, possibly inferred but same as 14 for now.
-    Serial.print(charComma);
-    Serial.print(ina219a_volts,2);
-    //Serial.print(sla_30sec, 2);
-
-    // 16: light level, referenced to voltage I think
-    Serial.print(charComma);
-    Serial.print(light_lvl, 2);
-
-    // 17: run time in days.HH:MM:SS
-    Serial.print(charComma);
-    Serial.print(days);
-    Serial.print(".");
-    printDigits(hours);
-    Serial.print(":");
-    printDigits(minutes);
-    Serial.print(":");
-    printDigits(seconds);
-
-    // 18: Print the RTC date & time. For debugging.
-    time_t rtcTime = RTC.get();
-    Serial.print(charComma);
-    Serial.print("rtc:");
-    Serial.print(year(rtcTime));
-    Serial.print("/");
-    Serial.print(month(rtcTime));
-    Serial.print("/");
-    Serial.print(day(rtcTime));
-    Serial.print(charComma);
-    Serial.print(hour(rtcTime));
-    Serial.print(":");
-    Serial.print(minute(rtcTime));
-    Serial.print(":");
-    Serial.print(second(rtcTime));
+  //calcWeather(); //Go calc all the various sensors; except now call it directly from loop()
+  timeStatus();             //check the time status now to force a sync if needed.
+
+  // 1: time
+  printDigits(hour());
+  Serial.print((":"));
+  printDigits(minute());
+
+  // 2: date
+  Serial.print(charComma);
+  Serial.print(month());
+  Serial.print(("/"));
+  Serial.print(day());
+  Serial.print(("/"));
+  Serial.print(year());
+
+  // 3: Wind speed, mph, 1 minute average
+  Serial.print(charComma);
+  if (windSpeedAvg < 10) Serial.print('0');
+  Serial.print(windSpeedAvg, 2);
+
+  // 4: wind speed, mph, 5 minute max (gust)
+  Serial.print(charComma);
+  if (windgustmph_5m < 10) Serial.print('0');
+  Serial.print(windgustmph_5m, 1);
+
+  // 5: wind direction, 1 minute average
+  Serial.print(charComma);
+  if (winddir == 0 ) Serial.print(" ");
+  if (winddir < 100) Serial.print(" ");
+  Serial.print(winddir);
+  //Serial.print(",windgustdir=");
+  //Serial.print(windgustdir);
+  //Serial.print(F(",wAvg="));
+  //Serial.print(windspdmph_avg2m, 2);
+
+  // 6: temperature, F, outside, instant
+  Serial.print(charComma);
+  Serial.print(tempf, 1);
+
+  // 7: humidity, %, outside, instant
+  Serial.print(charComma);
+  Serial.print(humidity, 1);
+
+  // 8: Barometric pressure, hPa, outside, instant
+  Serial.print(charComma);
+  Serial.print(pressure / 100.0, 1);
+
+  // 9: Barometric pressure delta from previous reading
+  Serial.print(charComma);
+  if (pressure >= oldPressure) Serial.print(" ");
+  Serial.print((pressure - oldPressure) / 100.0, 2);
+
+  // 10: rain so far today
+  //Serial.print(",rainin=");
+  //Serial.print(rainin, 2);
+  Serial.print(charComma);
+  Serial.print(0.0, 2);
+
+  // 11: rain long term? Maybe it's supposed to be last 24h, but it's always zero.
+  //Serial.print(",dailyrainin=");
+  //Serial.print(dailyrainin, 2);
+  //Serial.print(",");
+  //Serial.print(0.0, 2);
+
+  // 11: wind speed, mph, instant (instead of 24h rain)
+  Serial.print((","));
+  if (windspeedmph < 10) Serial.print('0');
+  Serial.print(windspeedmph, 1);
+
+  // 12: temperature in the enclosure or 2nd sensor if we get one
+  Serial.print(charComma);
+  //Serial.print(tempf, 1); //(FIXME: same as ext sensor since we only have one)
+  Serial.print(RTC.temperature() / 4);
+
+  // 13: current in mA
+  //(FIXME: same as ext sensor since we only have one)
+  Serial.print(charComma);
+  Serial.print(ina219a_current, 2);
+  Serial.print("mA");
+
+  // 14: voltage onboard, ~5v source
+  Serial.print(charComma);
+  Serial.print(batt_lvl, 2);
+
+  // 15: voltage battery, possibly inferred but same as 14 for now.
+  Serial.print(charComma);
+  Serial.print(ina219a_volts,2);
+  //Serial.print(sla_30sec, 2);
+
+  // 16: light level, referenced to voltage I think
+  Serial.print(charComma);
+  Serial.print(light_lvl, 2);
+
+  // 17: run time in days.HH:MM:SS
+  Serial.print(charComma);
+  Serial.print(days);
+  Serial.print(".");
+  printDigits(hours);
+  Serial.print(":");
+  printDigits(minutes);
+  Serial.print(":");
+  printDigits(seconds);
+
+  // 18: Print the RTC date & time. For debugging.
+  time_t rtcTime = RTC.get();
+  Serial.print(charComma);
+  Serial.print("rtc:");
+  Serial.print(year(rtcTime));
+  Serial.print("/");
+  Serial.print(month(rtcTime));
+  Serial.print("/");
+  Serial.print(day(rtcTime));
+  Serial.print(charComma);
+  Serial.print(hour(rtcTime));
+  Serial.print(":");
+  Serial.print(minute(rtcTime));
+  Serial.print(":");
+  Serial.print(second(rtcTime));

 /*
-    // loop counter. For diagnostics, mostly useless.
-    Serial.print(charComma);
-    Serial.print(loopCounter);
-    Serial.print(charComma);
-    Serial.print(loopCounter - loopDelta);
-    loopDelta = loopCounter;
-
-    // Print the raw 12v input on A12/SLA_BATT_LVL
-    Serial.print(charComma);
-    Serial.print(sla_raw);
-    Serial.print(charComma);
-    Serial.print(sla_lvl, 2);
-    Serial.print(charComma);
-    Serial.print(sla_30sec, 2);
-
-    //Serial.print(charComma);
-    //Serial.print(F("__DATE__ "));    //C++ #DEFINE that expands to the current compile date
-    //Serial.print(F("__TIME__"));     //C++ #DEFINE that expands to the current compile time
-    //Serial.print(String(compile_date));
+  // loop counter. For diagnostics, mostly useless.
+  Serial.print(charComma);
+  Serial.print(loopCounter);
+  Serial.print(charComma);
+  Serial.print(loopCounter - loopDelta);
+  loopDelta = loopCounter;
+
+  // Print the raw 12v input on A12/SLA_BATT_LVL
+  Serial.print(charComma);
+  Serial.print(sla_raw);
+  Serial.print(charComma);
+  Serial.print(sla_lvl, 2);
+  Serial.print(charComma);
+  Serial.print(sla_30sec, 2);
+
+  //Serial.print(charComma);
+  //Serial.print(F("__DATE__ "));    //C++ #DEFINE that expands to the current compile date
+  //Serial.print(F("__TIME__"));     //C++ #DEFINE that expands to the current compile time
+  //Serial.print(String(compile_date));
 */

-    // 19: print free memory? Interesting...
-    Serial.print(charComma);
-    Serial.print(freeRam());
-
-    // 20: print raw ADC reading from wind direction, to troubleshooting why 270 degrees sometimes reads invalid
-    Serial.print(charComma);
-    Serial.print(winddirRaw);
-
-    // 21: print ina219a's voltage, current
-    Serial.print(charComma);
-    Serial.print(ina219a_volts);
-    Serial.print(charComma);
-    Serial.print(ina219a_current);
-
-    // NEWLINE:
-    Serial.println();
-
-}
-
+  // 19: print free memory? Interesting...
+  Serial.print(charComma);
+  Serial.print(freeRam());
+
+  // 20: print raw ADC reading from wind direction, to troubleshooting why 270 degrees sometimes reads invalid
+  Serial.print(charComma);
+  Serial.print(winddirRaw);
+
+  // 21: print ina219a's voltage, current
+  Serial.print(charComma);
+  Serial.print(ina219a_volts);
+  Serial.print(charComma);
+  Serial.print(ina219a_current);
+
+  // NEWLINE:
+  Serial.println();
+
+}
+


added more precision to output on imu

added more precision to output on imu

--- sandbox/Razor_AHRS/Output.ino
+++ sandbox/Razor_AHRS/Output.ino
@@ -118,20 +118,20 @@
 void output_sensors_and_angles_text()
 {
   Serial.print("#A-"); Serial.print('C'); Serial.print('=');
-  Serial.print(GRAVITY_MS_REF(Accel_Vector[0])); Serial.print(",");
-  Serial.print(GRAVITY_MS_REF(Accel_Vector[1])); Serial.print(",");
-  Serial.print(GRAVITY_MS_REF(Accel_Vector[2])); Serial.println();
+  Serial.print(GRAVITY_MS_REF(Accel_Vector[0]), 4); Serial.print(",");
+  Serial.print(GRAVITY_MS_REF(Accel_Vector[1]), 4); Serial.print(",");
+  Serial.print(GRAVITY_MS_REF(Accel_Vector[2]), 4); Serial.println();

   Serial.print("#G-"); Serial.print('C'); Serial.print('=');
-  Serial.print(Gyro_Vector[0]); Serial.print(",");
-  Serial.print(Gyro_Vector[1]); Serial.print(",");
-  Serial.print(Gyro_Vector[2]); Serial.println();
+  Serial.print(Gyro_Vector[0], 4); Serial.print(",");
+  Serial.print(Gyro_Vector[1], 4); Serial.print(",");
+  Serial.print(Gyro_Vector[2], 4); Serial.println();

   Serial.print("#YPR=");
   Serial.print(TO_DEG(yaw)); Serial.print(",");
   Serial.print(TO_DEG(pitch)); Serial.print(",");
   Serial.print(TO_DEG(roll)); Serial.println();
-
+
 }

 void output_sensors()


New canDiag-Class and BMS_dfs.h for BMS specific code

--- ED_BMSdiag/ED_BMSdiag.ino
+++ ED_BMSdiag/ED_BMSdiag.ino
@@ -1,5 +1,5 @@
 //--------------------------------------------------------------------------------
-// ED BMSdiag, v0.4.0-b3
+// ED BMSdiag, v0.4.0
 // Retrieve battery diagnostic data from your smart electric drive EV.
 //
 // (c) 2016 by MyLab-odyssey
@@ -23,7 +23,7 @@
 //! \brief   compatible hardware.
 //! \date    2016-July
 //! \author  My-Lab-odyssey
-//! \version 0.4.0-b3
+//! \version 0.4.0
 //--------------------------------------------------------------------------------

 #define VERBOSE 1                //!< VERBOSE mode will output individual cell data
@@ -36,12 +36,13 @@
 #include "canDiag.h"

 //Global definitions
-#define VERSION F("0.4.0-b3")
 #define SPACER F("-----------------------------------------")
 #define MSG_OK F("OK")
 #define MSG_FAIL F("F")
 #define MSG_DOT F(".")

+char* const PROGMEM version = "0.4.0";
+
 #define CS     10                //!< chip select pin of MCP2515 CAN-Controller
 #define CS_SD  8                 //!< CS for SD card, if you plan to use a logger...
 MCP_CAN CAN0(CS);                //!< Set CS pin
@@ -105,10 +106,14 @@
 //! \brief   Output header data
 //--------------------------------------------------------------------------------
 void printWelcomeScreen() {
+  byte vLength = strlen(version);
   Serial.println(SPACER);
   Serial.println(F("--- ED Battery Management Diagnostics ---"));
-  Serial.print(F("--- v")); Serial.print(VERSION);
-  Serial.println(F("                         ---"));
+  Serial.print(F("--- v")); Serial.print(version);
+  for (byte i = 0; i < (41 - 5 - vLength - 3); i++) {
+    Serial.print(" ");
+  }
+  Serial.println(F("---"));
   Serial.println(SPACER);

   Serial.println(F("Connect to OBD port - Waiting for CAN-Bus "));


Update pll_programmer.ino

Update pll_programmer.ino


Update MultiArrays.ino

Update MultiArrays.ino

comment said *four* strips on three pins. Code is for three strips on three pins.

--- examples/Multiple/MultiArrays/MultiArrays.ino
+++ examples/Multiple/MultiArrays/MultiArrays.ino
@@ -1,5 +1,5 @@
 // MultiArrays - see https://github.com/FastLED/FastLED/wiki/Multiple-Controller-Examples for more info on
-// using multiple controllers.  In this example, we're going to set up four NEOPIXEL strips on three
+// using multiple controllers.  In this example, we're going to set up three NEOPIXEL strips on three
 // different pins, each strip getting its own CRGB array to be played with

 #include "FastLED.h"


Savings on player bullet handling

Savings on player bullet handling

--- arduboy-game/arduboy-game.ino
+++ arduboy-game/arduboy-game.ino
@@ -476,13 +476,14 @@
     }

     if(inGameAButtonLastPress > 80 || inGameBButtonLastPress > 60) {
-       for (byte i = 0; i < MAX_ENEMIES; i++) {
-
-         playerBullets[i].update();
-//       playerBullets[1].update();
-//       playerBullets[2].update();
-//       playerBullets[3].update();
-       }
+//       for (byte i = 0; i < MAX_ENEMIES; i++) {
+//       playerBullets[i].update();
+//       }
+
+       playerBullets[0].update();
+       playerBullets[1].update();
+       playerBullets[2].update();
+       playerBullets[3].update();
     }

     drawStarLayer();
@@ -640,7 +641,7 @@
 //    enemies[0].update();
 //    enemies[1].update();
 //    enemies[2].update();
-//    enemies[3].update();
+//   enemies[3].update();

 }


compass sleep mode. saves about 0.1mA

compass sleep mode. saves about 0.1mA

--- Arduino/Sensor/Sensor.ino
+++ Arduino/Sensor/Sensor.ino
@@ -36,10 +36,6 @@
     /* End Power Management Stuff */

     Wire.begin();
-    Wire.beginTransmission(Addr);
-    Wire.write(byte(0x02));
-    Wire.write(byte(0x00));
-    Wire.endTransmission();

     // Calibrate compass on startup
     isCarPresent();
@@ -86,7 +82,7 @@

         DEBUG_PRINTLN();
     }
-
+
     sleepNow();
 }

@@ -143,6 +139,14 @@
     Returns the X, Y, and Z values from the compass module.
 */
 void getCompassData(int& x, int& y, int& z) {
+    // Set to continuous mode
+    Wire.beginTransmission(Addr);
+    Wire.write(byte(0x02));
+    Wire.write(byte(0x00));
+    Wire.endTransmission();
+
+    delay(10);
+
     // Initiate communications with compass
     Wire.beginTransmission(Addr);
     Wire.write(byte(0x03));       // Send request to X MSB register
@@ -154,6 +158,12 @@
         z = Wire.read() << 8 | Wire.read();
         y = Wire.read() << 8 | Wire.read();
     }
+
+    // Put compass to sleep
+    Wire.beginTransmission(Addr);
+    Wire.write(byte(0x02));
+    Wire.write(byte(0x03));
+    Wire.endTransmission();
 }
 /*
     Returns a byte from 0x40 of the ascii table. Starting at @ A B C ...


fix mapping of wristAngle

fix mapping of wristAngle

--- dfrdb/dfrdb.ino
+++ dfrdb/dfrdb.ino
@@ -102,8 +102,8 @@
     interrupts();   // there is a safer way to do this by saving and restoring
                     // settings register, but since I'm not using extensive
                     // libraries should be OK
-    wristAngle = map(wristPulse, 1000, 2000, minWristAngle, maxWristAngle);
-    wristAngle = constrain(wristAngle, minWristAngle, maxWristAngle); // want to lower when joystick forward, so map in reverse
+    wristAngle = map(wristPulse, 1000, 2000, maxWristAngle, minWristAngle);  // want to lower when joystick forward, so map in reverse
+    wristAngle = constrain(wristAngle, minWristAngle, maxWristAngle);
     wrist.write(wristAngle);
   }
   if (clawFlag){


rpm calc function

rpm calc function

--- Exhibit_MomentumTable.ino
+++ Exhibit_MomentumTable.ino
@@ -21,16 +21,12 @@
 #define STOPTIME            10000   //Expected ramp down time, in MS
  /////////
 #define STARTRELAYPIN       1      //pin locations
-#define HALLSENSOR1PIN      5       //dual hall sensors to detect rotaion
-#define HALLSENSOR2PIN      4
+#define HALLSENSORPIN      5       //hall sensor to detect rotaion
 #define SECONDS             1000    //ms in seconds

 WiFiClient espClient;
 PubSubClient client(espClient);
-unsigned long now = 0 ;
-unsigned long OTAUntilMillis = 0 ;

-char msg[50];

 /**************************************/
@@ -39,8 +35,14 @@

 uint16_t hallSensor1_count  = 0 ;
 uint16_t hallSensor2_count  = 0 ;
-
-
+volatile uint8_t pulseCount = 0 ;
+uint8_t rpm                 = 0 ;
+unsigned long timeOld       = 0 ;
+//
+unsigned long now = 0 ;
+unsigned long prevMillis = 0 ;
+unsigned long OTAUntilMillis = 0 ;
+char msg[50];

 /**************************************/
 /*               SETUP                 /
@@ -49,7 +51,7 @@
 {
 pinMode(STARTRELAYPIN, OUTPUT);
 pinMode(HALLSENSOR1PIN, INPUT);
-pinMode(HALLSENSOR2PIN, INPUT);
+attachInterrupt(digitalPinToInterrupt(HALLSENSORPIN), sensorPulseCount, RISING);

 client.setServer(mqtt_server, 1883);
 client.setCallback(callback);
@@ -63,7 +65,7 @@
 {
 //wait for mqtt commands
 //send out mqtt status
-sensorPulseCount(); // returns formatted RPM number
+calculateRPM();
 discSlipCheck();
 //if commanded != actual caution torque slip
 //if commanded != actual over time, report full error
@@ -79,9 +81,21 @@
 /**************************************/
 /*             FUNCTIONS               /
 /**************************************/
-void sensorPulseCount(){}
-//current rotation value xx
-// report back RPM
+void sensorPulseCount(){
+pulseCount++;
+// expected two pulse counts per rotation, two sensors
+}
+
+void calculateRPM(){
+if (millis() - prevMillis == 1000){
+    detachInterrupt();              //disable interrupts while running calculate
+    rpm = pulseCount * 60;          //converting frequency to RPM
+    pulseCount = 0;                 //reset pulse counter
+    prevMillis = millis();          //update prevMillis
+    attachInterrupt(digitalPinToInterrupt(HALLSENSORPIN), sensorPulseCount, RISING);
+    //reattach interrupt
+    }
+  }

 void motionControlStart(){}
 //enable start relay


Typo arrgh

Typo arrgh

--- ScooterSpeedo.ino
+++ ScooterSpeedo.ino
@@ -189,7 +189,7 @@
   EEPROM.put(MAX_RECORD_ACCEL_Y_ADDRESS, a);
 }

-void resetRecords(() {
+void resetRecords() {
   EEPROM.put(MAX_RECORD_KPH_ADDRESS, 0.0);
   EEPROM.put(MAX_RECORD_ACCEL_Y_ADDRESS, 0.0);
 }


Small adjustments.

Small adjustments.

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

-//#define NUKEYKTPROTO
+#define NUKEYKTPROTO 0

 OPL3Duo opl3Duo;


updated version description.

updated version description.

--- AOA_TONE_EFIS_SERIAL/AOA_TONE_EFIS_SERIAL.ino
+++ AOA_TONE_EFIS_SERIAL/AOA_TONE_EFIS_SERIAL.ino
@@ -2,7 +2,7 @@
 ////////////////////////////////////////////////////
 // AOA EFIS Serial to audio tone
 // Supports: Dynon EFIS data using a Arduino Due board
-// Ver 1.5.2
+// Ver 1.6.1
 // Christopher Jones 6/10/2016
 //
 // - Read data in from Serial3 on DUE board. (Dynon is at 115200 baud)
@@ -10,9 +10,10 @@
 // - Audio ouput on pin 2
 // - If no serial data is detected audio tone turns off and LED1 is off
 // - MUTE_AUDIO_UNDER_IAS define is used to only activate audio tones if above a given airspeed
-//
-// 7/9/2018   - 1.5.1 fix for tone PPS between solid tones.  was not calucating the right ratio for the PPS changes.
-// 9/2/2018   - 1.5.2 Atempts to fix hang up issues with skyview data.  Changed start up tones.  added more comments. fix min PPS for low tone.
+//
+// 6/10/2016  - Started
+// 7/09/2018  - 1.5.1 fix for tone PPS between solid tones.  was not calucating the right ratio for the PPS changes.
+// 9/02/2018  - 1.5.2 Atempts to fix hang up issues with skyview data.  Changed start up tones.  added more comments. fix min PPS for low tone.
 // 9/28/2018  - 1.6.0 Fixed Skyview lockup issue.
 // 9/28/2018  - 1.6.1 allow for automatic efis dectection d100 or skyview.


Forward declarations in Hello, World

Forward declarations in Hello, World

--- examples/HelloWorld/HelloWorld.ino
+++ examples/HelloWorld/HelloWorld.ino
@@ -20,10 +20,16 @@
 uint8_t header[16];
 uint8_t data[MAXDATALEN];

+// Forward declaration of onRequest() and onReceived() functions
+int onReceived(uint8_t type, enum Endpoint model, int datalen);
+int onRequest(uint8_t type, enum Endpoint model, int* headerlen,
+              int* datalen, data_callback* data_callback);
+
 void setup() {
     Serial.begin(9600);
     cbl.setLines(lineRed, lineWhite);
     cbl.resetLines();
+    //cbl.setVerbosity(true, &Serial);      // Comment this in for message information
     cbl.setupCallbacks(header, data, MAXDATALEN, onReceived, onRequest);
 }

@@ -32,7 +38,10 @@
 }

 int onReceived(uint8_t type, enum Endpoint model, int datalen) {
+    Serial. println(header[0]);
     if (type != VarTypes82::VarString) {
+        Serial.print(type);
+        Serial.println("Received invalid data type");
         return -1; // Can only accept strings
     }

@@ -42,8 +51,12 @@
 }

 int onRequest(uint8_t type, enum Endpoint model, int* headerlen,
-              int* datalen, data_callback* data_callback) {
+              int* datalen, data_callback* data_callback)
+{
+    Serial.println(header[0]);
     if (type != VarTypes82::VarString) {
+        Serial.print(type);
+        Serial.println("Received request for invalid data type");
         return -1; // Can only return strings
     }

@@ -64,4 +77,4 @@
     Serial.println("Sending: " + hello);

     return 0;
-}+}


Added missing include

Added missing include

--- examples/SimpleList/SimpleList.ino
+++ examples/SimpleList/SimpleList.ino
@@ -9,6 +9,7 @@
 	https://github.com/SloCompTech/QList

 */
+#include "Qlist.h"
 QList<String> myList;
 void setup()
 {


Added a bit more info to the status request.

--- weather_logger/weather_logger.ino
+++ weather_logger/weather_logger.ino
@@ -378,11 +378,14 @@
         streamingMode = true;
         commandTimeOut = millis() + 1000; // make sure it starts soon sending data
         break;
-      case 3: // Start debug mode (need to send 03 for this command)
-        sendSerialString("Arduino based weather data collector and logger.");
+      case 3: // Send status info (need to send 03 for this command)
+        sendSerialString("Arduino based weather data collector.");
         sendSerialString("Copyright (c) 2014 W. Boasson");
+        sendSerialString("License: MIT");
         sendSerialString("Serial connection established");
-        sendSerialString("Software version: " + (String)version);
+        sendSerialString("Measurement interval set to: " + (String)measurementInterval + " [ms]");
+        sendSerialString("Startup mode (1 = streaming; 0 = datalogger): " + (String)streamingMode);
+        sendSerialString("Software version: " + (String)version); // this must be the last output
         break;
       case 10: // Clear the data
         if (DEBUG) sendSerialString("Clear the data");


Modified

Modified

--- ESP_Programming/accel_tcp_post/accel_tcp_post.ino
+++ ESP_Programming/accel_tcp_post/accel_tcp_post.ino
@@ -21,6 +21,9 @@
 const char* host = "10.0.203.231";
 const char* streamId   = "....................";
 const char* privateKey = "....................";
+
+float G[3]={0.0,0.0,0.0};
+float alpha=0.9;

 void setup() {
   Serial.begin(115200);
@@ -81,23 +84,38 @@
     Serial.println("connection failed");
     return;
   }
+
+
+  G[0] = alpha * G[0] + (1-alpha) * accel.X;
+  G[1] = alpha * G[1] + (1-alpha) * accel.Y;
+  G[2] = alpha * G[2] + (1-alpha) * accel.Z;
+
+  //char* row;
+  //sprintf(row, "%d,%d,%d", accel.X - G[0], accel.Y - G[1], accel.Z - G[2]);
+
+  String row = String(int(accel.X - G[0])) + "," + String(int(accel.Y - G[1])) + "," + String(int(accel.Z - G[2]));
+  Serial.println(row);
+

   // We now create a URI for the request
   String url = "/stream";
-  String tsData = String("X=" + accel.X);
+  String tsData = String(accel.X);
+  //Serial.println(tsData);

   Serial.print("Requesting URL: ");
   Serial.println(url);
+
+

   // This will send the request to the server
   client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n");
-  client.print("Content-Type: application/x-www-form-urlencoded\n");
+  client.print("Content-Type: application/x-www-form-urlencoded\r\n");
   client.print("Content-Length: ");
   client.print(tsData.length());
-  client.print("\n\n");
+  client.print("\r\n\r\n");
   client.print(tsData);
   client.print("Connection: close\r\n\r\n");
-
+
   delay(1000);

   // Read all the lines of the reply from server and print them to Serial


Sawtooth Motorcontroller Test code

Sawtooth Motorcontroller Test code

Sample arduino test code for interfacing with Sawtooth Motorcontroller.

--- motorboard/Motor_Board_testcode/Motor_Board_testcode.ino
+++ motorboard/Motor_Board_testcode/Motor_Board_testcode.ino
@@ -21,17 +21,18 @@

 void setup(){
 //  attachInterrupt(2,RISING);
-  pinMode(2,INPUT);
-  pinMode(3,INPUT);
-  Serial.begin(9600);
-  _delay_us(1000);
-  Serial.write((uint8_t)127);
+//  pinMode(2,INPUT);
+  pinMode(6,OUTPUT);
+//  Serial.begin(9600);
+//  _delay_us(1000);
+//  Serial.write((uint8_t)127);
 }

 void loop(){
-  if (digitalRead(2) == HIGH){
-      Serial.write((uint8_t)64);
-  } else if (digitalRead(3) == HIGH) {
-      Serial.write((uint8_t)127);
-  }
+  analogWrite(6,125);
+//  if (digitalRead(2) == HIGH){
+//      Serial.write((uint8_t)64);
+//  } else if (digitalRead(3) == HIGH) {
+//      Serial.write((uint8_t)127);
+//  }
 }


Implement CAN network code, edit range on yaw mapping

--- GyroSketch/GyroSketch.ino
+++ GyroSketch/GyroSketch.ino
@@ -18,7 +18,7 @@
 #include "MPU6050_9Axis_MotionApps41.h"   //MPU6050 function library
 #include "mcp_can.h"    //CAN communication library

-#define CAN_ID 0x00
+#define CAN_ID 0x150

 // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
 // is used in I2Cdev.h
@@ -28,7 +28,7 @@

 // class default I2C address is 0x68
 MPU6050 mpu;
-//MCP_CAN CAN(9);
+MCP_CAN CAN(9);

 #define OUTPUT_READABLE_WORLDACCEL
@@ -104,12 +104,6 @@
     // verify connection
     Serial.println(F("Testing device connections..."));
     Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
-
-    // wait for ready
-    Serial.println(F("\nSend any character to begin DMP programming and demo: "));
-    while (Serial.available() && Serial.read()); // empty buffer
-    while (!Serial.available());                 // wait for data
-    while (Serial.available() && Serial.read()); // empty buffer again

     // load and configure the DMP
     Serial.println(F("Initializing DMP..."));
@@ -150,6 +144,10 @@
         Serial.println(F(")"));
     }

+    // init can bus, baudrate: 500k
+    if(CAN.begin(CAN_500KBPS) == CAN_OK) Serial.print("can init ok!!\r\n");
+    else Serial.print("Can init fail!!\r\n");
+
     // configure LED for output
     pinMode(LED_PIN, OUTPUT);

@@ -218,11 +216,11 @@
         Serial.print("\t");

         //yaw (Direction)/pitch/roll
-        Serial.print(ypr[0] * 180/M_PI);
-        Serial.print(",\t");
-        Serial.print(ypr[1] * 180/M_PI);
-        Serial.print(",\t");
-        Serial.print(ypr[2] * 180/M_PI);
+        Serial.print(ypr[0]);
+        Serial.print(",\t");
+        Serial.print(ypr[1]);
+        Serial.print(",\t");
+        Serial.print(ypr[2]);
         Serial.print("\t");

         //Quaternerion Coordinates
@@ -260,16 +258,16 @@
         Serial.print("\n");

         //Prep data to send over CAN
-        map(ypr[0],-M_PI, M_PI, 0, 65535);
-        map(aaReal.x, -32768, 32768, 0, 65535);
-        map(aaReal.y, -32768, 32768, 0, 65535);
-        map(aaReal.z, -32768, 32768, 0, 65535);
+        ypr[0] = map(ypr[0]*100,-M_PI*100, M_PI*100, 0, 65535);
+        aaReal.x = map(aaReal.x, -32768, 32768, 0, 65535);
+        aaReal.y = map(aaReal.y, -32768, 32768, 0, 65535);
+        aaReal.z = map(aaReal.z, -32768, 32768, 0, 65535);

         //separates value into two 8 bit sets for transmission by typecasting as an integer and shifting and bitwise &ing into 8bit int vars
         //break down Direction data
-        unsigned char hiDir = ((((int) (ypr[0])) >> 8) & 0xff);
-        unsigned char loDir = ((((int) (ypr[0])) >> 0) & 0xff);
+        unsigned char hiDir = ((((unsigned int) (ypr[0])) >> 8) & 0xff);
+        unsigned char loDir = ((((unsigned int) (ypr[0])) >> 0) & 0xff);
         //break down X data
         unsigned char hiX = ((((unsigned int) (aaReal.x)) >> 8) & 0xff);
         unsigned char loX = ((((unsigned int) (aaReal.x)) >> 0) & 0xff);
@@ -283,7 +281,7 @@
         //Create package to send over CAN
         unsigned char CANbuf[8] = {hiDir, loDir, hiX, loX, hiY, loY, hiZ, loZ};
         //Send data over CAN
-        //CAN.sendMsgBuf(CAN_ID, 0, 8, CANbuf); //send out the package above to the bus and tell other devices this is a standard frame from 0x00.
+        CAN.sendMsgBuf(CAN_ID, 0, 8, CANbuf); //send out the package above to the bus and tell other devices this is a standard frame from 0x00.

         // blink LED to indicate activity
         blinkState = !blinkState;


Cleanup

Cleanup


모듈 딜레이 시간 줄임

모듈 딜레이 시간 줄임

Signed-off-by: yoowonyoung <ad197563590a6860fa7b20962aa2162389840fd1@gmail.com>

--- Arduino/wifi_feeding/wifi_feeding.ino
+++ Arduino/wifi_feeding/wifi_feeding.ino
@@ -29,7 +29,7 @@
   String getRequest = "GET /iodsc/iodcontrol?action=getControl&moduleName=FEED";
   int getRequestLength = getRequest.length() + 2;
   r = espSendCommand( "AT+CIPSEND=" + String(getRequestLength) , "OK" , 5000 );
-  if(espSendCommand( getRequest , "ONCE" , 15000 )){
+  if(espSendCommand( getRequest , "ONCE" , 3000 )){
       analogWrite(motorPin, 255);
       delay(15000);
       analogWrite(motorPin, 0);


motor controller pins

motor controller pins

--- dfrdb/dfrdb.ino
+++ dfrdb/dfrdb.ino
@@ -5,8 +5,8 @@
 drives just the claw - user Sabertooth for motor shield

 Pin connections:
-AIL:
-ELE:
+AIL: roboclaw 2
+ELE: roboclaw 1
 THR: 3
 RUD: 2


added depp sleep

added depp sleep

--- esp8266_dht22.ino
+++ esp8266_dht22.ino
@@ -2,18 +2,23 @@
 #include "DHT.h"

 //WiFi setup
+//replace with your values
+byte ip[]        {192,168,1,14};
+byte dns[]       {192,168,1,1};
+byte gateway[]   {192,168,1,1};
+
+//replace with your values
 #define ssid       "......."
 #define password   "......."

 //Thingspeak setup
+//replace with your values
 #define thingspeakApiKey "................"
 #define thingSpeakAddress "api.thingspeak.com"
 #define thingSpeakUpdateJsonEndpoint "/update.json"
 #define thingSpeakHttpPort 80
-//Update data for the specific channel not frequently than 16 sec
-#define thingSpeakUpdateInterval 16000
-//Update data for the specific channel if it's the same not frequently than 5 mins
-#define thingSpeakUpdateSameDataInterval 300000 //5 min
+//Update data for the specific channel not frequently than 30 sec
+#define thingSpeakUpdateInterval 50000000

 //DHT22
 #define DHTTYPE DHT22
@@ -22,9 +27,6 @@

 //wifi client
 WiFiClient client;
-//byte lastClientStatus = WL_DISCONNECTED;
-//#define deepSleepTime 120000000 //2 minutes
-//#define wakeTime 120000 //2 minutes

 // === wifi section
 void setupWifi() {
@@ -33,9 +35,10 @@
     if (status == WL_DISCONNECTED || status == WL_CONNECTION_LOST) {

         //turnWifiInProgressLedState();
-
+        WiFi.config(ip, dns, gateway);
         WiFi.begin(ssid, password);

+        Serial.println();
         while (WiFi.status() == WL_DISCONNECTED) {
             delay(500);
             Serial.print(".");
@@ -108,9 +111,10 @@
 }

 void loop() {
-  //setup wifi
-  //in loop to re init connection if necessary
-  setupWifi();
+  unsigned long startTime = millis();
+
+  //delay before DHT measurements
+  delay(2000);

   // Reading temperature or humidity takes about 250 milliseconds!
   // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
@@ -122,7 +126,8 @@
   if (!isnan(h) && !isnan(t)) {
     // Compute heat index in Celsius (isFahreheit = false)
     float hic = dht.computeHeatIndex(t, h, false);
-
+
+    Serial.println();
     Serial.print("Humidity: ");
     Serial.print(h);
     Serial.print(" %\t");
@@ -132,12 +137,27 @@
     Serial.print("Heat index: ");
     Serial.print(hic);
     Serial.print(" *C ");
-
+
+    //setup wifi
+    //in loop to re init connection if necessary
+    setupWifi();
+
     postData(t, h, hic);
   } else {
+    Serial.println();
     Serial.println("Failed to read from DHT sensor!");
   }

-     // Wait a few seconds between measurements.
-  delay(30000);
+  Serial.println("Total uptime: " + String(millis() - startTime));
+
+  // deep sleep between measurements.
+  // for lower power consumptions
+  Serial.println("Going to deep sleep for " + String(thingSpeakUpdateInterval / (1000 * 1000)) + " sec.");
+  //Need to connect GPIO16 to RST otherwise deep sleep will not work
+  ESP.deepSleep(thingSpeakUpdateInterval, WAKE_RF_DEFAULT);
 }
+
+
+
+
+


get master back on track

get master back on track

--- Mod-Sketch/Mod-Sketch.ino
+++ Mod-Sketch/Mod-Sketch.ino
@@ -237,7 +237,7 @@
     Toy.step[0] = Toy.step[1] = Toy.step[2] = fadeTable[seq];
   }
   Toy.step[3] = 12;
-  return 1;
+  return 1;
 }

 int fadeCos(int seq) {


mcp2551 -> mcp2515

mcp2551 -> mcp2515

--- examples/CAN_read/CAN_read.ino
+++ examples/CAN_read/CAN_read.ino
@@ -2,19 +2,19 @@
 #include <mcp_can.h>

 struct can_frame canMsg;
-MCP_CAN mcp2551(10, MCP_CAN::MODE_NORMAL);
+MCP_CAN mcp2515(10, MCP_CAN::MODE_NORMAL);

 void setup() {
   Serial.begin(115200);
-  mcp2551.begin(CAN_125KBPS);
+  mcp2515.begin(CAN_125KBPS);
   Serial.println("------- CAN Read ----------");
   Serial.println("ID  DLC   DATA");
 }

 void loop() {

-  if (mcp2551.readMessage(&canMsg) == MCP_CAN::ERROR_OK) {
+  if (mcp2515.readMessage(&canMsg) == MCP_CAN::ERROR_OK) {

     Serial.print(canMsg.can_id); // print ID


Done reader

Done reader

--- RFIDreader/RFIDreader.ino
+++ RFIDreader/RFIDreader.ino
@@ -1,6 +1,4 @@
 #include <SoftwareSerial.h>
-
-

 /* RFID Reader
    Uses RDM880 breakout board with RX connected to pin 2 and TX connected to pin 3.
@@ -27,11 +25,11 @@
 // command packet - start, address, data length, command, data[0 to 2], end
 // response packet when idle - 0xAA, 0x00, 0x02, 0x01, 0x83, 0x80, 0xBB
 char get_readID[] = { 0xAA , 0x00, 0x03, 0x25, 0x26, 0x00, 0x00, 0xBB };
-byte response[11];
+byte response[15];
+
 const int ledPin = 13;
 const int signalPin = 4;
-bool standby;
-unsigned long elapsedTime;
+const int debounce = 25;

 void setup() {
   Serial.begin(57600);
@@ -41,12 +39,14 @@
 }

 void loop() {
+  bool standby = true;
+  response[7] = NULL;
+  unsigned long elapsedTime = 0;
+
   // send command packet to RDM880 to read serial number every second
   RDM880.write(get_readID, 8);
   delay(100);
   digitalWrite(ledPin, LOW);
-  response[7] = NULL;
-  standby = true;

   // read response packet from RDM880 and print
   int i = 0;
@@ -71,10 +71,11 @@
   unsigned long startTime, endTime = 0;
   int signalState;
   int previousState = NULL;
+
   while(standby == false) {
     // read signal state
     signalState = digitalRead(signalPin);
-    delay(25);
+    delay(debounce);

     // debounce check
     if (signalState == digitalRead(signalPin)) {


Fix for #148

Fix for #148

--- examples/ecc_test/ecc_test.ino
+++ examples/ecc_test/ecc_test.ino
@@ -1,6 +1,4 @@
 #include <uECC.h>
-
-extern "C" {

 static int RNG(uint8_t *dest, unsigned size) {
   // Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of
@@ -28,8 +26,6 @@
   // NOTE: it would be a good idea to hash the resulting random data using SHA-256 or similar.
   return 1;
 }
-
-}  // extern "C"

 void setup() {
   Serial.begin(115200);
@@ -82,4 +78,3 @@
     Serial.print("Shared secrets are identical\n");
   }
 }
-


To follow WireS change

To follow WireS change

--- c_I2C.ino
+++ c_I2C.ino
@@ -146,7 +146,7 @@
 volatile boolean emulateRom;

 // interrupts
-boolean addressHandler(uint8_t slave, uint8_t count)
+boolean addressHandler(uint16_t slave, uint8_t count)
 {
   emulateRom = ((slave >> 1) == I2CEEPROM);
   repeatedStart = (count > 0 ? true : false);


update comments

update comments

--- dfrdb/dfrdb.ino
+++ dfrdb/dfrdb.ino
@@ -23,19 +23,15 @@

 */

-/***************************
-To do:
-clean up variable names

-
-***************************/
 #include <Servo.h>

 Servo wrist;
 Servo claw;

 const int WristInterrupt = 3; // interrupt 0 is on pin 3 for wrist (throttle on receiver)
-const int ClawInterrupt = 2; // interrupt 1 is on pin 2 for claw (rudder on receiver)
+const int ClawInterrupt = 2;
+// interrupt 1 is on pin 2 for claw (rudder on receiver)
 const int WristPin = 12;
 const int ClawPin = 13;

@@ -50,12 +46,12 @@
 int clawAngle = 85;
 int clawMinDeadspaceLimit = 1400; // threshold for closing claw; want dead zone in center
 int clawMaxDeadspaceLimit = 1600; // threshold for opening claw
-const int minClawAngle = 35; // limit travel to protect servo
+const int minClawAngle = 35;      // limit travel to protect servo
 const int maxClawAngle = 135;

 void setup() {
   attachInterrupt(0, readWristInterrupt, CHANGE);  // pin 3 on Romeo  __ signal for wrist
-  attachInterrupt(1, readClawInterrupt, CHANGE);  // pin 2            __ signal for claw
+  attachInterrupt(1, readClawInterrupt, CHANGE);   // pin 2            __ signal for claw
   wrist.attach(WristPin);
   claw.attach(ClawPin);
   wrist.write(90); // starting position
@@ -73,7 +69,8 @@

     wrist.writeMicroseconds(wristPulse);

-    // for claw want to open/close base on stick, but then hold position
+    // for claw want to open/close base on stick, but then hold position; so increment/decrement depending on position
+    // and then keep that value if joystick centered
     if (clawPulse < clawMinDeadspaceLimit){
       clawAngle -= 1;
     }


httpGetの高速化

httpGetの高速化

--- 2_example/example60_lcdkey/httpGet.ino
+++ 2_example/example60_lcdkey/httpGet.ino
@@ -32,6 +32,7 @@
     Serial.println(s);
     Serial.print("Max Size  : ");
     Serial.println(max_size);
+    Serial.println("Recieving contents...");
     if (!client.connect(to,80)){            // 外部サイトへ接続を実行する
         Serial.println("ERROR: Failed to connect");
         return 0;
@@ -50,19 +51,27 @@
     client.print(to);                       // 相手先ホスト名
     client.println();                       // ホスト名の指定を終了
     client.println("Connection: close");    // セッションの都度切断を指定
-    i=0;
+
+    // 以下の処理はデータの受信完了まで終了しないので、その間に届いたデータを
+    // 損失してしまう場合があります。
+    // Wi-Fiカメラの初期版では、送信完了まで20秒くらいかかります。
     while(t<TIMEOUT){
         if(client.available()){             // クライアントからのデータを確認
             t=0;
             c=client.read();                // TCPデータの読み取り
             if(headF==2){
-				s[i]=c; size++; i++;
-                if(i>=64){
-					file.write((const uint8_t *)s, 64);
-					i=0;
-				}
+                // 複数バイトread命令を使用する
+                // int WiFiClient::read(uint8_t *buf, size_t size)
+                s[0]=c; size++;				// 既に取得した1バイト目を代入
+                i=client.read((uint8_t *)s+1,63);	// 63バイトを取得
+                // 戻り値はrecvが代入されている
+                // int res = recv(fd(), buf, size, MSG_DONTWAIT);
+                if(i>0){							// 受信データがある時
+                    file.write((const uint8_t *)s, i+1);
+                    size += i;
+                } else file.write(c);
                 if(size >= max_size) break;
-                continue;                   // while ループを継続
+                continue;
             }
             if(headF==1){                   // 前回が行端の時
                 if(c=='\n') headF=2;        // 今回も行端ならヘッダ終了


Limit number of updates for servo library to catch up

--- arduino/mearm.ino
+++ arduino/mearm.ino
@@ -48,6 +48,8 @@
   int dt = millis() - t0;
   if (Serial.available())
     controller.parseChar(Serial.read());
-  controller.update(dt);
-  t0 += dt;
+  if (dt >= 20) {
+    controller.update(dt);
+    t0 += dt;
+  };
 }