Added MPU calibration function

Added MPU calibration function

Original from Rodena and Rowberg, modified to enable writing the calibration values to the EEPROM of the Atmega328P. Moreover Limits are relaxed and the Progress of the calibration is logged.

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

--- MPU6050_calibration.ino
+++ MPU6050_calibration.ino
@@ -0,0 +1,368 @@
+// Arduino sketch that returns calibration offsets for MPU6050 //   Version 1.1  (31th January 2014)
+// Done by Luis Ródenas <luisrodenaslorda@gmail.com>
+// Based on the I2Cdev library and previous work by Jeff Rowberg <jeff@rowberg.net>
+// Updates (of the library) should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+
+// These offsets were meant to calibrate MPU6050's internal DMP, but can be also useful for reading sensors.
+// The effect of temperature has not been taken into account so I can't promise that it will work if you
+// calibrate indoors and then use it outdoors. Best is to calibrate and use at the same room temperature.
+
+/* ==========  LICENSE  ==================================
+ I2Cdev device library code is placed under the MIT license
+ Copyright (c) 2011 Jeff Rowberg
+
+ 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.
+ =========================================================
+ */
+
+// I2Cdev and MPU6050 must be installed as libraries
+#include "I2Cdev.h"
+#include "MPU6050.h"
+#include "Wire.h"
+#include <EEPROMex.h> // include EEPROM library to write the calibrated offset values into the EEPROM
+
+#define MEMORYBASEMPUCALIBOFFSET 96 // start storing the calibration values starting at this address
+#define DEBUGVERBOSE
+///////////////////////////////////   CONFIGURATION   /////////////////////////////
+//Change this 3 variables if you want to fine tune the skecth to your needs.
+int buffersize=1000;     //Amount of readings used to average, make it higher to get more precision but sketch will be slower  (default:1000)
+int discardfirstmeas=100;  // Amount of initial measurements to be discarded
+int acel_deadzone=10;     //Acelerometer error allowed, make it lower to get more precision, but sketch may not converge  (default:8)
+int giro_deadzone=10;     //Giro error allowed, make it lower to get more precision, but sketch may not converge  (default:1)
+int accel_offset_divisor=8; //8;
+int gyro_offset_divisor=4; //4;
+// deadzone: amount of variation between 2 consecutive measurements
+
+// default I2C address is 0x68
+// specific I2C addresses may be passed as a parameter here
+// AD0 low = 0x68 (default for InvenSense evaluation board)
+// AD0 high = 0x69
+MPU6050 accelgyro;
+//MPU6050 accelgyro(0x69); // <-- use for AD0 high
+
+int16_t ax, ay, az,gx, gy, gz;
+
+int mean_ax,mean_ay,mean_az,mean_gx,mean_gy,mean_gz,state=0;
+int ax_offset,ay_offset,az_offset,gx_offset,gy_offset,gz_offset;
+int ax_initoffset,ay_initoffset,az_initoffset,gx_initoffset,gy_initoffset,gz_initoffset;
+int16_t ax_offsetEEPROM,ay_offsetEEPROM,az_offsetEEPROM,gx_offsetEEPROM,gy_offsetEEPROM,gz_offsetEEPROM;
+unsigned int calibratedOffsetAdress = 0;
+
+unsigned int loopcount=0;
+
+
+///////////////////////////////////   SETUP   ////////////////////////////////////
+void setup() {
+  // join I2C bus (I2Cdev library doesn't do this automatically)
+  Wire.begin();
+  // COMMENT NEXT LINE IF YOU ARE USING ARDUINO DUE
+  TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz). Leonardo measured 250kHz.
+
+  // initialize serial communication
+  Serial.begin(115200);
+
+  // initialize device
+  accelgyro.initialize();
+
+  // wait for ready
+  while (Serial.available() && Serial.read()); // empty buffer
+  while (!Serial.available()){
+    Serial.println(F("Send any character to start sketch.\n"));
+    delay(1500);
+  }
+  while (Serial.available() && Serial.read()); // empty buffer again
+
+  // start message
+  Serial.println("\nMPU6050 Calibration Sketch");
+  delay(2000);
+  Serial.println("\nYour MPU6050 should be placed in horizontal position, with package letters facing up. \nDon't touch it until you see a finish message.\n");
+  delay(3000);
+  // verify connection
+  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
+  delay(1000);
+  // reset offsets
+  ax_initoffset=0;
+  ay_initoffset=0;
+  az_initoffset=0;
+  gx_initoffset=0;
+  gy_initoffset=0;
+  gz_initoffset=0;
+
+  accelgyro.setXAccelOffset(ax_initoffset);
+  accelgyro.setYAccelOffset(ay_initoffset);
+  accelgyro.setZAccelOffset(az_initoffset);
+  accelgyro.setXGyroOffset(gx_initoffset);
+  accelgyro.setYGyroOffset(gy_initoffset);
+  accelgyro.setZGyroOffset(gz_initoffset);
+
+          // set the fll scale range of the gyro- and accelerometer respectively
+        accelgyro.setFullScaleGyroRange(0); //0: 250deg/s | 1: 500deg/s | 2: 1000deg/s | 3: 2000deg/s
+        accelgyro.setFullScaleAccelRange(0); //0: 2g | 1: 4g | 2: 8g | 3: 16g
+
+  // Get config from EEPROM if there is one
+  // or initialise value with default ones set in StoreStruct
+  EEPROM.setMemPool(MEMORYBASEMPUCALIBOFFSET, EEPROMSizeATmega328); //Set memorypool base, assume Arduino Uno board
+
+}
+
+///////////////////////////////////   LOOP   ////////////////////////////////////
+void loop() {
+
+  bool CalibResult=false;
+
+  if (state==0){
+    Serial.println("\nReading sensors for first time...");
+    meansensors();
+    //if (abs(mean_ax)>=32000){ax_initoffset=-mean_ax;Serial.println("\nRemove X-axis deadlock...");}
+    //if (abs(mean_ay)>=32000){ay_initoffset=-mean_ay;Serial.println("\nRemove Y-axis deadlock...");}
+    //if (mean_az<-32000){az_initoffset=-mean_az;Serial.println("\nRemove Z-axis deadlock...");}
+    //if (abs(mean_gx)>=32000){gx_initoffset=-mean_gx;Serial.println("\nRemove Gyro X-axis deadlock...");}
+    //if (abs(mean_gy)>=32000){gy_initoffset=-mean_gy;Serial.println("\nRemove Gyro Y-axis deadlock...");}
+    //if (mean_gz<-32000){gz_initoffset=-mean_gz;Serial.println("\nRemove Gyro Z-axis deadlock...");}
+    state++;
+    delay(1000);
+  }
+
+  if (state==1) {
+    Serial.println("\nCalculating offsets...");
+    CalibResult=calibration();
+    if (CalibResult) {
+      Serial.println("\nCalibration successful!");
+    }
+    else {
+      Serial.println("\nCalibration failed!");
+    }
+    state++;
+    delay(1000);
+  }
+
+  if (state==2) {
+    meansensors();
+    ax_offsetEEPROM=ax_offset;
+    ay_offsetEEPROM=ay_offset;
+    az_offsetEEPROM=az_offset;
+    gx_offsetEEPROM=gx_offset;
+    gy_offsetEEPROM=gy_offset;
+    gz_offsetEEPROM=gz_offset;
+
+    Serial.println("\nFINISHED!");
+    Serial.print("\nSensor readings with offsets:\t");
+    Serial.print(mean_ax);
+    Serial.print("\t");
+    Serial.print(mean_ay);
+    Serial.print("\t");
+    Serial.print(mean_az);
+    Serial.print("\t");
+    Serial.print(mean_gx);
+    Serial.print("\t");
+    Serial.print(mean_gy);
+    Serial.print("\t");
+    Serial.println(mean_gz);
+    Serial.print("Your offsets:\t");
+    Serial.print(ax_offset+ax_initoffset);
+    Serial.print("\t");
+    Serial.print(ay_offset+ay_initoffset);
+    Serial.print("\t");
+    Serial.print(az_offset+az_initoffset);
+    Serial.print("\t");
+    Serial.print(gx_offset+gx_initoffset);
+    Serial.print("\t");
+    Serial.print(gy_offset+gy_initoffset);
+    Serial.print("\t");
+    Serial.println(gz_offset+gz_initoffset);
+    Serial.println("\nData is printed as: acelX acelY acelZ giroX giroY giroZ");
+    Serial.println("Check that your sensor readings are close to 0 0 16384 0 0 0");
+    Serial.println("If calibration was succesful write down your offsets so you can set them in your projects using something similar to mpu.setXAccelOffset(youroffset)");
+
+    // wait for ready
+  while (Serial.available() && Serial.read()); // empty buffer
+  while (!Serial.available()){
+    Serial.println(F("If you want to store the calibrated offset values into EEPROM, press \"y\" \n"));
+    delay(1500);
+  }
+  int inByte=0;
+  if (Serial.available() > 0) {
+  //while (Serial.available() && Serial.read()); // empty buffer again
+    inByte = Serial.read();
+    #ifdef DEBUGVERBOSE
+      Serial.print("Pressed key: ");Serial.println(inByte);
+    #endif
+  }
+
+  if (inByte==121) { // "y"
+      // 1
+        int addressInt = MEMORYBASEMPUCALIBOFFSET;
+        int output;
+        addressInt       = EEPROM.getAddress(sizeof(int));
+        EEPROM.updateInt(addressInt,ax_offsetEEPROM+ax_initoffset);
+        #ifdef DEBUGVERBOSE
+          output = EEPROM.readInt(addressInt);
+          Serial.print("address: ");Serial.println(addressInt);Serial.print("output: ");Serial.println(output);Serial.println("");
+        #endif
+        // 2
+        addressInt       = EEPROM.getAddress(sizeof(int));
+        EEPROM.updateInt(addressInt,ay_offsetEEPROM+ay_initoffset);
+        #ifdef DEBUGVERBOSE
+          output = EEPROM.readInt(addressInt);
+          Serial.print("address: ");Serial.println(addressInt);Serial.print("output: ");Serial.println(output);Serial.println("");
+        #endif
+        // 3
+        addressInt       = EEPROM.getAddress(sizeof(int));
+        EEPROM.updateInt(addressInt,az_offsetEEPROM+ax_initoffset);
+        #ifdef DEBUGVERBOSE
+          output = EEPROM.readInt(addressInt);
+          Serial.print("address: ");Serial.println(addressInt);Serial.print("output: ");Serial.println(output);Serial.println("");
+        #endif
+       // 4
+        addressInt       = EEPROM.getAddress(sizeof(int));
+        EEPROM.updateInt(addressInt,gx_offsetEEPROM+gx_initoffset);
+        #ifdef DEBUGVERBOSE
+          output = EEPROM.readInt(addressInt);
+          Serial.print("address: ");Serial.println(addressInt);Serial.print("output: ");Serial.println(output);Serial.println("");
+        #endif
+        // 5
+        addressInt       = EEPROM.getAddress(sizeof(int));
+        EEPROM.updateInt(addressInt,gy_offsetEEPROM+gy_initoffset);
+        #ifdef DEBUGVERBOSE
+          output = EEPROM.readInt(addressInt);
+          Serial.print("address: ");Serial.println(addressInt);Serial.print("output: ");Serial.println(output);Serial.println("");
+        #endif
+       // 6
+        addressInt       = EEPROM.getAddress(sizeof(int));
+        EEPROM.updateInt(addressInt,gz_offsetEEPROM+gz_initoffset);
+        #ifdef DEBUGVERBOSE
+          output = EEPROM.readInt(addressInt);
+          Serial.print("address: ");Serial.println(addressInt);Serial.print("output: ");Serial.println(output);Serial.println("");
+        #endif
+        Serial.println("Calibrated offset values stored in EEPROM!");
+  }
+  else {
+   Serial.println("Exiting without storing calibrated offset values into EEPROM");
+  }
+
+ #ifdef DEBUGVERBOSE
+   // dump values stored in EEPROM
+   for (uint8_t i = 0; i < 255; i++) {
+     Serial.println(EEPROM.readByte(i));
+   }
+ #endif
+    while (1);
+  }
+}
+
+///////////////////////////////////   FUNCTIONS   ////////////////////////////////////
+void meansensors(){
+  long i=0,buff_ax=0,buff_ay=0,buff_az=0,buff_gx=0,buff_gy=0,buff_gz=0;
+
+  while (i<(buffersize+discardfirstmeas+1)){
+    // read raw accel/gyro measurements from device
+    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
+
+    if (i>discardfirstmeas && i<=(buffersize+discardfirstmeas)){ //First 100 measures are discarded
+      buff_ax=buff_ax+ax;
+      buff_ay=buff_ay+ay;
+      buff_az=buff_az+az;
+      buff_gx=buff_gx+gx;
+      buff_gy=buff_gy+gy;
+      buff_gz=buff_gz+gz;
+    }
+    if (i==(buffersize+100)){
+      mean_ax=buff_ax/buffersize;
+      mean_ay=buff_ay/buffersize;
+      mean_az=buff_az/buffersize;
+      mean_gx=buff_gx/buffersize;
+      mean_gy=buff_gy/buffersize;
+      mean_gz=buff_gz/buffersize;
+    }
+    i++;
+    delay(2); //Needed so we don't get repeated measures
+  }
+
+  Serial.print("Results of measurements a/g:\t");
+  Serial.print(mean_ax); Serial.print("\t");
+  Serial.print(mean_ay); Serial.print("\t");
+  Serial.print(mean_az); Serial.print("\t");
+  Serial.print(mean_gx); Serial.print("\t");
+  Serial.print(mean_gy); Serial.print("\t");
+  Serial.println(mean_gz);
+}
+
+bool calibration(){
+  ax_offset=-mean_ax/accel_offset_divisor;
+  ay_offset=-mean_ay/accel_offset_divisor;
+  //az_offset=-mean_az/accel_offset_divisor;
+  az_offset=(16384-mean_az)/8;
+
+  gx_offset=-mean_gx/gyro_offset_divisor;
+  gy_offset=-mean_gy/gyro_offset_divisor;
+  gz_offset=-mean_gz/gyro_offset_divisor;
+  while (1){
+    int ready=0;
+    accelgyro.setXAccelOffset(ax_offset+ax_initoffset);
+    accelgyro.setYAccelOffset(ay_offset+ay_initoffset);
+    accelgyro.setZAccelOffset(az_offset+az_initoffset);
+
+    accelgyro.setXGyroOffset(gx_offset+gx_initoffset);
+    accelgyro.setYGyroOffset(gy_offset+gy_initoffset);
+    accelgyro.setZGyroOffset(gz_offset+gz_initoffset);
+
+    meansensors();
+    Serial.println("...");
+
+    if (abs(mean_ax)<=acel_deadzone) ready++;
+    else ax_offset=ax_offset-mean_ax/acel_deadzone;
+
+    if (abs(mean_ay)<=acel_deadzone) ready++;
+    else ay_offset=ay_offset-mean_ay/acel_deadzone;
+
+    //if (abs(mean_az)<=acel_deadzone) ready++;
+    //else az_offset=az_offset-mean_az/acel_deadzone;
+
+    if (abs(16384-mean_az)<=acel_deadzone) ready++;
+    else az_offset=az_offset+(16384-mean_az)/acel_deadzone;
+
+    if (abs(mean_gx)<=giro_deadzone) ready++;
+    else gx_offset=gx_offset-mean_gx/(giro_deadzone+1);
+
+    if (abs(mean_gy)<=giro_deadzone) ready++;
+    else gy_offset=gy_offset-mean_gy/(giro_deadzone+1);
+
+    if (abs(mean_gz)<=giro_deadzone) ready++;
+    else gz_offset=gz_offset-mean_gz/(giro_deadzone+1);
+
+    if (ready==6) {
+     return true;
+     break;
+    }
+
+    Serial.print("Resulting offset calibration value a/g:\t");
+  Serial.print(ax_offset+ax_initoffset); Serial.print("\t");
+  Serial.print(ay_offset+ay_initoffset); Serial.print("\t");
+  Serial.print(az_offset+az_initoffset); Serial.print("\t");
+  Serial.print(gx_offset+gx_initoffset); Serial.print("\t");
+  Serial.print(gy_offset+gy_initoffset); Serial.print("\t");
+  Serial.println(gz_offset+gz_initoffset);
+  loopcount=loopcount+1;
+  Serial.print("Loop Cnt: ");Serial.println(loopcount);
+  if (loopcount==10) {
+     return false;
+     break; // exit the calibration routine if no stable results can be obtained after 20 calibration loops
+    }
+  }
+}


