Go with the flow

Go with the flow

redoDO

--- Firmware/R2-Quadcopter/R2-Quadcopter.ino
+++ Firmware/R2-Quadcopter/R2-Quadcopter.ino
@@ -15,16 +15,16 @@
 // PID
 bool auto_stabilisation_mode = false; // Activer ou pas le mode auto-stabilisé
 int dt = 3;
-double pid_roll_speed_in, pid_roll_angle_in,   pid_roll_out,   pid_roll_setpoint,  roll_error,  Integral_roll_error,  Derivative_roll_error,  last_roll_error, AS_roll_error, AS_Integral_roll_error, AS_Derivative_roll_error, AS_last_roll_error = 0;
-double pid_pitch_speed_in, pid_pitch_angle_in,  pid_pitch_out,  pid_pitch_setpoint, pitch_error, Integral_pitch_error, Derivative_pitch_error, last_pitch_error, AS_pitch_error, AS_Integral_pitch_error, AS_Derivative_pitch_error, AS_last_pitch_error = 0;
-double pid_yaw_speed_in,    pid_yaw_out,       pid_yaw_setpoint,   yaw_error,   Integral_yaw_error,   Derivative_yaw_error,   last_yaw_error = 0;
+float pid_roll_out,   pid_roll_setpoint,  roll_error, Proportional_roll,  Integral_roll,  Derivative_roll,  last_roll_error, AS_roll_error, AS_Integral_roll, AS_Derivative_roll, AS_last_roll_error = 0;
+float pid_pitch_out,  pid_pitch_setpoint, pitch_error,Proportional_pitch, Integral_pitch, Derivative_pitch, last_pitch_error, AS_pitch_error, AS_Integral_pitch, AS_Derivative_pitch, AS_last_pitch_error = 0;
+float pid_yaw_out,    pid_yaw_setpoint,   yaw_error,  Proportional_yaw,   Integral_yaw,   Derivative_yaw,   last_yaw_error = 0;

 // MOTORS
 int motorFR, motorBL, motorFL, motorBR;

 // RX
 int throttle = THROTTLE_RMIN;
-volatile int input[4], arm;
+volatile int input[5];
 volatile unsigned long chrono_start0, chrono_start1, chrono_start2, chrono_start3, chrono_start4;
 volatile int last_interrupt_time0, last_interrupt_time1, last_interrupt_time2, last_interrupt_time3, last_interrupt_time4;

@@ -35,45 +35,52 @@
 const float pi = 3.14159265359;
 Adafruit_BNO055 bno = Adafruit_BNO055();

-//// Fonctions de lecture du gyro et accel
-
-//Initiation du IMU
-void bno_initialisation() {
+
+
+
+// Fonction qui s'execute une fois et au début
+void setup() {
+  Serial.begin(9600);
+  //BNO init
   bno.begin();
   bno.setExtCrystalUse(true);
-}
-
-// Calculer inclinaison
-void bno_get_values() {
+
+  //RX init
+  attachInterrupt(A0, calcSignal0, CHANGE);
+  attachInterrupt(A1, calcSignal1, CHANGE);
+  attachInterrupt(A2, calcSignal2, CHANGE);
+  attachInterrupt(A3, calcSignal3, CHANGE);
+  attachInterrupt(A4, calcSignal4, CHANGE);
+
+  //Motors init
+  esc_1.attach(MOTOR_PIN_FRONT_RIGHT);
+  esc_2.attach(MOTOR_PIN_FRONT_LEFT);
+  esc_3.attach(MOTOR_PIN_BACK_LEFT);
+  esc_4.attach(MOTOR_PIN_BACK_RIGHT);
+}
+
+
+// Fonction qui s'execute a chaque cycle
+void loop() {
+
+  //IMU calculations
   if (auto_stabilisation_mode == false) {
     imu::Vector<3> gyroscope = bno.getVector(Adafruit_BNO055::VECTOR_GYROSCOPE);
     roll_speed = gyroscope.x() * 180 / pi;
     pitch_speed = gyroscope.y() * 180 / pi;
     yaw_speed = gyroscope.z() * 180 / pi;
-    pid_roll_speed_in = roll_speed;
-    pid_pitch_speed_in = pitch_speed;
-    pid_yaw_speed_in = yaw_speed;
-  }
-  else {
+  }else{
     imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER);
     roll_angle = euler.z();
     pitch_angle = euler.y();
-    pid_roll_angle_in = map(roll_angle, -180, 180, ROLL_WMIN, ROLL_WMAX);
-    pid_pitch_angle_in = map(pitch_angle, -180, 180, PITCH_WMIN, PITCH_WMAX);
-  }
-}
-
-
-//// Fonctions de controle
-
-// Calculer l'output et l'ecrire
-void control_update() {
-  // Fait correspondre les valeurs du joystick aux valeurs des moteurs
+    yaw_angle = euler.x();
+  }
+
+
+  //MOTORS
   throttle = map(input[2], THROTTLE_RMIN, THROTTLE_RMAX, MOTOR_ZERO_LEVEL, MOTOR_MAX_LEVEL);
-
-  // Calculer les valeurs a écrire aux moteurs
+  //PID
   pid_compute();
-
   // Ecrire les valeurs aux moteurs
   motorFR = throttle + pid_pitch_out + pid_roll_out - pid_yaw_out;
   motorFL = throttle + pid_pitch_out - pid_roll_out + pid_yaw_out;
@@ -81,12 +88,174 @@
   motorBR = throttle - pid_pitch_out + pid_roll_out + pid_yaw_out;

-  esc_1.writeMicroseconds(motorFR);
-  esc_2.writeMicroseconds(motorFL);
-  esc_3.writeMicroseconds(motorBL);
-  esc_4.writeMicroseconds(motorBR);
-
-}
+  ///ARM switch
+  if(input[4] > 1500){
+    esc_1.writeMicroseconds(motorFR);
+    esc_2.writeMicroseconds(motorFL);
+    esc_3.writeMicroseconds(motorBL);
+    esc_4.writeMicroseconds(motorBR);
+  }else if (input[4] < 1500) {
+    esc_1.writeMicroseconds(1000);
+    esc_3.writeMicroseconds(1000);
+    esc_2.writeMicroseconds(1000);
+    esc_4.writeMicroseconds(1000);
+  }
+
+
+  print_motors();
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//INTERRUPTS
+////////////////////////////////////////////////////////////////////////
+void calcSignal0() {
+  last_interrupt_time0 = micros();
+  if(digitalRead(A0) == HIGH){
+    chrono_start0 = micros();
+  }
+  else{
+    if(chrono_start0 != 0){
+      input[0] = ((volatile int)micros() - chrono_start0);
+      chrono_start0 = 0;
+    }
+  }
+}
+
+void calcSignal1() {
+  last_interrupt_time1 = micros();
+  if(digitalRead(A1) == HIGH){
+    chrono_start1 = micros();
+  }
+  else{
+    if(chrono_start1 != 0){
+      input[1] = ((volatile int)micros() - chrono_start1);
+      chrono_start1 = 0;
+    }
+  }
+}
+
+void calcSignal2() {
+  last_interrupt_time2 = micros();
+  if(digitalRead(A2) == HIGH){
+    chrono_start2 = micros();
+  }
+  else{
+    if(chrono_start2 != 0){
+      input[2] = ((volatile int)micros() - chrono_start2);
+      chrono_start2 = 0;
+    }
+  }
+}
+
+void calcSignal3() {
+  last_interrupt_time3 = micros();
+  if(digitalRead(A3) == HIGH){
+    chrono_start3 = micros();
+  }
+  else{
+    if(chrono_start3 != 0){
+      input[3] = ((volatile int)micros() - chrono_start3);
+      chrono_start3 = 0;
+    }
+  }
+}
+
+void calcSignal4() {
+  last_interrupt_time4 = micros();
+  if(digitalRead(A4) == HIGH){
+    chrono_start4 = micros();
+  }
+  else{
+    if(chrono_start4 != 0){
+      input[4] = ((volatile int)micros() - chrono_start4);
+      chrono_start4 = 0;
+    }
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//PID controller
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void pid_compute() {
+
+  //REDO
+  //ROLL calculations
+  pid_roll_setpoint = 0;
+  if(input[0] > THROTTLE_RMID+10)pid_roll_setpoint = (input[0]-THROTTLE_RMID+10)/2.0;
+  else if(input[0] < THROTTLE_RMID-10)pid_roll_setpoint = (input[0]-THROTTLE_RMID-10)/2.0;
+
+  roll_error = roll_speed - pid_roll_setpoint;
+
+  Proportional_roll = ROLL_PID_KP * roll_error;
+  Integral_roll += ROLL_PID_KI * roll_error;
+  if(Integral_roll > ROLL_PID_MAX)Integral_roll = ROLL_PID_MAX;
+  else if(Integral_roll < ROLL_PID_MIN)Integral_roll = ROLL_PID_MIN;
+  Derivative_roll = ROLL_PID_KD * (roll_error - last_roll_error);
+
+  pid_roll_out = Proportional_roll + Integral_roll + Derivative_roll;
+  if(pid_roll_out > ROLL_PID_MAX)pid_roll_out = ROLL_PID_MAX;
+  else if(pid_roll_out < ROLL_PID_MIN)pid_roll_out = ROLL_PID_MIN;
+
+  last_roll_error = roll_error;
+
+
+  //PITCH calculations
+  pid_pitch_setpoint = 0;
+  if(input[1] > THROTTLE_RMID+10)pid_pitch_setpoint = (input[1]-THROTTLE_RMID+10)/2.0;
+  else if(input[1] < THROTTLE_RMID-10)pid_pitch_setpoint = (input[1]-THROTTLE_RMID-10)/2.0;
+
+  pitch_error = pitch_speed - pid_pitch_setpoint;
+
+  Proportional_pitch = PITCH_PID_KP * pitch_error;
+  Integral_pitch += PITCH_PID_KI * pitch_error;
+  if(Integral_pitch > PITCH_PID_MAX)Integral_pitch = PITCH_PID_MAX;
+  else if(Integral_pitch < PITCH_PID_MIN)Integral_pitch = PITCH_PID_MIN;
+  Derivative_pitch = PITCH_PID_KD * (pitch_error - last_pitch_error);
+
+  pid_picth_out = Proportional_pitch + Integral_pitch + Derivative_pitch;
+  if(pid_pitch_out > PITCH_PID_MAX)pid_pitch_out = PITCH_PID_MAX;
+  else if(pid_pitch_out < PITCH_PID_MIN)pid_pitch_out = PITCH_PID_MIN;
+
+  last_pitch_error = pitch_error;
+
+//YAW calculations
+  pid_yaw_setpoint = 0;
+  if(input[3] > THROTTLE_RMID+10)pid_yaw_setpoint = (input[3]-THROTTLE_RMID+10)/2.0;
+  else if(input[3] < THROTTLE_RMID-10)pid_yaw_setpoint = (input[3]-THROTTLE_RMID-10)/2.0;
+
+  yaw_error = yaw_speed - pid_yaw_setpoint;
+
+  Proportional_yaw = YAW_PID_KP * yaw_error;
+  Integral_yaw += YAW_PID_KI * yaw_error;
+  if(Integral_yaw > YAW_PID_MAX)Integral_yaw = YAW_PID_MAX;
+  else if(Integral_yaw < YAW_PID_MIN)Integral_yaw = YAW_PID_MIN;
+  Derivative_yaw = YAW_PID_KD * (yaw_error - last_yaw_error);
+
+  pid_yaw_out = Proportional_yaw + Integral_yaw + Derivative_yaw;
+  if(pid_yaw_out > YAW_PID_MAX)pid_yaw_out = YAW_PID_MAX;
+  else if(pid_yaw_out < YAW_PID_MIN)pid_yaw_out = YAW_PID_MIN;
+
+  last_yaw_error = yaw_error;
+
+ /////////AUTO STABILIZATION MANQUANTE
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
+

 // Fonction qui empeche les moteurs de tourner
 void motors_set_to_zero() {
@@ -95,103 +264,9 @@
   esc_2.writeMicroseconds(MOTOR_ZERO_LEVEL);
   esc_4.writeMicroseconds(MOTOR_ZERO_LEVEL);
 }
-
-//// Fonctions radio
-
-//TODO: fonction qui lit les interrupts pour une execution plus rapide(pas encore)
-void rx_initialize() {
-  attachInterrupt(A0, calcSignal0, CHANGE);
-  attachInterrupt(A1, calcSignal1, CHANGE);
-  attachInterrupt(A2, calcSignal2, CHANGE);
-  attachInterrupt(A3, calcSignal3, CHANGE);
-}
-
-// Fonctions qui lisent les valeurs de la radio
-void calcSignal0()
-{
-  last_interrupt_time0 = micros();
-
-  if (digitalRead(A0) == HIGH)
-  {
-    chrono_start0 = micros();
-  }
-  else
-  {
-    if (chrono_start0 != 0)
-    {
-      input[0] = ((volatile int)micros() - chrono_start0);
-      chrono_start0 = 0;
-    }
-  }
-}
-
-void calcSignal1()
-{
-  last_interrupt_time1 = micros();
-
-  if (digitalRead(A1) == HIGH)
-  {
-    chrono_start1 = micros();
-  }
-  else
-  {
-    if (chrono_start1 != 0)
-    {
-      input[1] = ((volatile int)micros() - chrono_start1);
-      chrono_start1 = 0;
-    }
-  }
-}
-
-void calcSignal2()
-{
-  last_interrupt_time2 = micros();
-
-  if (digitalRead(A2) == HIGH)
-  {
-    chrono_start2 = micros();
-  }
-  else
-  {
-    if (chrono_start2 != 0)
-    {
-      input[2] = ((volatile int)micros() - chrono_start2);
-      chrono_start2 = 0;
-    }
-  }
-}
-
-void calcSignal3()
-{
-  last_interrupt_time3 = micros();
-
-  if (digitalRead(A3) == HIGH)
-  {
-    chrono_start3 = micros();
-  }
-  else
-  {
-    if (chrono_start3 != 0)
-    {
-      input[3] = ((volatile int)micros() - chrono_start3);
-      chrono_start3 = 0;
-    }
-  }
-}
-
-
-// Fonction qui s'execute une fois et au début
-void setup() {
-  Serial.begin(9600);
-  bno_initialisation();
-  rx_initialize();
-  esc_1.attach(MOTOR_PIN_FRONT_RIGHT);
-  esc_2.attach(MOTOR_PIN_FRONT_LEFT);
-  esc_3.attach(MOTOR_PIN_BACK_LEFT);
-  esc_4.attach(MOTOR_PIN_BACK_RIGHT);
-}
-
+/////////////////////////////////////////////////////////////////////////////////////////
 // Fonctions de debug
+/////////////////////////////////////////////////////////////////////////////////////////
 void print_motors() {
   Serial.print(motorFR);
   Serial.print(",");
@@ -201,11 +276,11 @@
   Serial.print(",");
   Serial.print(motorBR);
   Serial.print(",");
-  Serial.print(pid_roll_speed_in);
-  Serial.print(",");
-  Serial.print(pid_pitch_speed_in);
-  Serial.print(",");
-  Serial.println(pid_yaw_speed_in);
+  Serial.print(roll_speed);
+  Serial.print(",");
+  Serial.print(pitch_speed);
+  Serial.print(",");
+  Serial.println(yaw_speed);
 }

 void print_pid_out() {
@@ -224,11 +299,11 @@
   Serial.println(pid_yaw_setpoint);
 }
 void print_imu() {
-  Serial.print(pid_roll_speed_in);
-  Serial.print(",");
-  Serial.print(pid_pitch_speed_in);
-  Serial.print(",");
-  Serial.println(pid_yaw_speed_in);
+  Serial.print(roll_speed);
+  Serial.print(",");
+  Serial.print(pitch_speed);
+  Serial.print(",");
+  Serial.println(yaw_speed);
 }

 void print_rx() {
@@ -241,16 +316,3 @@
   Serial.println(input[3]);
 }

-// Fonction qui s'execute a chaque cycle
-void loop() {
-  arm = pulseIn(A4, HIGH);
-  bno_get_values();
-
-  if (arm > 1500) {
-    control_update();
-  }
-  else {
-    motors_set_to_zero();
-  }
-  print_motors();
-}


Implemented kill switch

Implemented kill switch

--- Firmware/R2-Quadcopter/R2-Quadcopter.ino
+++ Firmware/R2-Quadcopter/R2-Quadcopter.ino
@@ -24,8 +24,8 @@

 // RX
 int throttle = THROTTLE_RMIN;
-volatile int input[5];
-volatile unsigned long chrono_start0, chrono_start1, chrono_start2, chrono_start3,chrono_start4;
+volatile int input[4], arm;
+volatile unsigned long chrono_start0, chrono_start1, chrono_start2, chrono_start3, chrono_start4;
 volatile int last_interrupt_time0, last_interrupt_time1, last_interrupt_time2, last_interrupt_time3, last_interrupt_time4;

 // IMU
@@ -79,19 +79,13 @@
   motorFL = throttle + pid_pitch_out - pid_roll_out + pid_yaw_out;
   motorBL = throttle - pid_pitch_out - pid_roll_out - pid_yaw_out;
   motorBR = throttle - pid_pitch_out + pid_roll_out + pid_yaw_out;
-
-  if(input[4] > 1500){
-    esc_1.writeMicroseconds(motorFR);
-    esc_2.writeMicroseconds(motorFL);
-    esc_3.writeMicroseconds(motorBL);
-    esc_4.writeMicroseconds(motorBR);
-  }
-  if (input[4] < 1500) {
-    esc_1.writeMicroseconds(1000);
-    esc_3.writeMicroseconds(1000);
-    esc_2.writeMicroseconds(1000);
-    esc_4.writeMicroseconds(1000);
-  }
+
+
+  esc_1.writeMicroseconds(motorFR);
+  esc_2.writeMicroseconds(motorFL);
+  esc_3.writeMicroseconds(motorBL);
+  esc_4.writeMicroseconds(motorBR);
+
 }

 // Fonction qui empeche les moteurs de tourner
@@ -110,99 +104,81 @@
   attachInterrupt(A1, calcSignal1, CHANGE);
   attachInterrupt(A2, calcSignal2, CHANGE);
   attachInterrupt(A3, calcSignal3, CHANGE);
-  attachInterrupt(A4, calcSignal4, CHANGE);
 }

 // Fonctions qui lisent les valeurs de la radio
-void calcSignal0()
-{
-    last_interrupt_time0 = micros();
-
-    if(digitalRead(A0) == HIGH)
-    {
-        chrono_start0 = micros();
-    }
-    else
-    {
-        if(chrono_start0 != 0)
-        {
-            input[0] = ((volatile int)micros() - chrono_start0);
-            chrono_start0 = 0;
-        }
-    }
-}
-
-void calcSignal1()
-{
-    last_interrupt_time1 = micros();
-
-    if(digitalRead(A1) == HIGH)
-    {
-        chrono_start1 = micros();
-    }
-    else
-    {
-        if(chrono_start1 != 0)
-        {
-            input[1] = ((volatile int)micros() - chrono_start1);
-            chrono_start1 = 0;
-        }
-    }
-}
-
-void calcSignal2()
-{
-    last_interrupt_time2 = micros();
-
-    if(digitalRead(A2) == HIGH)
-    {
-        chrono_start2 = micros();
-    }
-    else
-    {
-        if(chrono_start2 != 0)
-        {
-            input[2] = ((volatile int)micros() - chrono_start2);
-            chrono_start2 = 0;
-        }
-    }
-}
-
-void calcSignal3()
-{
-    last_interrupt_time3 = micros();
-
-    if(digitalRead(A3) == HIGH)
-    {
-        chrono_start3 = micros();
-    }
-    else
-    {
-        if(chrono_start3 != 0)
-        {
-            input[3] = ((volatile int)micros() - chrono_start3);
-            chrono_start3 = 0;
-        }
-    }
-}
-
-void calcSignal4()
-{
-    last_interrupt_time4 = micros();
-
-    if(digitalRead(A4) == HIGH)
-    {
-        chrono_start4 = micros();
-    }
-    else
-    {
-        if(chrono_start4 != 0)
-        {
-            input[4] = ((volatile int)micros() - chrono_start4);
-            chrono_start4 = 0;
-        }
-    }
-}
+void calcSignal0()
+{
+  last_interrupt_time0 = micros();
+
+  if (digitalRead(A0) == HIGH)
+  {
+    chrono_start0 = micros();
+  }
+  else
+  {
+    if (chrono_start0 != 0)
+    {
+      input[0] = ((volatile int)micros() - chrono_start0);
+      chrono_start0 = 0;
+    }
+  }
+}
+
+void calcSignal1()
+{
+  last_interrupt_time1 = micros();
+
+  if (digitalRead(A1) == HIGH)
+  {
+    chrono_start1 = micros();
+  }
+  else
+  {
+    if (chrono_start1 != 0)
+    {
+      input[1] = ((volatile int)micros() - chrono_start1);
+      chrono_start1 = 0;
+    }
+  }
+}
+
+void calcSignal2()
+{
+  last_interrupt_time2 = micros();
+
+  if (digitalRead(A2) == HIGH)
+  {
+    chrono_start2 = micros();
+  }
+  else
+  {
+    if (chrono_start2 != 0)
+    {
+      input[2] = ((volatile int)micros() - chrono_start2);
+      chrono_start2 = 0;
+    }
+  }
+}
+
+void calcSignal3()
+{
+  last_interrupt_time3 = micros();
+
+  if (digitalRead(A3) == HIGH)
+  {
+    chrono_start3 = micros();
+  }
+  else
+  {
+    if (chrono_start3 != 0)
+    {
+      input[3] = ((volatile int)micros() - chrono_start3);
+      chrono_start3 = 0;
+    }
+  }
+}
+

 // Fonction qui s'execute une fois et au début
 void setup() {
@@ -267,7 +243,13 @@

 // Fonction qui s'execute a chaque cycle
 void loop() {
+  arm = pulseIn(A4, HIGH);
   bno_get_values();
-  control_update();
-  print_motors();
-}
+
+  if (arm > 1500) {
+    control_update();
+  }
+  else {
+    motors_set_to_zero();
+  }
+}


Update ValuePull.ino

Update ValuePull.ino

--- examples/GettingStarted/ValuePull/ValuePull.ino
+++ examples/GettingStarted/ValuePull/ValuePull.ino
@@ -37,10 +37,10 @@
   Blynk.begin(auth);
 }

