bitbank2 / Thermal_Printer

Arduino library to draw text and graphics on BLE thermal printers
Apache License 2.0
383 stars 54 forks source link

Issue with Printing on Peripage A6+: Accelerated Printing Causing Distortion #56

Open julienrat opened 10 months ago

julienrat commented 10 months ago

Hello, first of all, congratulations on the work you have done.

I have an issue regarding printing on a Peripage A6+ 894E 306DPI. When printing images with a lot of white space, zone, it seems to speed up the printing process, resulting in bands and white lines that distort the image. I have tested this with both the peripage android application and the Python script (https://github.com/bitrate16/peripage-python), and this issue does not occur.

With ESP32 and thermal printer lib PXL_20240104_085249703 MP

With Python script PXL_20240104_085259986

With your original demo example PXL_20240104_085753350

Here is my code :

#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h"                // SD Card ESP32
#include "SD_MMC.h"            // SD Card ESP32
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h>            // read and write from flash memory
#include <Thermal_Printer.h>
#include <JPEGDEC.h>

// define the number of bytes you want to access
#define EEPROM_SIZE 1

// https://docs.m5stack.com/en/unit/m5camera
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27

#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

// https://github.com/bitbank2/JPEGDEC/wiki
uint8_t ucDither[(640 / 2) * 16]; // Image width (after scaling), x 16
JPEGDEC jpg;
static int iWidth;

int JPEGDraw(JPEGDRAW *pDraw)
{
  int i, iCount;
  uint8_t *s = (uint8_t *)pDraw->pPixels;

  tpSetBackBuffer((uint8_t *)pDraw->pPixels, pDraw->iWidth, pDraw->iHeight);
  // The output is inverted, so flip the bits
  iCount = (pDraw->iWidth * pDraw->iHeight) / 8;
  for (i = 0; i < iCount; i++)
    s[i] = ~s[i];

  tpPrintBuffer(); // Print this block of pixels
  //delay(3);
  return 1; // Continue decode
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
  Serial.begin(115200);

  Serial.println((char *)"Scanning for BLE printer");
  if (tpScan()) // Scan for any supported printer name
  {
    Serial.println((char *)"Found a printer!, connecting...");
    if (tpConnect())
    {
      Serial.println("Connected!");
      tpSetWriteMode(MODE_WITHOUT_RESPONSE);
    }
    else
    {
      Serial.println("Failed to connected :(");
      while (1) {};
    }
  } // if scan
  else
  {
    Serial.println((char *)"Didn't find a printer :( ");
    while (1) {};
  }

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format =  PIXFORMAT_JPEG;

  // https://github.com/espressif/esp32-camera/blob/master/driver/include/esp_camera.h
  // https://github.com/espressif/esp32-camera/blob/master/driver/include/sensor.h
  if (psramFound()) {
    config.frame_size = FRAMESIZE_SXGA; //SXVGA
    config.jpeg_quality = 12;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // Init Camera
  esp_err_t err = esp_camera_init(&config);
  sensor_t * s = esp_camera_sensor_get();
  //initial sensors are flipped vertically and colors are a bit saturated
  s->set_awb_gain(s, 1);
  s->set_raw_gma(s, 1);
  s->set_vflip(s, 1);//flip it back
  s->set_contrast(s, 0);//up the blightness just a bit
  s->set_brightness(s, 0);//up the blightness just a bit
  s->set_saturation(s, 0);//lower the saturation
  s->set_agc_gain(s, 15);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    Serial.println("");
    return;
  } else {
    Serial.println("Camera init");
  }
  //Serial.println("Starting SD Card");
  if (!SD_MMC.begin()) {
    Serial.println("SD Card Mount Failed");
    return;
  }
  uint8_t cardType = SD_MMC.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD Card attached");
    return;
  }
  //pinMode(4, INPUT);
  EEPROM.begin(EEPROM_SIZE);
}

void loop() {
  Serial.println("Waiting for red button press!");
  //

  camera_fb_t * fb = NULL;
  // Take Picture with Camera
  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  } else {
    Serial.println("Camera captured");
  }

  uint8_t *pImage;
  int iImageSize;

  iWidth = tpGetWidth(); // get the width of the printer in pixels
  Serial.printf("Printer width is %d\n", iWidth);

  Serial.printf("Jpg is %d x %d\n", fb->width, fb->height);

  pImage = (uint8_t *)fb->buf;
  iImageSize = (int)fb->len;
  tpFeed(32);
  if (jpg.openRAM(pImage, iImageSize, JPEGDraw)) {
    jpg.setPixelType(ONE_BIT_DITHERED);
    jpg.decodeDither(ucDither, JPEG_SCALE_HALF);
    Serial.printf("Decoded %d x %d\n", jpg.getWidth(), jpg.getHeight());
    Serial.printf("Last jpg decoder error %d\n", jpg.getLastError());
  }
  int pictureNumber = EEPROM.read(0) + 1;

  // Path where new picture will be saved in SD Card
  String path = "/picture" + String(pictureNumber) + ".jpg";

  fs::FS &fs = SD_MMC;
  Serial.printf("Picture file name: %s\n", path.c_str());

  File file = fs.open(path.c_str(), FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file in writing mode");
  }
  else {
    file.write(fb->buf, fb->len); // payload (image), payload length
    Serial.printf("Saved file to path: %s\n", path.c_str());
    EEPROM.write(0, pictureNumber);
    EEPROM.commit();
  }
  file.close();
  esp_camera_fb_return(fb);
  tpSetFont(0, 0, 0, 0, 0);
  // for GOOJPRT PT-210
  // uint8_t font_a_cmd[] = {0x1b,'M',0x00};
  // tpWriteRawData(&font_a_cmd[0],sizeof(font_a_cmd));
  tpPrint((char *)"12x24 plain text\r");
  tpFeed(32); // advance the paper 32 scan lines
  Serial.println("Finished printing!");
  while (true) {};
}