Create IR_Diag.ino

Create IR_Diag.ino

Reads IR commands from an IR detector and displays the IR Code type, and hex value on an attached LCD. Requires IRRemote library to be installed.

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

--- IR_Diag.ino
+++ IR_Diag.ino
@@ -0,0 +1,102 @@
+/*
+ * IR_Diag -- Reads IR codes and displays them on an LCD, optionally to Serial
+ * Bill Kibby 11/06/2014
+ *
+ * Based on the the IRremote library by Ken Shirriff: http://arcfn.com
+ */
+
+#include <IRremote.h>
+#include <LiquidCrystal.h>
+
+/* Configure the folllowing pin to read the IR detector */
+int RECV_PIN = 2;
+IRrecv irrecv(RECV_PIN);
+decode_results results;
+
+/* This is based on my LCD shield, you may need to adjust this */
+LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
+
+/* Remove any comments on Serial commands to dump results to serial port simultaniously */
+
+byte block[8] = {
+  0b11111,
+  0b11111,
+  0b11111,
+  0b11111,
+  0b11111,
+  0b11111,
+  0b11111,
+  0b11111
+};
+
+void clearline(int line) /* Clear previous line by printing an entire line of blocks, then really clearing line. Handy to see an update from several feet away */
+{
+  int p;
+  int w=30;
+  for(p=0; p<16; p++)
+  {
+    lcd.setCursor(p,line);
+    lcd.write((byte)0);
+    delay(w);
+  }
+  delay(280);
+  lcd.setCursor(0,line);
+  lcd.write("                ");
+}
+
+void setup()
+{
+  // Serial.begin(115200);
+  irrecv.enableIRIn();
+  // Serial.println("Ready to decode IR!");
+  lcd.createChar(0, block); // create a new character
+  lcd.begin(16, 2);
+  lcd.clear();
+  lcd.setCursor(0,0);
+  lcd.print("IR Remote Reader");
+}
+
+void dump(decode_results *results){
+  char buffer[10];
+  clearline(1);
+  int count = results->rawlen;
+  if (results->decode_type == UNKNOWN) {
+    // Serial.println("Could not decode message");
+    lcd.setCursor(0,1);
+    lcd.write("UNKNOWN TYPE ");
+  }
+  else {
+    if (results->decode_type == NEC) {
+      // Serial.print("NEC: ");
+      lcd.setCursor(0,1);
+      lcd.write("NEC: ");
+    }
+    else if (results->decode_type == SONY) {
+      // Serial.print("SONY: ");
+      lcd.setCursor(0,1);
+      lcd.write("SONY: ");
+    }
+    else if (results->decode_type == RC5) {
+      // Serial.print("RC5: ");
+      lcd.setCursor(0,1);
+      lcd.write("RC5: ");
+    }
+    else if (results->decode_type == RC6) {
+      // Serial.print("RC6: ");
+      lcd.setCursor(0,1);
+      lcd.write("RC6: ");
+    }
+    // Serial.println(results->value, HEX);
+    sprintf(buffer, "%08lX", (unsigned long)results->value);
+    // Serial.println(buffer);
+    lcd.write(buffer);
+  }
+}
+
+void loop() {
+  if (irrecv.decode(&results)) {
+    //    Serial.println(results.value, HEX);
+    dump(&results);
+    irrecv.resume(); // Receive the next value
+  }
+}


Memory tested with Grove sensor

Memory tested with Grove sensor

See worklog for details

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

--- Meng/grove_with_memory.ino
+++ Meng/grove_with_memory.ino
@@ -0,0 +1,117 @@
+// timer interrupt based grove dust sensor program
+// timer1 will interrupt at 1Hz
+
+// JST Pin 1 (Black Wire) = > Arduino GND
+// JST Pin 3 (Red wire) = > Arduino 5VDC
+// JST Pin 4 (Yellow wire) = > Arduino Digital Pin 8
+#include <SPI.h>
+
+//toggle variables to monitor timer interrupt status using oscilloscope
+boolean toggle1 = 0;
+
+int pin = 8;
+unsigned long duration;
+unsigned long starttime;
+unsigned long sampletime_ms = 1000;//sample 1s ;
+unsigned long lowpulseoccupancy = 0;
+float ratio = 0;
+float concentration = 0;
+
+//SRAM opcodes
+#define RDSR        5
+#define WRSR        1
+#define READ        3
+#define WRITE       2
+
+//Byte transfer functions
+uint8_t Spi23LC1024Read8(uint32_t address) {
+	uint8_t read_byte;
+
+	PORTB &= ~(1 << PORTB2);        //set SPI_SS low
+	SPI.transfer(READ);
+	SPI.transfer((uint8_t)(address >> 16) & 0xff);
+	SPI.transfer((uint8_t)(address >> 8) & 0xff);
+	SPI.transfer((uint8_t)address);
+	read_byte = SPI.transfer(0x00);
+	PORTB |= (1 << PORTB2);         //set SPI_SS high
+	return read_byte;
+}
+
+void Spi23LC1024Write8(uint32_t address, uint8_t data_byte) {
+	PORTB &= ~(1 << PORTB2);        //set SPI_SS low
+	SPI.transfer(WRITE);
+	SPI.transfer((uint8_t)(address >> 16) & 0xff);
+	SPI.transfer((uint8_t)(address >> 8) & 0xff);
+	SPI.transfer((uint8_t)address);
+	SPI.transfer(data_byte);
+	PORTB |= (1 << PORTB2);         //set SPI_SS high
+}
+
+void setup(){
+
+	//set pins as outputs
+	Serial.begin(9600);
+	SPI.begin();
+	pinMode(8, INPUT);
+	pinMode(5, OUTPUT);
+
+	cli();//stop interrupts
+
+	//set timer1 interrupt at 1Hz
+	TCCR1A = 0;// set entire TCCR1A register to 0
+	TCCR1B = 0;// same for TCCR1B
+	TCNT1 = 0;//initialize counter value to 0
+	// set compare match register for 1hz increments
+	OCR1A = 62499;// must be <65536, see worklog for calculation
+	// turn on CTC mode
+	TCCR1B |= (1 << WGM12);
+	// Set CS12 and CS10 bits for 1024 prescaler
+	TCCR1B |= (1 << CS12) | (1 << CS10);
+	// enable timer compare interrupt
+	TIMSK1 |= (1 << OCIE1A);
+
+	sei();//enable global interrupts
+
+}//end setup
+
+ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
+	//generates pulse wave of the same fequency as the interrupt, monitor using oscilloscope
+	if (toggle1){
+		digitalWrite(5, HIGH);
+		toggle1 = 0;
+	}
+	else{
+		digitalWrite(5, LOW);
+		toggle1 = 1;
+	} // THIS PART NEEDS TO BE COMMENTED OUT IN FINAL CODE!
+
+	ratio = lowpulseoccupancy / (sampletime_ms*10.0);  // Integer percentage 0=>100
+	concentration = 1.1*pow(ratio, 3) - 3.8*pow(ratio, 2) + 520 * ratio + 0.62; // using spec sheet curve
+
+	uint16_t concentration16 = (uint16_t)concentration;
+	uint8_t upperh = (uint8_t)(concentration16 >> 8);
+	uint8_t lowerh = (uint8_t)(concentration16);
+	uint16_t concentration_new = (upperh << 8) | lowerh;
+
+	Serial.print("Concentration: ");
+	Serial.println(concentration16);
+	Serial.print("\tRepeated: ");
+	Serial.println(concentration_new);
+
+	Spi23LC1024Write8(0, upperh);
+	Spi23LC1024Write8(1, lowerh);
+
+	uint8_t upperh_new = Spi23LC1024Read8(0);
+	uint8_t lowerh_new = Spi23LC1024Read8(1);
+
+	uint16_t concentration_read = (upperh_new << 8) | lowerh_new;
+	Serial.print("\t\tRead out: ");
+	Serial.println(concentration_read);
+
+	lowpulseoccupancy = 0;
+}
+
+void loop(){
+	duration = pulseIn(pin, LOW);
+	lowpulseoccupancy = lowpulseoccupancy + duration;
+}


New exaple for Serial communication

New exaple for Serial communication

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

--- SerialCommunication/SerialCommunication.ino
+++ SerialCommunication/SerialCommunication.ino
@@ -0,0 +1,17 @@
+void setup() {
+  Serial.begin(9600);
+
+  while (!Serial) {
+    ; // cekani na seriovy port
+  }
+
+  Serial.print("Napiste sve jmeno: ");
+}
+
+void loop() {
+    if (Serial.available() > 0) {
+      String text = Serial.readString();
+
+      Serial.println(text);
+    }
+}


Adding working rainbowduino heart animation

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

--- sketches/rainbow_heart/rainbow_heart.ino
+++ sketches/rainbow_heart/rainbow_heart.ino
@@ -0,0 +1,160 @@
+/*
+ * Rainbowduino-based Heart Animation
+ *
+ * Created on: Jul 30, 2014
+ * Author: Konstantin Gredeskoul
+ *
+ * © 2014 All rights reserved.  Please see LICENSE.
+ *
+ */
+
+#include <Rainbowduino.h>
+
+const char *hearts[] = {
+		".XX.XX.."
+		"XXXXXXX."
+		"XXXXXXX."
+		".XXXXX.."
+		"..XXX..."
+		"...X...."
+		"........"
+		"........",
+
+		"........"
+		".XX.XX.."
+		"XXXXXXX."
+		"XXXXXXX."
+		".XXXXX.."
+		"..XXX..."
+		"...X...."
+		"........",
+
+		"........"
+		"........"
+		".XX.XX.."
+		"XXXXXXX."
+		"XXXXXXX."
+		".XXXXX.."
+		"..XXX..."
+		"...X...." ,
+
+		"........"
+		"........"
+		"..XX.XX."
+		".XXXXXXX"
+		".XXXXXXX"
+		"..XXXXX."
+		"...XXX.."
+		"....X...",
+
+		"........"
+		"..XX.XX."
+		".XXXXXXX"
+		".XXXXXXX"
+		"..XXXXX."
+		"...XXX.."
+		"....X..."
+		"........",
+
+
+		"..XX.XX."
+		".XXXXXXX"
+		".XXXXXXX"
+		"..XXXXX."
+		"...XXX.."
+		"....X..."
+		"........"
+		"........"
+};
+
+
+const uint8_t
+		numberOfHearts = 6,
+		matrixSize = 8,
+		matrix2DSize = matrixSize * matrixSize;
+
+uint32_t i;
+uint8_t x, length;
+
+int randomColor;
+
+
+void getLineFromPattern(const char *pattern, uint8_t i, uint8_t *x, uint8_t *length) {
+	bool lineStarted = false;
+	*x = *length = 0;
+	for(uint8_t j = 0; j < matrixSize; j++) {
+		char c = pattern[i + j * matrixSize];
+		if (!lineStarted && c == 'X') {
+			*x = j;
+			lineStarted = true;
+		} else if (lineStarted && (c == '.')) {
+			*length = j - *x;
+			lineStarted = false;
+			break;
+		} else if (lineStarted && j == matrixSize - 1) {
+			*length = j - *x + 1;
+			lineStarted = false;
+			break;
+		}
+	}
+}
+
+void drawHeart(uint32_t color, uint8_t delayMs, const char* pattern) {
+	for (uint8_t i = 0; i < matrixSize; i++) {
+		getLineFromPattern(pattern, i, &x, &length);
+		if (length > 0)
+			Rb.drawHorizontalLine(x, i, length, color);
+		if (delayMs > 0) { 	delay(delayMs);	}
+	}
+}
+
+void fillOutRandom(uint32_t color, const char* pattern) {
+	uint16_t i;
+
+	char matrix[matrix2DSize];
+	for (i = 0; i < matrix2DSize; i++) {
+		matrix[i] = '_';
+	}
+
+	i = 0;
+	while (strncmp(pattern, matrix, matrix2DSize) != 0) {
+		i++;
+		uint8_t coordinate = rand() % matrix2DSize;
+		if (matrix[coordinate] != '_')
+			continue;
+
+		if (pattern[coordinate] == 'X' && matrix[coordinate] != 'X') {
+			Rb.drawHorizontalLine(coordinate / matrixSize, coordinate % matrixSize, 1, color);
+			delay(50);
+			continue;
+		}
+		if (matrix[coordinate] != pattern[coordinate]) {
+			matrix[coordinate] = pattern[coordinate];
+			continue;
+		}
+		if (i > 16000) { return; }
+	}
+}
+
+
+void setup() {
+	Rb.init();
+	Serial.begin(9600);
+	srand(millis());
+}
+
+
+void loop() {
+	randomColor = rand() % 8 + 1;
+	for (uint8_t j = 0; j < numberOfHearts; j++) {
+		// only vary red's intensity
+		drawHeart(randomColor * 0x100000, 1, hearts[j]);
+		delay(300);
+		Rb.blankDisplay();
+	}
+
+	delay(60000);
+
+}
+
+


arm auto shutdown

arm auto shutdown

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