-//
-BLYNK_READ(5)
+// This function tells Arduino that widget attached to Virtual Pin (5) is requesting data
+BLYNK_READ(5)
 {
-  Blynk.virtualWrite(5, millis()/1000);
+  Blynk.virtualWrite(5, millis()/1000); // this command writes Arduino's up time to Virtual Pin (5) every second
 }

 void loop()


Remove useless comments from ino

Remove useless comments from ino

--- arduino-workshop.ino
+++ arduino-workshop.ino
@@ -4,12 +4,7 @@
 void setup() {
   LCD::setup();
   LCD::helloworld();
-  // put your setup code here, to run once:
-
-
 }

 void loop() {
-  // put your main code here, to run repeatedly:
-
 }


analog based piezo checking, along with 1ms timer interrupt

--- range/arduino/piezo_score_test/piezo_score_test.ino
+++ range/arduino/piezo_score_test/piezo_score_test.ino
@@ -1,31 +1,48 @@
-/* Records inputs from a piezo knock sensor and displays cumulative hit count */
+/* Records inputs from a piezo knock sensor and displays cumulative hit count
+
+   Adjust the sensitivity of the hit based on the SCORE_THRESHOLD
+   A weight secured to the back of the piezo increases hit response e.g. an M6
+   nut pressed on with blue tack.
+*/
+
+#include<TimerOne.h>

 #define BAUD 9600
-#define RESEND_TIMER 100
-#define DEBOUNCE_LIMIT 100
-#define IN INT0
+#define RESEND_TIMER 250
+#define DEBOUNCE_LIMIT 20
+#define SCORE_THRESHOLD 102

 unsigned long last_send = 0UL;
-volatile unsigned long last_strike = 0UL;
-volatile boolean report_score = false;
-volatile int counter = 0;
+boolean report_score = false;
+volatile unsigned long last_hit = 0UL;
+volatile boolean record_hit = false;
+volatile long counter = 0UL;

 void setup() {
-  // put your setup code here, to run once:
-  pinMode(IN, INPUT);
-  pinMode(LED_BUILTIN, OUTPUT);
+  // open the USB serial port for reporting
+  Serial.begin(BAUD);

+  // open the scoreboard serial port
   Serial1.begin(BAUD);
   delay(100);
-
   // reset the scoreboard to zero on startup
   Serial1.println(F("Z"));

-  attachInterrupt(IN, piezo, RISING);
+  // 1ms timer interrupt to check for hits
+  Timer1.initialize(1000);
+  Timer1.attachInterrupt(piezoCheck);
 }

 void loop() {
-  // put your main code here, to run repeatedly:
+  // record a hit if registered
+  if (record_hit == true) {
+    counter++;
+    Serial.println(F("HIT"));
+    record_hit = false;
+    report_score = true;
+  }
+
+  // update the scoreboard if changed OR on regular resend time
   if (report_score == true || millis() - last_send >= RESEND_TIMER) {
     Serial1.print(F("D"));
     Serial1.println(counter);
@@ -34,10 +51,9 @@
   }
 }

