Okay Paul, you've got my attention!
I had no idea that String class was problematic, or I would never have used it. It's quite hard to feel your way around a bug when it takes several hours to manifest.
Here's the Arduino code in FULL: I'll post the servo handler loop in the next post, as the full sketch exceeds the forum's character limit
// MMM_matrix_Plotter3 (pairs with same-named VB)
// tjn 16/10/2012
//
// Status: Interleaving X, Y1, Y2 and Z(B)
// Note: 78 Steps/mm using B servo in Full-wave mode, slack = 36
#include <Wire.h>
#include <iox.h>
// Setup pins (0 and 1 reserved for serial I/O)
byte xctrl1 = 2; // X-Axis geartrain control 1
byte xctrl2 = 3; // X-Axis geartrain control 2
byte yctrl1 = 4; // South-Y geartrain control 1
byte yctrl2 = 5; // South-Y geartrain control 2
byte y2ctrl1 = 7; // North-Y geartrain control 1
byte y2ctrl2 = 8; // North-Y geartrain control 2
byte xypower = 12; // XY stepper supply
byte lpower = 13; // Laser logic supply
byte xsensors = 15; // X-buffer switches
byte ysensors = 14; // Y-buffer switches
byte scaleFactor = 1;
byte offset1, offset2, space, cut, gap;
byte xStepIdx, y1StepIdx, y2StepIdx, zStepIdx;
int xSteps, y1Steps, y2Steps, zSteps, totalSteps, subSteps, bitIndex, laserTime, tMult;
int xStore, yStore, zStore, pixCount, iterations, dotCount, max1, max2, iTimeIdx = 0;
String inStr = ""; // Hold incoming data
boolean stringComplete = false; // Data complete flag
boolean xStop = false;
boolean yStop = false;
boolean xDir = false; // TRUE = Clockwise
boolean yDir = false;
boolean zDir = false;
boolean oxDir = false;
boolean oyDir = false;
boolean ozDir = false;
boolean laserOn = false;
long MsDelay;
unsigned char twoWire[] = {
B01,B11,B10,B00}; // 2-Wire sequence for X/Y steppers
word fullWaveB[] = { // Full-wave Slave stepper motor sequence
0x6000,0x2010,0x18,0x4008};
word lampState = 0x0000;
double m, mx, my1, my2, mz, x, y1, y2, z;
void setup() {
Serial.begin(9600); // was 38400, but froze
inStr.reserve(40); // easily enough for longest command (ie.x7000y7000z1404o13s0c19g6i270o14)
pinMode(xctrl1, OUTPUT); // X stepper pin1
pinMode(xctrl2, OUTPUT); // X stepper pin2
pinMode(yctrl1, OUTPUT); // Y1 stepper pin1
pinMode(yctrl2, OUTPUT); // Y1 stepper pin2
pinMode(y2ctrl1, OUTPUT); // Y2 stepper pin1
pinMode(y2ctrl2, OUTPUT); // Y2 stepper pin2
pinMode(lpower, OUTPUT); // Laser power
pinMode(xypower, OUTPUT); // XY stepper power
pinMode(xsensors, INPUT); // X-buffer switches
pinMode(ysensors, INPUT); // Y-buffer switches
digitalWrite(xypower, LOW); // Power-down XY motors
digitalWrite(lpower,LOW); // Power-down laser
Wire.begin(); // Start 2-wire communications (Arduino as master device)
IOX.device(0x74, 16); // 0x74 is address for Servo A (Pitch)
IOX.write(0x0080, CFGPORT); // P07=INPUT Set ports LOW to make them OUTPUTS
IOX.write(0x0000, INVPORT); // Set slave device invert ports to all NON-INVERT
IOX.write(0x000, OUTPORT); // Power-down Lamp/Fan
Serial.println("OK?");
Serial.flush();
delay(100);
}
void loop() {
if (stringComplete) {
if(inStr.indexOf("x") >=0) xSteps = inStr.substring(inStr.indexOf("x")+1,inStr.indexOf("y")).toInt();
else xSteps = 0; // X Transit
if(inStr.indexOf("y") >=0) {
if(inStr.indexOf("z") >=0) y1Steps = inStr.substring(inStr.indexOf("y")+1,inStr.indexOf("z")).toInt();
else y1Steps = inStr.substring(inStr.indexOf("y")+1).toInt(); // Y Transit
}
else y1Steps = 0;
if(inStr.indexOf("z") >=0) {
if(inStr.indexOf("l") >=0) zSteps = inStr.substring(inStr.indexOf("z")+1,inStr.indexOf("l")).toInt();
else zSteps = inStr.substring(inStr.indexOf("z")+1).toInt(); // Y Transit
}
else zSteps = 0;
if(inStr.indexOf("l") >=0) laserTime = inStr.substring(inStr.indexOf("l")+1).toInt();
else laserTime = 0; // Laser On/Off
if(inStr.indexOf("o") >=0){
laserTime = inStr.substring(inStr.indexOf("l")+1,inStr.indexOf("o")).toInt(); // Laser On Time
offset1 = inStr.substring(inStr.indexOf("o")+1,inStr.indexOf("s")).toInt(); // Offset1
space = inStr.substring(inStr.indexOf("s")+1,inStr.indexOf("c")).toInt(); // Space
cut = inStr.substring(inStr.indexOf("c")+1,inStr.indexOf("g")).toInt(); // Cut
gap = inStr.substring(inStr.indexOf("g")+1,inStr.indexOf("i")).toInt(); // Gap
iterations = inStr.substring(inStr.indexOf("i")+1,inStr.lastIndexOf("o")).toInt(); // Iterations
offset2 = inStr.substring(inStr.lastIndexOf("o")+1).toInt(); // Offset2
}
else {
offset1 = 0;
space = 0;
cut = 0;
gap = 0;
iterations = 0;
offset2 = 0;
}
if (xSteps < 0) xDir = true;
if (xSteps > 0) xDir = false;
if (xSteps == 0) xDir = oxDir;
if (y1Steps < 0) yDir = true;
if (y1Steps > 0) yDir = false;
if (y1Steps == 0) yDir = oyDir;
if (zSteps < 0) zDir = false;
if (zSteps > 0) zDir = true;
if (zSteps == 0) zDir = ozDir;
if (xStop = true && xDir != oxDir) xStop = false;
if (yStop = true && yDir != oyDir) yStop = false;
xSteps = abs(xSteps);
y1Steps = abs(y1Steps);
zSteps = abs(zSteps);
y2Steps = y1Steps;
if (zDir != ozDir) { // Vertical Slack Handler
zSteps += 37; // Z-Slack value (from laser deflection test)
}
totalSteps = max(xSteps, y1Steps);
subSteps = min(xSteps, y1Steps);
m = (double)subSteps/(double)totalSteps;
if (m > 0.7) { // vector splitter/dog-legger to avoid bad harmonics between X&Y
digitalWrite(lpower,LOW);
if (xSteps > y1Steps) {
xStore = xSteps;
yStore = y1Steps;
xSteps = xStore - y1Steps;
y1Steps = 0;
y2Steps = 0;
digitalWrite(xypower, HIGH);
xyzServos();
xSteps = yStore;
y1Steps = yStore;
y2Steps = y1Steps;
}
if (xSteps < y1Steps) {
xStore = xSteps;
yStore = y1Steps;
y1Steps = yStore - xSteps;
xSteps = 0;
digitalWrite(xypower, HIGH);
xyzServos();
xSteps = xStore;
y1Steps = xStore;
y2Steps = y1Steps;
}
// else not used (no adjustment needed when X & Y are equal!
}
if (xSteps != 0 || y1Steps != 0 || zSteps != 0) {
digitalWrite(xypower, HIGH);
xyzServos(); // rem-out while testing
}
else {
if (laserTime == 1) {
digitalWrite(lpower, HIGH); // Laser ON
IOX.write(0x0200, OUTPORT); // Lamp & Fan ON
}
else{
digitalWrite(lpower,LOW); // Laser OFF
IOX.write(0x000, OUTPORT); // Lamp & Fan OFF
}
}
if (xSteps == 0 && y1Steps == 0) { // switch OFF motors on end vector
//digitalWrite(xypower, LOW); // Machine loses registration on power-down!
if (laserTime == 0) IOX.write(0x0000, OUTPORT); // Turn lamp & fan OFF
}
if (xStop == true) Serial.println("X-buffer Hit");
if (yStop == true) Serial.println("Y-buffer Hit");
Serial.println("OK"); // Tell VB Arduino's ready to receive next command
Serial.flush();
inStr = ""; // Clear input string
stringComplete = false;
oxDir = xDir;
oyDir = yDir;
ozDir = zDir;
}
//else{
//Serial.println("OK!"); // Tell VB Arduino's ready to receive next command from vb
//Serial.flush();
//delay(1000);
//}
}
void serialEvent() {
while (Serial.available()) { // get new byte
char inChar = (char)Serial.read();
inStr += inChar; // add to the inStr
if (inChar == '\n') { // Flag if char is vbcrlf
stringComplete = true;
}
}
}
Any ideas/suggestions would be greatly appreciated.