2012-12-29 24 views
5

Mi sto divertendo a giocare con un Arduino (Uno rev 3) e una stampante termica (questo modello https://www.sparkfun.com/products/10438). L'Arduino effettua una richiesta ogni 10 secondi sulla mia macchina locale (tramite uno scudo Ethernet) e memorizza la risposta (se 200) su una scheda SD. Viene quindi stampato utilizzando questa libreria https://github.com/adafruit/Adafruit-Thermal-Printer-Library.Invio di comandi binari da PHP a stampante termica alimentata con Arduino

Finora ho corretto il polling, l'archiviazione e la stampa del testo di base, ma ora sto cercando di utilizzare alcuni dei comandi più avanzati (sottolineato, inverso ecc.). Il mio obiettivo finale è quello di inviare le immagini verso il basso e gestire tutto il rendering sul server ala http://printer.gofreerange.com/.

Il problema è che i comandi che invio sono stati emessi come caratteri di testo. Alcuni comandi funzionano (avanzamento riga), ma altri sono confusi. Ho allegato sia il codice Arduino che lo script PHP di base che sta chiamando. Qualsiasi aiuto?

Arduino:

#include <SPI.h> 
#include <Ethernet.h> 
#include <SD.h> 
#include <SoftwareSerial.h> 
#include "Adafruit_Thermal.h" 

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
const char host[] = "192.168.1.100"; 
char cacheFilename[] = "TMP"; 

const byte printer_RX_Pin = 8; // this is the green wire 
const byte printer_TX_Pin = 9; // this is the yellow wire 
const byte SD_Pin = 4;   // the SD Card SPI pin 

bool downloadWaiting = false; 
bool statusOk = false; 
unsigned long content_length = 0; 

EthernetClient client; 
Adafruit_Thermal printer(printer_RX_Pin, printer_TX_Pin); 


void die(unsigned int times) { 
    while(true); 
} 


void checkForDownload() { 

    Serial.println("checkForDownload"); 

    content_length = 0; 
    statusOk = false; 
    unsigned long length = 0; 

    if (SD.exists(cacheFilename)) { 
    if (!SD.remove(cacheFilename)) { 
     die(4); 
    } 
    } 
    File cache = SD.open(cacheFilename, FILE_WRITE); 

    if(client.connect(host, 80)) { 

    client.println("GET /printer.php HTTP/1.1"); 
    client.print("Host: "); client.println(host); 
    client.println("User-Agent: arduino-ethernet"); 
    client.println("Connection: close"); 
    client.println(); 

    bool parsingHeader = true; 

    while(client.connected()) { 
     while(client.available()) { 

     if (parsingHeader) { 

      client.find((char*)"HTTP/1.1 "); 
      char statusCode[] = "000"; 
      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'); 
      } 

      client.find((char*)"\n\r\n"); 
      parsingHeader = false; 

     } else { 
      if(length < content_length) { 
      cache.write((byte)client.read()); 
      length++; 
      } else { 
       client.read(); 
      } 
     } 

     } 
    } 

    client.stop(); 
    cache.seek(0); 

    if (statusOk && content_length > 0 && (content_length == length) && (content_length == cache.size())) { 
     downloadWaiting = true; 
    } 

    } else { 
    client.stop(); 
    } 

    cache.close(); 

} 


void printFromDownload() { 

    Serial.println("printFromDownload"); 

    File cache = SD.open(cacheFilename); 
    byte b; 

    while (content_length--) { 
    printer.write((byte)cache.read()); 
    } 

    printer.feed(); 

    cache.close(); 
    downloadWaiting = false; 

} 


void setup(){ 

    pinMode(SD_Pin, OUTPUT); 
    if (!SD.begin(SD_Pin)) { 
    die(2); 
    } 

    if (Ethernet.begin(mac) == 0) { 
    die(3); 
    } 

    Serial.begin(9600); 
    printer.begin(255); 

    delay(1000); 

} 


void loop() { 
    if (downloadWaiting) { 
    printFromDownload(); 
    delay(5000); 
    } else { 
    checkForDownload(); 
    if (!downloadWaiting) { 
     delay(10000); 
    } 
    } 
} 

PHP:

<?php 

ob_start(); 


// Turn on Inverse mode 
// Doesn't work 
echo pack('S', 29); 
echo pack('S', 66); 
echo pack('S', 1); 

