Reduce storage requirements by making a color struct and only require 3 bytes per pixel vs 4.

--- projects/arduino/led_matrix_256/led_matrix_256.ino
+++ projects/arduino/led_matrix_256/led_matrix_256.ino
@@ -16,72 +16,79 @@
 //int sensorPin = A5;    // select the input pin for the potentiometer
 //int sensorValue = 0;  // variable to store the value coming from the sensor

-const uint8_t d = 0;
-const uint8_t b = pow(2,7);
-const uint8_t g = pow(2,15);
-const uint8_t r = pow(2,23);
-const uint8_t p = b+r;
-const uint8_t y = g+r;
-const uint8_t a = b+g;
-const uint8_t w = b+g+r;
+struct COLOR {
+  byte r;
+  byte g;
+  byte b;
+};

-const PROGMEM uint8_t frames[][NUM_OF_PIXELS] = { {
-        d,d,w,w,d,d,d,d,d,d,d,d,d,d,d,d,
-        d,d,d,d,d,d,d,d,d,d,d,w,d,w,d,d,
-        d,d,d,w,d,w,d,d,d,d,d,d,d,d,d,d,
-        d,d,d,d,d,d,d,d,d,w,d,d,d,d,d,d,
-        d,d,d,d,d,d,w,w,w,w,w,d,d,d,d,d,
-        d,d,d,d,d,w,w,w,w,w,d,d,d,d,d,d,
-        d,d,d,d,d,r,r,r,g,r,r,r,d,d,d,d,
-        d,d,d,r,r,r,r,g,r,r,r,r,d,d,d,d,
-        d,d,d,r,r,r,r,g,g,g,r,r,r,r,d,d,
-        d,d,r,r,r,r,g,g,g,r,r,r,r,d,d,d,
-        d,d,d,r,r,r,g,g,g,g,g,r,r,r,d,d,
-        d,d,r,r,g,g,g,g,g,g,g,r,r,d,d,d,
-        d,d,d,r,g,g,g,g,g,g,g,g,g,r,d,d,
-        d,d,d,r,r,r,r,y,r,r,r,r,d,d,d,d,
-        d,d,d,d,d,r,r,r,y,r,r,r,d,d,d,d,
-        d,d,d,d,d,r,r,y,r,r,d,d,d,d,d,d
+#define D {0x00, 0x00, 0x00}
+#define B {0x00, 0x00, 0xFF}
+#define G {0x00, 0xFF, 0x00}
+#define R {0xFF, 0x00, 0x00}
+#define P {0xFF, 0x00, 0xFF}
+#define Y {0xFF, 0xFF, 0x00}
+#define A {0x00, 0xFF, 0xFF}
+#define W {0xFF, 0xFF, 0xFF}
+
+
+const PROGMEM COLOR frames[][NUM_OF_PIXELS] = { {
+        D,D,W,W,D,D,D,D,D,D,D,D,D,D,D,D,
+        D,D,D,D,D,D,D,D,D,D,D,W,D,W,D,D,
+        D,D,D,W,D,W,D,D,D,D,D,D,D,D,D,D,
+        D,D,D,D,D,D,D,D,D,W,D,D,D,D,D,D,
+        D,D,D,D,D,D,W,W,W,W,W,D,D,D,D,D,
+        D,D,D,D,D,W,W,W,W,W,D,D,D,D,D,D,
+        D,D,D,D,D,R,R,R,G,R,R,R,D,D,D,D,
+        D,D,D,R,R,R,R,G,R,R,R,R,D,D,D,D,
+        D,D,D,R,R,R,R,G,G,G,R,R,R,R,D,D,
+        D,D,R,R,R,R,G,G,G,R,R,R,R,D,D,D,
+        D,D,D,R,R,R,G,G,G,G,G,R,R,R,D,D,
+        D,D,R,R,G,G,G,G,G,G,G,R,R,D,D,D,
+        D,D,D,R,G,G,G,G,G,G,G,G,G,R,D,D,
+        D,D,D,R,R,R,R,Y,R,R,R,R,D,D,D,D,
+        D,D,D,D,D,R,R,R,Y,R,R,R,D,D,D,D,
+        D,D,D,D,D,R,R,Y,R,R,D,D,D,D,D,D
     },

-    {   d,d,d,d,d,d,d,d,r,d,d,d,d,d,d,d,
-        d,d,d,d,d,d,d,r,d,d,d,d,d,d,d,d,
-        d,d,d,d,d,d,d,r,w,r,d,d,d,d,d,d,
-        d,d,d,d,d,r,r,w,r,r,d,d,d,d,d,d,
-        d,d,d,d,d,d,d,r,r,r,d,d,d,d,d,d,
-        d,d,d,d,d,d,d,y,d,d,d,d,d,d,d,d,
-        d,d,d,d,d,d,d,d,y,d,d,d,d,d,d,d,
-        d,d,d,d,w,w,w,w,w,w,w,d,d,d,d,d,
-        d,d,d,d,d,w,w,w,w,w,w,w,d,d,d,d,
-        d,d,d,d,w,w,w,w,w,w,w,d,d,d,d,d,
-        d,d,d,d,d,w,w,w,w,w,w,w,d,d,y,d,
-        y,d,y,d,w,w,w,w,w,w,w,d,d,d,d,d,
-        y,y,y,d,d,w,w,w,w,w,w,w,d,d,y,d,
-        d,y,y,y,w,w,w,w,w,w,w,y,y,y,y,d,
-        d,d,d,y,y,y,y,y,y,y,y,y,y,y,d,d,
-        d,d,d,y,y,y,y,y,y,y,y,y,d,d,d,d
+    {   D,D,D,D,D,D,D,D,R,D,D,D,D,D,D,D,
+        D,D,D,D,D,D,D,R,D,D,D,D,D,D,D,D,
+        D,D,D,D,D,D,D,R,W,R,D,D,D,D,D,D,
+        D,D,D,D,D,R,R,W,R,R,D,D,D,D,D,D,
+        D,D,D,D,D,D,D,R,R,R,D,D,D,D,D,D,
+        D,D,D,D,D,D,D,Y,D,D,D,D,D,D,D,D,
+        D,D,D,D,D,D,D,D,Y,D,D,D,D,D,D,D,
+        D,D,D,D,W,W,W,W,W,W,W,D,D,D,D,D,
+        D,D,D,D,D,W,W,W,W,W,W,W,D,D,D,D,
+        D,D,D,D,W,W,W,W,W,W,W,D,D,D,D,D,
+        D,D,D,D,D,W,W,W,W,W,W,W,D,D,Y,D,
+        Y,D,Y,D,W,W,W,W,W,W,W,D,D,D,D,D,
+        Y,Y,Y,D,D,W,W,W,W,W,W,W,D,D,Y,D,
+        D,Y,Y,Y,W,W,W,W,W,W,W,Y,Y,Y,Y,D,
+        D,D,D,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,D,D,
+        D,D,D,Y,Y,Y,Y,Y,Y,Y,Y,Y,D,D,D,D
     },

-    {   d,d,d,d,d,d,d,g,g,d,d,d,d,d,d,d,
-        d,d,d,d,d,d,d,g,g,d,d,d,d,d,d,d,
-        d,d,d,d,d,d,b,g,g,g,d,d,d,d,d,d,
-        d,d,d,d,d,d,g,g,b,r,d,d,d,d,d,d,
-        d,d,d,d,d,g,g,g,b,g,b,d,d,d,d,d,
-        d,d,d,d,d,g,b,g,g,g,b,d,d,d,d,d,
-        d,d,d,d,g,g,b,g,g,g,b,b,d,d,d,d,
-        d,d,d,d,g,r,g,b,b,g,g,g,d,d,d,d,
-        d,d,d,g,b,g,g,g,g,b,b,g,g,d,d,d,
-        d,d,d,g,b,p,g,g,g,b,b,g,g,d,d,d,
-        d,d,b,g,p,g,g,b,g,g,g,g,b,b,d,d,
-        d,d,g,g,y,g,b,b,g,r,g,b,b,g,d,d,
-        d,g,g,g,g,b,b,g,g,g,b,b,g,g,g,d,
-        d,d,d,d,d,d,y,y,y,y,d,d,d,d,d,d,
-        d,d,d,d,d,d,y,y,y,y,d,d,d,d,d,d,
-        d,d,d,d,d,d,y,y,y,y,d,d,d,d,d,d
+    {   D,D,D,D,D,D,D,G,G,D,D,D,D,D,D,D,
+        D,D,D,D,D,D,D,G,G,D,D,D,D,D,D,D,
+        D,D,D,D,D,D,B,G,G,G,D,D,D,D,D,D,
+        D,D,D,D,D,D,G,G,B,R,D,D,D,D,D,D,
+        D,D,D,D,D,G,G,G,B,G,B,D,D,D,D,D,
+        D,D,D,D,D,G,B,G,G,G,B,D,D,D,D,D,
+        D,D,D,D,G,G,B,G,G,G,B,B,D,D,D,D,
+        D,D,D,D,G,R,G,B,B,G,G,G,D,D,D,D,
+        D,D,D,G,B,G,G,G,G,B,B,G,G,D,D,D,
+        D,D,D,G,B,P,G,G,G,B,B,G,G,D,D,D,
+        D,D,B,G,P,G,G,B,G,G,G,G,B,B,D,D,
+        D,D,G,G,Y,G,B,B,G,R,G,B,B,G,D,D,
+        D,G,G,G,G,B,B,G,G,G,B,B,G,G,G,D,
+        D,D,D,D,D,D,Y,Y,Y,Y,D,D,D,D,D,D,
+        D,D,D,D,D,D,Y,Y,Y,Y,D,D,D,D,D,D,
+        D,D,D,D,D,D,Y,Y,Y,Y,D,D,D,D,D,D
     }
 };

-const uint16_t MAX_FRAME = sizeof(frames) / NUM_OF_PIXELS;
+const uint16_t MAX_FRAME = ((sizeof(frames) / sizeof(COLOR)) / NUM_OF_PIXELS);

 void setup() {
@@ -93,7 +100,7 @@
     strip.setBrightness(1);
     strip.show(); // Initialize all pixels to 'off'

-    Serial.print("Total number of frames: "); Serial.println(MAX_FRAME + 1);
+    Serial.print("Total number of frames: "); Serial.println(MAX_FRAME);
 }

 void loop() {
@@ -106,13 +113,16 @@
     delay(200);
 }

-void renderFrame( uint16_t frameNumber ) {
+void renderFrame( uint8_t frameNumber ) {
   // Ensure that there is a valid frame, otherwise we will walk off the memory allocated and then bad things happen
-  if (frameNumber >= 0 && frameNumber <= MAX_FRAME) {
+  if (frameNumber >= 0 && frameNumber < MAX_FRAME) {

+    COLOR pixel = {0, 0, 0};
+
     // Setup every pixels
-    for(uint16_t i = 0; i < strip.numPixels(); i++) {
-        strip.setPixelColor(i, frames[frameNumber][i]);
+    for(uint8_t i = 0; i < strip.numPixels(); i++) {
+        pixel = frames[frameNumber][i];
+        strip.setPixelColor(i, pixel.r, pixel.g, pixel.b);
     }

     // Render the frame
@@ -120,8 +130,8 @@
   }
 }

-uint16_t myRemoteRead() {
-    uint16_t remoteFrame = MAX_FRAME + 1; // Start off with an invalid frame to ease debugging
+uint8_t myRemoteRead() {
+    uint8_t remoteFrame = MAX_FRAME; // Start off with an invalid frame to ease debugging
     uint32_t remoteValue = 0;

     if (irrecv.decode(&results))  {  // have we received an IR signal?


sorter: removed button from source

sorter: removed button from source

--- arduino/sorting_machine/sorting_machine.ino
+++ arduino/sorting_machine/sorting_machine.ino
@@ -25,9 +25,6 @@
   distance_to_wall = calibrate_ultra_sound_sensor();
   DEBUG_PRINT("--- distance_to_wall: "); DEBUG_PRINTLN(distance_to_wall);

-  DEBUG_PRINTLN("- Button...");
-  button_init(BUTTON_INT_PIN, instant_stop_interrupt);
-
   DEBUG_PRINTLN("- Motors...");
   motor_init(&motor_conveyor, 0.36, MOTOR_CONVEYOR_PIN, MOTOR_CONVEYOR_INT_PIN,
     motor_conveyor_interrupt);
@@ -40,11 +37,6 @@

   DEBUG_PRINTLN("Starting the sorting machine...");
   motor_turn_analog(&motor_conveyor, 255);
-
-//  while (running){
-//    DEBUG_PRINTLN(get_range(RANGE_TRIG, RANGE_ECHO));
-//    delay(250);
-//  }
 }

 void motor_conveyor_interrupt()
@@ -61,12 +53,6 @@
 {
   advanced_motor_update_degrees(&adv_motor_separator);
   //DEBUG_PRINTLN("int");
-}
-
-void button_init(int16_t pin, void(*func)(void))
-{
-  pinMode(pin, INPUT_PULLUP);
-  attachInterrupt(digitalPinToInterrupt(pin), func, RISING);
 }

 int32_t calibrate_ultra_sound_sensor()
@@ -209,18 +195,3 @@
       exit(0);
   }
 }
-
-void instant_stop_interrupt()
-{
-  if (running == true && stopped == false)
-  {
-    running = false;
-    DEBUG_PRINTLN("Stopping sorting machine...");
-  }
-  else if (running == false && stopped == true)
-  {
-    running = true;
-    DEBUG_PRINTLN("Starting sorting machine...");
-    delay(1000);
-  }
-}


Add function to toggle autoResetControllerData()

Function to Enable or Disable autoResetControllerData()

--- ps2_controller/ps2_controller.ino
+++ ps2_controller/ps2_controller.ino
@@ -106,6 +106,7 @@
 unsigned long previousAnalogLedLevelLow = 0;

 unsigned long readMotorsStatus = 0; // 0 = Read Both Low to High and High to Low changes, 1 = Disabled, 2 = Read Low to High changes, 3 = Read High to Low Changes. 0 Means it's enabled by default.
+unsigned long autoResetControllerDataStatus = 0; // 0 = Automatic reset is enabled, 1 = Automatic reset is disabled

 unsigned long resetCalled = 0;
 unsigned long resetDone = 0;
@@ -129,6 +130,7 @@
 byte serial_rx_buffer_invalid_command[12];
 byte serial_rx_buffer_reset_controller[12];
 byte serial_rx_buffer_change_motors_status[12];
+byte serial_rx_buffer_change_autoreset_controller_status[12];
 unsigned long serial_rx_buffer_counter = 0;
 unsigned long controller = 0;

@@ -387,6 +389,12 @@

   //  Preamble/Postamble = 0x0F for Respond Back to Change Motor Readings
   //  Arduino sends data to tell the computer the change was succesful
+
+  //  Preamble/Postamble = 0x10 for Disable or Enable autoResetControllerData()
+  //  Arduino receives data to disable or enable Automatic Controller Reset Data (0 is disabled)
+
+  //  Preamble/Postamble = 0x11 for Respond Back to autoResetControllerData()
+  //  Arduino sends data to tell the computer the change was succesful
   if (Serial.available() > 0) {

     controller = Serial.readBytes(serial_rx_buffer, sizeof(serial_rx_buffer)) && 0xFF;
@@ -471,8 +479,18 @@
       Serial.flush();
       changeReadMotorsStatus();
     }
+    else if ((serial_rx_buffer[0] == 0x10) && (serial_rx_buffer[11] == 0x10)) {
+      // Choose to enable or disable Automatic Reset Controller Data
+      for (serial_rx_buffer_counter = 0; serial_rx_buffer_counter < sizeof(serial_rx_buffer_change_autoreset_controller_status); serial_rx_buffer_counter++) {
+        //  Pass Serial Buffer to AutoResetControllerData Buffer
+        serial_rx_buffer_change_autoreset_controller_status[serial_rx_buffer_counter] = serial_rx_buffer[serial_rx_buffer_counter];
+        Serial.write(serial_rx_buffer_change_autoreset_controller_status[serial_rx_buffer_counter]);
+      }
+      Serial.flush();
+      changeAutoResetControllerData();
+    }
     //  Get Invalid Command
-    else if ((((serial_rx_buffer[0] < 0x01) || (serial_rx_buffer[0] > 0x0F)) && ((serial_rx_buffer[11] < 0x01) || (serial_rx_buffer[11] > 0x0F))) && (((serial_rx_buffer[0] != 0xA0) && (serial_rx_buffer[0] != 0xA1)) && ((serial_rx_buffer[11] != 0xA0) && (serial_rx_buffer[11] != 0xA1)))) {
+    else if ((((serial_rx_buffer[0] < 0x01) || (serial_rx_buffer[0] > 0x11)) && ((serial_rx_buffer[11] < 0x01) || (serial_rx_buffer[11] > 0x11))) && (((serial_rx_buffer[0] != 0xA0) && (serial_rx_buffer[0] != 0xA1)) && ((serial_rx_buffer[11] != 0xA0) && (serial_rx_buffer[11] != 0xA1)))) {
       for (serial_rx_buffer_counter = 0; serial_rx_buffer_counter < sizeof(serial_rx_buffer_invalid_command); serial_rx_buffer_counter++) {
         //  Pass Serial Buffer to Reset Controller Data Buffer
         serial_rx_buffer_invalid_command[serial_rx_buffer_counter] = serial_rx_buffer[serial_rx_buffer_counter];
@@ -500,7 +518,32 @@
   autoResetControllerData();
 } // Close Loop Function

+void changeAutoResetControllerData() {
+  autoResetControllerData();
+  manualResetControllerData();
+  //Serial.println("");
+  //Serial.print("Changing from ");
+  //Serial.print(autoResetControllerDataStatus);
+  //Serial.print(" to");
+  autoResetControllerDataStatus = serial_rx_buffer_change_autoreset_controller_status[8];
+  serial_rx_buffer_change_autoreset_controller_status[0] = 0x11;
+  serial_rx_buffer_change_autoreset_controller_status[11] = 0x11;
+
+  for (serial_rx_buffer_counter = 0; serial_rx_buffer_counter < sizeof(serial_rx_buffer_change_autoreset_controller_status); serial_rx_buffer_counter++) {
+    //  Write back data as a way to tell the Status changed correctly
+    Serial.write(serial_rx_buffer_change_autoreset_controller_status[serial_rx_buffer_counter]);
+  }
+  Serial.flush();
+  //Serial.print(autoResetControllerDataStatus);
+  //Serial.println(" .");
+  //Serial.flush();
+  autoResetControllerData();
+  manualResetControllerData();
+}
+
 void changeReadMotorsStatus() {
+  getAttention();
+  readMotors();
   //Serial.println("");
   //Serial.print("Changing from ");
   //Serial.print(readMotorsStatus);
@@ -1522,9 +1565,11 @@
       serial_rx_buffer_controller[10] = 0x00; // Delay Byte 1
       serial_rx_buffer_controller[11] = 0x01; // Postamble

-      for (serial_rx_buffer_counter = 0; serial_rx_buffer_counter < sizeof(serial_rx_buffer); serial_rx_buffer_counter++) {
-        Serial.write(serial_rx_buffer_controller[serial_rx_buffer_counter]); //  This line writes the serial data back to the computer as a way to check if the Arduino isn't interpreting wrong values
-        serial_rx_buffer_inverted_controller[serial_rx_buffer_counter] = (255 - serial_rx_buffer_controller[serial_rx_buffer_counter]); //  Invert 0 to 255 and vice versa to make it easier to determine which commands to enable or not, and their values
+      if (autoResetControllerDataStatus == 0) {
+        for (serial_rx_buffer_counter = 0; serial_rx_buffer_counter < sizeof(serial_rx_buffer); serial_rx_buffer_counter++) {
+          Serial.write(serial_rx_buffer_controller[serial_rx_buffer_counter]); //  This line writes the serial data back to the computer as a way to check if the Arduino isn't interpreting wrong values
+          serial_rx_buffer_inverted_controller[serial_rx_buffer_counter] = (255 - serial_rx_buffer_controller[serial_rx_buffer_counter]); //  Invert 0 to 255 and vice versa to make it easier to determine which commands to enable or not, and their values
+        }
       }

       //  First 8 buttons, Buffer Array Element 1
@@ -1561,7 +1606,9 @@
       digitalWrite(commandArray[20], (serial_rx_buffer_inverted_controller[7] & B00000001));

       //  Buffer Array Element 8 is unused in this code, but is existing in case changes are needed
-      Serial.flush();
+      if (autoResetControllerDataStatus == 0) {
+        Serial.flush();
+      }
     }
     previousResetControllerDataDelay += resetControllerDataDelay;
   }


Cherry picked fix from 87865ac19df2f55e3d073cf5dc7ba08c0de4c584

--- libraries/LiquidCrystal/examples/setCursor/setCursor.ino
+++ libraries/LiquidCrystal/examples/setCursor/setCursor.ino
@@ -60,7 +60,7 @@
       // loop over the rows:
       for (int thisRow = 0; thisRow < numCols; thisRow++) {
         // set the cursor position:
-        lcd.setCursor(thisRow, thisCol);
+        lcd.setCursor(thisCol, thisRow);
         // print the letter:
         lcd.write(thisLetter);
         delay(200);


new blah 2

new blah 2

--- proj/hypercube/HCS/HCS.ino
+++ proj/hypercube/HCS/HCS.ino
@@ -203,7 +203,7 @@
   // Handle switching between outer shell animations. Don't do this if we're
   // already switching the inner shell though, don't want to figure that out
   EVERY_N_SECONDS(10) {
-    oAnimCounter = (oAnimCounter + 1) % 5;
+    oAnimCounter = (oAnimCounter + 1) % numAnimation;
   }

   // Same deal for the inner shell
@@ -275,10 +275,10 @@
     case 3:
       chase_mod(OUTER);
       break;
-    //case 4:
-    //  snow_anim(OUTER, 50, 0.3);
-    //  break;
     case 4:
+      snow_anim(OUTER, 50, 0.3);
+      break;
+    case 5:
       fill_shell(OUTER);
       break;
   }


Add Todo

Add Todo

--- Wetteranzeige/Wetteranzeige.ino
+++ Wetteranzeige/Wetteranzeige.ino
@@ -210,7 +210,8 @@
   }

   unsigned long loopEnd = millis();
-
+
+  // TODO also use a time threshold for update need
   if (sleepNow || shouldSleepNow) {
     unsigned long systemActive = loopEnd - systemStart;


Adding CAN to the ESP32IOBoard example

Adding CAN to the ESP32IOBoard example

With this being added you can now turn off the WiFi usage in the
ESP32IOBoard and it will expose only via CAN if USE_CAN is defined and
USE_WIFI is not defined.

Switched ESP32IOBoard to use a MultiConsumer instead of individual
consumer objects

--- arduino/examples/ESP32IOBoard/ESP32IOBoard.ino
+++ arduino/examples/ESP32IOBoard/ESP32IOBoard.ino
@@ -41,15 +41,24 @@
 #include <OpenMRN.h>
 #include <openlcb/TcpDefs.hxx>

+#include "openlcb/MultiConfiguredConsumer.hxx"
+
 #include "config.h"

+// Pick one mode below, if you select USE_WIFI it will expose this node on WIFI
+// if you select USE_CAN, this node will be available on CAN.
+
+#define USE_WIFI
+// #define USE_CAN
+
+/// This is the node id to assign to this device, this must be unique
+/// on the CAN bus.
+static constexpr uint64_t NODE_ID = UINT64_C(0x050101011423);
+
+#if defined(USE_WIFI)
 /// This is the TCP/IP port which the ESP32 will listen on for incoming
 /// GridConnect formatted CAN frames.
 constexpr uint16_t OPENMRN_TCP_PORT = 12021L;
-
-/// This is the node id to assign to this device, this must be unique
-/// on the CAN bus.
-static constexpr uint64_t NODE_ID = UINT64_C(0x050101011423);

 // Configuring WiFi accesspoint name and password
 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,6 +86,30 @@
 /// This is the TCP/IP listener on the ESP32.
 WiFiServer openMRNServer(OPENMRN_TCP_PORT);

+OVERRIDE_CONST(gridconnect_buffer_size, 512);
+OVERRIDE_CONST(gridconnect_buffer_delay_usec, 2000);
+
+#endif // USE_WIFI
+
+#if defined(USE_CAN)
+/// This is the ESP32 pin connected to the SN6565HVD23x/MCP2551 R (RX) pin.
+/// Recommended pins: 4, 16, 21.
+/// Note: Any pin can be used for this other than 6-11 which are connected to
+/// the onboard flash.
+/// Note: If you are using a pin other than 4 you will likely need to adjust
+/// the GPIO pin definitions for the outputs.
+constexpr gpio_num_t CAN_RX_PIN = GPIO_NUM_4;
+
+/// This is the ESP32 pin connected to the SN6565HVD23x/MCP2551 D (TX) pin.
+/// Recommended pins: 5, 17, 22.
+/// Note: Any pin can be used for this other than 6-11 which are connected to
+/// the onboard flash and 34-39 which are input only.
+/// Note: If you are using a pin other than 5 you will likely need to adjust
+/// the GPIO pin definitions for the outputs.
+constexpr gpio_num_t CAN_TX_PIN = GPIO_NUM_5;
+
+#endif // USE_CAN
+
 /// This is the primary entrypoint for the OpenMRN/LCC stack.
 OpenMRN openmrn(NODE_ID);

@@ -90,20 +123,31 @@
 /// layout. The argument of offset zero is ignored and will be removed later.
 static constexpr openlcb::ConfigDef cfg(0);

-OVERRIDE_CONST(gridconnect_buffer_size, 512);
-OVERRIDE_CONST(gridconnect_buffer_delay_usec, 2000);
-
 // Declare output pins
 // NOTE: pins 6-11 are connected to the onboard flash and can not be used for
 // any purpose and pins 34-39 are INPUT only.
-GPIO_PIN(IO0, GpioOutputSafeLow, 2);
-GPIO_PIN(IO1, GpioOutputSafeLow, 4);
-GPIO_PIN(IO2, GpioOutputSafeLow, 5);
-GPIO_PIN(IO3, GpioOutputSafeLow, 16);
-GPIO_PIN(IO4, GpioOutputSafeLow, 17);
-GPIO_PIN(IO5, GpioOutputSafeLow, 18);
-GPIO_PIN(IO6, GpioOutputSafeLow, 19);
-GPIO_PIN(IO7, GpioOutputSafeLow, 23);
+GPIO_PIN(IO0, GpioOutputSafeLow, 15);
+GPIO_PIN(IO1, GpioOutputSafeLow, 2);
+GPIO_PIN(IO2, GpioOutputSafeLow, 16);
+GPIO_PIN(IO3, GpioOutputSafeLow, 17);
+GPIO_PIN(IO4, GpioOutputSafeLow, 13);
+GPIO_PIN(IO5, GpioOutputSafeLow, 12);
+GPIO_PIN(IO6, GpioOutputSafeLow, 14);
+GPIO_PIN(IO7, GpioOutputSafeLow, 27);
+
+// List of GPIO objects that will be used for the output pins. You should keep
+// the constexpr declaration, because it will produce a compile error in case
+// the list of pointers cannot be compiled into a compiler constant and thus
+// would be placed into RAM instead of ROM.
+constexpr const Gpio *const kOutputGpio[] = {
+    IO0_Pin::instance(), IO1_Pin::instance(), //
+    IO2_Pin::instance(), IO3_Pin::instance(), //
+    IO4_Pin::instance(), IO5_Pin::instance(), //
+    IO6_Pin::instance(), IO7_Pin::instance()  //
+};
+
+openlcb::MultiConfiguredConsumer gpio_consumers(openmrn.stack()->node(), kOutputGpio,
+    ARRAYSIZE(kOutputGpio), cfg.seg().consumers());

 // Declare input pins, these are using analog pins as digital inputs
 // NOTE: pins 25 and 26 can not safely be used as analog pins while
@@ -116,23 +160,6 @@
 GPIO_PIN(IO13, GpioInputPU, 39);
 GPIO_PIN(IO14, GpioInputPU, 25);
 GPIO_PIN(IO15, GpioInputPU, 26);
-
-openlcb::ConfiguredConsumer IO0_consumer(
-    openmrn.stack()->node(), cfg.seg().consumers().entry<0>(), IO0_Pin());
-openlcb::ConfiguredConsumer IO1_consumer(
-    openmrn.stack()->node(), cfg.seg().consumers().entry<1>(), IO1_Pin());
-openlcb::ConfiguredConsumer IO2_consumer(
-    openmrn.stack()->node(), cfg.seg().consumers().entry<2>(), IO2_Pin());
-openlcb::ConfiguredConsumer IO3_consumer(
-    openmrn.stack()->node(), cfg.seg().consumers().entry<3>(), IO3_Pin());
-openlcb::ConfiguredConsumer IO4_consumer(
-    openmrn.stack()->node(), cfg.seg().consumers().entry<4>(), IO4_Pin());
-openlcb::ConfiguredConsumer IO5_consumer(
-    openmrn.stack()->node(), cfg.seg().consumers().entry<5>(), IO5_Pin());
-openlcb::ConfiguredConsumer IO6_consumer(
-    openmrn.stack()->node(), cfg.seg().consumers().entry<6>(), IO6_Pin());
-openlcb::ConfiguredConsumer IO7_consumer(
-    openmrn.stack()->node(), cfg.seg().consumers().entry<7>(), IO7_Pin());

 openlcb::ConfiguredProducer IO8_producer(
     openmrn.stack()->node(), cfg.seg().producers().entry<0>(), IO8_Pin());
@@ -174,6 +201,7 @@
 {
     Serial.begin(115200L);

+#if defined(USE_WIFI)
     printf("\nConnecting to: %s\n", ssid);
     WiFi.begin(ssid, password);
     uint8_t attempts = 30;
@@ -207,6 +235,15 @@
     printf("\nWiFi connected, IP address: %s\n",
         WiFi.localIP().toString().c_str());

+    // Start the TCP/IP listener
+    openMRNServer.setNoDelay(true);
+    openMRNServer.begin();
+
+    // Start the mDNS subsystem
+    MDNS.begin(hostname);
+
+#endif // USE_WIFI
+
     // Initialize the SPIFFS filesystem as our persistence layer
     if (!SPIFFS.begin())
     {
@@ -237,21 +274,28 @@
     // have performance impact.
     // openmrn.stack()->print_all_packets();

-    // Start the TCP/IP listener
-    openMRNServer.setNoDelay(true);
-    openMRNServer.begin();
-
-    // Start the mDNS subsystem
-    MDNS.begin(hostname);
-
+#if defined(USE_CAN)
+    // When using the hardware can device it is recommended to also utilize the
+    // background task on the ESP32 rather than call openmrn.loop() from the
+    // loop method.
+    openmrn.start_background_task();
+
+    // Add the hardware CAN device as a bridge
+    openmrn.add_can_port(
+        new Esp32HardwareCan("esp32can", CAN_RX_PIN, CAN_TX_PIN));
+#endif // USE_CAN
+
+#if defined(USE_WIFI)
     // Broadcast this node's hostname with the mDNS service name
     // for a TCP GridConnect endpoint.
     MDNS.addService(openlcb::TcpDefs::MDNS_SERVICE_NAME_GRIDCONNECT_CAN,
         openlcb::TcpDefs::MDNS_PROTOCOL_TCP, OPENMRN_TCP_PORT);
+#endif // USE_WIFI
 }

 void loop()
 {
+#if defined(USE_WIFI)
     // if the TCP/IP listener has a new client accept it and add it
     // as a new GridConnect port.
     if (openMRNServer.hasClient())
@@ -262,8 +306,13 @@
             openmrn.add_gridconnect_port(new Esp32WiFiClientAdapter(client));
         }
     }
-
+#endif // USE_WIFI
+
+    // if we are using the CAN driver the following lines are not
+    // required as the background task will have been started already.
+#if !defined(USE_CAN)
     // Call the OpenMRN executor, this needs to be done as often
     // as possible from the loop() method.
     openmrn.loop();
+#endif
 }


Modify how to calculate LED value

Modify how to calculate LED value

Modify how to calculate LED value

--- Software/OpenCM9.04/RovMain/RovMain.ino
+++ Software/OpenCM9.04/RovMain/RovMain.ino
@@ -29,6 +29,8 @@
 #define LED_PIN_L  8
 #define LED_PIN_R  9

+#define MOTOR_NEUTRAL 1500
+
 bool IsConnected;

 void rc_usb_test();
@@ -49,8 +51,8 @@
   RovServo[RC_MOTOR_C].attach(RC_MOTOR_PIN_C, 1000, 2000, 0, 255 );
   RovServo[RC_MOTOR_R].attach(RC_MOTOR_PIN_R, 1000, 2000, 0, 255 );

-  RovServo[RC_MOTOR_L].writeMicroseconds(0);
-  RovServo[RC_MOTOR_C].writeMicroseconds(0);
+  RovServo[RC_MOTOR_L].writeMicroseconds(1500);
+  RovServo[RC_MOTOR_C].writeMicroseconds(1500);
   RovServo[RC_MOTOR_R].writeMicroseconds(0);

   pinMode(LED_PIN_L, PWM);
@@ -196,7 +198,7 @@
   //Led_Left
   if(pCmd->Data[0] == 1)
   {
-    Led[0] = (pCmd->Data[2]<<8) | (pCmd->Data[1]);
+    Led[0] = (0xFFFF - (pCmd->Data[2]<<8) | (pCmd->Data[1]));
     Serial.print("Led_L : ");
     Serial.println(Led[0]);
     analogWrite(LED_PIN_L, Led[0]);
@@ -204,7 +206,7 @@
   //Led_Right
   if(pCmd->Data[3] == 1)
   {
-    Led[1] = (pCmd->Data[5]<<8) | (pCmd->Data[4]);
+    Led[1] = (0xFFFF - (pCmd->Data[5]<<8) | (pCmd->Data[4]));
     Serial.print("Led_R : ");
     Serial.println(Led[1]);
     analogWrite(LED_PIN_R, Led[1]);
@@ -217,7 +219,7 @@
 void rc_usb_test()
 {
   char ch;
-  static uint16_t  rc_pwm = 1000;
+  static uint16_t  rc_pwm = MOTOR_NEUTRAL;

   if( Serial.available() )
   {
@@ -225,7 +227,7 @@

     if( ch == 'p' )
     {
-      rc_pwm = 1000;
+      rc_pwm = MOTOR_NEUTRAL;
       RovServo[RC_MOTOR_C].writeMicroseconds(rc_pwm);
       Serial.println("Pwm = 0");
     }


解决上位机nodephyaddrburn连接node失败问题。方法：radio.begin()后再配置node的收发地址、功率等参数

--- src/BaseNode/BaseNode.ino
+++ src/BaseNode/BaseNode.ino
@@ -73,8 +73,8 @@
   byte CRC = *(datain + LEN + 1);
   byte BlockType;
   byte cmd;
-  bit link;// more 1, last 0
-  bit reqp;//request 0 , reply 1
+  byte link;// more 1, last 0
+  byte reqp;//request 0 , reply 1
   BlockType = (CTL&0xC0);
   if(BLOCK_S == BlockType)
   {
@@ -82,31 +82,20 @@
     reqp= (CTL&(1<<5));
     switch(cmd)
     {
-      case :
-
-      break;
+      case BLOCK_S_CMD_CONNECT:
+
+           break;
       default:
-      break;
+           break;
     }
   }
   else if(BLOCK_R == BlockType)
-  {    switch()
-    {
-      case :
-      break;
-      default:
-      break;
-    }
+  {
+
   }
   else if(BLOCK_I == BlockType)
   {
-        switch()
-    {
-      case :
-      break;
-      default:
-      break;
-    }
+
   }
   else
   {
@@ -115,7 +104,7 @@
 }
 /*##################################################################################################*/
 void setup(){
-  uint64_t addr;
+  uint64_t addr=0x0;
   Serial.begin(115200);

   LocalPhyAddress[0] = EEPROM.read(EEPROM_PHY_ADDR_START);
@@ -125,15 +114,12 @@
   LocalPhyAddress[4] = EEPROM.read(EEPROM_PHY_ADDR_START+4);
   memcpy( RemotePhyAddress,LocalPhyAddress,5);
   RemotePhyAddress[0] = 0x00;
-  memcpy(addr,RemotePhyAddress,5);
-  radio.openWritingPipe(addr);
-  memcpy(addr,BroadCastAddress,5);
-  radio.openReadingPipe(0,addr);
-  memcpy(addr,LocalPhyAddress,5);
-  radio.openReadingPipe(1,addr);
-  #if 0
   radio.begin();
-  #endif
+  radio.setPALevel(RF24_PA_LOW);
+  radio.openWritingPipe(RemotePhyAddress);
+  radio.openReadingPipe(0,BroadCastAddress);
+  radio.openReadingPipe(1,LocalPhyAddress);
+  radio.startListening();
 }

 void loop(){


arduino button simplification

arduino button simplification

--- arduino/light_switch/light_switch.ino
+++ arduino/light_switch/light_switch.ino
@@ -8,17 +8,16 @@
 #define OPENHAB_HOST "192.168.2.2"
 #define OPENHAB_PORT 8080

-const char* LIGHTS_URL = "/rest/items/Light_";
 const char* CONTENT_TYPE = "Content-Type:text/plain";
 const char* ACCEPT       = "Accept:application/json";

 const int main_led_pin   = 16;
 const int buttons_count = 3;
 // The Ethernet Controller (ENC28J60) uses the SPI pins (10, 11, 12, 13)
-const int buttons [buttons_count] = { 2, 3, 4 };
-const int leds_1 [buttons_count]  = { 5, 7, 14 };
-const int leds_2 [buttons_count]  = { 6, 8, 15 };
-boolean buttons_state [buttons_count] = { 0, 0, 0 };
+const int buttons [buttons_count] = { 5, 3, 4 };
+
+char* lights_url  = "/CMD?Light_X=TOGGLE";
+char* pin_as_char = "X";
 boolean button_was_pressed [buttons_count] = { 0, 0, 0 };
 unsigned long last_millis = 0;

@@ -30,15 +29,12 @@
 void setup()
 {
   pinMode(main_led_pin, OUTPUT);
-  digitalWrite( main_led_pin, HIGH );
-  delay(2000);
-  digitalWrite( main_led_pin, LOW );

   #ifdef DEBUG_SWITCHER
     Serial.begin(9600);
     Serial.println("connect to network");
   #endif
-
+
  setup_buttons();
  sturtup_blink();
  byte mac[] = { 0x9C, 0x92, 0x27, 0x2D, 0xDA, 0x93 };
@@ -52,18 +48,8 @@
 void loop()
 {
   #ifdef DEBUG_SWITCHER
-    Serial.println(".");
+    //Serial.println(".");
   #endif
-
-  // get buttons states from OpenHAB API
-  if ( more_than_4000_millis_passed() && api_available() )
-  {
-    for (int i=0; i<buttons_count; i++) {
-      int api_button_state = read_button_state_from_api( i+1 );
-      toggle_button_led( i+1, api_button_state);
-      buttons_state[i] = api_button_state;
-    }
-  }

   // send request to API if button pressed
   for (int i=0; i<buttons_count; i++) {
@@ -76,7 +62,7 @@
         digitalWrite( main_led_pin, HIGH );
         button_was_pressed[i] = true;

-        send_request_to_api( i+1, buttons_state[i] );
+        send_request_to_api( i+1 );
         last_pressed_at = millis();
       }

@@ -90,69 +76,29 @@

 }

+void setup_buttons()
+{
+  for (int i=0; i<buttons_count; i++) {
+    pinMode(buttons[i], INPUT);
+    digitalWrite(buttons[i], HIGH); //internal pull-ups
+  }
+}
+
 void set_headers()
 {
   client.setHeader(CONTENT_TYPE);
   client.setHeader(ACCEPT);
 }

-String json;
-int read_button_state_from_api(int button_number)
+int send_request_to_api(int b_number)
 {
-  json = "";
-
+  lights_url[11] = lights_url_by_button_number(b_number);
   set_headers();
-  int status_code = client.get( lights_url_by_button_number(button_number), &json );
+  int status_code = client.get( lights_url );

-
   #ifdef DEBUG_SWITCHER
-    Serial.print("Status code from server: ");
-    Serial.println(status_code);
-    Serial.print("Response body from server: ");
-    Serial.println(json);
-  #endif
-
-  if( status_code == 200 )
-  {
-    return parse_api_response_to_get_state();
-  }
-  return -1;
-}
-
-int parse_api_response_to_get_state()
-{
-  int index_of_state = json.indexOf("\"state\":");
-  if (index_of_state > 0)
-  {
-    String state;
-    state = json.substring(index_of_state + 9, index_of_state + 11);
-
-    #ifdef DEBUG_SWITCHER
-      Serial.print("STATE: ");
-      Serial.println(state);
-    #endif
-
-    if(state == "ON")
-    {
-      return 1;
-    }
-    if(state == "OF")
-    {
-      return 0;
-    }
-  }
-  return -1;
-}
-
-int send_request_to_api(int b_number, int current_state)
-{
-  char*  query_url = lights_url_by_button_number(b_number);
-  set_headers();
-  int status_code = client.post( query_url, param_by_state(current_state) );
-
-  #ifdef DEBUG_SWITCHER
-    Serial.println("POST query:");
-    Serial.print(query_url);
+    Serial.println("GET query:");
+    Serial.print(lights_url);
     Serial.print("Status code from server: ");
     Serial.println(status_code);
   #endif
@@ -160,50 +106,9 @@
   return status_code;
 }

-char* param_by_state(int state)
-{
-  if (state)
-    return "OFF";
-  else
-    return "ON";
-}
-
-void setup_buttons()
-{
-  for (int i=0; i<buttons_count; i++) {
-    pinMode(buttons[i], INPUT);
-    digitalWrite(buttons[i], HIGH); //internal pull-ups
-    pinMode(leds_1[i], OUTPUT);
-    pinMode(leds_2[i], OUTPUT);
-
-    //all off
-    digitalWrite(leds_1[i], LOW);
-    digitalWrite(leds_2[i], HIGH);
-  }
-}
-
-char url[40];
-char* lights_url_by_button_number(int button_number)
-{
-  char pin_as_char[2];
-
-  pin_as_char[0] = (char)(((int)'0') + button_number);
-  pin_as_char[1] = '\0';
-
-  strcpy (url, LIGHTS_URL);
-  strcat (url, pin_as_char);
-
-  return url;
-}
-
-void toggle_button_led(int button_number, int state)
-{
-  if (state == 0 || state == 1)
-  {
-    digitalWrite(leds_1[button_number-1], state == 1);
-    digitalWrite(leds_2[button_number-1], state != 1);
-  }
-
+char lights_url_by_button_number(int button_number)
+{
+  return (char)(((int)'0') + button_number);
 }

 int api_available()
@@ -244,9 +149,4 @@
   }
 }

-
-// void turn_on_main_led(unsigned char delayms){
-//   analogWrite(speaker_pin, 128);
-// }
-
-
+


Set all arrays back to 0 during resetAll(), not just the position array.

--- Arduino/Moppy/Moppy.ino
+++ Arduino/Moppy/Moppy.ino
@@ -378,6 +378,8 @@
   //Reset the current position array
   for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
     currentPosition[p]=0;
+    currentPeriod[p]=0;
+    currentTick[p]=0;
   }

   //Reset the outputs to forward


raised min speed and distance to start slowing down

--- examples/RoboMagellan6x6/RoboMagellan6x6.ino
+++ examples/RoboMagellan6x6/RoboMagellan6x6.ino
@@ -19,7 +19,8 @@
 const int SCHEDULE_DELAY  = 25;
 const int STEERTHROW	  = 30; //degrees from far turn to center
 const int REVTHROW		  = 20;
-const int FWDSPEED		  = 115;
+const int MIN_FWD		  = 105;
+const int MAX_FWD		  = 115;
 const int REVSPEED        = 75;
 const int STOP_TIME       = 1500;//time to coast to stop
 const int DANGER_TIME     = STOP_TIME+800; //time to backup after last sighting
@@ -58,6 +59,8 @@
 							reportLocation,
 							};

+int speed;
+
 void setup() {
 	Serial1.begin(38400);
 	CommSerial->begin(9600);
@@ -133,11 +136,10 @@
 		outputAngle = toDeg(atan2(y,x))+90;
 		bound(double(90-STEERTHROW), outputAngle, double(90+STEERTHROW));

-		//slow down near waypoints
-		int speed = (distance*5280.l);//distance in feet;
-		speed *= speed;
-		speed += 96;
-		speed = min(FWDSPEED, speed);
+		/*int */speed = (distance*5280.l);//from 7.5 feet to 4.7, slow
+		speed *= speed/2;
+		speed += 90;
+		bound(MIN_FWD, speed, MAX_FWD);

 		if(stop) output(90 ,90);
 		else     output(speed, outputAngle);
@@ -234,11 +236,11 @@
 	float voltage = float(analogRead(67)/1024.l*5.l*10.1l);
 	manager.sendDataMessage(Protocol::DATA_LATITUDE, location.degLatitude());
 	manager.sendDataMessage(Protocol::DATA_LONGITUDE, location.degLongitude());
-	manager.sendDataMessage(Protocol::DATA_ROLL, roll*180/PI);
-	manager.sendDataMessage(Protocol::DATA_PITCH, pitch*180/PI);
+	manager.sendDataMessage(Protocol::DATA_ROLL, 10.0*stop);//roll*180/PI);
+	manager.sendDataMessage(Protocol::DATA_PITCH, (double)speed);//pitch*180/PI);
 	manager.sendDataMessage(Protocol::DATA_HEADING, trueHeading);
 	manager.sendDataMessage(Protocol::DATA_SPEED, trunkAngle(nmea.getCourse()));
-	manager.sendDataMessage(Protocol::DATA_DISTANCE, voltage);//nmea.getCourse());//distance);
+	manager.sendDataMessage(Protocol::DATA_DISTANCE, distance);//voltage);
 }

 void calibrateGyro(){ //takes one second


clientId is required

clientId is required

--- examples/microblu_cc3000/microblu_cc3000.ino
+++ examples/microblu_cc3000/microblu_cc3000.ino
@@ -732,8 +732,12 @@
     // attempt to connect to Wifi network:
     if(wifi.connect(ssid, ap_security, pass, timeout)) {

-      // Octoblu doesnt use client so send empty client string and YOUR UUID and token
-      if (microblu.connect("", UUID, TOKEN)){
+      String clientIdStr = "microblu_" + String(random(500000)) + "_" + String(random(500000));
+      int clientId_len = clientIdStr.length() + 1;
+      char clientId[clientId_len];
+      clientIdStr.toCharArray(clientId, clientId_len);
+
+      if (microblu.connect(clientId, UUID, TOKEN)){

         //success!
         Serial.println(F("connected"));
@@ -749,4 +753,4 @@
         Serial.println(ssid);
     }
   }
-}+}


Response fix

Response fix

--- SensorBoard.ino
+++ SensorBoard.ino
@@ -40,14 +40,16 @@
       while (!done)
       {
         done = radio.read( ptr, sizeof(byte[32]) );
-
+        Serial.println(ptr[1]);
 	// Delay just a little bit to let the other unit
 	// make the transition to receiver
 	delay(20);
       }
       runCommand(ptr);
       Serial.println(ptr[3]);
+      radio.stopListening();
       radio.write(ptr, sizeof(byte[32]));
+      radio.startListening();
     }

 }


main: remove unused include

main: remove unused include

--- src/main.ino
+++ src/main.ino
@@ -3,7 +3,6 @@
 #include "Pcd8544.h"
 #include "Expander.h"
 #include "Dht.h"
-#include "DHT.h"

 #ifdef ESP8266
 #include <Wire.h>


10th Commit

10th Commit

Remove a file?

--- SmartPakku/SmartPakku-AncientRight.ino
+++ SmartPakku/SmartPakku-AncientRight.ino
@@ -1,387 +0,0 @@
-// Set Serial Monitor to 115200
-// Currently this will output large amounts of debugging data
-
-#define NRF_DEBUG 1
-#include <SPI.h>
-#include <nRF8001.h>
-
-#include "services.h"
-
-// For LiPo Fuel Gauge
-#include "MAX17043.h"
-#include "Wire.h"
-
-hal_aci_data_t setup_msgs[NB_SETUP_MESSAGES] = SETUP_MESSAGES_CONTENT;
-
-// change nRF8001 reset pin to -1 if it's not connected
-// Redbear BLE Shield users: to my knowledge reset pin is not connected so use -1!
-// NOTE: if you choose -1, youll need to manually reset your device after powerup!!
-#define RESET_PIN 9
-#define REQN_PIN 10
-#define RDYN_PIN 2
-
-nRF8001 *nrf;
-
-float temperatureC;
-uint8_t pipeStatusReceived, dataSent;
-unsigned long lastSent;
-
-// For LiPo Fuel Gauge
-MAX17043 batteryMonitor;
-
-// For FSR
-
-// each of a0 - a3 have a FSR and 10K pulldown resistor attached
-const int fsrPin0 = 0;
-const int fsrPin1 = 1;
-const int fsrPin2 = 2;
-const int fsrPin3 = 3;
-
-// store state of 4 FSRs
-uint8_t state;
-
-// store forces
-long fsrForces[4];
-
-// what data to send
-int bt_transfer_seq;
-
-long measure_force(int fsrPin)
-{
-	int fsrReading;     // the analog reading from the FSR resistor divider
-	int fsrVoltage;     // the analog reading converted to voltage
-	unsigned long fsrResistance;  // The voltage converted to resistance, can be very big so make "long"
-	unsigned long fsrConductance;
-	long fsrForce;       // Finally, the resistance converted to force
-
-	fsrReading = analogRead(fsrPin);
-
-	fsrVoltage = map(fsrReading, 0, 1023, 0, 5000);
-	if (fsrVoltage == 0)
-	{
-		fsrForce = 0;
-	}
-	else
-	{
-		fsrResistance = 5000 - fsrVoltage;     // fsrVoltage is in millivolts so 5V = 5000mV
-		fsrResistance *= 10000;                // 10K resistor
-		fsrResistance /= fsrVoltage;
-
-		fsrConductance = 1000000;           // we measure in micromhos so
-		fsrConductance /= fsrResistance;
-
-		// Use the two FSR guide graphs to approximate the force
-		if (fsrConductance <= 1000)
-		{
-			fsrForce = fsrConductance / 80;
-		}
-		else
-		{
-			fsrForce = fsrConductance - 1000;
-			fsrForce /= 30;
-		}
-	}
-	return fsrForce;
-}
-
-void process_forces()
-{
-	fsrForces[0] = measure_force(fsrPin0);
-	fsrForces[1] = measure_force(fsrPin1);
-	fsrForces[2] = measure_force(fsrPin2);
-	fsrForces[3] = measure_force(fsrPin3);
-}
-
-bool fsr_pressed(long fsrForce)
-{
-	if (fsrForce > 1)
-	{
-		return true;
-	}
-	else
-	{
-		return false;
-	}
-}
-
-uint8_t get_pressed_state()
-{
-	state = 0;
-	bool fsrPressed[4];
-
-	process_forces();
-
-	fsrPressed[0] = fsr_pressed(fsrForces[0]);
-	fsrPressed[1] = fsr_pressed(fsrForces[1]);
-	fsrPressed[2] = fsr_pressed(fsrForces[2]);
-	fsrPressed[3] = fsr_pressed(fsrForces[3]);
-
-	if (fsrPressed[0])
-	{
-		state = state | 1;
-
-	}
-	if (fsrPressed[1])
-	{
-		state = state | 2;
-
-	}
-	if (fsrPressed[2])
-	{
-		state = state | 4;
-
-	}
-	if (fsrPressed[3])
-	{
-		state = state | 8;
-
-	}
-	return state;
-}
-
-
-// This function is called when nRF8001 responds with the temperature
-void temperatureHandler(float tempC)
-{
-	Serial.println("received temperature");
-	temperatureC = tempC;
-}
-
-// Generic event handler, here it's just for debugging all received events
-void eventHandler(nRFEvent *event)
-{
-	Serial.println("event handler");
-	nrf->debugEvent(event);
-}
-
-void setup()
-{
-	temperatureC = 0.0;
-	pipeStatusReceived = 0;
-	lastSent = 0;
-	bt_transfer_seq = 0;
-
-	Wire.begin();
-	Serial.begin(115200);
-	Serial.println("Hello");
-
-	// LiPo Fuel Gauge Init Code
-
-	Serial.println("MAX17043 Example: reading voltage and SoC");
-	Serial.println();
-
-	batteryMonitor.reset();
-	batteryMonitor.quickStart();
-	delay(1000);
-
-	float cellVoltage = batteryMonitor.getVCell();
-	Serial.print("Voltage:\t\t");
-	Serial.print(cellVoltage, 4);
-	Serial.println("V");
-
-	float stateOfCharge = batteryMonitor.getSoC();
-	Serial.print("State of charge:\t");
-	Serial.print(stateOfCharge);
-	Serial.println("%");
-
-	// // LiPo Fuel Gauge Init Code End
-
-
-	// nRF8001 class initialized with pin numbers
-	nrf = new nRF8001(RESET_PIN, REQN_PIN, RDYN_PIN);
-
-	// Register event handles
-	nrf->setEventHandler(&eventHandler);
-	nrf->setTemperatureHandler(&temperatureHandler);
-	if ((nrf->setup(setup_msgs, NB_SETUP_MESSAGES)) == cmdSuccess)
-	{
-		Serial.println("SUCCESS");
-	}
-	else
-	{
-		Serial.println("FAIL");
-		while (1);
-	}
-
-	// These functions merely request device address and temperature,
-	// actual responses are asynchronous. They'll return error codes
-	// if somehow the request itself failed, for example because
-	// the device is not ready for these commands.
-	nrf->getDeviceAddress();
-	nrf->poll();
-	nrf->getTemperature();
-	nrf->poll();
-
-	if (temperatureC > 0.0) {
-	Serial.print("Temperature: ");
-	Serial.println(temperatureC, 2);
-	}
-
-	nrf->connect(0, 32);
-}
-
-uint8_t assign_value()
-{
-	switch(bt_transfer_seq)
-	{
-		case 1:
-		   return 's';
-		case 2:
-		   return get_pressed_state();
-		case 3:
-		   return fsrForces[0];
-		case 4:
-		   return fsrForces[1];
-		case 5:
-		   return fsrForces[2];
-		case 6:
-		   return fsrForces[3];
-		default:
-		   return 0;
-	}
-}
-
-void loop()
-{
-	Serial.println("polling");
-
-	// Polling will block - times out after 2 seconds
-	nrf->poll(2000);
-
-	// If heart rate pipe is open
-	if (nrf->isPipeOpen(PIPE_HEART_RATE_HEART_RATE_MEASUREMENT_TX) && (millis() - lastSent) > 1000 && temperatureC > 0.0 && nrf->creditsAvailable())
-	{
-		Serial.println("ready to send data");
-		uint8_t temp[2];
-		temp[0] = 0;
-		//temp[1] = round(temperatureC);
-
-		// The data that should be sent will depend on what stage of sending we are at
-		temp[1] = assign_value();
-		if (bt_transfer_seq <= 6)
-		{
-			bt_transfer_seq += 1;
-		}
-		else
-		{
-			bt_transfer_seq = 0;
-		}
-		//
-		Serial.print("We are in bt_transfer_seq stage: ");
-		Serial.print(bt_transfer_seq);
-		//
-		Serial.print("The value we are sending is: ");
-		Serial.print(temp[1]);
-
-		nrf->sendData(PIPE_HEART_RATE_HEART_RATE_MEASUREMENT_TX, 2, (uint8_t *)&temp);
-		lastSent = millis();
-
-		// For LiPo Fuel Gauge
-		uint8_t bat = batteryMonitor.getSoC();
-
-		// If battery pipe is open
-		if (nrf->isPipeOpen(PIPE_BATTERY_BATTERY_LEVEL_TX) && nrf->creditsAvailable())
-		{
-			nrf->sendData(PIPE_BATTERY_BATTERY_LEVEL_TX, 1, &bat);
-		}
-
-		// get new temperature
-		nrf->getTemperature();
-	}
-	else if (nrf->getConnectionStatus() == Disconnected)
-	{
-		Serial.println("Reconnecting");
-		dataSent = 0;
-		nrf->connect(0, 32);
-	}
-}
-
-
-
-
-
-
-
-
-
-
-/*
-void get_FSR_raw_values(int fsrRawData[])
-{
-	int fsrRawData0 = analogRead(fsrPin0);
-	int fsrRawData1 = analogRead(fsrPin1);
-	int fsrRawData2 = analogRead(fsrPin2);
-	int fsrRawData3 = analogRead(fsrPin3);
-
-	fsrRawData[0] = fsrRawData0;
-	fsrRawData[1] = fsrRawData1;
-	fsrRawData[2] = fsrRawData2;
-	fsrRawData[3] = fsrRawData3;
-}
-
-void get_FSR_voltages(int fsrVoltage[])
-{
-	int fsrVoltage0 = map(fsrRawData0, 0, 1023, 0, 5000);
-	int fsrVoltage1 = map(fsrRawData1, 0, 1023, 0, 5000);
-	int fsrVoltage2 = map(fsrRawData2, 0, 1023, 0, 5000);
-	int fsrVoltage3 = map(fsrRawData3, 0, 1023, 0, 5000);
-
-	fsrVoltage[0] = fsrVoltage0;
-	fsrVoltage[1] = fsrVoltage1;
-	fsrVoltage[2] = fsrVoltage2;
-	fsrVoltage[3] = fsrVoltage3;
-}
-
-long get_FSR_force(int fsrVoltage)
-{
-	unsigned long fsrResistance;  // The voltage converted to resistance, can be very big so make "long"
-	unsigned long fsrConductance;
-	long fsrForce;       // Finally, the resistance converted to force
-
-	if (fsrVoltage == 0)
-	{
-		fsrForce = 0;
-	}
-
-	else
-	{
-		// The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
-		// so FSR = ((Vcc - V) * R) / V        yay math!
-		fsrResistance = 5000 - fsrVoltage;     // fsrVoltage is in millivolts so 5V = 5000mV
-		fsrResistance *= 10000;                // 10K resistor
-		fsrResistance /= fsrVoltage;
-
-		fsrConductance = 1000000;           // we measure in micromhos so
-		fsrConductance /= fsrResistance;
-
-		// Use the two FSR guide graphs to approximate the force
-		if (fsrConductance <= 1000)
-		{
-			fsrForce = fsrConductance / 80;
-		}
-		else
-		{
-			fsrForce = fsrConductance - 1000;
-			fsrForce /= 30;
-		}
-	}
-	return fsrForce;
-}
-
-void process_forces(int fsrVoltage[])
-{
-	// This is held globally
-	// long fsrForces[4];
-
-	fsrForces[0] = get_force(fsrVoltage[0]);
-	fsrForces[1] = get_force(fsrVoltage[1]);
-	fsrForces[2] = get_force(fsrVoltage[2]);
-	fsrForces[3] = get_force(fsrVoltage[3]);
-
-}
-
-*/
-
-
-
-


Sending an 'initial' packet took us over the SRAM limit. Backout out of the changes.

--- things/examples/arduino/PressureMat/PressureMat/PressureMat.ino
+++ things/examples/arduino/PressureMat/PressureMat/PressureMat.ino
@@ -15,12 +15,12 @@

 char packetBuffer[512];

-PROGMEM prog_char *initialPacket = "{\"path\":\"/api/v1/thing/reporting\",\"requestID\":\"1\",\"things\":{\"/device/sensor/arduino/mat\":{\"prototype\":{\"device\":{\"name\":\"60# pressure mat (902PR)\",\"maker\":\"United Security Products\"},\"name\":\"true\",\"status\":[\"present\",\"absent\",\"recent\"],\"properties\":{\"pressure\":[\"on\",\"off\"]}},\"instances\":[]}}}";
+//PROGMEM prog_char *initialPacket = "{\"path\":\"/api/v1/thing/reporting\",\"requestID\":\"1\",\"things\":{\"/device/sensor/arduino/mat\":{\"prototype\":{\"device\":{\"name\":\"60# pressure mat (902PR)\",\"maker\":\"United Security Products\"},\"name\":\"true\",\"status\":[\"present\",\"absent\",\"recent\"],\"properties\":{\"contact\":[\"on\",\"off\"]}},\"instances\":[]}}}";

 PROGMEM prog_char *loopPacket1 = "{\"path\":\"/api/v1/thing/reporting\",\"requestID\":\"";
-PROGMEM prog_char *loopPacket2 = "\",\"things\":{\"/device/sensor/arduino/mat\":{\"prototype\":{\"device\":{\"name\":\"60# pressure mat (902PR)\",\"maker\":\"United Security Products\"},\"name\":\"true\",\"status\":[\"present\",\"absent\",\"recent\"],\"properties\":{\"pressure\":[\"on\",\"off\"]}},\"instances\":[{\"name\":\"Pressure Mat\",\"status\":\"present\",\"unit\":{\"serial\":\"";
+PROGMEM prog_char *loopPacket2 = "\",\"things\":{\"/device/sensor/arduino/mat\":{\"prototype\":{\"device\":{\"name\":\"60# pressure mat (902PR)\",\"maker\":\"United Security Products\"},\"name\":\"true\",\"status\":[\"present\",\"absent\",\"recent\"],\"properties\":{\"contact\":[\"on\",\"off\"]}},\"instances\":[{\"name\":\"Pressure Mat\",\"status\":\"present\",\"unit\":{\"serial\":\"";
 PROGMEM prog_char *loopPacket3 = "\",\"udn\":\"195a42b0-ef6b-11e2-99d0-";
-PROGMEM prog_char *loopPacket4 = "-mat\"},\"info\":{\"pressure\":\"";
+PROGMEM prog_char *loopPacket4 = "-mat\"},\"info\":{\"contact\":\"";
 PROGMEM prog_char *loopPacket5 = "\"},\"uptime\":\"";
 PROGMEM prog_char *loopPacket6 = "\"}]}}}";

@@ -67,10 +67,10 @@
   udp.beginMulti(ip,port);

   // Send intital packet to announce that we're here.
-  Serial.println((char*)pgm_read_word(&initialPacket));
-  udp.beginPacket(udp.remoteIP(), udp.remotePort());
-  udp.write((char*)pgm_read_word(&initialPacket));
-  udp.endPacket();
+  //Serial.println((char*)pgm_read_word(&initialPacket));
+  //udp.beginPacket(udp.remoteIP(), udp.remotePort());
+  //udp.write((char*)pgm_read_word(&initialPacket));
+  //udp.endPacket();

 }

@@ -85,9 +85,8 @@
     //Serial.print( "Button state = " );
     //Serial.println( buttonState );
     if ( buttonState && !sentPacket ) {
-       Serial.println("Sending pressure = on");
+       Serial.println("Sending contact = on");
        sentPacket = 1;
-       requestID = requestID + 1;

        char buffer[12];
        strcpy(packetBuffer,(char*)pgm_read_word(&loopPacket1) );
@@ -112,11 +111,11 @@
        udp.beginPacket(udp.remoteIP(), udp.remotePort());
        udp.write(packetBuffer);
        udp.endPacket();
-
+       requestID = requestID + 1;
+
     } else if ( !buttonState && !sentPacket ) {
-       Serial.println("Sending pressure = off");
+       Serial.println("Sending contact = off");
        sentPacket = 1;
-       requestID = requestID + 1;

        char buffer[12];
        strcpy(packetBuffer,(char*)pgm_read_word(&loopPacket1) );
@@ -140,10 +139,10 @@
        Serial.println(packetBuffer);
        udp.beginPacket(udp.remoteIP(), udp.remotePort());
        udp.write(packetBuffer);
-       udp.endPacket();
+       udp.endPacket();
+       requestID = requestID + 1;

    }
-

   }

@@ -151,39 +150,6 @@
      sentPacket = 0;
   }
   lastButtonState = reading;
-
-
-    /*
-
-    char buffer[12];
-
-    strcpy(packetBuffer,(char*)pgm_read_word(&loopPacket1) );
-    strcat(packetBuffer, itoa( requestID, buffer, 10) );
-    strcat(packetBuffer,(char*)pgm_read_word(&loopPacket2) );
-    for (byte thisByte = 0; thisByte < 6; thisByte++) {
-      sprintf(buffer, "%x", mac[thisByte] );
-      strcat(packetBuffer, buffer);
-    }
-    strcat(packetBuffer,(char*)pgm_read_word(&loopPacket3) );
-    for (byte thisByte = 0; thisByte < 6; thisByte++) {
-      sprintf(buffer, "%x", mac[thisByte] );
-      strcat(packetBuffer, buffer);
-    }
-    strcat(packetBuffer,(char*)pgm_read_word(&loopPacket4) );
-    strcat(packetBuffer, dtostrf(t,4,2,buffer));
-    strcat(packetBuffer,(char*)pgm_read_word(&loopPacket5) );
-    strcat(packetBuffer, dtostrf(h,4,2,buffer));
-    strcat(packetBuffer,(char*)pgm_read_word(&loopPacket6) );
-    strcat(packetBuffer, itoa( millis()/1000, buffer, 10) );
-    strcat(packetBuffer,(char*)pgm_read_word(&loopPacket7) );
-
-    Serial.println(packetBuffer);
-    udp.beginPacket(udp.remoteIP(), udp.remotePort());
-    udp.write(packetBuffer);
-    udp.endPacket();
-
-    */
-

 }


4david

--- arduino-program/MILaserCourseController.ino
+++ arduino-program/MILaserCourseController.ino
@@ -1,447 +1,108 @@
-#include <Arduino.h>
-#include <EventManager.h>   // Event-Based Arduino
-#include <Adafruit_GFX.h>   // [Adafruit] Core graphics library
-#include <RGBmatrixPanel.h> // [Adafruit] Hardware-specific library
+#include "Arduino.h"

-// for details on EventManager, see github
-// https://github.com/igormiktor/arduino-EventManager
+// globals
+String serialRx = "";    // incoming data on serial port
+String serialTx = "";    // outgoing data on serial port
+bool RxComplete = false; // whether we have finished recieving data
+int currentMode = 0;     // game mode, 0,1,2,3 rest,align,cal,play
+int gameSubMode = 0;     // sub-game mode, 0 for "rest" 1 for "play"

-// for details on reading analog voltages, see arduino references
-// https://www.arduino.cc/en/Reference/AnalogRead
+// pins
+const int laserOut = 3;
+const int startButton = 4;
+const int finishButton = 5;
+const int prPins[] = {
+  6,
+  7,
+  8,
+  9,
+  10,
+  11,
+  12,
+  13,
+  14,
+  15
+};
+const int numPrPins = sizeof(prPins) / sizeof(int);

-// /////////////////////////////////////////////////////////////////////////////
-// LED matrix panel code
-// /////////////////////////////////////////////////////////////////////////////
+int lasersOn = 0;
+int startVal = 0;
+int finishVal = 0;
+int prValues[numPrPins];

-// Similar to F(), but for PROGMEM string pointers rather than literals
-#define F2(progmem_ptr) (const __FlashStringHelper *)progmem_ptr
+void setup() {
+  // begin serial communication
+  Serial.begin(9600);
+  // reserve 200 bytes for the recieved string (this is just optimimzation)
+  serialRx.reserve(200);

-#define CLK 11
-#define LAT 9
-#define OE  10
-#define A   A3
-#define B   A2
-#define C   A1
-#define D   A0
-
-// desfine pin layout for the RGB matrix
-RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, true);
-
-// magic code stolen from
-const char str[] PROGMEM = "Adafruit 16x32 RGB LED Matrix";
-int    textX   = matrix.width(),
-       textMin = sizeof(str) * -12,
-       hue     = 0;
-
-
-void updateLEDMatrix(String time) {
-  // set text position
-  matrix.setCursor(textX, 1);
-
-  // draw text
-  matrix.print(time);
-
-  // smoothly refresh the matrix display
-  matrix.swapBuffers(false);
+  pinMode(laserOut, OUTPUT);
 }

-// /////////////////////////////////////////////////////////////////////////////
-// Event Manager globals
-// /////////////////////////////////////////////////////////////////////////////
-
-// initialize a global instance of EventManager
-EventManager gEM;
-
-// /////////////////////////////////////////////////////////////////////////////
-// operation globals
-// /////////////////////////////////////////////////////////////////////////////
-
-// current controller mode,
-int CURRENT_MODE   = 0;
-int MODE_STANDBY   = 0;
-int MODE_ALIGNMENT = 1;
-int MODE_GAME      = 2;
-bool gameState = false;
-
-// pin numbers
-const int laserPin          =  2;  // pin that controls laser on/off
-const int photoResPin       = A15; // analog voltage pin; 0~5V in 1024 steps
-const int startPin          = 33;  // pin for start button
-const int finishPin         = 31;  // pin for end game at end of course
-const int startLightPin     = 4;   // pin that controls the light behind the btn
-const int finishLightPin    = 6;   // pin that controls the light behind the btn
-const int failureTriggerPin = 35;  // pin that manually triggers failure
-
-int startVal       = 1; // state of start button
-int startValLast   = 1;
-int finishVal      = 1; // state of finish button
-int finishValLast  = 1;
-int manualfVal     = 1; // state of the manual failure switch
-int manualfValLast = 1;
-
-//
-// photoresistor moving average filter, ul for very big numbers
-//
-//
-unsigned long numCycles = 0;
-unsigned long totalVal  = 0;
-
-void updatePRWindow () {
-  numCycles += 1;
-  totalVal  += analogRead(photoResPin);
+// this function is called whenever a new byte is available on the serial port,
+// it runs "in parallel" to the main loop()
+void serialEvent() {
+  while (Serial.available()) {
+    char inChar = (char)Serial.read();
+    if (inChar == "\n") {
+      // if we recieve a newline, mark the transfer as complete and return
+      RxComplete = true;
+      return;
+    }
+    serialRx += inChar;
+  }
 }

-unsigned long getPRAvg() {
-  return totalVal / numCycles;
-}
+void loop() {
+  // if we've recieved information, use it
+  if (RxComplete) {
+    // TODO: use the string to change the mode, etc...

-bool isPRValueOk(unsigned long readValue, unsigned long avgValue) {
-  // TODO: algorithm to check photoresistor value
-}
+    RxComplete = true;
+  }

-//
-// clock and timing functions
-//
-//
-unsigned long startTime;
-unsigned long currTime;
-
-unsigned long getTimeDifference() {
-  return currTime - startTime;
-}
-
-String timeToText(unsigned long time) {
-  int seconds = time / 1000;
-  int ms = time % 1000;
-  return String(seconds) + ":" + String(ms);
-}
-
-//
-// pulse code
-//
-//
-unsigned long pulseInterval = 1250;
-bool startBtnLightState = false;
-bool finishBtnLightState = false;
-unsigned long previousMS = 0;
-
-unsigned long pulseLight (int pinNumber) {
-  unsigned long currentMS = millis();
-
-  // if the time since the last time this function ran is longer than the
-  // interval, change the state of the light.
-  if ((currentMS - previousMS) > pulseInterval) {
-    if (pinNumber == startLightPin) {
-      startBtnLightState = !startBtnLightState;
-      digitalWrite(pinNumber, (startBtnLightState) ? HIGH : LOW);
-      previousMS = currentMS;
+  if (currentMode == 0) { // rest - do nothing
+    return;
+  }
+  if (currentMode == 1) { // align - lasers on, nothing else
+    digitalWrite(laserOut, HIGH);
+    return;
+  }
+  if (currentMode == 2) { // calibrate - send data out
+    for(int i = 0; i < numPrPins; i++) {
+      prValues[i] = analogRead(prPins[i]);
     }
-    else if (pinNumber == finishLightPin) {
-      finishBtnLightState = !finishBtnLightState;
-      digitalWrite(pinNumber, (finishBtnLightState) ? HIGH : LOW );
-      previousMS = currentMS;
+    serialTx = constructSerialTx();
+    Serial.write(serialTx);
+    return;
+  }
+  if (currentMode == 3) { // game - branch on rest state then return values
+    if (gameSubMode == 0) {
+      // evaluate if the start button is pushed, if it is, change the submode to
+      // "play," the next loop() will pick up the state
+      startVal = digitalRead(startButton);
+      if (startVal == HIGH) {
+        gameSubMode = 1;
+      }
+      // also notify the Pi
+      serialTx = constructSerialTx();
+      Serial.write(serialTx);
+      return
+    }
+    if (gameSubMode == 1) {
+      // evaluate the photoresistor values
+      finishVal = digitalRead(finishButton);
+      for(int i = 0; i < numPrPins; i++) {
+        prValues[i] = analogRead(prPins[i]);
+      }
+      serialTx = constructSerialTx();
+      Serial.write(serialTx);
     }
   }
 }
-
-// /////////////////////////////////////////////////////////////////////////////
-// event functions
-// /////////////////////////////////////////////////////////////////////////////
-
-// codes for events
-// 00 - standby button pushed
-// 01 - alignment button pushed
-// 02 - game mode button pushed
-//
-// 10 - reserved for future use
-// 11 - game start button pushed
-// 12 - game finish button pushed
-// 13 - game photoresistor tripped
-
-void MODE_ENTER_STANDBY( int event, int param ) {
-  // DEBUG: serial print statements are used for debugging
-  Serial.print("sby :: 0 - disable lasers...");
-
-  // turn off lasers
-  digitalWrite( laserPin, HIGH );
-
-  Serial.println("done.");
-
-  // turn off Arduino onBoard LED
-  digitalWrite( 13, LOW );
-
-  // handle clock
-  // TODO: clock function
-
-  Serial.print("sby :: 1 - disable game mode event listeners...");
-
-  // disable events for gameplay
-  gEM.enableListener( 11, gameStartListener,       false);
-  gEM.enableListener( 12, gameFinishListener,      false);
-  gEM.enableListener( 13, gameLaserBrokenListener, false);
-
-  Serial.println("done.");
-
-  // set mode
-  CURRENT_MODE = MODE_STANDBY;
-
-  Serial.println("sby :: Successfully entered standby mode.");
-  return;
+String constructSerialTx() {
+  return finishPushed + "_" + startPushed + "_" + lasersOn
+    + "_" + pr1Val + "_" + pr2Val + "_" + pr3Val + "_" + pr4Val
+    + "_" + pr5Val + "_" + pr6Val + "_" + pr7Val + "_" + pr8Val
+    + "_" + pr9Val + "_" + pr10Val;
 }
-
-void MODE_ENTER_ALIGNMENT( int event, int param ) {
-  // DEBUG: serial print statements are used for deugging
-  Serial.print("aln :: 0 - enable lasers...");
-
-  // turn on lasers
-  digitalWrite( laserPin, LOW );
-
-  Serial.println("done.");
-
-  // turn on Arduino's onBoard LED
-  digitalWrite(13, HIGH);
-
-  // handle clock
-  // TODO: clock function
-
-  Serial.print("aln :: 1 - disable game mode event listeners...");
-
-  // disable events for gameplay
-  gEM.enableListener( 11, gameStartListener,       false);
-  gEM.enableListener( 12, gameFinishListener,      false);
-  gEM.enableListener( 13, gameLaserBrokenListener, false);
-
-  Serial.println("done.");
-
-  // set mode
-  CURRENT_MODE = MODE_ALIGNMENT;
-
-  Serial.println("aln :: Successfully entered alignment mode.");
-  return;
-}
-
-void MODE_ENTER_GAME( int event, int param ) {
-  // DEBUG: serial print statements are used for debugging
-  Serial.print("gme :: 0 - disable lasers until start button is pushed.");
-
-  // turn off lasers until begin course button pushed
-  digitalWrite( laserPin, HIGH );
-  digitalWrite( 13, HIGH );
-
-  Serial.println("done.");
-
-  // set game state
-  gameState = false;
-
-  // handle clock
-  // TODO: clock functions
-
-  Serial.print("gme :: 1 - enable game mode event listeners...");
-
-  // enable events for gameplay
-  gEM.enableListener( 11, gameStartListener,       true);
-  gEM.enableListener( 12, gameFinishListener,      true);
-  gEM.enableListener( 13, gameLaserBrokenListener, true);
-
-  Serial.println("done.");
-
-
-  // turn on lights on start and end button
-  Serial.print("gme :: 2 - turn on lights between s and f btns...");
-
-  digitalWrite(startLightPin,  HIGH);
-  digitalWrite(finishLightPin, HIGH);
-
-  Serial.println("done.");
-
-  // set mode
-  CURRENT_MODE = MODE_GAME;
-
-  Serial.println("gme :: Successfully entered game mode.");
-  return;
-}
-
-void gameStartListener( int event, int param ) {
-  // DEBUG : serial print statements are used for debugging
-  Serial.println("gme :: starting.");
-
-  // set game state;
-  gameState = true;
-
-  // turn on lasers
-  digitalWrite( laserPin, LOW );
-
-  // set start time
-  unsigned long stime = millis();
-  Serial.print("gme :: t0 = ");
-  Serial.println(stime);
-  startTime = stime;
-
-  // start clock
-  // TODO: clock function
-}
-
-void gameFinishListener( int event, int param ) {
-  // DEBUG : serial print statements are used for debugging
-  Serial.println("gme :: finishing, player success.");
-
-  // get finish time
-  currTime = millis();
-
-  // freeze clock
-  // TODO: clock function
-  //
-
-  // do something with lasers?
-  // TODO: laser function
-  digitalWrite(laserPin, HIGH);
-  delay(10000);
-  MODE_ENTER_GAME(0 ,0);
-}
-
-void gameLaserBrokenListener( int event, int param ) {
-  // DEBUG : serial print statements are used for debugging
-  Serial.println("gme :: finishing, player failure.");
-
-  // get finish time
-  currTime = millis();
-
-  // handle clock
-  // TODO: clock function
-
-  // handle lasers
-  // TODO: laser function
-  for (int i = 0; i < 2; i++) {
-    digitalWrite(laserPin, HIGH);
-    delay(500);
-    digitalWrite(laserPin, LOW);
-    delay(500);
-    digitalWrite(laserPin, HIGH);
-    delay(500);
-    digitalWrite(laserPin, LOW);
-  }
-  MODE_ENTER_GAME(0, 0);
-}
-
-// /////////////////////////////////////////////////////////////////////////////
-// Arduino run code
-// /////////////////////////////////////////////////////////////////////////////
-
-void setup() {
-  // DEBUG : begin serial stream
-  Serial.begin(9600);
-  Serial.println("Board booting...");
-  Serial.print("assigning pin modes...");
-
-  // set up button and laser control pins
-  pinMode( 13,              OUTPUT );
-  pinMode( laserPin,        OUTPUT );
-  pinMode( photoResPin,     INPUT  );
-  pinMode( startLightPin,   OUTPUT );
-  pinMode( finishLightPin,  OUTPUT );
-  pinMode( startPin,  INPUT_PULLUP );
-  pinMode( finishPin, INPUT_PULLUP );
-  pinMode( failureTriggerPin, INPUT_PULLUP );
-
-  Serial.println("done.");
-  Serial.print("Initializing LED matrix...");
-
-  // initialize matrix
-  matrix.begin();
-  matrix.setTextWrap(true); // Don't allow text to run off right edge
-  matrix.setTextSize(2);
-
-  // fill LED display with white for 1 second
-  matrix.fillScreen(1);
-  delay(1000);
-  matrix.fillScreen(0);
-
-  // pre-program matrix
-  matrix.setTextColor(matrix.ColorHSV(hue, 255, 255, true));
-  matrix.setCursor(textX, 1);
-
-  Serial.println("done.");
-  Serial.print("Registering listeners to mode switch event codes...");
-
-  // register listeners for mode switch events
-  gEM.addListener(  0, MODE_ENTER_STANDBY);
-  gEM.addListener(  1, MODE_ENTER_ALIGNMENT);
-  gEM.addListener(  2, MODE_ENTER_GAME);
-
-  Serial.println("done.");
-  Serial.print("Registering listeners to game event codes...");
-
-  // register listeners for game functions
-  gEM.addListener( 11, gameStartListener);
-  gEM.addListener( 12, gameFinishListener);
-  gEM.addListener( 13, gameLaserBrokenListener);
-
-  Serial.println("done.");
-  Serial.println("Entering standby mode:");
-
-  // go into standby mode
-  MODE_ENTER_STANDBY(0, 0);
-
-  Serial.println("Board booted successfully.");
-}
-
-void loop() {
-  // poll input pins for states
-  finishVal  = digitalRead(finishPin);
-  startVal   = digitalRead(startPin);
-  manualfVal = digitalRead(failureTriggerPin);
-
-  // check if button  / switch states changed
-  bool finishedHit = ( finishVal  != finishValLast )  ? true : false;
-  bool startHit    = ( startVal   != startValLast  )  ? true : false;
-  bool failureHit  = ( manualfVal != manualfValLast)  ? true : false;
-
-  // read photoresistor-modulated voltage
-  int prVoltage         = analogRead(photoResPin);
-  unsigned long prAvg   = getPRAvg();
-  bool lasersAreTripped = isPRValueOk(prVoltage, prAvg);
-  // Serial.print("Photoresistor voltage = ");
-  // Serial.println(prVoltage);
-
-  // Event queue is determined by priority.
-  // Priority is determined by user experience.
-  // Priority 0 is highest.
-  // 0 - finish button
-  // 1 - laser broken
-  // 2 - start button
-
-  // If the state has changed and the state is on, fire an event.
-  if ( finishedHit && finishVal == 0 ) {
-    if      ( CURRENT_MODE == MODE_STANDBY   ) { MODE_ENTER_ALIGNMENT(0 ,0); }
-    else if ( CURRENT_MODE == MODE_ALIGNMENT ) { MODE_ENTER_GAME(0, 0); }
-    else if ( CURRENT_MODE == MODE_GAME      ) {
-      if    ( gameState = false ) { MODE_ENTER_ALIGNMENT(0, 0); }
-      else                        { gEM.queueEvent( 12, 0, EventManager::kHighPriority ); }
-    }
-  }
-
-  if ( lasersAreTripped ) {
-    gEM.queueEvent( 13, 0, EventManager::kHighPriority );
-  }
-  if ( failureHit && manualfVal == 0 ) {
-    gEM.queueEvent( 13, 0, EventManager::kHighPriority );
-  }
-
-  if ( startHit && startVal == 0 ) {
-    if      ( CURRENT_MODE == MODE_STANDBY ) { MODE_ENTER_GAME(0, 0); }
-    else if ( CURRENT_MODE == MODE_GAME ) { gEM.queueEvent( 11, 0, EventManager::kHighPriority ); }
-  }
-
-	// process the event queue
-	gEM.processEvent();
-
-  // update the LED matrix display
-  // matrix.swapBuffers(false);
-
-  // pulse lights in various modes
-  if (CURRENT_MODE == MODE_STANDBY) { pulseLight(startLightPin); }
-
-  // update last states for the next cycle
-  finishValLast  = finishVal;
-  startValLast   = startVal;
-}


Add registration, topic storage and more to gateway.ino

--- src/gateway/gateway.ino
+++ src/gateway/gateway.ino
@@ -1,10 +1,32 @@
+#include "../common/secure.h"
+#include "config.h"
+#include "../common/defines.h"
+#include <EEPROM.h>
+
 #include <RFM69.h>
 #include <SPI.h>
+#include <PubSubClient.h>
+#include <Ethernet.h>
 #include "radioNode.h"

+#define MAX_NODES 16
+#define TOPIC_LENGTH
+
+uint8_t mac[] = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; // get real mac
+uint8_t server[] = { 192, 168, 0, 1 };
+uint8_t[4] ip;
+
+const uint8_t HEADER = sizeof(RadioHeader);
+uint8_t knownNodes = 0;
+uint8_t[MAX_NODES] nodes;
+
 RFM69 radio;
-byte ackCount=0;
-uint32_t packetCount = 0;
+EthernetClient ethClient;
+PubSubClient client(server, 1883, callback, ethClient);
+
+void callback(char* topic, byte* payload, unsigned int length) {
+    // handle message arrived
+}

 void setup()
 {
@@ -12,17 +34,95 @@
   delay(10);
   RadioNode::setupRadio();
   radio = RadioNode::getRadio();
+  if (Ethernet.begin(mac) == 0) {
+    Serial.println("Failed to configure Ethernet using DHCP");
+    while(true);
+  }
+  ip = Ethernet.localIP();
+  loadNodes();
 }

 void loop()
 {
-  // check for new wireless data
-  // open connection to mqtt
-  // send data to mqtt
+  if (!client.connected()) {
+    if (!client.connect("arduinoClient")) {
+      Serial.println("Failed to connect to MQTT server...");
+      delay(5000);
+    }
+  }
   char input = Serial.read();
   if (Serial.available() > 0)
     RadioNode::executeCommand(input);
-  if (radio.receiveDone())
-    char[RF69_MAX_DATA_LEN] value;
-    value = RadioNode::readRadio();
+  if (radio.receiveDone()) {
+    RadioHeader header;
+    char[RF69_MAX_DATA_LEN - HEADER] value;
+    char[64] topic;
+
+    RadioNode::readRadio(&header, value);
+    getTopicBase(topic, header.nodeId);
+    switch header.packetType {
+      case LIGHT_STATUS:
+        lightStatusChange(header, (lightStatus*) value);
+        break;
+    }
+  }
 }
+
+void loadNodes()
+  /*
+     All addresses in EEPROM should be initialized to 0xFF.
+     If we read the start of a topic and see a value other than 0xFF
+     then we can infer there is a topic written there.
+  */
+{
+  for (int i = 0; i < MAX_NODES; i++) {
+    uint8_t address = i * TOPIC_LENGTH;
+    if (addressIsUsed()) {
+      knownNodes++;
+    }
+  }
+}
+
+void getTopicBase(char *buff, int index)
+{
+  /*
+     The topic are 64 bytes each max occupying 2 pages each.
+     the start address is based on the index being accessed
+     and the data is read into the provided buffer
+  */
+  int address = TOPIC_LENGTH * index;
+  for (int i = 0; i < TOPIC_LENGTH; i++, adress++) {
+    buff[i] = EEPROM.read(address);
+  }
+}
+
+void handleRegistration(RadioHeader header, Registration registration)
+{
+  int address = TOPIC_LENGTH * header.nodeId;
+  if (!addressIsUsed()) {
+    for (int i = 0; i < TOPIC_LENGTH; i++, address++) {
+      EEPROM.write(address, registration.topic[i]);
+    }
+  } else {
+    Serial.writeln(F("DUPLICATE REGISTRATION DETECTED"));
+}
+
+void addressIsUsed(int address)
+{
+  for (int i = 0; i < TOPIC_LENGTH; i++, address++)
+  {
+    uint8_t val = EEPROM.read(address);
+    if (val != 0xFF) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void lightStatus(RadioHeader header, LightStatus lStatus)
+{
+  char[TOPIC_LENGTH] topic;
+  getTopicBase(topic, header.nodeId);
+  client.publish(topic, (char*)lstatus.status);
+}
+


Deleting shit :D

Deleting shit :D

--- Cbor/Examples/Cbor_Serialport_sender/Cborg_Serialport_sender.ino
+++ Cbor/Examples/Cbor_Serialport_sender/Cborg_Serialport_sender.ino
@@ -1,45 +0,0 @@
-/*
-
-Arduino Sketch to show how Send Encode Cbor package via Serial port
-
-Author: Juanjo Tara
-email:  j.tara@arduino.cc
-date: 	24/04/2015
-*/
-
-
-#include "CborEncoder.h"
-
-
-
-void setup() {
- Serial.begin(9600);
-
-}
-
-void loop() {
-
-  testSerialPort();
-  delay(10000);
-
-}
-
-void testSerialPort() {
-    CborStaticOutput output(32);
-    CborWriter writer(output);
-
-    //Write a Cbor Package with a number and String
-    writer.writeInt(124);
-    writer.writeString("I");
-
-    //get length and data of cbor package
-    unsigned int datalength = output.getSize();
-    unsigned char *datapkg = output.getData();
-
-    //print in Serial port the Data length and Cbor in binary
-    Serial.print("datalength:");
-    Serial.println(datalength);
-    Serial.write(*datapkg,datalength);
-}
-
-


Duino says: working on high score list

Duino says: working on high score list

--- arduino/duinosays/duinosays.ino
+++ arduino/duinosays/duinosays.ino
@@ -126,24 +126,75 @@
     void draw(DuinoSays *duinoSays);
 };

+class Scores {
+private:
+    uint16_t score[3];
+    char tags[3][3];
+    uint8_t trackCount;
+public:
+    Scores():trackCount(0) {
+
+    }
+
+    char* getTag(uint8_t n) {
+        if (n < trackCount) return tags[n];
+        return 0;
+    }
+    uint16_t getScore(uint8_t n) {
+        if (n < trackCount) return score[n];
+        return 0;
+    }
+    bool isHighEnough(uint8_t points) {
+        return trackCount < 3 || points > score[2];
+    }
+    void putScore(uint8_t points, char* tag) {
+        for (int i=0;i<3;i+=1) {
+            if (i >= trackCount || score[i] < points) {
+                uint16_t tmpPoints = score[i];
+                char tmp[3] = {tags[i][0],tags[i][1],tags[i][2]};
+                score[i] = points;
+                tags[i][0] = tag[0];
+                tags[i][1] = tag[1];
+                tags[i][2] = tag[2];
+                if (trackCount == i) {
+                    trackCount += 1;
+                }
+                // carry over
+                points = tmpPoints;
+                tag[0] = tmp[0];
+                tag[1] = tmp[1];
+                tag[2] = tmp[2];
+            }
+        }
+    }
+
+};
+
+class GameOverScreen {
+public:
+    void loop(DuinoSays* ds);
+};
+

 class DuinoSays {
 private:
     uint16_t seed;
     uint16_t currentLevel;
     uint16_t currentStep;
-    uint16_t progressCounter;
-    uint16_t currentScore;
     bool isShowingColors;
     DuinoSaysGameMode mode;
     TinyScreen display;
+    GameOverScreen gameOverScreen;
+public:
+    uint16_t progressCounter;
+    uint16_t currentScore;
+    Scores scores;
+    RenderBuffer<uint16_t,40> buffer;
+    ParticleSystem<28> particleSystem;
     Button btnTopLeft;
     Button btnTopRight;
     Button btnBottomLeft;
     Button btnBottomRight;
-public:
-    RenderBuffer<uint16_t,40> buffer;
-    ParticleSystem<28> particleSystem;

 public:
     DuinoSays():
@@ -383,18 +434,6 @@

     }

-    void loopGameOver() {
-        buffer.drawText(stringBuffer.start()->load(PSTR("game over"))->get(),20,28,buffer.rgb(255,128,32), &virtualDJ_5ptFontInfo);
-        buffer.drawText(stringBuffer.start()->load(PSTR("score: "))->put(currentScore)->get(),28,38,buffer.rgb(192,192,192), &virtualDJ_5ptFontInfo);
-        if (progressCounter < 50) {
-            progressCounter++;
-        } else {
-            drawButtons();
-            if (ScreenButtonState::wasAnyButtonReleased()) {
-                switchToMainMenu();
-            }
-        }
-    }

     void loopAbout() {
         drawDuinoSaysTitle(-24);
@@ -428,7 +467,7 @@
         switch (mode) {
         case DSMODE_MAINMENU: loopMainMenu(); break;
         case DSMODE_PLAYING: loopPlaying(); break;
-        case DSMODE_GAMEOVER: loopGameOver(); break;
+        case DSMODE_GAMEOVER: gameOverScreen.loop(this); break;
         case DSMODE_SHOWHELP: loopHelp(); break;
         case DSMODE_SHOWABOUT: loopAbout(); break;
         case DSMODE_SHOWSCORES: loopScores(); break;
@@ -444,6 +483,33 @@
         throttle = millis();
     }
 };
+
+
+void GameOverScreen::loop(DuinoSays* ds) {
+    ds->buffer.drawText(stringBuffer.start()->load(PSTR("game over"))->get(),20,18,ds->buffer.rgb(255,128,32), &virtualDJ_5ptFontInfo);
+    ds->buffer.drawText(stringBuffer.start()->load(PSTR("score: "))->put(ds->currentScore)->get(),32,38,ds->buffer.rgb(192,192,192), &virtualDJ_5ptFontInfo);
+    if (ds->progressCounter < 50) {
+        ds->progressCounter++;
+    } else {
+        if (ds->scores.isHighEnough(ds->currentScore)) {
+            ds->buffer.drawText(stringBuffer.start()->put("a")->get(),7,13,ds->buffer.rgb(255,255,255), &virtualDJ_5ptFontInfo);
+            ds->buffer.drawText(stringBuffer.start()->put("a")->get(),7,45,ds->buffer.rgb(255,255,255), &virtualDJ_5ptFontInfo);
+            ds->buffer.drawText(stringBuffer.start()->load(PSTR(">"))->get(),86,13,ds->buffer.rgb(255,255,255), &virtualDJ_5ptFontInfo);
+            ds->buffer.drawText(stringBuffer.start()->load(PSTR("ok"))->get(),78,45,ds->buffer.rgb(255,255,255), &virtualDJ_5ptFontInfo);
+            ds->drawButtons();
+        } else {
+            ds->buffer.drawText(stringBuffer.start()->load(PSTR("OK"))->get(),85,45,ds->buffer.rgb(255,255,255), &virtualDJ_5ptFontInfo);
+            ds->btnBottomRight.draw(ds);
+
+
+            if (ds->btnBottomRight.getIsPressed()) {
+                ds->switchToMainMenu();
+            }
+        }
+
+    }
+
+}

 void Particle::draw(DuinoSays* duinoSays) {
     const uint8_t rel = 255 - frameAge * 255 / maxAge;


fixed the boot weirdness

fixed the boot weirdness

--- turtleCode/arduino/final/LCD12864_test/LCD12864_test.ino
+++ turtleCode/arduino/final/LCD12864_test/LCD12864_test.ino
@@ -84,7 +84,7 @@
   LCDA.Initialise(); // INIT SCREEN

   //longboot();
-  semiclose()();
+  semiclose();
   //Serial.println(F("boot completed"));
 }


link to modbusSDM120C.h library

link to modbusSDM120C.h library

Different modbus energy monitor has different protocol

--- ModbusEnergyMonitor.ino
+++ ModbusEnergyMonitor.ino
@@ -1,39 +1,4 @@
 /**********************************************************************
-* ModbusEnergyMonitor example
-* An example to collect data from a Modbus energy monitor using ModbusSensor class
-* to datalogger, include a RTC DS3231 and a SD card
-* version 0.3 ALPHA 21/09/2015
-*
-* Author: Jaime García  @peninquen
-* License: Apache License Version 2.0.
-*
-**********************************************************************/
-/*
-PULSE ELECTRICAL ENERGY MONITOR
-DDS238-1 SINGLE-PHASE DIN-RAIL TYPE WATT-HOUR METER
-TECHNICAL DETAILS
-STANDARD IEC 62053-21 (IEC61036)
-Nominal voltage: 120/220/230/240 V +-10%
-Basic current (It): 5 A
-Maximun current (Ib1) 32 A
-Minimun current: 0.02 A
-Frequency: 50/60 Hz
-Consumption: <2w / 10 VA
-Accurancy class: 1
-Display: Mechanical 5+1 digits
-         LCD 5+1 / 6+1 digits
-Interface: Open colector output (SO)  SO+ ---------------------- PIN 2 (INT0) INTERNAL PULLUP RESISTOR
-           18-27V 27mA                SO- ---------------------- GND
-Impulse length: >= 30ms
-units conversion:
-Energy: 3200 imp = 1 KWh -> 1 imp = 0,3125 Wh;
-Power: 1 imps/s = 1125 W;
-Current(voltage 230V)-> 1 imp/s = 4.89 A;
-maximum impulse frequency (30 A): 6.13 imp/s -> period 163 ms
-basic frequency (5 A): 1.02 imp/s -> period 978.3 ms
-minimun impulse frequency (0.02 A): 1.0 imp/min-> period 60000 ms
-Mounting: DIN rail 18 mm (1 module)
-include flasing led proportional to load (1000 imp/KWh)
 */
 #define SERIAL_OUTPUT 1

@@ -47,15 +12,22 @@
 #   define SERIAL_PRINTLN(...)
 #endif

-#include "ModbusSensor.h"
+#include "ModbusSDM120C.h"

-#define SERIAL_PORT 0 // Arduino only one serial port, Mega has 3 serial ports.
-#define ID_SLAVE 1
-#define REFRESH_INTERVAL  5000      // refresh time, 5 SECONDS
+#define MODBUS_SERIAL_PORT &Serial1 // Arduino has only one serial port, Mega has 3 serial ports.
+// if use Serial 0, remember disconect Tx (pin0) when upload sketch, then re-conect
+#define ID_SDM120C      // modbus id of the energy monitor
+#define REFRESH_INTERVAL  5000      // refresh time, 5 SECONDS, equivalent to poll time
 #define WRITE_INTERVAL 300000UL  // values send to serial port, 15 minutes (5 * 60 * 1000)
 #define KWH_2_WS 36000000
-ModbusSensor wattmeter; // instance to collect data
+ModbusSDM120C wattmeter; // instance to collect data
 //variables to process and send values
+float voltage;
+float maxVoltage;
+float minVoltage;
+float current;
+float maxCurrent;
+float minCurrent;
 float power;
 float maxPower;
 float minPower;


anavi-thermometer.ino: Support multiple DS18B20

Support multiple DS18B20 sensors but show only the temperature
values from the last one on the display.

Signed-off-by: Leon Anavi <be92910ae7bb6f58bb9b7c6f845bc30640119592@anavi.org>

--- anavi-thermometer/anavi-thermometer/anavi-thermometer.ino
+++ anavi-thermometer/anavi-thermometer/anavi-thermometer.ino
@@ -95,11 +95,15 @@
         if (0 < sensors.getDeviceCount())
         {
             sensors.requestTemperatures();
-            float wtemp = sensors.getTempCByIndex(0);
-            dsTemperature = wtemp;
-            water="Water "+String(dsTemperature,1)+"C";
-            Serial.println(water);
+            for (int ds=0; ds < sensors.getDeviceCount(); ds++)
+            {
+              float wtemp = sensors.getTempCByIndex(ds);
+              dsTemperature = wtemp;
+              water="Water "+ String(ds) + ": "+String(dsTemperature,1)+"C";
+              Serial.println(water);
+            }
         }
+        // Show on the display only the value from the last DS18B20 sensor
         drawDisplay(air.c_str(), hum.c_str(), water.c_str());
     }
 }


new blah 2

new blah 2

--- proj/hypercube/HCS/HCS.ino
+++ proj/hypercube/HCS/HCS.ino
@@ -106,7 +106,7 @@
   gBrightness = maxBrightness;
   gBlending = LINEARBLEND;
   iPaletteCounter = 0;
-  oPaletteCounter = iPaletteCounter + 2;
+  oPaletteCounter = 3;
   gPaletteCounter = 0;

   iAnimCounter = 0;


Setting debug to True

Setting debug to True

--- examples/UbidotsSaveValue/UbidotsSaveValue.ino
+++ examples/UbidotsSaveValue/UbidotsSaveValue.ino
@@ -32,7 +32,7 @@

 void setup() {
   Serial.begin(115200);
-  client.setDebug(false);
+  client.setDebug(true);
 }

 void loop() {


updated serial baud rate and library links

--- software/sensors/sensors.ino
+++ software/sensors/sensors.ino
@@ -65,7 +65,6 @@

 // GENERAL DEFITIONS
 // is it an arduino mini? - used to set clock rates
-#define ARDUINO_MINI  1
 #define BAUD_RATE 9600

 // Define pins for sensors
@@ -96,11 +95,7 @@
 // begin setup
 void setup() {
   // general setup
-  #ifdef ARDUINO_MINI   // is it an arduino mini (it has half the clock rate of the nano)
-  Serial.begin(BAUD_RATE*2);
-  #else
   Serial.begin(BAUD_RATE);
-  #endif
   Serial.println("Serial Comms setup.");

   // ISL29125 RGB PHOTOSENSOR


Output NMEA0183 XDR sentences if we have relevant temp/pressure n2k data and conversion flag is on.

--- teensy/n2k.ino
+++ teensy/n2k.ino
@@ -1004,8 +1004,63 @@
        }
     }
   }
+  else if(n2k_output_cycle == 7)
+  {
+    //
+    //  Build custom 0183 Messages as the library does not natively support XDR
+    //
+
+    if( !N2kIsNA(n2k_air_temperature))
+    {
+      tNMEA0183Msg NMEA0183Msg;
+      if (
+            NMEA0183Msg.Init("XDR", "II")
+            &&
+            NMEA0183Msg.AddStrField("C")
+            &&
+            NMEA0183Msg.AddDoubleField(n2k_air_temperature -  273.15, 1,tNMEA0183Msg::DefDoubleFormat,"C")
+            &&
+            NMEA0183Msg.AddStrField("TempAir")
+          )
+       {
+         push_out_message(NMEA0183Msg, FLAG_ENV_N2K_TO_NMEA);
+       }
+    }
+    if( !N2kIsNA(n2k_water_temperature))
+    {
+      tNMEA0183Msg NMEA0183Msg;
+      if (
+            NMEA0183Msg.Init("XDR", "II")
+            &&
+            NMEA0183Msg.AddStrField("C")
+            &&
+            NMEA0183Msg.AddDoubleField(n2k_water_temperature -  273.15, 1,tNMEA0183Msg::DefDoubleFormat,"C")
+            &&
+            NMEA0183Msg.AddStrField("ENV_WATER_T")
+          )
+       {
+         push_out_message(NMEA0183Msg, FLAG_ENV_N2K_TO_NMEA);
+       }
+    }
+    if( !N2kIsNA(n2k_air_pressure))
+    {
+      tNMEA0183Msg NMEA0183Msg;
+      if (
+            NMEA0183Msg.Init("XDR", "II")
+            &&
+            NMEA0183Msg.AddStrField("P")
+            &&
+            NMEA0183Msg.AddDoubleField(PascalTomBar(n2k_air_pressure) / 1000.0, 1,tNMEA0183Msg::DefDoubleFormat,"B")
+            &&
+            NMEA0183Msg.AddStrField("Barometer")
+          )
+       {
+         push_out_message(NMEA0183Msg, FLAG_ENV_N2K_TO_NMEA);
+       }
+    }
+  }
   n2k_output_cycle += 1;
-  if(n2k_output_cycle >= 7)
+  if(n2k_output_cycle >= 8)
   {
     n2k_output_cycle = 0;
   }


Running average

Running average

--- transmitter/Monitor/Monitor.ino
+++ transmitter/Monitor/Monitor.ino
@@ -145,7 +145,10 @@
   // Read the battery level
   if (now - vcc_last > 1000) {
     vcc_last = now;
-    vcc = batteryVcc();
+    //vcc = batteryVcc();
+
+    // Running average
+    vcc = vcc * 0.9 + batteryVcc() * 0.1;
   }

   // Change the display if there is no serial data from the transmitter


fixed ACS715 offset calculation

fixed ACS715 offset calculation

--- src/analog_sensors_board.ino
+++ src/analog_sensors_board.ino
@@ -81,7 +81,6 @@

 #define LM35_MVC 10.0f          // mV/C
 #define ACS715_MVA 133.0f       // mv/A
-#define ACS715_OFF 202          // ADC levels (@ ADC_INTERNAL)
 #define ACS714_MVA 185.0f       // mv/A

 #define BMP085_ADDRESS 0x77     // I2C address
@@ -93,9 +92,11 @@

 // Allegro ACS715 0A to 30A     (using 2.56V ADC ref)
 //const float ACS715_CONV = ADC_INTERNAL_MV / ACS715_MVA;         // Amps per ADC level
+//const int ACS715_OFFSET = 202;                                  // ADC level (0.5 Vin @ 2.52 Vref ~= 202.2)

 // Allegro ACS715 0A to 30A     (using 5.00V ADC ref)
 const float ACS715_CONV = ADC_DEFAULT_MV / ACS715_MVA;          // Amps per ADC level
+const int ACS715_OFFSET = 103;                                  // ADC level (0.5 Vin @ 5 Vref = 102.6)

 // Allegro ACS714 current sensor
 //const int ACS_ZERO = (int) 2500 / ADC_INTERNAL_MV;            // ADC reading for 2.5V (~ 1007)
@@ -373,7 +374,7 @@
         digitalWrite(LED_PIN, LOW);

         // calculate output is Amps
-        acs0 = (float) (raw_acs0 - ACS715_OFF)  * ACS715_CONV;
+        acs0 = (float) (raw_acs0 - ACS715_OFFSET)  * ACS715_CONV;
         //acs0 = (float) (ACS_ZERO - raw_acs0) * ACS714_CONV;

         // send current report


Arduino drives motor

Arduino drives motor

--- Elcano_C2_MotorSPI2/Elcano_C2_MotorSPI2.ino
+++ Elcano_C2_MotorSPI2/Elcano_C2_MotorSPI2.ino
@@ -10,6 +10,11 @@

 // inslude the SPI library:
 #include <SPI.h>
+
+#define MEG 1000000
+
+volatile long SpeedCyclometer_degPs;
+
 /*---------------------------------------------------------------------------------------*/
 void setup()
 {
@@ -27,7 +32,8 @@
   SPI.begin();
   for (int i = 0; i < 4; i++)
       DAC_Write (i, 0);   // reset did not clear previous states
-
+   attachInterrupt(1, WheelRev, RISING);
+
 //  Serial.println(SS);
 //  Serial.println(MOSI);
 //  Serial.println(MISO);
@@ -41,7 +47,7 @@
 /*---------------------------------------------------------------------------------------*/
 /*---------------------------------------------------------------------------------------*/
 // WheelRev is called by an interrupt.
-/*
+
 void WheelRev()
 {
     static unsigned long OldTick = 0;
@@ -57,7 +63,7 @@
     SpeedCyclometer_degPs = (360 * MEG) / WheelRevMicros;
     OldTick = TickTime;
 }
-*/
+
 /*---------------------------------------------------------------------------------------*/
 void loop()
 {
@@ -75,25 +81,44 @@

 No ramp is seen on DB9F X4-3.  There is no continuity between IC3 pin 8 and X4-3.

-Only after it looks good, do we attach the DB15 cable to drive the motor.
+We attached the DB15 cable and drove the motor from PCB #1
+
+The DB-25 connector from Cruise supplies the wheel revolution click.  Since PCB #1 and #2 have
+reversed genders, the present wiring only plugs into PCB #2. When PCB #2 is used, there is no
+signal on IC2 pin 8.

 */
- // go through the four channels of the digital analog converter:
-  for (int channel = 0; channel < 4; channel++)
+ // Only use motor control:
+  int channel = 0;
   {
+      /* Observed behavior with manual throttle, no load (May 10, 2013, TCF)
+      0.831 V at rest       52 counts
+      1.20 V: nothing       75
+      1.27 V: just starting 79
+      1.40 V: slow, steady  87
+      1.50 V: brisker       94
+      3.63 V: max          227 counts
+
+      255 counts = 4.08 V
+
+      */
       // change the voltage on this channel from min to max:
-      for (int level = 0; level < 255; level++)
+      for (int level = 70; level < 200; level+=4)
       {
         DAC_Write(channel, level);
-        delay(100);
+        Serial.print(SpeedCyclometer_degPs); Serial.print(", ");
+        Serial.println(level);
+        delay(3000);
       }
       // wait a second at the top:
       delay(1000);
       // change the voltage on this channel from max to min:
-      for (int level = 0; level < 255; level++)
+      for (int level = 200; level > 70; level-=4)
       {
-        DAC_Write(channel, 255 - level);
-        delay(100);
+        DAC_Write(channel, level);
+        Serial.print(SpeedCyclometer_degPs); Serial.print(", ");
+        Serial.println(level);
+        delay(3000);
       }
  }


documentation finished - hopefully

documentation finished - hopefully

--- Arduino_codeline/fairytale23/fairytale23.ino
+++ Arduino_codeline/fairytale23/fairytale23.ino
@@ -217,6 +217,9 @@

       #define NFCTRACKDB   enables the use of the TrackDB to get the directiry for a tag

+      #define ALBUMNFC     enables a special file albumnfc.tdb in which all album <-> nfc
+                           connections are stored - additional to the TrackDb files
+
       #define RESUMELAST   enables the option to resume last played album upon startup.
                            This is achieved via a file in the TrackDB and works without
                            a tag but uses the pause/resume button instead
@@ -256,6 +259,10 @@
 // to use the Adafruit NFC library to get the Tag UID and retrieve the directory from the trackDb
 // uncomment the following line.
 #define NFCTRACKDB 1
+
+// uncomment to enable a special file albumnfc.tdb in which all album <-> nfc
+// connections are stored - additional to the TrackDb files
+//define ALBUMNFC 1

 // uncomment the next line to enable resuming the last played album on switch on
 // this is achieved via a special file on the SD card and works without a tag but uses the pause/resume button instead
@@ -350,10 +357,10 @@
 //            V    AA     AA  RR   RR
 //
 // mp3 player variables
-char plrCurrentFolder[]     = "system00";                // directory containing the currently played tracks - system00 is the system message directory
-char filename[]             = "/system00/track001.mp3";  // path and filename of the track to play - we start with the welcome track
+char plrCurrentFolder[]     = "system00";                // directory containing the currently played tracks
+char filename[]             = "/system00/track001.mp3";  // path and filename of the track to play
 byte firstTrackToPlay       = 1;                         // the track number to play (used for the loop)
-char nextTrackToPlay        = 1;                         // the track number to play next (can also be the previos number or a -1 in case of an error)
+char nextTrackToPlay        = 1;                         // the track number to play next (or -1 in case of an error)

 // file to hold the last played album (aka directory) name - from here we may retrieve other data from the trackDb
@@ -364,10 +371,13 @@

 // trackDb on the SD card - this is where we store the NFC TAG <-> Directory connection and the track to start playback with
 #ifdef NFCTRACKDB
-  const char trackDbDir[]   = "/trackdb0";               // where do we store the files for each album
-  const char trackDbFile[]  = "/trackdb0/albumnfc.txt";  // path to the file that holds the connection between an NFC tag UID and the corresponding directory / file name
-  char tDirFile[sizeof(trackDbFile)];                      // a char array to hold the path to the file with track and directory infos (name is shared with directory name plus .txt
-  char trackDbEntry[35];                                   // will hold a nfc <-> album info connection in the form of [NFC Tag UID]:[album]:[Track] e.g.: 43322634231761291:larsrent:1
+  const char trackDbDir[]   = "/trackdb0";     // where do we store the files for each album
+  #ifdef ALBUMNFC
+    // a special file that additionally holds the connection between an NFC tag UID and the corresponding directory
+    const char albumNfcFile[]  = "/trackdb0/albumnfc.tdb";
+  #endif
+  char trackDbFile[23];                      // holds the path to the file with track and directory infos - name is shared with directory name plus .txt
+  char trackDbEntry[35];                  // will hold a nfc <-> album info connection in the form of [NFC Tag UID]:[album]:[Track] e.g.: 43322634231761291:larsrent:1

   // NFC Tag data
   byte uid[] = { 0, 0, 0, 0, 0, 0, 0 };    // Buffer to store the returned UID
@@ -1181,41 +1191,49 @@
   #ifdef DEBUG
     Serial.print(F("saving nfc <-> album: "));Serial.println(trackDbEntry);
   #endif
-  /*
-  // FIRST write the trackDbFile --> ALBUMNFC.TXT
-  File file = SD.open(trackDbFile, FILE_WRITE);
+  #ifdef ALBUMNFC
+    // FIRST write the AlbumNFC file  --> ALBUMNFC.TDB
+    File file = SD.open(albumNfcFile, FILE_WRITE);
+    bytesWritten = file.write(trackDbEntry, sizeof(trackDbEntry));
+    file.close();                                   // and make sure everything is clean and save
+    if (bytesWritten == sizeof(trackDbEntry)) {
+      #ifdef DEBUG
+        Serial.print(F(" ok. wrote "));Serial.print(bytesWritten);Serial.print(F(" byte(s) to "));Serial.println(albumNfcFile);
+      #endif
+      success = true;
+    } else {
+      #ifdef DEBUG
+        Serial.print(F("  error writing "));Serial.println(albumNfcFile);
+      #endif
+      digitalWrite(warnLedPin, HIGH);
+    }
+  #endif
+
+  // SECOND write the TrackDb-File --> e.g. larsrent.txt
+  memset(trackDbFile, 0, sizeof(trackDbFile));          // make sure var to hold path to track db file is empty
+  strcat(trackDbFile, trackDbDir);                   // add the trackDb Directory to the
+  strcat(trackDbFile, "/");                          // a /
+  strcat(trackDbFile, plrCurrentFolder);             // and the filename
+  strcat(trackDbFile, ".txt");                       // plus of course a txt extension
+  SD.remove(trackDbFile);                            // we want the file to be empty prior writing directory and track to it, so we remove it
+
+  #ifdef ALBUMNFC
+    file = SD.open(trackDbFile, FILE_WRITE);         // used in case the albumnfc.tdb file is written first
+  #endif
+  #ifndef ALBUMNFC
+    File file = SD.open(trackDbFile, FILE_WRITE);    // used in case we only write the TrackDB files
+  #endif
+
   bytesWritten = file.write(trackDbEntry, sizeof(trackDbEntry));
   file.close();                                   // and make sure everything is clean and save
   if (bytesWritten == sizeof(trackDbEntry)) {
     #ifdef DEBUG
       Serial.print(F(" ok. wrote "));Serial.print(bytesWritten);Serial.print(F(" byte(s) to "));Serial.println(trackDbFile);
     #endif
-    success = true;
+    success = false;
   } else {
     #ifdef DEBUG
       Serial.print(F("  error writing "));Serial.println(trackDbFile);
-    #endif
-    digitalWrite(warnLedPin, HIGH);
-  }
-  */
-  // SECOND write the tDirFile --> e.g. larsrent.txt
-  memset(tDirFile, 0, sizeof(tDirFile));          // make sure var to hold path to track db file is empty
-  strcat(tDirFile, trackDbDir);                   // add the trackDb Directory to the
-  strcat(tDirFile, "/");                          // a /
-  strcat(tDirFile, plrCurrentFolder);             // and the filename
-  strcat(tDirFile, ".txt");                       // plus of course a txt extension
-  SD.remove(tDirFile);                            // we want the file to be empty prior writing directory and track to it, so we remove it
-  File file = SD.open(tDirFile, FILE_WRITE);      // and now we open / create it
-  bytesWritten = file.write(trackDbEntry, sizeof(trackDbEntry));
-  file.close();                                   // and make sure everything is clean and save
-  if (bytesWritten == sizeof(trackDbEntry)) {
-    #ifdef DEBUG
-      Serial.print(F(" ok. wrote "));Serial.print(bytesWritten);Serial.print(F(" byte(s) to "));Serial.println(tDirFile);
-    #endif
-    success = false;
-  } else {
-    #ifdef DEBUG
-      Serial.print(F("  error writing "));Serial.println(tDirFile);
     #endif
     digitalWrite(warnLedPin, HIGH);
     success = false;


extra debugging to the serial monitor

extra debugging to the serial monitor

--- oven-controller/src/menu_test/menu_test.ino
+++ oven-controller/src/menu_test/menu_test.ino
@@ -129,8 +129,8 @@
 int curstatus = OFF;

 // current temperature in Fahrenheit
-int curtemp = 32;
-int prevtemp = 32;
+int curtemp = -1;
+int prevtemp = -1;
 int curtempflag = 0;
 int tempThreshold = 5; // determines whether one or two heaters on/off
 int thermStatus[5] = {0};
@@ -161,7 +161,10 @@

 void setup(void) {

+
   Serial.begin(9600);
+  Serial.println("\nENTERING SETUP\n");
+  pinMode(LED_BUILTIN, OUTPUT);

   // Our supplier changed the 1.8" display slightly after Jan 10, 2012
   // so that the alignment of the TFT had to be shifted by a few pixels
@@ -254,6 +257,12 @@
 }

 void loop() {
+  Serial.println("\nENTERING LOOP\n");
+    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
+  delay(1000);                       // wait for a second
+  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
+  delay(1000);                       // wait for a second
+

   // check start button
   curstatus = CheckStartButton();
@@ -308,6 +317,17 @@
   // Serial.print(curtemp);
   // Serial.print(" ");
   // curtemp = curtemp / numActiveThermocouples;
+  Serial.println("thermocouple1.readFarenheit()");
+  Serial.println(thermocouple1.readFarenheit());
+  Serial.println("thermocouple2.readFarenheit()");
+  Serial.println(thermocouple2.readFarenheit());
+  Serial.println("thermocouple3.readFarenheit()");
+  Serial.println(thermocouple3.readFarenheit());
+  Serial.println("thermocouple4.readFarenheit()");
+  Serial.println(thermocouple4.readFarenheit());
+  Serial.println("thermocouple5.readFarenheit()");
+  Serial.println(thermocouple5.readFarenheit());
+  Serial.println("curtemp");
   Serial.println(curtemp);

   // if the temp has incremented, update temp


also fix LED reverse logic in manual button toggle

--- examples/SONOFF/SONOFF.ino
+++ examples/SONOFF/SONOFF.ino
@@ -263,7 +263,7 @@
     {
         currentRelayState= RELAY_STATE_ON;

-        digitalWrite(LED, HIGH);
+        digitalWrite(LED, LOW);
         digitalWrite(RELAY, HIGH);
         if(bootMode == BOOT_MODE_MQTT){
             char tmpChar = RELAY_STATE_ON;
@@ -274,7 +274,7 @@
     {
         currentRelayState = RELAY_STATE_OFF;

-        digitalWrite(LED, LOW);
+        digitalWrite(LED, HIGH);
         digitalWrite(RELAY, LOW);
         if(bootMode == BOOT_MODE_MQTT){
             char tmpChar = RELAY_STATE_OFF;