Difficulties connecting thermal printer with Arduino and Processing

Hello!
I'm new to this forum - I have been using Arduino for a while but never been stuck so long on an issue like this before - Any help would be super appreciated!
I'm trying to use an arduino connected to a thermal printer as an image printer for my laptop that I could directly access from a Processing sketch.

I'm using the Adafruit thermal printer library (Overview | Mini Thermal Receipt Printers | Adafruit Learning System), which works really well, even better now I have tweaked the printing parameters.
I'm trying, however to change the sketch it so that I can send the data directly from Processing (their original workflow is very slow and includes : pre-processing the image in photoshop, converting it in processing, importing the file in arduino and then printing).
I have managed to send the print data over Serial (which consists of int width, int height, and an array of, I think, Ascii characters).
The problem, however, is reading that Serial data on the Arduino end and printing it. I'm not entirely sure how to proceed.

The function used in the example sketch is printBitmap(int w, int h, const uint8_t *bitmap, bool fromProgMem=true), which expects something stored in the Arduino's memory, however, there is another one in the library called printBitmap(Stream *fromStream). The library doesn't explain how to use that function and I haven't found help online.

I've struggled on this for a while. It might be a bit above my level but I'm hoping I can find some help or direction here.
Let me know if you want me to post my tweaks to the original code (if that helps).
I'm using an Arduino Due, so memory shouldn't be an issue.
Thanks a lot for any tips or information.

