Problem converting BMP into correct OLED image. (SOLVED)

SVFeingold:
I'm not sure what you mean, how are you printing it?

Thus:

const unsigned char stern [] = {
0x20, 0x30, 0x78, 0x30, 0x33, 0x2D, 0x23, 0x33, 0x7A, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x33,
0x33, 0x2C, 0x20, 0x30, 0x7B, 0x30, 0x30, 0x2C, 0x23, 0x33, 0x7B, 0x35, 0x3A, 0x2C, 0x20, 0x31,
0x7A, 0x30, 0x30, 0x2C, 0x23, 0x33, 0x7B, 0x32, 0x30, 0x2C, 0x23, 0x32, 0x78, 0x33, 0x43, 0x2F,
0x20, 0x33, 0x7B, 0x33, 0x32, 0x2F, 0x0C, 0x08, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78
};

void setup()
{
  Serial.begin(115200);
  Serial.println ((const char *) stern); 
}

void loop(){}

It just doesn't look like bitmap data to me.

Put it this way, when I converted your bitmap with that program I got something like this:

//------------------------------------------------------------------------------
// File generated by LCD Assistant
// http://en.radzio.dxp.pl/bitmap_converter/
//------------------------------------------------------------------------------

const unsigned char stern [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x30, 0x00, 0x00,
0x04, 0x54, 0x44, 0x64, 0x6B, 0x77, 0x04, 0x44, 0x64, 0x68, 0x77, 0x33, 0x04, 0x4C, 0x64, 0x64,
0x74, 0x00, 0x30, 0x00, 0x54, 0x6C, 0x70, 0x00, 0x24, 0x04, 0x54, 0x68, 0x64, 0x74, 0x68, 0x00,
0x30, 0x04, 0x48, 0x64, 0x68, 0x64, 0x68, 0x74, 0x00, 0x14, 0x08, 0x54, 0x60, 0x60, 0x4C, 0x70,
...

Ah, I see. Yes, the data you showed as the output is the same thing I got. I removed most of it from the code because it kept exceeding the max character limit for the post, but left a little bit (the last part) just to show the kind of data I was getting.

I see now about the serial output, but it seems as though it attempts to convert the hex data into ASCII characters. Shouldn't this be more or less irrelevant as I'm not sending data as an ASCII string but as direct pixel values? I just want to make sure we're on the same page.

Now I am really confused. It seemed strange that I'm getting so much gibberish and not even a semblance of an image. I tried loading a completely empty, white bitmap into the program, and here is the output I get:

const unsigned char test2 [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x30, 0x38, 0x2C,
0x0C, 0x08, 0x30, 0x78, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78,
0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x34, 0x38, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20,
0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30,
0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x34, 0x40, 0x2C, 0x20, 0x30, 0x78,
0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x44, 0x2C, 0x20,
0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x34, 0x40,
0x2C, 0x0C, 0x08, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x34, 0x34, 0x2C, 0x20, 0x30,
0x78, 0x30, 0x44, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C,
0x20, 0x30, 0x78, 0x34, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30,
0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x44, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30,
0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x34, 0x38, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C,
0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30,
0x30, 0x2C, 0x0C, 0x08, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x34, 0x40, 0x2C, 0x20,
0x30, 0x78, 0x30, 0x34, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x44,
0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78,
0x34, 0x38, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20,
0x30, 0x78, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30,
0x2C, 0x20, 0x30, 0x78, 0x34, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x34, 0x2C, 0x20, 0x30, 0x78,
0x30, 0x34, 0x2C, 0x0C, 0x08, 0x30, 0x78, 0x30, 0x44, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C,
0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x34, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30,
0x30, 0x2C, 0x20, 0x30, 0x78, 0x34, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x40, 0x2C, 0x20, 0x30,
0x78, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x38, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C,
0x20, 0x30, 0x78, 0x34, 0x38, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30,
0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30,
0x78, 0x30, 0x30, 0x2C, 0x0C, 0x08, 0x30, 0x78, 0x34, 0x38, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x30,
0x2C, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2C, 0x20, 0x30, 0x78, 0x30, 0x40, 0x2C, 0x20, 0x30, 0x78,....

Starts out good for the first 16 lines, and then it looks just like a bunch of random values. I guess this program is garbage then?

Made a little progress, tried using a different program (bmp2h_conv) which is OK but doesn't seem to support the kind of output I need entirely. Also it is continually crashing over some error that looks like bad coding to me. Why a simple, robust program that can do this doesn't exist is beyond me, it seems like a common enough task that someone might just make a damn image converter that is straightforward.

No matter, after redoing the image with this program and adding in the Flash library to write this array to Flash and avoid memory limitations, I see this:

Still looks like garbage but at least it's halfway recognizable that there should be an image there! This may be the fault of the program, it is giving me 3072 bytes - too many. Should be half that number.

Yes your original program looks buggy.

Sweet merciful Jesus!

FINALLY I found a program that works for this. I must have downloaded every BMP converter from every shady website out there before finding this: http://www.novatronica.it/files/ODTv1.1.11278.zip

This is the ONLY program I have found that both supports 4 bit pixels (along with 1 bit) AND works.

I guess this means the problem is solved? I feel silly for such a long thread now...

It has been a long day!

It's been useful. Didn't Thomas Edison say something like "I haven't failed. I just found 1000 things that didn't work".

Well you have done something similar, and shared your findings which will hopefully help others.

I sure hope so, I feel so accomplished after slogging through this process (with your help of course!) that I would be sad if I couldn't help someone else with it. This display is very nice but wow, the only community "support" is people complaining about getting it to work.

EDIT: Just one more for fun. :smiley:

Now to delve into the issue of the horizontal banding...

Looks like I'm not completely out of the woods yet...now I am having problems with the display not clearing fully. Here is what it looks like with another sample image:

All those little random dots and lines on the top and bottom? That's bits of old images that were on the screen showing through. It's as if each new image is just being pasted on top of the old ones, with whatever "uncovered" parts showing through.

Comments:

  1. If I scale the image down to, say 50% and display it on the screen, I see just the image and the rest of the screen is blank as it should be.
  2. This only happens with a full size (256 x 64) image, but it shouldn't because the image should cover the entire screen! There are no "empty" parts. For instance if I upload an image with a few lines of text, in between the lines I will see old images that were on the screen. This doesn't make sense!
  3. I am completely clearing the screen with a command in my code; i.e. filling the ENTIRE display RAM with 0's. If I slow down the SPI bus enough I can even see it "wipe" the screen, but once the image is loaded...I still see the remnants on the edges!
  4. I tried using different variables for the array - which is being stored in FLASH memory using the Flash library. My thinking was that maybe, somehow, the old array was not being completely overwritten. Still does not make a difference.
  5. There is no way the old data is getting transmitted when I upload the sketch; there is only a single array and I am completely replacing it each time.

The "Tough Mudder" image I posted was the first full image to be displayed on the screen, every new image after that contains just a little bit of all previous images. I'm seriously confused!

My main code:

/* This is the main code for the control system. It has been modified to work with the Arduino
Pro Mini 3.3V board. Check that the pin assignments match the actual circuit. 

4-10-12
*/


#include <SPI.h>
#include <Flash.h>

FLASH_ARRAY(unsigned char, test,
DATA OMITTED FOR LENGTH
);


const int valve = 3;           // Output to SSR that switches valve
const int button = 4;          // 3.3V button signal
const int displayDC = 5;       // OLED display data control
const int displayReset = 6;    // OLED display reset 
const int displaySelect = 7;   // OLED display SPI slave select
const int interlock = 8;       // Input from interlock 
const int lightSensor = A0;    // Input from ambient light sensor


int brightness = 0;
int fadeamount = 1;  

void setup(){
  
  digitalWrite(displaySelect,HIGH);
  digitalWrite(valve,HIGH);
  pinMode(valve, OUTPUT);
  pinMode(displaySelect, OUTPUT);
  pinMode(displayReset, OUTPUT);
  pinMode(displayDC, OUTPUT);

  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  SPI.setDataMode(SPI_MODE3);
  SPI.begin();
  analogReference(DEFAULT);
  OLED_Init(); 
  clear_Screen();


/* This code sends a full image to the display. Because each byte
contains two 4 bit grayscale pixels, 8192 bytes are needed to fill the
complete 16384 pixel screen. 

SPI.transfer is explicitly called because the "oled_Data()" function
toggles the display select and data control lines before and after each byte.
The greatly reduces the transfer speed and results in a noticeable "wipe" 
as the data is loaded to RAM. */ 
  unsigned int i;
	
	Set_Column_Address(0x1C,0x5B);
	Set_Row_Address(0x00,0x3F);
	Set_Write_RAM();
        digitalWrite(displaySelect,LOW);
        digitalWrite(displayDC,HIGH);
	for(i=0;i<8192;i++)
	{
               SPI.transfer(test[i]);
	}
        digitalWrite(displaySelect,HIGH);
}

void loop(){
  
  while (digitalRead(button)){
    Set_Contrast_Current(brightness);
    brightness = brightness + fadeamount;
    if (brightness == 0 || brightness == 255){
      fadeamount = -fadeamount;
    }
    delay(5);
  }
  
 // Toggles between normal and inverse display every second
  Set_Display_Mode(0x03);
  delay(1000);
  Set_Display_Mode(0x02);
  delay(1000);

}

There is no command in the OLED datasheet to clear the screen, only to write to the RAM whatever values you desire. I am using this function to do so:

void clear_Screen()
{
  Set_Column_Address(0x00,0x77);
  Set_Row_Address(0x00,0x7F);
  Set_Write_RAM();
  digitalWrite(displaySelect,LOW);
  digitalWrite(displayDC,HIGH);
  for(unsigned int i=0; i<30720; i++){
    SPI.transfer(0x00);
  }
  digitalWrite(displaySelect,HIGH);
}

This should clear the ENTIRE ram contents. 120 columns, 127 rows -> 480 pixels x 128 pixels = 61440 pixels / 2 pixels per byte = 30720 bytes.

I just uploaded this image:

...and I get this result:

I suspect something strange may be going on in the Arduino FLASH memory, or perhaps with the display itself even though there is nothing in the datasheet to suggest this kind of behavior should even be possible.

So, again, I am asking for help. I am sure someone has seen this type of behavior before.

EDIT: Now when I upload I get this:

Binary sketch size: 11134 bytes (of a 30720 byte maximum)
avrdude: verification error, first mismatch at byte 0x00bd
         0xff != 0xfe
avrdude: verification error; content mismatch

What?

  Set_Row_Address(0x00,0x7F);

Where's the datasheet? Why don't you start at row 0?

Binary sketch size: 11134 bytes (of a 30720 byte maximum)
avrdude: verification error, first mismatch at byte 0x00bd
0xff != 0xfe
avrdude: verification error; content mismatch

There a bug in the bootloader where trailing 0xFF are not written. Try to put some other byte (eg. 0x01) as the last data byte in the sketch.

The datasheet is linked in the first post. Here it is again: http://www.newhavendisplay.com/app_notes/SSD1322.pdf

Here are the row and column functions:

void Set_Column_Address(unsigned char a, unsigned char b)
{
	oled_Command(0x15);			// Set Column Address
	oled_Data(a);				//   Default => 0x00
	oled_Data(b);				//   Default => 0x77
}

//--------------------------------------------------------------------------

void Set_Row_Address(unsigned char a, unsigned char b)
{
	oled_Command(0x75);			// Set Row Address
	oled_Data(a);				//   Default => 0x00
	oled_Data(b);				//   Default => 0x7F
}

And then the command and data functions:

//--------------------------------------------------------------------------
//send Command to OLED
//--------------------------------------------------------------------------
void oled_Command(unsigned char Data)
{
  
unsigned char i;	  //begin 4-wire serial mode
  digitalWrite(displayDC,LOW);
  digitalWrite(displaySelect,LOW);
  SPI.transfer(Data);
  digitalWrite(displayDC,HIGH);
  digitalWrite(displaySelect,HIGH);
}

//--------------------------------------------------------------------------
//send Data to OLED
//--------------------------------------------------------------------------
void oled_Data(unsigned char Data)
{
unsigned char i;	 
  digitalWrite(displayDC,HIGH);
  digitalWrite(displaySelect,LOW);

  SPI.transfer(Data);
  
  digitalWrite(displaySelect,HIGH);
}

When using the row and column address functions, the first byte sent is the command byte. So when calling Set_Row_Address(A,B), A is the first address and B is the last address, and it writes to all addresses between the two.

The addresses corresponding to this display are column: 0x1C to 0x5B (28 - 91; 256 pixels with 4 pixels/column) and the row addresses are 0x00 to 0x3F (0 to 63; 64 pixels for the display height).

Does the bootloader error affect the performance of the program? If I leave the void loop() section blank, the last byte sent should be a 0x01, as that is the last byte in the image array and the last function performed in void setup() is to write the image and de-select the display. I still get the same error though:

Binary sketch size: 11036 bytes (of a 30720 byte maximum)
avrdude: verification error, first mismatch at byte 0x00bd
         0xff != 0xfe
avrdude: verification error; content mismatch

Last part of my image array:

.......0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x01
);

I should also add that I've tried using this code in "void loop()"

void loop(){

    if (digitalRead(button)){
        clear_Screen();
    }
}

So once the image is loaded (Same as the most recent image I posted with the two lines of text), pressing a button attached to a digital input runs the clear screen function. This function has been modified to only address the parts of the display RAM corresponding to this specific screen. Otherwise it takes much longer to clear the screen, but I also wanted to test if there was some error in my loop that iterates through each element of the image array.

Here is the modified clear_Screen():

void clear_Screen()
{
  Set_Column_Address(0x1C,0x5B);
  Set_Row_Address(0x00,0x3F);
  Set_Write_RAM();
  digitalWrite(displaySelect,LOW);
  digitalWrite(displayDC,HIGH);
  for(unsigned int i=0; i<8192; i++){
    SPI.transfer(0x00);
  }
  digitalWrite(displaySelect,HIGH);
}

After loading the code with this change, pushing the button does indeed clear the screen completely. All pixels are completely off. Resetting the Arduino reloads the same (faulty) image.

So this leads me to believe that the process of writing to the display is working as it should. I am now starting to suspect that the problem is on the Arduino end, but I don't know enough about how FLASH memory is written/read on the Arduino to know if that is the culprit.

I've also checked the array and there are exactly 8192 bytes there, as it should be.

Sounds a bit like when you load a small image you aren't putting it all into memory, so when you copy it to the OLED you are copying part of the earlier image.

When it's a small image though, nothing else shows except the image as it is supposed to look. It's only when I load a full size image.

I am having a difficult time understanding by what mechanism it is happening. For instance with the image I posted of the two lines of text. There is no compression happening, the program should be "dumb" and just copy every byte of image data as it is in the array. Why would only the text show up correctly but not the parts above/below the text?

It looks like rows with all "0xFF" data are just being skipped entirely, but why? If I invert the image and make another array, it shows up correctly. I can then send the display an "invert" command to get it back to how it is supposed to look, and I suppose I can work with that behavior although I don't like to without understanding what is really going on. Is it an issue with the display or with the Arduino?

I can confirm that the faulty data is being sent over the SPI bus (tested with logic analyzer), so I don't think the display is at fault. I'm directly comparing the first bytes of the image array with the first bytes being sent to the display after the proper commands (also verified).

Here is the current image:

As it shows up:

First bit of the image array:

FLASH_ARRAY(unsigned char, test,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
....

And part of the SPI data stream:


The first bytes on the left are the row and column address commands being sent, followed by a command to enable writing to the RAM. Between the markers are roughly 280 bytes, corresponding to about 565 pixels (just over 2 rows). The first couple dozen bytes of 0xFF followed by a couple hundred bytes of 0x00 matches exactly what is seen on the screen. So the display itself seems to be working as it should, but the data being sent is faulty. If you look at the array, you see it is all 0xFF for a good while at the start.

After this I am confident that something is going on inside the Arduino that I am not understanding.

What is that screen shot proving? I see some zeroes in your data, and zeroes in the logic analyzer. Can you narrow down the part you think is wrong?

In the array, the first zero is the 302nd byte, before that is all 0xFF. This corresponds to the 604th pixel, which would be about 35% of the way into the third row - the display is scanned horizontally. If you look at the original image file, that is exactly where the first zero is. So the image array is correct in that regard. I should clarify since it may be hard to see; the first part of the text encountered while scanning the display (horizontally, left to right; vertically, top to bottom) is the top of the 'S.' The uppermost part of the 'S' is on the third row of pixels.

However the display is clearly not showing that, it is showing a short line of 0xFF followed by a bunch of zeros on the first, second, and part of the third row. The SPI stream shows that this is indeed what is being sent to the display. So the display is faithfully displaying the data being sent to it, but the data is incorrect. The data sent SHOULD match the image array exactly, and the image array is correct. So, somewhere between writing the data to the flash memory upon uploading the sketch, and reading the data from the array and sending it over the bus, the data is being corrupted.

To me this is very strange, I see no logical reason from my code why this should happen. Unless the Arduino itself is faulty, or the Flash library I used is faulty (Flash | Arduiniana), I see no logical reason why this should be happening.

Well to comment further I would have to see the code and preferably reproduce it. Can you make a minimal example that compiles, with the problem data, and exhibits the problem? Then I can see whether or not it happens to me, and this rules in or out faulty hardware.

hi
still have
ODTv1.1.11278.zip cause link seems to be broken
thx