--- robik_arduino.ino
+++ robik_arduino.ino
@@ -0,0 +1,949 @@
+/*
+ * On the Arduino Mega we have 6 timers and 15 PWM outputs:
+ * Pins 4 and 13: controlled by timer0 (used by clock)
+ * Pins 11 and 12: controlled by timer1 (Servo library)
+ * Pins 9 and10: controlled by timer2 (NewPing)
+ * Pin 2, 3 and 5: controlled by timer 3 (free)
+ * Pin 6, 7 and 8: controlled by timer 4 (free)
+ * Pin 46, 45 and 44:: controlled by timer 5 (free)
+ *
+ * PWM pins 2-13, 44-46. Free 9: 2,3,5,6,7,8,44,45,46
+ *
+ * IMU MPU9150 uses library from https://github.com/richards-tech/RTIMULib-Arduino.git
+ */
+
+#include <NewPing.h>
+#include <Servo.h>
+#include <RunningMedian.h>
+#include <Wire.h>
+#include "I2Cdev.h"
+#include "RTIMUSettings.h"
+#include "RTIMU.h"
+#include "CalLib.h"
+#include <EEPROM.h>
+#include <ros.h>
+#include "geometry_msgs/Twist.h"
+#include "robik/GenericStatus.h"
+#include "robik/GenericControl.h"
+#include "robik/ArmControl.h"
+#include "robik.h"
+#include "robot_config.h"
+#include "robik_api.h"
+
+
+ros::NodeHandle nh;
+
+void genericMessageListener(const robik::GenericControl& msg);
+void armMessageListener(const robik::ArmControl& msg);
+void velocityMessageListener(const geometry_msgs::Twist& msg);
+ros::Subscriber<robik::GenericControl> sub_generic_control("robik_generic_control", &genericMessageListener);
+ros::Subscriber<robik::ArmControl> sub_arm_control("robik_arm_control", &armMessageListener);
+ros::Subscriber<geometry_msgs::Twist> sub_velocity_control("robik_velocity_control", &velocityMessageListener);
+
+robik::GenericStatus status_msg;
+ros::Publisher pub_status("robik_status", &status_msg);
+
+unsigned long range_timer50;
+int motor_left_dir = 1; //direction for motor expected to go. 1 means forward
+int motor_right_dir = 1;
+double req_motor_left = 0; //store required wheel velocity
+double req_motor_right = 0;
+double old_motor_left = 0; //store to compare if speed changed since last cmd_vel
+double old_motor_right = 0;
+long odom_ticks_left_since_cmd = 0;
+long odom_ticks_right_since_cmd = 0;
+unsigned long millis_since_cmd = 0;
+
+//sonar.h
+unsigned long pingTimer;
+NewPing sonar(PIN_USOUND_TRIG, PIN_USOUND_ECHO, MAX_DISTANCE);
+void echoCheck();
+
+//IMU
+RTIMU *imu;                                           // the IMU object
+RTIMUSettings settings;                               // the settings object
+void read_IMU();
+void clean_IMU();
+
+//DISPLAY_INTERVAL sets the rate at which results are displayed
+#define DISPLAY_INTERVAL  300                         // interval between pose displays
+
+unsigned long lastDisplay;
+unsigned long lastRate;
+int sampleCount = 0;
+
+//determine the sign of a value
+template <typename type>
+type sign(type value) {
+	return type((value>0)-(value<0));
+}
+
+template <typename type>
+type signNZ(type value) {
+	return (value < 0) ? -1 : 1;
+}
+
+//arm.h
+void armPreInit();
+void armSetJointState(uint32_t clamp, uint32_t roll, uint32_t elbow, uint32_t shoulder, uint32_t yaw, uint32_t time_to_complete);
+unsigned long servoSenseTimer;
+FastRunningMedian<unsigned int,32, 0> servoSenseMedian_yaw;
+FastRunningMedian<unsigned int,32, 0> servoSenseMedian_shoulder;
+FastRunningMedian<unsigned int,32, 0> servoSenseMedian_elbow;
+FastRunningMedian<unsigned int,32, 0> servoSenseMedian_roll;
+FastRunningMedian<unsigned int,32, 0> servoSenseMedian_clamp;
+uint32_t shoulder2 = 512;
+estimated_pos_t estimated_clamp_pos;
+void refreshMotorJoints();
+unsigned long arm_enabled_time = 0;
+unsigned long arm_disabled_time = 1;
+
+//move.h
+void intr_left_encoder();
+void intr_right_encoder();
+void velocity_control_VelTh(float vel, float th);
+void velocity_control_LR();
+int motor_vel_to_pwm(double vel);
+
+//parking.h
+#define PARK_BACKSPEED -0.17 //-0.1 necouva
+#define PARK_TURNSPEED 0.9 //calibrated, do not put less, it won't work unless excitation energy will be provided
+#define PARK_BACKTURNSPEED_SLOW_RATIO 0.2
+#define PARKPHASE_NOPARKING 0
+#define PARKPHASE_NAVIGATING 1
+#define PARKPHASE_ROTATING 2
+#define PARKPHASE_BACKWARD 3
+#define PARKPHASE_PARKED 4
+	//0: normal operation;
+	//1: navigating to base;
+	//2: rotating to find laser;
+	//3: going backwards;
+	//4: final stage going backwards
+int state_parking = 0;
+int park_last_spotted = 0; //0: no value; 1: inner; -1: outer
+
+void park_rotating(bool inner, bool outer);
+void park_backward(bool inner, bool outer);
+void park_parked(bool inner, bool outer);
+void handle_parking();
+
+/*------------------Utils----------------------------*/
+#define LOG_STR_LEN 150
+char charBuf[LOG_STR_LEN + 1];
+char strtmp[LOG_STR_LEN + 1];
+
+void init_variables() {
+
+	estimated_clamp_pos.orig_time.sec = 0;
+	estimated_clamp_pos.orig_time.nsec = 0;
+	estimated_clamp_pos.time_to_complete = 0;
+	estimated_clamp_pos.orig_pos = 0;
+	estimated_clamp_pos.target_pos = 0;
+	estimated_clamp_pos.corrected = false;
+
+	status_msg.status_code = (int32_t *) malloc(20 * sizeof(int32_t));
+}
+
+void log_string(String str) {
+
+	unsigned int str_length = str.length();
+
+	if (str_length > 0) {
+
+		if (str_length > LOG_STR_LEN)
+			str_length = LOG_STR_LEN;
+
+		str.toCharArray(charBuf, str_length + 1);
+		status_msg.log_message = &charBuf[0];
+		status_msg.log_count++;
+
+	}
+
+}
+
+void log_chars(char *str) {
+
+	if (strlen(str) > 0) {
+		strcpy(charBuf, str);
+		status_msg.log_message = &charBuf[0];
+		status_msg.log_count++;
+
+	}
+
+}
+
+void status_msg_clean () {
+	charBuf[0] = '\0';
+	status_msg.log_count = 0;
+	status_msg.status_code_length = 0;
+	status_msg.status_param_length = 0;
+	clean_IMU();
+}
+
+void add_status_code (int32_t code) {
+	if (status_msg.status_code_length < 20) {
+		status_msg.status_code[status_msg.status_code_length] = code;
+		status_msg.status_code_length++;
+	}
+}
+
+void jetsonPower() {
+
+	if (digitalRead(PIN_JETSONPOWER) == LOW) {
+		digitalWrite(PIN_PETRPOWER, LOW); // Jetson was powered down (was up before). Poweroff whole robot
+	}
+}
+
+
+/*------------------State----------------------------*/
+#include "robik_state.h"
+
+/*--------------------SETUP()------------------------*/
+void setup() {
+
+	//Power
+	pinMode(PIN_PETRPOWER, OUTPUT);   // this pin needs to be enabled to keep power on
+	digitalWrite(PIN_PETRPOWER, HIGH); // turn on power
+	pinMode(PIN_JETSONPOWER, INPUT);  // read power-on status of Jetson
+	pinMode(PIN_CHARGER_BUTTON, OUTPUT);  // read power-on status of Jetson
+
+	init_variables();
+
+	//Arm
+	Serial3.begin(9600);
+	delay(100);
+	servoSenseTimer = millis();
+	pinMode(PIN_ARM_FORE_CLAMP, INPUT);
+	pinMode(PIN_ARM_BACK_CLAMP, INPUT);
+	digitalWrite(PIN_ARM_FORE_CLAMP, HIGH); // turn on pullup resistors
+	digitalWrite(PIN_ARM_BACK_CLAMP, HIGH); // turn on pullup resistors
+
+	//LED
+	pinMode(PIN_LED, OUTPUT);
+	digitalWrite(PIN_LED, LOW);
+
+	//power arm
+	pinMode(PIN_RELAY, OUTPUT);
+	digitalWrite(PIN_RELAY, HIGH);
+	armPreInit();
+	digitalWrite(PIN_RELAY, LOW);  //turn off arm (as standby)
+
+	//IMU init
+	int errcode;
+	Wire.begin();
+	imu = RTIMU::createIMU(&settings);  // create the imu object
+
+	if ((errcode = imu->IMUInit()) < 0) {
+		//#Serial.print("Failed to init IMU: "); Serial.println(errcode);
+	}
+
+	imu->getCalibrationValid();
+
+	//ROS node
+	nh.getHardware()->setBaud(115200); //57600 115200
+	nh.initNode();
+	nh.subscribe(sub_generic_control);
+	nh.subscribe(sub_arm_control);
+	nh.subscribe(sub_velocity_control);
+	nh.advertise(pub_status);
+
+	while(!nh.connected()) {
+		jetsonPower();
+		nh.spinOnce();
+	}
+	nh.loginfo("Arduino connected");
+
+	range_timer50 = 11;
+
+	//sonar
+	pingTimer = millis();
+
+	//odometry encoders
+	pinMode(PIN_ODOM_LEFT, INPUT);
+	digitalWrite(PIN_ODOM_LEFT, HIGH);       // turn on pullup resistor
+	pinMode(PIN_ODOM_RIGHT, INPUT);
+	digitalWrite(PIN_ODOM_RIGHT, HIGH);       // turn on pullup resistor
+	attachInterrupt(INT_ODOM_LEFT, intr_left_encoder, CHANGE);
+	attachInterrupt(INT_ODOM_RIGHT, intr_right_encoder, CHANGE);
+
+	//bumber
+	pinMode(PIN_BUMPER, INPUT);
+	digitalWrite(PIN_BUMPER, HIGH); // turn on pullup resistors
+
+	//motion detector
+	pinMode(PIN_MOTION_DETECTOR, INPUT);
+
+	//velocity
+	pinMode(PIN_MOTOR_LEFT_ENA, OUTPUT); //Motor left
+	pinMode(PIN_MOTOR_LEFT_0, OUTPUT);
+	pinMode(PIN_MOTOR_LEFT_1, OUTPUT);
+	pinMode(PIN_MOTOR_RIGHT_ENA, OUTPUT); //Motor right
+	pinMode(PIN_MOTOR_RIGHT_0, OUTPUT);
+	pinMode(PIN_MOTOR_RIGHT_1, OUTPUT);
+
+	//menu control
+	pinMode(PIN_MENU_MENU, INPUT);
+	digitalWrite(PIN_MENU_MENU, HIGH); // turn on pullup resistors
+	pinMode(PIN_MENU_OK, INPUT);
+	digitalWrite(PIN_MENU_OK, HIGH); // turn on pullup resistors
+	pinMode(PIN_MENU_CANCEL, INPUT);
+	digitalWrite(PIN_MENU_CANCEL, HIGH); // turn on pullup resistors
+	pinMode(PIN_MENU_UP, INPUT);
+	digitalWrite(PIN_MENU_UP, HIGH); // turn on pullup resistors
+	pinMode(PIN_MENU_DOWN, INPUT);
+	digitalWrite(PIN_MENU_DOWN, HIGH); // turn on pullup resistors
+
+}
+
+//Return time difference in milliseconds
+uint32_t ros_time_diff(ros::Time before, ros::Time after) {
+	uint32_t sec = after.sec - before.sec;
+	uint32_t nsec = after.nsec - before.nsec;
+
+	if (nsec < 0) {
+		nsec = 1000 + nsec;
+	}
+
+	return sec * 1000 + nsec / 1000000;
+}
+
+//-1: t2<t1
+// 0: t2==t1
+// 1: t2>t1
+int ros_time_cmp(ros::Time t1, ros::Time t2) {
+	if (t1.sec == t2.sec && t1.nsec == t2.nsec)
+		return 0;
+
+	if (ros_time_diff(t1, t2) > 0)
+		return 1;
+	else
+		return -1;
+}
+
+void checkClampAndStop() {
+//time_to_complete [ms]
+	ros::Time now = nh.now();
+	uint32_t milliseconds_since_start = ros_time_diff(estimated_clamp_pos.orig_time, now);
+
+	if ( (estimated_clamp_pos.orig_pos < estimated_clamp_pos.target_pos) &&
+	     (milliseconds_since_start < (estimated_clamp_pos.time_to_complete + 700)) ) { //clamp is being moved, try hard for extra 700
+		double progress = milliseconds_since_start / estimated_clamp_pos.time_to_complete;
+		progress *= 0.9; //bring it back a bit to compensate late detection
+		if (progress > 1)
+			progress = 1;
+
+		uint32_t estimatedClampPos = estimated_clamp_pos.orig_pos + (uint32_t)(progress * (estimated_clamp_pos.target_pos - estimated_clamp_pos.orig_pos));
+		sprintf(strtmp, "SSS %lu | TTC %lu | ORG %lu | TRG %lu | PRG %lu | ECP %lu", milliseconds_since_start, estimated_clamp_pos.time_to_complete, estimated_clamp_pos.orig_pos, estimated_clamp_pos.target_pos, (uint32_t)(progress*100), estimatedClampPos); log_chars(strtmp);
+		armSetJointState(estimatedClampPos, 0, 0, 0, 0, 80); //80ms
+		estimated_clamp_pos.corrected = true; //prevent iteration for stopping clamp again
+	}
+	else
+		sprintf(strtmp, "SSS %lu | TTC %lu | ORG %lu | TRG %lu ", milliseconds_since_start, estimated_clamp_pos.time_to_complete, estimated_clamp_pos.orig_pos, estimated_clamp_pos.target_pos); log_chars(strtmp);
+}
+
+unsigned int menu_lag = 0;
+uint8_t menu_controls(){
+  uint8_t res = 0;
+
+  if (menu_lag > 3) {
+		menu_lag = 0;
+		if (digitalRead(PIN_MENU_MENU) == LOW)
+			res |= MASK_MENU_MENU;
+		if (digitalRead(PIN_MENU_OK) == LOW)
+			res |= MASK_MENU_OK;
+		if (digitalRead(PIN_MENU_CANCEL) == LOW)
+			res |= MASK_MENU_CANCEL;
+		if (digitalRead(PIN_MENU_UP) == LOW)
+			res |= MASK_MENU_UP;
+		if (digitalRead(PIN_MENU_DOWN) == LOW)
+			res |= MASK_MENU_DOWN;
+  }
+  else {
+		menu_lag++;
+  }
+  return res;
+}
+
+
+/*---------------------- LOOP() ---------------------*/
+void loop() {
+
+	//sent status message
+	if ( (millis()-range_timer50) > 50){   //[ms] 50ms == 20Hz
+
+		status_msg.header.stamp = nh.now();
+
+		//bumper
+		status_msg.bumper_front = bumperFront;
+		bumperFrontPublished = true;
+
+		//menu controls
+		status_msg.menu_controls = menu_controls();
+
+		//odom
+		status_msg.odom_ticksLeft = motor_left_dir * odom_ticks_left;
+		status_msg.odom_ticksRight = motor_right_dir * odom_ticks_right;
+		odom_ticks_left = 0;
+		odom_ticks_right = 0;
+		unsigned long now = millis();
+		status_msg.odom_millisSinceLastUpdate = now - odomMillisSinceLastUpdate;
+		odomMillisSinceLastUpdate = now;
+
+		//wheels are expected to move but robot is stopped
+		velocity_control_LR();
+//add_status_code(req_motor_left);
+//add_status_code(old_motor_left);
+//add_status_code(odom_ticks_left_since_cmd);
+//add_status_code(millis_since_cmd);
+
+
+		//sonar
+		status_msg.ultrasound_Back = ultrasoundBack;
+
+		//arm
+		status_msg.arm_yaw = servoSenseMedian_yaw.getMedian();
+		status_msg.arm_shoulder = servoSenseMedian_shoulder.getMedian();
+		status_msg.arm_elbow = servoSenseMedian_elbow.getMedian();
+		status_msg.arm_roll = servoSenseMedian_roll.getMedian();
+		status_msg.arm_clamp = servoSenseMedian_clamp.getMedian();
+
+		status_msg.arm_fore_clamp = digitalRead(PIN_ARM_FORE_CLAMP) == LOW ? true : false;
+		status_msg.arm_back_clamp = digitalRead(PIN_ARM_BACK_CLAMP) == LOW ? true : false;
+		if (estimated_clamp_pos.corrected == false && (status_msg.arm_fore_clamp == true || status_msg.arm_back_clamp == true))
+			checkClampAndStop();
+
+		//motion detector
+		status_msg.motion_detector = motionDetector;
+		motionDetectorPublished = true;
+
+
+		//parking photo sensor
+		status_msg.parkSens_inner = analogRead(PIN_PARK_SENS_INNER);
+		status_msg.parkSens_outer = analogRead(PIN_PARK_SENS_OUTER);
+
+
+		//IMU
+		status_msg.imu_sample_count = sampleCount;
+		status_msg.imu_gyro_bias_valid = imu->IMUGyroBiasValid();  //do not move IMU if false
+
+		refreshMotorJoints();
+
+		//publish
+		range_timer50 = millis();
+		pub_status.publish(&status_msg);
+		status_msg_clean();
+
+		//check arm power timeout
+		if (arm_enabled_time != 0 && (arm_enabled_time + ARM_TIME_MAX_ENABLED) < millis()) {
+			setArmPower(false);
+		}
+
+	}
+
+	//thigs to be done frequently
+	read_IMU();
+	handle_parking();
+	jetsonPower();
+
+	nh.spinOnce();
+
+	//sonar
+	if (millis() >= pingTimer) {         // Is it this sensor's time to ping?
+		pingTimer += PING_INTERVAL;
+		sonar.ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
+	}
+
+	//bumper
+	if (digitalRead(PIN_BUMPER) == LOW) {
+		bumperFrontPublished = false;
+		bumperFront = true;
+	}
+	else {
+		if (bumperFrontPublished == true) bumperFront = false;
+	}
+
+	//motion detector
+	if (digitalRead(PIN_MOTION_DETECTOR) == HIGH) {
+		motionDetectorPublished = false;
+		motionDetector = true;
+	}
+	else {
+		if (motionDetectorPublished == true) motionDetector = false;
+	}
+
+	//servo sense
+	if (millis() >= servoSenseTimer) {         // Is it this sensor's time to ping?
+		servoSenseTimer += SERVO_SENSE_INTERVAL;
+                servoSenseMedian_yaw.addValue(analogRead(PIN_SERVO_SENSE_YAW));
+                servoSenseMedian_shoulder.addValue(analogRead(PIN_SERVO_SENSE_SHOULDER));
+                servoSenseMedian_elbow.addValue(analogRead(PIN_SERVO_SENSE_ELBOW));
+                servoSenseMedian_roll.addValue(analogRead(PIN_SERVO_SENSE_ROLL));
+                servoSenseMedian_clamp.addValue(analogRead(PIN_SERVO_SENSE_CLAMP));
+	}
+
+} //end of loop
+
+
+void clean_IMU() {
+	for (int i = 0; i < 3; i++) {
+		status_msg.imu_angular_velocity_v3_x[i] = 0;
+		status_msg.imu_angular_velocity_v3_y[i] = 0;
+		status_msg.imu_angular_velocity_v3_z[i] = 0;
+
+		status_msg.imu_linear_acceleration_v3_x[i] = 0;
+		status_msg.imu_linear_acceleration_v3_y[i] = 0;
+		status_msg.imu_linear_acceleration_v3_z[i] = 0;
+
+		status_msg.imu_compass_v3_x[i] = 0;
+		status_msg.imu_compass_v3_y[i] = 0;
+		status_msg.imu_compass_v3_z[i] = 0;
+	}
+	sampleCount = 0;
+}
+
+void read_IMU() {
+
+	if (sampleCount < 3 && imu->IMURead()) { // get the latest data if ready yet
+		RTVector3 gyro_v3 = (RTVector3&)imu->getGyro();
+		status_msg.imu_angular_velocity_v3_x[sampleCount] = gyro_v3.x();
+		status_msg.imu_angular_velocity_v3_y[sampleCount] = gyro_v3.y();
+		status_msg.imu_angular_velocity_v3_z[sampleCount] = gyro_v3.z();
+
+		RTVector3 accel_v3 = (RTVector3&)imu->getAccel();
+		status_msg.imu_linear_acceleration_v3_x[sampleCount] = accel_v3.x();
+		status_msg.imu_linear_acceleration_v3_y[sampleCount] = accel_v3.y();
+		status_msg.imu_linear_acceleration_v3_z[sampleCount] = accel_v3.z();
+
+		RTVector3 compass_v3 = (RTVector3&)imu->getCompass();
+		status_msg.imu_compass_v3_x[sampleCount] = compass_v3.x();
+		status_msg.imu_compass_v3_y[sampleCount] = compass_v3.y();
+		status_msg.imu_compass_v3_z[sampleCount] = compass_v3.z();
+
+		sampleCount++;
+	}
+
+}
+
+void park_rotating(bool inner, bool outer) {
+
+	if (inner || outer) {
+		//stop rotation
+		velocity_control_VelTh(PARK_BACKSPEED, 0);
+		state_parking = PARKPHASE_BACKWARD;
+		park_last_spotted = 1; //if beam is lost, turn reverse first to find it
+		// ROS_INFO("Laser beam found. Switching to PARKPHASE_BACKWARD");
+	}
+
+}
+
+void park_backward(bool inner, bool outer) {
+
+	//adjust speed
+	float parking_speed = PARK_BACKSPEED; //default ful speed
+	if ( ultrasoundBack < 10 ) { // getting as close as 10cm, slow down
+		// ROS_DEBUG("Jsem blizko 20cm. Brzdim na pulku");
+		parking_speed = PARK_BACKSPEED / 2;
+	}
+	if ( ultrasoundBack < 2 ) {  // <2cm stop
+		parking_speed = 0;
+		state_parking = PARKPHASE_PARKED;
+	}
+
+	float dir = 0;  // >0 toci se doleva
+	if (inner && outer)
+		dir = 0;
+	else if (inner == true && outer == false) {
+		dir = +1 * PARK_BACKTURNSPEED_SLOW_RATIO;
+		park_last_spotted = 1;
+	}
+	else if (inner == false && outer == true) {
+		dir = -1 * PARK_BACKTURNSPEED_SLOW_RATIO;
+		park_last_spotted = -1;
+	}
+	else if (inner == false && outer == false && park_last_spotted == 1) {
+		dir = +1 * 1.3 * PARK_BACKTURNSPEED_SLOW_RATIO;
+	}
+	else if (inner == false && outer == false && park_last_spotted == -1) {
+		dir = -1 * 1.3 * PARK_BACKTURNSPEED_SLOW_RATIO;
+	}
+	else if (inner == false && outer == false && park_last_spotted == 0) {
+		dir = 1;
+		parking_speed = 0;
+		state_parking = 0;
+		// ROS_ERROR("Parking laser beam lost. Switching to manual parking.");
+	}
+
+	velocity_control_VelTh(parking_speed, dir * PARK_TURNSPEED);
+	// ROS_INFO("B I:%d O:%d US: %f lst: %d | spd: %f tw %f",	inner, outer, laserscan_msg.ranges[0], park_last_spotted, parking_speed, dir * PARK_TURNSPEED);
+
+}
+
+void park_parked(bool inner, bool outer) {
+	velocity_control_VelTh(0, 0);
+	// ROS_INFO("Parked");
+	state_parking = PARKPHASE_NOPARKING;
+}
+
+void handle_parking() {
+
+	if (state_parking > PARKPHASE_NOPARKING) {
+
+		int ps_inner = analogRead(PIN_PARK_SENS_INNER);
+		int ps_outer = analogRead(PIN_PARK_SENS_OUTER);
+		bool inner = false;
+		bool outer = false;
+		if (ps_inner < 320)
+			inner = true;
+		if (ps_outer < 280)
+			outer = true;
+
+		//ROS_INFO("PS status: { inner: %d, outer: %d }", inner, outer);
+
+		switch (state_parking) {
+			case PARKPHASE_ROTATING:
+				park_rotating(inner, outer);
+				break;
+			case PARKPHASE_BACKWARD:
+				park_backward(inner, outer);
+				break;
+			case PARKPHASE_PARKED:
+				park_parked(inner, outer);
+				break;
+		}
+	}
+
+}
+
+/*------------------------ Listeners -------------------*/
+
+void echoCheck() { // If ping received, set the sensor distance to array.
+
+	 if (sonar.check_timer())
+		 ultrasoundBack = sonar.ping_result / US_ROUNDTRIP_CM;
+}
+
+void genop_head_pose(const robik::GenericControl& msg) {
+
+	//head
+		//int val = map(msg.gen_param2, -1000, 1000, 50, 165);
+		//servoHeadPitch.write(val);
+
+}
+
+void setParkingPhase(const robik::GenericControl& msg) {
+	state_parking = msg.gen_param1;
+	if (msg.gen_param1 == PARKPHASE_ROTATING) {
+		velocity_control_VelTh(0, 1 * PARK_TURNSPEED);
+	}
+}
+
+void setLED(const robik::GenericControl& msg) {
+	digitalWrite(PIN_LED, (msg.gen_param1 == 1) ? HIGH : LOW);
+}
+
+void setDPin(const robik::GenericControl& msg) {
+	digitalWrite(msg.gen_param1, (msg.gen_param2 == 1) ? HIGH : LOW);
+}
+
+bool getArmPower() {
+	return (digitalRead(PIN_RELAY) == HIGH) ? true : false;
+}
+void setArmPower(bool state) {
+	if (state) {
+		if (arm_disabled_time + ARM_TIME_MIN_BREAK < millis()) {
+			digitalWrite(PIN_RELAY, HIGH);
+			arm_enabled_time = millis();
+			arm_disabled_time = 0;
+		}
+	}
+	else {
+		digitalWrite(PIN_RELAY, LOW);
+		arm_enabled_time = 0;
+		arm_disabled_time = millis();
+	}
+}
+
+void genericMessageListener(const robik::GenericControl& msg) {
+
+	if (msg.gen_operation == OPERATION_HEAD_POSE) {
+		genop_head_pose(msg);
+	}
+	if (msg.gen_operation == OPERATION_SET_PARKING_PHASE) {
+		setParkingPhase(msg);
+	}
+	if (msg.gen_operation == OPERATION_SET_LED) {
+		setLED(msg);
+	}
+	if (msg.gen_operation == OPERATION_SET_DPIN) {
+		setDPin(msg);
+	}
+	if (msg.gen_operation == OPERATION_SET_ARMPOWER) {
+		setArmPower((msg.gen_param1 == 1) ? true : false);
+	}
+
+}
+
+void armPreInit() {
+	Serial3.print("#10P1320T500\r\n"); delay(500);
+	Serial3.print("#3P2250T500\r\n"); delay(500);
+	Serial3.print("#4P1740T500\r\n"); delay(500);
+	Serial3.print("#5P1091T500\r\n"); delay(500);
+	Serial3.print("#1P1908T500\r\n"); delay(500);
+	Serial3.print("#10P1280T500\r\n"); delay(500);
+
+	Serial3.print("#11P700T1\r\n");  //set initial speed for shoulder 2
+	shoulder2 = 512; //set initial position for shoulder2
+}
+
+
+void armMessageListener(const robik::ArmControl& msg) {
+
+	armSetJointState(msg.arm_clamp, msg.arm_roll, msg.arm_elbow, msg.arm_shoulder, msg.arm_yaw, msg.time_to_complete);
+
+}
+
+//replace by constrain arduino funtion after logging will no longer be needed
+uint32_t check_limits(uint32_t val, uint32_t min, uint32_t max) {
+
+    if (min > max) {
+	uint32_t t = min;
+	min = max;
+	max = t;
+    }
+
+    if (val < min) {
+	val = min;
+	log_string("ArmSrvoMinX:" + String(min, DEC));  //nevim jestli funguje
+    }
+    if (val > max) {
+	val = max;
+	log_string("ArmSrvoMaxX:" + String(max, DEC));
+    }
+
+    return val;
+}
+/*
+Postup ladeni
+- zapoj potenciometr serva do analogu a zapis min a max hodnotu
+- odladit smer otaceni, pak odstranit 100ms stop  //konfiguruj PWM stejne jako ohm
+- vyzkouset jestli shoulder2 se hybe stejne jako shoulder1
+*/
+
+//TODO pridej parametr effort
+void setMotorJoint(int pin0, int pin1, int pinsense, int target_ohm) {
+
+	int current_ohm = analogRead(pinsense);
+	add_status_code(current_ohm);
+
+	int a0 = LOW;  //stop implicitly
+	int a1 = LOW;
+	if (current_ohm > target_ohm) {
+		a0 = HIGH;
+	}
+	else if (current_ohm < target_ohm) {
+		a1 = HIGH;
+	}
+	/*digitalWrite(pin0, a0);*/
+	/*digitalWrite(pin1, a1);*/
+
+	//delay(100);   //zastav motor pro 100ms dokud neodladis smer
+	/*digitalWrite(pin0, LOW);*/
+	/*digitalWrite(pin1, LOW);*/
+}
+
+void refreshMotorJoints() {
+//TODO rozeber servo a predelej to ne lm298n
+  //setMotorJoint(PIN_MOTOR_SHOULDER_0, PIN_MOTOR_SHOULDER_1, PIN_SERVO_SENSE_SHOULDER2, shoulder2);
+  //add more joints here
+}
+
+
+void armSetJointState(uint32_t clamp, uint32_t roll, uint32_t elbow, uint32_t shoulder, uint32_t yaw, uint32_t time_to_complete) {
+	String arm_clamp = "";
+	String arm_roll = "";
+	String arm_elbow = "";
+	String arm_shoulder = "";
+	String arm_yaw = "";
+
+	//if arm power is off but a move request is received, enable power
+	if (!getArmPower() &&
+		(old_clamp != clamp ||
+		old_roll != roll ||
+		old_elbow != elbow ||
+		old_shoulder != shoulder ||
+		old_yaw != yaw)
+		)
+	{
+		setArmPower(true);
+	}
+
+	String time_to_complete_str = String(time_to_complete, DEC);
+	if (clamp != 0) {
+		arm_clamp = "#5P" + String(check_limits(clamp, ARM_MIN_CLAMP, ARM_MAX_CLAMP), DEC);
+		estimated_clamp_pos.orig_time = nh.now();
+		estimated_clamp_pos.time_to_complete = time_to_complete;
+		estimated_clamp_pos.orig_pos = estimated_clamp_pos.target_pos;
+		estimated_clamp_pos.target_pos = check_limits(clamp, ARM_MIN_CLAMP, ARM_MAX_CLAMP);
+		estimated_clamp_pos.corrected = false;
+	}
+
+	if (roll != 0) {
+		arm_roll = "#4P" + String(check_limits(roll, ARM_MIN_ROLL, ARM_MAX_ROLL), DEC);
+	}
+
+	if (elbow != 0) {
+		arm_elbow = "#3P" + String(check_limits(elbow, ARM_MIN_ELBOW, ARM_MAX_ELBOW), DEC);
+	}
+
+	if (shoulder != 0) {
+		arm_shoulder = "#10P" + String(check_limits(shoulder, ARM_MIN_SHOULDER, ARM_MAX_SHOULDER), DEC);
+		shoulder2 = 512; //TODO map from shoulder
+// otestuje servo   setMotorJoint(PIN_MOTOR_SHOULDER_0, PIN_MOTOR_SHOULDER_1, PIN_SERVO_SENSE_SHOULDER2, constrain(shoulder2, ARM_RES_MIN_SHOULDER2, ARM_RES_MAX_SHOULDER2));
+	}
+
+	if (yaw != 0) {
+		arm_yaw = "#1P" + String(check_limits(yaw, ARM_MIN_YAW, ARM_MAX_YAW), DEC);
+	}
+
+	String cmd = String(arm_clamp + arm_roll + arm_elbow + arm_shoulder + arm_yaw + "T" + time_to_complete_str + "\r\n");
+	log_string(cmd);
+	Serial3.print(cmd);
+
+}
+
+void velocityMessageListener(const geometry_msgs::Twist& msg) {
+	velocity_control_VelTh(msg.linear.x, msg.angular.z);
+}
+
+// vel: linear velocity [m/sec]
+// theta: angular velocity [rad/sec]
+void velocity_control_VelTh(float vel, float th) {
+
+	//limit to standard max values on input
+	vel = constrain(vel, -MAX_VEL, MAX_VEL);
+	th = constrain(th, -MAX_TH, MAX_TH);
+
+	//combine speed and rotation and set as required speed for boot wheels
+	req_motor_left  = vel - ((AXIAL_LENGTH_MM/1000 / 2) * th);
+	req_motor_right = vel + ((AXIAL_LENGTH_MM/1000 / 2) * th);
+
+	//limit combined speed to maximum available
+	double coef = 1;
+	if (abs(req_motor_left) > MAX_VEL)
+		coef = req_motor_left / MAX_VEL;
+	if (abs(req_motor_right) > MAX_VEL)
+		coef = req_motor_right / MAX_VEL;
+
+	req_motor_left = req_motor_left / abs(coef);
+	req_motor_right = req_motor_right / abs(coef);
+
+	velocity_control_LR();
+
+}
+
+
+int motor_vel_to_pwm(double vel) {
+	return vel / MAX_VEL * MOTOR_MAX;
+}
+
+int is_equal_3decplaces(double a, double b) {
+		long long ai = a * 1000;
+		long long bi = b * 1000;
+		return ai == bi;
+}
+
+//input is global variable req_motor_left and req_motor_right, [meter/sec], max speed is normalized
+void velocity_control_LR() {
+
+	//if velocity command has changed
+	if ( (!is_equal_3decplaces(req_motor_left, old_motor_left)) ||
+	     (!is_equal_3decplaces(req_motor_right, old_motor_right))
+	    ||
+	     (req_motor_left == 0 && req_motor_right == 0)
+	) {
+		//remove correction, use only estimated speeds for new velocity command
+		old_motor_left = req_motor_left;
+		old_motor_right = req_motor_right;
+		millis_since_cmd = millis();
+		odom_ticks_left_since_cmd = 0;
+		odom_ticks_right_since_cmd = 0;
+	}
+
+	//number of ticks that the robot is behind. Can be also < 0 which means the robot is ahead of required
+	long millis_now = millis();
+	long correction_motor_left  = long( (double)(millis_now - millis_since_cmd)/1000.0 * req_motor_left  * 1000 / TICK_LENGTH_MM ) - odom_ticks_left_since_cmd;
+	long correction_motor_right = long( (double)(millis_now - millis_since_cmd)/1000.0 * req_motor_right * 1000 / TICK_LENGTH_MM ) - odom_ticks_right_since_cmd;
+
+	//include correction <0 - ow; MOTOR_MAX + ow> where ow is an overflow
+	int corrected_motor_left  = motor_vel_to_pwm(abs(req_motor_left))  + constrain(correction_motor_left  * 5, -MOTOR_MAX/5, MOTOR_MAX/5);
+	int corrected_motor_right = motor_vel_to_pwm(abs(req_motor_right)) + constrain(correction_motor_right * 5, -MOTOR_MAX/5, MOTOR_MAX/5);
+	add_status_code(corrected_motor_left);
+	add_status_code(corrected_motor_right);
+
+	//remap if speed of any wheel overflows 0 or MOTOR_MAX
+	if (corrected_motor_left < MOTOR_MIN)
+		corrected_motor_left = 0;
+	if (corrected_motor_right < MOTOR_MIN)
+		corrected_motor_right = 0;
+
+	int ow_left = 0;
+	int ow_right = 0;
+	int ow = 0;
+	if (corrected_motor_left > MOTOR_MAX)
+		ow_left = corrected_motor_left - MOTOR_MAX;
+	if (corrected_motor_right > MOTOR_MAX)
+		ow_right = corrected_motor_right - MOTOR_MAX;
+
+	//subtract common overflow for both wheels
+	ow = max(ow_left, ow_right);
+	corrected_motor_left -= ow;
+	corrected_motor_right -= ow;
+
+	//derive direction from original speed
+	//left
+	int a0 = LOW;  //stop implicitly
+	int a1 = LOW;
+	if (req_motor_left < 0) {
+		a0 = HIGH;
+		motor_left_dir = -1;
+	}
+	if (req_motor_left > 0) {
+		a1 = HIGH;
+		motor_left_dir = 1;
+	}
+	digitalWrite(PIN_MOTOR_LEFT_0, a0);
+	digitalWrite(PIN_MOTOR_LEFT_1, a1);
+	analogWrite(PIN_MOTOR_LEFT_ENA, constrain(corrected_motor_left, 0, MOTOR_MAX));
+	add_status_code(correction_motor_left);
+	add_status_code(corrected_motor_left);
+
+	//right
+	a0 = LOW;
+	a1 = LOW;
+	if (req_motor_right < 0) {
+		a0 = HIGH;
+		motor_right_dir = -1;
+	}
+	if (req_motor_right > 0) {
+		a1 = HIGH;
+		motor_right_dir = 1;
+	}
+	digitalWrite(PIN_MOTOR_RIGHT_0, a0);
+	digitalWrite(PIN_MOTOR_RIGHT_1, a1);
+	analogWrite(PIN_MOTOR_RIGHT_ENA, constrain(corrected_motor_right, 0, MOTOR_MAX));
+	add_status_code(correction_motor_right);
+	add_status_code(corrected_motor_right);
+}
+
+//odometry encoders
+void intr_left_encoder() {
+
+	odom_ticks_left++;
+	odom_ticks_left_since_cmd++;
+}
+
+void intr_right_encoder() {
+
+	odom_ticks_right++;
+	odom_ticks_right_since_cmd++;
+}


