my first Arduino controlled robot - operated by IR remote

error: pathspec 'ir_robot_control/ir_robot_control.ino' did not match any file(s) known to git

--- ir_robot_control/ir_robot_control.ino
+++ ir_robot_control/ir_robot_control.ino
@@ -0,0 +1,391 @@
+#include <IRremote.h>
+#include <SoftwareSerial.h>
+
+/****************************************
+ *                                      *
+ * Constants                            *
+ *                                      *
+ * There were name clashes in Arduino   *
+ * thus this code uses ROBOT_ prefix    *
+ *                                      *
+ ****************************************/
+
+#define ROBOT_DIRECTIONS 8
+
+// bit mask for directions
+// 10000000
+#define ROBOT_N 1 << 7
+// 00010000
+#define ROBOT_S 1 << 4
+// 00001000
+#define ROBOT_E 1 << 3
+// 00000001
+#define ROBOT_W 1
+#define ROBOT_NE ROBOT_N | ROBOT_E
+#define ROBOT_NW ROBOT_N | ROBOT_W
+#define ROBOT_SE ROBOT_S | ROBOT_E
+#define ROBOT_SW ROBOT_S | ROBOT_W
+// special direction
+#define ROBOT_NO_MOVE 0
+
+/****************************************
+ *                                      *
+ * IR Remotes                           *
+ *                                      *
+ * Based on type different codes used   *
+ *                                      *
+ ****************************************/
+
+// Sony Bravia TV
+// note: my Sony Bravia - may differ for other models
+#define ROBOT_REMOTE_SONY 1
+// circuits.io simulator
+#define ROBOT_REMOTE_CIRCUITS_IO 2
+// Philips Mini Tower
+// note: my Philips Mini Towe - may differ for other models
+#define ROBOT_REMOTE_PHILIPS 3
+
+/****************************************
+ *                                      *
+ * Select the remote type               *
+ *                                      *
+ ****************************************/
+
+#define ROBOT_REMOTE_SELECTED ROBOT_REMOTE_SONY
+
+#if defined ROBOT_REMOTE_SELECTED == ROBOT_REMOTE_SONY
+
+#define ROBOT_IR_REMOTE_1 0x207BEF0F
+#define ROBOT_IR_REMOTE_2 0xE8455D8E
+#define ROBOT_IR_REMOTE_3 0xCBB7E949
+#define ROBOT_IR_REMOTE_4 0x2C1F3172
+#define ROBOT_IR_REMOTE_6 0x8CE1E3FC
+#define ROBOT_IR_REMOTE_7 0x315B1905
+#define ROBOT_IR_REMOTE_8 0xC67C01B6
+#define ROBOT_IR_REMOTE_9 0xB418D969
+#define ROBOT_IR_REMOTE_FUNC 0x2B4DA162
+
+#endif
+
+#if defined ROBOT_REMOTE_SELECTED == ROBOT_REMOTE_PHILIPS
+
+#define ROBOT_IR_REMOTE_1 0xC54DA1E5
+#define ROBOT_IR_REMOTE_2 0xDD54FA64
+#define ROBOT_IR_REMOTE_3 0x52394D26
+#define ROBOT_IR_REMOTE_4 0x90A84C9A
+#define ROBOT_IR_REMOTE_6 0xBBB5D0DB
+#define ROBOT_IR_REMOTE_7 0x898E1742
+#define ROBOT_IR_REMOTE_8 0xAFBC74A
+#define ROBOT_IR_REMOTE_9 0xBAEBCA37
+#define ROBOT_IR_REMOTE_FUNC 0xA26697EF
+
+#endif
+
+#if defined ROBOT_REMOTE_SELECTED == ROBOT_REMOTE_CIRCUITS_IO
+
+#define ROBOT_IR_REMOTE_1 0xFD08F7
+#define ROBOT_IR_REMOTE_2 0xFD8877
+#define ROBOT_IR_REMOTE_3 0xFD48B7
+#define ROBOT_IR_REMOTE_4 0xFD28D7
+#define ROBOT_IR_REMOTE_6 0xFD6897
+#define ROBOT_IR_REMOTE_7 0xFD18E7
+#define ROBOT_IR_REMOTE_8 0xFD9867
+#define ROBOT_IR_REMOTE_9 0xFD58A7
+#define ROBOT_IR_REMOTE_FUNC 0XFD40BF
+
+#endif
+
+// motor 1 pins
+#define ROBOT_RIGHT_MOTOR_PIN1 10
+#define ROBOT_RIGHT_MOTOR_PIN2 9
+// motor 2 pins
+#define ROBOT_LEFT_MOTOR_PIN1 5
+#define ROBOT_LEFT_MOTOR_PIN2 3
+// IR pin
+#define ROBOT_IR_PIN 11
+
+// move lenght in ms
+#define ROBOT_MOVE_LENGHT 4000
+// turn 90 degrees lenght in ms
+#define ROBOT_TURN_LENGHT 650
+// delay lenght in ms
+#define ROBOT_DELAY_LENGHT 20
+// delay in the loop function
+#define ROBOT_DELAY_LOOP 1000
+
+
+/****************************************
+ *                                      *
+ *  Lists                               *
+ *                                      *
+ ****************************************/
+
+struct node {
+  unsigned char direction;
+  struct node *next;
+};
+
+struct node* create_node(unsigned char direction) {
+  struct node* node = (struct node*) malloc(sizeof(struct node));
+  node->direction = direction;
+  node->next = NULL;
+  return node;
+}
+
+struct node* add_node(struct node* nodes, unsigned char direction) {
+  struct node* last = nodes;
+  while (last->next != NULL) {
+    last = last->next;
+  }
+  struct node* node = create_node(direction);
+  last->next = node;
+  return node;
+}
+
+void free_list(struct node* list) {
+  struct node* tmp;
+
+  while (list != NULL) {
+    tmp = list;
+    list = list->next;
+    free(tmp);
+  }
+
+  list = NULL;
+}
+
+/****************************************
+ *                                      *
+ * Maps                                 *
+ *                                      *
+ ****************************************/
+
+struct map {
+  unsigned char direction;
+  unsigned long code;
+  struct map *next;
+};
+
+
+struct map* create_map(unsigned char direction, unsigned long code) {
+  struct map* map = (struct map*) malloc(sizeof(struct map));
+  map->direction = direction;
+  map->code = code;
+  map->next = NULL;
+  return map;
+}
+
+struct map* add_item(struct map* map, unsigned char direction, unsigned long code) {
+  struct map* last = map;
+  while (last->next != NULL) {
+    last = last->next;
+  }
+  struct map* item = create_map(direction, code);
+  last->next = item;
+  return item;
+}
+
+struct map* find_item_by_direction(struct map* map, unsigned char direction) {
+  struct map* last = map;
+  while (last != NULL) {
+    if (last->direction == direction) {
+      return last;
+    }
+    last = last->next;
+  }
+  return NULL;
+}
+
+struct map* find_item_by_code(struct map* map, unsigned long code) {
+  struct map* last = map;
+  while (last != NULL) {
+    if (last->code == code) {
+      return last;
+    }
+    last = last->next;
+  }
+  return NULL;
+}
+
+/****************************************
+ *                                      *
+ * Moving Robot                         *
+ *                                      *
+ ****************************************/
+
+void move(unsigned char forward, unsigned int delayMs) {
+  digitalWrite(ROBOT_RIGHT_MOTOR_PIN1, forward);
+  digitalWrite(ROBOT_RIGHT_MOTOR_PIN2, !forward);
+
+  digitalWrite(ROBOT_LEFT_MOTOR_PIN1, forward);
+  digitalWrite(ROBOT_LEFT_MOTOR_PIN2, !forward);
+
+  delay(delayMs);
+}
+
+void forward(unsigned int delayMs) {
+  Serial.println("Forward");
+
+  move(HIGH, delayMs);
+}
+
+void reverse(unsigned int delayMs) {
+  Serial.println("Reverse");
+
+  move(LOW, delayMs);
+}
+
+void stop() {
+  digitalWrite(ROBOT_RIGHT_MOTOR_PIN1, LOW);
+  digitalWrite(ROBOT_RIGHT_MOTOR_PIN2, LOW);
+
+  digitalWrite(ROBOT_LEFT_MOTOR_PIN1, LOW);
+  digitalWrite(ROBOT_LEFT_MOTOR_PIN2, LOW);
+
+  delay(ROBOT_DELAY_LENGHT);
+}
+
+
+void turn(float delayMs, unsigned char left, unsigned char right) {
+  digitalWrite(ROBOT_LEFT_MOTOR_PIN1, left);
+  digitalWrite(ROBOT_LEFT_MOTOR_PIN2, !left);
+
+  digitalWrite(ROBOT_RIGHT_MOTOR_PIN1, right);
+  digitalWrite(ROBOT_RIGHT_MOTOR_PIN2, !right);
+
+  delay(delayMs);
+}
+
+void left(float delayMs) {
+  Serial.print("Left ");
+  Serial.print(delayMs / ROBOT_TURN_LENGHT * 90);
+  Serial.println(" degrees");
+
+  turn(delayMs, LOW, HIGH);
+}
+
+void right(float delayMs) {
+  Serial.print("Right ");
+  Serial.print(delayMs / ROBOT_TURN_LENGHT * 90);
+  Serial.println(" degrees");
+
+  turn(delayMs, HIGH, LOW);
+
+}
+
+void execute(unsigned long direction) {
+  switch (direction) {
+    case ROBOT_N:
+      forward(ROBOT_MOVE_LENGHT);
+      break;
+    case ROBOT_S:
+      reverse(ROBOT_MOVE_LENGHT);
+      break;
+    case ROBOT_W:
+      left(ROBOT_TURN_LENGHT);
+      break;
+    case ROBOT_NW:
+      left(ROBOT_TURN_LENGHT / 2);
+      break;
+    case ROBOT_SW:
+      left(ROBOT_TURN_LENGHT + ROBOT_TURN_LENGHT / 2);
+      break;
+    case ROBOT_E:
+      right(ROBOT_TURN_LENGHT);
+      break;
+    case ROBOT_NE:
+      right(ROBOT_TURN_LENGHT / 2);
+      break;
+    case ROBOT_SE:
+      right(ROBOT_TURN_LENGHT + ROBOT_TURN_LENGHT / 2);
+      break;
+  }
+  stop();
+}
+
+void replay_moves(struct node* list) {
+  struct node* tmp = list;
+  while (tmp != NULL) {
+    execute(tmp->direction);
+    tmp = tmp->next;
+  }
+}
+
+/****************************************
+ *                                      *
+ * Global variables                     *
+ *                                      *
+ ****************************************/
+
+IRrecv irrecv(ROBOT_IR_PIN);
+struct map* codes;
+struct node* directions;
+bool programming = 0;
+
+/****************************************
+ *                                      *
+ *  Arduino functions                   *
+ *                                      *
+ ****************************************/
+
+void setup() {
+  Serial.begin(9600);
+  irrecv.enableIRIn();
+
+  Serial.println("=======================");
+  Serial.print("Using remote with programming button ");
+  Serial.print(ROBOT_IR_REMOTE_FUNC, HEX);
+  Serial.println();
+
+  pinMode(ROBOT_RIGHT_MOTOR_PIN1, OUTPUT);
+  pinMode(ROBOT_RIGHT_MOTOR_PIN2, OUTPUT);
+
+  pinMode(ROBOT_LEFT_MOTOR_PIN1, OUTPUT);
+  pinMode(ROBOT_LEFT_MOTOR_PIN2, OUTPUT);
+
+  pinMode(ROBOT_IR_PIN, INPUT);
+
+  pinMode(LED_BUILTIN, OUTPUT);
+
+  codes = create_map(ROBOT_N, ROBOT_IR_REMOTE_2);
+  add_item(codes, ROBOT_NE, ROBOT_IR_REMOTE_3);
+  add_item(codes, ROBOT_E, ROBOT_IR_REMOTE_6);
+  add_item(codes, ROBOT_SE, ROBOT_IR_REMOTE_9);
+  add_item(codes, ROBOT_S, ROBOT_IR_REMOTE_8);
+  add_item(codes, ROBOT_SW, ROBOT_IR_REMOTE_7);
+  add_item(codes, ROBOT_W, ROBOT_IR_REMOTE_4);
+  add_item(codes, ROBOT_NW, ROBOT_IR_REMOTE_1);
+}
+
+void loop() {
+  decode_results results;
+  if (irrecv.decode(&results)) {
+    irrecv.resume();
+    if (results.value == ROBOT_IR_REMOTE_FUNC) {
+      programming = !programming;
+      if (programming) {
+        digitalWrite(LED_BUILTIN, HIGH);
+      } else {
+        digitalWrite(LED_BUILTIN, LOW);
+        replay_moves(directions);
+        free_list(directions);
+      }
+    } else {
+      struct map* item = find_item_by_code(codes, results.value);
+
+      if (item != NULL) {
+        if (programming) {
+          if (directions == NULL) {
+            directions = create_node(item->direction);
+          } else {
+            add_node(directions, item->direction);
+          }
+        } else {
+          execute(item->direction);
+        }
+      }
+    }
+  }
+  delay(ROBOT_DELAY_LOOP);
+}
+


HC-05 Example

HC-05 Example

error: pathspec 'examples/bluetooth_hc05/bluetooth_hc05/bluetooth_hc05.ino' did not match any file(s) known to git

