Problems running SSD1306 OLED - Page 1
Forum section: electronics / beginners

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 02:12:44 pm
content: 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:/*//ADAFRUIT-LIBstatic 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};*///DATASHEETstatic 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.

author: bktemp
author_rank: Super Contributor
timestamp: August 12, 2016, 02:20:53 pm
content: The display is showing something, so the init sequence works.How do you write data to the display?

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 02:24:50 pm
content: just pushing the buffer through the spi:Code:void oled_flush() {resetPosition();CHIPSELECT(MODE_DATA) {for( int i=0; i<FRAME_BUFFER_SIZE; i++ ) {uint8_t next = oledBuffer; // Load next byte//oledBuffer = 0x00; // Clear buffer byte__builtin_avr_delay_cycles(8);SPSR; // Need to read register to clear SPIFSPDR = 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:for(int i=0;i<FRAME_BUFFER_SIZE;i++) {oledBuffer = 0xFF;}thanks.

author: Rick60
author_rank: Contributor
timestamp: August 12, 2016, 02:31:46 pm
content: 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 dataIt 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

author: bktemp
author_rank: Super Contributor
timestamp: August 12, 2016, 02:36:46 pm
content: 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.

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 02:52:26 pm
content: the code is fromhttp://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: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())

author: bktemp
author_rank: Super Contributor
timestamp: August 12, 2016, 02:56:04 pm
content: 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.

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 02:57:34 pm
content: Quote from: bktemp on August 12, 2016, 02:56:04 pmdmm?

author: bktemp
author_rank: Super Contributor
timestamp: August 12, 2016, 03:05:35 pm
content: Quote from: bsunisol on August 12, 2016, 02:57:34 pmdigital multimeterOr add a led or whatever allows you to see if the pin is high or low.

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 03:28:57 pm
content: ok it's going high and low as supposed.

author: bktemp
author_rank: Super Contributor
timestamp: August 12, 2016, 03:39:19 pm
content: 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.

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 03:41:42 pm
content: Quote from: bktemp on August 12, 2016, 03:39:19 pmYes there IS a change but just in the little black bar you can see in the first post. The "snowish"-area stays the same.

author: bktemp
author_rank: Super Contributor
timestamp: August 12, 2016, 03:57:24 pm
content: 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.

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 04:07:58 pm
content: 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:int main( void ) {for(int i=0; i<FRAME_BUFFER_SIZE; i++) {oledBuffer = 0x0F;}spi_init();oled_init();beep(false);/* Replace with your application code */while (1) {for(int i=0; i<FRAME_BUFFER_SIZE; i++) {oledBuffer ^= 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.

author: bktemp
author_rank: Super Contributor
timestamp: August 12, 2016, 04:17:58 pm
content: 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: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 pagespi_transfer_nr(0x02); // Set column lower 4 bitsspi_transfer_nr(0x10); // Set column higher 4 bits}CHIPSELECT(MODE_DATA){for(uint16_t i=start;i<buffer;i++){uint8_t next = oledBuffer; // Load next byteoledBuffer = 0x00; // Clear buffer byte__builtin_avr_delay_cycles(8);SPSR; // Need to read register to clear SPIFSPDR = 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.

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 05:07:15 pm
content: @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: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 pagespi_transfer_nr( 0x02 ); // Set column lower 4 bitsspi_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 = 0x00; // Clear buffer byte__builtin_avr_delay_cycles(8);SPSR; // Need to read register to clear SPIFSPDR = next; // Send byte}__builtin_avr_delay_cycles(14);SPSR;}}

author: bktemp
author_rank: Super Contributor
timestamp: August 12, 2016, 05:24:18 pm
content: With oledBuffer instead of oledBuffer[i+i2] you should get all pixels at the correct position.

author: bsunisol
author_rank: Contributor
timestamp: August 12, 2016, 08:28:22 pm
content: Quote from: bktemp on August 12, 2016, 05:24:18 pmYes thanks. Works fine now. Missed i2=start