Faded prints when using exciting.io but fine with Adafruit example

35 views
Skip to first unread message

semaja2

unread,
Apr 28, 2015, 11:59:37 PM4/28/15
to gfr-p...@googlegroups.com
Hi Guys,

I have ported the code over to the Spark Core platform, and everything is now working fine for the most part however I am unable to get consistent results from the printer.

From the attached picture, the tests using the Exciting.io code have sporadic fading, where as the Adafruit example code (including bitmaps) are very dark and consistent.

So far I have tried the following
  • Using a 5V 2A power supplier for the printer
  • Using a USB cable and attaching to a 2A charger for the printer
  • Using a 12V 2A power supply going through a 9V 1.5A regulator for the printer
  • Using the Exciting.io Serial.println() with A2-raw format
  • Using the Adafruit Printer.printBitmap(dynamic_cast<Stream*>(&dataFile)); with A2-bitmap format
  • Adjusting the printers baud rate 9600/19200/115200 etc
In some situations I have found that the printer does appear to crash when printing large blocks of black, when this happens shortly after the black it just prints random characters then returns to printing the site

From some of my research it appears different firmwares may have various impacts to printing bitmaps, does anyone have access to the firmware files?

Below is the Spark Core code currently in use
#define USE_SPARK_RGB                             // Use the onbaord RGB LED, comment this out to use extenal LEDs
#define SPARK_MODE MANUAL                         // Use MANUAL mode to increase data download speed

#define DEBUG                                     // When debug is enabled, log a bunch of stuff to the hardware Serial, if disabled some events will use Spark.publish
#define DEBUG_BAUD 9600                         // Serial baud rate for debugging logs
#define DEBUG_DELAY 5                             // Delay system by x seconds or wait for serial connection, useful to allow time to attach to serial port for debugging

#define PRINTER_CONNECT_VIA_IP                    // Connect via IP instead of DNS Lookup of host, host must still be set however
#define PRINTER_SERVER_HOST "printer.exciting.io" // Print server hostname
#define PRINTER_SERVER_IP 178,79,132,137          // Print server IP (only required if PRINTER_CONNECT_VIA_IP defined)

#define PRINTER_SERVER_PORT 80                    // Printer Server Port (eg. 80)
#define PRINTER_POLL_DELAY 30                     // Time in x seconds between polling server for next print job
#define PRINTER_REQUEST_TIMEOUT 300               // Time in x seconds before request for print job is aborted
#define PRINTER_BAUD 19200                        // Printer baud rate
#define PRINTER_KEEP_PRINTS                       // Uncomment to archive all print jobs -- EXPERIMENTAL
#define PRINTER_CACHE_NAME_FORMAT "%03d.job"      // Adjust to set the name of the cache files
//#define PRINTER_MAX_SIZE 20000                  // If defined, sets max content size to prevent timeouts

//#define USE_ADAFRUIT_THERMAL                    // Uncomment to use the Adafruit libary instead -- NOT RECOMMENDED / UNTESTED

/********************************


  Do NOT modify anything below, for normal operations simply adjust the above defines as required



*********************************/













#ifdef SPARK_MODE
SYSTEM_MODE(SPARK_MODE);
#endif

#include "sd-card-library.h"
#ifdef USE_ADAFRUIT_THERMAL
  #define PRINTER_TYPE "A2-bitmap"
  #include "Adafruit_Thermal.h"
  Adafruit_Thermal printer;
  //#define PRINTER_WRITE(b) printer.writeBytes(b);
  #define PRINTER_INIT() Serial1.begin(printer_baud); printer.begin(&Serial1);
#else
  #define PRINTER_TYPE "A2-raw"
  #define PRINTER_WRITE(b) Serial1.write(b)
  #define PRINTER_INIT() Serial1.begin(printer_baud);
#endif


const char printerType[] = PRINTER_TYPE;

const char host[] = PRINTER_SERVER_HOST; // the host of the backend server

#ifdef PRINTER_CONNECT_VIA_IP
IPAddress host_ip(PRINTER_SERVER_IP);
#define PRINTER_SERVER host_ip
#else
#define PRINTER_SERVER host
#endif