--- examples/bluetooth_hc05/bluetooth_hc05/bluetooth_hc05.ino
+++ examples/bluetooth_hc05/bluetooth_hc05/bluetooth_hc05.ino
@@ -0,0 +1,78 @@
+#include <can.h>
+#include <mcp2515.h>
+
+#include <CanHacker.h>
+#include <CanHackerLineReader.h>
+#include <lib.h>
+
+#include <SPI.h>
+
+const int SPI_CS_PIN = 10; // 10 by default, 53 on mega
+const int INT_PIN = 2;
+
+CanHackerLineReader *lineReader = NULL;
+CanHacker *canHacker = NULL;
+
+void setup() {
+    Serial.begin(115200);
+    while (!Serial);
+    Serial1.begin(57600);
+    while (!Serial1);
+    SPI.begin();
+
+    Stream *interfaceStream = &Serial1;
+    Stream *debugStream = &Serial;
+
+
+    canHacker = new CanHacker(interfaceStream, debugStream, SPI_CS_PIN);
+    canHacker->enableLoopback(); // uncomment this for loopback
+    lineReader = new CanHackerLineReader(canHacker);
+
+    pinMode(INT_PIN, INPUT);
+}
+
+void loop() {
+    CanHacker::ERROR error;
+
+    if (digitalRead(INT_PIN) == LOW) {
+        error = canHacker->processInterrupt();
+        handleError(error);
+    }
+
+    error = lineReader->process();
+    handleError(error);
+}
+
+void handleError(const CanHacker::ERROR error) {
+
+    switch (error) {
+        case CanHacker::ERROR_OK:
+        case CanHacker::ERROR_UNKNOWN_COMMAND:
+        case CanHacker::ERROR_NOT_CONNECTED:
+        case CanHacker::ERROR_MCP2515_ERRIF:
+        case CanHacker::ERROR_INVALID_COMMAND:
+            return;
+
+        default:
+            break;
+    }
+
+    Serial.print("Failure (code ");
+    Serial.print((int)error);
+    Serial.println(")");
+
+    digitalWrite(SPI_CS_PIN, HIGH);
+    pinMode(LED_BUILTIN, OUTPUT);
+
+    while (1) {
+        int c = (int)error;
+        for (int i=0; i<c; i++) {
+            digitalWrite(LED_BUILTIN, HIGH);
+            delay(500);
+            digitalWrite(LED_BUILTIN, LOW);
+            delay(500);
+        }
+
+        delay(2000);
+    } ;
+}


Messing about with my node-red vibes

Messing about with my node-red vibes

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/rniemand/ArduinoProjects.git/'


Second prototype with most of the necessary code

error: pathspec 'balloon_proto_2/balloon_proto_2.ino' did not match any file(s) known to git

--- balloon_proto_2/balloon_proto_2.ino
+++ balloon_proto_2/balloon_proto_2.ino
@@ -0,0 +1,175 @@
+#include <Arduino.h>
+#include <si5351.h>
+#include <JTEncode.h>
+#include <rs_common.h>
+#include <int.h>
+#include <math.h>
+#include <string.h>
+#include <TinyGPS.h>
+#include <SoftwareSerial.h>
+#include <Wire.h>
+
+
+#define WSPR_TONE_SPACING       146           // ~1.46 Hz
+#define WSPR_CTC                10672         // CTC value for WSPR
+#define WSPR_DEFAULT_FREQ       14150000UL    // 10140200UL
+
+Si5351 si5351;
+JTEncode jtencode;
+TinyGPS gps;
+SoftwareSerial ss(4, 2);
+
+unsigned long freq;
+char message[] = "KD8UPW EM79";
+char call[] = "KD8UPW";
+char loc[] = "EM79";
+uint8_t dbm = 27;
+uint8_t tx_buffer[255];
+uint8_t symbol_count;
+uint16_t ctc, tone_spacing;
+
+// Global variables used in ISRs
+volatile bool proceed = false;
+volatile bool processing = false;
+
+// Timer interrupt vector.  This toggles the variable we use to gate
+// each column of output to ensure accurate timing.  Called whenever
+// Timer1 hits the count set below in setup().
+ISR(TIMER1_COMPA_vect)
+{
+  if(!processing) {
+    proceed = true;
+  }
+}
+
+void setup() {
+  ss.begin(9600);
+
+  freq = WSPR_DEFAULT_FREQ;
+  ctc = WSPR_CTC;
+  symbol_count = WSPR_SYMBOL_COUNT; // From the library defines
+  tone_spacing = WSPR_TONE_SPACING;
+
+  // Initialize the Si5351
+  // Change the 2nd parameter in init if using a ref osc other
+  // than 25 MHz
+  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
+
+  // Set CLK0 output
+  si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Set for max power if desired
+  si5351.output_enable(SI5351_CLK0, 0); // Disable the clock initially
+
+  // Set up Timer1 for interrupts every symbol period.
+  noInterrupts();          // Turn off interrupts.
+  TCCR1A = 0;              // Set entire TCCR1A register to 0; disconnects
+                           //   interrupt output pins, sets normal waveform
+                           //   mode.  We're just using Timer1 as a counter.
+  TCNT1  = 0;              // Initialize counter value to 0.
+  TCCR1B = (1 << CS12) |   // Set CS12 and CS10 bit to set prescale
+    (1 << CS10) |          //   to /1024
+    (1 << WGM12);          //   turn on CTC
+                           //   which gives, 64 us ticks
+  TIMSK1 = (1 << OCIE1A);  // Enable timer compare interrupt.
+  OCR1A = ctc;             // Set up interrupt trigger count;
+  interrupts();            // Re-enable interrupts.
+}
+
+void loop() {
+  if(proceed) {
+    processing = true;
+    if(can_transmit()) {
+      encode();
+    }
+    processing = false;
+  }
+}
+
+bool can_transmit() {
+  float lat, lon;
+  unsigned long fix_age;
+  int year, retries;
+  byte month, day, hour, minute, second, hundredths;
+
+  populate_gps_data();
+  while (retries < 10) {
+    gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &fix_age);
+    if (fix_age != TinyGPS::GPS_INVALID_AGE) {
+      break;
+    }
+    delay(1000);
+    populate_gps_data();
+  }
+  if (retries >= 10) {
+    return false;
+  }
+  gps.f_get_position(&lat, &lon, &fix_age);
+  if (!valid_coords(lat, lon)) {
+    return false;
+  }
+  if(minute % 2 != 0) {
+    delay((60 - second) * 1000);
+  }
+  to_maidenhead(lat, lon);
+  return true;
+}
+
+void populate_gps_data() {
+  while (true) {
+    while (ss.available()) {
+      if (gps.encode(ss.read())) {
+        return;
+      }
+    }
+  }
+}
+
+bool valid_coords(double lat, double lon) {
+  if(lat <= 0) // equator or South
+    return false;
+  if(lon < -169 || lon > -19) // Alaska and Africa
+    return false;
+  return true;
+}
+
+void to_maidenhead(double lat, double lon) {
+  lat += 90;
+  lon += 180;
+  loc[0] = 'A' + (int)floor(lon / 20);
+  loc[1] = 'A' + (int)floor(lat / 10);
+  loc[2] = (int)floor(fmod((lon / 2), 10.0)) + '0';
+  loc[3] = (int)floor(fmod(lat, 10.0)) + '0';
+//  double rLat = (lat - floor(lat)) * 60;
+//  double rLon = (lon - 2 * floor(lon / 2)) * 60;
+//  loc[4] = 'a' + (int)floor(rLon / 5);
+//  loc[5] = 'a' + (int)floor(rLat / 2.5);
+  loc[5] = '\0';
+}
+
+// Loop through the string, transmitting one character at a time.
+void encode()
+{
+  uint8_t i;
+
+  // Clear out the old transmit buffer
+  memset(tx_buffer, 0, 255);
+
+  // Set the proper frequency and timer CTC depending on mode
+  jtencode.wspr_encode(call, loc, dbm, tx_buffer);
+
+  // Reset the tone to the base frequency and turn on the output
+  si5351.output_enable(SI5351_CLK0, 1);
+//  digitalWrite(LED_PIN, HIGH);
+
+  for(i = 0; i < symbol_count; i++)
+  {
+      si5351.set_freq((freq * 100) + (tx_buffer[i] * tone_spacing), SI5351_CLK0);
+      proceed = false;
+      while(!proceed);
+  }
+
+  // Turn off the output
+  si5351.output_enable(SI5351_CLK0, 0);
+  //digitalWrite(LED_PIN, LOW);
+}
+
+


Added a default firmware sketch that has the syntax I would like to use.

error: pathspec 'examples/default.ino' did not match any file(s) known to git

--- examples/default.ino
+++ examples/default.ino
@@ -0,0 +1,89 @@
+/**
+ * Example firmware that starts up the Platypus Controller with default settings.
+ *
+ * Copyright (c) 2014, Platypus LLC. All rights reserved.
+ */
+#include <Platypus.h>
+
+// Create an instance of the Platypus Controller.
+platypus::Controller controller;
+
+// Set up the devices that we want to use on the DrivePort.
+// For this example, we configure two servos.
+platypus::ServoMotor motor0;
+platypus::ServoMotor motor1;
+platypus::DrivePort motors[2] = { motor0, motor1 };
+
+// Set up the devices that we want to use on the MultiPorts.
+// For this example, we configure four analog sensors.
+int sampleRate = 100; // Sampling rate in Hz
+
+// Analog sensors return (voltage - offset) * scale.
+float offset = 2.5;
+float scale = 1.0;
+
+platypus::AnalogSensor sensor0(sampleRate, offset, scale);
+platypus::AnalogSensor sensor1(sampleRate, offset, scale);
+platypus::AnalogSensor sensor2(sampleRate, offset, scale);
+platypus::AnalogSensor sensor3(sampleRate, offset, scale);
+platypus::DrivePort sensors[4] = { sensor0, sensor1, sensor2, sensor3 };
+
+// Create some references that will hold stream descriptors for JSON commands
+// and the text debugging console.
+Stream command;
+Stream console;
+
+void setup()
+{
+    // Initialize the Platypus Controller.
+    controller.begin();
+
+    // You can configure drive ports individually:
+    controller.setDrivePort(0, motor0);
+    controller.setDrivePort(1, motor1);
+
+    // Or you can set them all at once:
+    controller.setDrivePorts(motors);
+
+    // You can configure multi ports individually:
+    controller.setMultiPort(0, sensor0);
+    controller.setMultiPort(1, sensor1);
+    controller.setMultiPort(2, sensor2);
+    controller.setMultiPort(3, sensor3);
+
+    // Or you can set them all at once:
+    controller.setMultiPorts(sensors);
+
+    // Get a reference to the JSON command/response stream.
+    command = controller.command();
+
+    // Get a reference to the string debugging stream.
+    console = controller.console();
+}
+
+void loop()
+{
+    // You don't have to do anything in here, but you can create your own
+    // logic such as manipulating LEDs or printing status regularly.
+
+    // Blink the LED every second, with the color indicating whether we are
+    // connected to Android.
+    controller.led.rgb(0,0,0);
+    delay(500);
+    if (controller.isConnected())
+    {
+        controller.led.rgb(255,0,0);
+    }
+    else
+    {
+        controller.led.rgb(0,255,0);
+    }
+    delay(500);
+
+    // Send a JSON status command to Android.
+    // All commands must be newline terminated JSON strings.
+    printf(command, "{\"status\": \"OK\"}\n");
+
+    // Print the same status to the debugging console.
+    printf(console, "STATUS: OK\n");
+}


initial commit

initial commit

error: pathspec 'examples/HelloWorld/HelloWorld.ino' did not match any file(s) known to git

--- examples/HelloWorld/HelloWorld.ino
+++ examples/HelloWorld/HelloWorld.ino
@@ -0,0 +1,26 @@
+//
+// "Hello World" for Tlc59711 library
+//
+// 27 Feb 2016 by Ulrich Stern
+//
+// open source (see LICENSE file)
+//
+
+#include <Tlc59711.h>
+
+const int NUM_TLC = 2;
+
+Tlc59711 tlc(NUM_TLC);
+
+void setup() {
+  tlc.beginFast();
+}
+
+void loop() {
+  for (int i=0; i<2; i++) {
+    tlc.setRGB(65535*i, 6554*i, 655*i);
+    tlc.write();
+    delay(200);
+  }
+}
+


added sweep function for testing

added sweep function for testing

error: pathspec 'Servos/servo_calibration/servo_calibration.ino' did not match any file(s) known to git

--- Servos/servo_calibration/servo_calibration.ino
+++ Servos/servo_calibration/servo_calibration.ino
@@ -0,0 +1,40 @@
+#include <Servo.h>
+
+Servo servo;
+
+/* low and high positions for all 9 arduinos, labeled and corresponding to the array index */
+int servo_low[] = {110};
+int servo_high[] = {175, 180};
+
+void setup()
+{
+  Serial.begin(9600);
+
+  servo.attach(9);
+
+
+}
+
+void sweep_servo()
+{
+  Serial.println(servo.read());
+  int height = servo.read();
+  while(height > servo_low[0])
+  {
+    height--;
+    servo.write(height);
+    delay(20);
+  }
+  while(height < servo_high[0])
+  {
+    height++;
+    servo.write(height);
+    delay(20);
+  }
+}
+
+void loop()
+{
+  sweep_servo();
+
+}


Initial Code Sample Commit

Initial Code Sample Commit

error: pathspec 'ATTinyRFSerialTest.ino' did not match any file(s) known to git


add M5ez + MQTT based user interface

add M5ez + MQTT based user interface

error: pathspec '_m5stack/scan2drive-ui-m5stack.ino' did not match any file(s) known to git