Change to serial read in loop instead of read line command

error: pathspec 'Muscle/Arduino' did not match any file(s) known to git
error: pathspec 'Code/MuscleLeonardo/MuscleLeonardo.ino' did not match any file(s) known to git


uploading RFID example code

uploading RFID example code

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/nicksutera/railroad.git/'


Add 8x8 bicolor example

Add 8x8 bicolor example

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

--- firmware/examples/8x8-bicolor.ino
+++ firmware/examples/8x8-bicolor.ino
@@ -0,0 +1,122 @@
+
+/***************************************************
+  This is a library for our I2C LED Backpacks
+
+  Designed specifically to work with the Adafruit LED Matrix backpacks
+  ----> http://www.adafruit.com/products/872
+  ----> http://www.adafruit.com/products/871
+  ----> http://www.adafruit.com/products/870
+
+  These displays use I2C to communicate, 2 pins are required to
+  interface. There are multiple selectable I2C addresses. For backpacks
+  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
+  with 3 Address Select pins: 0x70 thru 0x77
+
+  Adafruit invests time and resources providing this open source code,
+  please support Adafruit and open-source hardware by purchasing
+  products from Adafruit!
+
+  Written by Limor Fried/Ladyada for Adafruit Industries.
+  BSD license, all text above must be included in any redistribution
+ ****************************************************/
+
+// This #include statement was automatically added by the Spark IDE.
+#include "adafruit-led-backpack/adafruit-led-backpack.h"
+
+Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
+
+void setup() {
+  Serial.begin(9600);
+  Serial.println("8x8 LED Matrix Test");
+
+  matrix.begin(0x70);  // pass in the address
+}
+
+static const uint8_t
+  smile_bmp[] =
+  { B00111100,
+    B01000010,
+    B10100101,
+    B10000001,
+    B10100101,
+    B10011001,
+    B01000010,
+    B00111100 },
+  neutral_bmp[] =
+  { B00111100,
+    B01000010,
+    B10100101,
+    B10000001,
+    B10111101,
+    B10000001,
+    B01000010,
+    B00111100 },
+  frown_bmp[] =
+  { B00111100,
+    B01000010,
+    B10100101,
+    B10000001,
+    B10011001,
+    B10100101,
+    B01000010,
+    B00111100 };
+
+void loop() {
+
+  matrix.clear();
+  matrix.drawBitmap(0, 0, smile_bmp, 8, 8, LED_GREEN);
+  matrix.writeDisplay();
+  delay(500);
+
+  matrix.clear();
+  matrix.drawBitmap(0, 0, neutral_bmp, 8, 8, LED_YELLOW);
+  matrix.writeDisplay();
+  delay(500);
+
+  matrix.clear();
+  matrix.drawBitmap(0, 0, frown_bmp, 8, 8, LED_RED);
+  matrix.writeDisplay();
+  delay(500);
+
+  matrix.clear();      // clear display
+  matrix.drawPixel(0, 0, LED_GREEN);
+  matrix.writeDisplay();  // write the changes we just made to the display
+  delay(500);
+
+  matrix.clear();
+  matrix.drawLine(0,0, 7,7, LED_YELLOW);
+  matrix.writeDisplay();  // write the changes we just made to the display
+  delay(500);
+
+  matrix.clear();
+  matrix.drawRect(0,0, 8,8, LED_RED);
+  matrix.fillRect(2,2, 4,4, LED_GREEN);
+  matrix.writeDisplay();  // write the changes we just made to the display
+  delay(500);
+
+  matrix.clear();
+  matrix.drawCircle(3,3, 3, LED_YELLOW);
+  matrix.writeDisplay();  // write the changes we just made to the display
+  delay(500);
+
+  matrix.setTextWrap(false);  // we dont want text to wrap so it scrolls nicely
+  matrix.setTextSize(1);
+  matrix.setTextColor(LED_GREEN);
+  for (int8_t x=7; x>=-36; x--) {
+    matrix.clear();
+    matrix.setCursor(x,0);
+    matrix.print("Hello");
+    matrix.writeDisplay();
+    delay(100);
+  }
+  matrix.setRotation(3);
+  matrix.setTextColor(LED_RED);
+  for (int8_t x=7; x>=-36; x--) {
+    matrix.clear();
+    matrix.setCursor(x,0);
+    matrix.print("World");
+    matrix.writeDisplay();
+    delay(100);
+  }
+  matrix.setRotation(0);
+}


