Go Down

Topic: Parallel Thermal Receipt Printer (Read 2836 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