2012-12-29 19 views
5

Arduino (Uno rev 3) ve termal yazıcı (bu model https://www.sparkfun.com/products/10438) ile oynamayı seviyorum. Arduino, her 10 saniyede bir yerel makineme (Ethernet kalkanı üzerinden) bir istekte bulunur ve bir SD karttaki yanıtı (eğer 200) kaydeder. Daha sonra bu kitaplığı https://github.com/adafruit/Adafruit-Thermal-Printer-Library kullanarak yazdırır.PHP'den Arduino destekli termal yazıcıya ikili komutlar gönderme

Şimdiye kadar temel metni yoklamayı, depolamayı ve yazdırmayı doğru şekilde yapıyorum ama şimdi daha gelişmiş komutlardan bazılarını kullanmaya çalışıyorum (alt çizgi, ters vb). Nihai amacım, görüntüleri aşağı yüklemek ve sunucudaki tüm işleme işlemlerini alabilmenizdir. http://printer.gofreerange.com/.

Sorun şu ki, göndermekte olduğum komutlar metin karakterleri olarak çıktı. Bazı komutlar çalışır (satır besleme), ancak diğerleri bozuk. Arduino kodunu ve çağırdığı temel PHP betiğini ekledim. Herhangi bir yardım?

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

Yazıcınız bozulduğunda PHP hangi verileri yolluyor? – chugadie

cevap

0

Size printer.write doğrudan bitmap verilerini yazdırmak olamayacağını görünüyor(). Yazıcı, printBitmap() yönteminde gördüğünüz gibi bazı özel baytların bitmap yazdırma modunu açmasını bekler. (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'; 
} 

Sizin kroki PHP gelen verileri anlamak ve ne zaman göndermek için (printer.write ile bayt olarak bireysel karakterleri göndermek zaman bilmek) ve gerekecektir printer.printBitmap() ile bir görüntü olarak bayt. Bu şekilde yazıcı, uygun verileri yazdırmak için hazırlanmak için uygun komutları alır. PHP'de yazdırmak istediğiniz şey hakkında bazı meta veriler oluşturup bunu Arduino'ya göndermeniz gerekecektir. Bir JSON biçimi şöyle olabilir:

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

Şimdi Arduino kroki metin ve ne zaman bitmap olarak çok miktarda veri göndermek için tek tek bayt göndermeye zaman anlayacaksınız. Eğer çok Content-Length başlığındaki gibi ikili veri kaçan önlemek için her segment ile veri miktarını gönderebilir,

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

Veya: hattını kullanabilir

bir daha kompakt biçim kesimleri arasında bir mola olarak beslemeleri HTTP

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

printBitmap sadece sahnelerin arkasına yazıyor. Kalın yazdırma vb. Düzgün çalışır, bu nedenle bayt olarak gönderilen komutları doğru şekilde yorumlamalıdır (paket için PHP'ye bakın). Sanırım sadece görüntü verilerim yanlış. – Dachande663

+0

Bayt gönderirken zamanlama sorunu olmadığından emin misiniz, 4 kez daha bekletip 4 byte gönderip beklemeyi bekler misiniz? writeBytes (a, b, c, d), writeBytes (a) ile tam olarak aynı olmayabilir; writeBytes (b) writeBytes (c) writeBytes (d); Yine de termal kütüphanenin tüm C'sini PHP'ye yeniden uygulamaya çalışmıyorum, böylece arduino sadece baytlık bir geçittir - işe yarayabilir ama zamanlama sorunları ile sonuçlanabilir. Hata ayıklamanın bir yolu, Arduino örneklerinden bazılarını alıp, bunları salt writeBytes (a) çağrıları olarak yeniden yazmaktır. Bu çalışırsa, o zaman verilerle ilgili bir problemdir. – chugadie