code for gyro added

code for gyro added

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

--- Arduino/gyro/gyro.ino
+++ Arduino/gyro/gyro.ino
@@ -0,0 +1,45 @@
+#include "Wire.h"
+#include "I2Cdev.h"
+#include "MPU6050.h"
+
+// class default I2C address is 0x68
+// specific I2C addresses may be passed as a parameter here
+// AD0 low = 0x68 (default for InvenSense evaluation board)
+// AD0 high = 0x69
+MPU6050 accelgyro;
+
+int16_t ax, ay, az, gx, gy, gz;
+
+void setup() {
+    Wire.begin();
+
+    // initialize serial communication
+    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
+    // it's really up to you depending on your project)
+    Serial.begin(38400);
+
+    accelgyro.initialize();
+
+    // verify connection
+    Serial.println("Testing device connections...");
+    Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
+}
+
+void printNumber(int16_t number) {
+    char tmp[5];
+    sprintf(tmp, "%6d", number);
+    //sprintf(tmp, "%0.4X", number);
+    Serial.print(tmp); Serial.print(" ");
+}
+
+void loop() {
+    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
+    printNumber(ax);
+    printNumber(ay);
+    printNumber(az);
+    printNumber(gx);
+    printNumber(gy);
+    printNumber(gz);
+    Serial.println();
+    delay(100);
+}


Arduino code for evaluating stepper drivers, initial commit

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

--- Arduino/Stepper_eval/Stepper_eval.ino
+++ Arduino/Stepper_eval/Stepper_eval.ino
@@ -0,0 +1,25 @@
+unsigned long tic;
+unsigned long toc;
+
+void setup() {
+  Serial.begin(9600);
+  // initialize digital pin 13 as an output.
+  pinMode(13, OUTPUT);
+
+  tic = millis();
+  toc = millis();
+}
+
+void loop() {
+  toc = millis();
+
+  if(Serial.available()) {
+    Serial.write(Serial.read());
+  }
+
+
+  if (toc - tic > 1000) {
+    digitalWrite(13, !digitalRead(13));
+    tic = toc;
+  }
+}


upload test sketch for users to try basic functionality

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

