EEVblog Electronics Community Forum

Electronics => Beginners => Topic started by: bsunisol on August 12, 2016, 02:12:44 pm

Title: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 02:12:44 pm
Hi,
I'm running a SSD1306 OLED 128x64 on my ATMega328p. As you can see in the picture below I can't show up anything. I only get this weired snow like thing.
The display is connected via SPI.

These are the startup sequenses I'm using:
Code: [Select]
/*
//ADAFRUIT-LIB
static const uint8_t oledConfig[] = {
0xAE,
0xD5,
0x80,
0x8A,
0xD3,
0x00,
0x40 | 0x0,
0x8D,
0x14,
0x20,
0x00,
0xA0 | 0x1,
0xC8,
0xDA,
0x12,
0x81,
0xCF,
0xD9,
0xF1,
0xDB,
0x40,
0xA4,
0xA6,
0x2E,
0xAF
};
*/
//DATASHEET
static const uint8_t oledConfig[] = {
0xA8, 0x3F,
0xD3, 0x00,
0x20, 00,
0x40 | 0,
0xA0, //0xA0?0xA1,
0xC0, //0xC0?0xC8,
0xDA, 0x12,
0x81, 0x7F,
0xA5,
0xA6,
0xD5, 0x80,
0xA4,
0xAF
};

Any ideas why it isn't working?

thanks and regards.
Title: Re: Problems running SSD1306 OLED
Post by: bktemp on August 12, 2016, 02:20:53 pm
The display is showing something, so the init sequence works.
How do you write data to the display?
Title: Re: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 02:24:50 pm
just pushing the buffer through the spi:
Code: [Select]
void oled_flush() {
resetPosition();

CHIPSELECT(MODE_DATA) {
for( int i=0; i<FRAME_BUFFER_SIZE; i++ ) {
uint8_t next = oledBuffer[i]; // Load next byte
//oledBuffer[i] = 0x00; // Clear buffer byte

__builtin_avr_delay_cycles(8);

SPSR; // Need to read register to clear SPIF

SPDR = next; // Send byte
}

// After sending the last byte the for loop exits, so we need to wait for the transfer to finish here
__builtin_avr_delay_cycles(14);
SPSR;
}
}

and filling the buffer:
Code: [Select]
for(int i=0;i<FRAME_BUFFER_SIZE;i++) {
oledBuffer[i] = 0xFF;
}

thanks.
Title: Re: Problems running SSD1306 OLED
Post by: Rick60 on August 12, 2016, 02:31:46 pm
I had a display just like that yesterday from a batch of 100 perfectly working , it turned out the DC line was shorted to 0V , so you can send commands but not data
It initialized but showed random dots when written to  , how are you generating DC? , it must be set prior to the spi writes ,and not change during it
Title: Re: Problems running SSD1306 OLED
Post by: bktemp on August 12, 2016, 02:36:46 pm
The code looks a bit unusual, but it should work.
So my guess would be also a hardware problem: Check if the DC signal at the display is high during image data write.
Title: Re: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 02:52:26 pm
the code is from http://blog.zakkemble.co.uk/diy-digital-wristwatch/ (http://blog.zakkemble.co.uk/diy-digital-wristwatch/) just to do a "quick" check of the display.

the DC line is pulled high/low correctly in the code. I have no oscilloscop to check it on the board.
when I send cmd 0xA5 the display turnes completly on. When I change the value from 0xA8 I get different patterns but no correct picture.

dc generation:
Code: [Select]
static bool oled_select( void ) {
spi_enable();
spiSelect();
return true;
}

static bool oled_deselect( void ) {
spiDeselect();
spi_disable();
return false;
}

#define cmdMode() (pinWrite(DC, LOW))
#define dataMode() (pinWrite(DC, HIGH))
#define MODE_CMD (cmdMode())
#define MODE_DATA (dataMode())
#define CHIPSELECT(mode) mode; \
for(bool cs = oled_select(); cs; cs = oled_deselect())
Title: Re: Problems running SSD1306 OLED
Post by: bktemp on August 12, 2016, 02:56:04 pm
If you write to the display and stop after the write routine, the DC line should still be high. You can use a DMM to verify this.
Title: Re: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 02:57:34 pm
If you write to the display and stop after the write routine, the DC line should still be high. You can use a DMM to verify this.

dmm?
Title: Re: Problems running SSD1306 OLED
Post by: bktemp on August 12, 2016, 03:05:35 pm
If you write to the display and stop after the write routine, the DC line should still be high. You can use a DMM to verify this.

dmm?
digital multimeter

