2012-12-29 34 views
5

Tôi đang vui vẻ chơi với Arduino (Uno rev 3) và máy in nhiệt (mẫu này https://www.sparkfun.com/products/10438). Arduino thực hiện một yêu cầu 10 giây một lần cho máy cục bộ của tôi (thông qua một lá chắn Ethernet) và lưu trữ phản hồi (nếu 200) trên thẻ SD. Sau đó nó in ra bằng cách sử dụng thư viện này https://github.com/adafruit/Adafruit-Thermal-Printer-Library.Gửi các lệnh nhị phân từ máy in nhiệt chạy bằng PHP đến Arduino

Cho đến giờ tôi có nó bỏ phiếu, lưu trữ và in văn bản cơ bản một cách chính xác nhưng bây giờ tôi đang cố gắng sử dụng một số lệnh nâng cao hơn (gạch chân, ngược, vv). Mục tiêu cuối cùng của tôi là gửi hình ảnh xuống và xử lý tất cả hiển thị trên máy chủ ala http://printer.gofreerange.com/.

Sự cố là các lệnh tôi đang gửi được xuất thành ký tự văn bản. Một số lệnh hoạt động (nguồn cấp dữ liệu dòng), nhưng một số lệnh khác bị cắt xén. Tôi đã đính kèm cả mã Arduino và tập lệnh PHP cơ bản mà nó đang gọi. Bất kỳ giúp đỡ?

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

PHP gửi dữ liệu đến máy in nào? – chugadie

Trả lời

0

Có vẻ như bạn không thể in dữ liệu bitmap trực tiếp với printer.write(). Máy in mong đợi một số byte đặc biệt để bật chế độ in bitmap như bạn có thể thấy trong phương thức 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'; 
} 

phác thảo của bạn sẽ cần phải hiểu các dữ liệu đến từ PHP và biết khi nào để gửi đặc điểm cá nhân như byte với printer.write() và khi nào thì gửi byte dưới dạng hình ảnh với printer.printBitmap(). Bằng cách này, máy in nhận được các lệnh thích hợp để chuẩn bị cho việc in dữ liệu thích hợp. Bạn sẽ cần phải xây dựng một số siêu dữ liệu xung quanh những gì bạn muốn in trong PHP và gửi cho Arduino. Định dạng JSON có thể trông giống như sau:

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

Bây giờ bản phác thảo Arduino của bạn sẽ hiểu khi nào gửi byte riêng lẻ dưới dạng văn bản và khi gửi nhiều dữ liệu dưới dạng bitmap.

Một định dạng nhỏ gọn hơn có thể sử dụng dòng nguồn cấp dữ liệu như nghỉ ngơi giữa các phân đoạn:

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

Hoặc, bạn có thể gửi lượng dữ liệu với từng phân khúc để tránh thoát dữ liệu nhị phân giống như header Content-Length của HTTP

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

printBitmap chỉ cần gọi ghi đằng sau hậu trường. In đậm vv hoạt động chính xác, vì vậy nó phải được giải thích các lệnh được gửi dưới dạng byte đúng (xem trong gói PHP). Tôi nghĩ rằng tôi chỉ có dữ liệu hình ảnh của tôi sai. – Dachande663

+0

Bạn có chắc chắn không có vấn đề thời gian với việc gửi một byte, sau đó chờ đợi 4 lần so với gửi 4 byte sau đó chờ đợi tất cả cùng một lúc? writeBytes (a, b, c, d) có thể không chính xác giống như writeBytes (a); writeBytes (b); writeBytes (c); writeBytes (d); Tôi vẫn sẽ không cố gắng để thực hiện lại tất cả các C của thư viện nhiệt vào PHP để arduino chỉ là một passthru byte - nó có thể làm việc nhưng nó có thể kết thúc với vấn đề thời gian. Tôi đoán một cách để gỡ lỗi nó là lấy một số ví dụ Arduino và viết lại chúng như là các cuộc gọi writeBytes thuần túy (a). Nếu nó hoạt động, thì đó là vấn đề với dữ liệu. – chugadie

Các vấn đề liên quan