--- _m5stack/scan2drive-ui-m5stack.ino
+++ _m5stack/scan2drive-ui-m5stack.ino
@@ -0,0 +1,170 @@
+#include <M5ez.h>
+#include <WiFi.h>
+#include <PubSubClient.h>
+
+WiFiClient wificlient;
+PubSubClient client(wificlient);
+
+void redraw(void);
+
+void connectToWiFi(void) {
+  Serial.println("WiFi: configuring");
+  WiFi.mode(WIFI_STA);
+  // required to set hostname properly:
+  // https://github.com/espressif/arduino-esp32/issues/3438#issuecomment-721428310
+  WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
+  WiFi.setHostname("uiscan2drive");
+  WiFi.begin("mywifinetwork", "secret");
+  while (WiFi.status() != WL_CONNECTED) {
+    Serial.println("WiFi: connecting...");
+    delay(100);
+  }
+  Serial.print("WiFi: connected: mac=");
+  Serial.print(WiFi.macAddress());
+  Serial.print(" ip=");
+  Serial.print(WiFi.localIP());
+  Serial.println("");
+}
+
+void taskmqtt(void *pvParameters) {
+  for (;;) {
+    if (!client.connected()) {
+      client.connect("ui_scan2drive" /* clientid */);
+      client.subscribe("scan2drive/ui/status");
+      client.subscribe("scan2drive/ui/user");
+    }
+
+    // Poll PubSubClient for new messages and invoke the callback.
+    // Should be called as infrequent as one is willing to delay
+    // reacting to MQTT messages.
+    // Should not be called too frequently to avoid strain on
+    // the network hardware:
+    // https://github.com/knolleary/pubsubclient/issues/756#issuecomment-654335096
+    client.loop();
+    vTaskDelay(pdMS_TO_TICKS(100));
+  }
+}
+
+// Size determined by how much space we have on the LCD display.
+// m5ez does line wrapping for us.
+char statusbuffer[140] = {'\0'};
+
+void callback(char* topic, byte* payload, unsigned int length) {
+#if 0
+  Serial.print("Message arrived [");
+  Serial.print(topic);
+  Serial.print("] ");
+  for (int i = 0; i < length; i++) {
+    Serial.print((char)payload[i]);
+  }
+  Serial.println();
+#endif
+
+  if (strcmp(topic, "scan2drive/ui/status") == 0) {
+    int len = length;
+    if (len > sizeof(statusbuffer)) {
+      len = sizeof(statusbuffer) - 1;
+    }
+    strncpy(statusbuffer, (const char*)payload, len);
+    statusbuffer[len] = '\0';
+    if (strcmp(statusbuffer, "powersave") == 0) {
+      m5.lcd.setBrightness(0);
+    } else {
+      m5.lcd.setBrightness(100);
+    }
+    redraw();
+  }
+}
+
+void setup() {
+  Serial.begin(115200);
+  Serial.println("setup");
+#include <themes/default.h>
+#include <themes/dark.h>
+  ezt::setDebug(INFO);
+  // ez.begin() calls m5.begin() under the covers:
+  ez.begin();
+  redraw();
+
+  connectToWiFi();
+
+  client.setServer("dr.lan", 1883);
+  client.setCallback(callback);
+
+  xTaskCreatePinnedToCore(taskmqtt, "MQTT", 2048, NULL, 1, NULL, PRO_CPU_NUM);
+
+}
+
+int source = 0;
+const char *sourceIdentifiers[] = {
+  "usb",
+  "airscan",
+};
+const char *sourceLabels[] = {
+  "Fujitsu ScanSnap",
+  "Brother (AirScan)",
+};
+
+static bool destSubmenu = false;
+
+void redraw(void) {
+  //ez.screen.clear();
+  ez.canvas.reset();
+
+  ez.header.show("scan2drive");
+  if (destSubmenu) {
+    ez.buttons.show("M Privat # M Verein # exit");
+  } else {
+    ez.buttons.show("Lea # dest # source");
+  }
+  ez.canvas.lmargin(10);
+
+  ez.canvas.println("");
+  ez.canvas.font(&FreeSansBold12pt7b);
+  ez.canvas.printf("Source: ");
+  ez.canvas.font(&FreeSans12pt7b);
+  ez.canvas.println(sourceLabels[source]);
+
+  ez.canvas.font(&FreeSansBold12pt7b);
+  ez.canvas.printf("Status: ");
+  ez.canvas.font(&FreeSans12pt7b);
+  ez.canvas.println(statusbuffer);
+
+  ez.redraw();
+}
+
+void loop() {
+  String buttonName = ez.buttons.poll();
+  if (buttonName == "source") {
+    source = (source + 1) % 2;
+    redraw();
+    return;
+  }
+  if (buttonName == "dest") {
+    destSubmenu = true;
+    redraw();
+    return;
+  }
+  if (buttonName == "exit") {
+    destSubmenu = false;
+    redraw();
+    return;
+  }
+  String user = "Lea";
+  if (buttonName == "Lea") {
+  } else if (buttonName == "M Privat") {
+    user = "Michael Stapelberg";
+  } else if (buttonName == "M Verein") {
+    user = "Michael";
+  } else {
+    return;
+  }
+  String payload = String("{\"user\":\"") +
+                   user +
+                   String("\", \"source\": \"") +
+                   String(sourceIdentifiers[source]) +
+                   String("\"}");
+  client.publish("scan2drive/cmd/scan", payload.c_str());
+  destSubmenu = false;
+  redraw();
+}


Create MRLCommOculus3.ino

Create MRLCommOculus3.ino

error: pathspec 'home/Alessandruino/MRLCommOculus3.ino' did not match any file(s) known to git

