Mahlzeit zusammen,
es war etwas Zeit ueber und im Schrott lagen alte CD/DVD Laufwerke..
Schnell die Schrittmotoren mit den dazugehoerigen Schienen ausgebaut
und einen kleinen(winzigen) Plotter gebaut.
Dabei stieß ich auf das leidige Thema der Stepper.h Bibliothek, welche blockierend
arbeitete. (Heiß: Faehrt eine Achse bleibt der gesamte loop stehen bis das Ziel
erreicht wurde.)
Also noch auf die schnelle eine eigene Bibliothek geschrieben..
BETA des DVD Plotters:
//FastStepper 0.0.8 by grillgemuese 07.2018
#include <FastStepper.h>
/**** Pins ****/
const uint8_t X_limit = A1, Y_limit = A0, Z_limit = A0; //!!!
/**** Plotter configuration ****/
const int16_t X_CAL_DIR = 1, Y_CAL_DIR = -1, Z_CAL_DIR = 1;
const int16_t Z_DOWN = 135, Z_UP = 100;
const int16_t X_SPR = 200, Y_SPR = 200, Z_SPR = 200; //steps per revolution
const int16_t X_MAX = 260, Y_MAX = 260, Z_MAX = 200; //max. steps in total
const float X_MM = 38.0, Y_MM = 38.0; //max. mm in total
const float X_RPM = 34.0, Y_RPM = 33.0, Z_RPM = 32.0; //(DVD ~40),(28BYJ-48 ~14)
const float CAL_RPM = 10.0;
const uint32_t drawDuration = 50; //ms
/**** Picture config ****/
const uint8_t X_RES = 32, Y_RES = 32; //pic pixels
const float X_SPMM = (float)X_MAX / X_MM; //steps per mm
const float Y_SPMM = (float)Y_MAX / Y_MM;
const float X_SPPX = X_SPMM / ((float)X_RES / X_MM); //steps per pixel
const float Y_SPPX = Y_SPMM / ((float)Y_RES / Y_MM);
/**** Picture ****/
const bool pic[Y_RES][X_RES] = {
// 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 1
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 2
{0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0}, // 3
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 4
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 5
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 6
{0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}, // 7
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, // 8
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, // 9
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //10
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //11
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //12
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //13
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //14
{0,0,0,0,0,0,0,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,0,0,0}, //15
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //16
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //17
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //18
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //19
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //20
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //21
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, //22
{0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}, //23
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //24
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //25
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //26
{0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0}, //27
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //28
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //29
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //30
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //31
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //32
};
/**** Process states ****/
enum {Start, Calibrate, Search, MoveXY, DownZ, Draw, UpZ, Finished, Pause, Proceed, Empty};
//X & Z
FastStepper X_Axis(X_SPR, 2, 4, 3, 5, "X");
FastStepper Y_Axis(Y_SPR, 6, 8, 7, 9, "Y");
FastStepper Z_Axis(Z_SPR, 10, 12, 11, 13, "Z");
void setup()
{
X_Axis.begin(); Y_Axis.begin(); Z_Axis.begin();
Serial.begin(19200); while(!Serial){}
Serial.setTimeout(250);
Serial.println(F("Available commands:"));
Serial.println(F("<cal> calibrate X,Y,Z"));
Serial.println(F("<start>"));
Serial.println(F("<pause>")); //no emergency stop!
Serial.println(F("<resume>"));
}//void setup() END
void loop()
{
static bool firstCall = true, calibrated;
static uint8_t activeState = Empty;
static uint8_t act_X, act_Y;
static uint32_t drawStartMS, printStartMS;
if (Serial.available() > 0)
{
String msg = Serial.readStringUntil('\n');
if (msg == "cal" && activeState == Empty) activeState = Calibrate;
else if (msg == "start" && activeState == Empty) activeState = Start;
else if (msg == "pause" && activeState != Empty) activeState = Pause;
else if (msg == "resume" && activeState == Pause) activeState = Proceed;
else Serial.println(F("not available!"));
firstCall = true; //not 100% correct
}
switch (activeState)
{
case Start:
if (calibrated)
{
act_X = 0;
act_Y = 0;
printStartMS = millis();
activeState = Search;
Serial.println(F("start print"));
} else {
activeState = Empty;
Serial.println(F("not calibrated!"));
}
break;
case Calibrate:
if (firstCall) {
X_Axis.setRPM(CAL_RPM); Y_Axis.setRPM(CAL_RPM); Z_Axis.setRPM(CAL_RPM);
firstCall = false;
Serial.println(F("start calibration"));
}
if (!digitalRead(X_limit)) X_Axis.step(X_CAL_DIR);
if (digitalRead(Y_limit)) Y_Axis.step(Y_CAL_DIR);
if (digitalRead(Z_limit)) Z_Axis.step(Z_CAL_DIR);
if (digitalRead(X_limit) && !digitalRead(Y_limit) && !digitalRead(Z_limit))
{
X_Axis.setStep(0); Y_Axis.setStep(0); Z_Axis.setStep(0);
X_Axis.setRPM(X_RPM); Y_Axis.setRPM(Y_RPM); Z_Axis.setRPM(Z_RPM);
calibrated = true;
activeState = Empty;
firstCall = true;
Serial.println(F("end calibration"));
}
break;
case Search:
act_X++;
if (act_X > X_RES - 1)
{
act_X = 0;
act_Y++;
if (act_Y > Y_RES - 1)
{
activeState = Finished;
firstCall = true;
break;
}
}
if (pic[act_Y][act_X])
{
activeState = MoveXY;
firstCall = true;
}
break;
case MoveXY:
if (firstCall) {
X_Axis.stepTo(act_X * (uint8_t)X_SPPX);
Y_Axis.stepTo(act_Y * (uint8_t)Y_SPPX);
firstCall = false;
}
else if (X_Axis.getStepStat() && Y_Axis.getStepStat())
{
activeState = DownZ;
firstCall = true;
Serial.print(X_Axis.getName()); Serial.print(X_Axis.getStep());
Serial.print(F("\t"));
Serial.print(Y_Axis.getName()); Serial.println(Y_Axis.getStep());
}
break;
case DownZ:
if (firstCall) {
Z_Axis.stepTo(Z_DOWN);
firstCall = false;
}
else if (Z_Axis.getStepStat())
{
drawStartMS = millis();
activeState = Draw;
firstCall = true;
}
break;
case Draw:
if (millis() - drawStartMS >= drawDuration) activeState = UpZ;
break;
case UpZ:
if (firstCall) {
Z_Axis.stepTo(Z_UP);
firstCall = false;
}
else if (Z_Axis.getStepStat())
{
activeState = Search;
firstCall = true;
}
break;
case Finished:
if (firstCall) {
X_Axis.stepTo(0); Y_Axis.stepTo(0); Z_Axis.stepTo(0);
firstCall = false;
act_X = 0;
act_Y = 0;
Serial.print(F("Print finished after: ")); Serial.print(millis() - printStartMS);
Serial.println(F("ms"));
}
else if (X_Axis.getStepStat()&&Y_Axis.getStepStat()&&Z_Axis.getStepStat())
{
X_Axis.sleep(); Y_Axis.sleep(); Z_Axis.sleep();
activeState = Empty;
firstCall = true;
}
break;
case Pause:
if (firstCall) {
Z_Axis.stepTo(Z_UP);
X_Axis.stepTo(X_Axis.getStep());
Y_Axis.stepTo(Y_Axis.getStep());
firstCall = false;
Serial.println(F("pause print"));
}
break;
case Proceed:
activeState = MoveXY;
Serial.println(F("resume print"));
break;
case Empty:
break;
}//switch(activeState) END
X_Axis.run(); //call every loopcycle!
Y_Axis.run(); //call every loopcycle!
Z_Axis.run(); //call every loopcycle!
}//void loop() END
Gruß
grillgemuese
FastStepper.zip (5.99 KB)