2012-12-29 11 views
5

Mam trochę zabawy z Arduino (Uno rev 3) i drukarką termiczną (ten model https://www.sparkfun.com/products/10438). Arduino wysyła żądanie co 10 sekund do mojego lokalnego komputera (przez ekran Ethernet) i przechowuje odpowiedź (jeśli 200) na karcie SD. Następnie drukuje to za pomocą tej biblioteki https://github.com/adafruit/Adafruit-Thermal-Printer-Library.Wysyłanie poleceń binarnych z PHP na drukarkę termiczną Arduino

Do tej pory mam poprawnie odpytywanie, przechowywanie i drukowanie podstawowego tekstu, ale teraz próbuję użyć bardziej zaawansowanych poleceń (podkreślenie, odwrotność itd.). Moim nadrzędnym celem jest wysłanie obrazów i obsłużenie całego renderowania na serwerze, a mianowicie http://printer.gofreerange.com/.

Problem polega na tym, że polecenia, które wysyłam, zostały wyprowadzone jako znaki tekstowe. Niektóre polecenia działają (wierszowanie), ale inne są zniekształcone. Załączam zarówno kod Arduino, jak i podstawowy skrypt PHP, do którego dzwoni. Jakaś pomoc?

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

Jakie są dane dotyczące wysyłania PHP, które drukarz uszkadza? – chugadie

Odpowiedz

0

Wydaje się, że nie można drukować danych bitmapy bezpośrednio z printer.write(). Drukarka oczekuje, że niektóre bajty specjalne włączą tryb drukowania bitmap, jak widać w metodzie 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'; 
} 

Twój szkic będzie musiał zrozumieć dane pochodzące z PHP i wiedzieć, kiedy należy wysłać poszczególne znaki jako bajty z printer.write() i kiedy wysłać bajtów jako obraz z print.printBitmap(). W ten sposób drukarka otrzymuje odpowiednie polecenia przygotowujące ją do drukowania odpowiednich danych. Będziesz musiał zbudować metadane wokół tego, co chcesz wydrukować w PHP i wysłać je do Arduino. Format JSON może wyglądać następująco:

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

Teraz twój szkic Arduino zrozumieją, kiedy należy wysłać bajtów indywidualnie jako tekst i kiedy wysłać wiele danych w postaci bitmapy.

Bardziej kompaktowy Format może wykorzystywać linię karmi jak przerwy między segmentami:

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

Albo można wysłać ilość danych z każdego segmentu, aby uniknąć ucieczki danych binarnych podobnie jak w nagłówku Content-Length of HTTP

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

printBitmap po prostu wywołuje pisać za kulisami. Drukowanie pogrubione itp. Działa poprawnie, więc musi poprawnie interpretować polecenia wysłane jako bajty (spójrz na PHP dla paczki). Myślę, że po prostu mam błędne dane obrazu. – Dachande663

+0

Czy jesteś pewien, że nie ma problemów z synchronizacją wysyłania bajtu, a następnie czekaniem 4 razy w porównaniu do wysyłania 4 bajtów, a następnie czekania wszystkich naraz? writeBytes (a, b, c, d) może nie być dokładnie taki sam jak writeBytes (a); writeBytes (b); writeBytes (c); writeBytes (d); Nadal nie próbowałbym ponownie implementować całego C biblioteki termicznej w PHP, tak aby arduino było tylko tranzytem bajtów - może działać, ale może się to skończyć z problemami z timingiem. Myślę, że sposobem na debugowanie jest wzięcie niektórych przykładów Arduino i ponowne zapisanie ich jako czystych połączeń typu writeBytes (a). Jeśli to działa, oznacza to problem z danymi. – chugadie

Powiązane problemy