-void piezo() {
-  if (millis() - last_strike >= DEBOUNCE_LIMIT) {
-    report_score = true;
-    counter++;
-    last_strike = millis();
+void piezoCheck() {
+  if (analogRead(A0) >= SCORE_THRESHOLD && millis() - last_hit >= DEBOUNCE_LIMIT) {
+    record_hit = true;
+    last_hit = millis();
   }
 }


Fix syntax

Fix syntax

--- MusicalCar.ino
+++ MusicalCar.ino
@@ -1,103 +1,103 @@
-#include <MIDI.h>
-
-String notes[] = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
-int stepArr[] = {0,2,4,5,7,9,11,12};
-int keyStep[] = {10, 5, 0, 7, 2, 9, 4};
-int _note, _key, _range;
-int index;
-int counterS = 0;
-int counterP = 0;
-int counterG = 0;
-int counterT = 0;
-int state;
-int aLastState;
-int cLastState;
-int eLastState;
-int gLastState;
-
-//Steering Wheel Encoder
-const int outputA = 2;
-const int outputB = 3;
-
-//Pedal Encoder
-const int outputC = 3;
-const int outputD = 4;
-
-//Gear Shit Encoder
-const int outputE = 5;
-const int outputF = 6;
-
-//Turing Light Encoder
-const int outputG = 7;
-const int outputH = 8;
-
-void noteOn(byte channel, byte pitch, byte velocity) {
-  MIDIEvent noteOn = {0x09, 0x90 | channel, pitch, velocity};
-  MIDIUSB.write(noteOn);
-}
-
-void noteOff(byte channel, byte pitch, byte velocity) {
-  MIDIEvent noteOff = {0x08, 0x80 | channel, pitch, velocity};
-  MIDIUSB.write(noteOff);
-}
-
-void playNote(int note, int t){
- noteOn(0, note, 64);
- MIDIUSB.flush();
- delay(t);
-
- noteOff(0, note, 64);
- MIDIUSB.flush();
-}
-
-int eRead(int out1, int out 2, int lastState) {
-  int counter = 0;
-  state = digitalRead(out1);
-  if (state != lastState){
-     // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
-     if (digitalRead(out2) != state) {
-       counter ++;
-     }
-  }
-  else {
-       counter --;
-  }
-  Serial.print("Position: ");
-  Serial.println(counter);
-  return counter;
-}
-
-void setup(){
-  // put your setup code here, to run once:
-  Serial.begin (9600);
-
-  //Setup encoders' pins
-  pinMode (outputA,INPUT);
-  pinMode (outputB,INPUT);
-  pinMode (outputC,INPUT);
-  pinMode (outputD,INPUT);
-  pinMode (outputE,INPUT);
-  pinMode (outputF,INPUT);
-  pinMode (outputG,INPUT);
-  pinMode (outputH,INPUT);
-
-  // Reads the initial state of the outputA~G
-  aLastState = digitalRead(outputA);
-  cLastState = digitalRead(outputC);
-  eLastState = digitalRead(outputE);
-  gLastState = digitalRead(outputG);
-}
-
-void loop(){
-  // put your main code here, to run repeatedly:
-  counterS = eRead(outputA, outputB, aLastState);
-  //counterP = encoderRead(outputC, outputD, cLastState);
-  counterG = eRead(outputE, outputF, eLastState);
-  //counterT = encoderRead(outputG, outputG, gLastState);
-  _key = keyStep[(int)((double) counterG/20*7)];
-  _note = _key+stepArr[(int)((double)counterS/40*7)];
-  if(true){
-    playNote(_note, 500);
-  }
-  delay(500);
+#include <MIDI.h>
+
+String notes[] = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
+int stepArr[] = {0,2,4,5,7,9,11,12};
+int keyStep[] = {10, 5, 0, 7, 2, 9, 4};
+int _note, _key, _range;
+int index;
+int counterS = 0;
+int counterP = 0;
+int counterG = 0;
+int counterT = 0;
+int state;
+int aLastState;
+int cLastState;
+int eLastState;
+int gLastState;
+
+//Steering Wheel Encoder
+const int outputA = 2;
+const int outputB = 3;
+
+//Pedal Encoder
+const int outputC = 3;
+const int outputD = 4;
+
+//Gear Shit Encoder
+const int outputE = 5;
+const int outputF = 6;
+
+//Turing Light Encoder
+const int outputG = 7;
+const int outputH = 8;
+
+void noteOn(byte channel, byte pitch, byte velocity) {
+  MIDIEvent noteOn = {0x09, 0x90 | channel, pitch, velocity};
+  MIDIUSB.write(noteOn);
 }
+
+void noteOff(byte channel, byte pitch, byte velocity) {
+  MIDIEvent noteOff = {0x08, 0x80 | channel, pitch, velocity};
+  MIDIUSB.write(noteOff);
+}
+
+void playNote(int note, int t){
+ noteOn(0, note, 64);
+ MIDIUSB.flush();
+ delay(t);
+
+ noteOff(0, note, 64);
+ MIDIUSB.flush();
+}
+
+int eRead(int out1, int out2, int lastState) {
+  int counter = 0;
+  state = digitalRead(out1);
+  if (state != lastState){
+     // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
+     if (digitalRead(out2) != state) {
+       counter ++;
+     }
+  }
+  else {
+       counter --;
+  }
+  Serial.print("Position: ");
+  Serial.println(counter);
+  return counter;
+}
+
+void setup(){
+  // put your setup code here, to run once:
+  Serial.begin (9600);
+
+  //Setup encoders' pins
+  pinMode (outputA,INPUT);
+  pinMode (outputB,INPUT);
+  pinMode (outputC,INPUT);
+  pinMode (outputD,INPUT);
+  pinMode (outputE,INPUT);
+  pinMode (outputF,INPUT);
+  pinMode (outputG,INPUT);
+  pinMode (outputH,INPUT);
+
+  // Reads the initial state of the outputA~G
+  aLastState = digitalRead(outputA);
+  cLastState = digitalRead(outputC);
+  eLastState = digitalRead(outputE);
+  gLastState = digitalRead(outputG);
+}
+
+void loop(){
+  // put your main code here, to run repeatedly:
+  counterS = eRead(outputA, outputB, aLastState);
+  //counterP = encoderRead(outputC, outputD, cLastState);
+  counterG = eRead(outputE, outputF, eLastState);
+  //counterT = encoderRead(outputG, outputG, gLastState);
+  _key = keyStep[(int)((double) counterG/20*7)];
+  _note = _key+stepArr[(int)((double)counterS/40*7)];
+  if(true){
+    playNote(_note, 500);
+  }
+  delay(500);
+}


- start ledBlink in the on-state - PIR debug

--- GeheimTuer.ino
+++ GeheimTuer.ino
@@ -172,7 +172,7 @@
 union ledState {
   unsigned int ledidx;
   signed int fader;
-  bool blink_on;
+  bool blink_off;
 } ledState;

 // pre-defined colors. GRB order, g++ doesn't implement out-of-order initializers
@@ -270,6 +270,8 @@
   pinMode(switchBack, INPUT_PULLUP);

   pinMode(switchTrigger, INPUT_PULLUP);
+
+  pinMode(pirPin, INPUT);

   setLeds1(traktor, ledSolid);
   ledptr = &leds[0];
@@ -340,7 +342,6 @@
   debug(currentMillis, F("Elapsed millis: "));
   Serial.println(elapsedMillis);
 */
-

   // fast debounce driver error signals to filter short glitches
   debounce(motorDiagAPin, &motorDiagA, &motorDiagADeglitch, &motorDiagADebounce);
@@ -382,6 +383,10 @@
         swFront = LOW; break;
     case 'F':
         swFront = HIGH; break;
+    case 'i':
+        pirTrigger = HIGH; break;
+    case 'I':
+        pirTrigger = LOW; break;
     case 'm':
         debug(currentMillis, F("Door status: "));
         Serial.println(doorState);
@@ -557,12 +562,12 @@
       // motion stopped, return to work
       if (pirTrigger == LOW) {
         if (swBack == LOW) {
-          debug(currentMillis, F("IR sensor LOW - door open\r\n"));
+          debug(currentMillis, F("Motion sensor released - door open\r\n"));
           openMillis = 0;
           setLeds1(green, ledBlink);
           doorState = doorOpen;
         } else {
-          debug(currentMillis, F("IR sensor LOW - door blocked\r\n"));
+          debug(currentMillis, F("Motion sensor released - door blocked\r\n"));
           setLeds1(red, ledSolid);
           doorState = doorBlocked;
         }
@@ -651,17 +656,17 @@
       if (ledMillis >= ledBlinkInterval) {
         ledMillis = 0;

-        if (!ledState.blink_on) {
+        if (!ledState.blink_off) {
+          ledptr = &leds[0];
+        } else {
 //          memset(&tmp_leds, 0x00, sizeof(tmp_leds));
           for (uint8_t i = 0; i < MAXPIX; i++) {
             tmp_leds[i] = black;
           }
           ledptr = &tmp_leds[0];
-        } else {
-          ledptr = &leds[0];
         }

-        ledState.blink_on = !ledState.blink_on;
+        ledState.blink_off = !ledState.blink_off;

         LED.sync();
       }
@@ -780,7 +785,7 @@

 void motorFree() {
   _motorFree();
-  Serial.print(F("Brake disengaged\r\n"));
+  Serial.print(F("Brake released\r\n"));
 }

 void _motorFree() {


Firmware ~ Some software LED color calibration

--- arduino/tLamp/TLamp.ino
+++ arduino/tLamp/TLamp.ino
@@ -1,6 +1,6 @@
 #define PIN_RED 3
-#define PIN_GREEN 5
-#define PIN_BLUE 6
+#define PIN_GREEN 4
+#define PIN_BLUE 5

 #define PIN_STATUS LED_BUILTIN

@@ -10,7 +10,7 @@
 #define EMPTY_COMMAND_FAIL ""

 enum LightMode {
-  NONE, STATIC,CRUDE
+  NONE, STATIC, CRUDE, CANDLE
 };

 const int crude_T = 5000;
@@ -67,7 +67,8 @@
   int r = countColor(m, 0*crude_Ts);
   int g = countColor(m, 2*crude_Ts);
   int b = countColor(m, 4*crude_Ts);
-  setColor(1.5*r, g*0.6, b*0.6); // Some calibrations for LED color brightness
+  //setColor(1.5*r, g*0.6, b*0.6); // Some calibrations for LED color brightness
+  setColor(r, g, b);
 }

 String processCommand(String command) {
@@ -105,8 +106,8 @@

 void setColor(int r, int g, int b) {
   analogWrite(PIN_RED, r);
-  analogWrite(PIN_GREEN, g);
-  analogWrite(PIN_BLUE, b);
+  analogWrite(PIN_GREEN, g / 2);// * 5 / 3);
+  analogWrite(PIN_BLUE, b / 2);
 }

 void blink(int pin) {


Odometry Workinggit push

Odometry Workinggit push

--- sonarMain/sonarMain.ino
+++ sonarMain/sonarMain.ino
@@ -36,11 +36,23 @@

 // Odometry Setup
 void SetupOdometry(void);
-volatile unsigned long rightCount = 0;
-ISR(INT1_vect){rightCount++;}
-
-volatile unsigned long leftCount = 0;
-ISR(INT0_vect){leftCount++;}
+volatile long rightCount = 0;
+ISR(INT1_vect){
+	if (rightSpeed < 93){
+		rightCount++;
+	} else {
+		rightCount--;
+	}
+}
+
+volatile long leftCount = 0;
+ISR(INT0_vect){
+	if (leftSpeed > 93){
+		leftCount++;
+	} else {
+		leftCount--;
+	}
+}

 // I2C Response Buffer
 char i2c_buff[32];
@@ -95,7 +107,7 @@
 		PORTB ^= (1<<PB5);

 		char buff[32];
-		sprintf(buff, "Left: %u Right: %u\n", leftCount, rightCount);
+		sprintf(buff, "Left: %ld Right: %ld\n", leftCount, rightCount);
 		Serial.print(buff);

 		//Required Delay for Sonar Loop, Do Not Remove or Reduce
@@ -184,13 +196,16 @@

 	} else if(buff[0] == 'O'){
 		// Write back odometry counts
-		sprintf(i2c_buff, "%u %u\n", leftCount, rightCount);
+		sprintf(i2c_buff, "%ld %ld\n", leftCount, rightCount);

 		#ifdef DEBUG_ODOMETRY
 			char buff[32];
-			sprintf(buff, "Left: %u Right: %u\n", leftCount, rightCount);
+			sprintf(buff, "Left: %ld Right: %ld\n", leftCount, rightCount);
 			Serial.print(buff);
 		#endif
+
+		// Reset Counts
+		leftCount = 0; rightCount = 0;

 	} else if(buff[0] == 'S'){
 		// Write back message


Sending data as strings

Sending data as strings

--- sonarMain/sonarMain.ino
+++ sonarMain/sonarMain.ino
@@ -85,17 +85,18 @@

 		// Respond to Command
 		if (cmd == 1){
-			// Cast Sonar Readings as a char
-			char * sonar = (char)&SonarReading;
+			// Convert Sonar Readings to char array
+			char sonar[1028]; memset(&sonar[0], 0, sizeof(sonar));
+			for(int i = 0; i < nSonar; i++){
+				snprintf(sonar+strlen(sonar), sizeof(sonar), "%u ", SonarReading[i]);
+			}
+
 			// Return Sonar Readings
-			Wire.write(sonar, sizeof(sonar));
-			Serial.print("\t Sonar:");
-			Serial.print(sonar);
-
-			// Report Sonar Reading
-			char buff[64];
-			snprintf(buff, sizeof(buff), "Sonar: %u", SonarReading[0]);
-			Serial.print(buff);
+			Wire.write(sonar, strlen(sonar));
+			#ifdef debugOn
+				Serial.print("\t Sonar:");
+				Serial.print(sonar);
+			#endif
 		}
 		else {
 			// Report Error


Changed the program so it's up-to-date with the Serial Communication library Changed some data types to unsigned int, because that's safer

--- rp6control/rp6control.ino
+++ rp6control/rp6control.ino
@@ -29,41 +29,23 @@
 // specify the port to listen on as an argument
 WiFiServer server(80);

-const int maxClientCount = 20;
+const uint32_t maxClientCount = 20;

 WiFiClient client[maxClientCount];
 const size_t clientsize = sizeof(client) / sizeof (client[0]);
 bool connectionlist[clientsize];

-  SerialCommunication clientCommunication[] {
-  SerialCommunication(&client[0], '#', '%'),
-  SerialCommunication(&client[1], '#', '%'),
-  SerialCommunication(&client[2], '#', '%'),
-  SerialCommunication(&client[3], '#', '%'),
-  SerialCommunication(&client[4], '#', '%'),
-  SerialCommunication(&client[5], '#', '%'),
-  SerialCommunication(&client[6], '#', '%'),
-  SerialCommunication(&client[7], '#', '%'),
-  SerialCommunication(&client[8], '#', '%'),
-  SerialCommunication(&client[9], '#', '%'),
-  SerialCommunication(&client[10], '#', '%'),
-  SerialCommunication(&client[11], '#', '%'),
-  SerialCommunication(&client[12], '#', '%'),
-  SerialCommunication(&client[13], '#', '%'),
-  SerialCommunication(&client[14], '#', '%'),
-  SerialCommunication(&client[15], '#', '%'),
-  SerialCommunication(&client[16], '#', '%'),
-  SerialCommunication(&client[17], '#', '%'),
-  SerialCommunication(&client[18], '#', '%'),
-  SerialCommunication(&client[19], '#', '%')
-  };
+SerialCommunication clientCommunication[maxClientCount];

 void setup() {
-
-  //start of the Rp6
+  // setup all the SerialCommunication objects
+  for (uint32_t i = 0; i < maxClientCount; i++) {
+    clientCommunication[i].begin(client[i], '#', '%');
+  }
+  // start of the Rp6
   Rp6.begin();
-  //init array on false
-  for (int i = 0; i < clientsize; i++) {
+  // init array on false
+  for (uint32_t i = 0; i < clientsize; i++) {
     connectionlist[i] = false;
   }
   Serial.begin(9600);
@@ -106,7 +88,7 @@
     clientCounter++;
     clientCounter = clientCounter % clientsize;
   }
-  for (size_t j = 0; j < clientsize; j++) {
+  for (uint32_t j = 0; j < clientsize; j++) {
     if (client[j].available() > 0) {
       if (clientCommunication[j].update()) {
         commandline = clientCommunication[j].getCommand();


Finished Up TYSTWD code -shock

Finished Up TYSTWD code -shock

--- TYSTWD/intruder_alarm/intruder_alarm.ino
+++ TYSTWD/intruder_alarm/intruder_alarm.ino
@@ -8,10 +8,10 @@
 //Pins
 const int trip_wire = 12; //input
 const int ir_rec = 11; //input
-const int buzzerPin = 10; //out
-const int ledPin = 9; //out
-const int servoPin = 8; //out
-const int shockPin = 7;//out
+const int buzzerPin = 9; //out
+const int ledPin = 8; //out
+const int servoPin = 5; //out
+const int shockPin = 6;//out

@@ -26,6 +26,8 @@
   pinMode(ledPin, OUTPUT);
   pinMode(servoPin, OUTPUT);
   pinMode(shockPin, OUTPUT);
+  servo1.write(0);
+  delay(200);

 }

@@ -75,13 +77,24 @@
 }

 void picture(){
+  servo1.write(12);
+  delay(200);
 }

 void shock(){
-
+  for(int index = 0; index <= 7; index++)
+  {
+    digitalWrite(shockPin, HIGH);
+    delay(100);
+    digitalWrite(shockPin, LOW);
+    delay(100);
+  }
 }

 void cleanup(){
   noTone(buzzerPin);
   digitalWrite(ledPin, LOW);
+  digitalWrite(shockPin, LOW);
+  servo1.write(0);
+  delay(200);
 }


Indentation and spaces removal

Indentation and spaces removal

--- code/lissajous/lissajous.ino
+++ code/lissajous/lissajous.ino
@@ -7,7 +7,7 @@
 // Create the servo objects
 Servo servox;
 Servo servoy;
-
+
 double pos = 0; // Position incrementer
 float spd = 0.005; // This value seems to work for reasonable speed.
 float facter = 1.0; // Ratio between servox and servoy periods.
@@ -15,46 +15,42 @@
 int adjx = 90; // Position of servox
 int adjy = 90; // Position of servoy
 float decay = 60000; // Gives the amount of steps to run on. Higher gives a slower decay.
-
+
 void setup()
 {
-  servox.attach(9);  // attaches the servo on pin 9 to the servo object
-  servoy.attach(10);  // attaches the servo on pin 10 to the servo object
+  servox.attach(9);  // attaches the servo on pin 9 to the servo object
+  servoy.attach(10);  // attaches the servo on pin 10 to the servo object
   pinMode(2, INPUT_PULLUP); // Starting button input
   randomSeed(analogRead(0)); // Just seed with a random value
 }
-
-
+
 void loop()
 {
+    // Wait for a button press.
+    while (digitalRead(2) != 0)
+    {
+        // Keep generating random values. Only on button press do we lock in the values.
+        // The random seed is not random enough, so this provides a more random result.
+        facter = random(1001, 1021)/1000.0; // Increase the second number for variation.
+        starter = random(3141)/1000.0; // offset the starting point by 0-3.141 radians
+    }
+    // Main loop, to 90% decay in amplitude of the movements.
+    for(pos = 0; pos < decay*0.9; pos += 1)
+    {
+        // Adjx just gives me a nice sine wave
+        adjx = int(90 + int(70 * (1 - pos/decay) * sin(pos * spd)));

-  // Wait for a button press.
-  while (digitalRead(2) != 0)
-  {
-    // Keep generating random values. Only on button press do we lock in the values.
-    // The random seed is not random enough, so this provides a more random result.
-    facter = random(1001, 1021)/1000.0; // Increase the second number for variation.
-    starter = random(3141)/1000.0; // offset the starting point by 0-3.141 radians
-    delay(10);
-  }
+        // Also a sinewave, with offsets and different period.
+        adjy = int(90 + int(70 * (1 - pos/decay) * sin(starter + (pos * spd * facter))));

-  // Main loop, to 90% decay in amplitude of the movements.
-  for(pos = 0; pos < decay*0.9; pos += 1)
-  {
-    // Adjx just gives me a nice sine wave
-    adjx = int(90 + int(70 * (1 - pos/decay) * sin(pos * spd)));
+        // Get the values to the servos.
+        servox.write(adjx);
+        servoy.write(adjy);
+        delay(1); // Just for consistent speed.
+    }

-    // Also a sinewave, with offsets and different period.
-    adjy = int(90 + int(70 * (1 - pos/decay) * sin(starter + (pos * spd * facter))));
-
-    // Get the values to the servos.
-    servox.write(adjx);
-    servoy.write(adjy);
-    delay(1); // Just for consistent speed.
-  }
-
-  // Return to center after drawing.
-  servox.write(90);
-  servoy.write(90);
+    // Return to center after drawing.
+    servox.write(90);
+    servoy.write(90);
 }


Don't publish events as retained messages. Fixes #3 again

--- src/homie-sonoff-touch.ino
+++ src/homie-sonoff-touch.ino
@@ -2,7 +2,7 @@
 #include <Homie.h>

 #define FW_NAME "homie-sonoff-touch"
-#define FW_VERSION "2.0.1"
+#define FW_VERSION "2.0.2"

 /* Magic sequence for Autodetectable Binary Upload */
 const char *__FLAGGED_FW_NAME = "\xbf\x84\xe4\x13\x54" FW_NAME "\x93\x44\x6b\xa7\x75";
@@ -34,7 +34,8 @@
 // Register our two HomieNode instances
 // nodeName(property, value, retained);
 HomieNode relayNode("relay", "relay");
-HomieNode buttonNode("button", "button", false);
+//HomieNode buttonNode("button", "button", false);
+HomieNode buttonNode("button", "button");

 bool RelayHandler(const HomieRange& range, const String& value) {
   /*
@@ -71,16 +72,16 @@
     Serial.println("One-shot");
     if ( function == 1 ) {
       Serial.println("SINGLE click");
-      buttonNode.setProperty("event").send("SINGLE");
+      buttonNode.setProperty("event").setRetained(false).send("SINGLE");
     }

     if ( function == 2 ) {
-      buttonNode.setProperty("event").send("DOUBLE");
+      buttonNode.setProperty("event").setRetained(false).send("DOUBLE");
       Serial.println("DOUBLE click");
     }

     if ( function == 3 ) {
-      buttonNode.setProperty("event").send("TRIPLE");
+      buttonNode.setProperty("event").setRetained(false).send("TRIPLE");
       Serial.println("TRIPLE click");
     }
     // This has been a single event.
@@ -93,17 +94,17 @@
     if ( millis() - previousMillis >= waitInterval ) {
       previousMillis = millis();
       if ( function == -1 ) {
-        buttonNode.setProperty("event").send("SINGLEHELD");
+        buttonNode.setProperty("event").setRetained(false).send("SINGLEHELD");
         Serial.println("SINGLE LONG click");
       }

       if ( function == -2 ) {
-        buttonNode.setProperty("event").send("DOUBLEHELD");
+        buttonNode.setProperty("event").setRetained(false).send("DOUBLEHELD");
         Serial.println("DOUBLE LONG click");
       }

       if ( function == -3 ) {
-        buttonNode.setProperty("event").send("TRIPLEHELD");
+        buttonNode.setProperty("event").setRetained(false).send("TRIPLEHELD");
         Serial.println("TRIPLE LONG click");
       }
     }


Fix #116: add a pinout table for the Feather 32u4 LoRa

--- examples/ttn-otaa-feather-us915/ttn-otaa-feather-us915.ino
+++ examples/ttn-otaa-feather-us915/ttn-otaa-feather-us915.ino
@@ -84,6 +84,20 @@
     .rxtx_rx_active = 0,
     .rssi_cal = 8,              // LBT cal for the Adafruit Feather M0 LoRa, in dB
     .spi_freq = 8000000,
+};
+#elif defined(ARDUINO_AVR_FEATHER32U4)
+// Pin mapping for Adafruit Feather 32u4 LoRa, etc.
+// Just like Feather M0 LoRa, but uses SPI at 1MHz; and that's only
+// because MCCI doesn't have a test board; probably higher frequencies
+// will work.
+const lmic_pinmap lmic_pins = {
+    .nss = 8,
+    .rxtx = LMIC_UNUSED_PIN,
+    .rst = 4,
+    .dio = {3, 6, LMIC_UNUSED_PIN},
+    .rxtx_rx_active = 0,
+    .rssi_cal = 8,              // LBT cal for the Adafruit Feather M0 LoRa, in dB
+    .spi_freq = 1000000,
 };
 #elif defined(ARDUINO_CATENA_4551)
 // Pin mapping for Murata module / Catena 4551


Modified Start / Stop using a small delay for more accuracy

--- ARDUINO/spi_arduino_2_rpi/spi_arduino_2_rpi.ino
+++ ARDUINO/spi_arduino_2_rpi/spi_arduino_2_rpi.ino
@@ -135,14 +135,28 @@
   rc_data[ROLL].u16 = unRollInShared;

   if (unThrottleInShared < 1000 &
-      unYawInShared < 1200 &
-      unPitchInShared < 1200 &
-      unRollInShared <1200 ) {
-    start = !start;
-
+      unYawInShared      < 1200 &
+      unPitchInShared    < 1200 &
+      unRollInShared     < 1200 ) {
+
+    uint32_t t_old = millis();
+    while (millis()-t_old < 500 ){
+      //wait to be sure that stockes are still in position
+    }
+
+    // if so change current status
+    if (unThrottleInShared < 1000 &
+	unYawInShared      < 1200 &
+	unPitchInShared    < 1200 &
+	unRollInShared     < 1200 ) {
+
+      start = !start;
+      //change LED status
+      digitalWrite(13, start);
+    }
   }

-  //Update servo (ESC) if necessary
+  //Update servo (ESC) if necessary and started
   if (update_servo & start){
     uint8_t ipos=0;
     for (int i=0;i<SERVO_NUM;i++)
@@ -184,6 +198,7 @@
   }

   if (cmd == 'P') {
+    //process it !
     update_servo = true;
     pos=0;
     return;


Switch to IR

Switch to IR

--- Caravan_Thermostat_TX/Caravan_Thermostat_TX.ino
+++ Caravan_Thermostat_TX/Caravan_Thermostat_TX.ino
@@ -107,8 +107,8 @@
   // Read the Temperature
   ReadTemperature();
   ReadTime();
-  //CheckIR(); // This has the delay of 2000ms
-  CheckBT(); // This has a delay of 2000ms
+  CheckIR(); // This has the delay of 2000ms
+  //CheckBT(); // This has a delay of 2000ms

 }

@@ -187,6 +187,7 @@
   TFTscreen.drawLine(0, 24, TFTscreen.width(), 24, OffBlack);
   TFTscreen.drawLine(TFTscreen.width() - 60, 24, TFTscreen.width() - 60, TFTscreen.height() - 24, OffBlack);
   DrawFire(HeatingOn);
+  delay(5000); // wait a bit, NECESSARY!!
 }

 void ReadTemperature()


Update SigFoxMkr1200.ino

Update SigFoxMkr1200.ino

--- lpwan/SigFoxMkr1200.ino
+++ lpwan/SigFoxMkr1200.ino
@@ -53,7 +53,7 @@

-  //Sleep for 15 minutes
+  //Sleep for 20 minutes
   LowPower.sleep(20 * 60 * 1000);
 }


modify baud rate

modify baud rate

--- jenny5-firmware/jenny5-firmware.ino
+++ jenny5-firmware/jenny5-firmware.ino
@@ -67,7 +67,7 @@

 	tera_ranger_one_lidar = NULL;

-	Serial.begin(56700); //Open Serial connection
+	Serial.begin(57600); //Open Serial connection

 	while (!Serial);
 	while (Serial.available() > 0)


Oddly enough, the calibratedOffset was causing gyro drift. I removed it, but not its corresponding functions.

--- software/Arduino/ServoController/ServoController.ino
+++ software/Arduino/ServoController/ServoController.ino
@@ -15,10 +15,10 @@
 // ================ SYSTEM PARAMETERS ===================
 // Sample rates
 const int motorUpdateRate = 50; // gyro sample rate
-const int calibrationSamples = 250;
+const int calibrationSamples = 1000;

 // Initial calibration value
-float calibratedOffset = 0;
+float calibratedOffset;

 // Indicator LED
 const int LED = 13;
@@ -37,11 +37,12 @@
 // ============ Runtime variables ========================
 // Orientation data
 float positionChange;
+float correctionSum;

 // Interrupt flag
 int timer = millis();
 bool update_flag = false; // interrupt flag for executing motor update
-
+int ref;
 /**
     Sets up system
 */
@@ -63,6 +64,8 @@
   // Setup motor update interval timer
   MsTimer2::set(motorUpdateRate, updateMotor);
   MsTimer2::start();
+
+  ref = millis();
 }

 void loop() {
@@ -83,8 +86,9 @@
   // Update orientation data with measurements from gyro
   // Just using angular rates from gyro and time deltas to track position using a Reimann sum.
   int currentTime = millis();
+
   int deltaT = currentTime - timer;
-  positionChange += deltaT * readGyro() / 1000; // Gyro data is given in 1000ths of a degree, so we divide by 1000
+  positionChange += deltaT * (readGyro()) / 1000; // Gyro data is given in 1000ths of a degree, so we divide by 1000
   timer = currentTime;

   // Update motor position
@@ -146,18 +150,17 @@
     Finds the calibration constant of the
     gyro.
     @param number of calibration samples
+    @returns degrees of gyro drift per second
 */
-int zeroGyro(int calibrationSamples) {
-  float zSum = 0;
+float zeroGyro(int calibrationSamples) {
+  float gyroSum = 0;
   digitalWrite(LED, HIGH);
   for (int i = 0; i < calibrationSamples; i++) {
-    imu.readGyro();
-    float z = imu.calcGyro(imu.gz);
-    zSum += z;
-    delay(5);
+    gyroSum += readGyro();
   }
   blinkLED(300, 5);
-  return zSum / calibrationSamples;
+  Serial.println(gyroSum / calibrationSamples);
+  return gyroSum / calibrationSamples;
 }

 /**


increase settle time to 30s

increase settle time to 30s

--- short-circuit-limiter/short-circuit-limiter.ino
+++ short-circuit-limiter/short-circuit-limiter.ino
@@ -16,7 +16,7 @@
 #define TEMP_WARNING_RATE 120000 //2 x 60 x 1000ms

 #define CT_CALIBRATION_VALUE 60.6  // (100A / 0.05A) / 33 ohms
-#define INITIAL_SETTLE_TIME 20000 //20 seconds
+#define INITIAL_SETTLE_TIME 30000 //30 seconds

 #define BUTTON_DEBOUNCE 300


Delete GPSLCD.ino

Delete GPSLCD.ino

--- GPSLCD.ino
+++ GPSLCD.ino
@@ -1,642 +0,0 @@
-/* GPS LCD
-
-    By GK Grotsky
-    8/30/16
-
-  This program communicate with the u-blox NEO-6M GPS module
-  through a software serial interface. It then displays certain GPS
-  parameters on a I2C 16x2 (or 20x4) character LCD display module. The
-  GPS messages are received by the on-board Arduino UART circuit using
-  the SoftwareSerial library. It then uses the TinyGPS++ library to
-  decode the GPS NMEA messages. The parameters are then displayed on a
-  16x4 (or 20x4) LCD using the LiquidCrystal_I2C library.
-
-  Note: Both the 16x2 and 20x4 LCDs are supported as these are the most popular
-        LCDs available.
-*/
-#include "GPSLCD.h"
-#include <TinyGPS++.h>
-#include <SoftwareSerial.h>
-#include <LiquidCrystal_I2C.h>
-
-TinyGPSPlus gps; // This is the GPS object that will pretty much do all the grunt work with the NMEA data
-SoftwareSerial GPSModule(10, 11); // RX, TX
-LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin); // Initializes class variables and defines the I2C address of the LCD
-bool dataValid; // Data is valid from the GPS module
-GPSStruct GPSData; // Holds the GPS data coming from the GPS module
-
-// The setup (runs once at start up)
-void setup()
-{
-  pinMode(BACKLIGHT_SW, INPUT);
-
-#ifdef _16x2
-  // Selects either speed or heading to be displayed
-  pinMode(SPEED_ALTITUDE_SW, INPUT);
-#else
-  // Selects either altitude or the date/time to be displayed
-  pinMode(ALTITUDE_DATE_TIME_SW, INPUT);
-#endif
-
-#ifdef DEBUG
-  Serial.begin(9600); // This opens up communications to the serial monitor in the Arduino IDE
-  Serial.flush();
-#endif
-  GPSModule.begin(9600); // This opens up communications to the software serial tx and rx lines
-  GPSModule.flush();
-
-  lcd.begin (COLUMN, ROW); // Defines LCD type
-  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE); // Sets the pin to control the backlight
-  lcd.clear(); // Clear the LCD
-  lcd.home (); // Go to the home position on the LCD
-} // setup
-
-// The loop (runs forever and a day :-))
-void loop()
-{
-  static uint32_t pastSatellites = 0;
-  static byte initializingCounter = 0;
-  static unsigned long prevInitializationTime = INITIALIZATION_INTERVAL;
-  static unsigned long prevCreditTime = TOGGLETIME_INTERVAL;
-  static unsigned long prevInvalidSatellitesTime = TOGGLETIME_INTERVAL;
-  static bool leftInitialization = false;
-  static bool creditToggle = true;
-  static bool InvalidSatellitesToggle = true;
-#ifndef _16x2
-  static unsigned long prevDateTime = TOGGLETIME_INTERVAL;
-  static unsigned long prevHeadingTime = TOGGLETIME_INTERVAL;
-  static bool dateTimeToggle = true;
-  static bool headingToggle = true;
-#endif
-#ifdef DEBUG
-  static unsigned long prevDebugTime = 0;
-#endif
-#ifdef DATA_VALID_OVERRIDE
-  const bool dataValidOverride = true; // Set true to override data valid for debugging
-#else
-  const bool dataValidOverride = false; // Set false not to override data valid
-#endif
-#ifdef BACKLIGHT_OVERRIDE
-  // Override LCD backlight switch
-  // Force LCD backlight on/off
-  lcd.setBacklight(BACKLIGHT_ONOFF);
-#else
-  // Turn LCD backlight on/off
-  lcd.setBacklight(digitalRead(BACKLIGHT_SW));
-#endif
-  unsigned long now = millis();
-
-  while (GPSModule.available()) // While there are characters to come from the GPS
-  {
-    bool b = gps.encode(GPSModule.read()); // This feeds the serial NMEA data into the GPS library one char at a time
-  }
-
-  // Get the GPS data valid flags
-  dataValid =
-    gps.location.isValid()   &&
-    gps.speed.isValid()      &&
-    gps.altitude.isValid()   &&
-    gps.course.isValid()     &&
-    gps.date.isValid()       &&
-    gps.time.isValid()       &&
-    gps.satellites.isValid();
-
-  // Check if the GPS data is valid or data valid override is set (for debugging)
-  if (dataValid || dataValidOverride) {
-#ifndef DATA_VALID_OVERRIDE
-    // Store the real GPS data
-    GPSData.satellites = gps.satellites.value();
-    GPSData.lat        = gps.location.lat();
-    GPSData.lon        = gps.location.lng();
-    GPSData.speed      = gps.speed.mph();
-    GPSData.altitude   = gps.altitude.feet();
-#ifndef _16x2
-    GPSData.heading    = gps.course.deg();
-    GPSData.year       = gps.date.year();
-    GPSData.month      = gps.date.month();
-    GPSData.day        = gps.date.day();
-    GPSData.hour       = gps.time.hour();
-    GPSData.minute     = gps.time.minute();
-    GPSData.second     = gps.time.second();
-#endif // #ifndef _16x2
-#else // #ifndef DATA_VALID_OVERRIDE
-    // Store the fake GPS data (for debugging)
-    GPSData.satellites = 0; // Invalid satellites
-    GPSData.lat        = 39.16d; // East coast
-    GPSData.lon        = -77.07d; //   "
-    GPSData.speed      = 55.0d;
-    GPSData.altitude   = 555.0d;
-#ifndef _16x2
-    GPSData.heading    = 60.0d; // ENE or NE (16 cardinal points or 8 cardinal points)
-    GPSData.year       = 2016;
-    GPSData.month      = 11; // Day before ST starts
-    GPSData.day        = 5;  //      "
-    GPSData.hour       = 23; // 7pm my local time
-    GPSData.minute     = 10;
-    GPSData.second     = 25;
-#endif // #ifndef _16x2
-#endif // #ifndef DATA_VALID_OVERRIDE
-    // Clear the screen once when leaving initialization
-    if (!leftInitialization) {
-      leftInitialization = true;
-      lcd.clear(); // Clear the LCD
-    }
-    // Display the latest info from the gps object which it derived from the data sent by the GPS unit
-    // Send data to the LCD
-#ifdef _16x2 //------------------------------------------------------
-    lcd.home (); // Go to 1st line
-    lcd.print("Lat: ");
-    lcd.print(GPSData.lat);
-    lcd.setCursor (11, 0);
-    lcd.print("SV:");
-    if ((pastSatellites != GPSData.satellites) || (GPSData.satellites == 0)) {
-      pastSatellites = GPSData.satellites;
-      if (GPSData.satellites == 0) {
-        // Toggle invalid satellites indicator every TOGGLETIME_INTERVAL seconds
-        if (now - prevInvalidSatellitesTime > TOGGLETIME_INTERVAL / 4) {
-          prevInvalidSatellitesTime = now;
-          if (InvalidSatellitesToggle) {
-            InvalidSatellitesToggle = false;
-            lcd.print("XX");
-          }
-          else {
-            InvalidSatellitesToggle = true;
-            lcd.print("  ");
-          } // if (InvalidSatellitesToggle)
-        } // if (now - prevInvalidSatellitesTime > TOGGLETIME_INTERVAL)
-      } // if (GPSData.satellites == 0)
-      else if (GPSData.satellites <= 9) {
-        lcd.print(" "); // Blank leading char
-        lcd.print(GPSData.satellites);
-      }
-      else {
-        lcd.print(GPSData.satellites);
-      }
-    } // if ((pastSatellites != GPSData.satellites) || (GPSData.satellites == 0))
-    lcd.setCursor (0, 1); // Go to 2nd line
-    lcd.print("Lon: ");
-    lcd.print(GPSData.lon);
-    if ((digitalRead(SPEED_ALTITUDE_SW))) {
-      lcd.setCursor (12, 1);
-      if (GPSData.speed < SPEED_CUTOUT) {
-        lcd.print("0  ");
-      }
-      else {
-        lcd.print((int16_t)GPSData.speed);
-        lcd.print(" "); // Clear the extra char
-      }
-    }
-    else {
-      lcd.print("     "); // Clear the extra chars
-      if (GPSData.altitude <= 99.9) {
-        lcd.setCursor (14, 1);
-      }
-      else {
-        lcd.setCursor (13, 1);
-      }
-      lcd.print((int16_t)GPSData.altitude); // Altitude
-      // Toggle credit every TOGGLETIME_INTERVAL seconds
-      if (now - prevCreditTime > (TOGGLETIME_INTERVAL / 2)) {
-        prevCreditTime = now;
-        if (creditToggle) { // Display credit
-          creditToggle = false;
-          lcd.print("     "); // Clear the extra chars
-          lcd.print(CREDIT); // Yours truly :-)
-        }
-        else {
-          creditToggle = true;
-          lcd.print("        "); // Clear the extra chars
-        }
-      } // if (now - prevCreditTime > TOGGLETIME_INTERVAL)
-    } // if ((digitalRead(SPEED_ALTITUDE_SW)))
-#else // 20x4 ----------------------------------------------------
-    lcd.home (); // Go to 1st line
-    lcd.print("Lat: ");
-    lcd.print(GPSData.lat);
-    lcd.setCursor (15, 0);
-    lcd.print("SV:");
-    if ((pastSatellites != GPSData.satellites) || (GPSData.satellites == 0)) {
-      pastSatellites = GPSData.satellites;
-      if (GPSData.satellites == 0) {
-        // Toggle invalid satellites indicator every TOGGLETIME_INTERVAL seconds
-        if (now - prevInvalidSatellitesTime > TOGGLETIME_INTERVAL / 3) {
-          prevInvalidSatellitesTime = now;
-          if (InvalidSatellitesToggle) {
-            InvalidSatellitesToggle = false;
-            lcd.print("XX");
-          }
-          else {
-            InvalidSatellitesToggle = true;
-            lcd.print("  ");
-          } // if (InvalidSatellitesToggle)
-        } // if (now - prevInvalidSatellitesTime > TOGGLETIME_INTERVAL)
-      } // if (GPSData.satellites == 0)
-      else if (GPSData.satellites <= 9) {
-        lcd.print(" "); // Blank leading char
-        lcd.print(GPSData.satellites);
-      }
-      else {
-        lcd.print(GPSData.satellites);
-      }
-    } // if ((pastSatellites != GPSData.satellites) || (GPSData.satellites == 0))
-    lcd.setCursor (0, 1); // Go to 2nd line
-    lcd.print("Lon: ");
-    lcd.print(GPSData.lon);
-#ifndef CONVERT_TO_LOCAL
-    // Only display if time/date is selected
-    if (!(digitalRead(ALTITUDE_DATE_TIME_SW))) {
-      lcd.print("      "); // Clear the extra chars
-      uint8_t DOW = dayOfWeek(GPSData.year, GPSData.month, GPSData.day);
-      if (IsDST(GPSData.day, GPSData.month, DOW)) {
-        lcd.print("DST");
-      }
-      else {
-        lcd.print(" ST");
-      }
-    }
-    else {
-      lcd.print("         "); // Clear the extra chars
-    }
-#endif // #ifndef CONVERT_TO_LOCAL
-    lcd.setCursor (0, 2); // Go to 3rd line
-    lcd.print("Spd: ");
-    if (GPSData.speed < SPEED_CUTOUT) {
-      lcd.print("0  ");
-    }
-    else {
-      lcd.print((int16_t)GPSData.speed);
-      lcd.print(" "); // Clear the extra chars
-    }
-    lcd.setCursor (12, 2);
-    lcd.print("Hdg: ");
-    if (GPSData.speed < SPEED_CUTOUT) {
-      lcd.print("0  ");
-    }
-    else {
-      // Toggle heading every TOGGLETIME_INTERVAL seconds
-      if (now - prevHeadingTime > TOGGLETIME_INTERVAL) {
-        prevHeadingTime = now;
-        if (headingToggle) { // Display cardinal heading
-          headingToggle = false;
-          lcd.print(cardinal(GPSData.heading));
-        }
-        else { // Display degrees heading
-          headingToggle = true;
-          lcd.print((int16_t)GPSData.heading);
-          if (GPSData.heading <= 99.9) lcd.print(" "); // Clear the extra char
-        } // if (headingToggle)
-      } // if (now - prevHeadingTime > TOGGLETIME_INTERVAL)
-    } // if (GPSData.speed < SPEED_CUTOUT)
-    lcd.setCursor (0, 3); // Go to 4th line
-    if ((digitalRead(ALTITUDE_DATE_TIME_SW))) {
-      lcd.print("Alt: ");
-      lcd.print((int16_t)GPSData.altitude);
-      // Toggle credit every TOGGLETIME_INTERVAL seconds
-      if (now - prevCreditTime > (TOGGLETIME_INTERVAL / 2)) {
-        prevCreditTime = now;
-        if (creditToggle) { // Display credit
-          creditToggle = false;
-          lcd.print("         "); // Clear the extra chars
-          lcd.print(CREDIT); // Yours truly :-)
-        }
-        else {
-          creditToggle = true;
-          lcd.print("            "); // Clear the extra chars
-        }
-      } // if (now - prevCreditTime > TOGGLETIME_INTERVAL)
-      prevDateTime = TOGGLETIME_INTERVAL;
-      dateTimeToggle = true; // Default first to display date
-    } // if ((digitalRead(ALTITUDE_DATE_TIME_SW)))
-    else {
-      // Toggle date/time every TOGGLETIME_INTERVAL seconds
-      if (now - prevDateTime > TOGGLETIME_INTERVAL) {
-        prevDateTime = now;
-        if (dateTimeToggle) {
-          // Display date
-          dateTimeToggle = false;
-          lcd.print("Date: ");
-          uint8_t hour = GPSData.hour;
-          uint8_t day  = GPSData.day;
-          uint8_t month = GPSData.month;
-          uint16_t year = GPSData.year;
-#ifdef CONVERT_TO_LOCAL
-          // Convert UTC date to local date
-          bool DST = convertToLocal (&hour, &year, &month,
-                                     &day, GPSData.lon, true); // true means date conversion
-#endif // #ifdef CONVERT_TO_LOCAL
-          if (month < 10) lcd.print("0");
-          lcd.print(month);
-          lcd.print("/");
-          if (day < 10) lcd.print("0");
-          lcd.print(day);
-          lcd.print("/");
-          lcd.print(year);
-          printDay (dayOfWeek (year, month, day));
-        } // if (dateTimeToggle)
-        else {
-          // Display time
-          dateTimeToggle = true;
-          lcd.print("Time: ");
-          uint8_t hour = GPSData.hour;
-          uint8_t day  = GPSData.day;
-          uint8_t month = GPSData.month;
-          uint16_t year = GPSData.year;
-#ifdef CONVERT_TO_LOCAL
-          // Convert UTC time to local time (no need to convert the date)
-          bool DST = convertToLocal (&hour, &year, &month,
-                                     &day, GPSData.lon, false); // false means no date conversion
-#else // #ifdef CONVERT_TO_LOCAL
-#ifdef DISPLAY_12_HOUR
-          if (hour == 0) { // 12 hour clocks don't display 0
-            hour = 12;
-          }
-#endif // #ifdef DISPLAY_12_HOUR
-#endif // #ifdef CONVERT_TO_LOCAL
-#ifdef DISPLAY_12_HOUR
-          char AMPM[] = "am";
-          if (hour >= 12) { // Convert to 12 hour format
-            if (hour > 12) hour -= 12;
-            strcpy (AMPM, "pm");
-          }
-#endif
-          if (hour < 10) lcd.print("0");
-          lcd.print(hour);
-          lcd.print(":");
-          if (GPSData.minute < 10) lcd.print("0");
-          lcd.print(GPSData.minute);
-          lcd.print(":");
-          if (GPSData.second < 10) lcd.print("0");
-          lcd.print(GPSData.second);
-#ifdef DISPLAY_12_HOUR
-          lcd.print(AMPM);
-#endif // #ifdef DISPLAY_12_HOUR
-#ifdef CONVERT_TO_LOCAL
-#ifdef DISPLAY_12_HOUR
-          (DST) ? lcd.print(" DST") : lcd.print("  ST");
-#else // #ifdef DISPLAY_12_HOUR
-          (DST) ? lcd.print("   DST") : lcd.print("    ST");
-#endif // #ifdef DISPLAY_12_HOUR
-#endif // #ifndef CONVERT_TO_LOCAL
-#ifndef CONVERT_TO_LOCAL
-#ifdef DISPLAY_12_HOUR
-          lcd.print(" UTC");
-#else // #ifdef DISPLAY_12_HOUR
-          lcd.print("   UTC");
-#endif // #ifdef DISPLAY_12_HOUR
-#endif // #ifndef CONVERT_TO_LOCAL
-        } // if (dateTimeToggle)
-      } // if (now - prevDateTime > TOGGLETIME_INTERVAL)
-    } // if ((digitalRead(ALTITUDE_DATE_TIME_SW)))
-#endif //------------------------------------------------------------
-  } // if (dataValid)
-  else {
-    // GPS data is not valid, so it must be initializing
-#ifdef _16x2 //------------------------------------------------------
-    // Display initialization screen once every INITIALIZATION_INTERVAL
-    if (now - prevInitializationTime > INITIALIZATION_INTERVAL) {
-      prevInitializationTime = now;
-      lcd.setCursor (6, 0); // Go to 1st line
-      lcd.print("GPS");
-      lcd.setCursor (11, 0);
-      lcd.print("v");
-      lcd.print(VERSION);
-      lcd.setCursor (2, 1); // Go to 2nd line
-      lcd.print("Initializing");
-      lcd.setCursor (15, 1);
-      if (++initializingCounter > 9) initializingCounter = 1; // Limit 1 - 9
-      lcd.print(initializingCounter);
-      leftInitialization = false;
-    }
-#else // 20x4 -------------------------------------------------------
-    // Display initialization screen once every INITIALIZATION_INTERVAL
-    if (now - prevInitializationTime > INITIALIZATION_INTERVAL) {
-      prevInitializationTime = now;
-      lcd.setCursor (8, 0); // Go to 1st line
-      lcd.print("GPS");
-      lcd.setCursor (14, 0);
-      lcd.print("v");
-      lcd.print(VERSION);
-      lcd.setCursor (4, 1); // Go to 2nd line
-      lcd.print("Initializing");
-      lcd.setCursor (6, 2); // Go to 3rd line
-      lcd.print("Data Not");
-      lcd.setCursor (7, 3); // Go to 4th line
-      lcd.print("Valid");
-      lcd.setCursor (19, 3);
-      if (++initializingCounter > 9) initializingCounter = 1; // Limit 1 - 9
-      lcd.print(initializingCounter);
-      leftInitialization = false;
-    }
-#endif //------------------------------------------------------------
-  } // GPS data is not valid
-#ifdef DEBUG
-  // Display debug info to the serial monitor (if DEBUG is enabled)
-  // Display debug data once every DEBUG_INTERVAL
-  if (now - prevDebugTime > DEBUG_INTERVAL) {
-    prevDebugTime = now;
-    displayDebugData();
-  }
-#endif // #ifdef DEBUG
-} // loop
-
-#ifndef _16x2
-/* Helper functions start here
-
-  Ripped off from Electrical Engineering Stack Exchange
-  http://electronics.stackexchange.com/questions/66285/how-to-calculate-day-of-the-week-for-rtc
-  ------------------------------------------------------------
-   Returns the number of days to the start of the specified year, taking leap
-   years into account, but not the shift from the Julian calendar to the
-   Gregorian calendar. Instead, it is as though the Gregorian calendar is
-   extrapolated back in time to a hypothetical "year zero".
-*/
-uint16_t leap (uint16_t year)
-{
-  return year * 365 + (year / 4) - (year / 100) + (year / 400);
-}
-/* Returns a number representing the number of days since March 1 in the
-   hypothetical year 0, not counting the change from the Julian calendar
-   to the Gregorian calendar that occurred in the 16th century. This
-   algorithm is loosely based on a function known as "Zeller's Congruence".
-   This number MOD 7 gives the day of week, where 0 = Monday and 6 = Sunday.
-*/
-uint16_t zeller (uint16_t year, uint8_t month, uint8_t day)
-{
-  year += ((month + 9) / 12) - 1;
-  month = (month + 9) % 12;
-  return leap (year) + month * 30 + ((6 * month + 5) / 10) + day + 1;
-}
-
-// Returns the day of week for a given date.
-uint8_t dayOfWeek (uint16_t year, uint8_t month, uint8_t day)
-{
-  return (zeller (year, month, day) % 7) + 1;
-}
-//----------------------------------------------------------
-
-// Print the day of the week on the LCD
-void printDay(uint8_t day)
-{
-  if (day == 7) day = 0;
-  switch (day)
-  {
-    case 0:  lcd.print(" Mon"); break;
-    case 1:  lcd.print(" Tue"); break;
-    case 2:  lcd.print(" Wed"); break;
-    case 3:  lcd.print(" Thu"); break;
-    case 4:  lcd.print(" Fri"); break;
-    case 5:  lcd.print(" Sat"); break;
-    case 6:  lcd.print(" Sun"); break;
-    default: lcd.print(" Err");
-  }
-}
-
-// Compute the cardinal points of the compass
-const char* cardinal(double course)
-{
-#ifdef _16CARDINAL
-  const char* directions[] = {"N  ", "NNE", "NE ", "ENE", "E  ", "ESE", "SE ", "SSE",
-                              "S  ", "SSW", "SW ", "WSW", "W  ", "WNW", "NW ", "NNW"
-                             };
-#else
-  const char* directions[] = {"N  ", "N  ", "NE ", "NE ", "E  ", "E  ", "SE ", "SE ",
-                              "S  ", "S  ", "SW ", "SW ", "W  ", "W  ", "NW ", "NW "
-                             };
-#endif // #ifdef _16CARDINAL
-  uint8_t direction = (uint8_t)((course + 11.25d) / 22.5d);
-  return directions[direction % 16];
-}
-
-/* Ripped off from Stackoverflow
-  http://stackoverflow.com/questions/5590429/calculating-daylight-saving-time-from-only-date
-
-  Check to see if it's Daylight Savings Time (DST)
-*/
-bool IsDST(uint8_t day, uint8_t month , uint8_t DOW)
-{
-  // Make Day of Week (DOW) match with what Stackoverflow suggests
-  // for DOW (Sunday = 0 to Saturday = 6)
-  switch (DOW)
-  {
-    case 6:  DOW = 0; break; // Sun
-    case 7:  DOW = 1; break; // Mon
-    case 1:  DOW = 2; break; // Tue
-    case 2:  DOW = 3; break; // Wed
-    case 3:  DOW = 4; break; // Thu
-    case 4:  DOW = 5; break; // Fri
-    case 5:  DOW = 6; break; // Sat
-    default: break;
-  }
-  // January, February, and December are out
-  if (month < 3 || month > 11) {
-    return false;
-  }
-  // April to October are in
-  if (month > 3 && month < 11) {
-    return true;
-  }
-  int8_t previousSunday = (int8_t)(day - DOW);
-  // In march, we are DST if our previous Sunday was on or after the 8th
-  if (month == 3) {
-    return previousSunday >= 8;
-  }
-  // In November we must be before the first Sunday to be DST
-  // That means the previous Sunday must be before the 1st
-  return previousSunday <= 0;
-}
-
-#ifdef CONVERT_TO_LOCAL
-/* Convert UTC time and date to local time and date
-   Difference between UTC time/date (at Greenwich) and local time/date is 15 minutes
-   per 1 degree of longitude. See the following:
-   http://www.edaboard.com/thread101516.html
-*/
-bool convertToLocal (uint8_t* hour, uint16_t* year, uint8_t* month,
-                     uint8_t* day, const double lon, bool convertDate) {
-
-  uint8_t DaysAMonth [] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-  // Get Day of Week (DOW)
-  uint8_t DOW = dayOfWeek(*year, *month, *day);
-  // Get Daylight Saving Time (DST) or Standard Time (ST)
-  bool DST = IsDST(*day, *month, DOW);
-  // Compute local time (hours)
-  int8_t UTCOffset = (int8_t)(lon / 15.0d); // UTC offset
-  if (UTCOffset < 0) {
-    // West of Greenwich, subtract
-    UTCOffset = abs(UTCOffset); // Make offset positive
-    if (DST) --UTCOffset; // Compensate for DST
-    if (*hour <= UTCOffset) *hour += 24;
-    *hour = *hour - UTCOffset; // Subtract offset
-  }
-  else {
-    // East of Greenwich, add
-    if (DST) ++UTCOffset; // Compensate for DST
-    if (*hour <= UTCOffset) *hour += 24;
-    *hour = *hour + UTCOffset; // Add offset
-  }
-  // Convert date if convertDate flag is set
-  // Portions of the following code (with some modifications) ripped off from Instructables
-  // http://www.instructables.com/id/GPS-time-UTC-to-local-time-conversion-using-Arduin/?ALLSTEPS
-  if (convertDate) {
-    if ((24 - *hour) <= UTCOffset) { // A new UTC day started
-      if (*year % 4 == 0) DaysAMonth[1] = 29; //leap year check (the simple method)
-      if (*hour < 24) {
-        *day -= 1;
-        if (*day < 1) {
-          if (*month == 1) {
-            *month = 12;
-            *year -= 1;
-          } // if (*month == 1)
-          else {
-            *month -= 1;
-          }
-          *day = DaysAMonth[*month - 1];
-        } // if (*day < 1)
-      } // if (*hour < 24)
-      else if (*hour >= 24) {
-        day += 1;
-        if (*day > DaysAMonth[*month - 1]) {
-          *day = 1;
-          *month += 1;
-          if (*month > 12) *year += 1;
-        } // if (*day > DaysAMonth[*month - 1])
-      } // if (*hour >= 24)
-    } // if ((24 - *hour) <= UTCOffset)
-  } // if (convertDate)
-  return (DST);
-}
-#endif // #ifdef CONVERT_TO_LOCAL
-#endif // #ifndef _16x2
-
-#ifdef DEBUG
-// Displays debug data to the serial monitor
-void displayDebugData() {
-  Serial.print("Version: ");
-  Serial.println(VERSION);
-  Serial.print("Satellite Count: ");
-  Serial.println(GPSData.satellites);
-  Serial.print("Latitude: ");
-  Serial.println(GPSData.lat, 6);
-  Serial.print("Longitude: ");
-  Serial.println(GPSData.lon, 6);
-  Serial.print("Speed MPH: ");
-  Serial.println(GPSData.speed);
-  Serial.print("Altitude Feet: ");
-  Serial.println(GPSData.altitude);
-#ifdef _16x2
-  Serial.print("Alt/SPD: ");
-  Serial.println((digitalRead(SPEED_ALTITUDE_SW)) ? "Speed" : "Altitude");
-#else
-  Serial.print("Altitude/Date: ");
-  Serial.println(!(digitalRead(ALTITUDE_DATE_TIME_SW)) ? "Date/Time" : "Altitude");
-#endif
-  Serial.println((digitalRead(BACKLIGHT_SW)) ? "Backlight On" : "Backlight Off");
-  Serial.print("Data valid: ");
-  Serial.println(dataValid);
-  uint8_t DOW = dayOfWeek(GPSData.year, GPSData.month, GPSData.day);
-  Serial.print("DST = ");
-  Serial.println(IsDST(GPSData.day, GPSData.month, DOW));
-  Serial.println("");
-}
-#endif


Update assets.ino

Update assets.ino

--- src/Arduino/abs/assets.ino
+++ src/Arduino/abs/assets.ino
@@ -178,24 +178,40 @@
                         mySerial[num].print("\n");
                         response = usb_ok_packet();
                         break;
-                     case INIT_SPI:
-                         SPI.begin();
-                         pinMode(10, OUTPUT);
-                         break;
-                     case READ_SPI:
-                         digitalWrite(10, LOW);
-                         data = (char *) SPI.transfer(0x00);
-                         response = usb_ok_data_packet(NULL, data, 1);
-                         digitalWrite(10, HIGH);
-                         break;
-                     case WRITE_SPI:
-                         data = packet->data;
-                         for(j = 0; j < packet->data_size; j++) {
+                    case INIT_SPI:
+                        SPI.begin();
+                        pinMode(10, OUTPUT);
+                        break;
+                    case READ_SPI:
+                        digitalWrite(10, LOW);
+                        data = (char *) SPI.transfer(0x00);
+                        response = usb_ok_data_packet(NULL, data, 1);
+                        digitalWrite(10, HIGH);
+                        break;
+                    case WRITE_SPI:
+                        data = packet->data;
+                        for(j = 0; j < packet->data_size; j++) {
                              digitalWrite(10, LOW);
                              SPI.transfer(data[j]);
                              digitalWrite(10, HIGH);
-                         }
-                         break;
+                        }
+                        break;
+                    case CONFIGURE:
+                        comms.configure();
+                        break;
+                    case TRANSMIT:
+                        data = packet->data;
+                        data_size = packet->data_size;
+                        comms.tx(data);
+                        break;
+                    case RECEIVE:
+                        response=comms.rx();
+                        break;
+                    case CHANGE_X:
+                        parameter = packet->cmd_arg1;
+                        value = packet->cmd_arg2;
+                        comms.change_x(parameter,value);
+                        break;
                 }
             } else {
                 response = usb_error_packet(1);


v1.6.3: Update the defrost switch reading in arduino sketch.

Closes #17.

--- chillduino.ino
+++ chillduino.ino
@@ -120,6 +120,7 @@
   chillduino.setCurrentFreshFoodThermistorReading(analogRead(THERMISTOR));
   chillduino.setDoorSwitchReading(digitalRead(DOOR_SWITCH));
   chillduino.setModeSwitchReading(digitalRead(MODE_SWITCH));
+  chillduino.setDefrostSwitchReading(digitalRead(DEFROST_SWITCH));
   chillduino.loop();

   if (chillduino.isChanged()) {


code cleanup

code cleanup

cleaned up time display code, added some ui helpers and adjusted the way the lcd was cleared

--- clock_base.ino
+++ clock_base.ino
@@ -1,44 +1,31 @@
 /*******************************************************************************************
- * /                        Arduino Clock with DS 1307, Rocker Switch
- * /                             3 Push Buttons, and 20x4 LCD
+ * /                        Arduino Clock with and 20x4 LCD, DS 1307 RTC,
+ * /                             3 Push Buttons and Rocker Switch.
  * /
- * /                            Garth Vander Houwen, July. 2016
+ * /                            Garth Vander Houwen, July, 2016
+ * /                              Last Updated January, 2019
  * /
 /********************************************************************************************/

 #define build 1
-#define revision 5
-
-#include <LiquidCrystal_I2C.h>       // library for I@C interface
-#include <RTClib.h>                  // Realtime Clock
-
-// pin configuration for LCM1602 interface module
-// set the LCD I2C_ADDR to 0x27 for a 20 chars 4 line display
-#define I2C_ADDR  0x27
-#define RS_pin    0
-#define RW_pin    1
-#define EN_pin    2
-#define BACK_pin  3
-#define D4_pin    4
-#define D5_pin    5
-#define D6_pin    6
-#define D7_pin    7
-
-// Set the pins on the I2C chip used for LCD connections:
-//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
-LiquidCrystal_I2C lcd(I2C_ADDR, EN_pin, RW_pin, RS_pin, D4_pin, D5_pin, D6_pin, D7_pin, BACK_pin, POSITIVE);
-
-// Custom Big Number Characters
-byte x10[8] = {0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07};
-byte x11[8] = {0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C};
-byte x12[8] = {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F};
-byte x13[8] = {0x07,0x07,0x07,0x07,0x07,0x1F,0x1F,0x1F};
-byte x14[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1F,0x1F,0x1F};
-byte x15[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
-byte x16[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
-byte x17[8] = {0x00,0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00};
-
-// The different states of the clock
+#define revision 6
+
+#include <Wire.h>
+#include <LiquidCrystal_I2C.h>
+#include <RTClib.h>
+RTC_DS1307 RTC;
+// Set the pins on the I2C chip used for LCD connections
+LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
+// custom characters for time font
+byte x10[8] = {0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07};// digit piece
+byte x11[8] = {0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C};// digit piece
+byte x12[8] = {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F};// digit piece
+byte x13[8] = {0x07,0x07,0x07,0x07,0x07,0x1F,0x1F,0x1F};// digit piece
+byte x14[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1F,0x1F,0x1F};// digit piece
+byte x15[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};// digit piece
+byte x16[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};// digit piece
+byte x17[8] = {0x00,0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00};// digit piece (colon)
+// the different states of the clock
 enum states
 {
     SHOW_SPLASH,         // Displays the Splash Screen
@@ -46,45 +33,51 @@
     SHOW_CUSTOM_TEXT,    // Displays the time and custom text from the serial port
     SHOW_SYSTEM_INFO,    // Displays System Information
 };
-
-// Holds the current state of the clock
+// holds the current state of the clock
 states state;
-
+// holds the previous state of the clock
+// used to refresh the screen once when the mode changes
+states previousState;
+
+//////////////////////
+// Global Variables //
+//////////////////////
+
+// Button Pins
+int button1Pin = 2;
+int button2Pin = 3;
+int button3Pin = 4;
+int button4Pin = 5;
+// Button States
+int button1State, button2State, button3State, button4State;
+int previousToggleState;
 // Time and date variables
 const char* dayName[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
 const char* monthName[] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
+int hr_24, hr_12;
 String ampm;
-int hr_24, hr_12;
-RTC_Millis RTC;
-//RTC_DS1307 RTC;
-DateTime now;
-
-// Buttons
-int button1Pin = 2;
-int button2Pin = 3;
-int button3Pin = 4;
-
-// Time Display options
-bool showSeconds = false;
-bool militaryTime = true;
-byte row = 0,col = 0;
-
-// Setup
-// run once
+// Time Display options (TODO Store in eeprom)
+bool showSeconds = true;
+bool militaryTime = false;
+
+///////////////////////
+// Setup - runs once //
+///////////////////////
 void setup() {

     // Used to type in characters in custom text mode
-    Serial.begin(9600);
-//    RTC.begin();
-    RTC.begin(DateTime(__DATE__, __TIME__));
-
+    Serial.begin(9600);
+    // Start the RTC
+    Wire.begin();
+    RTC.begin();
     // Setup Button Pins
     pinMode(button1Pin, INPUT_PULLUP);
     pinMode(button2Pin, INPUT_PULLUP);
     pinMode(button3Pin, INPUT_PULLUP);
-
+    pinMode(button4Pin, INPUT_PULLUP);
+    // setup LCD  for 20 columns and 4 rows
     lcd.begin(20,4);
-    // setup LCD  for 20 columns and 4 rows
+    // create custom characters for clock font
     lcd.createChar(0, x10);                      // digit piece
     lcd.createChar(1, x11);                      // digit piece
     lcd.createChar(2, x12);                      // digit piece
@@ -93,53 +86,59 @@
     lcd.createChar(5, x15);                      // digit piece
     lcd.createChar(6, x16);                      // digit piece
     lcd.createChar(7, x17);                      // digit piece (colon)
-//    if(!RTC.isrunning())
-//    {
-//        RTC.adjust(DateTime(__DATE__,__TIME__));
-//    }
+    // set the time if the RTC is not running
+    if (! RTC.isrunning()) {
+      Serial.println("RTC is NOT running!");
+      // the following line sets the RTC to the date & time this sketch was compiled
+      RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
+    }
+    // Set Initial state
+    state = SHOW_SPLASH;
+    previousState = SHOW_SPLASH;
+}
+
+/////////////////////////////////////
+// Loop - runs over and over again //
+/////////////////////////////////////
+void loop() {
+    // Uses the current state to decide what to process

-    state = SHOW_SPLASH;  // Initial state
-}
-
-
-// Loop
-// run over and over again
-void loop() {
-
-    //timeRef = millis();
-    // Get the time from the RTC
-    now = RTC.now();
-
-    // Uses the current state to decide what to process
+    // Clear the LCD if state has changed
+    if(previousState != state)
+    {
+      lcd.clear();
+    }
     switch (state)
     {
         case SHOW_SPLASH:
+            drawLoadingScreen();
+            lcd.clear();
             showSplash();
-            delay(5000);
+            delay(6000);
             lcd.clear();
             state = SHOW_TIME;
             break;
         case SHOW_TIME:
             showTime();
             showDate();
+            previousState = state;
             break;
-        case SHOW_CUSTOM_TEXT:
+        case SHOW_CUSTOM_TEXT:
             showSerialText();
             showTime();
+            previousState = state;
             break;
-        case SHOW_SYSTEM_INFO:
+        case SHOW_SYSTEM_INFO:
             showSystemInfo();
+            previousState = state;
             break;
-    }
-
-    // variables to hold the pushbutton states
-    int button1State, button2State, button3State;
-
+    }
     // Read Button States
     button1State = digitalRead(button1Pin);
     button2State = digitalRead(button2Pin);
     button3State = digitalRead(button3Pin);
-
+    // Toggle Switch HIGH - ON, LOW - OFF
+    button4State = digitalRead(button4Pin);
     // Handle Button Presses
     if (button1State == LOW || button2State == LOW || button3State == LOW)
     {
@@ -153,9 +152,7 @@
                   Serial.println("Button 1 Pressed - Mode Changed to SHOW_SYSTEM_INFO");
                   break;
               case SHOW_SYSTEM_INFO:
-                  lcd.clear();
                   lcd.setCursor(0, 0);
-                  lcd.print("Awaiting Serial Text");
                   state = SHOW_CUSTOM_TEXT;
                   Serial.println("Button 1 Pressed - Mode Changed to SHOW_CUSTOM_TEXT");
                   break;
@@ -166,31 +163,68 @@
           }
           delay(500);
         }
-        // Button 2 - Black
+        // Button 2 - Green
         if (button2State == LOW) {
-          Serial.println("Button 2 Pressed - Black");
+          Serial.println("Button 2 Pressed - Green");
           delay(500);
         }
-        // Button 3 - White
+        // Button 3 - Blue
         if (button3State == LOW) {
-          Serial.println("Button 3 Pressed - White");
+          Serial.println("Button 3 Pressed - Blue");
           delay(500);
         }
     }
-}
-
-// Show System Information Software Version
-// and available RAM
+    if (previousToggleState != button4State && (state == SHOW_TIME || state == SHOW_CUSTOM_TEXT)){
+      if(button4State == HIGH){
+        Serial.println("Toggle Switch Toggled - ON");
+        lcd.setCursor(18, 1);
+        lcd.print("AL");
+      }
+      else{
+        Serial.println("Toggle Switch Toggled - Off");
+        lcd.setCursor(18, 1);
+        lcd.print("  ");
+      }
+      previousToggleState = button4State;
+      delay(500);
+    }
+}
+
+///////////////
+// Functions //
+///////////////
+
+// show splash screen
 void showSplash()
 {
-  lcd.setCursor(0, 0);
-  lcd.print("  GarthVH.com Labs  ");
-  lcd.setCursor(0, 1);
-  lcd.print(" Arduino Uno DS1307 ");
-  lcd.setCursor(0, 2);
-  lcd.print("  Custom LCD Clock  ");
-  lcd.setCursor(0, 3);
-  lcd.print(F("  [V"));
+  drawSideColumns(false);
+  lcd.setCursor(3, 0);
+  lcd.print("Garth's Clock");
+  lcd.setCursor(3, 1);
+  lcd.print("==============");
+  lcd.setCursor(3, 2);
+  lcd.print("Arduino DS1307");
+  lcd.setCursor(3, 3);
+  lcd.print(F("V"));
+  lcd.print(build);
+  lcd.print(F("."));
+  lcd.print(revision);
+  lcd.print(F(" RAM:"));
+  lcd.print(freeRam());
+  lcd.print(F("B"));
+}
+// show system information screen
+void showSystemInfo()
+{
+  drawSideColumns(true);
+  lcd.setCursor(2, 0);
+  lcd.print("Arduino RT Clock");
+  lcd.setCursor(2, 1);
+  lcd.print("3 btn, rocker sw");
+  lcd.setCursor(2, 2);
+  lcd.print("20X4 LCD, DS1307");
+  lcd.setCursor(2, 3);
+  lcd.print(F("[V"));
   lcd.print(build);
   lcd.print(F("."));
   lcd.print(revision);
@@ -198,166 +232,233 @@
   lcd.print(freeRam());
   lcd.print(F("B]"));
 }
-
-
-// Show System Information Software Version
-// and available RAM
-void showSystemInfo()
-{
-  lcd.setCursor(0, 0);
-  lcd.print("Arduino DS1307 Clock");
-  lcd.setCursor(0, 1);
-  lcd.print(" With Rocker Switch ");
-  lcd.setCursor(0, 2);
-  lcd.print("3 Buttons & 20X4 LCD");
-  lcd.setCursor(0, 3);
-  lcd.print(F("  [V"));
-  lcd.print(build);
-  lcd.print(F("."));
-  lcd.print(revision);
-  lcd.print(F(" RAM: "));
-  lcd.print(freeRam());
-  lcd.print(F("B]"));
-}
-
-// Show Text received
-// over serial connection
+// show text received over a serial connection
 void showSerialText()
 {
-    // when characters arrive over the serial port...
-    if (Serial.available()) {
-      // wait a bit for the entire message to arrive
-      delay(100);
-      // clear the top row
-      lcd.setCursor(0,0);
-      lcd.print("                    ");
-      lcd.setCursor(0,0);
-
-      String txtMsg;
-      // add any incoming characters to the String:
-      while (Serial.available() > 0) {
-        char inChar = Serial.read();
-        txtMsg += inChar;
-
-        if(txtMsg.length() < 21)
-        {
-          lcd.write(inChar);
-        }
-      }
-    }
+  // Initial text only drawn the first time through
+  if(previousState != state)
+  {
+    lcd.setCursor(0, 0);
+    lcd.print("Awaiting Serial Text");
+  }
+  // when characters arrive over the serial port...
+  if (Serial.available()) {
+    // wait a bit for the entire message to arrive
+    delay(100);
+    // clear the top row
+    lcd.setCursor(0,0);
+    lcd.print("                    ");
+    lcd.setCursor(0,0);
+    String txtMsg;
+    // add any incoming characters to the String:
+    while (Serial.available() > 0) {
+      char inChar = Serial.read();
+      txtMsg += inChar;
+      if(txtMsg.length() < 21)
+      {
+        lcd.write(inChar);
+      }
+    }
+  }
 }

 // Displays the current date in the top row
-// e.g. SAT 04 JAN 2014
+// e.g. SAT FEB 4,2019
 void showDate()
 {
-   now = RTC.now();
-   lcd.setCursor(0, 0);
-   String dateString = "* " + String(dayName[now.dayOfTheWeek()]) + " " + String(monthName[now.month()-1]) + " " + String(now.day()) + ", " + String(now.year()) + " *";
+   DateTime now = RTC.now();
+   int startCol = 3;
+   if(now.day() > 10){ startCol = 2; }
+   lcd.setCursor(startCol, 0);
+   String dateString = String(dayName[now.dayOfTheWeek()]) + " " + String(monthName[now.month()-1]) + " " + String(now.day()) + "," + String(now.year());
    lcd.print(dateString);
 }
-
 // displays time in large 3 row letters
 // starting on the second row
 // 10:59 AM
-void showTime()
-{
-    now = RTC.now();
-    lcd.setCursor(0, 0);
-
-    // Set Times for 12 Hour Clock
-    // Set AMPM Indicator Values
-    hr_24 = now.hour();
-    ampm = "AM";
-    if (hr_24 == 0) { // 12 AM
+void showTime() {
+  DateTime now = RTC.now();
+  // Standard (AM/PM) or 24 Hour Clock Setup
+  hr_24 = now.hour();
+  if (hr_24 == 0) { // 12 AM
       hr_12 = 12;
-    }
-    else if(hr_24 == 12) { // 12 PM
+      ampm = "AM";
+  }
+  else if(hr_24 == 12) { // 12 PM
       hr_12 = hr_24;
       ampm = "PM";
-    }
-    else if (hr_24 > 12) { // 13-23 PM
-       hr_12 = (hr_24 - 12);
-       ampm = "PM";
-    }
-    else { // 1-11 AM
-      hr_12 = hr_24;
-    }
+  }
+  else if (hr_24 > 12) { // 13-23 PM
+     hr_12 = (hr_24 - 12);
+     ampm = "PM";
+  }
+  else { // 1-11 AM
+    hr_12 = hr_24;
+    ampm = "AM";
+  }
+  // Time Starting Point
+  byte row = 1,col = 0;
+  // Indent if not showing seconds
+  if(!showSeconds){
+    col = col + 4;
+  }
+  // Hours
+  if (militaryTime && hr_24 < 10 ) {
+    col = col + 3;
+    bigNumber(hr_24,row,col);
+  }
+  else if(!militaryTime && hr_12 < 10) {
+    col = col + 3;
+    bigNumber(hr_12,row,col);
+  }
+  else{
     if(militaryTime){
-      lcd.setCursor(18, 2);
-      lcd.print("24");
-      lcd.setCursor(18, 3);
-      lcd.print("HR");
-    }
-    if(!showSeconds && !militaryTime){
-      lcd.setCursor(18, 2);
-      lcd.print(ampm);
-    }
-
-   // Display the time using bigNumber
-   row = 1;
-   col = 3;
-
-   if(!militaryTime) {
-     if (hr_12 < 10) {
-        // bigNumber(0,row,col);
-        //col = col + 3;
-        bigNumber(hr_12,row,col);
-        col = col + 3;
-     }
-     else {
-       bigNumber(getDigit(hr_12,2) ,row,col);
-       col = col + 3;
-       bigNumber(getDigit(hr_12,1) ,row,col);
-       col = col + 3;
-     }
+      bigNumber(getDigit(hr_24,2) ,row,col);
+      col = col + 3;
+      bigNumber(getDigit(hr_24,1) ,row,col);
+    }
+    else{
+      bigNumber(getDigit(hr_12,2) ,row,col);
+      col = col + 3;
+      bigNumber(getDigit(hr_12,1) ,row,col);
+    }
+  }
+  if(!showSeconds){
+    col = col + 1;
+  }
+  col = col + 2;
+  bigNumber(11,row,col);
+  col = col + 1;
+  // Minutes
+  if (now.minute() < 10) {
+    bigNumber(0,row,col);
+    col = col + 3;
+    bigNumber(now.minute(),row,col);
+  }
+  else {
+    bigNumber(getDigit(now.minute(),2) ,row,col);
+    col = col + 3;
+    bigNumber(getDigit(now.minute(),1) ,row,col);
+  }
+  col = col + 2;
+  // Seconds
+  if(showSeconds){
+   bigNumber(11,row,col);
+   col = col + 1;
+   if (now.second() < 10) {
+      bigNumber(0,row,col);
+      col = col + 3;
+      bigNumber(now.second(),row,col);
    }
    else {
-     if (hr_24 < 10) {
-        col = col + 2;
-        bigNumber(hr_24,row,col);
-        col = col + 3;
-     }
-     else {
-       bigNumber(getDigit(hr_24,2) ,row,col);
-       col = col + 3;
-       bigNumber(getDigit(hr_24,1) ,row,col);
-       col = col + 3;
-     }
+     bigNumber(getDigit(now.second(),2) ,row,col);
+     col = col + 3;
+     bigNumber(getDigit(now.second(),1) ,row,col);
    }
-
-
-   bigNumber(11,row,col);
-   col = col + 2;
-   if (now.minute() < 10) {
-      bigNumber(0,row,col);
-      col = col + 3;
-      bigNumber(now.minute(),row,col);
-      col = col + 2;
-   }
-   else {
-     bigNumber(getDigit(now.minute(),2) ,row,col);
-     col = col + 3;
-     bigNumber(getDigit(now.minute(),1) ,row,col);
-
-   }
-   if(showSeconds){
-     col = col + 2;
-     bigNumber(11,row,col);
-     col = col + 2;
-     if (now.second() < 10) {
-        bigNumber(0,row,col);
-        col = col + 3;
-        bigNumber(now.second(),row,col);
-     }
-     else {
-       bigNumber(getDigit(now.second(),2) ,row,col);
-       col = col + 3;
-       bigNumber(getDigit(now.second(),1) ,row,col);
-     }
-   }
-}
-
+  }
+  // Time Type Indicator On Right
+  if(militaryTime) {
+    lcd.setCursor(18, 3);
+    lcd.print("24");
+  }
+  else {
+    lcd.setCursor(18, 3);
+    lcd.print(ampm);
+  }
+  // Alarm Indicator On Right - Toggle Switch
+  if(button4State == HIGH){
+    lcd.setCursor(18, 1);
+    lcd.print("AL");
+  }
+  else{
+    lcd.setCursor(18, 1);
+    lcd.print("  ");
+  }
+}
+// draw a loading screen
+void drawLoadingScreen()
+{
+  lcd.clear();
+  //drawSolidBorder();
+  lcd.setCursor(1, 1);
+  lcd.print("Loading . . . . .");
+  lcd.setCursor(1, 2);
+  int count = 18;
+  while(count > 0 )
+  {
+    lcd.print((char)255);
+    delay(150);
+    count = count -1;
+  }
+}
+// draw columns on the side of screens
+// single or double column
+void drawSideColumns(bool singleColumn){
+  // Left Column
+  lcd.setCursor(0, 0);
+  lcd.print((char)255);
+  if(!singleColumn) { lcd.print((char)255); }
+  lcd.setCursor(0, 1);
+  lcd.print((char)255);
+  if(!singleColumn) { lcd.print((char)255); }
+  lcd.setCursor(0, 2);
+  lcd.print((char)255);
+  if(!singleColumn) { lcd.print((char)255); }
+  lcd.setCursor(0, 3);
+  lcd.print((char)255);
+  if(!singleColumn) { lcd.print((char)255); }
+  // Right Column
+  lcd.setCursor(19, 0);
+  lcd.print((char)255);
+  if(!singleColumn) {
+    lcd.setCursor(18, 0);
+    lcd.print((char)255);
+  }
+  lcd.setCursor(19, 1);
+  lcd.print((char)255);
+  if(!singleColumn) {
+    lcd.setCursor(18, 1);
+    lcd.print((char)255);
+  }
+  lcd.setCursor(19, 2);
+  lcd.print((char)255);
+  if(!singleColumn) {
+    lcd.setCursor(18, 2);
+    lcd.print((char)255);
+  }
+  lcd.setCursor(19, 3);
+  lcd.print((char)255);
+  if(!singleColumn) {
+    lcd.setCursor(18, 3);
+  }
+  lcd.print((char)255);
+}
+// draw a solid border around the screen
+void drawSolidBorder(){
+  lcd.setCursor(0, 0);
+  int topCount = 20;
+  while(topCount > 0 )
+  {
+    lcd.print((char)255);
+    topCount = topCount -1;
+  }
+  lcd.setCursor(0, 1);
+  lcd.print((char)255);
+  lcd.setCursor(19, 1);
+  lcd.print((char)255);
+  lcd.setCursor(0, 2);
+  lcd.print((char)255);
+  lcd.setCursor(19, 2);
+  lcd.print((char)255);
+  lcd.setCursor(0, 3);
+  int bottomCount = 20;
+  while(bottomCount > 0 )
+  {
+    lcd.print((char)255);
+    bottomCount = bottomCount -1;
+  }
+  lcd.setCursor(1, 1);
+}
 // Position a custom big font digit
 // position number 'num' starting top left at row 'r', column 'c'
 void bigNumber(byte num, byte r, byte c) {
@@ -405,7 +506,6 @@
        case 11: lcd.setCursor(c,r+1); lcd.write(byte(7)); lcd.setCursor(c,r+2); lcd.write(byte(7)); break;
     }
 }
-
 // Count the number of digits in a number
 // used to draw the individual big numbers
 byte countDigits(int num){
@@ -416,7 +516,6 @@
   }
   return count;
 }
-
 // Get a digit of a number
 // used to draw the individual big numbers one at a time
 int getDigit(unsigned int number, int digit) {
@@ -425,7 +524,6 @@
     }
     return number % 10;
 }
-
 // FREERAM: Returns the number of bytes currently free in RAM
 int freeRam(void) {
   extern int  __bss_end, *__brkval;
@@ -437,4 +535,4 @@
     free_memory = ((int)&free_memory) - ((int)__brkval);
   }
   return free_memory;
-}+}


Push brakes hard; find no current limit

Push brakes hard; find no current limit

--- Elcano_C2_In_Out/Elcano_C2_In_Out.ino
+++ Elcano_C2_In_Out/Elcano_C2_In_Out.ino
@@ -37,8 +37,8 @@
 const int FullThrottle =  179;   // 3.5 V
 const int MinimumThrottle = 39;  // Throttle has no effect until 0.75 V

-const int FullBrake = 225;  // start with a conservative value; could go as high as 255;
-const int MinimumBrake = 155; // start with a conservative value; could go as low as 127;
+const int FullBrake = 167;  // start with a conservative value; could go as high as 255;
+const int NoBrake = 207; // start with a conservative value; could go as low as 127;

 const int HardLeft = 223; // was 159; // start with a conservative value; could go as high as 255;
 const int HalfLeft = 223; // was 159;
@@ -184,22 +184,30 @@

         initialize();

-        CalibrateBrakes(95,900);
-
+        CalibrateBrakes(400);
+/*
        CalibrateSteering(HardRight,3);
        CalibrateSteering(HardLeft,3);
-       delay(10000);
+       delay(1000);
        CalibrateSteering(HardRight,1);
        CalibrateSteering(HardLeft,1);
-       delay(10000);
+       delay(1000);
        CalibrateSteering(HardRight,10);
-
+*/
 }

 /*---------------------------------------------------------------------------------------*/
-void CalibrateBrakes(int delayBig, int delaySmall)
-{
-  // This routine establishes the correct values for MinimumBrake and FullBrake.
+void BrakeOn()
+{
+     analogWrite(DiskBrake, FullBrake);
+}
+void BrakeOff()
+{
+     analogWrite(DiskBrake, NoBrake);
+}
+void CalibrateBrakes( int delaySmall)
+{
+  // This routine establishes the correct values for NoBrake and FullBrake.
   // Verify that the value for FullBrake stops the vehicle.
   // It allows us to establish the constants to map the feedback to the commanded position.

@@ -217,8 +225,9 @@

  // Mechanically adjust the brake cables so that the motion of the servo is appropriate
        int feedbacks[5];
-       Serial.println("Calibrate brakes");
-       for (int i = MinimumBrake; i < FullBrake; i += 10)
+       Serial.print(2*delaySmall);
+       Serial.println(" Calibrate brakes");
+       for (int i = NoBrake; i > FullBrake; i -= 15)
      {
        analogWrite(DiskBrake, i);
 //       int current =  analogRead(CurrentBrake);
@@ -304,26 +313,46 @@
       moveSteer(Straight);

 }
-int compareint (const void * a, const void * b)
-{
-  if ( *(int*)a <  *(int*)b ) return -1;
-  if ( *(int*)a == *(int*)b ) return 0;
-  if ( *(int*)a >  *(int*)b ) return 1;
-}
-int median_filter(int* readings)
-// on entry, readings holds the 5 most recent readings.
-// returned value is the median filter.
-// readings[0] is oldest; readings[4] is newest
-// on exit, all readings are shifted, with most recent reading in both [4] and [5]
-{
-  int sorted[5];
-  for (int i = 0; i < 5; i++)
-    sorted[i] = readings[i];
-   qsort(sorted, 5, sizeof(int), compareint);
-   for (int i = 0; i < 4; i++)
-    readings[i] = readings[i+1];
-  return sorted[2];
-
+
+#define SWAP(a,b) temp=(a);(a)=(b);(b)=temp;
+int median_filter(int arr[])
+{ // return the median of 5 numbers
+  // on exit, the order of the five numbers is unspecified.
+  // median filter has been tested and verified on 300 random arrays.
+	register int temp;
+	if (arr[0] > arr[1])
+	{
+		SWAP(arr[0],arr[1])
+	}
+	if (arr[1] > arr[2])
+	{
+		SWAP(arr[1],arr[2])
+		if (arr[0] > arr[1])
+		{
+			SWAP(arr[0],arr[1])
+		}
+	}
+	if (arr[4] < arr[3])
+	{
+		SWAP(arr[4],arr[3])
+	}
+	if (arr[2] <= arr[3])
+		return arr[2];
+	if (arr[4] <= arr[0])
+		return arr[0];
+	if (arr[0] < arr[3])
+	{
+		SWAP(arr[0],arr[3])	// arr[3] is the min
+	}
+	if (arr[2] > arr[4])
+	{
+		SWAP(arr[2],arr[4])	// arr[4] is the max
+	}
+	if (arr[0] >= arr[1])
+		return arr[0];
+	if (arr[2] <= arr[1])
+		return arr[2];
+	return arr[1];
 }
 /*---------------------------------------------------------------------------------------*/
 void initialize()
@@ -428,10 +457,25 @@
   static unsigned long EndTime = 0;
   static unsigned long OutsideTime;
   int center;
-
-  for (int i = 900; i> 0; i-=10)
-          CalibrateBrakes(i/10, i);
-
+
+ /*
+  for (int i = 300; i> 0; i-=10)
+  {
+          CalibrateBrakes(i);
+          delay(500);
+  } */
+  // With no load, there is no current limit on how fast the brakes can move.
+  // If we go from NoBrake (207) to FullBrake (167) with a delay of 250 ms between commands,
+  // maximum power draw is about 3.4 Amp;
+  // but actuator has only a 0.3 inch throw - it is not getting to the extremes
+  // If we use delays of 500 ms, power draw is 2.5 A; throw is 0.5 inch.
+  // With a 1 sec delay, draw is 2.2 A.
+  // Full throw is 0.7 inch
+  //
+  BrakeOn();
+  delay (500);
+  BrakeOff();
+  delay (500);

   return;


v6.5 Bug fix

v6.5 Bug fix

--- GPSLCD.ino
+++ GPSLCD.ino
@@ -493,7 +493,7 @@
 bool convertToLocal(uint8_t* hour, uint16_t* year, uint8_t* month,
                     uint8_t* day, const double lon, bool convertDate) {

-  uint8_t DaysAMonth [] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+  uint8_t DaysAMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

   // Get Day of Week (DOW)
   uint8_t DOW = dayOfWeek(*year, *month, *day);
@@ -534,7 +534,7 @@
         } // if (*day < 1)
       } // if (*hour < 24)
       else if (*hour >= 24) {
-        day += 1;
+        *day += 1;
         if (*day > DaysAMonth[*month - 1]) {
           *day = 1;
           *month += 1;


update example showing use of readArtNetPacketInputMode

--- examples/ESP-DMX/ESP-DMX.ino
+++ examples/ESP-DMX/ESP-DMX.ino
@@ -618,6 +618,10 @@
 		  checkInput(sACNInterface, &sUDP, DMXWiFiConfig.multicastMode());
 		} else {
 		  checkInput(artNetInterface, &aUDP, 0);
+		  art_packet_result = artNetInterface->readArtNetPacketInputMode(&aUDP);
+		  if ( art_packet_result == RESULT_NONE ) {
+			  checkConfigReceived(artNetInterface, aUDP);
+		  }
 		}

 	} else {                  //direction is output from network