--- DIYino_Testsketch.ino
+++ DIYino_Testsketch.ino
@@ -0,0 +1,345 @@
+
+
+#include <Arduino.h>
+#include <DFPlayer.h>
+#include <I2Cdev.h>
+#include <MPU6050_6Axis_MotionApps20.h>
+#include <EEPROMex.h>
+#include <OneButton.h>
+
+#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
+#include <Wire.h>
+#endif
+
+#define XYZ
+
+#define MPUCALIBEEPROM
+#ifdef MPUCALIBEEPROM
+#define MEMORYBASEMPUCALIBOFFSET 96 // start storing the calibration values starting at this address
+#endif
+#ifndef MPUCALIBEEPROM
+#define MPUCALIBMANUAL
+#endif
+#define DEBUGVERBOSE
+
+#define DFPLAYER_RX			8
+#define DFPLAYER_TX			7
+#define SPK1				20 //A6
+#define SPK2				21 //A7
+
+
+#define MAIN_BUTTON			13
+#define LOCKUP_BUTTON		4
+/***************************************************************************************************
+ * Motion detection Variables
+ */
+MPU6050 mpu;
+// MPU control/status vars
+volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
+bool dmpReady = false;  // set true if DMP init was successful
+uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
+uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
+uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
+uint8_t fifoBuffer[64]; // FIFO storage buffer
+uint16_t mpuFifoCount;     // count of all bytes currently in FIFO
+// calibrated acc/gyro values
+int16_t ax_zero, ay_zero, az_zero;
+int16_t gx_zero, gy_zero, gz_zero;
+// orientation/motion vars
+Quaternion quaternion;           // [w, x, y, z]         quaternion container
+VectorInt16 aaWorld; // [x, y, z]            world-frame accel sensor measurements
+static Quaternion quaternion_last;  // [w, x, y, z]         quaternion container
+static Quaternion quaternion_reading; // [w, x, y, z]         quaternion container
+static VectorInt16 aaWorld_last; // [x, y, z]            world-frame accel sensor measurements
+static VectorInt16 aaWorld_reading; // [x, y, z]            world-frame accel sensor measurements
+
+/***************************************************************************************************
+ * LED String variables
+ */
+#define LEDSTRING1 			3
+#define LEDSTRING2 			5
+#define LEDSTRING3 			6
+#define LEDSTRING4 			9
+#define LEDSTRING5 			10
+#define LEDSTRING6 			11
+uint8_t ledPins[] = { LEDSTRING1, LEDSTRING2, LEDSTRING3, LEDSTRING4,
+LEDSTRING5, LEDSTRING6 };
+uint8_t LEDbrightness;
+int8_t signSoundFile, signVolume, signBrightness;
+
+/***************************************************************************************************
+ * DFPLAYER variables
+ */
+DFPlayer dfplayer;
+uint8_t dfplayer_volume;
+uint8_t SoundFile;
+
+void setup() {
+
+// variable declaration
+int16_t mpu_caliboffset_AccX, mpu_caliboffset_AccY, mpu_caliboffset_AccZ, mpu_caliboffset_GyroX, mpu_caliboffset_GyroY, mpu_caliboffset_GyroZ;
+
+
+
+	// join I2C bus (I2Cdev library doesn't do this automatically)
+#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
+	Wire.begin();
+	TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz). Comment this line if having compilation difficulties with TWBR.
+#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
+			Fastwire::setup(400, true);
+#endif
+
+// Serial line for debug
+Serial.begin(115200);
+
+
+	/***** DF PLAYER INITIALISATION  *****/
+	dfplayer.setSerial(DFPLAYER_TX, DFPLAYER_RX);
+        dfplayer_volume=25;
+	dfplayer.setVolume(dfplayer_volume);
+	delay(200);
+	pinMode(SPK1, INPUT);
+	pinMode(SPK2, INPUT);
+
+	//setup finished. Boot ready. We notify !
+	dfplayer.playPhysicalTrack(18);
+	delay(20);
+
+
+               // dump config values stored in EEPROM
+                //saveConfig();
+                Serial.println("EEPROM Dump (first 256 bytes): ");
+                for (uint8_t i = 0; i < 255; i++) {
+                  Serial.println(EEPROM.readByte(i));
+                }
+
+
+
+
+	/***** MP6050 MOTION DETECTOR INITIALISATION  *****/
+
+	// initialize device
+	Serial.println(F("Initializing I2C devices..."));
+	mpu.initialize();
+
+	// verify connection
+	Serial.println(F("Testing device connections..."));
+	Serial.println(
+			mpu.testConnection() ?
+					F("MPU6050 connection successful") :
+					F("MPU6050 connection failed"));
+
+	// load and configure the DMP
+	Serial.println(F("Initializing DMP..."));
+	devStatus = mpu.dmpInitialize();
+
+#ifdef MPUCALIBEEPROM
+  //mpu.setXAccelOffset(0);
+  //mpu.setYAccelOffset(0);
+  //mpu.setZAccelOffset(20000);
+  //mpu.setXGyroOffset(0);
+  //mpu.setYGyroOffset(0);
+  //mpu.setZGyroOffset(20000);
+	/*
+	 * Those offsets are specific to each MPU6050 device.
+	 * they are found via calibration process.
+	 * See this script http://www.i2cdevlib.com/forums/index.php?app=core&module=attach&section=attach&attach_id=27
+	 */
+          // retreive MPU6050 calibrated offset values from EEPROM
+         EEPROM.setMemPool(MEMORYBASEMPUCALIBOFFSET, EEPROMSizeATmega328);
+         int addressInt=MEMORYBASEMPUCALIBOFFSET;
+         mpu_caliboffset_AccX=EEPROM.readInt(addressInt);
+         mpu.setXAccelOffset(mpu_caliboffset_AccX);
+         Serial.print("EEPROM address: ");Serial.println(addressInt);Serial.print("Calibrated AcceleroX Offset: ");Serial.println(mpu_caliboffset_AccX);Serial.println("");
+
+         addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
+         mpu_caliboffset_AccY=EEPROM.readInt(addressInt);
+         mpu.setYAccelOffset(mpu_caliboffset_AccY);
+         Serial.print("EEPROM address: ");Serial.println(addressInt);Serial.print("Calibrated AcceleroY Offset: ");Serial.println(mpu_caliboffset_AccY);Serial.println("");
+
+         addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
+         mpu_caliboffset_AccZ=EEPROM.readInt(addressInt);
+         mpu.setZAccelOffset(mpu_caliboffset_AccZ);
+         Serial.print("EEPROM address: ");Serial.println(addressInt);Serial.print("Calibrated AcceleroZ Offset: ");Serial.println(mpu_caliboffset_AccZ);Serial.println("");
+
+         addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
+         mpu_caliboffset_GyroX=EEPROM.readInt(addressInt);
+         mpu.setXGyroOffset(mpu_caliboffset_GyroX);
+         Serial.print("EEPROM address: ");Serial.println(addressInt);Serial.print("Calibrated GyroX Offset: ");Serial.println(mpu_caliboffset_GyroX);Serial.println("");
+
+         addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
+         mpu_caliboffset_GyroY=EEPROM.readInt(addressInt);
+         mpu.setYGyroOffset(mpu_caliboffset_GyroY);
+         Serial.print("EEPROM address: ");Serial.println(addressInt);Serial.print("Calibrated GyroY Offset: ");Serial.println(mpu_caliboffset_GyroY);Serial.println("");
+
+         addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
+         mpu_caliboffset_GyroZ=EEPROM.readInt(addressInt);
+         mpu.setZGyroOffset(mpu_caliboffset_GyroZ);
+         Serial.print("EEPROM address: ");Serial.println(addressInt);Serial.print("Calibrated GyroZ Offset: ");Serial.println(mpu_caliboffset_GyroZ);Serial.println("");
+
+#endif
+#ifdef XYZ
+	if (devStatus == 0) {
+		// turn on the DMP, now that it's ready
+		Serial.println(F("Enabling DMP..."));
+		mpu.setDMPEnabled(true);
+
+		// enable Arduino interrupt detection
+		Serial.println(
+				F(
+						"Enabling interrupt detection (Arduino external interrupt 0)..."));
+//		attachInterrupt(0, dmpDataReady, RISING);
+		mpuIntStatus = mpu.getIntStatus();
+
+		// set our DMP Ready flag so the main loop() function knows it's okay to use it
+		Serial.println(F("DMP ready! Waiting for first interrupt..."));
+		dmpReady = true;
+
+		// get expected DMP packet size for later comparison
+		packetSize = mpu.dmpGetFIFOPacketSize();
+	} else {
+		// ERROR!
+		// 1 = initial memory load failed
+		// 2 = DMP configuration updates failed
+		// (if it's going to break, usually the code will be 1)
+		Serial.print(F("DMP Initialization failed (code "));
+		Serial.print(devStatus);
+		Serial.println(F(")"));
+	}
+
+
+        // set the fll scale range of the gyro- and accelerometer respectively
+        mpu.setFullScaleGyroRange(0); //0: 250deg/s | 1: 500deg/s | 2: 1000deg/s | 3: 2000deg/s
+        mpu.setFullScaleAccelRange(0); //0: 2g | 1: 4g | 2: 8g | 3: 16g
+
+	// configure the motion interrupt for clash recognition
+	// INT_PIN_CFG register
+	// in the working code of MPU6050_DMP all bits of the INT_PIN_CFG are false (0)
+
+	mpu.setInterruptMode(false); // INT_PIN_CFG register INT_LEVEL (0-active high, 1-active low)
+	mpu.setInterruptDrive(false); // INT_PIN_CFG register INT_OPEN (0-push/pull, 1-open drain)
+	mpu.setInterruptLatch(false); // INT_PIN_CFG register LATCH_INT_EN (0 - emits 50us pulse upon trigger, 1-pin is held until int is cleared)
+	mpu.setInterruptLatchClear(false); // INT_PIN_CFG register INT_RD_CLEAR (0-clear int only on reading int status reg, 1-any read clears int)
+	mpu.setFSyncInterruptLevel(false);
+	mpu.setFSyncInterruptEnabled(false);
+	mpu.setI2CBypassEnabled(false);
+	// Enable/disable interrupt sources - enable only motion interrupt
+	mpu.setIntFreefallEnabled(false);
+	mpu.setIntMotionEnabled(true);
+	mpu.setIntZeroMotionEnabled(false);
+	mpu.setIntFIFOBufferOverflowEnabled(false);
+	mpu.setIntI2CMasterEnabled(false);
+	mpu.setIntDataReadyEnabled(false);
+	mpu.setIntMotionEnabled(true); // INT_ENABLE register enable interrupt source  motion detection
+	mpu.setMotionDetectionThreshold(10); // 1mg/LSB
+	mpu.setMotionDetectionDuration(2); // number of consecutive samples above threshold to trigger int
+	mpuIntStatus = mpu.getIntStatus();
+	Serial.println("MPU6050 register setup:");
+	Serial.print("INT_PIN_CFG\t");
+	Serial.print(mpu.getInterruptMode());
+	Serial.print("\t");
+	Serial.print(mpu.getInterruptDrive());
+	Serial.print("\t");
+	Serial.print(mpu.getInterruptLatch());
+	Serial.print("\t");
+	Serial.print(mpu.getInterruptLatchClear());
+	Serial.print("\t");
+	Serial.print(mpu.getFSyncInterruptLevel());
+	Serial.print("\t");
+	Serial.print(mpu.getFSyncInterruptEnabled());
+	Serial.print("\t");
+	Serial.println(mpu.getI2CBypassEnabled());
+	// list INT_ENABLE register contents
+	Serial.print("INT_ENABLE\t");
+	Serial.print(mpu.getIntFreefallEnabled());
+	Serial.print("\t");
+	Serial.print(mpu.getIntMotionEnabled());
+	Serial.print("\t");
+	Serial.print(mpu.getIntZeroMotionEnabled());
+	Serial.print("\t");
+	Serial.print(mpu.getIntFIFOBufferOverflowEnabled());
+	Serial.print("\t");
+	Serial.print(mpu.getIntI2CMasterEnabled());
+	Serial.print("\t");
+	Serial.println(mpu.getIntDataReadyEnabled());
+	/***** MP6050 MOTION DETECTOR INITIALISATION  *****/
+
+	/***** LED SEGMENT INITIALISATION  *****/
+	// initialize ledstrings segments
+	DDRD |= B01101000;
+	DDRB |= B00001110;
+
+	//We shut off all pins that could wearing leds,just to be sure
+	PORTD &= B10010111;
+	PORTB &= B11110001;
+#endif
+
+  //mpu.setXAccelOffset(0);
+  //mpu.setYAccelOffset(0);
+  //mpu.setZAccelOffset(32767);
+  //mpu.setXGyroOffset(0);
+  //mpu.setYGyroOffset(0);
+  //mpu.setZGyroOffset(20000);
+
+        // initialise global loop variables
+        LEDbrightness=0;
+        SoundFile=1;
+        signBrightness=1;
+        signSoundFile=1;
+        signVolume=1;
+
+        dfplayer.setVolume(dfplayer_volume);
+	delay(200);
+	dfplayer.playPhysicalTrack(20);
+}
+
+void loop() {
+
+  uint8_t i;
+  int16_t ax, ay, az;
+  int16_t gx, gy, gz;
+
+  if (LEDbrightness==50) {signBrightness=-1;}
+  if (LEDbrightness==0) {signBrightness=1;}
+  if (dfplayer_volume==31) {signVolume=-1;}
+  if (dfplayer_volume==0) {signVolume=1;}
+  if (SoundFile==30) {signSoundFile=-1;}
+  if (SoundFile==0) {signSoundFile=1;}
+
+  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
+             // display tab-separated accel/gyro x/y/z values
+            Serial.print("Acceleration- and Gyro values:\t");
+            Serial.print(ax); Serial.print("\t");
+            Serial.print(ay); Serial.print("\t");
+            Serial.print(az); Serial.print("\t");
+            Serial.print(gx); Serial.print("\t");
+            Serial.print(gy); Serial.print("\t");
+            Serial.println(gz);
+
+  for (int i = 0; i < sizeof(ledPins); i++) {
+    analogWrite(ledPins[i], constrain(LEDbrightness,0,50));
+  }
+ if (LEDbrightness==50) {
+
+	//delay(20);
+ }
+
+  LEDbrightness=LEDbrightness+signBrightness;
+  dfplayer_volume=dfplayer_volume+signVolume;
+  SoundFile=SoundFile+signSoundFile;
+
+  mpuIntStatus = mpu.getIntStatus();
+		if (mpuIntStatus > 60 and mpuIntStatus < 70) {
+			/*
+			 * THIS IS A CLASH  !
+			 */
+                  Serial.println("*");Serial.println("*");Serial.println("*");Serial.println("*");Serial.println("*");
+                  Serial.println("*");Serial.println("*");Serial.println("*");Serial.println("*");Serial.println("*");
+                  Serial.println("                       CLASH!                                    ");
+                  Serial.println("*");Serial.println("*");Serial.println("*");Serial.println("*");Serial.println("*");
+                  Serial.println("*");Serial.println("*");Serial.println("*");Serial.println("*");Serial.println("*");
+
+
+
+                }
+}


Grabber code added

Grabber code added

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/auvnitrkl/tiburon-3.0.git/'


dimmer LEDs

dimmer LEDs

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