--- home/Alessandruino/MRLCommOculus3.ino
+++ home/Alessandruino/MRLCommOculus3.ino
@@ -0,0 +1,1308 @@
+#include "I2Cdev.h"
+#include "MPU6050.h"
+#include <HMC5883L.h>
+#include <L3G4200D.h>
+
+#include <Servo.h>
+
+MPU6050 accelgyro;
+HMC5883L mag;
+L3G4200D gyro;
+
+
+//MPU6050 accelgyro(0x69); // <-- use for AD0 high
+
+int16_t ax, ay, az;
+int16_t gx, gy, gz;
+int16_t ax2, ay2, az2;
+int16_t mx, my, mz;
+int16_t avx, avy, avz;
+int cnt;
+
+#define MRLCOMM_VERSION				21
+
+// serial protocol functions
+#define MAGIC_NUMBER  					170 // 10101010
+
+// ----- MRLCOMM FUNCTION GENERATED INTERFACE BEGIN -----------
+///// INO GENERATED DEFINITION BEGIN //////
+// {publishMRLCommError Integer}
+#define PUBLISH_MRLCOMM_ERROR		1
+
+// {getVersion}
+#define GET_VERSION		2
+
+// {publishVersion Integer}
+#define PUBLISH_VERSION		3
+
+// {analogReadPollingStart Integer}
+#define ANALOG_READ_POLLING_START		4
+
+// {analogReadPollingStop Integer}
+#define ANALOG_READ_POLLING_STOP		5
+
+// {analogWrite Integer Integer}
+#define ANALOG_WRITE		6
+
+// {digitalReadPollingStart Integer}
+#define DIGITAL_READ_POLLING_START		7
+
+// {digitalReadPollingStop Integer}
+#define DIGITAL_READ_POLLING_STOP		8
+
+// {digitalWrite Integer Integer}
+#define DIGITAL_WRITE		9
+
+// {motorAttach String String Integer Integer Integer}
+#define MOTOR_ATTACH		10
+
+// {motorDetach String}
+#define MOTOR_DETACH		11
+
+// {motorMove String}
+#define MOTOR_MOVE		12
+
+// {motorMoveTo String double}
+#define MOTOR_MOVE_TO		13
+
+// {pinMode Integer Integer}
+#define PIN_MODE		14
+
+// {publishCustomMsg Integer}
+#define PUBLISH_CUSTOM_MSG		15
+
+// {publishLoadTimingEvent Long}
+#define PUBLISH_LOAD_TIMING_EVENT		16
+
+// {publishPin Pin}
+#define PUBLISH_PIN		17
+
+// {publishPulse Integer}
+#define PUBLISH_PULSE		18
+
+// {publishServoEvent Integer}
+#define PUBLISH_SERVO_EVENT		19
+
+// {publishSesorData SensorData}
+#define PUBLISH_SESOR_DATA		20
+
+// {publishStepperEvent StepperData}
+#define PUBLISH_STEPPER_EVENT		21
+
+// {publishTrigger Pin}
+#define PUBLISH_TRIGGER		22
+
+// {pulseIn int int int String}
+#define PULSE_IN		23
+
+// {sensorAttach UltrasonicSensor}
+#define SENSOR_ATTACH		24
+
+// {sensorPollingStart String int}
+#define SENSOR_POLLING_START		25
+
+// {sensorPollingStop String}
+#define SENSOR_POLLING_STOP		26
+
+// {servoAttach Servo Integer}
+#define SERVO_ATTACH		27
+
+// {servoDetach String}
+#define SERVO_DETACH		28
+
+// {servoSweepStart String int int int}
+#define SERVO_SWEEP_START		29
+
+// {servoSweepStop String}
+#define SERVO_SWEEP_STOP		30
+
+// {servoWrite String Integer}
+#define SERVO_WRITE		31
+
+// {servoWriteMicroseconds String Integer}
+#define SERVO_WRITE_MICROSECONDS		32
+
+// {setDebounce int}
+#define SET_DEBOUNCE		33
+
+// {setDigitalTriggerOnly Boolean}
+#define SET_DIGITAL_TRIGGER_ONLY		34
+
+// {setLoadTimingEnabled boolean}
+#define SET_LOAD_TIMING_ENABLED		35
+
+// {setPWMFrequency Integer Integer}
+#define SET_PWMFREQUENCY		36
+
+// {setSampleRate int}
+#define SET_SAMPLE_RATE		37
+
+// {setSerialRate int}
+#define SET_SERIAL_RATE		38
+
+// {setServoEventsEnabled String boolean}
+#define SET_SERVO_EVENTS_ENABLED		39
+
+// {setServoSpeed String Float}
+#define SET_SERVO_SPEED		40
+
+// {setStepperSpeed Integer}
+#define SET_STEPPER_SPEED		41
+
+// {setTrigger int int int}
+#define SET_TRIGGER		42
+
+// {softReset}
+#define SOFT_RESET		43
+
+// {stepperAttach StepperControl}
+#define STEPPER_ATTACH		44
+
+// {stepperDetach String}
+#define STEPPER_DETACH		45
+
+// {stepperMoveTo String Integer}
+#define STEPPER_MOVE_TO		46
+
+// {stepperReset String}
+#define STEPPER_RESET		47
+
+// {stepperStep String Integer Integer}
+#define STEPPER_STEP		48
+
+// {stepperStop String}
+#define STEPPER_STOP		49
+
+// {stopService}
+#define STOP_SERVICE		50
+
+///// INO GENERATED DEFINITION END //////
+
+// ----- MRLCOMM FUNCTION GENERATED INTERFACE END -----------
+
+#define STEPPER_TYPE_SIMPLE  			1
+
+// ------ event types ------
+#define STEPPER_EVENT_STOP				1
+
+// servo event types
+#define  SERVO_EVENT_STOPPED			1
+#define  SERVO_EVENT_POSITION_UPDATE 	2
+
+// error types
+#define ERROR_SERIAL					1
+#define ERROR_UNKOWN_CMD				2
+#define ERROR_ALREADY_EXISTS			3
+#define ERROR_DOES_NOT_EXIST			4
+
+// ------ error types ------
+#define SENSOR_ULTRASONIC				1
+
+// need a method to identify type of board
+// http://forum.arduino.cc/index.php?topic=100557.0
+
+#define COMMUNICATION_RESET	   252
+#define SOFT_RESET			   253
+#define NOP  				   255
+
+// ----------  MRLCOMM FUNCTION INTERFACE END -----------
+
+// MAX definitions
+// MAX_SERVOS defined by boardtype/library
+#define PINGDARS_MAX		6
+#define SENSORS_MAX			12
+#define STEPPERS_MAX		6
+
+#define MAX_MOTORS 10
+
+#define ECHO_STATE_START 1
+#define ECHO_STATE_TRIG_PULSE_BEGIN 2
+#define ECHO_STATE_TRIG_PULSE_END 3
+#define ECHO_STATE_MIN_PAUSE_PRE_LISTENING 4
+#define ECHO_STATE_LISTENING 5
+#define ECHO_STATE_GOOD_RANGE	6
+#define ECHO_STATE_TIMEOUT	7
+
+// --VENDOR DEFINE SECTION BEGIN--
+// --VENDOR DEFINE SECTION END--
+
+// FIXME FIXME FIXME
+// -- FIXME - modified by board type BEGIN --
+// Need Arduino to do a hardware abstraction layer
+// https://code.google.com/p/arduino/issues/detail?id=59
+// AHAAA !! - many defintions in - pins_arduino.h !!!
+// Need a "board" identifier at least !!!
+
+#define ANALOG_PIN_COUNT 16 // mega
+#define DIGITAL_PIN_COUNT 54 // mega
+// #define MAX_SERVOS 48 - is defined @ compile time !!
+// -- FIXME - modified by board type END --
+
+#define ARDUINO_TYPE_INT 16; // :) type identifier - not size - but what the hell ;)
+
+/*
+* TODO - CRC for last byte
+* getCommand - retrieves a command message
+* inbound and outbound messages are the same format, the following represents a basic message
+* format
+*
+* MAGIC_NUMBER|NUM_BYTES|FUNCTION|DATA0|DATA1|....|DATA(N)
+*              NUM_BYTES - is the number of bytes after NUM_BYTES to the end
+*
+*/
+
+int msgSize = 0; // the NUM_BYTES of current message
+
+unsigned int debounceDelay = 50; // in ms
+long lastDebounceTime[DIGITAL_PIN_COUNT];
+byte msgBuf[64];
+
+typedef struct
+  {
+      int type;
+      int trigPin;
+      int echoPin;
+      bool isRunning;
+      int timeoutUS;
+      unsigned long ts;
+      unsigned long lastValue;
+      int state;
+      //NewPing* ping;
+  }  sensor_type;
+
+sensor_type sensors[SENSORS_MAX];
+
+typedef struct
+  {
+  	  int ts;
+      int type;
+      int index; // is this redundant?
+      int currentPos;
+      int targetPos;
+      int speed;
+      int dir; // not needed ? dirPin or currentPos - targetPos keeps state
+      bool isRunning; // don't need this if compare currentPos with targetPos
+
+      int dirPin;
+      int stepPin;
+
+	  // support up to 5 wire steppers
+      int pin0;
+      int pin1;
+      int pin2;
+      int pin3;
+      int pin4;
+
+  }  stepper_type;
+
+stepper_type steppers[STEPPERS_MAX];
+
+// Servos
+typedef struct
+{
+    Servo* servo;
+    int index; // index of this servo
+    int speed;
+    int targetPos;
+    int currentPos;
+    bool isMoving;
+
+    int step; // affects speed usually 1
+
+    // sweep related
+    int min;
+    int max;
+    // int delay; - related to speed
+    int increment;
+    bool isSweeping;
+
+    // event related
+    bool eventsEnabled;
+} servo_type;
+
+
+servo_type servos[MAX_SERVOS];
+
+// Motors
+typedef struct {
+    int index; // index of this motor
+    int speed;
+    int targetPos;
+    int currentPos;
+    bool isMoving;
+
+    int step; // affects speed usually 1
+
+    // sweep related
+    int min;
+    int max;
+    // int delay; - related to speed
+    int increment;
+    bool isSweeping;
+
+    // event related
+    bool eventsEnabled;
+} motor_type;
+
+motor_type motors[MAX_MOTORS];
+
+unsigned long loopCount     = 0;
+unsigned long lastMicros 	= 0;
+int byteCount               = 0;
+unsigned char newByte 		= 0;
+unsigned char ioCmd[64];  // message buffer for all inbound messages
+int readValue;
+
+// FIXME - normalize with sampleRate ..
+int loadTimingModulus = 1000;
+
+boolean loadTimingEnabled = false;
+unsigned long loadTime = 0;
+// TODO - avg load time
+
+unsigned int sampleRate = 1; // 1 - 65,535 modulus of the loopcount - allowing you to sample less
+
+int digitalReadPin[DIGITAL_PIN_COUNT];        // array of pins to read from
+int digitalReadPollingPinCount = 0;           // number of pins currently reading
+int lastDigitalInputValue[DIGITAL_PIN_COUNT]; // array of last input values
+bool digitalTriggerOnly	= false;      // send data back only if its different
+
+int analogReadPin[ANALOG_PIN_COUNT];          // array of pins to read from
+int analogReadPollingPinCount = 0;            // number of pins currently reading
+int lastAnalogInputValue[ANALOG_PIN_COUNT];   // array of last input values
+bool analogTriggerOnly = false;         // send data back only if its different
+
+//---- data record definitions begin -----
+
+
+// TODO - all well and good .. but you dont control Servo's data (yet)
+// should have a struct for it too - contains all the data info you'd want to have
+// in a servo - same with stepper
+
+typedef struct
+  {
+      int servoIndex; // id of servo in servos array
+      //int servoPos; in servo
+      int sensorIndex;
+      int sweepMin;
+      int sweepMax;
+      int step;
+      bool isRunning; // needed ? - is combo of two
+  }  pingdar_type;
+
+pingdar_type pingdars[PINGDARS_MAX];
+//===custom msg interface begin===
+	byte customParams[256];
+	int paramBuffIndex;
+	int paramCnt;
+//===custom msg interface end===
+
+
+/* could optimize - but makes for ugly code - just to save a couple clock cycles - counting to 6 :P
+not worth it
+int pingdarsRunningCount = 0;
+int pingdarsRunning[6]; // map array of running pingdars
+*/
+
+void sendServoEvent(servo_type& s, int eventType);
+unsigned long getUltrasonicRange(sensor_type& sensor);
+// void sendMsg ( int num, ... );
+
+//---- data record definitions end -----
+
+void append(const int& data) {
+	++paramCnt;
+	customParams[paramBuffIndex] = ARDUINO_TYPE_INT;
+	customParams[++paramBuffIndex] = (byte)(data >> 8);
+	customParams[++paramBuffIndex] = ((byte) data & 0xFF);
+	++paramBuffIndex;
+}
+
+void startMsg() {
+}
+
+void setup() {
+	 // join I2C bus (I2Cdev library doesn't do this automatically)
+    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
+        Wire.begin();
+    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
+        Fastwire::setup(400, true);
+    #endif
+
+    accelgyro.initialize();
+    gyro.initialize();
+    mag.initialize();
+
+    gyro.setFullScale(2000);
+
+	Serial.begin(57600);        // connect to the serial port
+
+	softReset();
+
+	// --VENDOR SETUP BEGIN--
+	// --VENDOR SETUP END--
+}
+
+
+void sendMsg(){
+
+	// unbox
+	Serial.write(MAGIC_NUMBER);
+	Serial.write(paramBuffIndex + 2); // = param buff size + FN + paramCnt
+	//Serial.write(2); // = param buff size + FN + paramCnt
+	Serial.write(PUBLISH_CUSTOM_MSG);
+	Serial.write(paramCnt);
+
+	for (int i = 0; i < paramBuffIndex; ++i){
+		Serial.write(customParams[i]);
+	}
+
+	paramCnt = 0;
+	paramBuffIndex = 0;
+}
+
+
+
+void softReset()
+{
+	for (int i = 0; i < MAX_SERVOS - 1; ++i)
+	{
+                servo_type& s = servos[i];
+		s.speed = 100;
+                if (s.servo != 0){
+		  s.servo->detach();
+                }
+	}
+
+	for (int j = 0; j < DIGITAL_PIN_COUNT - 1; ++j)
+	{
+		pinMode(j, OUTPUT);
+	}
+
+
+	digitalReadPollingPinCount = 0;
+	analogReadPollingPinCount = 0;
+	loopCount = 0;
+
+}
+
+void setPWMFrequency (int address, int prescalar)
+{
+	int clearBits = 0x07;
+	if (address == 0x25)
+	{
+		TCCR0B &= ~clearBits;
+		TCCR0B |= prescalar;
+	} else if (address == 0x2E)
+	{
+		TCCR1B &= ~clearBits;
+		TCCR1B |= prescalar;
+	} else if (address == 0xA1)
+	{
+		TCCR2B &= ~clearBits;
+		TCCR2B |= prescalar;
+	}
+
+}
+
+/**
+ * checks the existance of the searched value in the array
+ * - good for not adding to a dynamic list of values if it
+ * already exists
+ */
+bool exists(int array[], int len, int searchValue){
+	for (int i = 0; i < len; ++i)
+	{
+		if (searchValue == array[i])
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+/**
+ * adds new value to a pseudo dynamic array/list
+ * if successful - if value already exists on list
+ * sends back an error
+ */
+bool addNewValue(int array[], int& len, int addValue)
+{
+	if (exists(array, len, addValue)){
+		array[len] = addValue;
+		++len;
+		return true;
+	} else {
+		sendError(ERROR_ALREADY_EXISTS);
+		return false;
+	}
+}
+
+
+bool removeAndShift (int array [], int& len, int removeValue)
+{
+	if (!exists(array, len, removeValue)){
+		sendError(ERROR_DOES_NOT_EXIST);
+		return false;
+	}
+
+	int pos = -1;
+
+	if (len == 0)
+	{
+		// "should" never happen
+		// would be calling remove on an empty list
+		// the error ERROR_DOES_NOT_EXIST - "should" be called
+		return true;
+	}
+
+	// find position of value
+	for (int i = 0; i < len; ++i)
+	{
+		if (removeValue == array[i])
+		{
+			pos = i;
+			break;
+		}
+	}
+	// if at the end just decrement size
+	if (pos == len - 1)
+	{
+		--len;
+		return true;
+	}
+
+	// if found somewhere else shift left
+	if (pos < len && pos > -1)
+	{
+		for (int j = pos; j < len - 1; ++j)
+		{
+			array[j] = array[j+1];
+		}
+		--len;
+	}
+
+	return true;
+}
+
+boolean getCommand ()
+{
+	// handle serial data begin
+	if (Serial.available() > 0)
+	{
+		// read the incoming byte:
+		newByte = Serial.read();
+		++byteCount;
+
+		// checking first byte - beginning of message?
+		if (byteCount == 1 && newByte != MAGIC_NUMBER)
+		{
+			sendError(ERROR_SERIAL);
+
+			// reset - try again
+			byteCount = 0;
+			return false;
+		}
+
+		if (byteCount == 2)
+		{
+		   // get the size of message
+		   // todo check msg < 64 (MAX_MSG_SIZE)
+		   msgSize = newByte;
+		}
+
+		if (byteCount > 2) {
+		  // fill in msg data - (2) headbytes -1 (offset)
+		  ioCmd[byteCount - 3] = newByte;
+		}
+
+		// if received header + msg
+		if (byteCount == 2 + msgSize)
+		{
+          return true;
+		}
+	} // if Serial.available
+
+	return false;
+}
+
+void loop () {
+
+	++loopCount;
+
+	if (getCommand())
+	{
+		switch (ioCmd[0])
+		{
+
+		case DIGITAL_WRITE:{
+			digitalWrite(ioCmd[1], ioCmd[2]);
+			break;
+		}
+
+		case ANALOG_WRITE:{
+			analogWrite(ioCmd[1], ioCmd[2]);
+			break;
+		}
+
+		case PIN_MODE:{
+			pinMode(ioCmd[1], ioCmd[2]);
+			break;
+		}
+
+		case SERVO_ATTACH:{
+			servo_type& s = servos[ioCmd[1]];
+			s.index = ioCmd[1];
+			if (s.servo == NULL){
+				s.servo = new Servo();
+			}
+			s.servo->attach(ioCmd[2]);
+			s.step = 1;
+			s.eventsEnabled = false;
+			break;
+		}
+
+		case SERVO_SWEEP_START:{
+			servo_type& s = servos[ioCmd[1]];
+			s.min = ioCmd[2];
+			s.max = ioCmd[3];
+			s.step = ioCmd[4];
+			s.isMoving = true;
+			s.isSweeping = true;
+			break;
+		}
+
+		case SERVO_SWEEP_STOP:{
+			servo_type& s = servos[ioCmd[1]];
+			s.isMoving = false;
+			s.isSweeping = false;
+			break;
+		}
+
+		case SERVO_WRITE:{
+			servo_type& s = servos[ioCmd[1]];
+			if (s.speed == 100 && s.servo != 0)// move at regular/full 100% speed
+			{
+				s.targetPos = ioCmd[2];
+				s.currentPos = ioCmd[2];
+				s.isMoving = false;
+				s.servo->write(ioCmd[2]);
+				if (s.eventsEnabled) sendServoEvent(s, SERVO_EVENT_STOPPED);
+			} else if (s.speed < 100 && s.speed > 0) {
+				s.targetPos = ioCmd[2];
+				s.isMoving = true;
+			}
+			break;
+		}
+
+		case PUBLISH_SERVO_EVENT:{
+			servo_type& s = servos[ioCmd[1]];
+			s.eventsEnabled = ioCmd[2];
+			break;
+		}
+
+		case SET_LOAD_TIMING_ENABLED:{
+			loadTimingEnabled = ioCmd[1];
+			//loadTimingModulus = ioCmd[2];
+			loadTimingModulus = 1000;
+			break;
+		}
+
+		case SERVO_WRITE_MICROSECONDS:{
+			// TODO - incorporate into speed control etc
+			// normalize - currently by itself doesn't effect events
+			// nor is it involved in speed control
+			servo_type& s = servos[ioCmd[1]];
+			if (s.servo != 0) {
+				// 1500 midpoint
+				s.servo->writeMicroseconds(ioCmd[2]);
+			}
+
+			break;
+		}
+
+		case SET_SERVO_SPEED:{
+			// setting the speed of a servo
+			servo_type& servo = servos[ioCmd[1]];
+			servo.speed = ioCmd[2];
+			break;
+		}
+
+		case SERVO_DETACH:{
+			servo_type& s = servos[ioCmd[1]];
+			if (s.servo != 0){
+			  s.servo->detach();
+			}
+			break;
+		}
+
+		case SET_PWMFREQUENCY:{
+			setPWMFrequency (ioCmd[1], ioCmd[2]);
+			break;
+		}
+
+		case ANALOG_READ_POLLING_START:{
+			int pin = ioCmd[1];
+			addNewValue(analogReadPin, analogReadPollingPinCount, pin);
+			break;
+		}
+
+		case ANALOG_READ_POLLING_STOP:{
+			int pin = ioCmd[1];
+			removeAndShift(analogReadPin, analogReadPollingPinCount, pin);
+			break;
+		}
+
+		case DIGITAL_READ_POLLING_START:{
+			int pin = ioCmd[1];
+			addNewValue(digitalReadPin, digitalReadPollingPinCount, pin);
+			break;
+		}
+
+		case DIGITAL_READ_POLLING_STOP:{
+			int pin = ioCmd[1];
+			removeAndShift(digitalReadPin, digitalReadPollingPinCount, pin);
+			break;
+		}
+
+		case SET_TRIGGER:{
+                        // FIXME !!! - you need 1. a complete pin list !!!   analog & digital should be defined by attribute not
+                        // data structure !!!  if (pin.type == ??? if needed
+			// TODO - if POLLING ALREADY DON'T RE-ADD - MAKE RE-ENTRANT
+			analogReadPin[analogReadPollingPinCount] = ioCmd[1]; // put on polling read list
+			++analogReadPollingPinCount;
+			break;
+		}
+
+		case SET_DEBOUNCE:{
+			// default debounceDelay = 50;
+			debounceDelay = ((ioCmd[1]<<8) + ioCmd[2]);
+			break;
+		}
+
+		case SET_DIGITAL_TRIGGER_ONLY:{
+			digitalTriggerOnly = ioCmd[1];
+			break;
+                }
+
+		case SET_SERIAL_RATE:
+		{
+			Serial.end();
+			delay(500);
+			Serial.begin(ioCmd[1]);
+			break;
+		}
+
+		case GET_VERSION:{
+			Serial.write(MAGIC_NUMBER);
+			Serial.write(2); // size
+			Serial.write(PUBLISH_VERSION);
+			Serial.write((byte)MRLCOMM_VERSION);
+			break;
+			}
+
+		case PULSE_IN: {
+		    // might need to hack the pulseIn lib - but would
+		    // like to do it without delay
+			// http://arduino.cc/en/Tutorial/BlinkWithoutDelay
+			int trigPin = ioCmd[1];
+			int echoPin = ioCmd[2];
+			// TODO - implement HI/LOW value & timeout & variable delay for trigger
+
+			pinMode(trigPin, OUTPUT);
+			pinMode(echoPin, INPUT);
+
+			digitalWrite(trigPin, LOW);
+			delayMicroseconds(2);
+
+			digitalWrite(trigPin, HIGH);
+			delayMicroseconds(10);
+
+			digitalWrite(trigPin, LOW);
+			unsigned long duration = pulseIn(echoPin, HIGH);
+
+			//Calculate the distance (in cm) based on the speed of sound.
+			// distance = duration/58.2;
+
+			//sendMsg(4, ANALOG_VALUE, analogReadPin[i], readValue >> 8, readValue & 0xFF);
+ 			//sendMsg(5, PULSE_IN, duration >> 24, duration >> 16, duration >> 8, duration & 0xFF);
+ 			//sendMsg(6, SENSOR_DATA, 47, duration >> 24, duration >> 16, duration >> 8, duration & 0xFF);
+
+
+			Serial.write(MAGIC_NUMBER);
+			Serial.write(5); // size 1 FN + 4 bytes of unsigned long
+			Serial.write(PULSE_IN);
+            // write the long value out
+			Serial.write((byte)(duration >> 24));
+			Serial.write((byte)(duration >> 16));
+			Serial.write((byte)(duration >> 8));
+			Serial.write((byte)duration & 0xFF);
+
+
+			break;
+		}
+
+		case SET_SAMPLE_RATE:{
+			// 2 byte int - valid range 1-65,535
+			sampleRate = (ioCmd[1]<<8) + ioCmd[2];
+			if (sampleRate == 0)
+				{ sampleRate = 1; } // avoid /0 error - FIXME - time estimate param
+			break;
+		}
+
+		case SOFT_RESET:{
+			softReset();
+			break;
+		}
+
+		case STEPPER_ATTACH:{
+			stepper_type& stepper = steppers[ioCmd[1]];
+			stepper.index = ioCmd[1];
+			stepper.type = ioCmd[2];
+			stepper.isRunning = false;
+			stepper.currentPos = 0;
+			stepper.targetPos = 0;
+			stepper.dir = 0;
+			stepper.speed = 100;
+
+			if (stepper.type == STEPPER_TYPE_SIMPLE) {
+				stepper.dirPin = ioCmd[3]; // dir pin
+				stepper.stepPin = ioCmd[4]; // step pin
+			} else {
+				sendError(ERROR_UNKOWN_CMD);
+			}
+			break;
+		}
+
+		case STEPPER_RESET:{
+			stepper_type& stepper = steppers[ioCmd[1]];
+			stepper.isRunning = false;
+			stepper.currentPos = 0;
+			stepper.targetPos = 0;
+			stepper.dir = 0;
+			stepper.speed = 100;
+			break;
+		}
+
+		/* absolute position - not relative */
+		case STEPPER_MOVE_TO:{
+			stepper_type& stepper = steppers[ioCmd[1]];
+			if (stepper.type == STEPPER_TYPE_SIMPLE) {
+				//stepper.isRunning = true;
+
+				stepper.targetPos = stepper.currentPos + (ioCmd[2]<<8) + ioCmd[3];
+				// relative position & direction
+				if (stepper.targetPos < 0) {
+					// direction
+					digitalWrite(stepper.dirPin, 1);
+				} else {
+					digitalWrite(stepper.dirPin, 0);
+				}
+			} else {
+				sendError(ERROR_UNKOWN_CMD);
+			}
+			break;
+		}
+
+		case STEPPER_STOP:{
+			stepper_type& stepper = steppers[ioCmd[1]];
+			if (stepper.type == STEPPER_TYPE_SIMPLE) {
+				stepper.isRunning = false;
+				stepper.targetPos = stepper.currentPos;
+
+				Serial.write(MAGIC_NUMBER);
+				Serial.write(5); // size = 1 FN + 1 eventType + 1 index + 1 curPos
+				Serial.write(PUBLISH_STEPPER_EVENT);
+				Serial.write(STEPPER_EVENT_STOP);
+				Serial.write(stepper.index); // send my index
+				Serial.write(stepper.currentPos >> 8);   // MSB
+				Serial.write(stepper.currentPos & 0xFF);	// LSB
+			} else {
+				sendError(ERROR_UNKOWN_CMD);
+			}
+			break;
+		}
+
+			// --VENDOR CODE BEGIN--
+			// --VENDOR CODE END--
+// not sure if its worth implementing - same info can be retrieved from publish servo event & publish pin
+/*
+		case PINGDAR_ATTACH:{
+			int pingdarIndex = ioCmd[1];
+			pingdar_type& pingdar = pingdars[pingdarIndex];
+			pingdar.servoIndex = ioCmd[2];
+			pingdar.sensorIndex = ioCmd[3];
+			pingdar.step = 1;
+			break;
+		}
+*/
+		// used by ultrasonic sensor
+		case SENSOR_ATTACH:{
+			int sensorIndex = ioCmd[1];
+			sensor_type& sensor = sensors[sensorIndex];
+			sensor.type = ioCmd[2];
+
+
+
+			// initialize based on sensor type
+			if (sensor.type == SENSOR_ULTRASONIC){
+				sensor.trigPin = ioCmd[3];
+				sensor.echoPin = ioCmd[4];
+				pinMode(sensor.trigPin, OUTPUT);
+				pinMode(sensor.echoPin, INPUT);
+				//sensor.ping = new NewPing(sensor.trigPin, sensor.echoPin, 100);
+			}
+
+			break;
+		}
+
+		case SENSOR_POLLING_START:{
+			int sensorIndex = ioCmd[1];
+			sensor_type& sensor = sensors[sensorIndex];
+			sensor.isRunning = true;
+
+			// I'm used to ms - and would need to change some
+			// interfaces if i was to support inbound longs
+			//sensor.timeoutUS = ioCmd[2] * 1000;
+			sensor.timeoutUS = 20000; // 20 ms
+			sensor.state = ECHO_STATE_START;
+
+			break;
+		}
+
+		case SENSOR_POLLING_STOP:{
+			int sensorIndex = ioCmd[1];
+			sensor_type& sensor = sensors[sensorIndex];
+			sensor.isRunning = false;
+			break;
+		}
+
+		case NOP:{
+			// No Operation
+			break;
+		}
+
+		default:{
+		    sendError(ERROR_UNKOWN_CMD);
+			break;
+		}
+		} // end switch
+
+		// reset buffer
+		memset(ioCmd,0,sizeof(ioCmd));
+		byteCount = 0;
+
+	} // if getCommand()
+
+	// all reads are affected by sample rate
+	if (loopCount%sampleRate == 0) {
+		// digital polling read - send data for pins which are currently in INPUT mode only AND whose state has changed
+		for (int i  = 0; i < digitalReadPollingPinCount; ++i)
+		{
+			if (debounceDelay)
+			{
+			  if (millis() - lastDebounceTime[digitalReadPin[i]] < debounceDelay)
+			  {
+			    continue;
+			  }
+			}
+
+			// FIXME !! - normalize with analog
+			// read the pin
+			readValue = digitalRead(digitalReadPin[i]);
+
+			// if my value is different from last time  && config - send it
+			if (lastDigitalInputValue[digitalReadPin[i]] != readValue  || !digitalTriggerOnly)
+			{
+				Serial.write(MAGIC_NUMBER);
+				Serial.write(4); // size
+				Serial.write(PUBLISH_PIN);
+				Serial.write(digitalReadPin[i]);// Pin#
+				Serial.write(0); 	// MSB
+				Serial.write(readValue); 	// LSB
+
+			    lastDebounceTime[digitalReadPin[i]] = millis();
+			}
+
+			// set the last input value of this pin
+			lastDigitalInputValue[digitalReadPin[i]] = readValue;
+		}
+
+
+		// analog polling read - send data for pins which are currently in INPUT mode only AND whose state has changed
+		for (int i  = 0; i < analogReadPollingPinCount; ++i)
+		{
+			// read the pin
+			readValue = analogRead(analogReadPin[i]);
+
+			// if my value is different from last time - send it
+			if (lastAnalogInputValue[analogReadPin[i]] != readValue   || !analogTriggerOnly) //TODO - SEND_DELTA_MIN_DIFF
+			{
+				//sendMsg(4, ANALOG_VALUE, analogReadPin[i], readValue >> 8, readValue & 0xFF);
+
+				Serial.write(MAGIC_NUMBER);
+				Serial.write(4); //size
+				Serial.write(PUBLISH_PIN);
+				Serial.write(analogReadPin[i]);
+				Serial.write(readValue >> 8);   // MSB
+				Serial.write(readValue & 0xFF);	// LSB
+
+	        }
+			// set the last input value of this pin
+			lastAnalogInputValue[analogReadPin[i]] = readValue;
+		}
+	}
+
+	// update moving servos - send events if required
+	for (int i = 0; i < MAX_SERVOS; ++i)
+	{
+		servo_type& s = servos[i];
+		if (s.isMoving && s.servo != 0){
+			if (s.currentPos != s.targetPos)
+			{
+				// caclulate the appropriate modulus to drive
+				// the servo to the next position
+				// TODO - check for speed > 0 && speed < 100 - send ERROR back?
+				int speedModulus = (100 - s.speed) * 10;
+				if (loopCount % speedModulus == 0)
+				{
+					int increment = s.step * ((s.currentPos < s.targetPos)?1:-1);
+					// move the servo an increment
+					s.currentPos = s.currentPos + increment;
+					s.servo->write(s.currentPos);
+					if (s.eventsEnabled) sendServoEvent(s, SERVO_EVENT_POSITION_UPDATE);
+				}
+			} else {
+				if (s.isSweeping) {
+					if (s.targetPos == s.min){
+						s.targetPos = s.max;
+					} else {
+						s.targetPos = s.min;
+					}
+				} else {
+					if (s.eventsEnabled) sendServoEvent(s, SERVO_EVENT_STOPPED);
+					s.isMoving = false;
+				}
+			}
+		}
+	}
+
+	unsigned long ts;
+
+	for (int i = 0; i < SENSORS_MAX; ++i) {
+		sensor_type& sensor = sensors[i];
+		if (sensor.isRunning == true){
+			if (sensor.type == SENSOR_ULTRASONIC){
+
+				// we are running & have an ultrasonic (ping) sensor
+				// check to see what state we  are in
+
+				if (sensor.state == ECHO_STATE_START){
+					// trigPin prepare - start low for an
+					// upcoming high pulse
+					pinMode(sensor.trigPin, OUTPUT);
+					digitalWrite(sensor.trigPin, LOW);
+
+					// put the echopin into a high state
+					// is this necessary ???
+					pinMode(sensor.echoPin, OUTPUT);
+					digitalWrite(sensor.echoPin, HIGH);
+
+					ts = micros();
+					if (ts - sensor.ts > 2){
+						sensor.ts = ts;
+						sensor.state = ECHO_STATE_TRIG_PULSE_BEGIN;
+					}
+				} else if (sensor.state == ECHO_STATE_TRIG_PULSE_BEGIN){
+
+					// begin high pulse for at least 10 us
+					pinMode(sensor.trigPin, OUTPUT);
+					digitalWrite(sensor.trigPin, HIGH);
+
+					ts = micros();
+					if (ts - sensor.ts > 10){
+						sensor.ts = ts;
+						sensor.state = ECHO_STATE_TRIG_PULSE_END;
+					}
+				} else if (sensor.state == ECHO_STATE_TRIG_PULSE_END){
+					// end of pulse
+					pinMode(sensor.trigPin, OUTPUT);
+					digitalWrite(sensor.trigPin, LOW);
+
+					sensor.state = ECHO_STATE_MIN_PAUSE_PRE_LISTENING;
+					sensor.ts = micros();
+				} else if (sensor.state == ECHO_STATE_MIN_PAUSE_PRE_LISTENING){
+
+					ts = micros();
+					if (ts - sensor.ts > 1500){
+						sensor.ts = ts;
+
+						// putting echo pin into listen mode
+						pinMode(sensor.echoPin, OUTPUT);
+						digitalWrite(sensor.echoPin, HIGH);
+						pinMode(sensor.echoPin, INPUT);
+
+						sensor.state = ECHO_STATE_LISTENING;
+					}
+
+				} else if (sensor.state == ECHO_STATE_LISTENING) {
+					// timeout or change states..
+					int value = digitalRead(sensor.echoPin);
+					ts = micros();
+
+					if (value == LOW) {
+						sensor.lastValue = ts - sensor.ts;
+						sensor.ts = ts;
+						sensor.state = ECHO_STATE_GOOD_RANGE;
+					} else if (ts - sensor.ts > sensor.timeoutUS) {
+						sensor.state = ECHO_STATE_TIMEOUT;
+						sensor.ts = ts;
+						sensor.lastValue = 0;
+					}
+
+				} else if (sensor.state == ECHO_STATE_GOOD_RANGE || sensor.state == ECHO_STATE_TIMEOUT) {
+					Serial.write(MAGIC_NUMBER);
+					Serial.write(6); // size 1 FN + 4 bytes of unsigned long
+					Serial.write(PUBLISH_SESOR_DATA);
+					Serial.write(i);
+		            // write the long value out
+					Serial.write((byte)(sensor.lastValue >> 24));
+					Serial.write((byte)(sensor.lastValue >> 16));
+					Serial.write((byte)(sensor.lastValue >> 8));
+					Serial.write((byte) sensor.lastValue & 0xFF);
+					sensor.state = ECHO_STATE_START;
+				} // end else if
+
+			} // if (sensor.type == SENSOR_ULTRASONIC)
+
+		} // end isRunning
+
+	} // end for each sensor
+
+	// TODO - brake - speed - fractional stepping - other stepper types
+	for (int i = 0; i < STEPPERS_MAX; ++i) {
+		stepper_type& stepper = steppers[i];
+		if (stepper.currentPos != stepper.targetPos){
+			if (stepper.type == STEPPER_TYPE_SIMPLE){
+
+				// direction is already set in initial STEPPER_MOVE
+
+				if (stepper.currentPos < stepper.targetPos) {
+
+				    // step - POLOLU has single step pin (dir is on step0)
+					digitalWrite(stepper.stepPin, 1);
+					delayMicroseconds(1); // :P should require another state? loop is ~106us min ?
+					digitalWrite(stepper.stepPin, 0);
+
+					stepper.currentPos++;
+				} else if (stepper.currentPos > stepper.targetPos) {
+
+				    // step - POLOLU has single step pin (dir is on step0)
+					digitalWrite(stepper.stepPin, 1);
+					delayMicroseconds(1); // :P should require another state? loop is ~106us min ?
+					digitalWrite(stepper.stepPin, 0);
+
+					stepper.currentPos--;
+
+				}
+
+				if (stepper.currentPos == stepper.targetPos){
+					//stepper.isRunning = false;
+					// stepper.currentPos = stepper.targetPos; // forcing ? :P
+					Serial.write(MAGIC_NUMBER);
+					Serial.write(5); // size = 1 FN + 1 eventType + 1 index + 1 curPos
+					Serial.write(PUBLISH_STEPPER_EVENT);
+					Serial.write(STEPPER_EVENT_STOP);
+					Serial.write(stepper.index); // send my index
+					Serial.write(stepper.currentPos >> 8);   // MSB
+					Serial.write(stepper.currentPos & 0xFF);	// LSB
+				}
+
+			}
+		}
+	}
+
+	// FIXME - fix overflow with getDiff() method !!!
+	unsigned long now = micros();
+	loadTime = now - lastMicros; // avg outside
+ 	lastMicros = now;
+
+	// report load time
+	if (loadTimingEnabled && (loopCount%loadTimingModulus == 0)) {
+
+ 		// send it
+		Serial.write(MAGIC_NUMBER);
+		Serial.write(5); // size 1 FN + 4 bytes of unsigned long
+		Serial.write(PUBLISH_LOAD_TIMING_EVENT);
+        // write the long value out
+		Serial.write((byte)(loadTime >> 24));
+		Serial.write((byte)(loadTime >> 16));
+		Serial.write((byte)(loadTime >> 8));
+		Serial.write((byte) loadTime & 0xFF);
+	}
+
+	accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
+  	gyro.getAngularVelocity(&avx, &avy, &avz);
+  	mag.getHeading(&mx, &my, &mz);
+	float heading = atan2(my, mx);
+  	int16_t headingint = (heading * 180/M_PI);
+  	// process mrl commands
+  	// servo control, sensor, control send & recieve
+  	// oscope, analog polling, digital polling etc..
+  	// mrl messages
+  	//mrl.process();
+
+  	// example how to
+  	// send 3 vars to mrl
+
+  	cnt += 1;
+  	if (cnt%10 == 0) {
+    		startMsg();
+    		append(ay);
+    		append(mx);
+    		append(headingint);
+    		sendMsg();
+    		cnt = 0;
+	}
+
+
+} // end of big loop
+
+unsigned long getUltrasonicRange(sensor_type& sensor){
+
+		// added for sensors which have single pin !
+		pinMode(sensor.trigPin, OUTPUT);
+		digitalWrite(sensor.trigPin, LOW);
+		delayMicroseconds(2);
+
+		digitalWrite(sensor.trigPin, HIGH);
+		delayMicroseconds(10);
+
+		digitalWrite(sensor.trigPin, LOW);
+
+		// added for sensors which have single pin !
+		pinMode(sensor.echoPin, INPUT);
+		// CHECKING return pulseIn(sensor.echoPin, HIGH, sensor.timeoutUS);
+		// TODO - adaptive timeout ? - start big - pull in until valid value - push out if range is coming close
+		return pulseIn(sensor.echoPin, HIGH);
+}
+
+void sendServoEvent(servo_type& s, int eventType){
+  	// check type of event - STOP vs CURRENT POS
+
+	Serial.write(MAGIC_NUMBER);
+	Serial.write(5); // size = 1 FN + 1 INDEX + 1 eventType + 1 curPos
+	Serial.write(PUBLISH_SERVO_EVENT);
+	Serial.write(s.index); // send my index
+	// write the long value out
+	Serial.write(eventType);
+	Serial.write(s.currentPos);
+	Serial.write(s.targetPos);
+}
+
+void sendError(int type){
+	Serial.write(MAGIC_NUMBER);
+	Serial.write(2); // size = 1 FN + 1 TYPE
+	Serial.write(PUBLISH_MRLCOMM_ERROR);
+	Serial.write(type);
+}


Refactored heater control functions into a single common function.  RAM reduction via the F macro.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/FirstBuild/pizzaduino.git/'


Implements the gpio example for arduino.

Arduino - FreeRTos feature parity: b/241973960

Change-Id: I1a4f43615abc471a62d269c5f5ea1127f0c3b3fa
GitOrigin-RevId: 985fdc682a720d90fbbb92da68abad33bb15a00f

error: pathspec 'arduino/libraries/Basics/examples/GPIO/GPIO.ino' did not match any file(s) known to git

--- arduino/libraries/Basics/examples/GPIO/GPIO.ino
+++ arduino/libraries/Basics/examples/GPIO/GPIO.ino
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Arduino.h>
+
+// Toggles each available GPIO on the two 12-pin headers.
+//
+// These GPIOs are not powerful enough to drive an LED,
+// but you can observe the changes with a multimeter.
+
+constexpr int kGpiosToTest[] = {
+    D0, D1, D2, D3,
+};
+
+bool high = true;
+
+void setup() {
+  Serial.begin(115200);
+  // Turn on Status LED to show the board is on.
+  pinMode(PIN_LED_STATUS, OUTPUT);
+  digitalWrite(PIN_LED_STATUS, HIGH);
+
+  Serial.begin(115200);
+  Serial.println("Arduino GPIO Example!");
+
+  for (auto pin : kGpiosToTest) {
+    pinMode(pin, OUTPUT);
+  }
+
+  Serial.println("Periodically toggling header GPIOs...");
+}
+
+void loop() {
+  for (auto pin : kGpiosToTest) {
+    digitalWrite(pin, high ? HIGH : LOW);
+  }
+  high = !high;
+  delay(1000);
+}


Initial commit. Used to twiddle a servo just to see if it's working.

error: pathspec 'Project/servo_sweep/servo_sweep.ino' did not match any file(s) known to git

--- Project/servo_sweep/servo_sweep.ino
+++ Project/servo_sweep/servo_sweep.ino
@@ -0,0 +1,50 @@
+/**
+ *             servo_sweep.ino
+ * Purpose:    Used to calibrate measured position vs input angle.
+ *
+ * @author:    Tyler Lucas
+ * Student ID: 3305203
+ * Date:       October 9, 2017
+ * Version     1.1
+ *
+ * References: N/A
+ *
+ */
+
+
+#include <Servo.h>
+
+#define boomArmPin 11
+#define mainArmPin 10
+#define clawPin 9       // max 140, min 69
+#define swivelPin 6     // max 180, min 10
+
+#define angleMin 60
+#define angleMax 110
+#define angleInitial 90
+#define angleAdjustmentMagnitude 2
+
+Servo servo;
+int angle = angleInitial;
+int angleAdjustment = angleAdjustmentMagnitude;
+
+void setup()
+{
+  servo.attach( clawPin );
+
+  Serial.begin(9600);
+}
+
+void loop()
+{
+  while ( angle >= angleMin && angle <= angleMax )
+  {
+    servo.write( angle );
+    Serial.println( angle );
+    angle += angleAdjustment;
+    delay(50);
+  }
+
+  angleAdjustment *= -1;  // reverse
+  angle += 2 * angleAdjustment;
+}


Added ChannelPoll example.

Added ChannelPoll example.

error: pathspec 'examples/ChannelPoll/ChannelPoll.ino' did not match any file(s) known to git

--- examples/ChannelPoll/ChannelPoll.ino
+++ examples/ChannelPoll/ChannelPoll.ino
@@ -0,0 +1,44 @@
+#include <SPI.h>
+#include <Ethernet.h>
+#include <RC.h>
+
+// SET THESE
+// Public and Private Key can be obtained by creating a project
+// on the roboticsclub.org/admin website.
+//#define PUBLIC_KEY ""
+//#define PRIVATE_KEY ""
+//byte mac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+// Channel 1 is the test Channel
+#define CHANNEL_ID 1
+
+EthernetClient ethernetClient;
+APIClient api(ethernetClient, PUBLIC_KEY, PRIVATE_KEY);
+
+Channel channel;
+
+void setup() {
+  Serial.begin(9600);
+  Serial.println(F("Welcome!"));
+
+  if(!Ethernet.begin(mac)) {
+    Serial.println(F("Failed to initialize ethernet shield"));
+    return;
+  }
+
+  Serial.println(F("Connected to Internet"));
+}
+
+
+void loop() {
+  Channel newChannel;
+
+  if(!api.channel(CHANNEL_ID, newChannel)) {
+    Serial.println("Channel failed");
+  } else {
+    if(CHANNEL_UPDATED(channel, newChannel)) {
+      Serial.println(newChannel.value);
+      channel = newChannel;
+    }
+  }
+}


Moving LFSRExample to its own directory.

error: pathspec 'examples/LFSRExample/LFSRExample.ino' did not match any file(s) known to git

--- examples/LFSRExample/LFSRExample.ino
+++ examples/LFSRExample/LFSRExample.ino
@@ -0,0 +1,15 @@
+
+
+#include "XLR8_LFSR.h"
+
+void setup() {
+  Serial.begin(115200);
+  XLR8_LFSR.set_seed(0x55);
+  XLR8_LFSR.set_freerunning_mode(false);
+}
+
+void loop() {
+  Serial.println(XLR8_LFSR.get_lfsr(), BIN);
+  delay(1000);
+}
+


sketch that sends messages through lora based on 2 buttons

error: pathspec 'node_autonomo/autonomo_lorabee.ino' did not match any file(s) known to git

--- node_autonomo/autonomo_lorabee.ino
+++ node_autonomo/autonomo_lorabee.ino
@@ -0,0 +1,130 @@
+#include <Sodaq_RN2483.h>
+
+#define debugSerial SerialUSB
+
+#define loraSerial Serial1
+
+const uint8_t devAddr[4] = { 0x02, 0x01, 0x59, 0x00 };
+const uint8_t appSKey[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,  0xAB, 0xF7, 0x15, 0x88,  0x09, 0xCF, 0x4F, 0x3C };
+const uint8_t nwkSKey[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,  0xAB, 0xF7, 0x15, 0x88,  0x09, 0xCF, 0x4F, 0x3C };
+
+const int led = 12;
+const int startButton = 11;
+const int stopButton = 10;
+
+long t = millis();
+
+boolean charging = false;
+
+String startMessage = "{'charge':'start'}";
+String stopMessage = "{'charge':'stop', 'duration':'%DUR%', 'volume':'???'}";
+
+void setup()
+{
+  debugSerial.begin(57600);
+
+  digitalWrite(BEE_VCC, HIGH);
+
+  pinMode(led, OUTPUT);
+  pinMode(startButton, INPUT);
+  pinMode(stopButton, INPUT);
+
+
+  loraSerial.begin(LoRaBee.getDefaultBaudRate());
+
+  LoRaBee.setDiag(debugSerial); // optional
+  if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, true))
+  {
+    debugSerial.println("Connection to the network was successful.");
+  }
+  else
+  {
+    debugSerial.println("Connection to the network failed!");
+  }
+}
+
+void loop()
+{
+  debugSerial.println("Sleeping for 5 seconds before starting sending out test packets.");
+  for (uint8_t i = 5; i > 0; i--)
+  {
+    debugSerial.println(i);
+    delay(1000);
+  }
+
+  while (true)
+  {
+    int startPressed = ! digitalRead(startButton);
+    int stopPressed = ! digitalRead(stopButton);
+
+    if (startPressed && !charging) {
+      charging=true;
+      digitalWrite(12,HIGH);
+      sendMessage(startMessage);
+      debugSerial.println("Starting Charging");
+    }
+
+    if (stopPressed && charging) {
+      charging=false;
+      digitalWrite(12,LOW);
+      stopMessage.replace("%DUR%",String((millis()-t)/1000));
+      sendMessage(stopMessage);
+      debugSerial.println("Stopped Charging");
+    }
+
+    delay(100);
+  }
+}
+
+void blinkLed(int times, int len) {
+  for (uint8_t i = times; i > 0; i--) {
+    digitalWrite(13, HIGH);
+    delay(len/2);
+    digitalWrite(13, LOW);
+    delay(len/2);
+  }
+}
+
+void sendMessage(String data) {
+  byte buf[data.length()+1];
+  data.getBytes(buf, data.length()+1);
+
+ switch (LoRaBee.send(1, buf, data.length())) {
+  case NoError:
+    debugSerial.println("Successful transmission.");
+    break;
+  case NoResponse:
+    debugSerial.println("There was no response from the device.");
+    break;
+  case Timeout:
+    debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
+    delay(20000);
+    break;
+  case PayloadSizeError:
+    debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
+    break;
+  case InternalError:
+    debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! Try restarting the device!\r\nThe program will now halt.");
+    while (1) {};
+    break;
+  case Busy:
+    debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
+    delay(10000);
+    break;
+  case NetworkFatalError:
+    debugSerial.println("There is a non-recoverable error with the network connection. You should re-connect.\r\nThe program will now halt.");
+    while (1) {};
+    break;
+  case NotConnected:
+    debugSerial.println("The device is not connected to the network. Please connect to the network before attempting to send data.\r\nThe program will now halt.");
+    while (1) {};
+    break;
+  case NoAcknowledgment:
+    debugSerial.println("There was no acknowledgment sent back!");
+    break;
+  default:
+    break;
+  }
+}
+
+