Or add a led or whatever allows you to see if the pin is high or low.
Title: Re: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 03:28:57 pm
ok it's going high and low as supposed.
Title: Re: Problems running SSD1306 OLED
Post by: bktemp on August 12, 2016, 03:39:19 pm
The DC pin is going high (measured directly at the display), but there is so change in the displayed image if you change the written image data from 0x00 to 0xFF? That's odd.
Title: Re: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 03:41:42 pm
The DC pin is going high (measured directly at the display), but there is so change in the displayed image if you change the written image data from 0x00 to 0xFF? That's odd.

Yes there IS a change but just in the little black bar you can see in the first post. The "snowish"-area stays the same.
Title: Re: Problems running SSD1306 OLED
Post by: bktemp on August 12, 2016, 03:57:24 pm
You can write correct data to the black bar at the bottom of the image?
It seems like the page adress does not increment after the column has reached the end.
The horizontal addressing mode is selected in the init code (0x20 + 0x00), so it should work.
You can try adding spi_transfer_nr(0x20); spi_transfer_nr(0x00); in  resetPosition(void) to be shure it is correctly set.
Title: Re: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 04:07:58 pm
I don't know if this is correct data. But there is a change as supposed to be.
adding them in the resetposition doesn't change anything.....

Code: [Select]
int main( void ) {
for(int i=0; i<FRAME_BUFFER_SIZE; i++) {
oledBuffer[i] = 0x0F;
}

spi_init();
oled_init();
beep(false);

/* Replace with your application code */
while (1) {
for(int i=0; i<FRAME_BUFFER_SIZE; i++) {
oledBuffer[i] ^= 0xFF;
}
oled_flush();
delay(500);
}
}

this code generates a switching black and white bar in the area without snow. So I guess this little area is working as supposed.
Title: Re: Problems running SSD1306 OLED
Post by: bktemp on August 12, 2016, 04:17:58 pm
It looks to me your OLED does not have an SSD1306 but some other variant.
Try this code (it should be already in your file, disabled by the #if OLED_CONTROLLER == OLED_CONTROLLER_SSD1306 / #else in oled_flush()):
Code: [Select]
uint16_t buffer = 0;
uint16_t start;

for(uint8_t i=0;i<8;i++)
{
start = buffer;
buffer += 128;

// Need to manually set page and column with SH1106 :/
CHIPSELECT(MODE_CMD)
{
spi_transfer_nr(0xB0 + i); // Set page
spi_transfer_nr(0x02); // Set column lower 4 bits
spi_transfer_nr(0x10); // Set column higher 4 bits
}

CHIPSELECT(MODE_DATA)
{
for(uint16_t i=start;i<buffer;i++)
{
uint8_t next = oledBuffer[i]; // Load next byte
oledBuffer[i] = 0x00; // Clear buffer byte

__builtin_avr_delay_cycles(8);

SPSR; // Need to read register to clear SPIF

SPDR = next; // Send byte
}

__builtin_avr_delay_cycles(14);
SPSR;
}
}
This variant sets the adress for each page and does not rely on the adressing mode selected in the display.
Title: Re: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 05:07:15 pm
@bktemp:
thank you!
with some little logic tweaking (i/i2) it works nearly as supposed to!
there are just some little parts without pixels...
Code: [Select]
uint16_t buffer = 0;
uint16_t start;

for(uint8_t i=0; i<8; i++) {
start = buffer;
buffer += 128;

// Need to manually set page and column with SH1106 :/
CHIPSELECT( MODE_CMD ) {
spi_transfer_nr( 0xB0 + i ); // Set page
spi_transfer_nr( 0x02 ); // Set column lower 4 bits
spi_transfer_nr( 0x10 ); // Set column higher 4 bits
}

CHIPSELECT( MODE_DATA ) {
for(uint16_t i2=start; i2<buffer; i2++) {
uint8_t next = oledBuffer[i+i2]; // Load next byte
//oledBuffer[i] = 0x00; // Clear buffer byte

__builtin_avr_delay_cycles(8);

SPSR; // Need to read register to clear SPIF

SPDR = next; // Send byte
}

__builtin_avr_delay_cycles(14);
SPSR;
}
}

Title: Re: Problems running SSD1306 OLED
Post by: bktemp on August 12, 2016, 05:24:18 pm
With oledBuffer[i2] instead of oledBuffer[i+i2] you should get all pixels at the correct position.
Title: Re: Problems running SSD1306 OLED
Post by: bsunisol on August 12, 2016, 08:28:22 pm
With oledBuffer[i2] instead of oledBuffer[i+i2] you should get all pixels at the correct position.

Yes thanks. Works fine now. Missed i2=start :D