从PHP向Arduino供电的热敏打印机发送二进制命令
我在玩Arduino(Uno版本3)和热敏打印机(这款)时玩得很开心。Arduino每10秒向我的本地机器发出一次请求(通过以太网屏蔽),并将响应(如果200)存储在SD卡上。然后用这个库打印出来 到目前为止,我已经正确地轮询、存储和打印了基本文本,但现在我正在尝试使用一些更高级的命令(下划线、反转等)。我的最终目标是发送图像并在服务器上处理所有渲染 问题是我发送的命令被输出为文本字符。有些命令可以工作(换行),但有些命令是乱码的。我附上了Arduino代码和它调用的基本PHP脚本。有什么帮助吗 阿杜伊诺:从PHP向Arduino供电的热敏打印机发送二进制命令,php,arduino,Php,Arduino,我在玩Arduino(Uno版本3)和热敏打印机(这款)时玩得很开心。Arduino每10秒向我的本地机器发出一次请求(通过以太网屏蔽),并将响应(如果200)存储在SD卡上。然后用这个库打印出来 到目前为止,我已经正确地轮询、存储和打印了基本文本,但现在我正在尝试使用一些更高级的命令(下划线、反转等)。我的最终目标是发送图像并在服务器上处理所有渲染 问题是我发送的命令被输出为文本字符。有些命令可以工作(换行),但有些命令是乱码的。我附上了Arduino代码和它调用的基本PHP脚本。有什么帮助吗
#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);
}
}
}
#包括
#包括
#包括
#包括
#包括“Adafruit_Thermal.h”
字节mac[]={0xDE,0xAD,0xBE,0xEF,0xFE,0xED};
常量字符主机[]=“192.168.1.100”;
char cacheFilename[]=“TMP”;
常量字节打印机_RX_Pin=8;//这是绿色的电线
常量字节打印机_TX_Pin=9;//这是黄线
常量字节SD_Pin=4;//SD卡的SPI引脚
bool downloadWaiting=false;
bool statusOk=false;
无符号长内容长度=0;
以太网络客户端;
Adafruit_热敏打印机(打印机_RX_引脚、打印机_TX_引脚);
无效骰子(无符号整数次){
虽然(正确);
}
void checkForDownload(){
Serial.println(“checkForDownload”);
内容长度=0;
statusOk=false;
无符号长长度=0;
如果(SD.exists(cacheFilename)){
如果(!SD.remove(cacheFilename)){
模具(4);
}
}
File cache=SD.open(cacheFilename,File\u WRITE);
if(客户端连接(主机,80)){
println(“GET/printer.php HTTP/1.1”);
client.print(“主机:”;client.println(主机);
client.println(“用户代理:arduino以太网”);
client.println(“连接:关闭”);
client.println();
bool parsingHeader=true;
while(client.connected()){
while(client.available()){
如果(帕辛格领导){
client.find((char*)“HTTP/1.1”);
字符状态码[]=“000”;
client.readBytes(状态码,3);
statusOk=(strcmp(statusCode,“200”)==0);
client.find((char*)“内容长度:”);
字符c;
while(isdigit(c=client.read()){
内容长度=(内容长度*10)+(c-“0”);
}
client.find((char*)“\n\r\n”);
parsingHeader=false;
}否则{
if(长度<内容长度){
cache.write((字节)client.read());
长度++;
}否则{
client.read();
}
}
}
}
client.stop();
cache.seek(0);
如果(statusOk&&content\u length>0&&(content\u length==length)&&(content\u length==cache.size()){
downloadWaiting=true;
}
}否则{
client.stop();
}
cache.close();
}
void printFromDownload(){
Serial.println(“printFromDownload”);
文件缓存=SD.open(cacheFilename);
字节b;
while(内容长度--){
printer.write((字节)cache.read());
}
printer.feed();
cache.close();
downloadWaiting=false;
}
无效设置(){
引脚模式(SD_引脚,输出);
如果(!SD.begin(SD_引脚)){
模具(2);
}
if(以太网开始(mac)==0){
模具(3);
}
Serial.begin(9600);
打印机。开始(255);
延迟(1000);
}
void循环(){
如果(下载等待){
printFromDownload();
延迟(5000);
}否则{
checkForDownload();
如果(!下载等待){
延迟(10 000);
}
}
}
PHP:
似乎无法使用printer.write()直接打印位图数据。打印机需要一些特殊的字节来打开位图打印模式,正如您在printBitmap()方法中看到的那样。(写入字节(18、42、块高、行字节剪裁))
现在,您的Arduino草图将了解何时以文本形式单独发送字节,何时以位图形式发送大量数据
更紧凑的格式可能使用换行符作为线段之间的分隔符:
F|bold
T|Thank you for shopping with us\r
P|Center
B|...binary data (with \r escaped)... \r
或者,您可以发送每个段的数据量,以避免转义二进制数据,就像HTTP的内容长度头一样
F4|boldT32|Thank you for shopping with us\rP6|CenterB3000|...binary data...
PHP发送的哪些数据被打印机破坏了?printBitmap只是在幕后调用write。打印粗体etc工作正常,因此它必须正确地解释以字节形式发送的命令(查看PHP包)。我想我只是把图像数据搞错了。你确定发送一个字节然后等待4次与发送4个字节然后一次等待没有时间问题吗?写字节(a、b、c、d)可能与写字节(a)不完全相同;写字节(b);写字节(c);写入字节(d);我仍然不会尝试将thermal库中的所有C语言重新实现到PHP中,这样arduino就只是一个字节的传递——它可能会工作,但最终可能会出现时间问题。我想调试它的一种方法是使用一些Arduino示例,并将它们作为纯writeBytes(a)调用重新编写。如果这样做有效,那就是数据问题。
{"reciept": [
{
"type": "text",
"style": "bold",
"value": "Thank you for your purchase"
},
{
"type": "bitmap",
"pos": "center",
"value": ".... binary data ..."
}
]}
F|bold
T|Thank you for shopping with us\r
P|Center
B|...binary data (with \r escaped)... \r
F4|boldT32|Thank you for shopping with us\rP6|CenterB3000|...binary data...