Go Down

Topic: Parallel Thermal Receipt Printer (Read 2478 times) previous topic - next topic

mixographer

I've seen a few examples around of using the Serial versions of the common thermal receipt printer. I've found the parallel version quite easy to work with. My printer is a CBM1000II and I'm using an i2c I/O expander to send the bytes to a parallel port on the printer. This code uses the PFC8574 i2c chip. Most of this code is just sending the appropriate ESC/POS codes to the printer. I submit it here in case it's useful for anyone, and also as a code review, since I'm not too keen a programmer. I think I'll also try to turn this into a library, so I did things like making separate functions for bold and boldOff instead of passing boolean parameters to one function.  

My 'printString' function is a bit convoluted, but I couldn't really figure out how to know sizeof my char array and this was how I tried to count the size of the array.

Thanks for looking and any feedback is appreciated,

Here is my demo code:



Code: [Select]

#include <Wire.h>

const int strobePin = 10;
const int busyPin = 11;
const int ackPin = 12;
const int strobeWait = 10; // how long to bounce the strobe
boolean goOnce = 1;

void setup(){
  Wire.begin(0x20);
  pinMode(strobePin, OUTPUT);
  digitalWrite(strobePin, HIGH);
  pinMode(ackPin, INPUT);
  digitalWrite(ackPin, LOW);
  pinMode(busyPin, INPUT);
  digitalWrite(busyPin, LOW);
  initializePrinter();
  delay(1000);
}

void waitForPrinter(int port){
 while(digitalRead(port) == 1){
    // wait for busy to go low
 }
}

void doStrobe(){
 digitalWrite(strobePin, LOW);
 delayMicroseconds(strobeWait);
 digitalWrite(strobePin, HIGH);
}

// This is the part that works with the I/O expander
// everything else should be adaptable to other ways of setting the byte.
// write the data to the port on the I/O Expander
void setData(char text){
 Wire.beginTransmission(0x20);
 Wire.write(text);
 Wire.endTransmission();
 doStrobe();
}

void printChar(char toPrint){
 waitForPrinter(busyPin);
 setData(toPrint);
 doStrobe();
}

void initializePrinter(){
 printChar((byte)0x1B);
 printChar((byte)0x40);
}

void alignCenter(){
 printChar((byte)0x1B);
 printChar((byte)0x61);
 printChar(1);
}

void alignRight(){
 printChar((byte)0x1B);
 printChar((byte)0x61);
 printChar(2);
}

void alignLeft(){
 printChar((byte)0x1B);
 printChar((byte)0x61);
 printChar(0);
}

//Start or Cancel underline. Valid params include 0 = cancel, 1 = 1 line thick, 2 = 2 lines thick
void underline(){
 printChar((byte)0x1B);
 printChar((byte)0x2D);
 printChar(1);
}

void thickUnderline(){
 printChar((byte)0x1B);
 printChar((byte)0x2D);
 printChar(2);
}

void noUnderline(){
 printChar((byte)0x1B);
 printChar((byte)0x2D);
 printChar(0);
}


void doCut(){
 printChar((byte)0x1D);
 printChar((byte)0x56);
 printChar(49);
}

//Do the buzzer in increments of 200ms
void doBuzzer(int repeat){
 for (int i = 0; i < repeat; i++){
   printChar((byte)0x1B);
   printChar((byte)0x1E);
   printChar(49);
 }
}

//Select  the font. Valid params are 0 or 1
void fontA(){
 printChar((byte)0x1B);
 printChar((byte)0x4D);
 printChar(0);
}

void fontB(){
 printChar((byte)0x1B);
 printChar((byte)0x4D);
 printChar(1);
}

//Line feed (the number of lines to feed)
void lineFeed(int lines){
 printChar((byte)0x1B);
 printChar((byte)0x64);
 printChar(lines);
}

void boldOn(){
 printChar((byte)0x1B);
 printChar((byte)0x45);
 printChar(1);
}

void boldOff(){
 printChar((byte)0x1B);
 printChar((byte)0x45);
 printChar(0);
}

void inverse(){
 printChar((byte)0x1D);
 printChar((byte)0x42);
 printChar(1);
}

void notInverse(){
 printChar((byte)0x1D);
 printChar((byte)0x42);
 printChar(0);
}

//I don't understand the font size description in the manual.
// fontsize 00 = standard, and the size changes based on this byte,
// MSB is Horizontal and LSB is Vertical
// 22 is larger, 33 is even larger. Needs work.
void printSize(byte fontsize){
 printChar((byte)0x1D);
 printChar((byte)0x21);
 printChar(fontsize);
}

void upsideDown(){
 printChar((byte)0x1B);
 printChar((byte)0x7B);
 printChar(1);
}

void notUpsideDown(){
 printChar((byte)0x1B);
 printChar((byte)0x7B);
 printChar(0);
}