Added example `HelloHabr.ino`

Added example `HelloHabr.ino`

error: pathspec 'examples/HelloHabr/HelloHabr.ino' did not match any file(s) known to git


added Firmware for Sonoff-4CH

added Firmware for Sonoff-4CH

error: pathspec 'sonoff-homie-4ch/sonoff-homie-4ch.ino' did not match any file(s) known to git

--- sonoff-homie-4ch/sonoff-homie-4ch.ino
+++ sonoff-homie-4ch/sonoff-homie-4ch.ino
@@ -0,0 +1,131 @@
+#include <Homie.h>
+#include <ArduinoOTA.h>
+
+#define PIN_LED     13      // PIN 12 / HSPI_MOSI; UART0_CTS MTCK
+#define RELAY_1     12
+#define RELAY_2      5
+#define RELAY_3      4
+#define RELAY_4     15
+#define BUTTON_1     0
+#define BUTTON_2     9
+#define BUTTON_3    10
+#define BUTTON_4    14
+
+/**
+  * Arduino IDE instructions
+  *
+  * select "generic ESP8285 Module"
+  * 80Mhz CPU, 40Mhz Flash
+  * Upload Speed 460800
+  * 1M (64K SPIFFS)
+  * ck
+  *
+*/
+
+#define FW_NAME "sonoff-4ch"
+#define FW_VERSION "1.0.0"
+
+HomieNode relayNode1("switch1", "switch");
+HomieNode relayNode2("switch2", "switch");
+HomieNode relayNode3("switch3", "switch");
+HomieNode relayNode4("switch4", "switch");
+Bounce debouncer1 = Bounce();
+Bounce debouncer2 = Bounce();
+Bounce debouncer3 = Bounce();
+Bounce debouncer4 = Bounce();
+
+
+bool relayHandler1(const HomieRange& range, const String& value) {
+  if (value != "true" && value != "false") return false;
+  digitalWrite(RELAY_1, value == "true");
+  relayNode1.setProperty("on").send(value);
+  return true;
+}
+
+bool relayHandler2(const HomieRange& range, const String& value) {
+  if (value != "true" && value != "false") return false;
+  digitalWrite(RELAY_2, value == "true");
+  relayNode2.setProperty("on").send(value);
+  return true;
+}
+
+bool relayHandler3(const HomieRange& range, const String& value) {
+  if (value != "true" && value != "false") return false;
+  digitalWrite(RELAY_3, value == "true");
+  relayNode2.setProperty("on").send(value);
+  return true;
+}
+bool relayHandler4(const HomieRange& range, const String& value) {
+  if (value != "true" && value != "false") return false;
+  digitalWrite(RELAY_4, value == "true");
+  relayNode2.setProperty("on").send(value);
+  return true;
+}
+
+void toggleRelay(int pin, HomieNode& node) {
+  bool on = digitalRead(pin) == HIGH;
+  digitalWrite(pin, on ? LOW : HIGH);
+  node.setProperty("on").send(on ? "false" : "true");
+}
+
+void loopHandler() {
+
+  ArduinoOTA.handle();
+  debouncer1.update();
+  debouncer2.update();
+  debouncer3.update();
+  debouncer4.update();
+
+  if(debouncer1.fell()) {
+    toggleRelay(RELAY_1, relayNode1);
+  }
+  if(debouncer2.fell()) {
+    toggleRelay(RELAY_2, relayNode2);
+  }
+  if(debouncer3.fell()) {
+    toggleRelay(RELAY_3, relayNode3);
+  }
+  if(debouncer4.fell()) {
+    toggleRelay(RELAY_4, relayNode4);
+  }
+
+}
+
+void setup() {
+  Serial.begin(115200);
+  Serial << endl << endl;
+  Homie_setFirmware(FW_NAME, FW_VERSION);
+  Homie_setBrand(FW_NAME);
+  Homie.disableLogging();
+
+  pinMode(RELAY_1, OUTPUT);
+  pinMode(RELAY_2, OUTPUT);
+  pinMode(RELAY_3, OUTPUT);
+  pinMode(RELAY_4, OUTPUT);
+
+  debouncer1.attach(BUTTON_1, INPUT);
+  debouncer1.interval(50);
+  debouncer2.attach(BUTTON_2, INPUT);
+  debouncer2.interval(50);
+  debouncer3.attach(BUTTON_3, INPUT);
+  debouncer3.interval(50);
+  debouncer4.attach(BUTTON_4, INPUT);
+  debouncer4.interval(50);
+
+  relayNode1.advertise("on").settable(relayHandler1);
+  relayNode2.advertise("on").settable(relayHandler2);
+  relayNode3.advertise("on").settable(relayHandler3);
+  relayNode4.advertise("on").settable(relayHandler4);
+
+  Homie.setLedPin(PIN_LED, LOW);
+  Homie.setLoopFunction(loopHandler);
+  Homie.setResetTrigger(BUTTON_1, LOW, 10000);  // BTN0 = Flash = BTN_A set to 10sec
+  Homie.setup();
+
+  ArduinoOTA.setHostname(Homie.getConfiguration().deviceId);
+  ArduinoOTA.begin();
+}
+
+void loop() {
+  Homie.loop();
+}


