Printing images with a thermal printer + uno

Sorry for the wall of text, can't think of an accurate TL;DR version.

Hi all, first time poster here! :slight_smile:

I'm in the process of making my first Arduino project. It seemed simple at the beginning but I'm starting to have doubts about my ideas/solutions and I wanted to see if there are better ways to achieve what I want. I am not a professional programmer but I have developed other small projects in Processing, HTML/CSS/JS and Unity (C#).

Here it goes, hope everything is clear.


What are you making?

Simply put: A device which prints an image and lights an LED when a button is pressed.

The device construction is inspired by the Internet of Things Printer.

Anything else?

Multiple images are stored on a MicroSD card. Each time the button is pressed, a random image is selected and printed.

An image can only be printed once every X hours.

Nice to have: Conditional random - print all available images before re-printing something.

What hardware are you using?

  • Arduino Uno
  • Adafruit Thermal Printer [[/url][/li]
  • Sparkfun MicroSD shield [[/url][/li]
  • A push button
  • An LED
    [/list]
  • What have you done so far?*

Hardware:

  • Connected both the printer and the SD card reader.
  • Calibrated the printer to have a decent image output
  • Connected a push button
  • Connected an LED

Software:

  • Tracking time since boot to restrict printing based on an interval
  • Made button to fire a function when pressed
  • Made LED light up if printing is allowed and started
  • Made a pipeline to generate complete .h files from the .jpgs I want to print (there's a lot of them). Printer can't read jpg (duh) so it needs a data object with all pixel information in hex.

Doesn't sound like much but it took me ages to put everything together.


My initial plan was to create the header files (corresponding to each image) on my PC and copy them on the SD card.
At Arduino runtime I would assign a random image to a myFile object and pass that through the print function as such:

printer.printBitmap(myFile_width, myFile_height, myFile_data);

Since I have no previous experience with Arduino or C, I miserably failed to see the obvious which is that .h files get compiled along with the rest of the sketch. So it's pointless to read them from the SD card.

I then thought of pre-compiling them outside of the sketch and putting the .c files on the SD card but my gut is telling me that this is not really a good way to go so that's why I made this post.

Any ideas on how to store and access these images?
Any ideas on a functional/optimal different approach altogether?

Any help is appreciated. Thanks!](SparkFun microSD Shield - DEV-12761 - SparkFun Electronics)](Mini Thermal Receipt Printer : ID 597 : $49.95 : Adafruit Industries, Unique & fun DIY electronics and kits)

First question is the size of the image data. If all images together fit into (PROGMEM) memory, you don’t need a SD card.

Otherwise write a sketch to transfer the image data from the declaration in one header file to the SD card. Then exchange the header file and SD card file name, and continue until all image files have been written. Then write another sketch that reads an image from the SD card and sends it to the printer. You may have to read parts (scan lines?) from the file, which fit into a buffer array in RAM, and send the buffer to the printer, until the whole image is printed.

treipatru:
Printer can’t read jpg (duh) so it needs a data object with all pixel information in hex.

Doesn’t sound like much but it took me ages to put everything together.

Neither your Arduino can read and decode JPG pictures, nor can your printer print something different than black dots on white paper.

So the first step would be to use a graphics software and convert the pictures into

  • a data format that can be read by your Arduino
  • a data format that can be printed by your printer (black-and-white graphics with 1-bit color-depth)

A simple and uncompressed data format which can be read from your Arduino would be BMP.

And for rendering a RGB color or greyscale picture into a 1-bit color depth b/w picture your graphics software should offer a “dithering” function.

After you have created at least one suitable file for printing, you then can go and develop a printing function.

@jurs I'm already doing that. I am using PS to convert to 1Bit depth BMP with dithering then I am running a (completely separate) Processing sketch on my computer to convert said files to .h header files as requested by the printer library.

Here's an example:

I have managed to successfully print multiple images like this.

@DrDiettrich An image fits in the Arduino memory just fine, that's how I printed a lot of tests so far but I have 500+ images that need to be crammed in the final product.

I can just copy the header files on the SD card (with my computer) but aren't header files supposed to be compiled when the software is uploaded to the board? Thus making my .h files on the SD card unusable by the program?!

DrDiettrich:
Otherwise write a sketch to transfer the image data from the declaration in one header file to the SD card.

This is what I was thinking of doing but I have no idea how to approach this. I can't understand exactly how the data must look like on the SD card so it's readily accessible by the software at runtime.

Any directions to research?! Does it even seem doable?

Thanks!

I think it's pretty clear the first thing you need to do is just print a bitmap. Don't worry about LEDs or timing or any of the other details you want in your final program just print a bitmap.

Adafruit shows how to do this.

It doesn't look like you've taken this step yet. Did I miss it? Edit: Sorry, I did miss it.

Once you've printed a simple small bitmap, you can worry about getting your other bitmaps in the right format to be read from the SD card.

Edit: Sorry, I hadn't read the thread carefully enough.

treipatru:
I have managed to successfully print multiple images like this.

I'll think about this and hopefully have something useful to add later. Sorry for missing such an important point.

How would you like the file on the SD card to look? Do you want raw data (a smaller file) or do you want the data saved as human readable ASCII text?

It sure seems like it shouldn't be too hard to parse data from a SD card to replace the data block in the Adafruit example.

Do you have a simple sketch with just a small bitmap? If so, post it and I'll see if can help figure out how to read the bitmap from a SD card.

Edit: Nevermind about the example. I see one of Adafruit's examples includes a bitmap.

It is my understanding that .h files get compiled along with the rest of the sketch.

As such, I can't store all my images as IMG001.h, IMG002.h, IMG003.h, IMG004.h etc. on the SD card because the program can't read them at runtime because they're not compiled.

There are too many images to be stored in the flash memory so that is definitely not an option. So I am trying to figure out a way to store images on the SD card in a format which the Arduino can read and transmit to the printer at runtime.

Is it possible to just store the hex data for each file in a txt and load that into an image object for the printer? I had assumed a clear no after researching a bit before my initial post.

Anyway, here's a sample code which simply prints an image.

#include "Adafruit_Thermal.h"
#include "adalogo.h"

#include "SoftwareSerial.h"
#define TX_PIN 6 // Transmit pin
#define RX_PIN 5 // Receive pin

SoftwareSerial mySerial(RX_PIN, TX_PIN); // Declare SoftwareSerial obj first
Adafruit_Thermal printer(&mySerial);     // Pass addr to printer constructor


void setup() {


  mySerial.begin(19200);  // Initialize SoftwareSerial
  printer.begin();        // Init printer (same regardless of serial type)


  // Print the 75x75 pixel logo in adalogo.h:
  printer.printBitmap(adalogo_width, adalogo_height, adalogo_data);
  printer.feed(2);

  printer.sleep();      // Tell printer to sleep
  delay(3000L);         // Sleep for 3 seconds
  printer.wake();       // MUST wake() before printing again, even if reset
  printer.setDefault(); // Restore printer to defaults
}

void loop() {
}

And here is adalogo.h - the header file with the image data

#ifndef _adalogo_h_
#define _adalogo_h_

#define adalogo_width  75
#define adalogo_height 75

static const uint8_t PROGMEM adalogo_data[] = {
  0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x01,0xf0,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x03,0xf0,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x03,0xf8,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x07,0xf8,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x0f,0xf8,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x1f,0xfc,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x1f,0xfc,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x3f,0xfc,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x7f,0xfe,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x7f,0xfe,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0xff,0xfe,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x01,0xff,0xff,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x03,0xff,0xff,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x03,0xff,0xff,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x07,0xff,0xff,0x80,0x00,0x00,0x00,
  0x00,0x00,0x00,0x07,0xff,0xff,0x80,0x00,0x00,0x00,
  0x00,0x00,0x00,0x07,0xff,0xff,0x80,0x00,0x00,0x00,
  0x00,0x00,0x00,0x0f,0xff,0xff,0x80,0x00,0x00,0x00,
  0x00,0x00,0x00,0x0f,0xff,0xff,0x80,0x00,0x00,0x00,
  0x7f,0xff,0xfc,0x0f,0xff,0xff,0x80,0x00,0x00,0x00,
  0xff,0xff,0xff,0x0f,0xff,0xff,0x80,0x00,0x00,0x00,
  0xff,0xff,0xff,0xcf,0xff,0xff,0x80,0x00,0x00,0x00,
  0xff,0xff,0xff,0xef,0xff,0xff,0x80,0x00,0x00,0x00,
  0x7f,0xff,0xff,0xf7,0xff,0xff,0x80,0x00,0x00,0x00,
  0x3f,0xff,0xff,0xff,0xfb,0xff,0x00,0x00,0x00,0x00,
  0x3f,0xff,0xff,0xff,0xf1,0xff,0x3f,0xf0,0x00,0x00,
  0x1f,0xff,0xff,0xff,0xf1,0xfe,0xff,0xfe,0x00,0x00,
  0x0f,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xc0,0x00,
  0x0f,0xff,0xff,0xff,0xe1,0xff,0xff,0xff,0xf8,0x00,
  0x07,0xff,0xff,0xff,0xe1,0xff,0xff,0xff,0xff,0x00,
  0x03,0xff,0xff,0xff,0xe1,0xff,0xff,0xff,0xff,0xc0,
  0x01,0xff,0xff,0x3f,0xe1,0xff,0xff,0xff,0xff,0xe0,
  0x01,0xff,0xfe,0x07,0xe3,0xff,0xff,0xff,0xff,0xe0,
  0x00,0xff,0xff,0x03,0xe3,0xff,0xff,0xff,0xff,0xe0,
  0x00,0x7f,0xff,0x00,0xf7,0xff,0xff,0xff,0xff,0xc0,
  0x00,0x3f,0xff,0xc0,0xff,0xc0,0x7f,0xff,0xff,0x80,
  0x00,0x1f,0xff,0xf0,0xff,0x00,0x3f,0xff,0xff,0x00,
  0x00,0x0f,0xff,0xff,0xff,0x00,0x7f,0xff,0xfc,0x00,
  0x00,0x07,0xff,0xff,0xff,0x01,0xff,0xff,0xf8,0x00,
  0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
  0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,
  0x00,0x00,0x1f,0xfc,0x7f,0xff,0xff,0xff,0x80,0x00,
  0x00,0x00,0x7f,0xf8,0x78,0xff,0xff,0xfe,0x00,0x00,
  0x00,0x00,0xff,0xf0,0x78,0x7f,0xff,0xfc,0x00,0x00,
  0x00,0x01,0xff,0xe0,0xf8,0x7f,0xff,0xf0,0x00,0x00,
  0x00,0x03,0xff,0xc0,0xf8,0x3f,0xdf,0xc0,0x00,0x00,
  0x00,0x07,0xff,0xc1,0xfc,0x3f,0xe0,0x00,0x00,0x00,
  0x00,0x07,0xff,0x87,0xfc,0x1f,0xf0,0x00,0x00,0x00,
  0x00,0x0f,0xff,0xcf,0xfe,0x1f,0xf8,0x00,0x00,0x00,
  0x00,0x0f,0xff,0xff,0xff,0x1f,0xf8,0x00,0x00,0x00,
  0x00,0x1f,0xff,0xff,0xff,0x1f,0xfc,0x00,0x00,0x00,
  0x00,0x1f,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,
  0x00,0x1f,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,
  0x00,0x3f,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,
  0x00,0x3f,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,
  0x00,0x3f,0xff,0xff,0x3f,0xff,0xfe,0x00,0x00,0x00,
  0x00,0x7f,0xff,0xff,0x3f,0xff,0xfe,0x00,0x00,0x00,
  0x00,0x7f,0xff,0xff,0x3f,0xff,0xfe,0x00,0x00,0x00,
  0x00,0x7f,0xff,0xfe,0x3f,0xff,0xfe,0x00,0x00,0x00,
  0x00,0xff,0xff,0xfc,0x1f,0xff,0xfe,0x00,0x00,0x00,
  0x00,0xff,0xff,0xf8,0x1f,0xff,0xfe,0x00,0x00,0x00,
  0x00,0xff,0xff,0xe0,0x0f,0xff,0xfe,0x00,0x00,0x00,
  0x01,0xff,0xff,0x80,0x07,0xff,0xfe,0x00,0x00,0x00,
  0x01,0xff,0xfc,0x00,0x03,0xff,0xfe,0x00,0x00,0x00,
  0x01,0xff,0xe0,0x00,0x01,0xff,0xfe,0x00,0x00,0x00,
  0x01,0xff,0x00,0x00,0x00,0xff,0xfe,0x00,0x00,0x00,
  0x00,0xf8,0x00,0x00,0x00,0x7f,0xfe,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x1f,0xfe,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x0f,0xfe,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x07,0xfe,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x01,0xfe,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00
};

#endif // _adalogo_h_

Additionally, here's what the printBitmap function from the thermal printer library does. Linked to hastebin as I'm going over my charlimit for the post.

http://hastebin.com/ororupejuy.coffee

While a header file can be compiled that does not stop you storing it on an SD card and reading it byte by byte in your code.

Yes you can store your image as a HEX file and read that back a byte at a time as well.

treipatru:
There are too many images to be stored in the flash memory so that is definitely not an option. So I am trying to figure out a way to store images on the SD card in a format which the Arduino can read and transmit to the printer at runtime.

Is it possible to just store the hex data for each file in a txt and load that into an image object for the printer?

If you have the data, you can store it in any format and where you want.
I.e. store as bytes on a SD card file.

But most likely you cannot load that file "all in one" from file to RAM, due to very limited RAM size.

As I can see the library you are using can print from RAM or from PROGMEM flash:

   printBitmap(int w, int h, const uint8_t *bitmap, bool fromProgMem=true),

But it has also a function to print from a "Stream":

   printBitmap(int w, int h, Stream *fromStream),

For printing from file you will most likely have to use that and print from the file (stream) to the printer.

Thank you both for your answers, this really helped me narrow down what’s going on but I’m not quite there yet. Sorry for being so difficult but it’s the first time I’m doing such low-level stuff and there were quite a few things I needed to catch up to.

So I’ve managed to open and stream the contents of a file to the serial monitor but I can’t for the life of me understand how I can pass that stream to the printer. I know the stream will probably need some parsing (in the final form) but I’ll deal with that after I at least get some garbled images on paper.

Maybe some of you more experienced gentlemen coders can better understand how the printBitmap function is written.

void Adafruit_Thermal::printBitmap(
 int w, int h, const uint8_t *bitmap, bool fromProgMem) {
  int rowBytes, rowBytesClipped, rowStart, chunkHeight, chunkHeightLimit,
      x, y, i;

  rowBytes        = (w + 7) / 8; // Round up to next byte boundary
  rowBytesClipped = (rowBytes >= 48) ? 48 : rowBytes; // 384 pixels max width

  // Est. max rows to write at once, assuming 256 byte printer buffer.
  if(dtrEnabled) {
    chunkHeightLimit = 255; // Buffer doesn't matter, handshake!
  } else {
    chunkHeightLimit = 256 / rowBytesClipped;
    if(chunkHeightLimit > maxChunkHeight) chunkHeightLimit = maxChunkHeight;
    else if(chunkHeightLimit < 1)         chunkHeightLimit = 1;
  }

  for(i=rowStart=0; rowStart < h; rowStart += chunkHeightLimit) {
    // Issue up to chunkHeightLimit rows at a time:
    chunkHeight = h - rowStart;
    if(chunkHeight > chunkHeightLimit) chunkHeight = chunkHeightLimit;

    writeBytes(ASCII_DC2, '*', chunkHeight, rowBytesClipped);

    for(y=0; y < chunkHeight; y++) {
      for(x=0; x < rowBytesClipped; x++, i++) {
        timeoutWait();
        stream->write(fromProgMem ? pgm_read_byte(bitmap + i) : *(bitmap+i));
      }
      i += rowBytes - rowBytesClipped;
    }
    timeoutSet(chunkHeight * dotPrintTime);
  }
  prevByte = '\n';
}

void Adafruit_Thermal::printBitmap(int w, int h, Stream *fromStream) {
  int rowBytes, rowBytesClipped, rowStart, chunkHeight, chunkHeightLimit,
      x, y, i, c;

  rowBytes        = (w + 7) / 8; // Round up to next byte boundary
  rowBytesClipped = (rowBytes >= 48) ? 48 : rowBytes; // 384 pixels max width

  // Est. max rows to write at once, assuming 256 byte printer buffer.
  if(dtrEnabled) {
    chunkHeightLimit = 255; // Buffer doesn't matter, handshake!
  } else {
    chunkHeightLimit = 256 / rowBytesClipped;
    if(chunkHeightLimit > maxChunkHeight) chunkHeightLimit = maxChunkHeight;
    else if(chunkHeightLimit < 1)         chunkHeightLimit = 1;
  }

  for(rowStart=0; rowStart < h; rowStart += chunkHeightLimit) {
    // Issue up to chunkHeightLimit rows at a time:
    chunkHeight = h - rowStart;
    if(chunkHeight > chunkHeightLimit) chunkHeight = chunkHeightLimit;

    writeBytes(ASCII_DC2, '*', chunkHeight, rowBytesClipped);

    for(y=0; y < chunkHeight; y++) {
      for(x=0; x < rowBytesClipped; x++) {
        while((c = fromStream->read()) < 0);
        timeoutWait();
        stream->write((uint8_t)c);
      }
      for(i = rowBytes - rowBytesClipped; i>0; i--) {
        while((c = fromStream->read()) < 0);
      }
    }
    timeoutSet(chunkHeight * dotPrintTime);
  }
  prevByte = '\n';
}

void Adafruit_Thermal::printBitmap(Stream *fromStream) {
  uint8_t  tmp;
  uint16_t width, height;

  tmp    =  fromStream->read();
  width  = (fromStream->read() << 8) + tmp;

  tmp    =  fromStream->read();
  height = (fromStream->read() << 8) + tmp;

  printBitmap(width, height, fromStream);
}

treipatru:
I can't for the life of me understand how I can pass that stream to the printer.

I'd say: open the file, pass the file handle to the function, close the file.

Something like perhaps:

  myFile = SD.open("example.bin", FILE_READ);
  printBitmap(width, height, myFile);
  myFile.close();

with the file "example.bin" containing the binary image data.

Can you print a large bitmap in sections?

You could move sections of a bitmap into RAM and print these sections one after another. I don't think this would require modifying the printer library.

I think another easier (than modifying the library) solution would be to use the library just to set up the printer and then (when it came time to print a bitmap) control the printer directly from your sketch.

I think it's pretty clear the library does something to put the printer in a mode so it's ready to receive a bitmap one byte at a time. It shouldn't be too hard to figure out how to do this without having the library doing it for you.

I think good start would be to save a text file with the hex data you want printed, and then be able to open the file and display these values as numeric information. You could use the hex notation "0X" as indicators there's a new byte to read and convert the two following characters into a numeric value.

I don't think it will be too hard to send this numeric data to the printer.

Poking around the interwebs I've found that there's a ruby script to prep images specifically for storage on the SD card.

The script is actually included in the library but I didn't check since I've never used ruby before. I now have ruby on my machine and am generating proper files and data to feed to the printer as per the developer of the library. Everything looks A-OK!

Now, on to actually printing a file.

I assume the most direct approach is this:

File myFile = SD.open ("test.cpp", FILE_READ); //open file
printer.printBitmap(myFile.read());  //call the printBitmap function
myFile.close();  //close file

If I run it like this I am getting this error:

sandbox.ino: In function 'void setup()':
sandbox.ino:31:35: error: invalid conversion from 'int' to 'Stream*' [-fpermissive]
In file included from sandbox.ino:7:0:
C:\Users\Andrei34\Documents\Arduino\libraries\Adafruit_Thermal_Printer/Adafruit_Thermal.h:148:5: error:   initializing argument 1 of 'void Adafruit_Thermal::printBitmap(Stream*)' [-fpermissive]
     printBitmap(Stream *fromStream),
     ^
Error compiling.

Is the way I'm reading the data wrong?
Do I need to make some sort of conversion while reading the data from the file and before sending it to the printer?

Reading through the library code I keep seeing Stream *fromStream where the data object should be. I know that * is a C Pointer but I have no idea what it does and what are the specific implications to this case in particular.

void Adafruit_Thermal::printBitmap(int w, int h, Stream *fromStream) {

void Adafruit_Thermal::printBitmap(Stream *fromStream) {

Thanks for all the help so far!

treipatru:
Is the way I'm reading the data wrong?

As far as I know the "File" class in the SD library is derived from the "Stream" class.

So perhaps you just need to call the function with the File object:

printer.printBitmap(myFile);  //call the printBitmap function

or use a type casting to "Stream*":

printer.printBitmap((Stream*)myFile);  //call the printBitmap function

I don't know. I don't have the printer hardware and I don't have the library for it.

BTW: "test.cpp" sounds like a file containing ASCII text (most likely C code), and not like a binary picture file.

treipatru:
And here is adalogo.h - the header file with the image data

#define adalogo_width  75

#define adalogo_height 75

static const uint8_t PROGMEM adalogo_data = {
  0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,
...
};

Include this header into your conversion sketch, then store the values in a file on the SD card.
For the width and heigth you declare variables, like
const int width = adalogo_width, height = adalogo_height;
Then open the new image file on the SD card, and write width, height and adalogo_data to that file.

For printing you open the file, read the image width and height into variables.
Then read the image data (width*height bytes) into a byte array, and pass all that to the printer.

When the image is too big to fit into RAM, then you create a buffer array like
uint8_t image[MAX_WIDTH]; //width of your widest image or printer width
and read the image in a loop, one scanline at a time, which you can send to the printer.

Hey guys, thanks for the replies!

The problem I am facing is that I can't send shit to the printer through the streaming option of the printBitmap function!
I can't figure out if it is a problem of how I am reading the data or if it's the format/encoding of feeding it to the printer. Please check again post #12

This is why I was asking if anyone can better understand the print/stream function of the library. (github//line 473)

Otherwise I am aware of how the data is structured and what needs needs to be declared in order for a print to happen correctly, I've done this with images stored on the flash. Eventually all my images are the same size - both W and H - so I can store that as a const easily.

I believe that even if I try to make a buffer the problem lies within the reading of the data.

So for this code which I think should work:

  File myFile = SD.open ("hex.txt", FILE_READ);
  while (myFile.available()) {
    printer.printBitmap(myFile.read());
  }
  myFile.close();

I receive this error:

Arduino: 1.7.8 (Windows 8.1), Board: "Arduino Uno"

sandbox.ino: In function 'void setup()':

sandbox.ino:33:37: error: invalid conversion from 'int' to 'Stream*' [-fpermissive]

In file included from sandbox.ino:7:0:

C:\Users\Andrei34\Documents\Arduino\libraries\Adafruit_Thermal_Printer/Adafruit_Thermal.h:148:5: error:   initializing argument 1 of 'void Adafruit_Thermal::printBitmap(Stream*)' [-fpermissive]

     printBitmap(Stream *fromStream),

     ^

Error compiling.

This makes me think that at least this gives the function correct parameters which it is expecting but it's not in the right format. Any other use of the function returns an error saying I'm not using the correct arguments.

What do you think?! I really feel I'm hitting a brick wall here.

Provided that File is a Stream, try printer.printBitmap(myFile);

I receive this error:

This is a syntax error, this means that the compiler got lost with what you are trying to do. Just because a compiler can follow what you are trying to do does not make it the correct thing to do but first things first.

This makes me think that at least this gives the function correct parameters which it is expecting but it's not in the right format.

No the compiler has no idea that the data is correct but in the wrong format.

invalid conversion from 'int' to 'Stream*'

What this means is that the data you are telling it to use can not / should not be converted from the form you give it into the form it needs.

This is the big big problem with using libraries that you don't understand. Once you go outside the scope of what that library was designed to do you are sunk and need to rewrite the library or find another way to complete your task.

So it’s done. I found some answers on the adafruit forum… which I didn’t even know existed since it seems that it’s not indexed by google.

The first part of the problem was to issue the right parameters; here’s how the correct command looks like, or at least what’s working for me:

printer.printBitmap(printWidth, printHeight, dynamic_cast<Stream*>(&myFile));

Would love it if anyone can comment on why/how this works - dynamic_cast<Stream*>(&myFile). Is it just part of the printer library or will I possibly need it while trying to build something else in the future?

The second part was transforming the bitmaps from images to binary files before saving to the SD card. I used a processing script from the same thread.

It’s been so difficult but having struggled so much at least I understood a lot more about low level data wrangling. I haven’t felt this technologically impaired since I installed gentoo 10 years ago.

If anyone is interested I’ll post a link when the project is done.

Grumpy_Mike:
This is the big big problem with using libraries that you don’t understand. Once you go outside the scope of what that library was designed to do you are sunk and need to rewrite the library or find another way to complete your task.

You make a valid point however this particular library seems fairly well documented and is quite small. I do not have enough C experience and that’s why I was asking for opinions.
Some libraries are indeed quite complex and it is a nightmare to extend them or modify them but I don’t feel that it was the case here, I just didn’t have sufficient knowledge to dive right in.

Thanks you all for your time and replies!

About
printer.printBitmap(printWidth, printHeight, dynamic_cast<Stream*>(&myFile));
where myFile is of type (SD) File class.

The File class inherits from the Stream class, so that a variable (object) of that type can be used wherever a Stream type is required. The dynamic_cast<Stream*> instructs the compiler to “extract” that base class from the File object.

When you have a closer look at various library classes, Serial and other communication classes also include (inherit from) the Stream class, or take arguments of type Stream. This makes Stream the “glue” that allows to connect many different data sources to many different data consumers.