void printString(char toPrint[]){
 int wStart = 0, //start of word in string
 wEnd = 0;  //end of word
 int count = 0, //string position counter
 wordLen = 0;  //length of string
 while (toPrint[count] != '\0'){
   wStart = count;
   wordLen = 0;
   wEnd = count;
   count ++;
   wordLen++;
   for (int n = wEnd; n > (wStart - 1); n--){
     printChar(toPrint[n]);
   }
 }
}

void printDemo(){
  printString("This string of numbers should wrap:");
  lineFeed(2);

  printString("012345678901234567890123456789012345678901234567890....");
  lineFeed(2);

  fontA();
  printString("This is font A.");
  fontB();
  printString("and this is font B.");
  fontA();
  lineFeed(1);

  printString("This is normal text that is a long string");
  lineFeed(1);

  alignRight();
  printString("Right aligned");
  lineFeed(1);

  alignCenter();
  printString("Centered text");
  lineFeed(1);
  alignLeft();

  upsideDown();
  printString("Upside down text?");
  lineFeed(1);
  notUpsideDown();
  lineFeed(2);
  alignLeft();

  boldOn();
  printString("This is a string in Bold font for emphasis.");
  boldOff();
  lineFeed(1);

  underline();
  printString("Testing the underline function");
  noUnderline();
  lineFeed(1);

  inverse();
  printString("This is a Test! (Inverse)");
  notInverse();
  lineFeed(2);

  printString("this is not inverse");
  lineFeed(2);

  printSize(0x22);
  printString("This should be 3x printing");
  lineFeed(4);

  boldOn();
  underline();
  printString("and Bold");
  boldOff();
  noUnderline();
  printSize(00);
  lineFeed(10);
  doCut();
}

void loop(){
 if (goOnce){
   printDemo();
   delay(10000);
   goOnce = 0;
 }
}




robtillaart

discussion about creating lib from this code - http://forum.arduino.cc/index.php?topic=205629 -
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

mixographer

I've created some libraries for working with the common parallel receipt printers. I've seen a lot of projects that use the serial printers, but I find the parallel ones are more common, and a little cheaper. The libraries aren't finished yet, Rob T. has given me a lot of good ideas about optimizing them, but they do work now, with either an 8574 IO expander or a 595-type shift register.

You can get them or have a look on github:


https://github.com/mixographer/Thermal-Printer-I2C


You can access most of the printer functions with these libraries, such as Bold, underline, different fonts, use the cutter, etc, etc.

Have fun,

jimmy

Tubical

#3
Jul 01, 2016, 10:07 pm Last Edit: Jul 03, 2016, 01:38 am by Tubical
Hi there,

i tried to make this library to work with my thermal printer and my uno,with no luck.

But i´m sure my connections are ok, as i done a "manual" pin toggle and also single byte transfer via the PCF8574. I2C address is set to A2=0, A1=0, and A0=1 equals B0111001, "Strobe" line is routed to UNO pin 3 and "Busy" line is routed to UNO pin 2

After some quick & dirty testing this one prints out "test" on my thermal printer.

If i try to use the library instead the printer does nothing because i can´t set the I2C adress right, i tried to set the I2C address B0111001 but with no luck. Also 0x21 doesn´t work....

After all, i´m a bit confused as 0x20 isn´t equal to B0111000. And my B0111001 put in the 

printer.begin(3, 2, B0111001);

don´t print anything neither.

Any suggestions, what i have overlooked...?



Code: [Select]
/*
 ChipTest
*/

#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Sainsmart keypad LCD

#define PCF B0111001  // Address with !A2, !A1 and A0
                          // Note that the R/W bit is not part of this address, it´s the MSB and will be
                          // set via the wire.read/write

int strobe = 3;
int i = 1;

void setup() {
 Wire.begin();
 Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.print("hello, world!");

  pinMode(strobe, OUTPUT);
  digitalWrite(strobe, HIGH);
 
}

void loop() {


 delay(100);

 lcd.setCursor(0, 1);
 lcd.print ("test");
 lcd.print (" ");
 lcd.print (i);
 lcd.print (" ");
 
 Wire.beginTransmission(PCF);
 digitalWrite(strobe, LOW);
 delay (2);
 Wire.write("t");
 lcd.print(".");
 delay (2);
 digitalWrite(strobe,HIGH);
 Wire.endTransmission();
 
 delay (10);

  Wire.beginTransmission(PCF);
 digitalWrite(strobe, LOW);
 delay (2);
 Wire.write("e");
 lcd.print(".");
 delay (2);
 digitalWrite(strobe,HIGH);
 Wire.endTransmission();
 
 delay (10);

 Wire.beginTransmission(PCF);
 digitalWrite(strobe, LOW);
 delay (2);
 Wire.write("s");
 lcd.print(".");
 delay (2);
 digitalWrite(strobe,HIGH);
 Wire.endTransmission();
 
 delay (10);

 Wire.beginTransmission(PCF);
 digitalWrite(strobe, LOW);
 delay (2);
 Wire.write("t");
 lcd.print(".");
 delay (2);
 digitalWrite(strobe,HIGH);
 Wire.endTransmission();
 
 delay (500);

i++;
 
}




Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy