Rework live tune

Rework live tune

--- examples/Live_tune/Live_tune.ino
+++ examples/Live_tune/Live_tune.ino
@@ -2,50 +2,88 @@
 #define DIR_PIN   55  //			19			55	//direction
 #define STEP_PIN  54  //			18			54	//step
 #define CS_PIN    40  //			17			40	//chip select
+#define STEP_PORT   PORTF
+#define STEP_BIT     0

 int speed = 10;
 bool running = false;
 float Rsense = 0.11;
 float hold_x = 0.5;
 boolean toggle1 = 0;
+uint8_t stall_value = 9;
+volatile uint32_t step_counter = 0;
+const uint32_t steps_per_mm = 80 * 16; // @ 256 microsteps
+const uint16_t fsteps_per_rotation = 200;
+const uint32_t MHz = 16000000>>8; // Scaled by 256
+const uint16_t acceleration = 2000;

 #include <TMC2130Stepper.h>
-TMC2130Stepper myStepper = TMC2130Stepper(EN_PIN, DIR_PIN, STEP_PIN, CS_PIN);
-
-ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
-//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
-  if (toggle1){
-    digitalWrite(STEP_PIN, HIGH);
-    toggle1 = 0;
-  }
-  else{
-    digitalWrite(STEP_PIN, LOW);
-    toggle1 = 1;
-  }
+TMC2130Stepper myStepper = TMC2130Stepper(CS_PIN);
+
+ISR(TIMER1_COMPA_vect){
+	STEP_PORT |= 1 << STEP_BIT;
+	STEP_PORT &= ~(1 << STEP_BIT);
+	step_counter++;
 }

 void initTimer() {
 	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 = 256;// = (16*10^6) / (1*1024) - 1 (must be <65536)
+	//set timer1 interrupt at 10kHz => 10000 steps/s => ~ 20 fullsteps/s
+	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 2kHz increments
+	OCR1A = 61;// = (16*10^6) / (8*2000) - 1 (must be <65536)
 	// turn on CTC mode
 	TCCR1B |= (1 << WGM12);
-	// Set CS12 and CS10 bits for 1024 prescaler
-	TCCR1B |= (1 << CS11);// | (1 << CS10);
-	// enable timer compare interrupt
-	TIMSK1 |= (1 << OCIE1A);
+	// Set CS01 bit for no prescaler
+	TCCR1B |= (1 << CS10);
+	// enable/disable timer compare interrupt on start
+	//TIMSK1 |= (1 << OCIE1A);
+	TIMSK1 &= ~(1 << OCIE1A);
 	sei();//allow interrupts
 }

-void setTimer(int t) {
+uint16_t calculateMMSTimer(uint8_t mms) {
+	uint32_t steps_per_second = mms * steps_per_mm;
+	steps_per_second >>= 8;
+	uint32_t tmr = MHz / steps_per_second - 1;
+	return tmr;
+}
+uint16_t calculateFSPSTimer(uint16_t fsps) {
+	return MHz / fsps - 1;
+}
+uint16_t calculateRPSTimer(uint8_t rps) {
+	return MHz / (rps * fsteps_per_rotation) - 1;
+}
+
+void accelerationRamp(uint16_t maxMMS = 100) {
+	TIMSK1 &= ~(1 << OCIE1A);
+	while (myStepper.cur_a() != 0) { // Use cur_b if measuring from B coil
+		digitalWrite(STEP_PIN, HIGH);
+		digitalWrite(STEP_PIN, LOW);
+		delay(1);
+	}
+	delay(100);
+	digitalWrite(EN_PIN, HIGH);
+	uint16_t mms = 2;
+	uint16_t maxOCR1A = calculateMMSTimer(maxMMS);
+	uint16_t _OCR1A = calculateMMSTimer(mms);
+	digitalWrite(EN_PIN, LOW);
+	OCR1A = _OCR1A;
+	TIMSK1 |= 1 << OCIE1A;
+	for (; mms <= maxMMS; mms += acceleration) {
+		delay(1);
+		OCR1A = calculateMMSTimer(mms);
+	}
 	cli();
-	TCNT1 = 0;
-	OCR1A = t;
+	step_counter = 0;
 	sei();
+	while (step_counter <= 100*steps_per_mm);
+	for (; mms >= 2; mms -= acceleration) {
+		delay(1);
+		OCR1A = calculateMMSTimer(mms);
+	}
 }

 void serialTuple(String cmd, int arg) {
@@ -56,14 +94,49 @@
 	Serial.println(")");
 }

-
 void setup() {
 	initTimer();
-	Serial.begin(9600);
-	myStepper.begin();
-	myStepper.SilentStepStick2130(1000);
+	Serial.begin(500000);
+
+	pinMode(EN_PIN, OUTPUT);
+	pinMode(DIR_PIN, OUTPUT);
+	pinMode(STEP_PIN, OUTPUT);
+	pinMode(CS_PIN, OUTPUT);
+	digitalWrite(EN_PIN, HIGH); //deactivate driver (LOW active)
+	digitalWrite(DIR_PIN, LOW); //LOW or HIGH
+	digitalWrite(STEP_PIN, LOW);
+	digitalWrite(CS_PIN, HIGH);
+
+	myStepper.push();
+    myStepper.tbl(1); //blank_time(24);
+    myStepper.power_down_delay(255);
+	myStepper.toff(4);
+
+	// Effective hysteresis = 0
+	myStepper.hstrt(0);
+	myStepper.hend(2);
+
+	myStepper.en_pwm_mode(true);
+	myStepper.pwm_freq(1);
+	myStepper.pwm_autoscale(true);
+	myStepper.pwm_ampl(180);
+	myStepper.pwm_grad(1);
+
+    myStepper.rms_current(600); // mA
+    myStepper.microsteps(256);
+    myStepper.diag1_stall(1);
+    myStepper.diag1_active_high(1);
 	digitalWrite(EN_PIN, LOW);
-	Serial.println("Setup ready");
+
+	while (myStepper.cur_a() < 240) { // Use cur_b if measuring from B coil
+		digitalWrite(STEP_PIN, HIGH);
+		digitalWrite(STEP_PIN, LOW);
+		delay(3);
+	}
+	Serial.print("cur_a = ");
+	Serial.println(myStepper.cur_a(), DEC);
+	Serial.print("cur_b = ");
+	Serial.println(myStepper.cur_b(), DEC);
 }

 void loop() {
@@ -76,16 +149,51 @@
 		if (cmd == "run") {
 			serialTuple("run", arg);
 			running = arg;
-			arg ? digitalWrite(EN_PIN, LOW) : digitalWrite(EN_PIN, HIGH);
-		}
-		else if (cmd == "speed") {
-			serialTuple("speed", arg);
-			//speed = arg;
-			setTimer(arg);
+			arg ? TIMSK1 |= 1 << OCIE1A : TIMSK1 &= ~(1 << OCIE1A);
+			//arg ? digitalWrite(EN_PIN, LOW) : digitalWrite(EN_PIN, HIGH);
+		}
+
+		else if (cmd == "mms") {
+			serialTuple("mms", arg);
+			cli();
+			TCNT1 = 0;
+			OCR1A = calculateMMSTimer(arg);
+			Serial.print("Set OCR1A to ");
+			Serial.println(OCR1A);
+			sei();
+		}
+		else if (cmd == "fsps") {
+			serialTuple("fsps", arg);
+			cli();
+			OCR1A = calculateFSPSTimer(arg);
+			Serial.print("Set OCR1A to ");
+			Serial.println(OCR1A);
+			sei();
+		}
+		else if (cmd == "rps") {
+			serialTuple("rps", arg);
+			cli();
+			OCR1A = calculateRPSTimer(arg);
+			Serial.print("Set OCR1A to ");
+			Serial.println(OCR1A);
+			sei();
 		}
 		else if (cmd == "setCurrent") {
 			serialTuple("setCurrent", arg);
 			myStepper.setCurrent(arg, Rsense, hold_x);
+		}
+		else if (cmd == "find_pos") {
+			serialTuple("find_pos", arg);
+			TIMSK1 &= ~(1 << OCIE1A);
+			while (myStepper.cur_a() != arg) { // Use cur_b if measuring from B coil
+				digitalWrite(STEP_PIN, HIGH);
+				digitalWrite(STEP_PIN, LOW);
+				delay(1);
+			}
+		}
+		else if (cmd == "rampTo") {
+			serialTuple("rampTo", arg);
+			accelerationRamp(arg);
 		}
 		else if (cmd == "Rsense") {
 			Serial.print("Setting R sense value to: ");
@@ -101,25 +209,25 @@
 			Serial.print("GCONF: 0b");
 			Serial.println(myStepper.GCONF(), BIN);
 		}
-		else if (cmd == "external_ref") {
-			serialTuple("external_ref", arg);
-			myStepper.external_ref(arg);
-		}
-		else if (cmd == "internal_sense_R") {
-			serialTuple("internal_sense_R", arg);
-			myStepper.internal_sense_R(arg);
-		}
-		else if (cmd == "stealthChop") {
-			serialTuple("stealthChop", arg);
-			myStepper.stealthChop(arg);
-		}
-		else if (cmd == "commutation") {
-			serialTuple("commutation", arg);
-			myStepper.commutation(arg);
-		}
-		else if (cmd == "shaft_dir") {
-			serialTuple("shaft_dir", arg);
-			myStepper.shaft_dir(arg);
+		else if (cmd == "I_scale_analog") {
+			serialTuple("I_scale_analog", arg);
+			myStepper.I_scale_analog(arg);
+		}
+		else if (cmd == "internal_Rsense") {
+			serialTuple("internal_Rsense", arg);
+			myStepper.internal_Rsense(arg);
+		}
+		else if (cmd == "en_pwm_mode") {
+			serialTuple("en_pwm_mode", arg);
+			myStepper.en_pwm_mode(arg);
+		}
+		else if (cmd == "enc_commutation") {
+			serialTuple("enc_commutation", arg);
+			myStepper.enc_commutation(arg);
+		}
+		else if (cmd == "shaft") {
+			serialTuple("shaft", arg);
+			myStepper.shaft(arg);
 		}
 		else if (cmd == "diag0_errors") {
 			serialTuple("diag0_errors", arg);
@@ -145,10 +253,6 @@
 			serialTuple("diag1_chopper_on", arg);
 			myStepper.diag1_chopper_on(arg);
 		}
-		else if (cmd == "diag1_steps_skipped") {
-			serialTuple("diag1_steps_skipped", arg);
-			myStepper.diag1_steps_skipped(arg);
-		}
 		else if (cmd == "diag0_active_high") {
 			serialTuple("diag0_active_high", arg);
 			myStepper.diag0_active_high(arg);
@@ -169,212 +273,198 @@
 			serialTuple("direct_mode", arg);
 			myStepper.direct_mode(arg);
 		}
-		else if (cmd == "hold_current") {
-			serialTuple("hold_current", arg);
-			myStepper.hold_current(arg);
-		}
-		else if (cmd == "run_current") {
-			serialTuple("run_current", arg);
-			myStepper.run_current(arg);
-		}
-		else if (cmd == "hold_delay") {
-			serialTuple("hold_delay", arg);
-			myStepper.hold_delay(arg);
-		}
-		else if (cmd == "power_down_delay") {
-			serialTuple("power_down_delay", arg);
-			myStepper.power_down_delay(arg);
-		}
+		// IHOLD_IRUN
+		else if (cmd == "ihold") {
+			serialTuple("ihold", arg);
+			myStepper.ihold(arg);
+		}
+		else if (cmd == "irun") {
+			serialTuple("irun", arg);
+			myStepper.irun(arg);
+		}
+		else if (cmd == "iholddelay") {
+			serialTuple("iholddelay", arg);
+			myStepper.iholddelay(arg);
+		}
+
 		else if (cmd == "microstep_time") {
 			Serial.print("microstep_time: ");
 			Serial.println(myStepper.microstep_time());
 		}
-		else if (cmd == "stealth_max_speed") {
-			serialTuple("stealth_max_speed", arg);
-			myStepper.stealth_max_speed(arg);
-		}
-		else if (cmd == "coolstep_min_speed") {
-			serialTuple("coolstep_min_speed", arg);
-			myStepper.coolstep_min_speed(arg);
-		}
-		else if (cmd == "mode_sw_speed") {
-			serialTuple("mode_sw_speed", arg);
-			myStepper.mode_sw_speed(arg);
-		}
-		else if (cmd == "coil_A_current") {
-			serialTuple("coil_A_current", arg);
-			myStepper.coil_A_current(arg);
-		}
-		else if (cmd == "coil_B_current") {
-			serialTuple("coil_B_current", arg);
-			myStepper.coil_B_current(arg);
-		}
-		else if (cmd == "DCstep_min_speed") {
-			serialTuple("DCstep_min_speed", arg);
-			myStepper.DCstep_min_speed(arg);
-		}
+
+		else if (cmd == "TPWMTHRS") {
+			serialTuple("TPWMTHRS", arg);
+			myStepper.TPWMTHRS(arg);
+		}
+		else if (cmd == "TCOOLTHRS") {
+			serialTuple("TCOOLTHRS", arg);
+			myStepper.TCOOLTHRS(arg);
+		}
+		else if (cmd == "THIGH") {
+			serialTuple("THIGH", arg);
+			myStepper.THIGH(arg);
+		}
+		// XDIRECT
+		else if (cmd == "coil_A") {
+			serialTuple("coil_A", arg);
+			myStepper.coil_A(arg);
+		}
+		else if (cmd == "coil_B") {
+			serialTuple("coil_B", arg);
+			myStepper.coil_B(arg);
+		}
+
+		else if (cmd == "VDCMIN") {
+			serialTuple("VDCMIN", arg);
+			myStepper.VDCMIN(arg);
+		}
+
 		else if (cmd == "CHOPCONF") {
 			Serial.print("CHOPCONF: 0b");
 			Serial.println(myStepper.CHOPCONF(), BIN);
 		}
-		else if (cmd == "off_time") {
-			serialTuple("off_time", arg);
-			myStepper.off_time(arg);
-		}
-		else if (cmd == "hysteresis_start") {
-			serialTuple("hysteresis_start", arg);
-			myStepper.hysteresis_start(arg);
-		}
-		else if (cmd == "fast_decay_time") {
-			serialTuple("fast_decay_time", arg);
-			myStepper.fast_decay_time(arg);
-		}
-		else if (cmd == "hysteresis_low") {
-			serialTuple("hysteresis_low", arg);
-			myStepper.hysteresis_low(arg);
-		}
-/*		else if (cmd == "sine_offset") {
-			serialTuple("sine_offset", arg);
-			myStepper.sine_offset(arg);
-		}*/
-		else if (cmd == "disable_I_comparator") {
-			serialTuple("disable_I_comparator", arg);
-			myStepper.disable_I_comparator(arg);
-		}
-		else if (cmd == "random_off_time") {
-			serialTuple("random_off_time", arg);
-			myStepper.random_off_time(arg);
-		}
-		else if (cmd == "chopper_mode") {
-			serialTuple("chopper_mode", arg);
-			myStepper.chopper_mode(arg);
-		}
-		else if (cmd == "blank_time") {
-			serialTuple("blank_time", arg);
-			myStepper.blank_time(arg);
-		}
-		else if (cmd == "high_sense_R") {
-			serialTuple("high_sense_R", arg);
-			myStepper.high_sense_R(arg);
-		}
-		else if (cmd == "fullstep_threshold") {
-			serialTuple("fullstep_threshold", arg);
-			myStepper.fullstep_threshold(arg);
-		}
-		else if (cmd == "high_speed_mode") {
-			serialTuple("high_speed_mode", arg);
-			myStepper.high_speed_mode(arg);
-		}
-		else if (cmd == "sync_phases") {
-			serialTuple("sync_phases", arg);
-			myStepper.sync_phases(arg);
-		}
-		else if (cmd == "microsteps") {
-			serialTuple("microsteps", arg);
-			myStepper.microsteps(arg);
-		}
-		else if (cmd == "interpolate") {
-			serialTuple("interpolate", arg);
-			myStepper.interpolate(arg);
-		}
-		else if (cmd == "double_edge_step") {
-			serialTuple("double_edge_step", arg);
-			myStepper.double_edge_step(arg);
-		}
-		else if (cmd == "disable_short_protection") {
-			serialTuple("disable_short_protection", arg);
-			myStepper.disable_short_protection(arg);
-		}
-		else if (cmd == "sg_min") {
-			serialTuple("sg_min", arg);
-			myStepper.sg_min(arg);
-		}
-		else if (cmd == "sg_max") {
-			serialTuple("sg_max", arg);
-			myStepper.sg_max(arg);
-		}
-		else if (cmd == "sg_step_width") {
-			serialTuple("sg_step_width", arg);
-			myStepper.sg_step_width(arg);
-		}
-		else if (cmd == "sg_current_decrease") {
-			serialTuple("sg_current_decrease", arg);
-			myStepper.sg_current_decrease(arg);
-		}
-		else if (cmd == "smart_min_current") {
-			serialTuple("smart_min_current", arg);
-			myStepper.smart_min_current(arg);
-		}
-		else if (cmd == "sg_stall_value") {
-			serialTuple("sg_stall_value", arg);
-			myStepper.sg_stall_value(arg);
-		}
-		else if (cmd == "sg_filter") {
-			serialTuple("sg_filter", arg);
-			myStepper.sg_filter(arg);
-		}
-		else if (cmd == "stealth_amplitude") {
-			serialTuple("stealth_amplitude", arg);
-			myStepper.stealth_amplitude(arg);
-		}
-		else if (cmd == "stealth_gradient") {
-			serialTuple("stealth_gradient", arg);
-			myStepper.stealth_gradient(arg);
-		}
-		else if (cmd == "stealth_freq") {
-			serialTuple("stealth_freq", arg);
-			myStepper.stealth_freq(arg);
-		}
-		else if (cmd == "stealth_freq") {
-			serialTuple("stealth_freq", arg);
-			myStepper.stealth_freq(arg);
-		}
-		else if (cmd == "stealth_autoscale") {
-			serialTuple("stealth_autoscale", arg);
-			myStepper.stealth_autoscale(arg);
-		}
-		else if (cmd == "stealth_symmetric") {
-			serialTuple("stealth_symmetric", arg);
-			myStepper.stealth_symmetric(arg);
-		}
-		else if (cmd == "standstill_mode") {
-			serialTuple("standstill_mode", arg);
-			myStepper.standstill_mode(arg);
-		}
+		else if (cmd == "toff") {
+			serialTuple("toff", arg);
+			myStepper.toff(arg);
+		}
+		else if (cmd == "hstrt") {
+			serialTuple("hstrt", arg);
+			myStepper.hstrt(arg);
+		}
+		else if (cmd == "hend") {
+			serialTuple("hend", arg);
+			myStepper.hend(arg);
+		}
+		else if (cmd == "fd") {
+			serialTuple("fd", arg);
+			myStepper.fd(arg);
+		}
+		else if (cmd == "disfdcc") {
+			serialTuple("disfdcc", arg);
+			myStepper.disfdcc(arg);
+		}
+		else if (cmd == "rndtf") {
+			serialTuple("rndtf", arg);
+			myStepper.rndtf(arg);
+		}
+		else if (cmd == "chm") {
+			serialTuple("chm", arg);
+			myStepper.chm(arg);
+		}
+		else if (cmd == "tbl") {
+			serialTuple("tbl", arg);
+			myStepper.tbl(arg);
+		}
+		else if (cmd == "vsense") {
+			serialTuple("vsense", arg);
+			myStepper.vsense(arg);
+		}
+		else if (cmd == "vhighfs") {
+			serialTuple("vhighfs", arg);
+			myStepper.vhighfs(arg);
+		}
+		else if (cmd == "vhighchm") {
+			serialTuple("vhighchm", arg);
+			myStepper.vhighchm(arg);
+		}
+		else if (cmd == "sync") {
+			serialTuple("sync", arg);
+			myStepper.sync(arg);
+		}
+		else if (cmd == "mres") {
+			serialTuple("mres", arg);
+			myStepper.mres(arg);
+		}
+		else if (cmd == "intpol") {
+			serialTuple("intpol", arg);
+			myStepper.intpol(arg);
+		}
+		else if (cmd == "dedge") {
+			serialTuple("dedge", arg);
+			myStepper.dedge(arg);
+		}
+		else if (cmd == "diss2g") {
+			serialTuple("diss2g", arg);
+			myStepper.diss2g(arg);
+		}
+		// COOLCONF
+		else if (cmd == "semin") {
+			serialTuple("semin", arg);
+			myStepper.semin(arg);
+		}
+		else if (cmd == "seup") {
+			serialTuple("seup", arg);
+			myStepper.seup(arg);
+		}
+		else if (cmd == "semax") {
+			serialTuple("semax", arg);
+			myStepper.semax(arg);
+		}
+		else if (cmd == "sedn") {
+			serialTuple("sedn", arg);
+			myStepper.sedn(arg);
+		}
+		else if (cmd == "seimin") {
+			serialTuple("seimin", arg);
+			myStepper.seimin(arg);
+		}
+		else if (cmd == "sgt") {
+			serialTuple("sgt", arg);
+			myStepper.sgt(arg);
+		}
+		else if (cmd == "sfilt") {
+			serialTuple("sfilt", arg);
+			myStepper.sfilt(arg);
+		}
+		// PWMCONF
+		else if (cmd == "pwm_ampl") {
+			serialTuple("pwm_ampl", arg);
+			myStepper.pwm_ampl(arg);
+		}
+		else if (cmd == "pwm_grad") {
+			serialTuple("pwm_grad", arg);
+			myStepper.pwm_grad(arg);
+		}
+		else if (cmd == "pwm_freq") {
+			serialTuple("pwm_freq", arg);
+			myStepper.pwm_freq(arg);
+		}
+		else if (cmd == "pwm_autoscale") {
+			serialTuple("pwm_autoscale", arg);
+			myStepper.pwm_autoscale(arg);
+		}
+		else if (cmd == "pwm_symmetric") {
+			serialTuple("pwm_symmetric", arg);
+			myStepper.pwm_symmetric(arg);
+		}
+		else if (cmd == "freewheel") {
+			serialTuple("freewheel", arg);
+			myStepper.freewheel(arg);
+		}
+		// ENCM_CTRL
+		else if (cmd == "inv") {
+			serialTuple("inv", arg);
+			myStepper.inv(arg);
+		}
+		else if (cmd == "maxspeed") {
+			serialTuple("maxspeed", arg);
+			myStepper.maxspeed(arg);
+		}
+
 		else if (cmd == "DRVSTATUS") {
 			Serial.print("DRVSTATUS: 0b");
 			Serial.println(myStepper.DRV_STATUS(), BIN);
 		}
 		else if (cmd == "PWM_SCALE") {
 			Serial.print("PWM_SCALE: 0b");
-			Serial.println(myStepper.PWM_SCALE(), BIN);
-		}
-		else if (cmd == "invert_encoder") {
-			serialTuple("invert_encoder", arg);
-			myStepper.invert_encoder(arg);
-		}
-		else if (cmd == "maxspeed") {
-			serialTuple("maxspeed", arg);
-			myStepper.maxspeed(arg);
-		}
-		else if (cmd == "interpolate") {
-			serialTuple("interpolate", arg);
-			myStepper.interpolate(arg);
+			Serial.println(myStepper.PWM_SCALE(), DEC);
 		}
 		else if (cmd == "LOST_STEPS") {
 			Serial.print("LOST_STEPS: 0b");
-			Serial.println(myStepper.LOST_STEPS(), BIN);
+			Serial.println(myStepper.LOST_STEPS(), DEC);
 		}
 		else {
 			Serial.println("Invalid command!");
 		}
 	}
-/*
-	if (running) {
-		digitalWrite(STEP_PIN, HIGH);
-		delayMicroseconds(speed);
-		digitalWrite(STEP_PIN, LOW);
-		delayMicroseconds(speed);
-	}
-*/
-}
+}


XとYを別々のコマンドに分離。 その方がコマンド体系がすっきりするので。 ただし、スケッチサイズオーバー。

--- examples/Console2TFT/Console2TFT.ino
+++ examples/Console2TFT/Console2TFT.ino
@@ -106,7 +106,7 @@
   return init_font();
 }

-enum State {ST_WAITCMD, ST_GOTO, ST_GOTO2, ST_TEXT, ST_SJIS1};
+enum State {ST_WAITCMD, ST_SETX, ST_SETY, ST_TEXT, ST_SJIS1};
 State state = ST_WAITCMD;
 int16_t x = 0;
 int16_t y = 0;
@@ -133,37 +133,40 @@
         state = ST_TEXT;
         buf[1] = ch;
         buf[2] = '\0';
-      } else if (state == ST_GOTO) {
-        if (isdigit(ch)) {
-          row = row * 10 + ch - '0';
-        } else if (ch == ';') {
-          state = ST_GOTO2;
-          col = 0;
-        }
-        return;
-      } else if (state == ST_GOTO) {
+      } else if (state == ST_SETX) {
         if (isdigit(ch)) {
           col = col * 10 + ch - '0';
-          return;
         } else {
-          state = ST_TEXT;
-          if (row < 1) {
-            row = 1;
-          }
+          state = ST_WAITCMD;
           if (col < 1) {
             col = 1;
           }
           // 左上位置はrow=1,col=1→x=0,y=0
-          y = (row-1) * tftkanji.height();
           x = (col-1) * tftkanji.ankWidth();
         }
+        return;
+      } else if (state == ST_SETY) {
+        if (isdigit(ch)) {
+          row = row * 10 + ch - '0';
+        } else {
+          state = ST_WAITCMD;
+          if (row < 1) {
+            row = 1;
+          }
+          y = (row-1) * tftkanji.height();
+        }
+        return;
       } else if (state == ST_WAITCMD) {
         switch (ch) {
         case 'J':
           tft.fillScreen(bgcolor);
           return;
-        case 'H':
-          state = ST_GOTO;
+        case 'X':
+          state = ST_SETX;
+          col = 0;
+          break;
+        case 'Y':
+          state = ST_SETY;
           row = 0;
           break;
         case 'K':


Update basic-esp32.ino

Update basic-esp32.ino

Serial1 doesn't need declaration anymore

--- examples/basic-esp32/basic-esp32.ino
+++ examples/basic-esp32/basic-esp32.ino
@@ -17,8 +17,6 @@
 DPTemp outsideTemp("outsideTemp", "boiler", 0x5525);
 DPTemp boilerTemp("boilertemp", "boiler", 0x0810);
 DPStat pumpStat("pump", "heating1", 0x2906);
-
-HardwareSerial Serial1(1);  // use Serial1 for VitoWifi

 void tempCallbackHandler(const IDatapoint& dp, DPValue value) {
   float fahrenheit = 0;


remake

remake

--- examples/serial_menu/serial_menu.ino
+++ examples/serial_menu/serial_menu.ino
@@ -1,3 +1,32 @@
+/*
+ * LiquidMenu library - serial_menu.ino
+ *
+ * This example uses the serial communication to execute commands.
+ *
+ * The available commands will be printed on the serial monitor.
+ *
+ * The circuit:
+ * https://github.com/VasilKalchev/LiquidMenu/blob/master/examples/serial_menu/serial_menu.png
+ * - LCD RS pin to Arduino pin 12
+ * - LCD E pin to Arduino pin 11
+ * - LCD D4 pin to Arduino pin 5
+ * - LCD D5 pin to Arduino pin 4
+ * - LCD D6 pin to Arduino pin 3
+ * - LCD D7 pin to Arduino pin 2
+ * - LCD R/W pin to ground
+ * - LCD VSS pin to ground
+ * - LCD VCC pin to  5V
+ * - 10k ohm potentiometer: ends to 5V and ground, wiper to LCD V0
+ * - 150 ohm resistor from 5V to LCD Anode
+ * - LCD Cathode to ground
+ *
+ * Created July 24, 2016
+ * by Vasil Kalchev
+ *
+ * https://github.com/VasilKalchev/LiquidMenu
+ *
+ */
+
 #include <LiquidCrystal.h>
 #include <LiquidMenu.h>

@@ -18,51 +47,70 @@
 LiquidScreen welcome_screen(welcome_line1, welcome_line2);

 LiquidLine line21(4, 0, "Screen 2");
-LiquidLine line22(1, 1, "next, previous");
-LiquidScreen screen2(line21, line22);
+LiquidLine type_line(4, 1, "type...");
+LiquidScreen screen2(line21, type_line);

 LiquidLine line31(4, 0, "Screen 3");
-LiquidLine line32(1, 1, "focus, position");
-LiquidScreen screen3(line31, line32);
+LiquidScreen screen3(line31, type_line);

 LiquidLine line41(4, 0, "Screen 4");
-LiquidLine line42(1, 1, "update");
-LiquidScreen screen4(line41, line42);
+LiquidScreen screen4(line41, type_line);

 LiquidMenu menu(lcd, welcome_screen, screen2, screen3, screen4);

+void callback_function() {
+  Serial.println("You called the callback function.");
+}
+
 void setup() {
-	Serial.begin(250000);
-	lcd.begin(16, 2);
+  Serial.begin(250000);
+  lcd.begin(16, 2);

-	menu.update();
+  line21.attach_function(1, callback_function);
+  line31.attach_function(1, callback_function);
+  line41.attach_function(1, callback_function);
+  type_line.attach_function(1, callback_function);
+
+  menu.update();
+
+  Serial.print("LiquidMenu "); Serial.print(VERSION); Serial.println(" - Serial example:");
+  Serial.println("To navigate the menu type 'menu.next_screen()' or 'menu.previous_screen()'.");
+  Serial.println("To switch focus type 'menu.switch_focus()'.");
+  Serial.println("To call the callback function type 'menu.call_function(1)'.");
+  Serial.println("To adjust the focus position type 'menu.set_focusPosition(Position::LEFT)'");
+  Serial.println("  or 'menu.set_focusPosition(Position::RIGHT)'.");
+  Serial.println("To update the display type 'menu.update()'."); Serial.println();
 }

 void loop() {
-	while (Serial.available() > 0) {
-		String command = Serial.readStringUntil('\0');
-		if (command == "next") {
-			Serial.println(command);
-			menu.next_screen();
-		} else if (command == "previous") {
-			Serial.println(command);
-			menu.previous_screen();
-		} else if (command == "focus") {
-			Serial.println(command);
-			menu.switch_focus(); // switches focus to the next line
-			// focus is used with functions (see 'functions_menu' example)
-		} else if (command == "focus position = left") {
-			Serial.println(command);
-			// this function sets the focus position
-			menu.set_focusPosition(Position::LEFT);
-		} else if (command == "focus position = right") {
-			Serial.println(command);
-			menu.set_focusPosition(Position::RIGHT);
-		} else if (command == "update") {
-			Serial.println(command);
-		} else {
-			Serial.print(command); Serial.println(" - unknown command");
-		}
-		menu.update();
-	}
+  while (Serial.available() > 0) {
+    String command = Serial.readStringUntil('\0');
+    if (command == "menu.next_screen()") {
+      Serial.println(command);
+      menu.next_screen();
+    } else if (command == "menu.previous_screen()") {
+      Serial.println(command);
+      menu.previous_screen();
+    } else if (command == "menu.switch_focus()") {
+      Serial.println(command);
+      menu.switch_focus(); // switches focus to the next line
+      // focus is used with functions (see 'functions_menu' example)
+    } else if (command == "menu.call_function(1)") {
+      Serial.println(command);
+      menu.call_function(1);
+    } else if (command == "menu.set_focusPosition(Position::LEFT)") {
+      Serial.println(command);
+      // this function sets the focus position
+      menu.set_focusPosition(Position::LEFT);
+    } else if (command == "menu.set_focusPosition(Position::RIGHT)") {
+      Serial.println(command);
+      menu.set_focusPosition(Position::RIGHT);
+    } else if (command == "menu.update()") {
+      Serial.println(command);
+      menu.update();
+    } else {
+      Serial.print(command); Serial.println(" - unknown command");
+    }
+    menu.update();
+  }
 }


Update arrowprint_firmware.ino

Update arrowprint_firmware.ino

--- arrowprint_firmware/arrowprint_firmware.ino
+++ arrowprint_firmware/arrowprint_firmware.ino
@@ -22,60 +22,91 @@
  *  =======================================================================================
  */

+//int hotheadtarget = 160;    //160 DEFAULT
+int hotheadtarget = 10;    //160 DEFAULT
+
 //physical movement scale (bigger == more);
-double tablexsteps    = 13000;
-double tableysteps    = 13000;
-double tablezsteps    = 100000;    //257142 (100mm) from top (STEPS FROM TABLE SURFACE TO TOP) 0,0,0 is FAR LEFT BOTTOM
-double tableesteps  = -3600;
+double tablexsteps    = 23000;
+double tableysteps    = 33000;
+double tablezsteps    = 203205;    //234000 (100mm) from top (STEPS FROM TABLE SURFACE TO TOP) 0,0,0 is FAR LEFT BOTTOM
+double tableesteps  = -1000000;

 //measured (1000 = 1mm)
-double tablexdistance = 250000;    //in microns (158mm )
-double tableydistance = 250000;    //in microns (200mm)
-double tablezdistance = 96000;    //in microns (96mm)
-double tableedistance = 1000;    //in microns (96mm)
-
-double maxmotorSpeed = 12600;
-double motorSpeed = 12600;                                           //default 9600
-double motorAccel = 160000; //steps/second/second to accelerate      //default 80000
+double tablexdistance = 200.000;    //in microns (158mm )
+double tableydistance = 200.000;    //in microns (200mm)
+double tablezdistance = 70.000;    //in microns (96mm)
+double tableedistance = 310.000;    //in microns (96mm)
+

 // Motor pins
-int motorpinXstep = 7;
-int motorpinXdir  = 6;
-int motorpinYstep = 9;
-int motorpinYdir  = 8;
-int motorpinZstep = 13;
-int motorpinZdir  = 12;
-int motorpinEstep = 11;
-int motorpinEdir  = 10;
+// step = pin for step on controller
+// dir  = pin for direction on controller
+// speed is minimum delay between pulses in microseconds
+int motorpinXstep = 24;
+int motorpinXdir  = 25;
+double stepperXcurrPosition = 0;
+double stepperXdestPosition = 0;
+double stepperXtimer = 0;
+int    stepperXtoggle = 0;
+double stepperXspeed = 60;
+
+int motorpinYstep = 26;
+int motorpinYdir  = 27;
+double stepperYcurrPosition = 0;
+double stepperYdestPosition = 0;
+double stepperYtimer = 0;
+int    stepperYtoggle = 0;
+double stepperYspeed = 120;  //slower for more power
+
+int motorpinZstep = 30;
+int motorpinZdir  = 31;
+double stepperZcurrPosition = 0;
+double stepperZdestPosition = 0;
+double stepperZtimer = 0;
+int    stepperZtoggle = 0;
+double stepperZspeed = 60;
+
+int motorpinEstep = 28;
+int motorpinEdir  = 29;
+double stepperEcurrPosition = 0;
+double stepperEdestPosition = 0;
+double stepperEtimer = 0;
+int    stepperEtoggle = 0;
+double stepperEspeed = 120;
+

 // Motor Zero switch pins
-int xZeropin = 5;        //INPUT pin
-int yZeropin = 4;        //INPUT pin
-int zZeropin = 3;        //INPUT pin
-
-int xZeroNC  =  1;        //Normally closed/open
-int yZeroNC  =  1;          //Normally closed/open
-int zZeroNC  =  0;          //Normally closed/open
+int xZeropin = 50;        //INPUT pin
+int yZeropin = 51;        //INPUT pin
+int zZeropin = 52;        //INPUT pin
+
+//thermo control
+int thermoswitch = 2;    //output switch for turning on melter
+int thermo = A0;         //input for reading temperature of melter
+
+//NC/NO toggles
+int xZeroNC  =  1;       //Normally closed/open
+int yZeroNC  =  1;       //Normally closed/open
+int zZeroNC  =  0;       //Normally closed/open
+
+

 // =========================================================================================
-
+// INTERNAL DO NOT CHANGE BELOW
 //latest position in microns (1000 = 1mm)
-double lastx = tablexdistance/2;
-double lasty = tableydistance/2;
+
+double lastx = 0;
+double lasty = 0;
 double lastz = 0;
 double laste = 0;

-
-
 // =========================================================================================

-AccelStepper stepper5(1, motorpinXstep, motorpinXdir);          //CROSSBEAM      X AXIS
-AccelStepper stepper4(1, motorpinYstep, motorpinYdir);          //TABLE IN/OUT   Y AXIS
-AccelStepper stepper1(1, motorpinZstep, motorpinZdir);          //UP DOWN        Z AXIS
-AccelStepper stepper2(1, motorpinEstep, motorpinEdir);          //EXSTRUDER FEED E AXIS

 void setup() {
+  analogReadResolution(16);
+  analogWriteResolution(16);
   Serial.begin(115200);
   Serial.print("{ \"log\" : \"Connecting...\"}");
   //ZERO SWITCHES
@@ -83,65 +114,86 @@
   pinMode(yZeropin, INPUT);                  //Y SWITCH
   pinMode(zZeropin, INPUT);                  //Z SWITCH

-
-  stepper1.setMaxSpeed(maxmotorSpeed);
-  stepper2.setMaxSpeed(maxmotorSpeed);
-  stepper4.setMaxSpeed(maxmotorSpeed);
-  stepper5.setMaxSpeed(maxmotorSpeed);
-
-  stepper1.setSpeed(motorSpeed);
-  stepper2.setSpeed(motorSpeed);
-  stepper4.setSpeed(motorSpeed);
-  stepper5.setSpeed(motorSpeed);
-  stepper1.setAcceleration(motorAccel);
-  stepper2.setAcceleration(motorAccel);
-  stepper4.setAcceleration(motorAccel);
-  stepper5.setAcceleration(motorAccel);
-
-  zeroaxis();                                //ZERO AXIS
-
-  stepper1.setSpeed(motorSpeed);
-  stepper2.setSpeed(motorSpeed);
-  stepper4.setSpeed(motorSpeed);
-  stepper5.setSpeed(motorSpeed);
-  stepper1.setAcceleration(motorAccel);
-  stepper2.setAcceleration(motorAccel);
-  stepper4.setAcceleration(motorAccel);
-  stepper5.setAcceleration(motorAccel);
-
-  //testaxis();                                //(optional) RUNS TO EXTREMES AND STOPS AT (X0,Y0,Z0,E0)
+  //Thermo
+  pinMode(thermo, INPUT);              //Analogue temperature measure
+  pinMode(thermoswitch, OUTPUT);       //Heater mosfet switch
+  digitalWrite(thermoswitch, LOW);     //Defaults to OFF/LOW
+
+  pinMode(motorpinXstep, OUTPUT);
+  pinMode(motorpinXdir, OUTPUT);
+  pinMode(motorpinYstep, OUTPUT);
+  pinMode(motorpinYdir, OUTPUT);
+  pinMode(motorpinZstep, OUTPUT);
+  pinMode(motorpinZdir, OUTPUT);
+  pinMode(motorpinEstep, OUTPUT);
+  pinMode(motorpinEdir, OUTPUT);
+
+  thermistor();
+  zeroaxis();
+  thermistor();
+
+
   Serial.print("{ \"log\" : \"Success\"}");
   Serial.print("{ \"version\" : \""+version+"\"}");
-  //rapid(75000,100000, 10000, 0);
-
-  line(tablexdistance/2, tableydistance/2, 0, 0);  //CENTER
-
+  pinMode(13, OUTPUT);
+  Serial.print("{ \"status\" : \"waiting\"}");
 }

 aJsonStream serial_stream(&Serial);

+double lastcmd = 0;
+double tempcounter = 0;
+
 void loop() {
-  //line(10000,10000,-20000,0);
-  //line(150000,127052,-30000,20000);
-  //gotoxyze(0,0,0,0);
-  //testsurface();  //(optional) this runs around on the table so you can test height consistancy
-
-  //gotoxyze(150000,100000,0,0);
-  //circle(50000,50000,0,0,20000);
-  //
-  //
-      if (serial_stream.available()) {
-        /* First, skip any accidental whitespace like newlines. */
-        serial_stream.skip();
-      }
-
-      if (serial_stream.available()) {
-        /* Something real on input, let's take a look. */
+    double lastloop = millis();
+    while (serial_stream.available()) {
         aJsonObject *msg = aJson.parse(&serial_stream);
         processMessage(msg);
-        aJson.deleteItem(msg);
-      }
-  Serial.print("{ \"status\" : \"waiting\"}");
+        lastcmd = millis();
+        aJson.deleteItem(msg);
+
+        tempcounter++;
+        if (tempcounter > 5) {
+            thermistor();
+            tempcounter = 0;
+        }
+
+        Serial.print("{ \"status\" : \"waiting\"}");
+    }
+
+
+    if (!serial_stream.available()) {
+
+    }
+
+
+    if (lastloop > lastcmd+1000) {
+        pinMode(13, HIGH);
+        delay(250);
+        pinMode(13, LOW);
+        delay(250);
+        pinMode(13, HIGH);
+        delay(250);
+        pinMode(13, LOW);
+        delay(250);
+        Serial.print("{ \"status\" : \"waiting\"}");
+        pinMode(13, HIGH);
+        delay(250);
+        pinMode(13, LOW);
+        delay(250);
+        pinMode(13, HIGH);
+        delay(250);
+        pinMode(13, LOW);
+        delay(250);
+    }
+
+}
+//=======================================================================================
+
+void thermistor() {
+   Serial.print("{ \"thermistor\" : \"");
+   Serial.print(analogRead(thermo));
+   Serial.print("\"}");
 }

 //=======================================================================================
@@ -151,204 +203,148 @@
       Runs each motor towards the zero switch and resets its position. Must be run at start.
   */

-///////////////////////////////////////////////////////ZERO X OVERHANG SIDE TO SIDE
+    ////////////////////////////////////////////////////////ZERO Z - UPDOWN
+    Serial.print("{ \"log\" : \"Attempting to zero Z axis\"}");
+
+    while (digitalRead(zZeropin) != zZeroNC) {
+      stepperZdestPosition = stepperZdestPosition + 16;
+      while (stepperZdistanceToGo() != 0) {
+        stepperZrun();
+      }
+    }
+
+    stepperZcurrPosition = tablezsteps + 6400;
+
+    //moves a little off switch
+    stepperZdestPosition = tablezsteps -30000;
+    while (stepperZdistanceToGo() != 0) {
+      stepperZrun();
+    }
+    /////////////////////////////////////////////////////////// X LEFT RIGHT
+    Serial.print("{ \"log\" : \"Attempting to zero X axis\"}");
+    while (digitalRead(xZeropin) != xZeroNC) {
+      stepperXdestPosition = stepperXdestPosition - 32;
+      while (stepperXdistanceToGo() != 0) {
+        stepperXrun();
+      }
+    }

-    //stepper5.setSpeed(6400);
-    //stepper5.setAcceleration(999999);
+    stepperXcurrPosition = -1000;
+    //moves a little off switch (0)
+    stepperXdestPosition = tablexsteps;
+    while (stepperXdistanceToGo() != 0) {
+      stepperXrun();
+    }
+    Serial.print("{ \"log\" : \"X axis zero success\"}");
+    ////////////////////////////////////////////////////////////// Y TABLE FRONT BACK
+    Serial.print("{ \"log\" : \"Attempting to zero Y axis\"}");
+    while (digitalRead(yZeropin) != yZeroNC) {
+      stepperYdestPosition = stepperYdestPosition + 32;
+      while (stepperYdistanceToGo() != 0) {
+        stepperYrun();
+      }
+    }
+    //moves to 0
+    stepperYcurrPosition = tableysteps+1000;
+    stepperYdestPosition = 0;
+    while (stepperYdistanceToGo() != 0) {
+      stepperYrun();
+    }
+    ////////////////////////////////////////////////////////////// E zero
+    Serial.print("{ \"log\" : \"Attempting to test E axis\"}");
+    stepperEdestPosition = 6400;  //1 rotation
+    while (stepperEdistanceToGo() != 0) {
+        stepperErun();
+      }
+    //moves to 0
+    stepperEcurrPosition = 0;
+    stepperEdestPosition = 0;
+    Serial.print("{ \"log\" : \"Extruder stepper axis zero success\"}");

-    while (digitalRead(xZeropin) != xZeroNC) {
-      stepper5.moveTo(stepper5.currentPosition()-10);      //change to +4 for zero on opposite side
-      stepper5.run();
-    }
-
-    stepper5.stop();
-    stepper5.setCurrentPosition(-1000);
-    stepper5.setSpeed(motorSpeed);
-    stepper5.setAcceleration(motorAccel);
-    stepper5.moveTo(7000);
-    while (stepper5.distanceToGo() != 0) {
-      stepper5.run();
-    }
-
-
-    ///////////////////////////////////////////////////////ZERO Y TABLE
-    stepper4.setSpeed(6400);
-    stepper4.setAcceleration(999999);
-    while (digitalRead(yZeropin) != yZeroNC) {
-      stepper4.moveTo(stepper4.currentPosition()+10);
-      stepper4.run();
-    }
-    delay(100);
-    stepper4.stop();
-    stepper4.setCurrentPosition(tableysteps+1000);
-    stepper4.moveTo(0);
-    while (stepper4.distanceToGo() != 0) {
-      stepper4.run();
-    }
-    ////////////////////////////////////////////////////////ZERO Z - UPDOWN
-    stepper1.setSpeed(8000);
-    stepper1.setAcceleration(999999);
-
-    while (digitalRead(zZeropin) != zZeroNC) {
-      stepper1.moveTo(stepper1.currentPosition()+320);
-      stepper1.run();
-    }
-    stepper1.stop();
-    stepper1.setCurrentPosition(tablezsteps);
-    stepper1.setSpeed(motorSpeed);
-    stepper1.setAcceleration(motorAccel);
-    stepper1.moveTo(0);
-    while (stepper1.distanceToGo() != 0) {
-      stepper1.run();
-    }
-
-    //////////////////////////////////////////////////////////E zero - feeder
-    stepper2.setSpeed(6400);
-    stepper2.setAcceleration(999999);
-    stepper2.moveTo(0);
-    while (stepper2.distanceToGo() != 0) {
-      stepper2.runSpeedToPosition();
-    }
-
 }
 // END ZEROAXIS()
-
-// ==============================================================================================================================================================================
-// START TESTAXIS()
-void testaxis() {
-  /*
-    Runs all axis to extremes and also gives extruder a test spin
-  */
-    //HIGH
-    stepper5.moveTo(tablexsteps);
-    stepper4.moveTo(tableysteps);
-    stepper1.moveTo(tablezsteps);
-    stepper2.moveTo(tableesteps);
-    while ((stepper5.distanceToGo() != 0) || (stepper4.distanceToGo() != 0) || (stepper1.distanceToGo() != 0) || (stepper2.distanceToGo() != 0)) {
-      stepper5.run();
-      stepper4.run();
-      stepper1.run();
-      stepper2.run();
-    }
-    //ZERO
-    stepper5.moveTo(0);
-    stepper4.moveTo(0);
-    stepper1.moveTo(0);
-    stepper2.moveTo(0);
-    while ((stepper5.distanceToGo() != 0) || (stepper4.distanceToGo() != 0) || (stepper1.distanceToGo() != 0) || (stepper2.distanceToGo() != 0)) {
-      stepper5.run();
-      stepper4.run();
-      stepper1.run();
-      stepper2.run();
-    }
-}
-// END TESTAXIS();
-
-// ==============================================================================================================================================================================
-
-// START RAPID()
-void rapid(int x, int y, int z, int e) {
-  /*
-    Allows you to position the printer and control the feeder
-    dimensions are in microns. 1000 = 1mm
-    Moves proportionally so all motors arrive at destination at the same time.
-  */
-    double nx = tablexsteps*x/tablexdistance;
-    double ny = tableysteps*y/tableydistance;
-
-    stepper5.moveTo(nx);
-    stepper4.moveTo(ny);
-    stepper1.moveTo(z);
-    stepper2.moveTo(e);
-
-    while ((stepper5.distanceToGo() != 0) || (stepper4.distanceToGo() != 0) || (stepper1.distanceToGo() != 0) || (stepper2.distanceToGo() != 0)) {
-      stepper5.runSpeedToPosition();
-      stepper4.runSpeedToPosition();
-      stepper1.runSpeedToPosition();
-      stepper2.runSpeedToPosition();
-    }
-}
-// END RAPID();
-// ==============================================================================================================================================================================
-// START CIRCLE()
-void circle(int x, int y,int z,int e, int rad) {
-  double nx = tablexsteps*x/tablexdistance;
-  double ny = tableysteps*y/tableydistance;
-
-  for (int i = 0; i < 3600; i++)
-  {
-    float angle = i*2*3.14/1000;
-    double cx = nx + (cos(angle) * (tablexsteps*rad/tablexdistance));
-    double cy = ny + (sin(angle) * (tableysteps*rad/tableydistance));
-    stepper5.moveTo(cx);
-    stepper4.moveTo(cy);
-    stepper1.moveTo(z);
-    stepper2.moveTo(e);
-    while ((stepper5.distanceToGo() != 0) || (stepper4.distanceToGo() != 0) || (stepper1.distanceToGo() != 0) || (stepper2.distanceToGo() != 0)) {
-          stepper5.runSpeedToPosition();
-          stepper4.runSpeedToPosition();
-          stepper1.runSpeedToPosition();
-          stepper2.runSpeedToPosition();
-        }
-  }
-}
-// END CIRCLE()
 // ==============================================================================================================================================================================
 // START LINE()
 void line(double x, double y, double z, double e) {
-  /*
-    Allows you to position the printer and control the feeder
-    dimensions are in microns. 1000 = 1mm
-    Moves proportionally so all motors arrive at destination at the same time.
-  */
-/*
-      Serial.print("RAWLINE:X");      Serial.print(x);
-      Serial.print(" Y");             Serial.print(y);
-      Serial.print(" Z");             Serial.print(z);
-      Serial.print(" E");             Serial.print(e);
-      */
-
-   double steps = 100;
+
+  //DISTANCESTEPS
+
+   double deltax = lastx - x;
+   double deltay = lasty - y;
+   double deltaz = lastz - z;
+   double deltae = laste - e;
+
+   double distance = pow(deltax,2) + pow(deltay,2) + pow(deltaz, 2) + pow(deltae, 2);
+   distance = sqrt(distance);
+
+  ///
+
+//   double steps = 25;
+    double steps = round(distance)*5;

         //calculate new step positions from micron position
    double nx = tablexsteps*(x/tablexdistance);
    double ny = tableysteps*(y/tableydistance);
    double nz = tablezsteps*(z/tablezdistance);
-   double ne = tableesteps*(e/tableedistance);
-
-   double cx = float(stepper5.currentPosition());
-   double cy = float(stepper4.currentPosition());
-   double cz = float(stepper1.currentPosition());
-   double ce = float(stepper2.currentPosition());
-
+   double ne = tableesteps*(e/tableedistance);
+
+   double cx = float(stepperXcurrPosition);
+   double cy = float(stepperYcurrPosition);
+   double cz = float(stepperZcurrPosition);
+   double ce = float(stepperEcurrPosition);
+
+
    double dx = ((nx-cx)/steps);
    double dy = ((ny-cy)/steps);
    double dz = ((nz-cz)/steps);
    double de = ((ne-ce)/steps);

+
+   //distance
+   /*
+   double deltax = lastx - x;
+   double deltay = lasty - y;
+   double deltaz = lastz - z;
+   double deltae = laste - e;
+   Serial.print("{ \"deltax\" : \"");
+   Serial.print(deltax);
+   Serial.print("\", \"deltay\" : \"");
+   Serial.print(deltay);
+   Serial.print("\", \"deltaz\" : \"");
+   Serial.print(deltaz);
+   Serial.print("\", \"deltae\" : \"");
+   Serial.print(deltae);
+   Serial.println("\"}");
+   */
+   //
+
    lastx = x;
    lasty = y;
    lastz = z;
    laste = e;

-   for (int i = 0; i <= steps; i++) {
+   for (int i = 0; i < steps; i++) {
      double newx = cx + (dx*i);
      double newy = cy + (dy*i);
      double newz = cz + (dz*i);
      double newe = ce + (de*i);

-     stepper5.moveTo(int(newx));
-     stepper4.moveTo(int(newy));
-     stepper1.moveTo(int(newz));
-     stepper2.moveTo(int(newe));
-     while ((stepper5.distanceToGo() != 0) || (stepper4.distanceToGo() != 0) || (stepper1.distanceToGo() != 0) || (stepper2.distanceToGo() != 0)) {
-       stepper5.run();
-       stepper4.run();
-       stepper1.run();
-       stepper2.run();
-     }
+     stepperXdestPosition = newx;
+     stepperYdestPosition = newy;
+     stepperZdestPosition = newz;
+     stepperEdestPosition = newe;
+
+
+     while ((stepperXdistanceToGo() != 0) || (stepperYdistanceToGo() != 0) || (stepperZdistanceToGo() != 0) || (stepperEdistanceToGo() != 0)) {
+       ///GET THESE INTO THE MAIN LOOP
+       // NEED TO REFACTOR EVENT LOOP
+       stepperXrun();
+       stepperYrun();
+       stepperZrun();
+       stepperErun();
+       }
    }
-
+
 }
 // END LINE();
 // ==============================================================================================================================================================================
@@ -356,70 +352,180 @@

 void processMessage(aJsonObject *msg)
 {
+
   int command = 0;
-  aJsonObject *jsonpg = aJson.getObjectItem(msg, "G");
+  aJsonObject *jsonpg = aJson.getObjectItem(msg, "cmd");
   if (jsonpg) {
-    if (jsonpg->valueint == 1) {
+    String cmd = jsonpg->valuestring;
+    if (cmd == "G1") {
       double g1x = lastx;
       double g1y = lasty;
       double g1z = lastz;
       double g1e = laste;
       //G1 PARSE
-      // GCODE X
-      aJsonObject *jsonpx = aJson.getObjectItem(msg, "X");
-      if (jsonpx) {
-        int ig1x = jsonpx->valueint;
-        g1x = ig1x;
-        g1x = g1x * 10;
+
+      /*
+      aJsonObject *jsonpx = aJson.getObjectItem(msg, "x");
+      if (jsonpx) {  g1x = jsonpx->valuefloat;   }
+
+      aJsonObject *jsonpy = aJson.getObjectItem(msg, "y");
+      if (jsonpy) {  g1y = jsonpy->valuefloat;   }
+
+      aJsonObject *jsonpz = aJson.getObjectItem(msg, "z");
+      if (jsonpz) {  g1z = jsonpz->valuefloat;   }
+
+      aJsonObject *jsonpe = aJson.getObjectItem(msg, "e");
+      if (jsonpe) {  g1e = jsonpe->valuefloat;
+        Serial.print("EVAL:");
+        Serial.println(g1e);
+      }
+      */
+      aJsonObject *jsonpx = aJson.getObjectItem(msg, "x");
+      if (jsonpx) {
+        char* tempx = jsonpx->valuestring;
+        g1x = atof(tempx);
       }

-      // GCODE Y
-      aJsonObject *jsonpy = aJson.getObjectItem(msg, "Y");
-      if (jsonpy) {
-        int ig1y = jsonpy->valueint;
-        g1y = ig1y;
-        g1y = g1y * 10;
+      aJsonObject *jsonpy = aJson.getObjectItem(msg, "y");
+      if (jsonpy) {
+        char* tempy = jsonpy->valuestring;
+        g1y = atof(tempy);
       }

-      // GCODE Z
-      aJsonObject *jsonpz = aJson.getObjectItem(msg, "Z");
-      if (jsonpz) {
-        int ig1z = jsonpz->valueint;
-        g1z = ig1z;
-        g1z = g1z * 10;
+      aJsonObject *jsonpz = aJson.getObjectItem(msg, "z");
+      if (jsonpz) {
+        char* tempz = jsonpz->valuestring;
+        g1z = atof(tempz);
       }

-      aJsonObject *jsonpe = aJson.getObjectItem(msg, "E");
-      if (jsonpe) {
-        int ig1e = jsonpe->valueint;
-        g1e = ig1e;
-        g1e = g1e;
-      }
+      aJsonObject *jsonpe = aJson.getObjectItem(msg, "e");
+      if (jsonpe) {
+        char* tempe = jsonpe->valuestring;
+        g1e = atof(tempe);
+      }

       line(g1x, g1y, g1z, g1e);          //G1 RUN

     }
     ///END G 1
     /////////////////////////////////////////////////////////////////
-  if (jsonpg->valueint == 92) {
-      //G92 PARSE
-      // GCODE X
-
-      aJsonObject *jsonpe = aJson.getObjectItem(msg, "E");
+  if (cmd == "G92") {
+      aJsonObject *jsonpe = aJson.getObjectItem(msg, "e");
       if (jsonpe) {
-        stepper2.setCurrentPosition(0);
-        laste = 0;
-        stepper2.setSpeed(motorSpeed);
-        command += 1;
+        stepperEcurrPosition = 0.0;
+        stepperEdestPosition = 0.0;
+        laste = 0.0;
       }
-    }
-    ///END G92
+    }///END G92
+
     ///////////////////////////////////////////////////////////////
   }
-
+
 }

 // END PROCESS GCODE
 // =======================================================================================================================

-
+///////========================vvvvvvvv STEPPER CONTROLLERS vvvvvv==================
+
+double stepperXdistanceToGo() { return stepperXdestPosition - stepperXcurrPosition; }
+
+void stepperXrun() {
+  double dir = 0;
+  stepperXdestPosition = round(stepperXdestPosition);
+  stepperXcurrPosition = round(stepperXcurrPosition);
+  if (stepperXdestPosition != stepperXcurrPosition) {
+    //SET DIRECTION
+    if (stepperXdestPosition > stepperXcurrPosition) {
+      digitalWrite(motorpinXdir, HIGH);
+      dir = 1;
+    } else {
+      digitalWrite(motorpinXdir, LOW);
+      dir = -1;
+    }
+    //PULSE AT SPEED LIMIT
+    if (micros() > (stepperXtimer+stepperXspeed)) {
+      digitalWrite(motorpinXstep, stepperXtoggle);
+      stepperXtimer = micros();
+      stepperXtoggle = !stepperXtoggle;
+      stepperXcurrPosition += dir;
+    }
+  }
+}
+
+double stepperYdistanceToGo() { return stepperYdestPosition - stepperYcurrPosition; }
+
+void stepperYrun() {
+  double dir = 0;
+  stepperYdestPosition = round(stepperYdestPosition);
+  stepperYcurrPosition = round(stepperYcurrPosition);
+  if (stepperYdestPosition != stepperYcurrPosition) {
+    //SET DIRECTION
+    if (stepperYdestPosition > stepperYcurrPosition) {
+      digitalWrite(motorpinYdir, HIGH);
+      dir = 1;
+    } else {
+      digitalWrite(motorpinYdir, LOW);
+      dir = -1;
+    }
+    //PULSE AT SPEED LIMIT
+    if (micros() > (stepperYtimer+stepperYspeed)) {
+      digitalWrite(motorpinYstep, stepperYtoggle);
+      stepperYtimer = micros();
+      stepperYtoggle = !stepperYtoggle;
+      stepperYcurrPosition += dir;
+    }
+  }
+}
+
+double stepperZdistanceToGo() { return stepperZdestPosition - stepperZcurrPosition; }
+
+void stepperZrun() {
+  double dir = 0;
+  stepperZdestPosition = round(stepperZdestPosition);
+  stepperZcurrPosition = round(stepperZcurrPosition);
+  if (stepperZdestPosition != stepperZcurrPosition) {
+    //SET DIRECTION
+    if (stepperZdestPosition > stepperZcurrPosition) {
+      digitalWrite(motorpinZdir, HIGH);
+      dir = 1;
+    } else {
+      digitalWrite(motorpinZdir, LOW);
+      dir = -1;
+    }
+    //PULSE AT SPEED LIMIT
+    if (micros() > (stepperZtimer+stepperZspeed)) {
+      digitalWrite(motorpinZstep, stepperZtoggle);
+      stepperZtimer = micros();
+      stepperZtoggle = !stepperZtoggle;
+      stepperZcurrPosition += dir;
+    }
+  }
+}
+
+double stepperEdistanceToGo() { return stepperEdestPosition - stepperEcurrPosition; }
+
+void stepperErun() {
+  double dir = 0;
+  stepperEdestPosition = round(stepperEdestPosition);
+  stepperEcurrPosition = round(stepperEcurrPosition);
+  if (stepperEdestPosition != stepperEcurrPosition) {
+    //SET DIRECTION
+    if (stepperEdestPosition > stepperEcurrPosition) {
+      digitalWrite(motorpinEdir, HIGH);
+      dir = 1;
+    } else {
+      digitalWrite(motorpinEdir, LOW);
+      dir = -1;
+    }
+    //PULSE AT SPEED LIMIT
+    if (micros() > (stepperEtimer+stepperEspeed)) {
+      digitalWrite(motorpinEstep, stepperEtoggle);
+      stepperEtimer = micros();
+      stepperEtoggle = !stepperEtoggle;
+      stepperEcurrPosition += dir;
+    }
+  }
+}
+
+///////===================^^^^^^^^^^^^^ STEPPER CONTROLLERS ^^^^^^^^^^^^^============


Banished the evil delay() based loops

Banished the evil delay() based loops

--- NTPclock/NTPclock.ino
+++ NTPclock/NTPclock.ino
@@ -27,6 +27,8 @@

 LedControl lc1 = LedControl(D5,D6,D7,1); // Initialize MAX7219
 unsigned long timeLastBlinked = millis();
+unsigned long timeLastUpdated = millis();
+
 bool militaryTime = false;

 // Initial set up routines
@@ -53,11 +55,14 @@

 // Main program loop
 void loop() {
-  updateDigits(); //Update the time display
-  updateMisc();   //Update the rest of the display
-  delay(1000);    //CHANGE THIS TO A COUNTER-BASED DELAY.  NOT THIS EVIL STUFF THAT IS A DELAY()
-
-  Serial.println(NTP.getTimeDateString(now() ) );
+  if (millis() > (timeLastUpdated + 1000)) {
+    updateDigits(); //Update the time display
+    updateMisc();   //Update the rest of the display
+
+    Serial.println(NTP.getTimeDateString(now() ) );
+
+    timeLastUpdated = millis();
+  }
 }

 // Handles updating the primary 7-segment display


Proper place of SD CArd init

Proper place of SD CArd init

--- app/app.ino
+++ app/app.ino
@@ -110,6 +110,10 @@
     iCave::GpsModule* gpsModule = manager->createAndRegisterModule<iCave::GpsModule>();
   #endif // ENABLE_GPS

+  #if ENABLE_SD_CARD
+    iCave::SdCardModule* sdCardModule = manager->createAndRegisterModule<iCave::SdCardModule>();
+  #endif // ENABLE_SD_CARD
+
   #if ENABLE_TSL_2561
     iCave::Tsl2561Module* tsl2561Module = manager->createAndRegisterModule<iCave::Tsl2561Module>();
   #endif // ENABLE_TSL_2561
@@ -123,10 +127,6 @@
     iCave::SnoozeModule* snoozeModule = manager->createAndRegisterModule<iCave::SnoozeModule>();
   #endif // ENABLE_SNOOZE

-  #if ENABLE_SD_CARD
-    iCave::SdCardModule* sdCardModule = manager->createAndRegisterModule<iCave::SdCardModule>();
-  #endif // ENABLE_SD_CARD
-
   // Setup modules registered in manager
   manager->setup();
 }


Fix #800: print out subband setting for regions where that makes sense

--- examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino
+++ examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino
@@ -765,6 +765,12 @@
     printVersion(ARDUINO_LMIC_VERSION);
     Serial.print(F(" configured for region "));
     Serial.print(CFG_region);
+
+#if defined(ARDUINO_LMIC_CFG_SUBBAND) && ARDUINO_LMIC_CFG_SUBBAND != -1
+    Serial.print(F(" subband[0:7] "));
+    Serial.print(unsigned(ARDUINO_LMIC_CFG_SUBBAND));
+#endif // defined(ARDUINO_LMIC_CFG_SUBBAND) && ARDUINO_LMIC_CFG_SUBBAND != -1
+
     Serial.println(F(".\nRemember to select 'Line Ending: Newline' at the bottom of the monitor window."));

     setup_printSignOnDashLine();
@@ -772,9 +778,9 @@
     }

 void setupForNetwork(bool preJoin) {
-#if CFG_LMIC_US_like
-    LMIC_selectSubBand(0);
-#endif
+#if defined(ARDUINO_LMIC_CFG_SUBBAND) && ARDUINO_LMIC_CFG_SUBBAND != -1
+    LMIC_selectSubBand(ARDUINO_LMIC_CFG_SUBBAND);
+#endif // defined(ARDUINO_LMIC_CFG_SUBBAND) && ARDUINO_LMIC_CFG_SUBBAND != -1
 }

 void loop() {


Fix buffer overruns and loop timing. Add clock overflow handling. Remove spinloop and move test for receipt of RC data to where it's used. Remove extraneous comments and add many ToDos.

--- Elcano_C2_LowLevel/Elcano_C2_LowLevel.ino
+++ Elcano_C2_LowLevel/Elcano_C2_LowLevel.ino
@@ -41,6 +41,7 @@
 #define LOOP_TIME_US 400
 #define ERROR_HISTORY 20 //number of errors to accumulate
 #define TEN_SECONDS_IN_MICROS 10000000
+#define ULONG_MAX 4294967295

 /*================ReadTurnAngle ================*/
 // @ToDo: Are these specific to a particular trike? If so, move them to Settings.h.
@@ -72,20 +73,28 @@
 const int SelectCD = 49; // Select IC 3 DAC (channels C and D)
 const int SelectAB = 53; // Select IC 2 DAC (channels A and B)

-const unsigned long INVALID_DATA = 0;
 volatile int rc_index = 0;
-volatile unsigned long RC_rise[7];
-volatile unsigned long RC_elapsed[7];
+// This is a value that the RC controller can't produce.
+#define INVALID_DATA 0L
+// How many RC signals we receive
+#define RC_NUM_SIGNALS 7
+volatile unsigned long RC_rise[RC_NUM_SIGNALS];
+volatile unsigned long RC_elapsed[RC_NUM_SIGNALS];
+// We'll copy values here before using them in an attempt to have the
+// values change while we're using them.
+unsigned long local_results[RC_NUM_SIGNALS];
+// This tells us when we have started receiving RC data. Until then, we
+// ignore RC_rise and RC_elapsed.
+volatile bool RC_Done[RC_NUM_SIGNALS];
 volatile boolean synced = false;
-volatile unsigned long last_fallingedge_time = 4294967295; // max long
-volatile bool RC_Done[7] = {0, 0, 0, 0, 0, 0, 0};
 volatile bool flipping;

 long speed_errors[ERROR_HISTORY];
 long old_turn_degx1000;
-unsigned long calibrationTime_ms;
-unsigned long stoppedTime_ms;
-unsigned long straightTime_ms;
+// @ToDo: Remove calibration and test code to its own file.
+//unsigned long calibrationTime_ms;
+//unsigned long stoppedTime_ms;
+//unsigned long straightTime_ms;
 int  throttle_control = MIN_ACC_OUT;
 int  brake_control = MIN_BRAKE_OUT;
 int  steer_control = STRAIGHT_TURN_OUT;
@@ -254,119 +263,156 @@
   //brake(MIN_BRAKE_OUT);
   Serial.begin(9600);
   rc_index = 0;
-  for (int i = 0; i < 8; i++)
+  for (int i = 0; i < RC_NUM_SIGNALS; i++)
   {
     RC_rise[i] = INVALID_DATA;
     RC_elapsed[i] = INVALID_DATA;
+    RC_Done[i] = 0;
   }
   for (int i = 0; i < ERROR_HISTORY; i++)
   {
     speed_errors[i] = 0;
   }
-  //setupWheelRev(); // WheelRev4 addition
-  CalibrateTurnAngle(32, 20);
-  calibrationTime_ms = millis();
-        attachInterrupt(digitalPinToInterrupt(IRPT_TURN),  ISR_TURN_rise,  RISING);
-        //attachInterrupt(digitalPinToInterrupt(IRPT_RDR),   ISR_RDR_rise,   RISING);
-        attachInterrupt(digitalPinToInterrupt(IRPT_GO),    ISR_GO_rise,    RISING);
-        attachInterrupt(digitalPinToInterrupt(IRPT_ESTOP), ISR_ESTOP_rise, RISING);
-        //attachInterrupt(digitalPinToInterrupt(IRPT_RVS),   ISR_RVS_rise,   RISING);
-        attachInterrupt(digitalPinToInterrupt(IRPT_SWITCH), ISR_SWITCH_rise, RISING);
-        attachInterrupt(digitalPinToInterrupt(IRPT_MOTOR_FEEDBACK), ISR_MOTOR_FEEDBACK_rise, RISING);
-        //Print7headers(false);
-  //PrintHeaders();
-}
-/*---------------------------------------------------------------------------------------*/
+
+  // @ToDo: Remove any test and calibration code.
+  // //setupWheelRev(); // WheelRev4 addition
+  //CalibrateTurnAngle(32, 20);
+  //calibrationTime_ms = millis();
+
+  attachInterrupt(digitalPinToInterrupt(IRPT_TURN),  ISR_TURN_rise,  RISING);
+  //attachInterrupt(digitalPinToInterrupt(IRPT_RDR),   ISR_RDR_rise,   RISING);
+  attachInterrupt(digitalPinToInterrupt(IRPT_GO),    ISR_GO_rise,    RISING);
+  attachInterrupt(digitalPinToInterrupt(IRPT_ESTOP), ISR_ESTOP_rise, RISING);
+  //attachInterrupt(digitalPinToInterrupt(IRPT_RVS),   ISR_RVS_rise,   RISING);
+  attachInterrupt(digitalPinToInterrupt(IRPT_SWITCH), ISR_SWITCH_rise, RISING);
+  attachInterrupt(digitalPinToInterrupt(IRPT_MOTOR_FEEDBACK), ISR_MOTOR_FEEDBACK_rise, RISING);
+}
+
+/*---------------------------------------------------------------------------------------*/
+
+// Time at which this loop pass should end in order to maintain a
+// loop period of LOOP_TIME_US.
+unsigned long nextTime = micros();
+// Time at which we reach the end of loop(), which should be before
+// nextTime if we have set the loop period long enough.
+unsigned long endTime;
+// How much time we need to wait to finish out this loop pass.
+unsigned long delayTime;
+
+// Inter-module communications data.
+SerialData Results;
+
 void loop() {
-  //Serial.println("Start of loop");
-  SerialData Results;
-
-  // Save start time for performance report.
-  unsigned long startTime = micros();
-  // Get the next loop start time.
-  unsigned long nextTime = startTime + LOOP_TIME_US;
-
-  digitalWrite(27, LOW);
-  digitalWrite(33, LOW);
-  startCapturingRCState();
-
-  unsigned long local_results[7];
-  //  PrintDone();
-
-  while (micros() < nextTime &&
-         ~((RC_Done[RC_ESTP] == 1) && (RC_Done[RC_GO] == 1) && (RC_Done[RC_TURN] == 1) && (RC_Done[RC_RDR] == 1)))
+  // Get the next loop start time. Note this (and the micros() counter) will
+  // roll over back to zero after they exceed the 32-bit size of unsigned long,
+  // which happens after about 70 minues of operation. If the new nextTime
+  // value is <= LOOP_TIME_US, we've rolled over.
+  nextTime = nextTime + LOOP_TIME_US;
+
+  // ToDo: Verify why this is being copied, e.g. is it to avoid having the
+  // values change while we're using them? Because they can change right here
+  // while we're copying them. Would it help to disable interrupts while we
+  // copy them? or does that just freeze them in some intermediate state?
+  // How about if we just make sure that anytime we exit the interrupt routine,
+  // the RC_elapsed values are in a valid state? Then we don't need to copy
+  // them. (This is all under the assumption that we're copying to avoid
+  // an inconsistent state.)
+  for (int i = 0; i < RC_NUM_SIGNALS; i++)
+    local_results[i] = RC_elapsed[i];
+
+  byte automate = processRC(local_results);
+  // @ToDo: Verify that this should be conditional. May be moot if it is
+  // replaced in the conversion to the new Elcano Serial protocol.
+  if (automate == 0x01)
   {
-    ;  //wait
-  }
-  // got data;
-  for (int i = 0; i < 8; i++)
-    local_results[i] = RC_elapsed[i];
-  //Print7(false, local_results);
-  //Serial.println("Processing RC data...");
-  byte automate = processRC(local_results);
-  if (automate == 0x01) //remember to tell Pat to fix this, was = instead of ==
-  {
-    //Serial.println("Processing high-level data");
     processHighLevel(&Results);
   }
-  //    Print7( true, local_results);
-
-  //Serial.println(nextTime); //Old sanity check line; testing new pin output sanity check.
-  //Serial.println("Clearing Results");
-//  Results.Clear();
-//  Results.kind = MSG_SENSOR;
-//  Results.angle_deg = TurnAngle_degx10() / 10;
-  //show_speed (&Results);
-
-  // Report how long the loop took.
-
-  digitalWrite(27, HIGH);
-  if(nextTime < startTime || nextTime > startTime + LOOP_TIME_US) {
-    digitalWrite(33, HIGH);
-  }
-  //Serial.println(nextTime); //Old sanity check line; testing new pin output sanity check.
-  //Serial.println("Clearing Results");
+
+  // @ToDo: What is this doing?
   //Results.clear();
   Results.kind = MSG_SENSOR;
   Results.angle_deg = TurnAngle_degx10() / 10;
-  //show_speed (&Results);
-
-  //LogData(local_results, &Results);  // data for spreadsheet
-
-  calibrationTime_ms += LOOP_TIME_US;
-  straightTime_ms = (steer_control == STRAIGHT_TURN_OUT) ? straightTime_ms + LOOP_TIME_US : 0;
-  stoppedTime_ms = (throttle_control == MIN_ACC_OUT) ? stoppedTime_ms + LOOP_TIME_US : 0;
-  if (calibrationTime_ms > 40000 && straightTime_ms > 3000 && stoppedTime_ms > 3000)
-  {
-    //       int oldBrake = brake_control;
-    //       brake(MAX_BRAKE_OUT);  // put on brakes
-    CalibrateTurnAngle(16, 10);  // WARNING: No response to controls while calibrating
-    //       brake(oldBrake);       // restore brake state
-    calibrationTime_ms = 0;
+  // @ToDo: Is this working and should it be uncommented?
+  // show_speed (&Results);
+
+  // @ToDo: Remove all test or calibration code. If needed, put it in a separate file.
+  //calibrationTime_ms += LOOP_TIME_US;
+  //straightTime_ms = (steer_control == STRAIGHT_TURN_OUT) ? straightTime_ms + LOOP_TIME_US : 0;
+  //stoppedTime_ms = (throttle_control == MIN_ACC_OUT) ? stoppedTime_ms + LOOP_TIME_US : 0;
+  //if (calibrationTime_ms > 40000 && straightTime_ms > 3000 && stoppedTime_ms > 3000)
+  //{
+  //  //       int oldBrake = brake_control;
+  //  //       brake(MAX_BRAKE_OUT);  // put on brakes
+  //  CalibrateTurnAngle(16, 10);  // WARNING: No response to controls while calibrating
+  //  //       brake(oldBrake);       // restore brake state
+  //  calibrationTime_ms = 0;
+  //}
+
+  // @ToDo: What information do we need to send to C6? Is that communication already
+  // hiding in here somewhere, or does it need to be added?
+
+  // Figure out how long we need to wait to reach the desired end time
+  // for this loop pass. First, get the actual end time. Note: Beyond this
+  // point, there should be *no* more controller activity -- we want
+  // minimal time between now, when we capture the actual loop end time,
+  // and when we pause til the desired loop end time.
+  endTime = micros();
+  delayTime = 0L;
+
+  // Did the micros() counter or nextTime overflow and roll over during
+  // this loop pass? Did the loop's processing time overrun the desired
+  // loop period? We have different computations for the delay time in
+  // various cases:
+  if ((nextTime >= endTime) &&
+      (((endTime < LOOP_TIME_US) && (nextTime < LOOP_TIME_US)) ||
+       ((endTime >= LOOP_TIME_US) && (nextTime >= LOOP_TIME_US)))) {
+    // 1) Neither micros() nor nextTime rolled over --or-- micros() rolled
+    // over *and* nextTime rolled over when we incremented it. For this case,
+    // endTime and nextTime will be in their usual relationship, with
+    // nextTime >= endTime, and both nextTime and endTime are either greater
+    // than the desired loop period, or both are smaller than that.
+    // In this case, we want a delayTime of nextTime - endTime here.
+    delayTime = nextTime - endTime;
+  } else {
+    // (We get here if:
+    // nextTime < endTime -or- exactly one of nextTime or endTime rolled over.
+    // Negate the first if condition and use DeMorgan's laws...
+    // Now pick out the "nextTime rolled over" case. We don't need to test both
+    // nextTime and endTime as we know only one rolled over.)
+    if (nextTime < LOOP_TIME_US) {
+      // 2) nextTime rolled over when we incremented it, but the micros() timer
+      // hasn't yet rolled over.
+      // In this case, we know we didn't exhaust the loop time, and the time we
+      // need to wait is the remaining time til micros() will roll over, i.e.
+      // from endTime until the max long value, plus the time from zero to
+      // nextTime.
+      delayTime = ULONG_MAX - endTime + nextTime;
+    } else {
+      // (We get here if:
+      // nextTime < endTime -or-
+      // nextTime >= endTime -and- nextTime did not roll over but endTime did.)
+      // What remains are these two cases:
+      // 3) nextTime hasn't rolled over, but micros() has.
+      // In this case, we overran the loop time. Since micros() has rolled over,
+      // we can just use the normal overrun fixup. So combine this with...
+      // 4) Neither nextTime nor micros rolled over, but we overran the desired
+      // loop period.
+      // In this case, we have no delay, but instead extend the allowed time for
+      // this loop pass to the actual time it took.
+      nextTime = endTime;
+      delayTime = 0L;
+    }
   }

-  unsigned long endTime = micros();
-  // unsigned long elapsedTime = endTime - startTime;
-  // Serial.print("loop elapsed time = ");
-  // Serial.println(elapsedTime);
-  // Did we spend long enough in the loop that we should immediately
-  // start the next pass?
-  //Serial.print("Time: "); Serial.print(endTime); Serial.print(", Next: "); Serial.println(nextTime);
-  if (nextTime > endTime) {
+  // Did we spend long enough in the loop that we should immediately start
+  // the next pass?
+  if (delayTime > 0L) {
     // No, pause til the next loop start time.
-    Serial.print("Start Sanity: "); Serial.println(startTime);
-    Serial.print("Const Sanity: "); Serial.println(LOOP_TIME_US);
-    Serial.print("Next Sanity: "); Serial.println(nextTime);
-    Serial.print("End Sanity: "); Serial.println(endTime);
-    Serial.print("Delaying: "); Serial.println(nextTime - endTime);
-    delay(nextTime - endTime);
-  } else {
-    // Yes, we overran the expected loop interval. Extend the time.
-    nextTime = endTime + LOOP_TIME_US;
-  }
-
-  //Serial.println("End of loop");
-}
+    delay(delayTime);
+  }
+}
+
+// @ToDo: Can we remove all or most of this print code?
 /*---------------------------------------------------------------------------------------*/
 void PrintDone()
 {
@@ -460,6 +506,11 @@
   Serial.println("(m) Distance");
 }

+// @ToDo: Remove all code that does not directly pertain to the actual
+// operation of the low-level controller. If we want to execute a pattern
+// of movement as a test, put this in a separate module, running on a
+// separate Arduino, and have that *send in commands* over the serial line
+// just as C3 will do.
 /*---------------------------------------------------------------------------------------*/
 //circleRoutine
 void circleRoutine(unsigned long seconds, unsigned long &rcAuto) {
@@ -515,13 +566,8 @@
   brake(MIN_BRAKE_OUT);
   rcAuto = LOW;
 }
-/*---------------------------------------------------------------------------------------*/
-void startCapturingRCState(){
-  for (int i = 1; i < 7; i++) {
-    RC_Done[i] = 0;
-  }
-}
-
+
+// @ToDo: Remove all obsolete code.
 ///*---------------------------------------------------------------------------------------*/
 ////done in setup, calibrate RC values for MIDDLE, MIN_RC, and MAX_RC at startup
 //void calibrateRC(unsigned long mic) {
@@ -563,90 +609,109 @@
 //  //digitalWrite(LED_PIN_OUT, LOW);
 //}

+// @ToDo: Q: What do the expressions "1st pulse", etc. mean? Is this a
+// leftover from trying to combine the RC controls into a single stream?
 /*---------------------------------------------------------------------------------------*/
 byte processRC (unsigned long *results){
+  // Each use of a particular results element is guarded by a check of RC_Done
+  // for that element, to see if we have begun receiving any data for that element.
   // 1st pulse is aileron (position 5 on receiver; controlled by Right left/right joystick on transmitter)
   //     used for Steering
-    //    Serial.print("\tTurn Cmd "); Serial.println(results[RC_TURN]);
   /* 2nd pulse is aux (position 1 on receiver; controlled by flap/gyro toggle on transmitter)
      will be used for selecting remote control or autonomous control. */
-  //    Serial.print("In processRC, received results[RC_AUTO] = "); Serial.println(results[RC_AUTO]);
-  if (NUMBER_CHANNELS > 5)
-    results[RC_AUTO] = (results[RC_AUTO] > MIDDLE ? HIGH : LOW);
-  //    Serial.print("processed results[RC_AUTO] = "); Serial.println(results[RC_AUTO]);
+  if (RC_Done[RC_AUTO]) {
+    if (NUMBER_CHANNELS > 5) {
+      results[RC_AUTO] = (results[RC_AUTO] > MIDDLE ? HIGH : LOW);
+    }
+  }

   /* 4th pulse is gear (position 2 on receiver; controlled by gear/mode toggle on transmitter)
     will be used for emergency stop. D38 */
-  Serial.println(results[RC_ESTP]);
-  results[RC_ESTP] = (results[RC_ESTP] > MIDDLE ? HIGH : LOW);
-
-  if (results[RC_ESTP] == HIGH){
-    Serial.println("Exiting processRC due to E-stop.");
-    E_Stop();  // already done at interrupt level
-    if ((results[RC_AUTO] == LOW)  && (NUMBER_CHANNELS > 5)) // under RC control
-      ;//steer(results[RC_TURN]);
-    return 0x00;
-  }
-
-
-  if ((results[RC_AUTO] == HIGH)  && (NUMBER_CHANNELS > 5))
-  {
-            Serial.println("Calling processHighLevel.");
-    return 0x01;  // not under RC control
-  } else {
-         Serial.println("Continuing processRC as under RC control.");
-  }
-
+  if (RC_Done[RC_ESTP]) {
+    results[RC_ESTP] = (results[RC_ESTP] > MIDDLE ? HIGH : LOW);
+
+    if (results[RC_ESTP] == HIGH){
+      // Serial.println("Exiting processRC due to E-stop.");
+      E_Stop();  // already done at interrupt level
+      if (RC_Done[RC_AUTO]) {
+      // if ((results[RC_AUTO] == LOW)  && (NUMBER_CHANNELS > 5)) // under RC control
+      //   {
+      //     ;//steer(results[RC_TURN]);
+      //   }
+      // }
+      }
+      return 0x00;
+    }
+  }
+
+  if (RC_Done[RC_AUTO]) {
+    if ((results[RC_AUTO] == HIGH)  && (NUMBER_CHANNELS > 5))
+    {
+      return 0x01;  // not under RC control
+    }
+  }
+
   /*  6th pulse is marked throttle (position 6 on receiver; controlled by Left up/down joystick on transmitter).
     It will be used for shifting from Drive to Reverse . D40
   */
-  //results[RC_RVS] = (results[RC_RVS] > MIDDLE? HIGH: LOW);
+  //if (RC_Done[RC_RVS]) {
+  //  //results[RC_RVS] = (results[RC_RVS] > MIDDLE? HIGH: LOW);
+  //}

   // TO DO: Select Forward / reverse based on results[RC_RVS]

   /*   3rd pulse is elevator (position 4 on receiver; controlled by Right up/down.
      will be used for throttle/brake: RC_Throttle
   */
-  int aileron = results[RC_TURN];
-  //    Serial.print("\tTurn input "); Serial.print(aileron);
-  results[RC_TURN] = convertTurn(aileron);
+  if (RC_Done[RC_TURN]) {
+    results[RC_TURN] = convertTurn(results[RC_TURN]);
+  }

   // Braking or Throttle
-  Serial.println(results[RC_GO]);
-  if (liveBrake(results[RC_GO])){
-    Serial.print("Braking: "); Serial.println(results[RC_GO]);
-    brake(convertBrake(results[RC_GO]));
-  }
-  else {
-    brake(MIN_BRAKE_OUT);
+  if (RC_Done[RC_GO]) {
+    if (liveBrake(results[RC_GO])){
+      brake(convertBrake(results[RC_GO]));
+    }
+    else {
+      brake(MIN_BRAKE_OUT);
+    }
   }

   //Accelerating
-  if (liveThrottle(results[RC_RDR])){
-    int going = convertThrottle(results[RC_RDR]);
-    moveVehicle(going);
-  }
-  else if(doRoutine(results[RC_RDR])){
-    moveVehicle(MIN_ACC_OUT);
-    squareRoutine(5, results[RC_AUTO]);
-  }
-  else {
-    moveVehicle(MIN_ACC_OUT);
-  }
-
-  steer(results[RC_TURN]);
+  if (RC_Done[RC_RDR]) {
+    if (liveThrottle(results[RC_RDR])){
+      int going = convertThrottle(results[RC_RDR]);
+      moveVehicle(going);
+    }
+    // @ToDo: Move test code out. Will eventually want to have a separate
+    // module execute the tests.
+    else {
+      if (RC_Done[RC_AUTO]) {
+        if(doRoutine(results[RC_RDR])){
+          moveVehicle(MIN_ACC_OUT);
+          squareRoutine(5, results[RC_AUTO]);
+        } else {
+          moveVehicle(MIN_ACC_OUT);
+        }
+      }
+    }
+  }
+
+  if (RC_Done[RC_TURN]) {
+    steer(results[RC_TURN]);
+  }

   /* 5th pulse is rudder (position 3 on receiver; controlled by Left left/right joystick on transmitter)
     Not used */
-  //    results[RC_RDR] = (results[RC_RDR] > MIDDLE? HIGH: LOW);  // could be analog
-  //    Serial.println(results[RC_RDR]);
-  //    if (results[RC_RDR] >= HubAtZero)
-  //        HubSpeed_kmPh = 0;
-  //    else
-  //        HubSpeed_kmPh = HubSpeed2kmPh / results[RC_RDR];
-
-  //  Serial.println("");  // New line
+  // if (RC_Done[RC_RDR]) {
+  //   results[RC_RDR] = (results[RC_RDR] > MIDDLE? HIGH: LOW);  // could be analog
+  //   if (results[RC_RDR] >= HubAtZero)
+  //     HubSpeed_kmPh = 0;
+  //   else
+  //     HubSpeed_kmPh = HubSpeed2kmPh / results[RC_RDR];
+  // }
+
   return 0x00;
 }
 /*---------------------------------------------------------------------------------------*/
@@ -1148,49 +1213,49 @@
     Calibration will block any response to controls; there will be no turning or movemnet during calibration.
     Angle sensors can drift, and should periodically be zeroed.
 */
-void CalibrateTurnAngle(int count, int pause)
-{
-  int totalRight = 0;
-  int totalLeft = 0;
-  int i, left, right;
-  for (i = 0; i < count; i++)
-  {
-    totalRight += analogRead(A2);
-    totalLeft += analogRead(A3);
-    delay(pause);
-  }
-  right = totalRight / count;
-  left  = totalLeft  / count;
-  // Only recalibrate when instruments are reasonable
-  // Do not make garbage readings the new normal.
-  if (RIGHT_MIN_COUNT <= right && right <= RIGHT_MAX_COUNT)
-  {
-    RightStraight_A2 = right;
-    Right_Min_Count = RightStraight_A2 - 60;   // 60 counts is 20 degrees
-    Right_Max_Count = RightStraight_A2 + 60;
-  }
-  else
-  {
-    RightStraight_A2 = RIGHT_MIN_COUNT + (RIGHT_MAX_COUNT - RIGHT_MIN_COUNT) / 2 ;
-    Right_Min_Count = RIGHT_MIN_COUNT;
-    Right_Max_Count = RIGHT_MAX_COUNT;
-  }
-  if  (LEFT_MIN_COUNT  <= left  && left  <= LEFT_MAX_COUNT)
-  {
-    LeftStraight_A3  = left;
-    Left_Min_Count  = LeftStraight_A3  - 60;
-    Left_Max_Count  = LeftStraight_A3  + 60;
-  }
-  else
-  {
-    LeftStraight_A3  = LEFT_MIN_COUNT + (LEFT_MAX_COUNT - LEFT_MIN_COUNT) / 2 ;
-    Left_Min_Count = LEFT_MIN_COUNT;
-    Left_Max_Count = LEFT_MAX_COUNT;
-  }
-  //    Serial.print("\tCALIBRATE: Left Straight\t"); Serial.print(LeftStraight_A3);
-  //    Serial.print("\tRight Straight\t"); Serial.println(RightStraight_A2);
-  old_turn_degx1000 = 0; // straight
-}
+//void CalibrateTurnAngle(int count, int pause)
+//{
+//  int totalRight = 0;
+//  int totalLeft = 0;
+//  int i, left, right;
+//  for (i = 0; i < count; i++)
+//  {
+//    totalRight += analogRead(A2);
+//    totalLeft += analogRead(A3);
+//    delay(pause);
+//  }
+//  right = totalRight / count;
+//  left  = totalLeft  / count;
+//  // Only recalibrate when instruments are reasonable
+//  // Do not make garbage readings the new normal.
+//  if (RIGHT_MIN_COUNT <= right && right <= RIGHT_MAX_COUNT)
+//  {
+//    RightStraight_A2 = right;
+//    Right_Min_Count = RightStraight_A2 - 60;   // 60 counts is 20 degrees
+//    Right_Max_Count = RightStraight_A2 + 60;
+//  }
+//  else
+//  {
+//    RightStraight_A2 = RIGHT_MIN_COUNT + (RIGHT_MAX_COUNT - RIGHT_MIN_COUNT) / 2 ;
+//    Right_Min_Count = RIGHT_MIN_COUNT;
+//    Right_Max_Count = RIGHT_MAX_COUNT;
+//  }
+//  if  (LEFT_MIN_COUNT  <= left  && left  <= LEFT_MAX_COUNT)
+//  {
+//    LeftStraight_A3  = left;
+//    Left_Min_Count  = LeftStraight_A3  - 60;
+//    Left_Max_Count  = LeftStraight_A3  + 60;
+//  }
+//  else
+//  {
+//    LeftStraight_A3  = LEFT_MIN_COUNT + (LEFT_MAX_COUNT - LEFT_MIN_COUNT) / 2 ;
+//    Left_Min_Count = LEFT_MIN_COUNT;
+//    Left_Max_Count = LEFT_MAX_COUNT;
+//  }
+//  //    Serial.print("\tCALIBRATE: Left Straight\t"); Serial.print(LeftStraight_A3);
+//  //    Serial.print("\tRight Straight\t"); Serial.println(RightStraight_A2);
+//  old_turn_degx1000 = 0; // straight
+//}
 /*---------------------------------------------------------------------------------------*/
 /*======================ReadTurnAngle======================*/
 int TurnAngle_degx10()
@@ -1254,6 +1319,7 @@
   return new_turn_degx10;
 }
 /*---------------------------------------------------------------------------------------*/
+// @ToDo: Is this a work in progress?
 void newThrottlePID(){

 }


Completed MorseAdvanced (tried using hashtables and PROGMEM, but couldn't get either to work on my rig)

--- people/mikewesthad/Week4/Arduino/MorseAdvanced/MorseAdvanced.ino
+++ people/mikewesthad/Week4/Arduino/MorseAdvanced/MorseAdvanced.ino
@@ -1,80 +1,125 @@
+// Explanation of International Morse Code from: http://en.wikipedia.org/wiki/Morse_code
+//  Dot is basic unit of time
+//  Dash is three dits
+//  Space between dots and dashes within characters is one dot
+//  Space between letters is 3 dots
+//  Space between words is 7 dots

-float ditLength;
-float dotLength;

-//A:('.-')
-//B:('-...'),
-//C:('-.-.'),
-//D:('-..'),
-//E: ('.'),
-//F: ('..-.'),
-//G: ('--.'),
-//H: ('....'),
-//I: ('..'),
-//J: ('.---'),
-//K: ('-.-'),
-//L: ('.-..'),
-//M: ('--'),
-//N: ('-.'),
-//O: ('---'),
-//P: ('.--.'),
-//Q: ('--.-'),
-//R: ('.-.'),
-//S: ('...'),
-//T: ('-'),
-//U: ('..-'),
-//V: ('...-'),
-//W: ('.--'),
-//X: ('-..-'),
-//Y: ('-.--'),
-//Z: ('--..'),
-//0: ('-----'),
-//1: ('.----'),
-//2: ('..---'),
-//3: ('...--'),
-//4: ('....-'),
-//5: ('.....'),
-//6: ('-....'),
-//7: ('--...'),
-//8: ('---..'),
-//9: ('----.')
+// These units are in seconds
+#define DOT_LENGTH 0.25;
+float dotLength = DOT_LENGTH;
+float dashLength = 3 * DOT_LENGTH;
+
+String message = "Calibration Calibration This Better Get Picked Up By openFrameworks.  EOM";
+
+int led = 13;
+

 void setup() {
-  // put your setup code here, to run once:
-  Serial.begin(9600);
-  Serial.println(convertCharToUpper('a'));
-  Serial.println(convertCharToUpper('m'));
-  Serial.println(convertCharToUpper('0'));
-  Serial.println(convertCharacterToMorse('A'));
-  Serial.println(convertCharacterToMorse('A'));
+  pinMode(led, OUTPUT);
+
+  // Loop through each letter of the message
+  for (int i=0; i<message.length(); i++) {
+
+    // Get the current character
+    char c = message[i];
+
+    // Convert it to morse
+    String morseString = internationalMorse(c);
+
+    // Process the morse string to the LED
+    processMorseToLED(morseString);
+
+    // Hacky solution to the problem of determining when to signal a space between letters
+    //   If the current character is not a space AND
+    //   If there is another character left in the string AND
+    //   The next character is not a space
+    //      Then send a signal to indicate a space between letters
+    if ((i+1<message.length()) && (message[i]!=' ') && (message[i+1]!=' ')) {
+        processMorseToLED("   "); // Space between letters is equal to three dots
+    }
+  }
+}
+
+void processMorseToLED(String morse) {
+  for (int i=0; i<morse.length(); i++) {
+    char c = morse[i];
+    if (c == '.') {
+      digitalWrite(led, HIGH);
+      delay(dotLength * 1000.0);
+    }
+    else if (c == '-') {
+      digitalWrite(led, HIGH);
+      delay(dashLength * 1000.0);
+    }
+    else if (c == ' ') {
+      digitalWrite(led, LOW);
+      delay(dotLength * 1000.0);
+    }
+  }
+
+}
+
+// Given a char, c, return the uppercase version (if c is alphabetical)
+//   Lower Case Letters a-z are from 97 to 122
+//   Upper Case Letters are from 65 to 90
+//   Converting to upper case then just requires subtacting 32
+char convertCharToUpper(char c) {
+  if (c >= 97 && c <= 122) c -= 32;
+  return c;
+}
+
+// Given an alphanumeric char (or space), c, return a string of morse code where:
+//  a dot is represented by '.'
+//  a dash is represented by '-'
+//  the gap between dots and dashes is represented by ' '
+//  a space between words is represented by '       '
+// NOTE: all other chars will return an empty string
+String internationalMorse(char c) {
+  c = convertCharToUpper(c);
+  if (c == 'A')      return ". -";
+  else if (c == 'B') return "- . . .";
+  else if (c == 'C') return "- . - .";
+  else if (c == 'D') return "- . .";
+  else if (c == 'E') return ".";
+  else if (c == 'F') return ". . - .";
+  else if (c == 'G') return "- - .";
+  else if (c == 'H') return ". . . .";
+  else if (c == 'I') return ". .";
+  else if (c == 'J') return ". - - -";
+  else if (c == 'K') return "- . -";
+  else if (c == 'L') return ". - . .";
+  else if (c == 'M') return "- -";
+  else if (c == 'N') return "- .";
+  else if (c == 'O') return "- - -";
+  else if (c == 'P') return ". - - .";
+  else if (c == 'Q') return "- - . -";
+  else if (c == 'R') return ". - .";
+  else if (c == 'S') return ". . .";
+  else if (c == 'T') return "-";
+  else if (c == 'U') return ". . -";
+  else if (c == 'V') return ". . . -";
+  else if (c == 'W') return ". - -";
+  else if (c == 'X') return "- . . -";
+  else if (c == 'Y') return "- . - -";
+  else if (c == 'Z') return "- - . .";
+  else if (c == '1') return ". - - - -";
+  else if (c == '2') return ". . - - -";
+  else if (c == '3') return ". . . - -";
+  else if (c == '4') return ". . . . -";
+  else if (c == '5') return ". . . . .";
+  else if (c == '6') return "- . . . .";
+  else if (c == '7') return "- - . . .";
+  else if (c == '8') return "- - - . .";
+  else if (c == '9') return "- - - - .";
+  else if (c == '0') return "- - - - -";
+  else if (c == ' ') return "       ";
+  else               return "";
 }

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

-int convertCharacterToMorse(char c) {
-  c = convertCharToUpper(c);
-
-  // Upper Case Letters A-Z
-  if (c >= 65 and c <= 90) {
-
-  }
-
-  return int(c);
-}
-
-
-// Given a char, c, return the uppercase version (if c is alphabetical)
-char convertCharToUpper(char c) {
-  // Lower Case Letters a-z are 97-122
-  if (c >= 97 && c <= 122) {
-    c -= 32;
-  }
-  return c;
-}
-
-
-


Use LEDPIN

Use LEDPIN

--- serial_com_test/arduinio/serial_blink_test/serial_blink_test.ino
+++ serial_com_test/arduinio/serial_blink_test/serial_blink_test.ino
@@ -2,7 +2,7 @@

 void setup() {
   Serial.begin(9600);
-  pinMode(13, OUTPUT);
+  pinMode(LEDPIN, OUTPUT);
 }

 void loop() {


Make same as in library impl

Make same as in library impl

--- tests/loopback/EchoEsp8266_standalone/EchoEsp8266_standalone.ino
+++ tests/loopback/EchoEsp8266_standalone/EchoEsp8266_standalone.ino
@@ -47,10 +47,10 @@
       byte buf[128];
       int qty = client.available();
       if (qty) {
-        qty = client.read((uint8_t*)buf, qty);
+        yield();
+        qty = client.readBytes((uint8_t*)buf, qty);
         yield();
         qty = client.write((const uint8_t*)buf, qty);
-        yield();
         draw('.');
       }
       yield();


first cut at adding alarm set via serial

--- NeoPixelNightLight/NeoPixelNightLight.ino
+++ NeoPixelNightLight/NeoPixelNightLight.ino
@@ -1,4 +1,4 @@
-//#define DEBUG
+#define DEBUG
 #include <EEPROM.h>

 // RTC
@@ -82,21 +82,27 @@
 #define BACKLIGHT_MODE 0
 #define CLOCK_MODE  1
 #define FADING_BACKLIGHT_MODE 2
-#define NIGHTLIGHT_MODE 3
+#define ALARM_ENTER 3
+#define NIGHTLIGHT_MODE 4
+char *modes[] = {"Backlight", "Clock", "Fader", "AlarmEnter", "Nightlight"};

 #define MODE_SWITCH_PIN 10
 int mode = CLOCK_MODE; // BACKLIGHT_MODE;
 char s[200];

+DateTime compileTime;
 DateTime wakeTime = DateTime( 2016,1,1, // ignore y,m,d
                               5,45); // 5:45am

-#define MODE_INDEX 0
+// EEPROM indexes
+const int MODE_INDEX = 0;
+const int WAKE_INDEX = (MODE_INDEX+sizeof(mode));

 /*******************************************************************************
 *******************************************************************************/
 void setup() {
-
+  compileTime = DateTime(F(__DATE__), F(__TIME__));
+
 #ifndef ESP8266
   while (!Serial); // for Leonardo/Micro/Zero
 #endif
@@ -106,22 +112,40 @@
   pinMode(MODE_SWITCH_PIN,INPUT_PULLUP);

   EEPROM.get(MODE_INDEX,mode);
-
   Serial.print(F("Got mode from eeprom ") );
   Serial.println(mode);
-
+  if ( mode < 0 )
+    mode = 0;
+
+  int32_t wakeUnixTime;
+  EEPROM.get(WAKE_INDEX,wakeUnixTime);
+  Serial.print(F("Got wakeTime from eeprom ") );
+  Serial.println(wakeUnixTime);
+  if ( wakeUnixTime >= 0 )
+    wakeTime = DateTime(wakeUnixTime);
+
   rtcSetup();
   neoPixelSetup();

 }
-
+bool rtcRunning = false;
 bool pressed = false;
 bool forceChange = false;
+
+DateTime getCurrent()
+{
+  if ( rtcRunning )
+    return rtc.now();
+  else
+    return compileTime.unixtime() + millis()/1000;
+}
+
 /*******************************************************************************
 *******************************************************************************/
 void loop() {

-  current = rtc.now();
+  current = getCurrent();
+  bool next = false;

   switch ( mode )
   {
@@ -134,28 +158,34 @@
     case FADING_BACKLIGHT_MODE:
       fadingBacklight(current, forceChange);
       break;
+    case ALARM_ENTER:
+      if ( enterAlarm(forceChange) )
+        next = true;
+      break;
     case NIGHTLIGHT_MODE:
       nightlight(current, forceChange);
       break;
   }
   forceChange = false;

-  if ( digitalRead(MODE_SWITCH_PIN) == LOW )
-  {
-    if ( !pressed )
+  if ( digitalRead(MODE_SWITCH_PIN) == LOW  || next )
+  {
+    if ( !pressed || next )
     {
+      next = false;
       pressed = true;
       mode++;
-      if ( mode > NIGHTLIGHT_MODE )
+      if ( mode >= sizeof(modes)/sizeof(char*) )
         mode = BACKLIGHT_MODE;

       forceChange = true;
       printTime(current);
       Serial.print(F(" Switching mode to "));
-      Serial.println(mode);
+      Serial.println(modes[mode]);
       EEPROM.put(MODE_INDEX,mode);

       clearPixels();
+      strip.show();
     }
   }
   else
@@ -170,6 +200,62 @@
 {
   for ( int i = 0; i < NEOPIXEL_LEDS; i++ )
     strip.setPixelColor(i,0);
+}
+
+bool prompted = false;
+int currentPixel = 0;
+
+bool enterAlarm(bool forceChange)
+{
+  if ( !prompted || forceChange)
+  {
+    clearPixels();
+    strip.show();
+    Serial.print(F("Current wake time is "));
+    printTime(wakeTime);
+    Serial.println("");
+    Serial.println(F("Enter time to wake in 24 hour clock HH,MM"));
+    prompted = true;
+
+  }
+  if ( millis() % 100 == 0 )
+  {
+      strip.setPixelColor(currentPixel,0);
+      strip.setPixelColor(NEOPIXEL_LEDS-currentPixel++,0);
+      if ( currentPixel >= NEOPIXEL_LEDS )
+        currentPixel = 0;
+      strip.setPixelColor(currentPixel,Wheel(colorValue));
+      strip.setPixelColor(NEOPIXEL_LEDS-currentPixel,Wheel(colorValue));
+      strip.show();
+      delay(5);
+  }
+
+  // if there's any serial available, read it:
+  if (Serial.available() > 0) {
+
+    // look for the next valid integer in the incoming serial stream:
+    int hours = Serial.parseInt();
+    // do it again:
+    int minutes = Serial.parseInt();
+    while (Serial.available() > 0) {
+      Serial.read(); // pull off rest
+    }
+    if ( hours >= 0 && hours < 24 && minutes >=0 && minutes < 60 )
+    {
+      wakeTime = DateTime( 2016,1,1, // ignore y,m,d
+                              hours,minutes);
+      printTime(wakeTime);
+      Serial.println(F(" is new waketime"));
+      EEPROM.put(WAKE_INDEX,wakeTime.unixtime());
+    }
+    else
+      Serial.println(F("Invalid time.  Must be 0-23 for hour and 0-59 for minute"));
+
+    prompted = false;
+
+    return true;
+  }
+  return false;
 }
 /*******************************************************************************
 *******************************************************************************/
@@ -240,14 +326,17 @@
     prevHours = newHours;
   }

-  DEBUG_PRINT( F("Wakey current is "));
-  DEBUG_PRINT( currentMin );
-  DEBUG_PRINT( F(" and wakey is "));
-  DEBUG_PRINT( wakeyMin );
-  DEBUG_PRINT( F(" and diffMin is "));
-  DEBUG_PRINT( diffMin );
-  DEBUG_PRINT( F(" and show is "));
-  DEBUG_PRINTLN( show );
+  if ( millis() % 1000 == 0 )
+  {
+    DEBUG_PRINT( F("Wakey - current: "));
+    DEBUG_PRINT( (int)wakeyMin );
+    DEBUG_PRINT( F("min - "));
+    DEBUG_PRINT( (int)currentMin );
+    DEBUG_PRINT( F("min and diff is "));
+    DEBUG_PRINT( (int)diffMin );
+    DEBUG_PRINT( F("min and show is "));
+    DEBUG_PRINTLN( show );
+  }

   if ( show )
     strip.show();
@@ -367,7 +456,7 @@
   if (! rtc.isrunning()) {
     Serial.println(F("RTC is NOT running!"));
     // following line sets the RTC to the date & time this sketch was compiled
-    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
+    rtc.adjust(compileTime);
   }
 }


Update KP_Password.ino

Update KP_Password.ino

--- Examples/KP_Password/KP_Password.ino
+++ Examples/KP_Password/KP_Password.ino
@@ -1,3 +1,5 @@
+// Creator: Andrew Mascolo
+
 #include <OnewireKeypad.h>
 #include <Password.h>

@@ -37,19 +39,16 @@
         default: password.append(Key);
       }
     }
-  }
-  else if (KState == HELD) {
+  } else if (KState == HELD) {
     Serial << "Key:" << KP.Getkey() << " being held\n";
   }
 }

-void checkPassword()
-{
+void checkPassword() {
   if (password.evaluate()) {
     Serial.println("Success");
     //Add code to run if it works
-  }
-  else {
+  } else {
     Serial.println("Wrong");
     //add code to run if it did not work
   }


Update MRLCommOculus2.ino

Update MRLCommOculus2.ino

--- home/Alessandruino/MRLCommOculus2.ino
+++ home/Alessandruino/MRLCommOculus2.ino
@@ -1275,6 +1275,7 @@
     		append(ay);
     		append(ax2);
     		append(headingint);
+    		append(accel.testConnection());
     		sendMsg();
     		cnt = 0;
 	}


Made functions inline to reduce inter-bit delays

--- SimpleNeopixelDemo/SimpleNeopixelDemo.ino
+++ SimpleNeopixelDemo/SimpleNeopixelDemo.ino
@@ -12,7 +12,14 @@
 // These values depend on which pin your string is connected to and what board you are using
 // More info on how to find these at http://www.arduino.cc/en/Reference/PortManipulation

-// These values are for digital pin 8 on an Arduino Yun or digital pin 12 on a DueMilinove/UNO
+// These values are for the pin that connects to the Data Input pin on the LED strip. They correspond to...
+
+// Arduino Yun:     Digital Pin 8
+// DueMilinove/UNO: Digital Pin 12
+// Arduino MeagL    PWM Pin 4
+
+// You'll need to look up the port/bit combination for other boards.
+
 // Note that you could also include the DigitalWriteFast header file to not need to to this lookup.

 #define PIXEL_PORT  PORTB  // Port of the pin the pixels are connected to
@@ -43,7 +50,7 @@
 // Actually send a bit to the string. We must to drop to asm to enusre that the complier does
 // not reorder things and make it so the delay happens in the wrong place.

-void sendBit( bool bitVal ) {
+inline void sendBit( bool bitVal ) {

     if (  bitVal ) {				// 0 bit

@@ -98,7 +105,7 @@
 }

-void sendByte( unsigned char byte ) {
+inline void sendByte( unsigned char byte ) {

     for( unsigned char bit = 0 ; bit < 8 ; bit++ ) {

@@ -128,7 +135,7 @@

 }

-void sendPixel( unsigned char r, unsigned char g , unsigned char b )  {
+inline void sendPixel( unsigned char r, unsigned char g , unsigned char b )  {

   sendByte(g);          // Neopixel wants colors in green then red then blue order
   sendByte(r);
@@ -332,13 +339,13 @@

 void setup() {

-  ledsetup();
+  ledsetup();

 }

 void loop() {
-
+
   // Some example procedures showing how to display to the pixels:
   colorWipe(255, 0, 0, 0); // Red
   colorWipe(0, 255, 0, 0); // Green


Refactoring

Refactoring

--- all/all.ino
+++ all/all.ino
@@ -18,22 +18,22 @@
 bool firstRun = false;

 // Patterns
-#define RAINBOW 1
-#define RAINBOW_2 2
-#define RAINBOW_3 3
+#define NIGHT_SPARKLES 1
+#define BEAUTIFUL_SPARKLES 2
+#define SINGLE_COLOR_SPARKLES 3
 #define DISCO_BARBER_1 4
 #define DISCO_BARBER_2 5
 #define JUGGLE 6
 #define NEW 7

 int maxPatternId = 6;
-int rotationInMillseconds = 20000; // 20 seconds for production
+int rotationInMillseconds = 2000; // 20 seconds for production

-//int patternId = 3;
 //bool holdPattern = false;
 bool holdPattern = true;
-int patternId = RAINBOW;
+//int patternId = 2;
+int patternId = SINGLE_COLOR_SPARKLES;

 const int ledPin = 13;
 const int led = 13;
@@ -50,45 +50,45 @@
 int numberOfSparkles = 1;
 int increasing = true;

-void confetti() {
-
-  if (patternId == RAINBOW) {
-    fadeToBlackBy(leds, NUM_LEDS, 180);
-  } else {
-    fadeToBlackBy(leds, NUM_LEDS, 200);
-  }
-
-  if (numberOfSparkles < 80 && increasing) {
-    numberOfSparkles += 1;
-  } else if (numberOfSparkles > 5) {
-    numberOfSparkles -= 1;
+int upAndDownBy(int value, int difference) {
+  if (value < 80 && increasing) {
+    value += difference;
+  } else if (value > 5) {
+    value -= difference;
     increasing = false;
   } else {
     increasing = true;
-    numberOfSparkles += 1;
+    value += difference;
   }
+  return value;
+}

-  int pos;
+void nightSparkles() {
+  fadeToBlackBy(leds, NUM_LEDS, 180);
+  numberOfSparkles = upAndDownBy(numberOfSparkles, 1);
+  for (int i = 0; i < 20; i++) {
+    int pos = random16(NUM_LEDS);
+    leds[pos] = CHSV(hue, 180, 255);
+  }
+  for (int i = 0; i < numberOfSparkles * 4; i++) {
+    leds[random16(NUM_LEDS)] += CHSV(hue, 200, 20);
+  }
+  hue = hue + 1;
+}

-  if (patternId == RAINBOW) {
-    for (int i = 0; i < 20; i++) {
-      pos = random16(NUM_LEDS);
-      leds[pos] = CHSV(hue, 180, 255);
-    }
-  }
-
+void sparkles() {
+  fadeToBlackBy(leds, NUM_LEDS, 200);
+  numberOfSparkles = upAndDownBy(numberOfSparkles, 1);
   for (int i = 0; i < numberOfSparkles * 4; i++) {
-    pos = random16(NUM_LEDS);
-    if (patternId == RAINBOW) {
-      leds[pos] += CHSV(hue, 200, 20);
-    } else if (patternId == RAINBOW_2) {
+    int pos = random16(NUM_LEDS);
+    if (patternId == BEAUTIFUL_SPARKLES) {
       leds[pos] = CHSV(hue + (pos / 10), 240, 255);
-    } else if (patternId == RAINBOW_3) {
+    } else if (patternId == SINGLE_COLOR_SPARKLES) {
       leds[pos] = CHSV(hue, 240, 255);
     }
   }

-  if (patternId == RAINBOW_2) {
+  if (patternId == BEAUTIFUL_SPARKLES) {
     hue += 10;
   } else {
     hue = hue + 1;
@@ -107,9 +107,9 @@
   if (faderate == 100 || faderate == 200) {
     numdots += 1;
   }
-
+
   fadeToBlackBy(leds, NUM_LEDS, faderate);
-
+
   for ( int i = 0; i < numdots; i++) {
     for ( int j = 0; j < 20; j++) {
       leds[beatsin16(basebeat + i + numdots, 0, NUM_LEDS - 20) + j] += CHSV(curhue, 240, 255); //beat16 is a FastLED 3.1 function
@@ -134,7 +134,7 @@
     allfreq = 3;
     thisphase += 48;
   }
-
+
   hue = hue + 1;                                                // Hue rotation is fun for thiswave.

   for (int k = 0; k < NUM_LEDS - 1; k++) {                                    // For each of the LED's in the strand, set a brightness based on a wave as follows:
@@ -167,8 +167,10 @@
     }
   }

-  if (patternId == RAINBOW || patternId == RAINBOW_2 || patternId == RAINBOW_3) {
-    confetti();
+  if (patternId == NIGHT_SPARKLES) {
+    nightSparkles();
+  } else if (patternId == BEAUTIFUL_SPARKLES || patternId == SINGLE_COLOR_SPARKLES) {
+    sparkles();
   } else if (patternId == DISCO_BARBER_1 || patternId == DISCO_BARBER_2) {
     discoBarber();
   } else if (patternId == JUGGLE) {


Swapped from A4,A5 since those are also mapped to I2C

--- Arduino/Master_Arduino_Metro_BGAs_STBD_SARJs_TRRJs/Master_Arduino_Metro_BGAs_STBD_SARJs_TRRJs.ino
+++ Arduino/Master_Arduino_Metro_BGAs_STBD_SARJs_TRRJs/Master_Arduino_Metro_BGAs_STBD_SARJs_TRRJs.ino
@@ -50,24 +50,27 @@

 Encoder myEnc1A(0, 1);
 Encoder myEnc3A(5, 6);
-// Pins 9, 10 are used by Servos.  Odd issues with Pins 2-4. Pin 13 is nominally used by LED and general guidance from encoder library is to avoid it.
+// Pins 9, 10 are used by Servos.
+// Odd issues with Pins 2-4.
+// Pin 13 is nominally used by LED and general guidance from encoder library is to avoid it.
 Encoder myEnc1B(7, 8);
 Encoder myEnc3B(11, 12);

 // Per here, Analog pins on Metro M0 are also digtial IO. https://learn.adafruit.com/adafruit-metro-m0-express-designed-for-circuitpython/pinouts
 // From here, A1 is digital 15, A2 is 16, A3 is 17, A4 is 18, A5 is 19. http://www.pighixxx.net/portfolio_tags/pinout-2/#prettyPhoto[gallery1368]/0/

-Encoder myEncPSARJ(15, 16); // 15,16 is A2, A3
-Encoder myEncSSARJ(17, 18); // 17,18 is A4 ,A5
+Encoder myEncPSARJ(14, 15); // 14,15 is A0, A1
+Encoder myEncSSARJ(16, 17); // 16,17 is A2 ,A3
+// Also avoiding A4, A5 as these are coupled to the I2C SLA, SCA pins via the Motor Shield (for backward compatibility with older Ards).

 void setup() {

-  // Set some pins to high, just for convenient connection to power Hall Effect Sensors
-pinMode(A0, OUTPUT);
-digitalWrite(A0, HIGH);
-pinMode(A1, OUTPUT);
-digitalWrite(A1, HIGH);
+  // Set some pins to high, just for convenient connection to power Hall Effect Sensors - can't, per above use of these pins
+//pinMode(A0, OUTPUT);
+//digitalWrite(A0, HIGH);
+//pinMode(A1, OUTPUT);
+//digitalWrite(A1, HIGH);
 //pinMode(A2, OUTPUT);
 //digitalWrite(A2, HIGH);


More Clean code

More Clean code

--- SpeakersControl.ino
+++ SpeakersControl.ino
@@ -196,13 +196,18 @@
   serverRich.getWeatherHandler = getWeather;
 }

-void setup(void)
-{
-  system_update_cpu_freq(SYS_CPU_160MHZ);
+void initRelayModules()
+{
   pinMode(SRD_SRC_PIN, OUTPUT);
   pinMode(SRD_POWER_PIN, OUTPUT);
   digitalWrite(SRD_SRC_PIN, HIGH);//select default source
   digitalWrite(SRD_POWER_PIN, HIGH);// power on !!
+}
+
+void setup(void)
+{
+  system_update_cpu_freq(SYS_CPU_160MHZ);
+  initRelayModules();

   Serial.begin(115200);
   Serial.println("");
@@ -212,8 +217,6 @@
   initLed();
   initRichServer();

-
-
   if (MDNS.begin("esp8266")) {
     Serial.println("MDNS responder started");
   }


Oops. Fixed a typo

Oops. Fixed a typo

--- src/Deutsch/NOKO/NOKO.ino
+++ src/Deutsch/NOKO/NOKO.ino
@@ -1,4 +1,4 @@
-   ,m/* NOKO V1.0 13.04.2017 - Nikolai Radke
+ /* NOKO V1.0 13.04.2017 - Nikolai Radke
  *
  * Sketch for NOKO-Monster - Deutsch
  * NOTE: Does NOT run without the Si4703 Radio Module!