--- ardesp/neopixel/strandtest2/strandtest2.ino
+++ ardesp/neopixel/strandtest2/strandtest2.ino
@@ -0,0 +1,140 @@
+#include <Adafruit_NeoPixel.h>
+#ifdef __AVR__
+  #include <avr/power.h>
+#endif
+
+#define PIN 6
+
+// Parameter 1 = number of pixels in strip
+// Parameter 2 = Arduino pin number (most are valid)
+// Parameter 3 = pixel type flags, add together as needed:
+//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
+//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
+//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
+//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
+//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
+Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
+
+// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
+// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
+// and minimize distance between Arduino and first pixel.  Avoid connecting
+// on a live circuit...if you must, connect GND first.
+
+void setup() {
+  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
+  #if defined (__AVR_ATtiny85__)
+    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
+  #endif
+  // End of trinket special code
+
+
+  strip.begin();
+  strip.setBrightness(10);
+  strip.show(); // Initialize all pixels to 'off'
+}
+
+void loop() {
+  // Some example procedures showing how to display to the pixels:
+  colorWipe(strip.Color(255, 0, 0), 50); // Red
+  colorWipe(strip.Color(0, 255, 0), 50); // Green
+  colorWipe(strip.Color(0, 0, 255), 50); // Blue
+//colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
+  // Send a theater pixel chase in...
+  theaterChase(strip.Color(127, 127, 127), 50); // White
+  theaterChase(strip.Color(127, 0, 0), 50); // Red
+  theaterChase(strip.Color(0, 0, 127), 50); // Blue
+
+  rainbow(20);
+  rainbowCycle(20);
+  theaterChaseRainbow(50);
+}
+
+// Fill the dots one after the other with a color
+void colorWipe(uint32_t c, uint8_t wait) {
+  for(uint16_t i=0; i<strip.numPixels(); i++) {
+    strip.setPixelColor(i, c);
+    strip.setBrightness(10);
+    strip.show();
+    delay(wait);
+  }
+}
+
+void rainbow(uint8_t wait) {
+  uint16_t i, j;
+
+  for(j=0; j<256; j++) {
+    for(i=0; i<strip.numPixels(); i++) {
+      strip.setPixelColor(i, Wheel((i+j) & 255));
+    }
+    strip.setBrightness(10);
+    strip.show();
+    delay(wait);
+  }
+}
+
+// Slightly different, this makes the rainbow equally distributed throughout
+void rainbowCycle(uint8_t wait) {
+  uint16_t i, j;
+
+  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
+    for(i=0; i< strip.numPixels(); i++) {
+      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
+    }
+    strip.setBrightness(10);
+    strip.show();
+    delay(wait);
+  }
+}
+
+//Theatre-style crawling lights.
+void theaterChase(uint32_t c, uint8_t wait) {
+  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
+    for (int q=0; q < 3; q++) {
+      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
+        strip.setPixelColor(i+q, c);    //turn every third pixel on
+      }
+      strip.setBrightness(10);
+      strip.show();
+
+      delay(wait);
+
+      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
+        strip.setPixelColor(i+q, 0);        //turn every third pixel off
+      }
+    }
+  }
+}
+
+//Theatre-style crawling lights with rainbow effect
+void theaterChaseRainbow(uint8_t wait) {
+  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
+    for (int q=0; q < 3; q++) {
+      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
+        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
+      }
+      strip.setBrightness(10);
+      strip.show();
+
+      delay(wait);
+
+      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
+        strip.setPixelColor(i+q, 0);        //turn every third pixel off
+      }
+    }
+  }
+}
+
+// Input a value 0 to 255 to get a color value.
+// The colours are a transition r - g - b - back to r.
+uint32_t Wheel(byte WheelPos) {
+  WheelPos = 255 - WheelPos;
+  if(WheelPos < 85) {
+    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
+  }
+  if(WheelPos < 170) {
+    WheelPos -= 85;
+    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
+  }
+  WheelPos -= 170;
+  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
+}


added program for waspmote

added program for waspmote

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

--- src/main/c/ard.ino
+++ src/main/c/ard.ino
@@ -0,0 +1,29 @@
+char aux[200];
+packetXBee* paq_sent;
+uint8_t direction[8]={0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF};
+
+void setup()
+{
+  ACC.ON();
+  xbee802.init(XBEE_802_15_4,FREQ2_4G,NORMAL);
+  xbee802.ON();
+}
+
+void loop()
+{
+  paq_sent=(packetXBee*) calloc(1,sizeof(packetXBee));
+  paq_sent->mode=BROADCAST;
+  paq_sent->MY_known=0;
+  paq_sent->packetID=0x52;
+  paq_sent->opt=0;
+  xbee802.hops=0;
+  xbee802.setOriginParams(paq_sent,MAC_TYPE);
+
+  sprintf(aux,"|%d|%d|%d|%c",ACC.getX(),ACC.getY(),ACC.getZ(),'\n');
+
+  xbee802.setDestinationParams(paq_sent, direction, aux, MAC_TYPE, DATA_ABSOLUTE);
+  xbee802.sendXBee(paq_sent);
+  free(paq_sent);
+  paq_sent = NULL;
+
+}


5th firmware added with magnetometer as step counter

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