Add PrintRGB Example

Add PrintRGB Example

PrintRGB is a small example program that read RGB color from TCS sensor and print it in serial monitor.

error: pathspec 'examples/PrintRGB/PrintRGB.ino' did not match any file(s) known to git

--- examples/PrintRGB/PrintRGB.ino
+++ examples/PrintRGB/PrintRGB.ino
@@ -0,0 +1,42 @@
+/**
+ * Print RGB value read by TCS sensor
+ *
+ * Copyright (c) 2016 Ilham Imaduddin
+ *
+ * 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 "TCS.h"
+
+TCS tcs(40, 41, 42, 43, 44, 45);
+
+void setup() {
+  Serial.begin(9600);
+  tcs.setSpeed(FAST);
+}
+
+void loop() {
+  Serial.print("R: ");
+  Serial.print(tcs.getColor(RED));
+  Serial.print("\tG: ");
+  Serial.print(tcs.getColor(GREEN));
+  Serial.print("\tB: ");
+  Serial.println(tcs.getColor(BLUE));
+  delay(500);
+}


Add Example

Add Example

error: pathspec 'firmware/examples/dht-test.ino' did not match any file(s) known to git

--- firmware/examples/dht-test.ino
+++ firmware/examples/dht-test.ino
@@ -0,0 +1,70 @@
+#include "Adafruit_DHT.h"
+
+// Example testing sketch for various DHT humidity/temperature sensors
+// Written by ladyada, public domain
+
+#define DHTPIN 2     // what pin we're connected to
+
+// Uncomment whatever type you're using!
+//#define DHTTYPE DHT11		// DHT 11
+#define DHTTYPE DHT22		// DHT 22 (AM2302)
+//#define DHTTYPE DHT21		// DHT 21 (AM2301)
+
+// Connect pin 1 (on the left) of the sensor to +5V
+// Connect pin 2 of the sensor to whatever your DHTPIN is
+// Connect pin 4 (on the right) of the sensor to GROUND
+// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
+
+DHT dht(DHTPIN, DHTTYPE);
+
+void setup() {
+	Serial.begin(9600);
+	Serial.println("DHTxx test!");
+
+	dht.begin();
+}
+
+void loop() {
+// Wait a few seconds between measurements.
+	delay(2000);
+
+// Reading temperature or humidity takes about 250 milliseconds!
+// Sensor readings may also be up to 2 seconds 'old' (its a very slow
+sensor)
+	float h = dht.getHumidity();
+// Read temperature as Celsius
+	float t = dht.getTempCelcius();
+// Read temperature as Farenheit
+	float f = dht.getTempFarenheit();
+
+// Check if any reads failed and exit early (to try again).
+	if (isnan(h) || isnan(t) || isnan(f)) {
+		Serial.println("Failed to read from DHT sensor!");
+		return;
+	}
+
+// Compute heat index
+// Must send in temp in Fahrenheit!
+	float hi = dht.getHeatIndex();
+	float dp = dht.getDewPoint();
+	float k = dht.getTempKelvin();
+
+	Serial.print("Humid: ");
+	Serial.print(h);
+	Serial.print("% - ");
+	Serial.print("Temp: ");
+	Serial.print(t);
+	Serial.print("*C ");
+	Serial.print(f);
+	Serial.print("*F ");
+	Serial.print(k);
+	Serial.print("*K - ");
+	Serial.print("DewP: ");
+	Serial.print(dp);
+	Serial.print("*C - ");
+	Serial.print("HeatI: ");
+	Serial.print(hi);
+	Serial.println("*C");
+	Serial.println(Time.timeStr());
+}
+


Add demo using NV08C GNSS receiver

Add demo using NV08C GNSS receiver

error: pathspec 'examples/NV08C_demo/NV08C_demo.ino' did not match any file(s) known to git

--- examples/NV08C_demo/NV08C_demo.ino
+++ examples/NV08C_demo/NV08C_demo.ino
@@ -0,0 +1,162 @@
+#include <MicroNMEA.h>
+
+// To display free memory include the MemoryFree library, see
+// https://github.com/maniacbug/MemoryFree and uncomment the line
+// below
+//#include <MemoryFree.h>
+
+// Refer to serial devices by use
+HardwareSerial& console = Serial;
+HardwareSerial& gps = Serial1;
+
+char nmeaBuffer[100];
+MicroNMEA nmea(nmeaBuffer, sizeof(nmeaBuffer));
+bool ledState = LOW;
+volatile bool ppsTriggered = false;
+
+void ppsHandler(void);
+
+
+void ppsHandler(void)
+{
+  ppsTriggered = true;
+}
+
+
+void printUnknownSentence(MicroNMEA& nmea)
+{
+  console.println();
+  console.print("Unknown sentence: ");
+  console.println(nmea.getSentence());
+}
+
+
+void gpsHardwareReset()
+{
+  // Empty input buffer
+  while (gps.available())
+    gps.read();
+
+  digitalWrite(A0, LOW);
+  delay(50);
+  digitalWrite(A0, HIGH);
+
+  // Reset is complete when the first valid message is received
+  while (1) {
+    while (gps.available()) {
+      char c = gps.read();
+      if (nmea.process(c))
+        return;
+
+    }
+  }
+}
+
+
+void setup(void)
+{
+  console.begin(115200); // console
+  gps.begin(115200); // gps
+
+  pinMode(LED_BUILTIN, OUTPUT);
+  digitalWrite(LED_BUILTIN, ledState);
+
+  nmea.setUnknownSentenceHandler(printUnknownSentence);
+
+  pinMode(A0, OUTPUT);
+  digitalWrite(A0, HIGH);
+  console.println("Resetting GPS module ...");
+  gpsHardwareReset();
+  console.println("... done");
+
+  // Clear the list of messages which are sent.
+  MicroNMEA::sendSentence(gps, "$PORZB");
+
+  // Send only RMC and GGA messages.
+  MicroNMEA::sendSentence(gps, "$PORZB,RMC,1,GGA,1");
+
+  // Disable compatability mode (NV08C-CSM proprietary message) and
+  // adjust precision of time and position fields
+  MicroNMEA::sendSentence(gps, "$PNVGNME,2,9,1");
+  MicroNMEA::sendSentence(gps, "$PONME,2,4,1,0");
+
+#ifdef ARDUINO_AVR_CALUNIUM
+  pinMode(6, INPUT);
+  attachInterrupt(2, ppsHandler, RISING);
+#else
+#error Please configure interrupt handler code for alternative board.
+#endif
+}
+
+
+void loop(void)
+{
+  if (ppsTriggered) {
+    ppsTriggered = false;
+    ledState = !ledState;
+    digitalWrite(LED_BUILTIN, ledState);
+
+    // Output GPS information from previous second
+    console.print("Valid fix: ");
+    console.println(nmea.isValid() ? "yes" : "no");
+
+    console.print("Nav. system: ");
+    if (nmea.getNavSystem())
+      console.println(nmea.getNavSystem());
+    else
+      console.println("none");
+
+    console.print("Num. satellites: ");
+    console.println(nmea.getNumSatellites());
+
+    console.print("HDOP: ");
+    console.println(nmea.getHDOP() / 10., 1);
+
+    console.print("Date/time: ");
+    console.print(nmea.getYear());
+    console.print('-');
+    console.print(int(nmea.getMonth()));
+    console.print('-');
+    console.print(int(nmea.getDay()));
+    console.print('T');
+    console.print(int(nmea.getHour()));
+    console.print(':');
+    console.print(int(nmea.getMinute()));
+    console.print(':');
+    console.println(int(nmea.getSecond()));
+
+    long latitude_mdeg = nmea.getLatitude();
+    long longitude_mdeg = nmea.getLongitude();
+    console.print("Latitude (deg): ");
+    console.println(latitude_mdeg / 1000000., 6);
+
+    console.print("Longitude (deg): ");
+    console.println(longitude_mdeg / 1000000., 6);
+
+    long alt;
+    console.print("Altitude (m): ");
+    if (nmea.getAltitude(alt))
+      console.println(alt / 1000., 3);
+    else
+      console.println("not available");
+
+    console.print("Speed: ");
+    console.println(nmea.getSpeed() / 1000., 3);
+    console.print("Course: ");
+    console.println(nmea.getCourse() / 1000., 3);
+
+#ifdef MEMORY_FREE_H
+    console.print("freeMemory()=");
+    console.println(freeMemory());
+#endif
+    console.println("-----------------------");
+    nmea.clear();
+  }
+
+  while (!ppsTriggered && gps.available()) {
+    char c = gps.read();
+    console.print(c);
+    nmea.process(c);
+  }
+
+}


added pendulum code

added pendulum code

error: pathspec 'pendulum.ino' did not match any file(s) known to git

--- pendulum.ino
+++ pendulum.ino
@@ -0,0 +1,82 @@
+#define LED 13
+
+#define IPIN0 2 // CHANNEL B
+#define IPIN1 3 // CHANNEL A
+
+volatile int angle;  // What is the current angle?
+
+volatile int state0 = LOW;  // what is the state of pin 0?
+volatile int state1 = LOW;  // what is the state of pin 1?
+
+long int t0;
+
+int going=0;
+
+void blink0() {
+    state0 = digitalRead(IPIN0);  // state0 has changed. check state0 and state1 and update angle.
+    state1 = digitalRead(IPIN1);
+
+    digitalWrite(LED,state0);     // let the LED know we're here.
+
+    if (state0) {
+      if (state1) {
+        angle -= 1;
+      } else {
+        angle += 1;
+      }
+    } else {
+      if (state1) {
+        angle += 1;
+      } else {
+        angle -= 1;
+      }
+    }
+}
+
+void blink1() {
+    state0 = digitalRead(IPIN0);   // state1 has changed. check state0 and state1 and update angle.
+    state1 = digitalRead(IPIN1);
+    if (state0) {
+      if (state1) {
+        angle += 1;
+      } else {
+        angle -= 1;
+      }
+    } else {
+      if (state1) {
+         angle -= 1;
+      } else {
+        angle += 1;
+      }
+    }
+}
+
+void setup() {
+    pinMode(LED, OUTPUT);
+    Serial.begin(9600);
+    attachInterrupt(digitalPinToInterrupt(IPIN0), blink0, CHANGE);
+    attachInterrupt(digitalPinToInterrupt(IPIN1), blink1, CHANGE);
+    Serial.println("Ready");  // tell the computer we're ready
+    Serial.println("Time,Angle");
+}
+
+void loop() {
+  char command;
+  if (Serial.available()>0) {          // are there characters to read?
+    command = (char)Serial.read();     // grab one
+    if (command=='g') {                // check it
+      going=1;
+      angle=0;
+      t0=millis();
+    } else if (command=='s') {
+      going=0;
+    }
+  }
+  if (going) {
+    Serial.print(1.0*(millis()-t0)/1000,3);
+    Serial.print(",");
+    Serial.println(360.0*angle/2048,3);
+  }
+}
+
+


Initial commit

Initial commit

error: pathspec 'src/mqtt_gsm.ino' did not match any file(s) known to git

--- src/mqtt_gsm.ino
+++ src/mqtt_gsm.ino
@@ -0,0 +1,167 @@
+/**************************************************************
+ *
+ * For this example, you need to install PubSubClient library:
+ *   https://github.com/knolleary/pubsubclient/releases/latest
+ *   or from http://librarymanager/all#PubSubClient
+ *
+ * TinyGSM Getting Started guide:
+ *   http://tiny.cc/tiny-gsm-readme
+ *
+ **************************************************************
+ * Use Mosquitto client tools to work with MQTT
+ *   Ubuntu/Linux: sudo apt-get install mosquitto-clients
+ *   Windows:      https://mosquitto.org/download/
+ *
+ * Subscribe for messages:
+ *   mosquitto_sub -h test.mosquitto.org -t GsmClientTest/init -t GsmClientTest/ledStatus -q 1
+ * Toggle led:
+ *   mosquitto_pub -h test.mosquitto.org -t GsmClientTest/led -q 1 -m "toggle"
+ *
+ * You can use Node-RED for wiring together MQTT-enabled devices
+ *   https://nodered.org/
+ * Also, take a look at these additional Node-RED modules:
+ *   node-red-contrib-blynk-websockets
+ *   node-red-dashboard
+ *
+ **************************************************************/
+
+// Select your modem:
+#define TINY_GSM_MODEM_SIM800
+// #define TINY_GSM_MODEM_SIM900
+// #define TINY_GSM_MODEM_A6
+// #define TINY_GSM_MODEM_A7
+// #define TINY_GSM_MODEM_M590
+// #define TINY_GSM_MODEM_ESP8266
+
+#include <TinyGsmClient.h>
+#include <PubSubClient.h>
+#include <OneWire.h>
+#include <SimpleDHT.h>
+
+// Your GPRS credentials
+// Leave empty, if missing user or pass
+const char apn[]  = "YourAPN";
+const char user[] = "";
+const char pass[] = "";
+
+// Use Hardware Serial on Mega, Leonardo, Micro
+//#define SerialAT Serial1
+
+// or Software Serial on Uno, Nano
+#include <SoftwareSerial.h>
+SoftwareSerial SerialAT(2, 3); // RX, TX
+
+TinyGsm modem(SerialAT);
+TinyGsmClient client(modem);
+PubSubClient mqtt(client);
+
+const char* broker = "kw.dy.fi";
+
+const char* topicLed = "GsmClientTest/led";
+const char* topicInit = "GsmClientTest/init";
+const char* topicLedStatus = "GsmClientTest/ledStatus";
+
+#define LED_PIN 13
+int ledStatus = LOW;
+
+long lastReconnectAttempt = 0;
+int pinDHT22 = 2;
+SimpleDHT22 dht22;
+
+void setup() {
+  pinMode(LED_PIN, OUTPUT);
+
+  // Set console baud rate
+  Serial.begin(115200);
+  delay(10);
+
+  // Set GSM module baud rate
+  SerialAT.begin(115200);
+  delay(3000);
+
+  // Restart takes quite some time
+  // To skip it, call init() instead of restart()
+  Serial.println("Initializing modem...");
+  modem.restart();
+
+  // Unlock your SIM card with a PIN
+  //modem.simUnlock("1234");
+
+  Serial.print("Waiting for network...");
+  if (!modem.waitForNetwork()) {
+    Serial.println(" fail");
+    while (true);
+  }
+  Serial.println(" OK");
+
+  Serial.print("Connecting to ");
+  Serial.print(apn);
+  if (!modem.gprsConnect(apn, user, pass)) {
+    Serial.println(" fail");
+    while (true);
+  }
+  Serial.println(" OK");
+
+  // MQTT Broker setup
+  mqtt.setServer(broker, 1883);
+  mqtt.setCallback(mqttCallback);
+}
+
+boolean mqttConnect() {
+  Serial.print("Connecting to ");
+  Serial.print(broker);
+  if (!mqtt.connect("GsmClientTest")) {
+    Serial.println(" fail");
+    return false;
+  }
+  Serial.println(" OK");
+  mqtt.publish(topicInit, "GsmClientTest started");
+  mqtt.subscribe(topicLed);
+  return mqtt.connected();
+}
+
+void loop() {
+
+  if (mqtt.connected()) {
+    mqtt.loop();
+  } else {
+    // Reconnect every 10 seconds
+    unsigned long t = millis();
+    if (t - lastReconnectAttempt > 10000L) {
+      lastReconnectAttempt = t;
+      if (mqttConnect()) {
+        lastReconnectAttempt = 0;
+      }
+    }
+  }
+}
+
+void mqttCallback(char* topic, byte* payload, unsigned int len) {
+  Serial.print("Message arrived [");
+  Serial.print(topic);
+  Serial.print("]: ");
+  Serial.write(payload, len);
+  Serial.println();
+
+  // Only proceed if incoming message's topic matches
+  if (String(topic) == topicLed) {
+    // start working...
+  Serial.println("=================================");
+  Serial.println("Sample DHT22...");
+
+  // read without samples.
+  // @remark We use read2 to get a float data, such as 10.1*C
+  //    if user doesn't care about the accurate data, use read to get a byte data, such as 10*C.
+  float temperature = 0;
+  float humidity = 0;
+  int err = SimpleDHTErrSuccess;
+  if ((err = dht22.read2(pinDHT22, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
+    Serial.print("Read DHT22 failed, err="); Serial.println(err);delay(2000);
+    return;
+  }
+    ledStatus = !ledStatus;
+    digitalWrite(LED_PIN, ledStatus);
+    mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
+  }
+}
+


Create customMsgMrlComm.ino

Create customMsgMrlComm.ino

error: pathspec 'home/Calamity/customMsgMrlComm.ino' did not match any file(s) known to git

--- home/Calamity/customMsgMrlComm.ino
+++ home/Calamity/customMsgMrlComm.ino
@@ -0,0 +1,106 @@
+/**
+* MRLComm.c
+* -----------------
+* This file is part of MyRobotLab.
+* (myrobotlab.org)
+*
+* Enjoy !
+* @authors
+* GroG
+* Kwatters
+* Mats
+* calamity
+* and many others...
+*
+* MRL Protocol definition
+* -----------------
+* MAGIC_NUMBER|NUM_BYTES|FUNCTION|DATA0|DATA1|....|DATA(N)
+*              NUM_BYTES - is the number of bytes after NUM_BYTES to the end
+*
+* more info - http://myrobotlab.org/content/myrobotlab-api
+*
+* General Concept
+* -----------------
+* Arduino is a slave process to MyRobotLab Arduino Service - this file receives
+* commands and sends back data.
+* Refactoring has made MRLComm.c far more general
+* there are only 2 "types" of things - controllers and pins - or writers and readers
+* each now will have sub-types
+*
+* Controllers
+* -----------------
+* digital pins, pwm, pwm/dir dc motors, pwm/pwm dc motors
+*
+* Sensors
+* -----------------
+* digital polling pins, analog polling pins, range pins, oscope, trigger events
+*
+* Combination
+* -----------------
+* pingdar, non-blocking pulsin
+*
+* Requirements: MyRobotLab running on a computer & a serial connection
+*
+*  TODO - need a method to identify type of board http://forum.arduino.cc/index.php?topic=100557.0
+*  TODO - getBoardInfo() - returns board info !
+*  TODO - getPinInfo() - returns pin info !
+*  TODO - implement with std::vector vs linked list - https://github.com/maniacbug/StandardCplusplus/blob/master/README.md
+*  TODO - make MRLComm a c++ library
+*/
+
+
+// Included as a 3rd party arduino library from here: https://github.com/ivanseidel/LinkedList/
+#include "LinkedList.h"
+#include "MrlComm.h"
+
+/***********************************************************************
+ * GLOBAL VARIABLES
+ * TODO - work on reducing globals and pass as parameters
+*/
+MrlComm mrlComm;
+/***********************************************************************
+ * STANDARD ARDUINO BEGIN
+ * setup() is called when the serial port is opened unless you hack the
+ * serial port on your arduino
+ *
+ * Here we default out serial port to 115.2kbps.
+*/
+void setup() {
+  // TODO: the arduino service might get a few garbage bytes before we're able
+  // to run, we should consider some additional logic here like a "publishReset"
+  // publish version on startup so it's immediately available for mrl.
+  // TODO: see if we can purge the current serial port buffers
+  mrlComm.publishVersion();
+  // publish the board type (uno/mega)
+  mrlComm.publishBoardInfo();
+
+}
+
+/**
+ * STANDARD ARDUINO LOOP BEGIN
+ * This method will be called over and over again by the arduino, it is the
+ * main loop any arduino sketch runs
+ */
+void loop() {
+  // increment how many times we've run
+  // TODO: handle overflow here after 32k runs, i suspect this might blow up?
+  mrlComm.loopCount++;
+  // get a command and process it from the serial port (if available.)
+  mrlComm.readCommand();
+  // update devices
+  mrlComm.updateDevices();
+  // send back load time and memory
+  mrlComm.publishBoardStatus();
+
+
+  MrlMsg msg(PUBLISH_CUSTOM_MSG);
+  msg.countData();
+  int i=0;
+  while (mrlComm.getCustomMsgSize()){
+    int x = mrlComm.getCustomMsg();
+    //MrlMsg is the class that build message to send to MRL
+    msg.addData(x);
+    i++;
+  }
+  if (i) msg.sendMsg();
+} // end of big loop


Create attachInterrupt.ino

Create attachInterrupt.ino

error: pathspec 'interrupts/attachInterrupt.ino' did not match any file(s) known to git

--- interrupts/attachInterrupt.ino
+++ interrupts/attachInterrupt.ino
@@ -0,0 +1,40 @@
+#include <Arduino.h>
+
+/*
+Using attachInterrupt()
+
+James H. Bannock
+Norges teknisk-naturvitenskapelige universitet (NTNU)
+
+This example toggles the LED with every press of a button
+
+Notes:
+  - connect a push button switch to PIN 2
+  - we are focusing on falling-edge detection (5V -> GND), the input is normally
+    high and will be pulled low when the button is pressed, therefore we are
+    detecting the moment the switch is pressed (as opposed to the rising-edge
+    which will detect GND -> 5V transition)
+  - attachInterrupt requires a function name to be provided to act as the
+    interrupt function, here it is called toggleLed()
+  - digitalPinToInterrupt(pin) is required to convert physical pin number to
+    lower-level registry values
+
+*/
+
+#define LED_PIN 13
+#define INTERRUPT_PIN 2
+
+bool ledState = LOW;
+
+void setup() {
+  pinMode(LED_PIN, OUTPUT);
+  pinMode(INTERRUPT_PIN, INPUT_PULLUP); // pull-up to pin voltage to 5V
+  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), toggleLed, FALLING);
+}
+
+void loop() {}
+
+void toggleLed() {
+  ledState = !ledState; // ! means not, here ledState is flipped
+  digitalWrite(LED_PIN, ledState);
+}