const unsigned int port = PRINTER_SERVER_PORT;

const unsigned long pollingDelay = PRINTER_POLL_DELAY * 1000; // delay between polling requests (milliseconds)
const unsigned long serialDelay = DEBUG_DELAY * 1000;
const unsigned long requestTimeout = PRINTER_REQUEST_TIMEOUT * 1000;

const int pingTries = 20;

const int serialBaud = DEBUG_BAUD;

// Printer Connections
//const int printer_TX_Pin = RX; // this is the yellow wire
//const int printer_RX_Pin = TX; // this is the green wire
const int printer_baud = PRINTER_BAUD;

// Buttons -- Not in use but for reference of the Choosatron
const uint8_t button1 =  D1;
const uint8_t button2 =  D2;
const uint8_t button3 =  D3;
const uint8_t button4 =  D4;

// LED Pins
#ifdef USE_SPARK_RGB
  #define LED_ON true
  #define LED_OFF false
#else
  const uint8_t errorLED = D5;       // the red LED
  const uint8_t downloadLED = D6;    // the amber LED
  const uint8_t readyLED = D7;       // the green LED
  #define LED_ON HIGH
  #define LED_OFF LOW
#endif

#define LED_ERROR 2
#define LED_DOWNLOAD 0
#define LED_READY 1


// SD Card
const uint8_t chipSelect = A2;
const uint8_t mosiPin = A5;
const uint8_t misoPin = A4;
const uint8_t clockPin = A3;
// SD Card debugging
#ifdef DEBUG
  Sd2Card card;
  SdVolume volume;
  SdFile root;
#endif

boolean downloadWaiting = false;
unsigned long content_length = 0;
boolean statusOk = false;
char cacheFilename[10];


// -- Everything below here can be left alone

const char sketchVersion[] = "1.0.7";
// -- Debugging

#ifdef DEBUG
  void debugTimeAndSeparator() {
    Serial.print(millis()); Serial.print(": ");
  }
  void debug(const char *a) {
    debugTimeAndSeparator(); Serial.println(a);
  }
  #define debug2(a, b) debugTimeAndSeparator(); Serial.print(a); Serial.println(b);
#else
  #define debug(a) Spark.publish(a);
  #define debug2(a, b) Spark.publish(a, b);
#endif


// -- Initialize the printer ID

const byte idAddress = 0;
char printerId[17]; // the unique ID for this printer.
//char printerId[] = "4r2f5i4u1l3s3s8d\0";

inline void initPrinterID() {
  #ifdef DEBUG
    debug("Initializing Printer ID");
  #endif
  if ((EEPROM.read(idAddress) == 255) || (EEPROM.read(idAddress+1) == 255)) {
    debug("Generating new ID");
    randomSeed(analogRead(0) * analogRead(5));
    for(int i = 0; i < 16; i += 2) {
      printerId[i] = random(48, 57); // 0-9
      printerId[i+1] = random(97, 122); // a-z
      EEPROM.write(idAddress + i, printerId[i]);
      EEPROM.write(idAddress + i+1, printerId[i+1]);
    }
  } else {
    for(int i = 0; i < 16; i++) {
      printerId[i] = (char)EEPROM.read(idAddress + i);
    }
  }
  printerId[16] = '\0';
  debug2("Printer ID: ", printerId);
}


// -- Initialize the LEDs

void initDiagnosticLEDs() {
  #ifdef DEBUG
    debug("Initializing LEDs");
  #endif
#ifndef USE_SPARK_RGB
  pinMode(errorLED, OUTPUT);
  pinMode(downloadLED, OUTPUT);
  pinMode(readyLED, OUTPUT);
#endif

  statusLED(LED_ERROR, LED_ON);
  delay(500);
  statusLED(LED_ERROR, LED_OFF);

  statusLED(LED_DOWNLOAD, LED_ON);
  delay(500);
  statusLED(LED_DOWNLOAD, LED_OFF);

  statusLED(LED_READY, LED_ON);
  delay(500);
  statusLED(LED_READY, LED_OFF);
}

