here is the skeleton of my plotting sketch, it takes care of not overrunning the plotter's 1024 byte buffer and detects disconnections and plotter errors.
user.h
enum pState {
reset,
waiting,
plotting,
buffering,
noconnection,
error
};
enum pWorld {
plotter,
text,
drawing
};
void setState(pState state);
First Part of code (too long to fit one post)
#include "user.h"
#include <math.h>
#include <avr/pgmspace.h> // for progmem stuff
#define DEBUG_enabled 0
#define buttonPin 8
#define ESC "\x1B"
#define cmdBufferSize 255
pState plotterState;
pState noConnectionReturnState;
pWorld plotterWorld;
byte errorCode = 0;
byte statusCode = 0;
int bufferCapacity = 0;
char serInStr[64];
char cmd[cmdBufferSize] ="";
char progStrLine[48] = "";
boolean textMessageBuffered;
boolean textMessagePlotted;
unsigned long nextDrawMillis = 0ul;
unsigned long nextPingMillis = 0ul;
union coordinate {
byte b[4];
double d;
}
currentCoordinate;
const double minDistToDraw = 60.0;
double x, y, xOld, yOld;
boolean firstDraw = true;
boolean penDown = false;
boolean wantsToEnd = false;
boolean endingInited = false;
int currentPen = 0;
// A3 plotter space size: 16158 x 11040
int plotterWidth = 16158;
int plotterHeight = 11040;
// system coordinates MAX_INT x MAX_INT
int systemWidth=32767;
int systemHeight=32767;
int textLines = 0;
int margin = 40*10;
/********************** PROGMEM SECTION BELOW **********************/
// long text string can be stored in program memory, and sent to the plotter
// from there as commands or log messages
const char startMessage[] PROGMEM =
"\n___________________________________________\n"
"\nARDUINO PLOTTER\n"
"version 2.0\n"
"\n"
"ole kristensen 2010\n"
"\n"
"mailto:ole@kristensen.name\n"
"http://ole.kristensen.name\n"
"___________________________________________\n\n"
;
const char textMessage[] PROGMEM =
"http://ole.kristensen.name\n"
"mailto:ole" "\x40" "kristensen.name\n"
;
const char resetPlotterCodes[] PROGMEM =
"\x1B" ".Y\n"
"\x1B" ".R\n"
"\x1B" ".M0;;;13:\n"
"IN;\n"
"SP0;\n"
;
boolean getProgStrLine(const prog_char str[], int lineNo){
memset(progStrLine, 0, sizeof(progStrLine));
char c;
int currentLine = 0;
byte currentChar = 0;
if(!str) return false;
while((c = pgm_read_byte(str++))){
progStrLine[currentChar] = c;
currentChar++;
if(c == '\n'){
if(currentLine == lineNo) {
if(currentChar == 1){
progStrLine[0] = ' ';
}
return true;
}
else {
memset(progStrLine, 0, sizeof(progStrLine));
currentLine++;
currentChar = 0;
}
}
}
if(currentLine == lineNo && currentChar > 0){
return true;
}
if(currentLine < lineNo) {
return false;
}
}
void printProgStr(const prog_char str[])
{
char c;
if(!str) return;
while((c = pgm_read_byte(str++)))
Serial.print(c,BYTE);
}
void logProgStr(const prog_char str[])
{
Serial.println(ESC ".)");
printProgStr( str );
Serial.println(ESC ".(");
}
/********************** MAIN SECTION BELOW **********************/
void setup() {
// start/stop button
pinMode(buttonPin, INPUT);
Serial.begin(9600);
setState(reset);
}
void loop() {
if(plotterState == plotting){
if(digitalRead(buttonPin) == HIGH){
wantsToEnd = true;
}
if(wantsToEnd && !endingInited){
endingInited = true;
}
if(wantsToEnd){
plotSend();
Serial.flush();
Serial.println(";OA;");
delay(1000);
if (readSerialString()) {
while(readSerialString()){
Serial.flush();
}
setState(reset);
}
}
else {
if(statusCode < 16) {
if(millis() > nextDrawMillis){
/********************** TEXT PLOTTING BELOW **********************/
if(!textMessageBuffered){
int textMessageLineNo = 0;
textLines = 0;
while(getProgStrLine(textMessage, textMessageLineNo++)){
writeTextLine(progStrLine);
}
textMessageBuffered = true;
}
if(!textMessagePlotted){
plotSend();
Serial.flush();
delay(10);
Serial.println(";OA;");
nextDrawMillis = millis() + 2000ul; // prevent buffer overflow while waiting
if (readSerialString()) {
while(readSerialString()){
Serial.flush();
}
textMessagePlotted = true;
}
}
else {
/********************** MAIN DRAWING BELOW **********************/
setupDrawingWorld();
double xReal = 0.0;
double yReal = 0.0;
double xDist = 0.0;
double yDist = 0.0;
if(firstDraw){
selectPen(1);
plotPenUp();
plotPenAt(x,y);
firstDraw = false;
}
penDown = true;
x=random(-systemWidth/2.0,systemWidth/2.0);
y=random(-systemHeight/2.0,systemHeight/2.0);
xDist = x-xOld;
yDist = y-yOld;
xDist = abs(xDist);
yDist = abs(yDist);
if(xDist > minDistToDraw || yDist > minDistToDraw) {
xOld = x;
yOld = y;
plotPenAt(x,y);
if(penDown){
plotPenDown();
}
else{
plotPenUp();
}
}
}
}
}
else {
if(errorCode == 0){
if(!plotterPing())
setState(noconnection);
}
}
}
}
else {
if(errorCode == 0 && plotterState != reset){
if(millis() > nextPingMillis){
nextPingMillis = millis() + 2000ul;
if(!plotterPing())
setState(noconnection);
}
}
}
if(errorCode > 15)
setState(error);
if(plotterState == reset){
resetPlotter();
}
if(plotterState == waiting){
if(digitalRead(buttonPin) == HIGH){
// give feedback, eg by turning on a specific led
delay(1000);
startPlotter();
}
}
if(plotterState == noconnection){
if(plotterPing()){
plot(";");
setState(noConnectionReturnState);
}
if(digitalRead(buttonPin) == HIGH){
// give feedback, eg by turning on a specific led
delay(1000);
setState(reset);
}
delay(100);
}
if(plotterState == error){
if(digitalRead(buttonPin) == HIGH){
// give feedback, eg by turning on a specific led
delay(1000);
errorCode = 0;
setState(reset);
}
}
}
void waitForPlotterBuffer(){
boolean isBuffering = true;
while(isBuffering){
Serial.flush();
Serial.println(ESC ".B");
if (readSerialString()) {
bufferCapacity = atoi(serInStr);
debugStr(serInStr);
if(bufferCapacity >= cmdBufferSize+1){
isBuffering = false;
setState(plotting);
}
else {
setState(buffering);
}
}
else {
isBuffering = false;
setState(noconnection);
}
}
}
boolean plotterPing(){
Serial.println(ESC ".Y");
Serial.flush();
if (readSerialString()) {
while(readSerialString()){
Serial.flush();
}
}
Serial.println(ESC ".O");
if (readSerialString()) {
statusCode = atoi(serInStr);
char msg[128] = "";
memset( msg, 0, sizeof(msg) );
strcat(msg, serInStr);
Serial.flush();
if (readSerialString()) {
while(readSerialString()){
Serial.flush();
}
}
Serial.println(ESC ".B");
if (readSerialString()) {
bufferCapacity = atoi(serInStr);
strcat(msg, "\t");
strcat(msg, serInStr);
}
if(errorCode == 0){
Serial.flush();
if (readSerialString()) {
while(readSerialString()){
Serial.flush();
}
}
Serial.println(ESC ".E");
if (readSerialString()) {
errorCode = atoi(serInStr);
strcat(msg, "\t");
strcat(msg, serInStr);
if (errorCode == 0){
debugStr(msg);
return true;
}
else{
logStr(msg);
return false;
}
}
}
else {
logStr(msg);
return true;
}
}
else {
return false;
}
}