diff --git a/src/firmware/IAD_v2_4_AIO.ino b/src/firmware/IAD_v2_4_AIO.ino new file mode 100644 index 0000000..7f32eff --- /dev/null +++ b/src/firmware/IAD_v2_4_AIO.ino @@ -0,0 +1,479 @@ +#include + +#define Xdir 13 +#define Ydir 12 +#define Zdir 11 + +#define Ybump 32 +#define Xbump 36 +#define AFbump 28 +#define bumpGnd 42 + +/*************************************************************************************** +This is what matters when you change the Step size : change the FoV accordingly +Rest of everything is calculated in terms of steps only +So the GUI needs to take care of step size to um conversion +***************************************************************************************/ +// FoV size. This is in steps. Calcuated as FoV (steps) = FoV (um) / stepSize +// The step size as on 27 June is 198 nm / step +long xFoV = 1843, yFoV = 2323; + +long XMaxStep=260000L, YMaxStep=130000L, ZMaxStep=30000L; +long limitTOZfocus = 31000L,limitToXZero=-250000,limitToYZero=4000; + +// steps to go before stopping +int trayOutNoiseMargin = 50; + +long XcurrStep=0L, YcurrStep=0L, ZcurrStep=0L; +long Ax=0L,Ay=0L,Az=0L,Bx=0L,By=0L,Bz=0L,Cx=0L,Cy=0L,Cz=0L; +long nextZstep = 0, XdeltaZperFoV=0, YdeltaZperFoV=0; +int needtocheckXmovement=0,needtocheckYmovement=0,needtocheckZmovement=0; + +void setup() { + Serial.begin(57600); + // pulse : X,Y,Z :: TX 1,2,3 + Serial1.begin(38400); Serial2.begin(38400); Serial3.begin(38400); + pinMode(Zdir,OUTPUT); pinMode(Ydir,OUTPUT); pinMode(Xdir,OUTPUT); + pinMode(Xbump,INPUT); pinMode(Ybump,INPUT); pinMode(AFbump,INPUT); // The bump switchs + pinMode(bumpGnd,OUTPUT); digitalWrite(bumpGnd,LOW); // this sets the gnd for the bump switches + +} + +void loop() { + + int choice = Serial.read(); + + switch(choice){ + case('T') : digitalWrite(Zdir,LOW); delayMicroseconds(10); doZSteps(1); ZcurrStep=ZcurrStep-1; // T == Z up by 5 counts + break; + case('G') : digitalWrite(Zdir,HIGH); delayMicroseconds(10); doZSteps(1); ZcurrStep=ZcurrStep+1; // G == Z down + break; + case('A') : needtocheckXmovement=1; digitalWrite(Xdir,LOW); delayMicroseconds(10); doXSteps(xFoV/5); XcurrStep=XcurrStep+xFoV; // A == X up by 1 FoV + break; + case('D') : needtocheckXmovement=0; digitalWrite(Xdir,HIGH); delayMicroseconds(10); doXSteps(xFoV/5); XcurrStep=XcurrStep-xFoV; // D == X down by 1 FoV + break; + case('W') : needtocheckYmovement=0; digitalWrite(Ydir,LOW); delayMicroseconds(10); doYSteps(yFoV/5); YcurrStep=YcurrStep+yFoV; // W == Y up + break; + case('S') : needtocheckYmovement=1; digitalWrite(Ydir,HIGH); delayMicroseconds(10); doYSteps(yFoV/5); YcurrStep=YcurrStep-yFoV; // S == Y down + break; + case('J') : XcurrStep = 0; // J == X reset + break; + case('K') : YcurrStep = 0; // K == Y reset + break; + case('L') : ZcurrStep = 0; // L == Z reset + break; + case('B') : gotoXSetStep(getStep()); + break; + case('N') : gotoYSetStep(getStep()); + break; + case('M') : gotoZSetStep(getStep()); + break; + case('I') : Serial1.flush(); Serial.print('X'); Serial.print("#"); Serial.print(XcurrStep); Serial.print("#"); + break; + case('O') : Serial2.flush(); Serial.print('Y'); Serial.print("#"); Serial.print(YcurrStep); Serial.print("#"); + break; + case('P') : Serial3.flush(); Serial.print('Z');Serial.print("#"); Serial.print(ZcurrStep); Serial.print("#"); + break; + + // Set A,B,C - Codes are E,R,Y respectively + case('E') : Ax=XcurrStep; Ay=YcurrStep; Az=ZcurrStep; + break; + case('R') : Bx=XcurrStep; By=YcurrStep; Bz=ZcurrStep; + break; + case('Y') : Cx=XcurrStep; Cy=YcurrStep; Cz=ZcurrStep; + break; + case('U') : + break; + case('Z') : do4ptArea(); + break; + case('X') : + break; + case('C') : // linear scan + doAtoB(); + break; + case('V') : debug(); + break; + case('Q') : gohome(); + break; + case('F') : doFullArea(); + break; + + case('H') : gotoZSetStep(0); + // Signal that ready to AF now + Serial.print("H#"); + break; + case('1') : tray_out(); + break; + case('2') : tray_in(); + break; + case('0') : EEPROM.write(0,0); + break; + case('7') : Serial.print('7'); Serial.print("#"); + break; + case('3') : digitalWrite(Zdir,HIGH); delayMicroseconds(10); Serial3.print("X"); ZcurrStep=ZcurrStep+1; + break; + case('5') : digitalWrite(Zdir,LOW); delayMicroseconds(10); Serial3.print("X"); ZcurrStep=ZcurrStep-1; + break; + case('.'): // this is the travel sync option. First go 20 k steps and note time + Serial.print('0'); Serial.print("#"); gotoXSetStep(XcurrStep+20000); Serial.print('1'); Serial.print("#"); + Serial.print('2'); Serial.print("#"); gotoXSetStep(XcurrStep-20000); Serial.print('3'); Serial.print("#"); + Serial.print('4'); Serial.print("#"); gotoYSetStep(YcurrStep+20000); Serial.print('5'); Serial.print("#"); + Serial.print('6'); Serial.print("#"); gotoYSetStep(YcurrStep-20000); Serial.print('7'); Serial.print("#"); + default : break; + } +} + + +void doXSteps(long num) { while (num > 0 ) { + if( (needtocheckXmovement==1) && (digitalRead(Xbump) == LOW)) { XcurrStep=0; return;} // DO NOT MOVE IF ALREADY AT LIMIT + Serial1.print("U"); num--; } } + +void doYSteps(long num) { while (num > 0 ) { + if( (needtocheckYmovement==1) && (digitalRead(Ybump) == LOW)) { YcurrStep=0; return;} // DO NOT MOVE IF ALREADY AT LIMIT + Serial2.print("U"); num--; } } + +void doZSteps(long num) { while (num > 0 ) { + if( (needtocheckZmovement==1) && (digitalRead(AFbump) == LOW)) { ZcurrStep=0; return;} // DO NOT MOVE IF ALREADY AT LIMIT + Serial3.print("@"); num--; } } + +long getStep() +{ + long index = 0, inpStep[7]={0,0,0,0,0,0,0}, invalidInput = 0; + long setStep = 0L; + + + for(index=0; index<8; index++ ) + { + while ( Serial.available() < 1 ); + inpStep[index] = Serial.read() - 48; + } + + // DISCARD first byte : MATLAB sends the terminator character there. We need it since if we turn it off, MATALB won't read the Tx from this arduino + // ALSO igmore the second byte : that's the sign symbol + setStep = (inpStep[2]*100000) + (inpStep[3]*10000) + (inpStep[4]*1000) + (inpStep[5]*100) + (inpStep[6]*10) + (inpStep[7]*1) + 0L ; + + // check what sign was sent. If it was anything other than a '-' then dont worry + if (inpStep[1] + 48 == '-' ) { setStep = setStep*(-1); } + + return setStep; +} + +void gotoXSetStep(long XsetStep) +{ + if(XsetStep > XMaxStep) {XsetStep=XMaxStep;} + long stepstodo = abs(XsetStep - XcurrStep) / 5; + + if (XsetStep > XcurrStep) + { needtocheckXmovement=1 ; + digitalWrite(Xdir,LOW); delayMicroseconds(10); XcurrStep=XsetStep; doXSteps( stepstodo ); } + + if (XsetStep < XcurrStep) + { needtocheckXmovement=0 ; + digitalWrite(Xdir,HIGH); delayMicroseconds(10); XcurrStep=XsetStep; doXSteps( stepstodo ); } + +} + +void gotoYSetStep(long YsetStep) +{ + if(YsetStep > YMaxStep) {YsetStep = YMaxStep;} + long stepstodo = abs(YsetStep - YcurrStep) / 5; + + if (YsetStep > YcurrStep) + { needtocheckYmovement=0 ; + digitalWrite(Ydir,LOW); delayMicroseconds(10); YcurrStep=YsetStep; doYSteps( stepstodo ); } + + if (YsetStep < YcurrStep) + { + needtocheckYmovement=1 ; + digitalWrite(Ydir,HIGH); delayMicroseconds(10); YcurrStep=YsetStep; doYSteps( stepstodo ); } + +} + +void gotoZSetStep(long ZsetStep) +{ + //if(ZsetStep > ZMaxStep) {ZsetStep = ZMaxStep;} + long stepstodo = abs(ZsetStep - ZcurrStep) / 5; + + if (ZsetStep > ZcurrStep) + { needtocheckZmovement=0 ; + digitalWrite(Zdir,HIGH); delayMicroseconds(10); ZcurrStep=ZsetStep; doZSteps( stepstodo ); } + + if (ZsetStep < ZcurrStep) + { + needtocheckZmovement=1 ; + digitalWrite(Zdir,LOW); delayMicroseconds(10); ZcurrStep=ZsetStep; doZSteps( stepstodo ); } + +} + +void tray_out () +{/* + // if already tray out then skip this + //if (EEPROM.read(0) == 1) { return; } + // var to even out electric noise + int Xnoise=0, Ynoise=0, Znoise=0; + // x & y out + digitalWrite(Xdir,HIGH); digitalWrite(Ydir,HIGH); digitalWrite(Zdir,HIGH); delayMicroseconds(20); + + while ( Znoise < trayOutNoiseMargin ) + { + Serial1.print("U"); + if (digitalRead(AFbump) == HIGH) { Znoise++; } + } + + digitalWrite(Zdir,LOW); + for (int i=0; i<2000;i++) + { Serial1.print("U"); } + + + while ( Xnoise < trayOutNoiseMargin ) + { + Serial2.print("U"); + if (digitalRead(Xbump) == HIGH) { Xnoise++; } + } + + for (int i=0; i<5000;i++) + { Serial2.print("U"); } + + while ( Ynoise < trayOutNoiseMargin ) + { + Serial3.print("U"); + if (digitalRead(Ybump) == LOW) { Ynoise++; } + } + +// if all done, store this in EEPROM +//EEPROM.write(0,1); +*/ + +Serial.println("Tray out"); +} + +void tray_in() +{ +// assuming that it is called only after tray_out + // gotoXSetStep(125000); + //gotoYSetStep(-40000); + // gotoZSetStep(-3000); + + // now that we're at position, reset counts + //XcurrStep=0L; YcurrStep=0L; ZcurrStep=0L; + + // and the tray in var + // EEPROM.write(0,0); + } + + +void doFullArea() +{ + // calculate num of x & y FoV. And the tilts + long XstepCount = 252525 ; long numXsteps = (XstepCount / xFoV) ; long YstepCount = 126260 ; long numYsteps = (YstepCount / yFoV) ; + + /* The equations are + * Az = {Tx(Ax-Bx)} + {Ty(Ay-By)} + {Bz} + * and + * Az = {Tx(Ax-Cx)} + {Ty(Ay-Cy)} + {Cz} + * + * we can find Tx and Ty after some algebra + * After Tx and Ty, we can find Oz too + */ +long a = (round)( (Ax-Bx) / (float)xFoV); long b = (round)((Ay-By)/(float)yFoV); long c = (Az-Bz); +long d = (round)((Ax-Cx)/(float)xFoV); long e = (round)((Ay-Cy)/(float)yFoV); long f =(Az-Cz); +long Oz = 0L; + +XdeltaZperFoV = (round) ((c*e)-(b*f)) / (float) ((a*e)-(b*d)) ; +YdeltaZperFoV = (round) (c-(a*XdeltaZperFoV)) / (float) b ; +Oz = Az - (XdeltaZperFoV *(Ax/xFoV)) - (YdeltaZperFoV * (Ay/yFoV)); + +// Tilts calculated. Now go ahead with WSI ************************************************************** +// set the initial delta z to the x one. Later, in the loop, it will be changed continously +long deltaZperFoV = XdeltaZperFoV; + +//this var keeps track of xdir while scanning . +1 is inc., -1 is dec +long XtravelDir = 1; + +// go to the origin + gotoXSetStep(0); gotoYSetStep(0); gotoZSetStep(Oz); + delay(300); + +// Send sync signal to the imager. By now we're starting FoV and this will be immediately imaged. + Serial.print("S#"); + +// go go go + for (long trackY = 0; trackY <= numYsteps; trackY++) + { + for (long trackX = 0; trackX < numXsteps; trackX++) + { + gotoXSetStep(XcurrStep + (XtravelDir * xFoV)); + + /* Four cases now --- (a) we're at 1st fov : dont move Z ! + * --- (b)we're on first strip but more than 1st fov : keep adding X tilt + * --- (c) we're at end of strip and just moved to next strip : only add the Y tilt + * --- (d) we're in 2nd or higher strip : keep adding only X tilt (Y tilt already added at (c)) + */ + + if((trackX==0)&&(trackY==0)) { nextZstep = ZcurrStep; } + if((trackX>0)&&(trackY==0)) { nextZstep = ZcurrStep +(XtravelDir * deltaZperFoV); } + if((trackX==0)&&(trackY>0)) { nextZstep = ZcurrStep + YdeltaZperFoV;} + if((trackX>0)&&(trackY>0)) { nextZstep = ZcurrStep +(XtravelDir * deltaZperFoV); } + + gotoZSetStep(nextZstep); + + } + + // shift in the Y dir + gotoYSetStep(YcurrStep + yFoV); + + // now go in the opposite direction + XtravelDir = XtravelDir * -1; + } + + // All done. Now go back to ORIGIN + gotoXSetStep(0); gotoYSetStep(0); gotoZSetStep(0); + delay(300); +} + + +//88888888888888888888888888888888888888888888888888888888888888888 +// THIS IS THE GOHOME() FUNCTION +//88888888888888888888888888888888888888888888888888888888888888888 +void gohome() +{ +// turn on all lights +gotoYSetStep(-300000); gotoXSetStep(400000); +Serial1.flush(); Serial.print('X'); Serial.print("#"); Serial.print(XcurrStep); Serial.print("#"); +// Y already at origin. Need to bring X and Z there + +gotoXSetStep(limitToXZero); gotoYSetStep(limitToYZero); + +gotoZSetStep(-100000); gotoZSetStep(limitTOZfocus); + +// SET THIS AS ORIGIN +XcurrStep=0L; YcurrStep=0L; ZcurrStep=0L; +// all done now. Send sync signal + Serial.print("S#"); +} + +void debug() +{ + +// calc steps in X +long XstepCount = abs(Bx - Ax) ; long numXsteps = (XstepCount / xFoV) ; + +// calc steps in Y +long YstepCount = abs(Cy - By) ; long numYsteps = (YstepCount / yFoV) ; + +// calc the z changes +long XZdeltaCount = Bz - Az ; long XdeltaZperFoV = XZdeltaCount / (numXsteps-1); +long YZdeltaCount = Cz - Bz ; long YdeltaZperFoV = YZdeltaCount / (numYsteps-1); + +// set the initial delta z to the x one. Later, in the loop, it will be changed continously +long deltaZperFoV = XdeltaZperFoV; + +Serial.print(" Ax: ");Serial.print(Ax);Serial.print(" Ay: ");Serial.print(Ay);Serial.print(" Az: ");Serial.print(Az); +Serial.print(" Bx: ");Serial.print(Bx);Serial.print(" By: ");Serial.print(By);Serial.print(" Bz: ");Serial.print(Bz); +Serial.print(" Cx: ");Serial.print(Cx);Serial.print(" Cy: ");Serial.print(Cy);Serial.print(" Cz: ");Serial.print(Cz); +Serial.print(" XdeltaZperFoV: ");Serial.print(XdeltaZperFoV); +Serial.print(" YdeltaZperFoV: ");Serial.print(YdeltaZperFoV); +Serial.print("#"); + +} + +void do4ptArea() +{ +// calc steps in X +long XstepCount = abs(Bx - Ax) ; long numXsteps = (XstepCount / xFoV) ; + +// calc steps in Y +long YstepCount = abs(Cy - By) ; long numYsteps = (YstepCount / yFoV) ; + +// calc the z changes +long XZdeltaCount = Bz - Az ; long XdeltaZperFoV = XZdeltaCount / (numXsteps-1); +long YZdeltaCount = Cz - Bz ; long YdeltaZperFoV = YZdeltaCount / (numYsteps-1); + +// set the initial delta z to the x one. Later, in the loop, it will be changed continously +long deltaZperFoV = XdeltaZperFoV; + +//this var keeps track of xdir while scanning . +1 is inc., -1 is dec +long XtravelDir = 1; + +// go to the origin + gotoXSetStep(Ax); gotoYSetStep(Ay); gotoZSetStep(Az); + delay(300); + +// Send sync signal to the imager + Serial.print("S#"); +// go go go + for (long trackY = 0; trackY <= numYsteps; trackY++) + { + for (long trackX = 0; trackX < numXsteps; trackX++) + { + gotoXSetStep(XcurrStep + (XtravelDir * xFoV)); + + /* Four cases now --- (a) we're at 1st fov : dont move Z ! + * --- (b)we're on first strip but more than 1st fov : keep adding X tilt + * --- (c) we're at end of strip and just moved to next strip : only add the Y tilt + * --- (d) we're in 2nd or higher strip : keep adding only X tilt (Y tilt already added at (c)) + */ + + if((trackX==0)&&(trackY==0)) { nextZstep = ZcurrStep; } + if((trackX>0)&&(trackY==0)) { nextZstep = ZcurrStep +(XtravelDir * deltaZperFoV); } + if((trackX==0)&&(trackY>0)) { nextZstep = ZcurrStep + YdeltaZperFoV;} + if((trackX>0)&&(trackY>0)) { nextZstep = ZcurrStep +(XtravelDir * deltaZperFoV); } + + gotoZSetStep(nextZstep); + + } + + // shift in the Y dir + gotoYSetStep(YcurrStep + yFoV); + + // now go in the opposite direction + XtravelDir = XtravelDir * -1; + } + + // All done. Now go back to ORIGIN + gotoXSetStep(0); gotoYSetStep(0); gotoZSetStep(0); + delay(300); +} + +void doAtoB() +{ + long XMovDir = 1; + + // find num of Fov to be traversed and their direction + long XstepCount = abs(Bx - Ax) ; long numXFoV = (XstepCount / xFoV) ; + + if (Bx > Ax) { XMovDir = 1; } + if (Bx < Ax) { XMovDir = -1; } + + // setup Z data + long ZdeltaCount = Bz - Az ; + long deltaZperFoV = ZdeltaCount / numXFoV; // This gives the Z change per FoV + Serial.println("deltaperZfov is "); + Serial.println(deltaZperFoV); + // go to the origin + gotoXSetStep(Ax); gotoYSetStep(Ay); gotoZSetStep(Az); + + // Send sync signal to the imager + Serial.print("S#"); + delay(300); + + // go go go + if( XMovDir == 1) // means we're going in inc X dir + { + for(long i=0; i