Create main.ino

Create main.ino

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lolisa/2014-15.git/'


Create AZIMUTH.ino

Create AZIMUTH.ino

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Garuda-1/RealityGateway.git/'


refactored the directory struture to better suite having multiple types of firmware

error: pathspec 'Core/Core.ino' did not match any file(s) known to git

--- Core/Core.ino
+++ Core/Core.ino
@@ -0,0 +1,179 @@
+/*
+Author:    William Hogg
+Description:
+            This is a core proram for features that span all instances
+            of my robot control work on the CS26410 robot
+
+*/
+//included librarys
+#include <SharpIR.h>
+#include <NewPing.h>
+#include <Servo.h>
+
+//analog pin definitions
+#define LDRLeft         A0
+#define LDRCenter       A1
+#define LDRRight        A2
+#define LDRTop          A4
+#define SharpIr         A3
+
+//digital pin definitions
+#define SerialRx        0
+#define SerialTx        1
+#define IrRx            2
+#define IrTx            3
+#define PB1             4
+#define Dright          5
+#define Dleft           6
+#define LEDRed          7
+#define Ping1           8
+#define Ping2           9
+#define Ping3           10
+#define Ping4           11
+#define SharpIrEnable   12
+#define turret          13
+
+//calibration values
+#define DrightStop      67
+#define DleftStop       83
+#define TurretCenter    84
+
+//app control deffinition
+#define Forward         48
+#define Backward	49
+#define Turret_Left	50
+#define Turret_Right	51
+#define Pivot_Left	52
+#define Pivot_Right	53
+#define Stop	        54
+#define Function_1	55
+#define Function_2	56
+#define Function_3      57
+
+//object instantition
+Servo Driveleft;
+Servo Driveright;
+Servo Turret;
+SharpIR IRRangeFinder(SharpIr, 25, 93, 20150);
+NewPing sonar1(Ping1, Ping1, 200);
+NewPing sonar2(Ping2, Ping2, 200);
+NewPing sonar3(Ping3, Ping3, 200);
+NewPing sonar4(Ping4, Ping4, 200);
+
+void remote(int val) {
+  switch (val) {
+      case Forward:
+          //move forward
+          motorBasic(1);
+          break;
+      case Backward:
+          //move backwards
+          motorBasic(1);
+          break;
+      case Turret_Left:
+          //move turret left
+          break;
+      case Turret_Right:
+          //move Turret right
+          break;
+      case Pivot_Left:
+          //pivot robot left
+          motorBasic(2);
+          break;
+      case Pivot_Right:
+          //pivot robot right
+          motorBasic(3);
+          break;
+      case Stop:
+          //stop robot
+          motorBasic(0);
+          break;
+      case Function_1:
+          //implement function 1
+          break;
+      case Function_2:
+          //implement function 2
+          break;
+      case Function_3:
+          //implement function 2
+          break;
+      default:
+          //stuff perhaps
+          break;
+  }
+}
+
+void motorBasic(int dir) {
+  switch (dir) {
+    case -1:
+      //do something when var equals 1
+      Driveleft.write(DleftStop - 40);
+      Driveright.write(DrightStop + 40);
+      break;
+    case 0:
+      //do something when var equals 2
+      Driveleft.write(DleftStop );
+      Driveright.write(DrightStop);
+      break;
+    case 1:
+      //do something when var equals 2
+      Driveleft.write(DleftStop + 40);
+      Driveright.write(DrightStop - 40);
+      break;
+    case 2:
+      //do something when var equals 2
+      Driveleft.write(DleftStop);
+      Driveright.write(DrightStop + 40);
+      break;
+    case 3:
+      //do something when var equals 2
+      Driveleft.write(DleftStop - 40);
+      Driveright.write(DrightStop);
+      break;
+    default:
+      // if nothing else matches, do the default
+      // default is optional
+      break;
+  }
+}
+
+
+
+void setup() {
+
+  Driveleft.attach(Dleft);
+  Driveleft.write(DleftStop);
+  Driveright.attach(Dright);
+  Driveright.write(DrightStop);
+  Turret.attach(turret);
+  Turret.write(TurretCenter);
+
+  pinMode(LDRLeft, INPUT);
+  pinMode(LDRCenter, INPUT);
+  pinMode(LDRRight, INPUT);
+  pinMode(LDRTop, INPUT);
+  pinMode(PB1,INPUT);
+
+  pinMode(SharpIrEnable, OUTPUT);
+  pinMode(LEDRed, OUTPUT);
+
+  Serial.begin(9600);
+
+
+
+
+}
+
+void loop(){
+    Serial.println("starting loop");
+while(!Serial.available());
+int test1 = Serial.parseInt();
+Serial.flush();
+Serial.println(test1);
+remote(test1);
+delay(250);
+}
+
+
+
+