adding I2c comms to slave and report from slave

--- Lifter/Lifter.ino
+++ Lifter/Lifter.ino
@@ -1,5 +1,6 @@
 #include <AccelStepper.h>
 #include <Servo.h>
+#include <Wire.h>

 // #defines are macros for faster pin access than built-in digitalWrite().
 //  *http://masteringarduino.blogspot.com/2013/10/fastest-and-smallest-digitalread-and.html
@@ -24,11 +25,12 @@

 boolean DEBUG = false;                      // send stuff to serial monitor for testing

+const byte slaveAdr = 0x002;                // I2c "Wire" address for slave mcu
 const byte ledPin = 13;                     // on board LED
-const byte holdPinArm = 12;                 // enable pins for stepper drivers
+const byte holdPinArm = 12;                 // enable pins for stepper drivers: arm, lift
 const byte holdPinLift = 11;                // HIGH->disable, LOW->enables
 const byte SERV1PIN = 10;                   // servo control pin
-const byte PINST1_ST = 6;
+const byte PINST1_ST = 6;                   // step & direction pins going to driver boards
 const byte PINST1_DIR = 7;
 const byte PINST2_ST = 4;
 const byte PINST2_DIR = 5;
@@ -41,14 +43,16 @@
 const byte CARD_PIN = A1;                   // Analog prox. for 'card on-board'
 const byte flutterConst = 36;               // analog sensors must change more than this to update serial monitor
 const int cardThickness = 52;               // calculated 141 steps to lift a card. 608steps/turn
-                                            // (20 turns per 86 cards, 141.3953 ...
+                                            // (20 turns per 86 cards, 141.3953
+const byte i2cSDA = A4;                      // i2c serial bus pins
+const byte i2cSCL = A5;
 const int proxSense2 = 620;                 // threshold for OPB606A showing a card riding on fan housing
 const int proxSense3 = 900;                 // below this a passenger card is still engaged
 const int liftSenseTop = 740;               // above threshold nothing is close to face of OPB606A
 const int HOLDms = 800;                     // this long to get to extremes of servo travel, then relax
-const long int hoverArmPos = 15;            // pick up postion after zeroing against armLimit
-const long int firstArmPos = 120;           // experimentally determined drop-off position
-const long int secondArmPos = 220;          // 2nd drop (less frequent) and max Arm travel
+const long hoverArmPos = 15;            // pick up postion after zeroing against armLimit
+const long firstArmPos = 120;           // experimentally determined drop-off position
+const long secondArmPos = 220;          // 2nd drop (less frequent) and max Arm travel
 const byte closeAng = 115;                  // servo position: closest approach to card-stack
 const byte openAng = 158;                   // servo postion:
 const byte bumpBinSteps = 36;               // for jiggle when grabTryCount goes up.
@@ -58,26 +62,29 @@
 int newAnalog2 = 0;                         // hold value from the CARD_PIN sensor
 int oldAnalog1 = 0;                         // discover changes in the PROX_PIN sensor
 int oldAnalog2 = 0;                         // discover changes in the CARD_PIN sensor
-long int destinationArmPos = firstArmPos;   // arm drop-off point (first or second)
+long destinationArmPos = firstArmPos;   // arm drop-off point (first or second)
 byte grabTryCount = 0;                      // bump the bin to help the grabber
 byte oldServoPos = servoPosition;           // for tracking changes is servo. Are they continuous?
-String inputString = "";
+String inputString = "";                    // serial communication string
 boolean LOADED = false;
 boolean BACKINGOFF = false;
-byte restServoPos = servoPosition;      // used for moving servo back off its maximum travel on either end;
-                                        //set in fanDown()
-boolean stressedServo = false;          // flag for above
-unsigned long timeStart = 0;
+byte restServoPos = servoPosition;          // used for moving servo back off its maximum travel on either end;
+                                            //set in fanDown()
+boolean stressedServo = false;              // flag for above
+unsigned long timeStart = 0;
 unsigned long timeCurrent = 0;
-boolean UPDATE = true;                  // flag for printing updated info to serial monitor
-unsigned long currentTime = millis();   // I can't seem to declare local variables
-byte currentServoPos = 0;
-
+boolean UPDATE = true;                      // flag for printing updated info to serial monitor
+unsigned long currentTime = millis();       // I can't seem to declare local variables
+byte currentServoPos = 0;
+String commandChar = "";                      // single letter command parsed from Serial input
+long destInt = 0;                       // serial connection sends stepper position for slider carriage as long - this is sent via I2C to slave mcu
+boolean cmdGood = false;                    // most recent I2C command will be executed?
+long movingToPos = 0;                   // report via I2C of where the slave is moving
 AccelStepper stepperArm(AccelStepper::DRIVER, PINST1_ST, PINST1_DIR);
 AccelStepper stepperLift(AccelStepper::DRIVER, PINST2_ST, PINST2_DIR);

 const long int liftUpToTop = -200000;     // arbitrary rise until limit switch hit.
-long int liftBackOff = 500;              // steps to back off the switch; zero is limit-switch position
+long liftBackOff = 500;               // steps to back off the switch; zero is limit-switch position

 Servo myserv;

@@ -86,7 +93,8 @@

 void setup()
