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:
#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;
}
}