$string = 'Testing 1, 2, 3'; 

foreach(str_split($string) as $char) { 
    echo pack('S', ord($char)); // works 
} 

// Turn off Inverse mode 
echo pack('S', 29); 
echo pack('S', 66); 
echo pack('S', 0); 

// Line feed 
echo pack('S', 10); // works 

$content = ob_get_clean(); 
$length = strlen($content); 
header("Content-Length: $length"); 

echo $content; 
+0

Quali dati invia PHP che la stampante corrompe? – chugadie

risposta

0

Sembra che non è possibile stampare i dati bitmap direttamente con printer.write(). La stampante prevede alcuni byte speciali per attivare la modalità di stampa bitmap, come si può vedere nel metodo printBitmap(). (writeBytes (18, 42, chunkHeight, rowBytesClipped))

void Adafruit_Thermal::printBitmap(
int w, int h, const uint8_t *bitmap, bool fromProgMem) { 
    int rowBytes, rowBytesClipped, rowStart, chunkHeight, x, y, i; 

    rowBytes  = (w + 7)/8; // Round up to next byte boundary 
    rowBytesClipped = (rowBytes >= 48) ? 48 : rowBytes; // 384 pixels max width 

    for(i=rowStart=0; rowStart < h; rowStart += 255) { 
    // Issue up to 255 rows at a time: 
    chunkHeight = h - rowStart; 
    if(chunkHeight > 255) chunkHeight = 255; 

    writeBytes(18, 42, chunkHeight, rowBytesClipped); 

    for(y=0; y < chunkHeight; y++) { 
     for(x=0; x < rowBytesClipped; x++, i++) { 
     PRINTER_PRINT(fromProgMem ? pgm_read_byte(bitmap + i) : *(bitmap+i)); 
     } 
     i += rowBytes - rowBytesClipped; 
    } 
    timeoutSet(chunkHeight * dotPrintTime); 
    } 
    prevByte = '\n'; 
} 

vostro disegno dovrà comprendere i dati provenienti dal PHP e sapere quando inviare singoli caratteri come byte con printer.write() e quando inviare byte come immagine con printer.printBitmap(). In questo modo la stampante riceve i comandi corretti per prepararla per la stampa dei dati appropriati. Dovrai costruire alcuni metadati su ciò che vuoi stampare in PHP e inviarlo ad Arduino. Un formato JSON potrebbe assomigliare a questo:

{"reciept": [ 
    { 
    "type": "text", 
    "style": "bold", 
    "value": "Thank you for your purchase" 
    }, 
    { 
    "type": "bitmap", 
    "pos": "center", 
    "value": ".... binary data ..." 
    } 
]} 

Ora lo schizzo Arduino capiranno quando inviare i byte singolarmente come testo e quando inviare molti dati come bitmap.

un formato più compatto potrebbe utilizzare avanzamenti di riga come una pausa tra i segmenti:

F|bold 
T|Thank you for shopping with us\r 
P|Center 
B|...binary data (with \r escaped)... \r 

In alternativa, è possibile inviare la quantità di dati con ciascun segmento per evitare la fuga di dati binari molto simile l'intestazione Content-Length di HTTP

F4|boldT32|Thank you for shopping with us\rP6|CenterB3000|...binary data... 
+0

printBitmap chiama semplicemente scrivere dietro le quinte. La stampa in grassetto ecc funziona correttamente, quindi deve essere interpretato correttamente i comandi inviati come byte (guarda in PHP per pack). Penso di aver sbagliato i miei dati di immagine. – Dachande663

+0

Sei sicuro che non ci siano problemi di temporizzazione con l'invio di un byte, poi aspettando 4 volte contro l'invio di 4 byte e poi aspettando tutto in una volta? writeBytes (a, b, c, d) potrebbe non essere esattamente uguale a writeBytes (a); writeBytes (b); writeBytes (c); writeBytes (d); Non proverei ancora a ri-implementare tutta la C della libreria termica in PHP in modo che l'arduino sia solo un passthru di byte - potrebbe funzionare ma potrebbe finire con problemi di temporizzazione. Immagino che un modo per eseguire il debug sia prendere alcuni degli esempi di Arduino e riscriverli come chiamate pure writeBytes (a). Se funziona, allora è un problema con i dati. – chugadie

Problemi correlati