-{
+{
+    Wire.begin();
     myserv.attach(SERV1PIN);
     myserv.write(servoPosition);

@@ -103,7 +111,7 @@
     pinAsInput(PROX_PIN);

     attachInterrupt(0, limitLift, CHANGE);          // int.0 on pin 2
-    attachInterrupt(1, limitArm, CHANGE);          // int.1 on pin 3
+    attachInterrupt(1, limitArm, CHANGE);           // int.1 on pin 3

     digitalLow(holdPinArm);                 // HIGH disables driver, LOW enables
     digitalLow(holdPinLift);                // HIGH disables driver, LOW enables
@@ -206,33 +214,33 @@
     // first character sent switches us into LOADED mode
     // 97="a", 98="b", 99="c", 100="d", 120="x"
     if (Serial.available() > 0) {
-      inputString = String(Serial.read());
+      commandChar, destInt = parseSerial();
       if (!LOADED) {
         LOADED = true;
         stepperLift.setCurrentPosition(0);
         UPDATE = true;
       }
       Serial.println("Rx: " + inputString);
-      if (inputString == "97") {              // 'a' hover over input stack
+      if (commandChar == "a") {              // 'a' hover over input stack
         stepperArm.moveTo(hoverArmPos);
         stepperLift.moveTo(stepperLift.currentPosition() - 20);
       }
-      else if (inputString == "98") {        // 'b' ID'd pile
+      else if (commandChar == "b") {        // 'b' ID'd pile
         stepperArm.moveTo(firstArmPos);
         destinationArmPos = firstArmPos;
       }
-      else if (inputString == "99") {        // 'c' unidentified pile
+      else if (commandChar == "c") {        // 'c' unidentified pile
         stepperArm.moveTo(secondArmPos);
         destinationArmPos = secondArmPos;
       }
-      else if (inputString == "100") {       // 'd' Reset into loading mode until another character sent
+      else if (commandChar == "d") {       // 'd' Reset into loading mode until another character sent
         stepperArm.moveTo(firstArmPos);
         destinationArmPos = firstArmPos;
         LOADED = false;
       }
-      else if (inputString == "120") {
-        DEBUG = !DEBUG;
-        Serial.println("DEBUG <x> is: " + String(DEBUG));
+      else if (commandChar == "x") {
+        cmdGood, movingToPos = sendtoSlave(destInt);
+        Serial.println("slave Mcu sent: " + String(destInt));
       }
       inputString = "";
     }
@@ -246,6 +254,65 @@
 // interrupt function on pin 3, int.1
 void limitArm() {
   armState = digitalState(LIMIT_ARM);
+}
+
+
+long sendtoSlave(long int destiny) {
+  long int accumulator = 0;
+  boolean readyNow = true;
+  Wire.requestFrom(slaveAdr, 6);    // request 6 bytes from slave device #2
+  unsigned long int markstart = millis();
+  // pause for slave to make Wire.available() == true, but time-out if none
+  while (!Wire.available() && readyNow){
+    if ((millis() - markstart) > 700){
+      Serial.println("ERROR in I2C slave");
+      Serial.println("timeout at: " + String((millis() - markstart)) + " ms");
+      readyNow = false;
+    }
+  }
+  // initial state indicator characters r & d
+  Serial.println("from request to ready-to-send: " + String((millis() - markstart)) + " ms");
+  if (readyNow) {
+    readyNow = false;
+    char c = Wire.read();
+    if ((Wire.read() == 'd') && (c == 'r'))
+        readyNow = true;
+  }
+
+  // get the rest of slave's transmission, turn it into longint
+  if ((Wire.available()) && (Wire.available() <= 4){
+    accumulator = Wire.read();
+    accumulator |= Wire.read() << 8;
+    accumulator |= Wire.read() << 16;
+    accumulator |= Wire.read() << 24;
+  }
+
+  // if slave is ready for new destination, transmit to it
+  if (readyNow) {
+    Wire.beginTransmission(slaveAdr);   // I2c address set globally
+    byte* pInt=(byte*) &destiny;
+    Wire.send(pInt,sizeof(destiny));
+  }
+  readyNess = readyNow;
+  return accumulator;
+}
+
+
+byte, long parseSerial() {
+  // return the waiting contents of the Serial buffer
+  char cmdCode = Serial.read();
+  if (cmdCode == '\n')
+    return 'q', 0
+  long int bigNum = Serial.parseInt();
+  if ((bigNum == '\n') || (!bignum))
+    return cmdCode, 0
+  if (Serial.peek() != '\n'){
+    Serial.print("Warning: extra commands to process")
+    return parseSerial();
+  }
+  // clear out the remaining newline char
+  Serial.read();
+  return cmdCode, bigNum;
 }


Add support for writing to a TFT display

--- Event_Printer/Event_Printer.ino
+++ Event_Printer/Event_Printer.ino
@@ -4,9 +4,13 @@
 #include "BMW_R1200_GS_K25_CAN_Bus_Defines.h"
 #include "BMW_R1200_GS_K25_State.h"

+#include <Adafruit_GFX.h>    // Core graphics library
+#include <Adafruit_ST7735.h> // Hardware-specific library
+
 /* Compile time Flags */
 #define DEBUG 0
-#define PRINT_TO_SERIAL_CONSOLE 1
+#define PRINT_TO_SERIAL_CONSOLE 0
+#define PRINT_TO_TFT 1

 /* Helper Macros */
 #define HI_NIBBLE(b) (((b) >> 4) & 0x0F)
@@ -21,109 +25,143 @@
     #define DEBUG_PRINT_LN(...)
 #endif

+/* TFT Pin Defines */
+#define TFT_CS     10
+#define TFT_RST    9
+#define TFT_DC     8
+
 /* Globals */
 MCP_CAN CAN(9);
 K25_State_t motorcycle_state;
+Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

 /* Arduino Functions */
 void setup()
 {
-    Serial.begin(115200);
-    setup_CAN_Bus_Filters();
+  Serial.begin(115200);
+  setup_CAN_Bus_Filters();
+  init_display();
 }

 void loop()
 {
-    process_CAN_Messages();
+  process_CAN_Messages();
+
+  print_status();
+}
+
+void init_display()
+{
+  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
+  tft.setRotation(1); // rotate 90 degrees
+
+  tft.fillScreen(ST7735_BLACK);
+}
+
+void print_status()
+{
+  String text = "";
+
+  text += "Throttle: ";
+  text += motorcycle_state.throttle_position;
+  text += "%\n";
+
+  text += "Heated Grips: ";
+  if ( motorcycle_state.heated_grips == K25_Heated_Grips_State_off ) text += "OFF";
+  else if ( motorcycle_state.heated_grips == K25_Heated_Grips_State_low ) text += "LOW";
+  else if ( motorcycle_state.heated_grips == K25_Heated_Grips_State_high ) text += "HIGH";
+  else text += "Unknown";
+  text += "\n";
+
+  text += "Turn Signals: ";
+  if ( motorcycle_state.turn_signals == K25_Turn_Signals_State_off ) text += "OFF";
+  else if ( motorcycle_state.turn_signals == K25_Turn_Signals_State_left ) text += "LEFT";
+  else if ( motorcycle_state.turn_signals == K25_Turn_Signals_State_right ) text += "RIGHT";
+  else if ( motorcycle_state.turn_signals == K25_Turn_Signals_State_both ) text += "HAZARDS";
+  else text += "Unknown";
+  text += "\n";
+
+  text += "High Beam: ";
+  if ( motorcycle_state.high_beam == K25_High_Beam_State_off ) text += "OFF";
+  else if ( motorcycle_state.high_beam == K25_High_Beam_State_on ) text += "ON";
+  else text += "Unknown";
+  text += "\n";
+
+  /* INFO BUTTON CURRENTLY NOT WORKING
+  text += "Info Button: ";
+  if ( motorcycle_state.info_button == K25_Info_Button_State_short_press ) text += "SHORT";
+  else if ( motorcycle_state.info_button == K25_Info_Button_State_long_press ) text += "LONG";
+  else text += "Unknown";
+  text += "\n";
+  */
+
+  text += "Clutch: ";
+  if ( motorcycle_state.clutch == K25_Clutch_Lever_State_out ) text += "OUT";
+  else if ( motorcycle_state.clutch == K25_Clutch_Lever_State_in ) text += "IN";
+  else text += "Unknown";
+  text += "\n";
+
+  text += "Brakes: ";
+  if ( motorcycle_state.brake_levers == K25_Brake_Lever_State_none ) text += "NONE";
+  else if ( motorcycle_state.brake_levers == K25_Brake_Lever_State_front ) text += "FRONT";
+  else if ( motorcycle_state.brake_levers == K25_Brake_Lever_State_rear ) text += "REAR";
+  else text += "Unknown";
+  text += "\n";
+
+  text += "ABS: ";
+  if ( motorcycle_state.abs_system == K25_ABS_State_off ) text += "OFF";
+  else if ( motorcycle_state.abs_system == K25_ABS_State_on ) text += "ON";
+  else text += "Unknown";
+  text += "\n";
+
+  text += "ALS: ";
+  if ( motorcycle_state.als == K25_ALS_State_dark ) text += "DARK";
+  else if ( motorcycle_state.als == K25_ALS_State_light ) text += "LIGHT";
+  else text += "Unknown";
+  text += "\n";
+
 #if PRINT_TO_SERIAL_CONSOLE
-    print_motorcycle_state();
+  Serial.println(text);
 #endif
-}
-
-void print_motorcycle_state()
-{
-    Serial.print("Throttle Position: ");
-    Serial.print(motorcycle_state.throttle_position, DEC);
-    Serial.println();
-
-    Serial.print("Heated Grips: ");
-    if( motorcycle_state.heated_grips == K25_Heated_Grips_State_off ) Serial.print("OFF");
-    else if( motorcycle_state.heated_grips == K25_Heated_Grips_State_low ) Serial.print("LOW");
-    else if( motorcycle_state.heated_grips == K25_Heated_Grips_State_high ) Serial.print("HIGH");
-    else Serial.print("Unknown");
-    Serial.println();
-
-    Serial.print("Turn Signals: ");
-    if( motorcycle_state.turn_signals == K25_Turn_Signals_State_off ) Serial.print("OFF");
-    else if( motorcycle_state.turn_signals == K25_Turn_Signals_State_left ) Serial.print("LEFT");
-    else if( motorcycle_state.turn_signals == K25_Turn_Signals_State_right ) Serial.print("RIGHT");
-    else if( motorcycle_state.turn_signals == K25_Turn_Signals_State_both ) Serial.print("HAZARDS");
-    else Serial.print("Unknown");
-    Serial.println();
-
-    Serial.print("High Beam: ");
-    if( motorcycle_state.high_beam == K25_High_Beam_State_off ) Serial.print("OFF");
-    else if( motorcycle_state.high_beam == K25_High_Beam_State_on ) Serial.print("ON");
-    else Serial.print("Unknown");
-    Serial.println();
-
-    Serial.print("Info Button: ");
-    if( motorcycle_state.info_button == K25_Info_Button_State_short_press ) Serial.print("SHORT");
-    else if( motorcycle_state.info_button == K25_Info_Button_State_long_press ) Serial.print("LONG");
-    else Serial.print("Unknown");
-    Serial.println();
-
-    Serial.print("Clutch: ");
-    if( motorcycle_state.clutch == K25_Clutch_Lever_State_out ) Serial.print("OUT");
-    else if( motorcycle_state.clutch == K25_Clutch_Lever_State_in ) Serial.print("IN");
-    else Serial.print("Unknown");
-    Serial.println();
-
-    Serial.print("Brakes: ");
-    if( motorcycle_state.brake_levers == K25_Brake_Lever_State_none ) Serial.print("NONE");
-    else if( motorcycle_state.brake_levers == K25_Brake_Lever_State_front ) Serial.print("FRONT");
-    else if( motorcycle_state.brake_levers == K25_Brake_Lever_State_rear ) Serial.print("REAR");
-    else Serial.print("Unknown");
-    Serial.println();
-
-    Serial.print("ABS: ");
-    if( motorcycle_state.abs_system == K25_ABS_State_off ) Serial.print("OFF");
-    else if( motorcycle_state.abs_system == K25_ABS_State_on ) Serial.print("ON");
-    else Serial.print("Unknown");
-    Serial.println();
-
-    Serial.print("ALS: ");
-    if( motorcycle_state.als == K25_ALS_State_dark ) Serial.print("DARK");
-    else if( motorcycle_state.als == K25_ALS_State_light ) Serial.print("LIGHT");
-    else Serial.print("Unknown");
-    Serial.println();
+
+#if PRINT_TO_TFT
+  tft.fillScreen(ST7735_BLACK);
+  draw_text(&text, ST7735_WHITE);
+#endif
+}
+
+void draw_text(String *text, uint16_t color) {
+  tft.setCursor(0, 0);
+  tft.setTextColor(color);
+  tft.setTextWrap(true);
+  tft.print(text->c_str());
 }

 void setup_CAN_Bus_Filters()
 {
-    while(CAN_OK != CAN.begin(CAN_500KBPS)){
-        Serial.println("Failed to initialize CAN");
-        Serial.println("Retrying..");
-        delay(100);
-    }
-
-    Serial.println("Starting to initialize CAN");
-
-    // Set filter masks
-    CAN.init_Mask(0, 0, 0xfff);
-    CAN.init_Mask(1, 0, 0xfff);
-
-    // Set filters
-    CAN.init_Filt(0, 0, MSG_ID_BMSK_Control_Module);
-    CAN.init_Filt(1, 0, MSG_ID_BMSK_Control_Module_2);
-    CAN.init_Filt(2, 0, MSG_ID_ZFE_Control_Module);
-    CAN.init_Filt(3, 0, MSG_ID_ZFE_Control_Module_2);
-    CAN.init_Filt(4, 0, MSG_ID_ABS_Control_Module);
-    CAN.init_Filt(5, 0, MSG_ID_ABS_Control_Module_2);
-    CAN.init_Filt(6, 0, MSG_ID_Instrument_Cluster);
-    CAN.init_Filt(7, 0, MSG_ID_Instrument_Cluster_2);
-
-    Serial.println("CAN Initialized");
+  while (CAN_OK != CAN.begin(CAN_500KBPS)) {
+    Serial.println("Failed to initialize CAN");
+    Serial.println("Retrying..");
+    delay(100);
+  }
+
+  Serial.println("Starting to initialize CAN");
+
+  // Set filter masks
+  CAN.init_Mask(0, 0, 0xfff);
+  CAN.init_Mask(1, 0, 0xfff);
+
+  // Set filters
+  CAN.init_Filt(0, 0, MSG_ID_BMSK_Control_Module);
+  CAN.init_Filt(1, 0, MSG_ID_BMSK_Control_Module_2);
+  CAN.init_Filt(2, 0, MSG_ID_ZFE_Control_Module);
+  CAN.init_Filt(3, 0, MSG_ID_ZFE_Control_Module_2);
+  CAN.init_Filt(4, 0, MSG_ID_ABS_Control_Module);
+  CAN.init_Filt(5, 0, MSG_ID_ABS_Control_Module_2);
+  CAN.init_Filt(6, 0, MSG_ID_Instrument_Cluster);
+  CAN.init_Filt(7, 0, MSG_ID_Instrument_Cluster_2);
+
+  Serial.println("CAN Initialized");
 }

 void process_CAN_Messages()


changed PA default to 10

changed PA default to 10

--- PulsePatch_01/PulsePatch_01.ino
+++ PulsePatch_01/PulsePatch_01.ino
@@ -25,8 +25,8 @@
 char readPointer;
 char writePointer;
 char ovfCounter;
-int rAmp = 20;
-int irAmp = 20;
+int rAmp = 10;
+int irAmp = 10;

 //  TESTING
 unsigned int thisTestTime;


LowLevel routine uses micros again, much more responsive now

--- Elcano_C2_LowLevel/Elcano_C2_LowLevel.ino
+++ Elcano_C2_LowLevel/Elcano_C2_LowLevel.ino
@@ -19,7 +19,7 @@
 #define s7s Serial2
 Servo STEER_SERVO;

-#define LOOP_TIME_MS 400
+#define LOOP_TIME_US 400
 #define ERROR_HISTORY 20 //number of errors to accumulate
 #define TEN_SECONDS_IN_MICROS 10000000

@@ -78,9 +78,9 @@
 int max_rc = MAX_RC;
 int mid = MIDDLE;
 int min_rc = MIN_RC;
-#define LED_PIN_OUT 16
+
 //==========================================================================================
-void ISR_TURN_rise() {
+void ISR_TURN_rise(){
   noInterrupts();
   ProcessRiseOfINT(RC_TURN);
   attachInterrupt(digitalPinToInterrupt(IRPT_TURN), ISR_TURN_fall, FALLING);
@@ -264,7 +264,7 @@
   // Save start time for performance report.
   unsigned long startTime = micros();
   // Get the next loop start time.
-  unsigned long nextTime = startTime + LOOP_TIME_MS;
+  unsigned long nextTime = startTime + LOOP_TIME_US;

   startCapturingRCState();

@@ -272,35 +272,40 @@
   //  PrintDone();

   while (micros() < nextTime &&
-         ~((RC_Done[RC_ESTP] == 1) && (RC_Done[RC_GO] == 1) && (RC_Done[RC_TURN] == 1) && (RC_Done[RC_RDR])))
+         ~((RC_Done[RC_ESTP] == 1) && (RC_Done[RC_GO] == 1) && (RC_Done[RC_TURN] == 1) && (RC_Done[RC_RDR] == 1)))
+  {
     ;  //wait
-
+  }
   // got data;
   for (int i = 0; i < 8; i++)
     local_results[i] = RC_elapsed[i];
   //Print7(false, local_results);
-
+  //Serial.println("Processing RC data...");
   byte automate = processRC(local_results);
   if (automate == 0x01) //remember to tell Pat to fix this, was = instead of ==
+  {
+    //Serial.println("Processing high-level data");
     processHighLevel(&Results);
+  }
   //    Print7( true, local_results);

-  Results.Clear();
-  Results.kind = MSG_SENSOR;
-  Results.angle_deg = TurnAngle_degx10() / 10;
+
+  //Serial.println(nextTime); //Old sanity check line; testing new pin output sanity check.
+  //Serial.println("Clearing Results");
+//  Results.Clear();
+//  Results.kind = MSG_SENSOR;
+//  Results.angle_deg = TurnAngle_degx10() / 10;
   //show_speed (&Results);

   // Report how long the loop took.
-  unsigned long endTime = micros();
-  unsigned long elapsedTime = endTime - startTime;
-//  Serial.print("loop elapsed time = ");
-//  Serial.println(elapsedTime);
+
+

   //LogData(local_results, &Results);  // data for spreadsheet

-  calibrationTime_ms += LOOP_TIME_MS;
-  straightTime_ms = (steer_control == STRAIGHT_TURN_OUT) ? straightTime_ms + LOOP_TIME_MS : 0;
-  stoppedTime_ms = (throttle_control == MIN_ACC_OUT) ? stoppedTime_ms + LOOP_TIME_MS : 0;
+  calibrationTime_ms += LOOP_TIME_US;
+  straightTime_ms = (steer_control == STRAIGHT_TURN_OUT) ? straightTime_ms + LOOP_TIME_US : 0;
+  stoppedTime_ms = (throttle_control == MIN_ACC_OUT) ? stoppedTime_ms + LOOP_TIME_US : 0;
   if (calibrationTime_ms > 40000 && straightTime_ms > 3000 && stoppedTime_ms > 3000)
   {
     //       int oldBrake = brake_control;
@@ -309,7 +314,11 @@
     //       brake(oldBrake);       // restore brake state
     calibrationTime_ms = 0;
   }
-
+
+  unsigned long endTime = micros();
+  // unsigned long elapsedTime = endTime - startTime;
+  // Serial.print("loop elapsed time = ");
+  // Serial.println(elapsedTime);
   // Did we spend long enough in the loop that we should immediately
   // start the next pass?
   if (nextTime > endTime) {
@@ -317,7 +326,7 @@
     delay(nextTime - endTime);
   } else {
     // Yes, we overran the expected loop interval. Extend the time.
-    nextTime = endTime + 1000 * LOOP_TIME_MS;
+    nextTime = endTime + LOOP_TIME_US;
   }
 }
 /*---------------------------------------------------------------------------------------*/
@@ -415,17 +424,59 @@

 /*---------------------------------------------------------------------------------------*/
 //circleRoutine
-void circleRoutine(unsigned long seconds, unsigned long &results) {
-  results = HIGH;
+void circleRoutine(unsigned long seconds, unsigned long &rcAuto) {
+  rcAuto = HIGH;

   steer(LEFT_TURN_OUT);
   delay(1000);
   seconds = seconds * 1000;
   unsigned long loopTime = millis();
   while (millis() < (loopTime + seconds)) {
-    moveVehicle(128);
-  }
-  results = LOW;
+    moveVehicle(112);
+  }
+  rcAuto = LOW;
+}
+/*---------------------------------------------------------------------------------------*/
+//squareRoutine
+void squareRoutine(unsigned long sides, unsigned long &rcAuto) {
+  Serial.println("Starting square routine...");
+  rcAuto = HIGH;
+  long straightSpeed = 2750;        //mmPs
+  long turnSpeed = 1800;            //mmPs
+  sides = sides * 1000;             //convert side length to mm
+  unsigned long sideSec = sides / straightSpeed;  //calculate seconds per side at set speed
+  sideSec = sideSec * 1000;         //convert to ms
+  unsigned long loopTime;           //start time of while loops for throttle
+  float turnDist = TURN_RADIUS_CM * PI / 2 * 10; //turnDist == 1/4 turn circumference in mm
+  unsigned long turnSec = (long)turnDist / turnSpeed * 1000; //turnSec == time for 90-degree turn at 1250 mmPs
+  for(int i = 0; i < 4; i++){
+    //steer(LEFT_TURN_OUT);
+    steer(STRAIGHT_TURN_OUT);
+    brake(MAX_BRAKE_OUT);
+    delay(1000);
+    brake(MIN_BRAKE_OUT);
+
+    loopTime = millis();
+    while (millis() < (loopTime + sideSec)) {
+      moveVehicle(112);
+    }
+
+    steer(LEFT_TURN_OUT);
+    brake(MAX_BRAKE_OUT);
+    delay(1000);
+
+    brake(MIN_BRAKE_OUT);
+
+
+    loopTime = millis();
+    while (millis() < (loopTime + turnSec)) {
+      moveVehicle(96);
+    }
+  }
+  brake(MAX_BRAKE_OUT);
+  delay(1000);
+  brake(MIN_BRAKE_OUT);
+  rcAuto = LOW;
 }
 /*---------------------------------------------------------------------------------------*/
 void startCapturingRCState(){
@@ -491,12 +542,11 @@
     will be used for emergency stop. D38 */
   results[RC_ESTP] = (results[RC_ESTP] > MIDDLE ? HIGH : LOW);

-  if (results[RC_ESTP] == HIGH)
-  {
+  if (results[RC_ESTP] == HIGH){
+    Serial.println("Exiting processRC due to E-stop.");
     E_Stop();  // already done at interrupt level
     if ((results[RC_AUTO] == LOW)  && (NUMBER_CHANNELS > 5)) // under RC control
       ;//steer(results[RC_TURN]);
-    Serial.println("Exiting processRC due to E-stop.");
     return 0x00;
   }

@@ -528,7 +578,10 @@
   Serial.println(results[RC_GO]);
   if (liveBrake(results[RC_GO])){
     Serial.print("Braking: "); Serial.println(results[RC_GO]);
-    convertBrake ((results[RC_GO]));
+    brake(convertBrake(results[RC_GO]));
+  }
+  else {
+    brake(MIN_BRAKE_OUT);
   }

   //Accelerating
@@ -536,7 +589,7 @@
     int going = convertThrottle(results[RC_RDR]);
     moveVehicle(going);
   }
-  else if(doCircleRoutine(results[RC_RDR])){
+  else if(doRoutine(results[RC_RDR])){
     moveVehicle(MIN_ACC_OUT);
     circleRoutine(5, results[RC_AUTO]);
   }
@@ -561,13 +614,13 @@
 /*---------------------------------------------------------------------------------------*/
 void processHighLevel(SerialData * results)
 {
-  results->update();
+  //results->update();
   //Steer
   int turn_signal = convertDeg(results->angle_deg);
   steer(turn_signal);
   //End Steer
-   //Throttle
-  ThrottlePID(10*results->speed_cmPs);
+  //Throttle
+  Throttle_PID(10*results->speed_cmPs);
   //End Throttle
   writeSerial(&Serial3, &results);
 }
@@ -662,7 +715,7 @@
 {
   return (acc > MIDDLE + DEAD_ZONE);
 }
-boolean doCircleRoutine(int acc){
+boolean doRoutine(int acc){
   if(acc < 800) return false;
   return (acc < MIN_RC + DEAD_ZONE);
 }
@@ -672,7 +725,7 @@
 boolean liveBrake(int b)
 {
   if (b < 500) return false;
-  return (b < (MIDDLE - DEAD_ZONE));
+  return (b > (MIDDLE + DEAD_ZONE));
 }
 /*---------------------------------------------------------------------------------------*/
 // Emergency stop
@@ -692,13 +745,23 @@
   steer_control = pos;
 }
 /*---------------------------------------------------------------------------------------*/
-void convertBrake(unsigned long amount)
-{
-  if(amount < (MIDDLE + MIN_RC) / 2)
-    amount = MAX_BRAKE_OUT;
-  else if (amount > (MAX_RC - DEAD_ZONE))
-    amount = MIN_BRAKE_OUT;
-  brake (amount);
+int convertBrake(unsigned long amount){
+  const int brakeRange = MAX_BRAKE_OUT - MIN_BRAKE_OUT;
+  const int rcRange = MAX_RC - (MIDDLE + DEAD_ZONE);
+  amount -= (MIDDLE + DEAD_ZONE);
+  float operand = (float)amount / (float)rcRange;
+  operand *= brakeRange;
+  operand += MIN_BRAKE_OUT;
+  int result = (int)operand;
+  if(result > MAX_BRAKE_OUT)
+  {
+    result = MAX_BRAKE_OUT;
+  }
+//  if(amount > (MIDDLE + MIN_RC)
+//    amount = MAX_BRAKE_OUT;
+//  else if (amount > (MAX_RC - DEAD_ZONE))
+//    amount = MIN_BRAKE_OUT;
+  return result;
 }
 /*---------------------------------------------------------------------------------------*/
 void brake (int amount)
@@ -1031,7 +1094,7 @@
   ComputeSpeed (&history);
   //   PrintSpeed(&history);

-  Odometer_m += (float)(LOOP_TIME_MS * SpeedCyclometer_mmPs) / MEG;
+  Odometer_m += (float)(LOOP_TIME_US * SpeedCyclometer_mmPs) / MEG;
   // Since Results have not been cleared, angle information will also be sent.
   Results->speed_cmPs = SpeedCyclometer_mmPs / 10;
   writeSerial(&Serial3, Results);  // Send speed to C6


further commenting / header on template

further commenting / header on template

--- VirtualShield/examples/StartingTemplate-Simple/StartingTemplate-Simple.ino
+++ VirtualShield/examples/StartingTemplate-Simple/StartingTemplate-Simple.ino
@@ -1,3 +1,27 @@
+/*
+    Copyright(c) Microsoft Open Technologies, Inc. All rights reserved.
+
+    The MIT License(MIT)
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files(the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions :
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
 #include <ArduinoJson.h>

 #include <VirtualShield.h>
@@ -8,7 +32,8 @@

 void refresh(ShieldEvent* shieldEvent)
 {
-   // put your refresh code here, which runs when Bluetooth connects or the 'refresh' button is pressed in the app:
+   // put your refresh code here
+   // this runs whenever Bluetooth connects, whenever the shield.begin() executes, or the 'refresh' button is pressed in the app:
    screen.clear();
    screen.printAt(1, "Hello Virtual Shields");
 }
@@ -17,6 +42,8 @@
 {
    // set up virtual shield events:
    shield.setOnRefresh(refresh);
+
+   // begin the shield communication (also calls refresh()).
    shield.begin(); //assumes 115200 Bluetooth baudrate

    // put your setup code here, to run once:


added manual control and comments

added manual control and comments

--- aquaponicMCP/aquaponicMCP.ino
+++ aquaponicMCP/aquaponicMCP.ino
@@ -1,9 +1,11 @@

 #include "OneWire.h"
+
 //analog pins
 #define plantLight A0
 #define aquaLight A1
 #define waterTurbSensor A2
+
 //digital pins
 OneWire  ds(2); //water temp sensor
 #define RELAY1  3
@@ -11,7 +13,9 @@
 #define aquaLed 5
 #define turbLed 6
 #define tempLed 7
-
+#define lightButton 8
+
+//sensor constraints
 #define minLightPlant 0
 #define minLightAqua 0
 #define targetTemperature 0
@@ -19,11 +23,13 @@
 #define targetTurbidity 0
 #define turbidityVarience 0

+//sensor readings
 float aquaLightReading = 0.0;
 float plantLightReading = 0.0;
 float waterTempReading = 0.0;
 float waterTurbReading = 0.0;

+//buffers to hold sensor data
 uint16_t plantLightBuffer[64];
 uint16_t aquaLightBuffer[64];
 uint16_t tempBuffer[64];
@@ -31,15 +37,15 @@

 uint8_t bufferCounter = 1;

-bool plantLightOn = false;
-bool aquaLightOn = false;
-
-unsigned long lightInterval = 12;
-unsigned long lastTime = millis();
 bool powerIsOn = false;

 uint8_t incomingByte;

+bool onAuto = true;
+#define autoTime 1 //number of hours until auto mode resumes.
+unsigned long autoTimer = 0;
+
+//run once on start
 void setup() {
   Serial.begin(9600);
   plantLightBuffer[0] = 1791;
@@ -50,13 +56,35 @@
   pinMode(aquaLed, OUTPUT);
   pinMode(turbLed, OUTPUT);
   pinMode(tempLed, OUTPUT);
-}
-
+  pinMode(lightButton, INPUT);
+  digitalWrite(lightButton, HIGH);
+}
+
+//main program loop.
 void loop() {
   LogData();
   SendData();
-  GetInput();
   SendCommands();
+  GetManual();
+  if(onAuto){
+    GetInput();
+  } else {
+    if(millis() > autoTimer + autoTime*3600*1000){
+      onAuto = false;
+    }
+  }
+}
+
+/* Any kind of manual control will go here. Currently a button
+ * is hooked up and will turn the lights either on or off.
+ * After an hour has passed, auto mode will turn back on.
+ */
+void GetManual(){
+  if(digitalRead(lightButton)){
+    digitalWrite(RELAY1, powerIsOn);
+    powerIsOn = !powerIsOn;
+    autoTimer = millis();
+  }
 }

 /*these will be raw readings, converting from voltage to
@@ -157,9 +185,10 @@
   return fahrenheit;
 }

-//im sure there is a better way, consider a timeout?
-//we'll need to check for missed or overwritten data
-//because this might take to long
+/* Im sure there is a better way, consider a timeout?
+ * we'll need to check for missed or overwritten data
+ * because this might take to long
+ */
 void SendData(){
   if(bufferCounter >= 64){
     SendBuffer(plantLightBuffer);
@@ -176,6 +205,7 @@
   }
 }

+//read input via serial
 void GetInput(){
   if (Serial.available() > 0) {
     incomingByte = Serial.read();
@@ -184,21 +214,24 @@
     //turn lights off
     if(incomingByte == 1){
        digitalWrite(RELAY1,0);
+       powerIsOn = false;
     }
     //turn lights on
     if(incomingByte == 2){
        digitalWrite(RELAY1,1);
-    }
-  }
-}
-
+       powerIsOn = true;
+    }
+  }
+}
+
+//turns on warning leds, should later control temperature.
 void SendCommands(){
 //  sensor operation
 //  lighting
-  if(aquaLightOn && aquaLightReading < minLightAqua){
+  if(powerIsOn && aquaLightReading < minLightAqua){
     digitalWrite(aquaLed, HIGH);
   }
-  if(plantLightOn && plantLightReading < minLightPlant){
+  if(powerIsOn && plantLightReading < minLightPlant){
     digitalWrite(plantLed, HIGH);
   }


moe's face!

moe's face!

--- poli_launch/scripts/arduino/led_controller/led_controller.ino
+++ poli_launch/scripts/arduino/led_controller/led_controller.ino
@@ -123,9 +123,9 @@

 boolean eye_enabled = true;
 boolean face_mode = false;
-int eye_shape = 10; // 13: sleepy
+int eye_shape = 0; // 13: sleepy
 int eye_direction = 0;
-int eye_color_idx = 0;
+int eye_color_idx = 4;
 int mouth_shape = 5; //smile
 int mouth_direction = 0;
 int mouth_color_idx = 0;


remove demo. finished check list

remove demo. finished check list

--- demo/src/demo.ino
+++ demo/src/demo.ino
@@ -1,286 +0,0 @@
-#include "avr/io.h"    // hmm
-#include "avr/interrupt.h" //
-
-#include "SharpA21.h"  // Short-distance
-#include "SharpA02.h"  // Long-distance
-#include "URM37.h"     // Ultrasonic
-#include "MotorShield.h"
-
-//digital 0, 1 are not alow to use ==> serial port is using
-//digital 2, 3, 4, 7, 8, 9, 10, 13 are occuppied by motor shield & encoder
-//A0, A1, 6, 12 need to be kicked out before use
-
-//5, 6, 11, 12
-
-//PWM for reading ==> orange
-//TRIG for writing ==> yellow
-#define urTRIG A3 //use one to write command
-
-#define urPWM_F 12
-#define urPWM_L A2
-#define urPWM_R 5
-
-#define motor_L 13  // encoder
-#define motor_R 3     // encoder
-
-
-#define shortIR_LF_in A4
-#define shortIR_RF_in A5
-
-#define longIR_L_in A1
-#define shortIR_R_in A0
-
-//#define longIR_F_in A4
-/**********************/
-#define RisingEdgePerGrid 380 // need testing
-#define RisingEdgePerTurn_200 412 //for speed 200
-#define stepToStraighten 5 //every 5 step make a auto adjust
-
-
-volatile int direction;
-volatile int delta;
-volatile int rightMCtr, leftMCtr;
-volatile int speedMode;  //1 for fast(400), 0 for slow(200)
-
-volatile int counter_for_straighten;
-volatile int empty_space_R;
-
-int pwd = 1; // current direction
-//1 north
-//2 east
-//3 south
-//4 west
-
-int currentX, currentY;
-int goalX, goalY;
-
-URM37 u_F, u_L, u_R;
-SharpA21 shortIR_LF, shortIR_RF, shortIR_R;
-SharpA02 longIR_L;
-
-int u_F_dis, u_R_dis, u_L_dis;
-int ir_rf_dis, ir_lf_dis, ir_l_dis, ir_r_dis;
-
-MotorShield md;
-
-void setPinsMode() {
-    //analog pins no need
-    //so IR sensor no need
-    //digital pins are set in URM37.h
-    //
-    pinMode(motor_R, INPUT);
-    pinMode(motor_L, INPUT);
-}
-
-void waitForCommand() {
-    /**/
-    delay(1000);
-    return;
-    /**/
-    while (!Serial.available() || Serial.read() != 'S') {
-        ;
-    }
-    delay(10);
-}
-
-void setup() {
-
-    Serial.begin(9600);
-    setPinsMode();
-
-    //set up motor
-    md.init();
-    delay(10);
-
-    //set up 3 Ultrasonic
-    u_F.init(urPWM_F, urTRIG);
-    u_L.init(urPWM_L, urTRIG);
-    u_R.init(urPWM_R, urTRIG);
-    delay(10);
-
-    //set up IR sensor
-    shortIR_RF.init(shortIR_RF_in);
-    shortIR_LF.init(shortIR_LF_in);
-
-    shortIR_R.init(shortIR_R_in);
-    longIR_L.init(longIR_L_in);
-    delay(10);
-}
-
-void loop() {
-
-    /*************************/
-    /**** 8 shape drifting****/
-    /*************************/
-    md.init();
-
-}
-
-
-/**************************************************************/
-/***************************movement***************************/
-/**************************************************************/
-
-
-
-void goAhead(int grids) {
-    speedMode = 1;
-    direction = 1;
-    delta = 0;
-    rightMCtr = leftMCtr = RisingEdgePerGrid * grids;
-
-    setTimerInterrupt();
-    attachInterrupt(1, countRight, RISING);
-
-    md.init();
-    md.setSpeeds(250, 250);
-    while (--leftMCtr) {
-        while (digitalRead(motor_L));
-        while (!digitalRead(motor_L));
-        //wait for one cycle
-    }
-
-    detachTimerInterrupt();
-    detachInterrupt(1);
-
-    md.brakeWithABS();
-
-    //update direciton
-    switch (pwd) {
-        case 1: currentY +=grids;
-                break;
-        case 2: currentX +=grids;
-                break;
-        case 3: currentY -=grids;
-                break;
-        case 4: currentX -=grids;
-                break;
-        default: break;
-    }
-    delay(3000);
-}
-
-void turn(int turnRight) {
-    speedMode = 0;
-    direction = turnRight;
-    delta = 0;
-    rightMCtr = leftMCtr = RisingEdgePerTurn_200;
-
-    setTimerInterrupt();
-    attachInterrupt(1, countRight, RISING);
-
-    //sp.setSpeedLvls(3, 3);
-    md.init();
-    md.setSpeeds(-200 * direction, 200 * direction);
-    while (--leftMCtr) {
-        while (digitalRead(motor_L));
-        while (!digitalRead(motor_L));
-        //wait for one cycle
-    }
-
-    detachTimerInterrupt();
-    detachInterrupt(1);
-
-    md.brakeWithABS();
-
-    //update direction
-    pwd += turnRight;
-    if (pwd == 5) {
-        pwd = 1;
-    } else if (pwd == 0) {
-        pwd = 4;
-    }
-    delay(3000);
-}
-
-
-
-void countRight() {
-    --rightMCtr;
-    delta = rightMCtr - leftMCtr;
-}
-
-void setTimerInterrupt() {
-  cli();          // disable global interrupts
-  // Timer/Counter Control Registers
-  TCCR1A = 0;     // set entire TCCR1A register to 0
-  TCCR1B = 0;     // same for TCCR1B
-
-  // set compare match register to desired timer count:
-  OCR1A = 1562;   // scale = 1024, OCR1A = (xxx / 64 / 1024)
-
-  // turn on CTC mode:
-  TCCR1B |= (1 << WGM12);
-  // Set CS10 and CS12 bits for 1024 prescaler:
-  TCCR1B |= (1 << CS10);
-  TCCR1B |= (1 << CS12);
-
-  //  enable timer compare interrupt:
-  //  Timer/Counter Interrupt Mask Register
-  //  Compare A&B interrupts
-  TIMSK1 |= (1 << OCIE1A);
-  sei();          // enable global interrupts
-}
-void detachTimerInterrupt() {
-  cli();
-  TIMSK1 &= 0; // disable
-  sei();
-}
-ISR(TIMER1_COMPA_vect) {
-    if (speedMode) {
-        md.setM2Speed((250 - delta*5) * direction);
-    } else {
-        md.setM2Speed((200 - delta*5) * direction);
-    }
-}
-
-
-
-/**************************************************************/
-/***************************auto fix***************************/
-/**************************************************************/
-
-
-void straighten() {
-    adjustDistance();
-    delay(50);
-    adjustDirection();
-    delay(50);
-}
-
-void adjustDirection() {
-    //Ultrasonic go until 5cm
-    int speed = 60;
-    int l, r;
-    for (int i = 0; i < 800; i++) {
-        l = shortIR_LF.getDis();
-        r = shortIR_RF.getDis();
-        delay(10);
-        if (r > l + 20) { //TODO WARNING
-            md.setSpeeds(-60, 60);
-        } else if (r < l) {
-            md.setSpeeds(60, -60);
-        }
-    }
-    md.setBrakes(400, 400);
-}
-
-void adjustDistance() {
-    int speed = 100;
-    int l, r, frontDis;
-    for (int i = 0; i < 500; i++) {
-        l = shortIR_LF.getDis();
-        r = shortIR_RF.getDis();
-        delay(6);
-        frontDis = max(l, r);
-
-        if (frontDis < 450) {
-            md.setSpeeds(speed, speed);
-        } else if (frontDis > 500) {
-            md.setSpeeds(-speed, -speed);
-        } else {
-            break;
-        }
-    }
-    md.setBrakes(400, 400);
-}


Update LogoBotWifiScribbler.ino

Update LogoBotWifiScribbler.ino

Reworked to include command queue, added "TO" command and internal tracking of position/angle in cartesian co-ord frame

--- software/firmware/LogoBotWifiScribbler/LogoBotWifiScribbler.ino
+++ software/firmware/LogoBotWifiScribbler/LogoBotWifiScribbler.ino
@@ -39,9 +39,84 @@
 AccelStepper stepperL(AccelStepper::HALF4WIRE, motorLPin1, motorLPin3, motorLPin2, motorLPin4);
 AccelStepper stepperR(AccelStepper::HALF4WIRE, motorRPin1, motorRPin3, motorRPin2, motorRPin4);

+#define STEPS_PER_MM 5000/232;
+#define STEPS_PER_DEG 3760.0 / 180.0;
+
+#define MAX_CMD_LENGTH 10
+#define QUEUE_LENGTH 20
+
+// position state info
+struct POSITION {
+  long x;
+  long y;
+  long ang;
+};
+POSITION position;
+
 Servo penliftServo;

 long buzzEnd = 0;
+
+// buffered text to "write" using the pen
+String text = "";
+
+// cmd received over serial - builds up char at a time
+String cmd;
+
+struct COMMAND {
+  String cmd;
+};
+
+COMMAND cmdQ[QUEUE_LENGTH];
+int qHead = 0;
+int qSize = 0;
+
+
+boolean pushCmd(String s) {
+  // push s onto tail of queue
+  // return true if pushed ok, false if buffer full
+
+  if (!isQFull()) {
+    int next = qHead + qSize;
+    if (next >= QUEUE_LENGTH) next -= QUEUE_LENGTH;
+
+    cmdQ[next].cmd = String(s);
+
+    qSize++;
+
+    return true;
+  } else
+    return false;
+}
+
+
+String popCmd() {
+  // pops head of queue
+  if (qSize > 0) {
+    String s = cmdQ[qHead].cmd;
+    qSize--;
+    qHead++;
+    if (qHead >= QUEUE_LENGTH) qHead -= QUEUE_LENGTH;
+    return s;
+  } else
+    return "";
+}
+
+boolean isQFull() {
+  // returns true if full
+  return qSize == QUEUE_LENGTH;
+}
+
+boolean isQEmpty() {
+  return qSize == 0;
+}
+
+// position calcs
+void resetPosition() {
+  position.x = 0;
+  position.y = 0;
+  position.ang = 0;
+}

 void setup()
@@ -49,12 +124,12 @@
   Serial.begin(9600);
   Serial.println("Logobot");
   stepperL.setMaxSpeed(1000);
-  stepperL.setAcceleration(500);
+  stepperL.setAcceleration(2000);
   //stepperL.moveTo(5000);
   stepperL.setPinsInverted(true, true, false, false, false);

   stepperR.setMaxSpeed(1000);
-  stepperR.setAcceleration(500);
+  stepperR.setAcceleration(2000);
   //stepperR.moveTo(5000);

   pinMode(switchFL, INPUT_PULLUP);
@@ -72,33 +147,35 @@
   pinMode(buzzer, OUTPUT);

   buzz(250);
+
+  resetPosition();
 }

 int progStep = 0;

-String cmd;

 void loop()
 {
-  // Process Logo commands from Serial
+  // Parse Logo commands from Serial, add to cmdQ
   if (Serial.available()) {
     char c = Serial.read();
     if (c == '\r' || c == '\n') {
       if (cmd != "") {
         Serial.println("OK:" + cmd);
-        doLogoCommand(cmd);
+        //doLogoCommand(cmd);
+        pushCmd(cmd);
         cmd = "";
       }
     } else {
       cmd += c;
     }
   }
-
+
   // Check bump switches
   if (!digitalRead(switchFL) || !digitalRead(switchFR)) {
     buzz(250);
-    stepperL.stop();
-    stepperR.stop();
+    stepperL.setCurrentPosition(stepperL.currentPosition());
+    stepperR.setCurrentPosition(stepperR.currentPosition());
   }

   // Do buzzer
@@ -115,26 +192,44 @@
   // Note that AccelStepper.disableOutputs doesn't seem to work
   // correctly when pins are inverted and leaves some outputs on.
   if (stepperL.distanceToGo() == 0 && stepperR.distanceToGo() == 0) {
-      digitalWrite(motorLPin1, LOW);
-      digitalWrite(motorLPin2, LOW);
-      digitalWrite(motorLPin3, LOW);
-      digitalWrite(motorLPin4, LOW);
-      digitalWrite(motorRPin1, LOW);
-      digitalWrite(motorRPin2, LOW);
-      digitalWrite(motorRPin3, LOW);
-      digitalWrite(motorRPin4, LOW);
+
+    if (isQEmpty()) {
+
+      // check the text writing buffer
+      if (text.length() > 0) {
+        char c = text[0];
+        text = text.substring(1);  // lose the first character
+        writeChar(c);
+
+      } else {
+        // take a breather
+        digitalWrite(motorLPin1, LOW);
+        digitalWrite(motorLPin2, LOW);
+        digitalWrite(motorLPin3, LOW);
+        digitalWrite(motorLPin4, LOW);
+        digitalWrite(motorRPin1, LOW);
+        digitalWrite(motorRPin2, LOW);
+        digitalWrite(motorRPin3, LOW);
+        digitalWrite(motorRPin4, LOW);
+      }
+    } else {
+      // pop and process next command from queue
+      doLogoCommand(popCmd());
+    }
   }
 }

-void doLogoCommand(String cmd)
-{
+void doLogoCommand(String c)
+{
+
+  Serial.println(c);
   /* Official Logo Commands
        Implemented
          -FD, BK, LT, RT
        Todo
          -PU - Pen Up
          -PD - Pen Down
-         -ARC
+         -ARC
    */
   /* Unofficial extensions
       BZ n - sound buzzer for n milliseconds
@@ -142,29 +237,37 @@
       SIG - sign Logobots name
     */

-  if (cmd.startsWith("FD")) {
-    int dist = cmd.substring(3).toInt();
-    driveForward(dist);
-  } else if (cmd.startsWith("BK")) {
-    int dist = cmd.substring(3).toInt();
-    driveBackward(dist);
-  } else if (cmd.startsWith("RT")) {
-    int angle = cmd.substring(3).toInt();
-    rightTurn(angle * 3760.0 / 180.0);
-  } else if (cmd.startsWith("LT")) {
-    int angle = cmd.substring(3).toInt();
-    leftTurn(angle * 3760.0 / 180.0);
-  } else if (cmd.startsWith("ST")) {
+  if (c.startsWith("TO")) {
+    // split out x and y co-ordinates
+    int sp = c.indexOf(" ",3);
+    int x = c.substring(3,sp).toInt();
+    int y = c.substring(sp+1).toInt();
+    driveTo(x,y);
+  } else if (c.startsWith("FD")) {
+    int dist = c.substring(3).toInt();
+    drive(dist);
+  } else if (c.startsWith("BK")) {
+    int dist = c.substring(3).toInt();
+    drive(-dist);
+  } else if (c.startsWith("RT")) {
+    int angle = c.substring(3).toInt();
+    turn(-angle);
+  } else if (c.startsWith("LT")) {
+    int angle = c.substring(3).toInt();
+    turn(angle);
+  } else if (c.startsWith("ST")) {
     stepperL.stop();
     stepperR.stop();
-  } else if (cmd.startsWith("BZ")) {
-    buzz(cmd.substring(3).toInt());
-  } else if (cmd.startsWith("PU")) {
+  } else if (c.startsWith("BZ")) {
+    buzz(c.substring(3).toInt());
+  } else if (c.startsWith("PU")) {
     penUp();
-  } else if (cmd.startsWith("PD")) {
+  } else if (c.startsWith("PD")) {
     penDown();
-  } else if (cmd.startsWith("SIG")) {
-    sign();
+  } else if (c.startsWith("SIG")) {
+    writeLogobot();
+  } else if (c.startsWith("WT")) {
+    writeText(c.substring(3));
   }
 }

@@ -179,28 +282,57 @@
   }
 }

-void driveForward(long distance)
-{
+void driveTo(long x, long y) {
+  Serial.print(x);
+  Serial.print(",");
+  Serial.println(y);
+
+  // calc angle
+  long ang = atan2(y-position.y, x-position.x) * 180 / PI;
+  // now angle delta
+  ang = ang - position.ang;
+  if (ang > 0)
+    pushCmd("LT " + String(ang));
+  else
+    pushCmd("RT " + String(-ang));
+
+  // and distance
+  long dist = sqrt(sqr(y-position.y) + sqr(x-position.x));
+  pushCmd("FD "+String(dist));
+}
+
+void drive(long distance)
+{
+  // update state
+  position.x += distance * cos(position.ang * PI / 180);
+  position.y += distance * sin(position.ang * PI / 180);
+
+  Serial.print("Pos: ");
+  Serial.print(position.x);
+  Serial.print(",");
+  Serial.println(position.y);
+
+  distance *= STEPS_PER_MM;
   stepperL.move(distance);
   stepperR.move(distance);
 }

-void driveBackward(long distance)
-{
-  stepperL.move(-distance);
-  stepperR.move(-distance);
-}
-
-void leftTurn(long distance)
-{
-  stepperR.move(distance);
-  stepperL.move(-distance);
-}
-
-void rightTurn(long distance)
-{
-  stepperR.move(-distance);
-  stepperL.move(distance);
+void turn(long ang)
+{
+  // update state
+  position.ang += ang;
+
+  ang *= STEPS_PER_DEG;
+  stepperR.move(ang);
+  stepperL.move(-ang);
+
+
+  // correct wrap around
+  if (position.ang > 360) position.ang -= 360;
+  if (position.ang < -360) position.ang += 360;
+
+  Serial.print("Angle: ");
+  Serial.println(position.ang);
 }

 void buzz(int len)
@@ -218,7 +350,34 @@
   penliftServo.write(90);
 }

-void sign()
+void writeChar(char c) {
+    switch(c) {
+        case 'L':
+          pushCmd("FD 100");
+          pushCmd("PD");
+          pushCmd("BK 100");
+          pushCmd("RT 90");
+          pushCmd("FD 80");
+          pushCmd("PU");
+
+          pushCmd("FD 50");
+          break;
+
+        default:
+          pushCmd("BZ 500");
+          break;
+    }
+}
+
+void writeText(String s) {
+  // overwrite write text
+  text = s;
+
+  // reset current state
+  resetPosition();
+}
+
+void writeLogobot()
 {
   // L
   dlcs("FD 100");
@@ -327,3 +486,7 @@
   dlcs("FD 2000");

 }
+
+long sqr(long v) {
+  return v*v;
+}


Radio sending the same message to all 3 pipes

--- communication_firmware/central_firmware/central_firmware.ino
+++ communication_firmware/central_firmware/central_firmware.ino
@@ -14,7 +14,7 @@
 RF24 radio(CE,CS);

 const uint64_t pipes[4] = { 0xABCDABCD71LL, 0x544d52687CLL , 0x644d52687CLL, 0x744d52687CLL};
-uint64_t pipeEnvia=pipes[3];
+uint64_t pipeEnvia=pipes[1];
 uint64_t pipeRecebe=pipes[0];

 ros::NodeHandle nh;
@@ -54,7 +54,10 @@
 void repeteVelocidade(){
   radio.stopListening();
   radio.enableDynamicAck();
-  radio.write(&velocidades,sizeof(velocidades), 1);
+  for (int i=0; i<3; i++) {
+    radio.openWritingPipe(pipes[1+i]);
+    radio.write(&velocidades,sizeof(velocidades), 1);
+  }
   radio.startListening();
 }

@@ -64,7 +67,6 @@
   radio.setPALevel(RF24_PA_MAX);           //usa potencia maxima
   radio.setDataRate(RF24_2MBPS);           //usa velocidade maxima

-  radio.openWritingPipe(pipeEnvia);        //escreve pelo pipe0
   radio.openReadingPipe(1,pipeRecebe);      //escuta pelo pipe1

   radio.enableDynamicPayloads();           //ativa payloads dinamicos(pacote tamamhos diferentes do padrao)


Fix variable name bug in Arduino code

Fix variable name bug in Arduino code

--- src/arduino_lights_controller/arduino_lights_controller.ino
+++ src/arduino_lights_controller/arduino_lights_controller.ino
@@ -6,8 +6,8 @@

 void setup() {
   Serial.begin(9600);
-  pinMode(led1, OUTPUT);
-  pinMode(led2, OUTPUT);
+  pinMode(relay1, OUTPUT);
+  pinMode(relay2, OUTPUT);
 }

 void loop() {
@@ -20,7 +20,7 @@
       } else {
         state1 = false;
       }
-      digitalWrite(led1, state1);
+      digitalWrite(relay1, state1);
     } else if (incomingByte == '2') {
       Serial.println("Toggling light 2");
       if (state2 == false){
@@ -28,7 +28,7 @@
       } else {
         state2 = false;
       }
-      digitalWrite(led2, state2);
+      digitalWrite(relay2, state2);
     }
   }
 }


Bubblehead working

Bubblehead working

--- crusty_363_bubblehead_joint_control/crusty_363_bubblehead_joint_control.ino
+++ crusty_363_bubblehead_joint_control/crusty_363_bubblehead_joint_control.ino
@@ -37,18 +37,18 @@
   Dynamixel.setHoldingTorque(0x05, true);

   //Set profile acceleration
-  Dynamixel.setProfileAcceleration(0x01, 10);           //Set profile acc for each servo
-  Dynamixel.setProfileAcceleration(0x02, 10);
-  Dynamixel.setProfileAcceleration(0x03, 10);
-  Dynamixel.setProfileAcceleration(0x04, 300);
-  Dynamixel.setProfileAcceleration(0x05, 300);
+  Dynamixel.setProfileAcceleration(0x01, 0);           //Set profile acc for each servo
+  Dynamixel.setProfileAcceleration(0x02, 0);
+  Dynamixel.setProfileAcceleration(0x03, 0);
+  Dynamixel.setProfileAcceleration(0x04, 100);
+  Dynamixel.setProfileAcceleration(0x05, 100);

   //Set profile velocity
-  Dynamixel.setProfileVelocity(0x01, 100);              //Set profile vel for each servo
-  Dynamixel.setProfileVelocity(0x02, 100);
-  Dynamixel.setProfileVelocity(0x03, 100);
-  Dynamixel.setProfileVelocity(0x04, 200);
-  Dynamixel.setProfileVelocity(0x05, 200);
+  Dynamixel.setProfileVelocity(0x01, 50);              //Set profile vel for each servo
+  Dynamixel.setProfileVelocity(0x02, 50);
+  Dynamixel.setProfileVelocity(0x03, 50);
+  Dynamixel.setProfileVelocity(0x04, 100);
+  Dynamixel.setProfileVelocity(0x05, 100);
  }

 int x, y, z, jointexcess_prevention;
@@ -65,7 +65,7 @@
             infoPk[i] = jelly;
           }

-while(z < 300 && jointexcess_prevention==0){                              //Tilting the head to the right moves on to the next joint && h prevents from excessive joint counting.
+while(z < 300 && z > 200 && jointexcess_prevention==0 && x > 0 && x < 1000 && y > 0 && y < 1000){                              //Tilting the head to the right moves on to the next joint && h prevents from excessive joint counting.
     joint++;
     jointexcess_prevention++;
     if(joint > 4){
@@ -73,7 +73,7 @@
     }
     break;
 }
-while(z > 700 && jointexcess_prevention==0){                              //Tilting the head to the left moves on to the previous joint
+while(z > 600 && z < 700 && jointexcess_prevention==0 && x > 0 && x < 1000 && y > 0 && y < 1000){                              //Tilting the head to the left moves on to the previous joint
    joint--;
    jointexcess_prevention++;
    if(joint < 1){
@@ -81,44 +81,44 @@
    }
    break;
 }
-  if(z >= 460 && z <= 470){                         //Sets it back to the original position and the counter to 0
+  if(z >= 420 && z <= 470){                         //Sets it back to the original position and the counter to 0
     jointexcess_prevention=0;
     }
-while(joint == 1 && y > 700){                        //Tilting forward moves joint 1 down
+while(joint == 1 && y > 600 && z > 300 && z < 700 && x > 0 && x < 1000){                        //Tilting forward moves joint 1 down
   i = i + 10;
   Dynamixel.setNGoalPositions(i, -1, -1, -1, -1);
   break;
 }
-while(joint == 1 && y < 300){                        //Tilting backward moves joint 1 up
+while(joint == 1 && y < 400 && z > 300 && z < 700 && x > 0 && x < 1000){                        //Tilting backward moves joint 1 up
   i = i - 10;
   Dynamixel.setNGoalPositions(i, -1, -1, -1, -1);
   break;
 }
-while(joint == 2 && y > 700){                        //Tilting forward moves joint 2 down
+while(joint == 2 && y > 600 && z > 300 && z < 700 && x > 0 && x < 1000){                        //Tilting forward moves joint 2 down
   j = j + 10;
   Dynamixel.setNGoalPositions(-1, j, -1, -1, -1);
   break;
 }
-while(joint == 2 && y < 300){                        //Tilting backward moves joint 2 up
+while(joint == 2 && y < 400 && z > 300 && z < 700 && x > 0 && x < 1000){                        //Tilting backward moves joint 2 up
   j = j - 10;
   Dynamixel.setNGoalPositions(-1, j, -1, -1, -1);
   break;
 }
-while(joint == 3 && y > 700){                        //Tilting forward moves joint 3 down
+while(joint == 3 && y > 600 && z > 300 && z < 700 && x > 0 && x < 1000){                        //Tilting forward moves joint 3 down
   k = k + 10;
   Dynamixel.setNGoalPositions(-1, -1, k, -1, -1);
   break;
 }
-while(joint == 3 && y < 300){                        //Tilting backward moves joint 3 up
+while(joint == 3 && y < 400 && z > 300 && z < 700 && x > 0 && x < 1000){                        //Tilting backward moves joint 3 up
   k = k - 10;
   Dynamixel.setNGoalPositions(-1, -1, k, -1, -1);
   break;
 }
-while(joint == 4 && y > 700){                        //Tilting forward opens the gripper
+while(joint == 4 && y > 600 && z > 300 && z < 700 && x > 0 && x < 1000){                        //Tilting forward opens the gripper
    Dynamixel.gripper(OPEN);
    break;
 }
-while(joint == 4 && y < 300){                        //Tilting backward closes the gripper
+while(joint == 4 && y < 400 && z > 300 && z < 700 && x > 0 && x < 1000){                        //Tilting backward closes the gripper
    Dynamixel.gripper(CLOSE);
    break;
 }
@@ -128,7 +128,7 @@
   y = infoPk[15] + (infoPk[14] << 8);
   x = infoPk[17] + (infoPk[16] << 8);
 }
-  Serial.print(" X = ") && Serial.print(x);
+  //Serial.print(" X = ") && Serial.print(x);
   Serial.print(" Y = ") && Serial.print(y);
   Serial.print(" Z = ") && Serial.print(z);
   Serial.print(" joint number= ") && Serial.print(joint);


calibration mode

calibration mode

--- remap.ino
+++ remap.ino
@@ -82,7 +82,7 @@

 uint16_t getEllipticalSpeed(const EllipticalData_t* ellipticalP, uint32_t multiplier) {
   if (multiplier == 0) {
-    if (speed == 0)
+    if (ellipticalP->speed == 0)
       return 512;
     else if (ellipticalP->direction)
       return 1023;


Examples: removed unneeded #include's and add header comments

--- examples/03-Intermediate/WDRC_SingleBand/WDRC_SingleBand.ino
+++ examples/03-Intermediate/WDRC_SingleBand/WDRC_SingleBand.ino
@@ -1,9 +1,23 @@
+/*
+  WDRC_SingleBand
+
+  Created: Chip Audette (OpenAudio), Feb 2017
+    Primarly built upon CHAPRO "Generic Hearing Aid" from
+    Boys Town National Research Hospital (BTNRH): https://github.com/BTNRH/chapro
+
+  Purpose: Implements BTNRH's Wide Dynamic Range Compressor, though
+    only in a single frequency band.  I've also added an expansion stage
+    to manage noise at very low SPL.
+
+  User Controls:
+    Potentiometer on Tympan controls the algorithm gain
+
+   MIT License.  use at your own risk.
+*/
+
+// Include the required libraries
 #include <Tympan_Library.h>
-//include <Audio.h>
-//include <Wire.h>
-#include <SPI.h>
-//include <SD.h>
-//include <SerialFlash.h>
+

 // GUItool: begin automatically generated code
 AudioInputI2S_F32        i2sAudioIn1;    //xy=136,112


Updating PWM threshold for fob stop (#61)

--- Arduino/victoria_teensy_ros_node/victoria_teensy_ros_node.ino
+++ Arduino/victoria_teensy_ros_node/victoria_teensy_ros_node.ino
@@ -84,8 +84,9 @@
 // indicates which fob to check.
 byte fob_mode(0);

-// PWM threshold that a "fob" will be considered activated.
-unsigned int fob_threshold(2000);
+// Threshold for which a PWM value less than will be considered
+// "fob" activated.
+unsigned int fob_threshold(1575);

 // Victoria configuration
 double ticks_per_radian;
@@ -241,7 +242,7 @@
     ros_param_helper.getParam("motor_controller_acceleration", 10);

   fob_threshold =
-    ros_param_helper.getParam("fob_threshold", 2000);
+    ros_param_helper.getParam("fob_threshold", 1575);

   ticks_per_radian =
     ros_param_helper.getParam("victoria_ticks_per_radian", 9072);


Fixed EasyWebSocket_test.ino of sample sketch

Deleted .
char res_html[html_str.length()+1];
html_str.toCharArray(res_html, html_str.length());

--- EasyWebSocket/examples/EasyWebSocket_test/EasyWebSocket_test.ino
+++ EasyWebSocket/examples/EasyWebSocket_test/EasyWebSocket_test.ino
@@ -105,8 +105,6 @@
     }
   }else if(ret_str == "_close"){
     delay(100);
-    char res_html[html_str.length()+1];
-    html_str.toCharArray(res_html, html_str.length());
     ews.EWS_HandShake(LocalIPaddress, view_scale, s_rate, html_str);
     CountTestTime = millis();
     ret_str = String('\0');


One step backwards, I think. (Doesn't work.)

--- Project/demo_just_get_it_working/demo_just_get_it_working.ino
+++ Project/demo_just_get_it_working/demo_just_get_it_working.ino
@@ -124,22 +124,29 @@
 /*
  * Increments towards the intended angle, keeping other angles in valid ranges.
  */
-void go_towards(int servo_number, int angle)
+boolean go_towards(int servo_number, int angle)
 {
   angle = constrain_servo_angle(servo_number, angle);
   int diff = angle - angles[servo_number];

   int dir;
   if (diff == 0)
-    dir = 0;
+    return false;
   else
     dir = diff / abs(diff);

   angles[servo_number] += dir;
   servo[servo_number].write( angles[servo_number] );
+
+  if ( servo_number = 1 )
+    go_to(3, angles[3]);
+  if ( servo_number = 3 )
+    go_to(1, angles[1]);

 //  if ( angles[servo_number] % 15 == 0 )
 //    Serial.print(angles[servo_number]);
+
+  return true;
 }

 void go_to(int servo_number, int angle)
@@ -150,14 +157,12 @@
   do {
     previous_angle = angles[servo_number];

-    go_towards(servo_number, angle);
-
     delay(delay_time);

     if ( abs(angle - angles[servo_number]) > 15 && delay_time > min_delay_time )
       delay_time -= min_delay_time;
     else if ( abs(angle - angles[servo_number]) <= 15 && delay_time < max_delay_time)
       delay_time += min_delay_time;
-  } while ( abs(previous_angle - angles[servo_number]) != 0 );
+  } while ( go_towards(servo_number, angle) );
 }


Tidied up the comments

Tidied up the comments

--- examples/ping.ino
+++ examples/ping.ino
@@ -40,7 +40,9 @@
  * Arduino on: use it to initialize and
  * set any initial values.
  *
- * DESC TODO
+ * We just initialize the serial
+ * connection (for debugging) and
+ * the SnowPlow tracker.
  */
 void setup()
 {
@@ -56,7 +58,8 @@
  * An empty loop() takes just a few
  * clock cycles to complete.
  *
- * DESC TODO
+ * Every 15 seconds, send a 'ping'
+ * event to SnowPlow.
  */
 void loop()
 {


Force setting clock on Yun during setup

Force setting clock on Yun during setup

--- RouterReset_Yun/RouterReset_Yun.ino
+++ RouterReset_Yun/RouterReset_Yun.ino
@@ -76,6 +76,8 @@
   digitalWrite(greenLED, LOW);
   digitalWrite(yellowLED, LOW);

+  setClock();
+
   logEvent("startup");
 }

@@ -185,3 +187,24 @@
   p.addParameter(status);
   p.run();
 }
+
+void setClock(void) {
+  Process p;
+  String result;
+
+  #ifdef DEBUG
+  Serial.println("Setting clock.");
+  #endif
+
+  p.runShellCommand("ntpd -qn -p 0.pool.ntp.org");
+
+  #ifdef DEBUG
+  result = "";
+  while(p.available() > 0) {
+    char c = p.read();
+    result += c;
+  }
+
+  Serial.println(result);
+  #endif
+}


cleared logging of events

cleared logging of events

--- sensors/letterbox/letterbox.ino
+++ sensors/letterbox/letterbox.ino
@@ -76,39 +76,31 @@

   write8(VCNL4000_IRLED, 20);        // set to 20 * 10mA = 200mA
-  Serial.print("IR LED current = ");
-  Serial.print(read8(VCNL4000_IRLED) * 10, DEC);
-  Serial.println(" mA");
-
-  //write8(VCNL4000_SIGNALFREQ, 3);
-  Serial.print("Proximity measurement frequency = ");
-  uint8_t freq = read8(VCNL4000_SIGNALFREQ);
-  if (freq == VCNL4000_3M125) Serial.println("3.125 MHz");
-  if (freq == VCNL4000_1M5625) Serial.println("1.5625 MHz");
-  if (freq == VCNL4000_781K25) Serial.println("781.25 KHz");
-  if (freq == VCNL4000_390K625) Serial.println("390.625 KHz");
+//  Serial.print("IR LED current = ");
+//  Serial.print(read8(VCNL4000_IRLED) * 10, DEC);
+//  Serial.println(" mA");
+//  Serial.print("Proximity measurement frequency = ");
+//  uint8_t freq = read8(VCNL4000_SIGNALFREQ);
+//  if (freq == VCNL4000_3M125) Serial.println("3.125 MHz");
+//  if (freq == VCNL4000_1M5625) Serial.println("1.5625 MHz");
+//  if (freq == VCNL4000_781K25) Serial.println("781.25 KHz");
+//  if (freq == VCNL4000_390K625) Serial.println("390.625 KHz");

   write8(VCNL4000_PROXINITYADJUST, 0x81);
   Serial.print("Proximity adjustment register = ");
   Serial.println(read8(VCNL4000_PROXINITYADJUST), HEX);
-
-  // arrange for continuous conversion
-  // write8(VCNL4000_AMBIENTPARAMETER, 0x89);
-
 }

 uint16_t readProximity() {
   write8(VCNL4000_COMMAND, VCNL4000_MEASUREPROXIMITY);
   while (1) {
     uint8_t result = read8(VCNL4000_COMMAND);
-    //Serial.print("Ready = 0x"); Serial.println(result, HEX);
     if (result & VCNL4000_PROXIMITYREADY) {
       return read16(VCNL4000_PROXIMITYDATA);
     }
     delay(1);
   }
 }
-

 void loop() {
@@ -135,7 +127,7 @@
       // proximity value
       proximitySensorVal = read16(VCNL4000_PROXIMITYDATA);
       proximitySmoothedVal = smooth(proximitySensorVal, proximityFilterVal, proximitySmoothedVal);
-      Serial.print("\tProximity = ");
+      Serial.print("\tMail = ");
       Serial.print(proximitySmoothedVal);

       break;
@@ -144,41 +136,34 @@
   }

   if(ownerSmoothedVal > bothSidesOpenThreshold && postmanSmoothedVal > bothSidesOpenThreshold) { // letterbox opened
-    if(ownerSmoothedVal > postmanSmoothedVal) {               // owner opens letterbox
+    if(ownerSmoothedVal > postmanSmoothedVal) {                                                  // owner opens letterbox
         Serial.println("\t => Owner opened letterbox");
         ownerOpened = true;
-        deliveries = 0; // owner has checked letterbox
-    } else {                                                  // postman opens letterbox
+        deliveries = 0;                                         // owner has checked letterbox
+    } else {                                                                                // postman opens letterbox
         Serial.println("\t => Postman opened letterbox");
         postmanOpened = true;
     }
-  } else {    // letterbox closed
+  } else {                                                                                // letterbox closed
     if(postmanOpened || ownerOpened) {

       if(postmanOpened) {                                       // postman just closed
          if(proximitySmoothedVal > 10 + previousMail) {
-            Serial.print("\tCurrent: ");
-            Serial.print(proximitySmoothedVal);
-            Serial.print("\t, Previous: ");
-            Serial.print(previousMail);
-            Serial.println("\t => new mail !!!");
+            Serial.println("\t => NEW MAIL DELIVERED !!!");
+            deliveries++; // send notification to owner's device
             postmanOpened = false;
             previousMail = proximitySmoothedVal;
          } else {
            postmanOpened = false;
            previousMail = proximitySmoothedVal;
-           Serial.println("\t => no mail");
+           Serial.println("\t => no mail delivered");
          }
       }
       if(ownerOpened){                                        // owner just closed
-        Serial.print("\tCurrent: ");
-        Serial.print(proximitySmoothedVal);
-        Serial.print("\t, Previous: ");
-        Serial.print(previousMail);
-        Serial.println("\t => no mail");
-        deliveries++; // send notification
+
         ownerOpened = false;
         previousMail = proximitySmoothedVal;
+        Serial.println("\t => mails cleared");
       }
     } else {
       Serial.println("\t => letterbox closed");


Rename variable and add comment to clarify.

--- tfttask.ino
+++ tfttask.ino
@@ -8,7 +8,7 @@
 const uint16_t TFT_BUTTON_HEIGHT      =  40;

 const bool     TFT_SHOW_RAW           = false;            /* show raw PWM values */
-const bool     HIGH_VIZ               = true;
+const bool     HIGH_VIZ_PERCENTAGE    = true;             /* show channel percent values in TFT_BACK_COLOR instead of the channel color to improve visibility */

 enum tftFontsize_t
 {
@@ -348,7 +348,7 @@
       tft.getTextBounds( label.text, 0, 0, &x, &y, &w, &h );
       tft.setCursor( ( label.x + label.w / 2 ) - ( w / 2 ),
                      ( label.y + label.h / 2 ) - ( h / 2 ) );
-      if ( HIGH_VIZ )
+      if ( HIGH_VIZ_PERCENTAGE )
       {
         tft.setTextColor( TFT_TEXT_COLOR, TFT_BACK_COLOR );
       }


use UART Serial1 now

use UART Serial1 now

--- autobaud_bitlash.ino
+++ autobaud_bitlash.ino
@@ -3,7 +3,7 @@
 // target : Arduino Mega (ATMega2560)
 // note   : - use timer1 for 0.5 uS accuracy time measure
 //            (arduino core micros() is just 4us accuracy).
-//          - signal to detect must be wire on pin 2.
+//          - signal to detect must be wire on pin 19 (Rx of Serial1).
 //          - use bitlash for console manager (see https://github.com/billroy/bitlash)
 //          - use Timer for schedule tasks (see  https://github.com/JChristensen/Timer)

@@ -11,20 +11,30 @@
 #include "bitlash.h"
 #include "Timer.h"

+// macro
+#define ROW_COUNT(array)  (sizeof(array) / sizeof(*array))
+
 // const
 // pin 2 = interrupt 1 on UNO board
-const byte SERIAL_IN_PIN = 2;
-const byte SERIAL_IN_INT = 0;
+const byte SERIAL_IN_PIN = 19;
+const byte SERIAL_IN_INT = 4;
+
+// struct
+struct in_bytes {
+  byte value;
+  unsigned long time;
+};

 // vars
+in_bytes rx_bytes[30];
+byte rx_byte_index;
 word times_buffer[60];
-byte level;
 volatile word isr_times_buffer[60];
 byte isr_index_buffer;
-word start_bit;
 word max_step, min_step;
 byte max_index, min_index;
-unsigned long baud;
+unsigned long auto_baud;
+unsigned long uart_baud;
 Timer t;

 // ISR call when edges rising/falling occurs on SERIAL_IN_PIN
@@ -60,8 +70,6 @@
   // search minimal/maximal time step
   max_step = 0;
   min_step = 0xFFFF;
-  start_bit = 0;
-  level = 0;

   for (byte i = 0; i < 60; i++) {
     // skip special values
@@ -77,49 +85,45 @@
         min_index = i;
       }
     }
-    if (times_buffer[i] != 0)
-      level++;
   }

-  // compute baudrate
-  baud = 2 * (1e6 / min_step);
-
-  // count start bit
-  for (byte i = 0; i < 60; i++) {
-    // count start bit
-    if (times_buffer[i] > (min_step * 15)) {
-      start_bit++;
-    }
-  }
-}
-
-numvar printRAW(void) {
+  // compute auto baudrate
+  auto_baud = 2 * (1e6 / min_step);
+}
+
+numvar printRaw(void) {
   // display array
-  /*
-  for (byte i = 0; i < 60; i++) {
-    Serial.print(times_buffer[i]);
-    Serial.print(" ");
-  }
-  Serial.println();*/
-
+  // banner
+  printf_P(PSTR("Index | Time (ms) | Hex  | Dec | ASCII\r\n"));
+  // datas
+  for (byte i = 0; i < ROW_COUNT(rx_bytes); i++) {
+    printf_P(PSTR("%03d   | %6lu    | 0x%02x | %03d | %c  \r\n"), i, rx_bytes[i].time, rx_bytes[i].value, rx_bytes[i].value, rx_bytes[i].value);
+  }
+  printf_P(PSTR("\r\n"));
+  return 0;
+}
+
+numvar printStat(void) {
   // display min_step time and compute baudrate
-  printf_P(PSTR("start bit : %5d\r\n"), start_bit);
   printf_P(PSTR("min step  : %5d us\r\n"), min_step/2);
   printf_P(PSTR("max step  : %5d us\r\n"), max_step/2);
-  printf_P(PSTR("level     : %5d\r\n"), level);
-
-  return 0;
-}
-
+  return 0;
+}
+
+numvar setBaud(void) {
+  uart_baud = getarg(1);
+  Serial1.begin(uart_baud);
+  return 0;
+}
+
+// return true if theoric baudrate and measure baudrate are 10% accuracy
 bool is_baud(long theoric, long measure) {
   return (measure > (theoric - theoric * 0.1)) and (measure < (theoric + theoric *0.1));
 }

-numvar printBaud(void) {
-  printf_P(PSTR("baud measured  : %6lu bps\r\n"), baud);
-  // convert measured baud to estimated baud
+// convert "baud" (like 305) to normalized baud (like 300 or 9600)
+unsigned long norm_baud(unsigned long baud) {
   long estim_baud = 0;
-
   if (is_baud(300, baud))
     estim_baud = 300;
   else if (is_baud(600, baud))
@@ -144,8 +148,13 @@
     estim_baud = 57600;
   else if (is_baud(115200, baud))
     estim_baud = 115200;
-
-  printf_P(PSTR("baud estimated : %6lu bps\r\n"), estim_baud);
+  return estim_baud;
+}
+
+numvar printBaud(void) {
+  printf_P(PSTR("baud measured  : %6lu bps\r\n"), auto_baud);
+  printf_P(PSTR("baud estimated : %6lu bps\r\n"), norm_baud(auto_baud));
+  printf_P(PSTR("UART set baud  : %6lu bps\r\n"), uart_baud);
   return 0;
 }

@@ -164,6 +173,7 @@

 void setup(void) {
   // vars init
+  rx_byte_index = 0;
   isr_index_buffer = 0;
   // timer1 init
   // disable global interrupts
@@ -175,13 +185,18 @@
   sei();
   // init bitlash
   initBitlash(57600);
-  // add bitlash function
-  addBitlashFunction("raw", (bitlash_function) printRAW);
-  addBitlashFunction("bd", (bitlash_function) printBaud);
+  // add spy functions to bitlash function
+  addBitlashFunction("spy_dump", (bitlash_function) printRaw);
+  addBitlashFunction("spy_stat", (bitlash_function) printStat);
+  addBitlashFunction("spy_baud", (bitlash_function) printBaud);
+  addBitlashFunction("spy_setbaud", (bitlash_function) setBaud);
   // fill in the UART file descriptor with pointer to writer
   fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
   // standard output device STDOUT is uart
   stdout = &uartout ;
+  // init serial 1 (pin18/19)
+  Serial1.begin(9600);
+  uart_baud = 9600;
   // launch timer task
   int updateJob = t.every(500, update_time_buffer);
   // IO init
@@ -189,6 +204,19 @@
   attachInterrupt(SERIAL_IN_INT, isr_serial_change, CHANGE);
 }

+// call if data available on Serial1
+void serialEvent1() {
+  while (Serial1.available()) {
+    // read rx byte
+    char inChar = (char)Serial1.read();
+    // add rx byte to array
+    rx_bytes[rx_byte_index].value = inChar;
+    rx_bytes[rx_byte_index].time  = millis();
+    if (++rx_byte_index >= ROW_COUNT(rx_bytes))
+      rx_byte_index = 0;
+  }
+}
+
 void loop(void) {
   // bitlash job
   runBitlash();


Shorten status line to fit in the buffer we use

--- RightpointLabs.Pourcast.Arduino/RightpointLabs.Pourcast.Arduino.ino
+++ RightpointLabs.Pourcast.Arduino/RightpointLabs.Pourcast.Arduino.ino
@@ -167,7 +167,7 @@
 void writeStatus() {
   char buf[128];
   PString pBuf(buf, 128);
-  pBuf << "Status: free memory: " << freeMemory() << ", Lowest: " << http->_minFreeMemory << ", lastWatch: " << lastWatch << ", maxWatch: " << maxWatch;
+  pBuf << "S:FM: " << freeMemory() << ",L: " << http->_minFreeMemory << ",LW: " << lastWatch << ",MW: " << maxWatch;
   http->LogMessage(buf);
 }