pATAq 发表于 2020-9-30 17:16:20

Lattepanda 使用 Python 控制热敏打印机 (文章节选)

## 前言

原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎指正。
已更新完整版:https://mc.dfrobot.com.cn/thread-308160-1-1.html
首先感谢葛老师和版主 rzyzzxw 的帖子,受益匪浅,自己跟着学习了一下,也做些补充与心得分享。原文『热敏打印机两日通』比较长,尚未完工,节选使用 Python 库操作热敏打印机的部分,实测这种打印效果较好,相比于直接驱动,失了些易用性但更灵活。

* [树莓派+热敏打印机1无驱动打印](https://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=305535&fromuid=725344)

* [树莓派+热敏打印机2,安装驱动](https://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=305550&fromuid=725344)

* [树莓派+热敏打印机3 删除打印机](https://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=305625&fromuid=725344)

* (https://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=304603&fromuid=725344)

---

**硬件环境:**

* Lattepanda Delta 432
* Thernal Printer (Model:GY-ETH402)

**软件环境:**

* Pop!_OS 20.04 (based on Ubuntu)/ Windows 10
* Python3 + python-escpos library

## 1、热敏打印机安装与测试

### 1.1 热敏打印机基本信息

![](https://ws.dfrobot.com.cn/FlzJrQ5vwdehYHQIN03JqngDxH8f)

本文采用的热敏打印机购自 (https://www.dfrobot.com.cn/goods-1795.html),深圳歌翼科技出品,产品基本信息如下:

*EH402 采用 TTL 和 USB 通讯接口,所以无法使用 RS232 接口自主升级固件
*工作电压 5~9v ,电压越高,打印速度越快
*实际支持中文字库 GB18030,虽然歌翼页面介绍是 GB2312
*使用 58 * 30 (纸宽 * 纸卷直径) 热敏打印纸
*采用 ESC/POS 兼容指令集进行打印
*分辨率 203DPI, 8 px/mm 每行最多打印 384px,即纸张虽然是58mm,但是可打印纸宽为 48mm。
*TTL 通讯时,如果每次打印数据量大于 1K,在连接 RX/TX 基础上,需要再连接流控 DTR

常见的通用热敏打印机有两种规格,一种是 58mm 纸卷,一种是 80mm 纸卷,使用 ESC/POS 指令集进行控制。

产品页面提供了 Windows 下的打印机驱动,可以直接显示为打印机使用,Linux 下则可以使用 CUPS 配合 `ZJ-58` 驱动,此方式比较方便,但是实测过程中,打印效果并不是最好的。

> * (https://mike42.me/blog/what-is-escpos-and-how-do-i-use-it)
>
> * https://en.wikipedia.org/wiki/ESC/P

### 1.2 安装与配置

建议先阅读[官方资料](https://wiki.dfrobot.com.cn/_SKU__DFR0503__%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%83%AD%E6%95%8F%E6%89%93%E5%8D%B0%E6%9C%BA)。

![](http://imgtest.dfrobot.com.cn/DFRobotCnWikiImage/DFR0503%E7%83%AD%E6%95%8F%E7%BA%B8%E5%AE%89%E8%A3%85%E7%A4%BA%E6%84%8F%E5%9B%BE.png)

【纸卷安装方式】

![](http://imgtest.dfrobot.com.cn/DFRobotCnWikiImage/%E9%85%8D%E7%BD%AE%E4%B8%B2%E5%8F%A3%E6%A8%A1%E5%BC%8F.png)

![](http://imgtest.dfrobot.com.cn/DFRobotCnWikiImage/DFR0503%E5%BC%95%E8%84%9A%E5%9B%BE1.png)

【接口与模式】

* 包括 TTL 和 USB 两种连接方式
* 包括串口和打印口两种模式

通电前按住顶端走纸键两秒,通电后放开,可以显示当前模式(默认为 `TTL 打印口模式`),根据字样提示按住走纸键两秒,可以切换为 `USB 串口模式`。

表述其实有迷惑性,原文是 `当前USB配置`,我以为这个设置和 `TTL 通讯接口` 无关,改动的都是 `USB 接口` 的模式。~~且原以为打印口就是使用的 USB-to-TTL 串口模块,电脑上直接识别为打印机;串口就是使用设备(单片机)等的 UART 引脚与打印机的串口引脚连接~~,两种接口与两种模式绑定且互斥,而实际上是2x2四种可能,不绑定不互斥。但是有些组合可能能用,但是会有问题,后面会介绍。我们这里以 USB 接口连接为例。

> 我们保证打印机处于 串口 模式,Linux 下使用 `lsusb` 命令可以看到名为
>
> `Bus 001 Device 007: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port` 的设备,对应的串口号为 `ttyUSB0`。

如果将 USB 设置为 `打印口` 模式,Linux 下识别为 `Bus 001 Device 005: ID 0fe6:811e ICS Advent Parallel Adapter` ,无对应的串口号。该模式下虽然可以打印,但是会存在乱码和打印图片时最大打印长度为 255 像素 的问题。

## 2、打印测试

### 安装使用 python-escpos

我这里以 Ubuntu Linux 为例,在 Windows 下也是差不多的。

```bash
# 安装 Python3 和 pip
sudo apt install python3 python3-pip
# 安装 python-escpos 库(使用第三方镜像加速下载)
python3 -m pip install python-escpos -i http://mirrors.cloud.tencent.com/pypi/simple --trusted-host mirrors.cloud.tencent.com
```

如果安装成功没有报错的话,下一步我们介绍如何初始化设备并打印`hello world!` 。好在官方有非常详尽的文档可供参考,地址如下:

https://python-escpos.readthedocs.io/en/latest/user/usage.html

注意该库不同版本间部分函数可能不通用。官方介绍了多种模式来初始化热敏打印机,从而可以进行控制发送命令,分别是:

* USB
* Serial
* Network
* File
* Dummy

我们这里选择 USB 模式,上面 `lsusb` 获得了该打印机的 ID 067b:2303,我们需要获取一下参数,方法为:

```bash
sjqlwy@LattePanda:~$ lsusb -vvv -d 067b:2303 | grep iInterface
      iInterface            0
sjqlwy@LattePanda:~$ lsusb -vvv -d 067b:2303 | grep bEndpointAddress
      bEndpointAddress   0x81EP 1 IN
      bEndpointAddress   0x02EP 2 OUT
      bEndpointAddress   0x82EP 2 IN
```

其中 `bEndpointAddress` 选择前两个 `IN` 和 `OUT`。

```python
sudo python3
from escpos.printer import Usb
p = Usb(0x067b, 0x2303, 0, 0x82, 0x02)

p.text("Hello World\n")
p.text("你好,世界\n")
# gb18030 支持繁體字
p.codepage = 'gb2312'
p.text("你好,世界\n")
```

此时出现了第一个问题,打印中文会出现乱码,设置 `codepage` 可以解决。具体按下不表。

```python
# 打印条形码
p.barcode('1324354657687', 'EAN13', 64, 2, '', '')
# 打印 QR 二维码
content = "https://www.cnblogs.com/sjqlwy"
p.qr(content, size=13)
# 打印图片,注意需要预处理好,最大384*384,否则会出现乱码。
p.image("32.png")
```

至此,我们就可以通过各种组合打印出自己想要的小票了。同时我总结的问题:

> 1. 当打印机 USB 接口模式设置为 `打印口` 时,上述方式同样可以得到相关参数并进行初始化,但是打印过程中会有问题。所以建议 USB 接口绑定 `串口` 模式
> 2. 如果打印的图像只有 255像素 高,请设置为串口模式
> 3. 代码注意中英文标点
> 4. 打印的图片需要预处理好,太大会打印乱码,此时拔掉打印机电源来省纸
> 5. 请购买品质良好的打印纸,我这个就不行
> 6. 如果出现有时候正常打印图片,有时候又是乱码,请设置 image() 的 `printing implementations` 我这里使用的 `impl='bitImageColumn` 正常,具体移步 [官方文档](https://python-escpos.readthedocs.io/en/latest/user/methods.html) 。
> 7. font A 和 font B 主要是不同大小的英文字母,中文没有 font A/B 的区分



## 3、高级设置

!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20200928144953.png)

当我们想设计打印一个如上图所示排队号票的时候,应该怎么做呢?

#### Plan A

文字用 `text()` 打印,图像用 `image()` 打印。需要设置文本格式,使用 `set()` 函数。

问题:

* 该打印机有闪存芯片用于存储默认打印参数,比如居中、字号、加粗、下划线等
* 每次修改完参数后,需要延迟数秒来生效
* 频繁修改打印参数可能会烧坏闪存芯片

综上,导致此方案会使一张小票需要很长时间才能打印出来,而且还有烧坏闪存芯片的风险

**Plan B**

将小票内容生成后,转换为图像格式,使用 `image()` 打印,比如借助 PIL 库,这个方案大家可以自行尝试

**Plan C**

固定部分用图像,可变部分用文字,比如这张小票,编号和时间是变量,其他都可以使用图像,大大减少闪存读写。

```python
from pyfirmata import Arduino, util
from datetime import datetime
from escpos.printer import Usb
import time
# from tinydb import TinyDB, Query

# db = TinyDB("/home/xin/Projects/Lshop/db.json")
# parcel = Query()

p = Usb(0x067b, 0x2303, 0, 0x81, 0x02)
p.codepage = 'gb18030'
board = Arduino("/dev/ttyACM0")

n = 0
def Label(n):
    p.image('/home/xin/Pictures/label-head.png', impl='bitImageColumn')
    time.sleep(1)
    p.set(align='center', font='b', text_type='B', width=4, height=4)
    p.text(str(n) + '\n')
    p.text('\n')
    time.sleep(5)         # Sleep to prevent printer buffer overflow
    p.set(width=1, height=1)
    p.text('时间:' + datetime.now().strftime('%Y-%m-%d %H:%M:%S') + '\n')
    p.image('/home/xin/Pictures/label-bottom.png', impl='bitImageColumn')
    # content = "https://www.cnblogs.com/sjqlwy"
    # p.qr(content, size=13)
    p.cut()

while True:
    reading =board.digital.read()
    if reading == 1:
      n = n + 1
      Label(n)
```

## 4、如何查找帮助(十分重要)

由于 `python-escpos` 库更新频繁,很多方法、参数可能会有变动。当你遇到各种 `no methond` 报错时,可以参考。

```python
sudo -E python3
from escpos.printer import Usb
p = Usb(0x067b, 0x2303, 0, 0x81, 0x02)
# 查看对象包含的方法
>>> print(dir(p))
['__abstractmethods__', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_abc_impl', '_image_send_graphics_data', '_int_low_high', '_raw', '_send_2d_code_data', 'barcode', 'block_text', 'cashdraw', 'charcode', 'close', 'codepage', 'columns', 'control', 'cut', 'device', 'hw', 'idProduct', 'idVendor', 'image', 'in_ep', 'line_spacing', 'open', 'out_ep', 'panel_buttons', 'qr', 'set', 'text', 'timeout']
# 查看方法的可用参数,不同打印机可能不一样,使用方法参考官方文档,但是以下面显示的为准
>>> print(help(p.set))
```

## 小结

不知道为何关于这篇关于热敏打印机的使用的文章如此难写,不过探索过程中也很有趣。本文概括如下:

* 使用 `python-escpos` 控制热敏打印机,灵活性更优,打印效果更好
* 建议使用 USB 接口绑定 `串口` 模式
* 虽然可以使用自动缩放,但是提前设计好打印内容更美观
* 打印图像时好时乱码请选择合适的 `impl` 参数
* 官方文档是宝库,但是也是有错误,有了问题看帮助





rzyzzxw 发表于 2020-9-30 17:40:44

特别帅{:5_179:}

gray6666 发表于 2020-9-30 17:53:29

pATAq 发表于 2020-9-30 17:16
# 前言

原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎指正。


写的很棒,重新燃起了我玩热敏打印机的欲望

hnyzcj 发表于 2020-9-30 18:04:47

gray6666 发表于 2020-9-30 17:53
写的很棒,重新燃起了我玩热敏打印机的欲望

怎么燃气

pATAq 发表于 2020-9-30 20:12:09

gray6666 发表于 2020-9-30 17:53
写的很棒,重新燃起了我玩热敏打印机的欲望

最近房子快装好了,准备做个甲醛/噪音记录仪,监测室内24小时变化,到时候试试使用 Plan B 绘制个图表

pATAq 发表于 2020-9-30 20:12:42

rzyzzxw 发表于 2020-9-30 17:40
特别帅

哈哈,谢谢捧场

pATAq 发表于 2020-9-30 20:13:00

hnyzcj 发表于 2020-9-30 18:04
怎么燃气

打火机

gray6666 发表于 2020-10-2 19:45:21

来一场疯狂的散热片烧烤{:6_214:}

佛系唐法官 发表于 2020-10-10 14:38:31

真棒!!!
{:6_213:}

发表于 2020-10-10 20:43:37

我家里就有一个热敏打印机

pATAq 发表于 2020-10-10 23:05:34

诩 发表于 2020-10-10 20:43
我家里就有一个热敏打印机

哈哈,挺好玩的

发表于 2020-10-11 13:08:29

pATAq 发表于 2020-10-10 23:05
哈哈,挺好玩的

         是啊

发表于 2020-10-11 13:24:22

pATAq 发表于 2020-10-10 23:05
哈哈,挺好玩的

         是呀

RRoy 发表于 2020-10-27 16:02:52

涨姿势了!

虾虾^0^ 发表于 2021-8-10 16:56:52

好好好好好好好好好好

糖醋花生 发表于 2022-12-9 08:21:49

《巴适得很》

三春牛-创客 发表于 2023-1-20 23:18:37

厉害         

三春牛-创客 发表于 2023-1-20 23:19:41

赞!!!

花生编程 发表于 2023-7-26 22:35:25

厉害厉害!!

花生编程 发表于 2023-7-26 22:36:54

热敏打印机不错!!省墨。但是写字在上面不容易干。
页: [1]
查看完整版本: Lattepanda 使用 Python 控制热敏打印机 (文章节选)