(I've included screenshots of the processing sketch and the data it sends over serial)

To me, it's unclear how your data is structured that you're sending to the Arduino. Code would certainly be useful to help debug (as well as an explanation of exactly how your sending this data).

That being said, I can explain how this function (printBitmap(Stream *fromStream)) works.

This function expects the stream data to be ordered like this:

byte 1: width lower byte
byte 2: width higher byte
byte 3: height lower byte
byte 4: height higher byte
bytes 5 - width * height + 5: image data (row major, meaning that you send the first row of image data, left to right, then the second row, etc.)

So, using this, you wouldn't need to store that data in an internal buffer on the Arduino and pass it to the library (you can see the implementation here, btw: Adafruit-Thermal-Printer-Library/Adafruit_Thermal.cpp at master · adafruit/Adafruit-Thermal-Printer-Library · GitHub)

If you need more help, post your code, and I can probably be more helpful on your particular implementation.

Thanks a lot for the info!
I've linked the two sketches as they currently are. I've tried to clean them up as best I could.

So (printBitmap(Stream *fromStream)) expects bytes instead of the ASCII characters that the Processing example files outputs? How would you go about changing that part of the code?
I imagine I must replace the first variable of this command in the Processing sketch?

datachunk.format(" 0x%02X", sum);

To send the data, I'm storing the same method as the original Processing sketch in the library, except I'm storing the variables in a String instead of a .h file, and then sending the String to Serial using a library called AP_Sync.

I feel like it's almost ok, I just need to understand the formatting better. I must admit I've never worked with bytes before, this is a bit more involved than I'm used to.

Thanks again and apologies if I'm a bit confused!

bitmap_send_to_arduino.zip (87.7 KB)

Printing_from_Processing.ino (834 Bytes)

Ok, so I THINK I see what's going on here. Yeah, that datachunk.format needs to change (and actually, you don't need to to have a whole separate string for that, it's a static method - you can just do String.format - confused me for a bit).

Easiest way would be to just convert that sum to a character and append it to your string array -

data.append((char)sum)

Then, you have to look at your actual send method - the arduino code expects the widht/height to be little endian (that is, the least significant byte) first, and it expects them to be 16-bit - in java, the int datatype is 32-bit, so you'll have to do some bit fiddling and cal lsend a little differently.

streamer.send((char)(printwidth & 0x00FF));
streamer.send((char)(printwidth & 0xFF00));
streamer.send((char)(printheight & 0x00FF));
streamer.send((char)(printheight & 0xFF00));

What I'm doing here is selecting the bottom half of the int, then the top half (by doing a bitwise AND with those bitmasks).

The rest of the processing code looks fine to me.

Then, on the Arduino side, you should just be able to call printer.printBitmap(&Serial) - it doesn't look like you even need that AP_Sync object in the arduino code. You might even be better off just using the Serial object - this library doesn't look entirely robust and looking at it, I'm not sure it's going to work properly with your use case here.

Thanks a lot!
I'll try it and keep you posted. it seems clearer now, fingers crossed I'll get it right!

BTW, looking back, I made a mistake w/ the upper bytes of those integers; should be (char)((int & 0xff00) >> 8) - needs to be shifted right 8 bits, otherwise you'll get all zeros for the upper bytes.

Alright, I've done a few things. I've followed your tips, gotten rid of Ap-sync, used the serial library instead.
on the Arduino side, i've first used printer.printBitmap(&Serial), which I then replaced by printer.printBitmap(&SerialUSB), which seems to work better. Now if finally have some proof that the arduino receives the information from Processing, but it's not quite there yet ...
When using data.append((char)sum), nothing happens, and when using data.append(String.format(" 0x%02X", sum)), the Arduino prints gibberish, but something none the less !!
I've joined a picture. I also used the command printer.println(data); to see what the arduino receives from Processing.

it seems to me that the error is in how the data after the width and height is structured ?
I might be wrong but I'm happy to see that at least it print something now.

sketch new version.zip (88.2 KB)

91505417_551098655523020_7626664300425248768_n.jpg

First line in your loop function -

data = SerialUSB.read();

This is discarding the first byte in the serial stream - possibly more that the first byte if the next byte hasn't been received yet. This line aught to be removed, as well as the printer.println(data).

I'm assuming you don't really want to print all the data in the end product, because that would be pretty long.

Also, like I mentioned in the second post, I made a mistake in how I told you to print those higher bytes. The four lines printing the width and height should be:

myPort.write((char)(printwidth & 0x00FF));
myPort.write((char)((printwidth & 0xFF00) >> 8));
myPort.write((char)(printheight & 0x00FF));
myPort.write((char)((printheight & 0xFF00) >> 8));

You definitely want to be throwing the raw bytes down the serial port, and not formatted strings. I can tell you're close - it's just small details getting in the way at this point :slight_smile:

Hi,
Thanks a lot! I've started getting it to work! It now prints the images.
I've found how to send the raw bytes directly on the adafruit forum Here
The issue I have now is sending the width and height data. It prints alright if I don't send it and declare it in the printbitmap function instead like this:

printer.printBitmap(384, 543, dynamic_cast<Stream*>(&SerialUSB));

However if I send the width and height data in Processing using:

myPort.write((char)(printwidth & 0x00FF));
myPort.write((char)((printwidth & 0xFF00) >> 8 ));
myPort.write((char)(printheight & 0x00FF));
myPort.write((char)((printheight & 0xFF00) >> 8 ));

and then print in Arduino with:

printer.printBitmap(dynamic_cast<Stream*>(&SerialUSB));

It only prints noise.

I'm attaching the Arduino and Processing sketches. At this point it's still clunky but it works so it might be useful to someone

ProcessingToArduino3.ino (482 Bytes)

bitmap_send_to_arduinoasbytes.zip (87.3 KB)

Have you tried casting to byte instead of char?

I think the problem is that "write" may be implicitly casting to int or something.

Maybe try

myPort.write(new byte[]{
    (byte)(printwidth & 0x00FF), 
    (byte)(printwidth & 0xFF00) >> 8), 
    (byte)(printheight & 0x00FF)), 
    (byte)((printheight & 0xFF00) >> 8)
});

Or something like that. I think you should also verify that these values are correct (printwidth & 0x00FF, etc). From the code I read from the library, that stuff should work, but if you can't get the library version that parses the integers to work, you could always send them before the data and parse them yourself; then you would know EXACTLY how it's parsed.

Anyways, glad you got something working!

I tried parsing the width and height data in all kinds of ways, including the one you gave me, but had no luck. Even after looking a long long time at the library and copying the way it parses that data I still end up with no print or gibberish.
I found out that the height data works with anything equal to or higher than the height of the image, so
I'll use:

printer.printBitmap(384, 3000, dynamic_cast<Stream*>(&SerialUSB));

384 is the widest image it can print, I'll resize the images in Processing to 384 in width, and as long as they're smaller than 3000 pixels in height it should work.
It's not a very elegant solution but it works...

I stand corrected. I stuck with it and now I've managed to get both width and height through Serial.

Here's the Arduino and Processing sketches if someone has the same problem. I still need to write something on the Processing end to automatically resize and dither the images, but this is already pretty good.
Thanks a lot for all the help!

ThermalPrinting from Processing with Arduino.zip (88.6 KB)