--- Stepper/watch6/watch6.ino
+++ Stepper/watch6/watch6.ino
@@ -0,0 +1,720 @@
+#include <MsTimer2.h>
+
+#include <Wire.h> //I2C Arduino Library
+#include <Adafruit_Sensor.h>
+#include <Adafruit_HMC5883_U.h>
+Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
+
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
+
+// CONFIG -------------------------------------------
+
+// --------- HARDWARE I2C HMC5883: A4 -> SDA, A5 -> SCL
+#define HMC_DRDY   A1 //unused
+
+// --------- HARDWARE SPI OLED: 11 -> MOSI/DIN, 13 -> SCK
+#define OLED_CS    4
+#define PIN_RESET  6
+#define PIN_DC     8
+
+#define BUTTON1    3
+#define BUTTON2    2
+
+#define LED_BLUE   10
+#define LED_GREEN  9
+#define LED_RED    5
+#define LED_OFF    LOW
+#define LED_ON     HIGH
+
+#define SERIAL_SPEED   9600
+#define DISPLAYSEC     10
+
+#define SYS_SWITCH A7
+#define MAS_SWITCH A0
+#define BLE_LED    7  //unused
+
+#define WARN_POWER 3270.0   // or try 3200, 3500, 3600
+
+// --------------------------------------------------
+
+#define CHAR_TIME_REQUEST     '~'
+#define CHAR_TIME_RESPONSE    '#' //#HH:mm:ss
+#define CHAR_NOTIFY_HINT      '%' //%[byte]
+
+#define MEMOSTR_LIMIT   115
+#define STEP_TRESHOLD   0.125
+
+#define MOVIE_X  7
+#define MOVIE_Y  52
+
+int  vcc;
+bool powerlow = false;
+
+#define MINDIF  10
+
+int xx,yy,zz;
+int minx=400, maxx=0;
+int miny=400, maxy=0;
+int minz=400, maxz=0;
+float changes      = 0.0;
+float changes_old  = 0.0;
+float delta        = 0.0;
+unsigned int steps = 0;
+
+char memoStr[MEMOSTR_LIMIT] = {'\0'};
+int  memoStrPos = 0;
+char buffMem;
+int  cEnd  = 0;
+int  cStart= 0;
+byte COUNT = 0;
+
+byte hours   = 0;
+byte minutes = 0;
+byte seconds = 0;
+byte tick    = 0;
+int  dsec    = DISPLAYSEC;
+
+class OledWrapper : public Adafruit_SSD1306 {
+  public:
+
+    OledWrapper(const int & dc, const int & res, const int & cs) : Adafruit_SSD1306(dc,res,cs) {}
+
+    void begin() {
+      Adafruit_SSD1306::begin(SSD1306_SWITCHCAPVCC);
+      clearDisplay();
+      setTextSize(1); // 8 line with 21 chars
+      setTextColor(WHITE);
+      setCursor(0,0);
+    }
+
+    void black(const int & num) {
+      setTextColor(BLACK);
+      print(num);
+      setTextColor(WHITE);
+    }
+    void black(const int & x, const int & y, const int & w, const int & h) {
+      fillRect(x,y,w,h, BLACK);
+    }
+    void line(const int & x, const int & y, const int & xx, const int & yy) {
+      drawLine(x,y,xx,yy, WHITE);
+    }
+    void pixel(const int & x, const int & y) {
+      drawPixel(x,y, WHITE);
+    }
+    void rect(const int & x, const int & y, const int & w, const int & h) {
+      drawRect(x,y,w,h, WHITE);
+    }
+    void rectFill(const int & x, const int & y, const int & w, const int & h) {
+      fillRect(x,y,w,h, WHITE);
+    }
+    void circle(const int & x, const int & y, const int & radius) {
+      drawCircle(x,y,radius, WHITE);
+    }
+    void setFontType(const int & t) {
+      setTextSize(t);
+    }
+    void on() {
+      ssd1306_command(SSD1306_DISPLAYON);
+    }
+    void off() {
+      ssd1306_command(SSD1306_DISPLAYOFF);
+    }
+    void clear() {
+      clearDisplay();
+    }
+    void command(uint8_t cmd) {
+      ssd1306_command(cmd);
+    }
+    char umlReplace(char inChar) {
+      if (inChar == -97) {
+        inChar = 224; // ß
+      } else if (inChar == -80) {
+        inChar = 248; // °
+      } else if (inChar == -67) {
+        inChar = 171; // 1/2
+      } else if (inChar == -78) {
+        inChar = 253; // ²
+      } else if (inChar == -92) {
+        inChar = 132; // ä
+      } else if (inChar == -74) {
+        inChar = 148; // ö
+      } else if (inChar == -68) {
+        inChar = 129; // ü
+      } else if (inChar == -124) {
+        inChar = 142; // Ä
+      } else if (inChar == -106) {
+        inChar = 153; // Ö
+      } else if (inChar == -100) {
+        inChar = 154; // Ü
+      } else if (inChar == -85) {
+        inChar = 0xAE; // <<
+      } else if (inChar == -69) {
+        inChar = 0xAF; // >>
+      }
+      return inChar;
+    }
+};
+
+OledWrapper * oled = new OledWrapper(PIN_DC, PIN_RESET, OLED_CS);
+
+enum {MSG_NO, MSG_CAL, MSG_MAIL, MSG_SMS, MSG_OTHER};
+int iconType = MSG_NO;
+
+static const uint8_t PROGMEM move0[] = {
+B00010000,
+B00101000,
+B11000111,
+B01000010,
+B01000100,
+B10010010,
+B11101110,
+B00000000,
+};
+
+static const uint8_t PROGMEM move1[] = {
+B00100100,
+B00111100,
+B01011010,
+B01011010,
+B00111100,
+B00011000,
+B00111100,
+B01011010,
+B00011000,
+B00100100,
+B00100100,
+B01100110
+};
+
+static const uint8_t PROGMEM move2[] = {
+B00111000,
+B01111100,
+B01111010,
+B01111010,
+B00111100,
+B00111000,
+B00111110,
+B00111000,
+B00011000,
+B01111100,
+B10000010,
+B00000011
+};
+
+
+static const uint8_t PROGMEM icon_calendar[] = {
+B11111111,
+B11111111,
+B10000001,
+B10000001,
+B10000101,
+B10000001,
+B11111111,
+B00000000
+};
+static const uint8_t PROGMEM icon_mail[] = {
+B11111111,
+B10000001,
+B11000011,
+B10100101,
+B10011001,
+B10000001,
+B11111111,
+B00000000
+};
+static const uint8_t PROGMEM icon_messaging[] = {
+B00111110,
+B01000001,
+B01000001,
+B01000001,
+B01000001,
+B01011110,
+B01100000,
+B01000000
+};
+static const uint8_t PROGMEM icon_other[] = {
+B00000111,
+B00011011,
+B01100101,
+B10001001,
+B01010001,
+B00110001,
+B00101101,
+B00110011
+};
+
+
+void mesure() {
+  static sensors_event_t event;
+  mag.getEvent(&event);
+
+  // get new
+  xx = event.magnetic.x + 184;
+  yy = event.magnetic.y + 184;
+  zz = event.magnetic.z + 184;
+  if (xx == -188) xx=500;
+  if (yy == -188) yy=500;
+  if (zz == -188) zz=500;
+  if (xx < minx) minx=xx;
+  if (yy < miny) miny=yy;
+  if (zz < minz) minz=zz;
+  if (xx<500 && xx > maxx) maxx=xx;
+  if (yy<500 && yy > maxy) maxy=yy;
+  if (zz<500 && zz > maxz) maxz=zz;
+
+  changes = ( (float) xx / (float)(maxx-minx) ) + ( (float) yy / (float)(maxy-miny) ) + ( (float) zz / (float)(maxz-minz) );
+  delta =  ab(changes_old - changes);
+  changes_old = changes;
+
+  if (delta > STEP_TRESHOLD) {
+    steps++;
+    if (steps%20 == 0) {
+      //analogWrite(LED_RED,   250);
+      analogWrite(LED_GREEN, 130);
+      //analogWrite(LED_BLUE,  130);
+      delay(50);
+      digitalWrite(LED_RED,   LED_OFF);
+      digitalWrite(LED_GREEN, LED_OFF);
+      digitalWrite(LED_BLUE,  LED_OFF);
+    }
+    if (steps%500 == 0) Serial.println(steps);
+  }
+}
+
+void readVcc() {
+  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
+  delay(10); // Wait for Vref to settle
+  ADCSRA |= _BV(ADSC); // Start conversion
+  while (bit_is_set(ADCSRA,ADSC)); // measuring
+  vcc = ADCL;
+  vcc |= ADCH<<8;
+  vcc = 1126400L / vcc;
+}
+
+void serialEvent() {
+  while (Serial.available()) {
+    if (memoStrPos >= MEMOSTR_LIMIT) memoStrPos = MEMOSTR_LIMIT;
+    char inChar = (char)Serial.read();
+    if (inChar == -61) continue; // symbol before utf-8
+    if (inChar == -62) continue; // other symbol before utf-8
+    if (inChar == '\n') {
+      memoStr[memoStrPos] = '\0';
+      dsec = 0;
+      cEnd = 0;
+      cStart = 0;
+      buffMem = memoStr[cEnd];
+      continue;
+    }
+
+    memoStr[memoStrPos] = oled->umlReplace(inChar);
+    memoStrPos++;
+    if (memoStrPos >= MEMOSTR_LIMIT) {
+      // ignore the other chars
+      memoStrPos = MEMOSTR_LIMIT-1;
+      memoStr[memoStrPos] = '\0';
+    }
+  }
+}
+
+inline void ticking() {
+  tick++;
+  // debug
+  //minutes++;
+  if (tick > 9) {
+    seconds += tick/10;
+    dsec++;
+  }
+
+  if (tick > 9) {
+    tick = tick % 10;
+    if (seconds > 59) {
+      minutes += seconds / 60;
+      seconds  = seconds % 60;
+      if (minutes%5 == 0) Serial.println(steps);
+
+      // modify limits every 1min to make a better re-calibration
+      if (minx > 1 && maxx < 399 && ( (maxx-minx) < MINDIF)) {
+        maxx--; minx++;
+      }
+      if (miny > 1 && maxy < 399 && ( (maxy-miny) < MINDIF)) {
+        maxy--; miny++;
+      }
+      if (minz > 1 && maxz < 399 && ( (maxz-minz) < MINDIF)) {
+        maxz--; minz++;
+      }
+    }
+    if (minutes > 59) {
+      hours  += minutes / 60;
+      minutes = minutes % 60;
+    }
+    if (hours > 23) {
+      hours = hours % 24;
+    }
+  }
+  if (COUNT > 0) {
+    if (tick == 0) {
+      analogWrite(LED_GREEN, 100);
+      analogWrite(LED_RED,    50);
+    } else {
+      digitalWrite(LED_RED,   LED_OFF);
+      digitalWrite(LED_GREEN, LED_OFF);
+      digitalWrite(LED_BLUE,  LED_OFF);
+    }
+  }
+}
+
+int myFont(int x, int y, byte b) {
+    int he = 18;
+    if (b>9) {
+      x = myFont(x,y,b/10);
+      b = b%10;
+    }
+    if (b == 0) {
+      oled->circle(x+he/4, y+3*he/4, he/4);
+      return x+2+he/2;
+    } else if (b == 1) {
+      oled->line(x,y+5,x+5,y);
+      oled->line(x+5,y,x+5,y+he);
+      return x+8;
+    } else if (b == 2) {
+      oled->circle(x+he/4, y-3+3*he/4, he/4);
+      oled->black(x,y,he/4,he);
+      oled->line(x+he/4,y+he-3,x+he/2,y+he);
+      return x+2+he/2;
+    } else if (b == 3) {
+      oled->circle(x+he/4, y+1*he/4, he/4);
+      oled->circle(x+he/4, y+3*he/4, he/4);
+      oled->black(x,y,he/4,he);
+      return x+2+he/2;
+    } else if (b == 4) {
+      oled->line(x,y+he/2,x+he/2,y);
+      oled->line(x,y+he/2,x+he/2,y+he/2);
+      oled->line(x+he/2,y,x+he/2,y+he);
+      return x+2+he/2;
+    } else if (b == 5) {
+      oled->line(x+he/4,y,x+he/2,y);
+      oled->line(x+he/4,y,x+he/4,y+he/2);
+      oled->circle(x+he/4, y+3*he/4, he/4);
+      oled->black(x,y,he/4,he);
+      return x+2+he/2;
+    } else if (b == 6) {
+      oled->line(x,y-2+3*he/4,x+he/2,y);
+      oled->circle(x+he/4, y+3*he/4, he/4);
+      return x+2+he/2;
+    } else if (b == 7) {
+      oled->line(x,y+3,x+he/2,y);
+      oled->line(x+he/2,y,x,y+he);
+      oled->line(x+3,y+he/2,x+he/2-1,y+he/2);
+      return x+2+5;
+    } else if (b == 8) {
+      oled->circle(x+he/4, y+1*he/4, he/4);
+      oled->circle(x+he/4, y+3*he/4, he/4);
+      return x+2+he/2;
+    } else if (b == 9) {
+      oled->circle(x+he/4, y+1*he/4, he/4);
+      oled->line  (x+he/2, y+1*he/4, x+he/2, y+he);
+      return x+2+he/2;
+    }
+}
+
+void anaClock() {
+  byte x = 96;
+  byte y = 38;
+  byte radius = 25;
+  oled->circle(x, y, radius);
+  int hour = hours;
+  if (hour>12) hour-=12;
+  oled->line(
+    x, y,
+    x + (radius-2)*cos(PI * ((float)seconds-15.0) / 30),
+    y + (radius-2)*sin(PI * ((float)seconds-15.0) / 30)
+  );
+
+  oled->line(
+    x, y,
+    x + (radius-5)*cos(PI * ((float)minutes-15.0) / 30),
+    y + (radius-5)*sin(PI * ((float)minutes-15.0) / 30)
+  );
+
+  oled->line(
+    x, y,
+    x + (radius-14)*cos(PI * ((float)hour+((float)minutes/60-0) -3.0) / 6),
+    y + (radius-14)*sin(PI * ((float)hour+((float)minutes/60.0) -3.0) / 6)
+  );
+
+  for (byte i=0; i<12; ++i) {
+    oled->pixel(x + (radius-3)*cos(PI * ((float)i) / 6), y + (radius-3)*sin(PI * ((float)i) / 6));
+  }
+}
+
+void printClock() {
+  if (hours<10) {
+    int xx = myFont(1, 2, 0);
+    myFont(xx, 2, hours);
+  } else {
+    myFont(1, 2, hours);
+  }
+  if (minutes<10) {
+    int xx = myFont(27, 2, 0);
+    myFont(xx, 2, minutes);
+  } else {
+    myFont(27, 2, minutes);
+  }
+  if (seconds<10) {
+    int xx = myFont(53, 2, 0);
+    myFont(xx, 2, seconds);
+  } else {
+    myFont(53, 2, seconds);
+  }
+
+
+  if(tick==0 || tick==1 || tick==2) oled->drawBitmap(3*tick, 23+(2*tick), move0, 8, 8, WHITE);
+  if(tick==5 || tick==3 || tick==4) oled->drawBitmap(3*tick, 23+(2*tick), move2, 8, 12, WHITE);
+  if(tick>6) oled->drawBitmap(3*tick, 23+(2*tick), move1, 8, 12, WHITE);
+
+  anaClock();
+
+  oled->setTextSize(1);
+  if (COUNT > 0) {
+    oled->setCursor(97, 2);
+    oled->print(COUNT);
+  }
+
+  if (delta > 0.2) {
+    oled->on();
+    dsec = 0;
+  }
+
+  oled->setCursor(5,55);
+  oled->print(steps);
+
+  oled->setCursor(50,55);
+  oled->print(vcc/34); //3400 -> 100%
+  oled->print('%');
+}
+
+inline void wakeUpIcon() {
+  oled->clear();
+  digitalWrite(LED_RED,   LED_OFF);
+  analogWrite(LED_BLUE,  10);
+  analogWrite(LED_GREEN,  5);
+  oled->circle(oled->width()/2, oled->height()/2, 5);
+  oled->black(0,0,oled->width()/2, oled->height());
+  oled->black(oled->width()/2, oled->height()/2,oled->width()/2, oled->height()/2);
+  oled->display();
+  delay(100);
+  analogWrite(LED_BLUE,  50);
+  analogWrite(LED_GREEN, 20);
+  oled->circle(oled->width()/2, oled->height()/2, 10);
+  oled->black(0,0,oled->width()/2, oled->height());
+  oled->black(oled->width()/2, oled->height()/2,oled->width()/2, oled->height()/2);
+  oled->display();
+  delay(100);
+  analogWrite(LED_BLUE, 100);
+  analogWrite(LED_GREEN, 50);
+  oled->circle(oled->width()/2, oled->height()/2, 15);
+  oled->black(0,0,oled->width()/2, oled->height());
+  oled->black(oled->width()/2, oled->height()/2,oled->width()/2, oled->height()/2);
+  oled->display();
+  delay(100);
+  analogWrite(LED_BLUE, 200);
+  analogWrite(LED_GREEN, 90);
+  oled->circle(oled->width()/2, oled->height()/2, 20);
+  oled->black(0,0,oled->width()/2, oled->height());
+  oled->black(oled->width()/2, oled->height()/2,oled->width()/2, oled->height()/2);
+  oled->display();
+  delay(200);
+  digitalWrite(LED_RED,   LED_OFF);
+  digitalWrite(LED_GREEN, LED_OFF);
+  digitalWrite(LED_BLUE,  LED_OFF);
+}
+
+inline byte tob(char c) { return c - '0';}
+
+float ab(float x) {
+  if (x<0) return -1*x;
+  return x;
+}
+
+int slen(char * str) {
+  int i;
+  for (i=0;str[i] != '\0' && i < 1000; ++i);
+  return i;
+}
+
+void setup() {
+  pinMode(BUTTON1, INPUT_PULLUP);
+  pinMode(BUTTON2, INPUT_PULLUP);
+  pinMode(LED_RED,   OUTPUT);
+  pinMode(LED_GREEN, OUTPUT);
+  pinMode(LED_BLUE,  OUTPUT);
+
+  Serial.begin(SERIAL_SPEED);
+
+  oled->begin();
+  oled->clearDisplay();
+  oled->display();
+  buffMem = '\0';
+
+  digitalWrite(LED_RED,   LED_OFF);
+  digitalWrite(LED_GREEN, LED_OFF);
+  digitalWrite(LED_BLUE,  LED_OFF);
+
+  mag.begin();
+  delay(7);
+
+  oled->clearDisplay();
+  buffMem = '\0';
+
+  MsTimer2::set(100, ticking); // 100ms period
+  MsTimer2::start();
+}
+
+void loop() {
+  delay(111);
+
+  if (seconds == 10 || tick == 1) {
+    readVcc();
+    if (vcc < WARN_POWER && powerlow == false) {
+      powerlow = true;
+      Serial.print("Steps: ");
+      Serial.println(steps);
+      Serial.print(vcc);
+      Serial.println(" mV");
+    } else {
+      powerlow = false;
+    }
+  }
+
+  oled->clear();
+  printClock();
+  oled->setTextSize(1);
+  mesure();
+
+  if (dsec < DISPLAYSEC && cStart < memoStrPos) {
+    oled->setCursor(0,22);
+    oled->black(0,22,128,42);
+    oled->print(&(memoStr[cStart]));
+  }
+
+  if (dsec == DISPLAYSEC) {
+    memoStr[0] = '\0';
+    memoStrPos = 0;
+    oled->off();
+  }
+
+  oled->setCursor(0, 0);
+
+  if (digitalRead(BUTTON1) == LOW) {
+    oled->on();
+    dsec = 0;
+    digitalWrite(LED_RED,   LED_OFF);
+    digitalWrite(LED_GREEN, LED_OFF);
+    digitalWrite(LED_BLUE,  LED_OFF);
+  }
+
+  if (digitalRead(BUTTON2) == LOW) {
+    delay(200);
+    if (digitalRead(BUTTON2) == LOW) {
+
+      COUNT = 0;
+      digitalWrite(LED_RED,   LED_OFF);
+      digitalWrite(LED_GREEN, LED_OFF);
+      digitalWrite(LED_BLUE,  LED_OFF);
+
+      Serial.print("Steps: ");
+      Serial.println(steps);
+      Serial.print(vcc);
+      Serial.println(" mV");
+
+      oled->on();
+      dsec = 0;
+      wakeUpIcon();
+
+      // "remove" old chars from buffer
+      // print ignores everyting behind \0
+      memoStr[0] = '\0';
+      memoStrPos = 0;
+      iconType = MSG_NO;
+      Serial.print(CHAR_TIME_REQUEST);
+      Serial.print('\n');
+    }
+  }
+
+  if (COUNT > 0) {
+    int l = slen(memoStr);
+    if (
+      (l > 8 &&
+      memoStr[l-8] == 'c' &&
+      memoStr[l-7] == 'a' &&
+      memoStr[l-6] == 'l' &&
+      memoStr[l-5] == 'e' &&
+      memoStr[l-4] == 'n' &&
+      memoStr[l-3] == 'd' &&
+      memoStr[l-2] == 'a' &&
+      memoStr[l-1] == 'r') || iconType == MSG_CAL
+    ) {
+      oled->drawBitmap(86, 2, icon_calendar, 8, 8, WHITE);
+      iconType = MSG_CAL;
+    } else if (
+      (l > 9 &&
+      memoStr[l-9] == 'm' &&
+      memoStr[l-8] == 'e' &&
+      memoStr[l-7] == 's' &&
+      memoStr[l-6] == 's' &&
+      memoStr[l-5] == 'a' &&
+      memoStr[l-4] == 'g' &&
+      memoStr[l-3] == 'i' &&
+      memoStr[l-2] == 'n' &&
+      memoStr[l-1] == 'g') || iconType == MSG_SMS
+    ) {
+      oled->drawBitmap(86, 2, icon_messaging, 8, 8, WHITE);
+      iconType = MSG_SMS;
+    } else if (
+      (l > 7 &&
+      memoStr[l-7] == 'f' &&
+      memoStr[l-6] == 's' &&
+      memoStr[l-5] == 'c' &&
+      memoStr[l-4] == 'k' &&
+      memoStr[l-3] == '.' &&
+      memoStr[l-2] == 'k' &&
+      memoStr[l-1] == '9') || iconType == MSG_MAIL
+    ) {
+      oled->drawBitmap(86, 2, icon_mail, 8, 8, WHITE);
+      iconType = MSG_MAIL;
+    } else if (
+      (l > 5) || iconType == MSG_OTHER
+    ) {
+      oled->drawBitmap(86, 2, icon_other, 8, 8, WHITE);
+      iconType = MSG_OTHER;
+    }
+  } else {
+    digitalWrite(LED_RED,   LED_OFF);
+    digitalWrite(LED_GREEN, LED_OFF);
+    digitalWrite(LED_BLUE,  LED_OFF);
+    iconType = MSG_NO;
+  }
+
+  if (memoStr[0] == CHAR_TIME_RESPONSE) {
+    // extract the time -------------------------
+
+    memoStr[0] = ' ';
+    hours = tob(memoStr[1])*10 + tob(memoStr[2]);
+    minutes = tob(memoStr[4])*10 + tob(memoStr[5]);
+    seconds = tob(memoStr[7])*10 + tob(memoStr[8]);
+
+  } else if (memoStr[0] == CHAR_NOTIFY_HINT) {
+    // there is a new message (or a message is deleted)
+    COUNT = (unsigned char) memoStr[1];
+  }
+
+  oled->display();
+
+  if (powerlow) analogWrite(LED_RED, 5*tick);
+
+  cEnd++;
+  cStart++;
+  if (cEnd <= memoStrPos) buffMem = memoStr[cEnd];
+}
+


Update SlaveModule.ino

Update SlaveModule.ino

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


Create menu.ino

Create menu.ino

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

--- games/menu.ino
+++ games/menu.ino
@@ -0,0 +1,50 @@
+#include <TVout.h>
+#include <fontALL.h>
+#include "schematic.h"
+#include "TVOlogo.h"
+
+TVout TV;
+
+#define  HRES  144      //Resolucao TV
+#define  VRES  96       //
+#define  TV_MODE NTSC
+#define  REFRESH_RATE 5
+#define  FONT8 font8x8  //Fonte padrao
+#define  PLAYER1 2      //Potenciometro player 1
+#define  PLAYER2 1      //Potenciometro player 2
+
+void setup() {
+  TV.begin(TV_MODE,HRES,VRES);
+  randomSeed(analogRead(0));
+  TV.select_font(FONT8);
+}
+
+void loop() {
+
+  int prev = -1;
+  int option = analogRead(1) + analogRead(1) + analogRead(1);
+  option = map(option/100,0,20,3,8);
+
+  while(true){
+    TV.println(0,0 ,"*---------------*\n");
+    TV.println(0,8 ,"|  Hackstation  |\n");
+    TV.println(0,16,"*---------------*\n");
+    TV.println(0,24,"| Pog-Pong      |\n");
+    TV.println(0,32,"|               |\n");
+    TV.println(0,40,"|               |\n");
+    TV.println(0,48,"|               |\n");
+    TV.println(0,56,"|               |\n");
+    TV.println(0,64,"| Exit          |\n");
+    TV.println(0,72,"*---------------*\n");
+
+    TV.set_cursor(8,option*8);
+    TV.print(">");
+
+    while(option == prev){
+      option = analogRead(PLAYER1) + analogRead(PLAYER1) + analogRead(PLAYER1);
+      option = map(option/100,0,20,3,8);
+      delay(REFRESH_RATE);
+    }
+    prev = option;
+  }
+}