// -- Initialize the printer connection
void initPrinter() {
  #ifdef DEBUG
    debug("Initializing printer");
  #endif
  PRINTER_INIT();
}


// -- Initialize the SD card

inline void initSD() {
  #ifdef DEBUG
    debug("Initializing SD card");

    // we'll use the initialization code from the utility libraries
    // since we're just testing if the card is working!
    if (!card.init(SPI_HALF_SPEED, chipSelect)) {
      debug("initialization failed. Things to check:");
      debug("* is a card is inserted?");
      debug("* Is your wiring correct?");
      debug("* did you change the chipSelect pin to match your shield or module?");
      return;
    } else {
     debug("Wiring is correct and a card is present.");
    }

    // print the type of card
    Serial.print("\nCard type: ");
    switch(card.type()) {
      case SD_CARD_TYPE_SD1:
        Serial.println("SD1");
        break;
      case SD_CARD_TYPE_SD2:
        Serial.println("SD2");
        break;
      case SD_CARD_TYPE_SDHC:
        Serial.println("SDHC");
        break;
      default:
        Serial.println("Unknown");
    }

    // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
    if (!volume.init(card)) {
      debug("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
      return;
    }


    // print the type and size of the first FAT-type volume
    uint32_t volumesize;
    Serial.print("\nVolume type is FAT");
    Serial.println(volume.fatType(), DEC);

    volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
    volumesize *= volume.clusterCount();       // we'll have a lot of clusters
    volumesize *= 512;                            // SD card blocks are always 512 bytes
    volumesize /= 1024;
    volumesize /= 1024;
    debug2("Volume size (Mbytes): ", volumesize);
  #endif

  // Initialize HARDWARE SPI with user defined chipSelect
  if (!SD.begin(chipSelect)) {
    // SD Card failure.
    terminalError(2);
    #ifdef DEBUG
      debug("Initialization failed!");
    #endif
    return;
  }
}


// -- Initialize the Ethernet connection & DHCP

TCPClient client;
inline void initNetwork() {
#ifdef DEBUG
  debug("Initialization network...");
#endif
#ifdef SPARK_MODE
  WiFi.connect();
  delay(5000);
#endif
#ifdef DEBUG
  debug2("IP: ", WiFi.localIP());
  debug2("NM: ", WiFi.subnetMask());
  debug2("GW: ", WiFi.gatewayIP());
#endif
}

// // -- Setup; runs once on boot.

void setup(){
#ifdef DEBUG
  Serial.begin(DEBUG_BAUD);
  while (!Serial.available() || millis() < serialDelay) {Spark.process();}
#endif
  initDiagnosticLEDs();
  initPrinterID();
  initSD();
  initPrinter();
  initNetwork();
}

// Set status LEDs
void statusLED(uint8_t status, bool state) {
#ifdef USE_SPARK_RGB
  if (state == LED_OFF) {
    RGB.control(false);
  } else {
    RGB.control(true);
    RGB.brightness(255);
    switch(status) {
      case LED_ERROR:
        RGB.color(255, 0, 0); //RED
      break;
      case LED_DOWNLOAD:
        RGB.color(0, 255, 0); //YELLOW
      break;
      case LED_READY:
        RGB.color(0, 0, 255); //BLUE
      break;
    }
  }
#else
  switch(status) {
    case LED_ERROR:
      digitalWrite(errorLED, state);
    break;
    case LED_DOWNLOAD:
      digitalWrite(downloadLED, state);
    break;
    case LED_READY:
      digitalWrite(readyLED, state);
    break;
  }
#endif
}



void generateFilename() {
  int n = 0;
  File temp;
  int size = 0;
  //char filename[10];
  snprintf(cacheFilename, sizeof(cacheFilename), PRINTER_CACHE_NAME_FORMAT, n); // includes a three-digit sequence number in the file name
#ifdef PRINTER_KEEP_PRINTS
  while(SD.exists(cacheFilename)) {
    temp = SD.open(cacheFilename, FILE_READ);
    size = temp.size();
    temp.close();
    if (size == 0) {
      SD.remove(cacheFilename);
    } else {
      n++;
      snprintf(cacheFilename, sizeof(cacheFilename), PRINTER_CACHE_NAME_FORMAT, n);
    }
  }
#else
  if (SD.exists(cacheFilename)) {
    if (!SD.remove(cacheFilename)) {
      // Failed to clear cache.
      statusLED(LED_ERROR, LED_ON);
      terminalError(4);
    }
  }
#endif

}


// -- Check for new data and download if found

void checkForDownload() {
  unsigned long length = 0;
  content_length = 0;
  statusOk = false;

#ifdef DEBUG
  unsigned long start = millis();
#endif


  //cacheFilename =
  generateFilename();
  File cache = SD.open(cacheFilename, FILE_WRITE);

  debug2("Attempting to connect to ", PRINTER_SERVER);
  if (client.connect(PRINTER_SERVER, port)) {
    debug2("Connected to ", PRINTER_SERVER);
    statusLED(LED_READY, LED_ON);
    client.print("GET "); client.print("/printer/"); client.print(printerId); client.println(" HTTP/1.0");
    client.print("Host: "); client.print(host); client.print(":"); client.println(port);
    client.flush();
    client.print("Accept: application/vnd.exciting.printer."); client.println(printerType);
    client.print("X-Printer-Version: "); client.println(sketchVersion);
    client.println();
    boolean parsingHeader = true;
    float downloadPerc;
    unsigned long connectTime = millis() + requestTimeout;
    while(client.connected()) {
      while(client.available()) {
        if (parsingHeader) {
          client.find((char*)"HTTP/1.1 ");
          char statusCode[] = "xxx";
          client.readBytes(statusCode, 3);
          statusOk = (strcmp(statusCode, "200") == 0);
          client.find((char*)"Content-Length: ");
          char c;
          while (isdigit(c = client.read())) {
            content_length = content_length*10 + (c - '0');
          }
          if (content_length == 0) {
            debug("Disconnecting due to nothing to download");
            client.stop();
            cache.close();
            SD.remove(cacheFilename);
            return;
          }
#ifdef PRINTER_MAX_SIZE
          else if (content_length > PRINTER_MAX_SIZE) {
            debug("Disconnecting due to content exceeding limit");
            client.stop();
            cache.close();
            SD.remove(cacheFilename);
            return;
          }
#endif
          debug2("Content length: ", content_length);
          client.find((char*)"\n\r\n"); // the first \r may already have been read above
          parsingHeader = false;
        } else {
          cache.write(client.read());
          length++;
          if (length == content_length) {
            debug("Downloaded all content...");
            //client.stop();
          }
          //char c = client.read();
          //Serial.print(c);
        }
      }
      if (connectTime < millis()) {
        debug("Disconnecting due to timeout");
        client.stop();
        cache.close();
        SD.remove(cacheFilename);
        return;
      }
    }

    debug("Server disconnected");
    statusLED(LED_DOWNLOAD, LED_OFF);

    // Close the connection, and flush any unwritten bytes to the cache.
    client.stop();

    cache.seek(0);

    if (statusOk) {
      if ((content_length == length) && (content_length == cache.size())) {
        if (content_length > 0) {
          debug2("Successfully downloaded print job ", cacheFilename)
          downloadWaiting = true;
          statusLED(LED_READY, LED_ON);
        }
      } else {
        debug2("Failure, content length: ", content_length);
        if (content_length != length) debug2("length: ", length);
        if (content_length != cache.size()) debug2("cache: ", cache.size());
        statusLED(LED_ERROR, LED_ON);
      }
    } else {
      debug("Response code != 200");
      recoverableError();
    }
  } else {
    debug("Couldn't connect");
    recoverableError();
  }

  cache.close();




#ifdef DEBUG
  unsigned long duration = millis() - start;
  debug2("Bytes: ", length);
  debug2("Duration: ", duration);
#endif
}

void flashErrorLEDs(unsigned int times, unsigned int pause) {
  while (times--) {
    statusLED(LED_ERROR, LED_ON);
    //delay(pause);
    statusLED(LED_ERROR, LED_OFF);
    //delay(pause);
  }
}

inline void recoverableError() {
  flashErrorLEDs(5, 100);
}

inline void terminalError(unsigned int times) {
  flashErrorLEDs(times, 500);
  statusLED(LED_ERROR, LED_ON);
  debug("Terminal Error - SYSTEM HALT");
  while(true) {SPARK_WLAN_Loop();} // no point in carrying on, so do nothing forevermore:
}

// // -- Print send any data from the cache to the printer

#ifdef USE_ADAFRUIT_THERMAL
void printFromDownload() {
  debug2("Printing job : ", cacheFilename);
  onpaper(String(cacheFilename));
  debug2("Finished printing job : ", cacheFilename);
  downloadWaiting = false;
  statusLED(LED_READY, LED_OFF);
}

void onpaper(String chemin) {
  char chemin2[50];
  chemin.toCharArray(chemin2, sizeof(chemin2));
  File dataFile = SD.open(chemin2, FILE_READ);
  if (dataFile) {
    printer.printBitmap(dynamic_cast<Stream*>(&dataFile));
    }
  else {
    printer.println("no dataFile");
  }
  printer.sleep();
  printer.wake();
  dataFile.close();
}
#else
void printFromDownload() {
  File cache = SD.open(cacheFilename);
  byte b;
  debug2("Printing job : ", cacheFilename);
  int file_size = cache.size();
  while (file_size--) {
    b = (byte)cache.read();
    PRINTER_WRITE(b);
  }
  debug2("Finished printing job : ", cacheFilename);
  cache.close();
  downloadWaiting = false;
  statusLED(LED_READY, LED_OFF);
}

#endif


// // -- Check for new data, if any new data then print
unsigned long nextDownloadCheck = 0;
void loop() {
  serialEvent();

  if (nextDownloadCheck < millis()) {
    checkForDownload();
    if (downloadWaiting) {
      printFromDownload();
    }
    nextDownloadCheck = millis() + pollingDelay;
    debug2("Next Download: ", nextDownloadCheck);
  }

  //unsigned long pollingDelaySeconds = pollingDelay / 1000;
  //debug2("Next Poll: ", pollingDelaySeconds);
  //delay(pollingDelay);
}

String inputString = "";
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    //Serial.print(inChar);
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n' || inChar == '\r') {
    //inputString.toUpperCase();


      Serial.println(inputString);
      if (inputString == "PRINT CACHE") {
        Serial.println("Printing cache...");
        int n = 0;
        File temp;
        int size = 0;
        char filename[10];
        snprintf(filename, sizeof(filename), PRINTER_CACHE_NAME_FORMAT, n); // includes a three-digit sequence number in the file name
        while(SD.exists(filename)) {
          printFromDownload();
          n++;
          snprintf(filename, sizeof(filename), PRINTER_CACHE_NAME_FORMAT, n);
        }
      } else if (inputString == "CLEAR CACHE") {
        Serial.println("Clearing cache...");
        int n = 0;
        File temp;
        int size = 0;
        char filename[10];
        snprintf(filename, sizeof(filename), PRINTER_CACHE_NAME_FORMAT, n); // includes a three-digit sequence number in the file name
        while(SD.exists(filename)) {
          SD.remove(filename);
          Serial.print("Deleting cached job : ");
          Serial.println(filename);
          n++;
          snprintf(filename, sizeof(filename), PRINTER_CACHE_NAME_FORMAT, n);
        }
      } else if (inputString == "CHECK") {
        Serial.println("Checking for downloads...");
        checkForDownload();
        if (downloadWaiting) {
          printFromDownload();
        }
        nextDownloadCheck = millis() + pollingDelay;
        debug2("Next Download: ", nextDownloadCheck);
      } else if (inputString == "SPARK") {
        Spark.process();
      } else if (inputString == "DFU") {
        debug("Entering DFU Mode");
        System.bootloader();
      } else {
        Serial.println("Unknown Command!");
      }

      // clear the string:
      inputString = "";



    } else {
      // add it to the inputString:
      inputString += inChar;
    }
  }
}




IMG_5065.JPG
Reply all
Reply to author
Forward
0 new messages