ABOUT SSD1306

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi i am new in avr .These days i am trying interface ssd1306 oled display with i2c_master library but display shows weird things .What is wrong with my code please help ,thanks.

 

<

#define F_CPU 16000000UL
#include <stdint.h>
#include "i2c_master.h"
#include <avr/pgmspace.h>
#include <string.h>

#include <util/delay.h>

#define HEIGHT 64
#define WIDTH 128

typedef uint8_t byte;

typedef uint8_t byte;
typedef uint16_t uint;

 unsigned char array[1024];

void sendcommand(unsigned char );
void senddata(unsigned char );
void draw_pixel(int , int );

void Flush();

void initialize_OLED();
 void resetPosition(void);

int main(){
    
    initialize_OLED();
    memset(array, 0x0, sizeof(array));
    memset(array, 0x1, sizeof(array));
    Flush();
    

while (1)
{

}
}

void initialize_OLED(){
        
    
    
    i2c_init();
    

    
    sendcommand(0x00); //Command stream
    sendcommand(0xAE); //Set display Off
    sendcommand(0xD5); //Set display clock divide ratio/oscillator frequency   Wire.write(0x80);
    sendcommand(0xA8); //Set multiplex ratio
    sendcommand(0x3F);
    sendcommand(0xD3); //Set display offset
    sendcommand(0x00);
    sendcommand(0x40); //Set display start line
    sendcommand(0x8D); //Set charge pump
    sendcommand(0x14); //VCC generated by internal DC/DC circuit
    sendcommand(0xA1); //Set segment re-map
    sendcommand(0xC8); //Set COM output scan direction
    sendcommand(0xDA); //Set COM pins hardware configuration
    sendcommand(0x12);
    sendcommand(0x81); //Set contrast control
    sendcommand(0xCF);
    sendcommand(0xD9); //Set pre-changed period
    sendcommand(0xF1);
    sendcommand(0xDB); //Set VCOMH Deselected level
    sendcommand(0x40);
    sendcommand(0xA4); //Set entire display on/off
    sendcommand(0xA6); //Set normal/inverse display
    sendcommand(0x20); //Set memory address mode
    sendcommand(0x00); //Vertical
    sendcommand(0xAF); //Set display on
    
}

void Flush(){
    

     resetPosition();
    
    
    uint8_t j=0;
    
    // set the Column and Page addresses to 0,0
    
    
    i2c_start(0x78);
    //I2C_Write(_i2c_address);
    i2c_write(0X40); // data not command
    for(j=0;j<1024;j++)
    {
        senddata(array[j]);
    }

    i2c_stop();
}

 void sendcommand(unsigned char com)
{
    uint8_t control=0x00;
    i2c_start(0x78);    //begin transmitting
    i2c_write(control);                          //command mode
    i2c_write(com);
    i2c_stop();                    // stop transmitting
}

void senddata(unsigned char data){
        uint8_t datamode=0x40;
        
        i2c_start(0x78); 
        i2c_write(0x78);    //begin transmitting
        i2c_write(datamode);                          //data mode
        i2c_write(data);
        i2c_stop();
}

 void resetPosition(void)
{
    
    sendcommand(0x22);
    sendcommand(0x00);
    sendcommand(0x07);

    sendcommand(0x21);
    sendcommand(0x00);
    sendcommand(0x7F);

    // also set display start line and display offset
    
}

void draw_pixel(int x, int y){
    if((x<0) || (x>=WIDTH) || (y<0) || (y>=HEIGHT)){ //Check for boundaries
        return;
    }
    else{
        array[x+(y/8)*WIDTH] |= _BV((y%8)); //Store pixel in array
    }
}

 

>

 

and the library   https://github.com/g4lvanix/I2C-master-lib

emre

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One:  Is your OLED even I2C compatable?   Some SSD1306 are I2C and others are SPI interface.

 

Two: Does your AVR (you didn't tell us the device type) have over 2046 bytes of SRAM?  The SRAM size is in powers of two so your AVR needs 4096 SRAM bytes because of the reserving of two 1024-byte arrays in main(), along with more housekeeping SRAM memory.

 

Three:  Where did you get those OLED initialization numbers?  Do they match the numbers used to initialize OLEDs that are found in other OLED libraries?  If not, why not?

 

Four:  Is your I2C library expecting you to send a 7-bit or and 8-bit address?  What is this "  I2C-address + I2C_WRITE" and "I2C-address + I2C_READ" in the I2C library mean?   Real I2C does a shift, then an add:   I2C-address<<1 + I2C_READ.

 

Five:  Why are you sending the I2C address twice in the senddata() routine?

 

Six:  Is this a school project?   I hope so.  I don't want to think that anyone is actually paying you for this code.   What school?  What level/year?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for answer .

 

one : my oled is I2C compatable

 

two: i though indicate the device with #tags is enough and it is a atmega328p. 

 

three: i found the numbers from another project that is on internet.and i tried them with my arduino with Wire library it works but i didn't convert the code to avr .

 

six : no, i am freshman at a university but this is not about school or homework.

 

i think my problem in 4. and 5. questions 

emre

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Install a respected library on your Arduino e.g. Adafruit_SSD1306

Then run one of the library examples.

 

Quote library,  example name,  any edits that you made to the example / library.   e.g. I2C address.

Verify that your hardware is working.

 

If you show this information,  I will debug your code in the original post.

 

God gave you the Arduino.    It works pretty well.   Easy for readers to replicate your project.

 

David.

Last Edited: Tue. Apr 16, 2019 - 11:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it is a atmega328p. 

  so your AVR needs 4096 SRAM bytes because of the reserving of two 1024-byte arrays in main(), along with more housekeeping SRAM memory.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 my oled is already working flawless with adafruit libary .adress is 0x3c .

emre

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With a Mega 328?? It only has 1K of memory but as David points out you have

unsigned char array[1024];

.

.

 for(j=0;j<1024;j++)  etc.

So if your data takes up ALL of your ram where is the space for the stack?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No,  the mega328 has 2048 bytes of SRAM.   The array size is fine.

There are some minor errors in the code.   The initialisation sequence "looks" ok,  the screen can be drawn but the scanning rate shows a flashing display.

 

I am not sure what the display frequency problem is.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes,my problem is this. lcd is blinking.

emre

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is a working version.   Please look for my comments marked with ".kbv"

#define F_CPU 16000000UL
#include <stdint.h>
//#include "i2c_master.h"
#include "i2cmaster.h"       //.kbv I used Fleury 
#include <avr/pgmspace.h>
#include <string.h>

#include <util/delay.h>

#define HEIGHT 64
#define WIDTH 128

typedef uint8_t byte;

typedef uint8_t byte;
typedef uint16_t uint;

unsigned char array[1024];

void sendcommand(unsigned char );
void senddata(unsigned char );
void draw_pixel(int , int );

void Flush();

void initialize_OLED();
void resetPosition(void);

int main(){
    
    initialize_OLED();
    memset(array, 0x0, sizeof(array));
    memset(array, 0x1, sizeof(array));
    Flush();
    

    while (1)
    {

    }
}

void initialize_OLED(){
    
    
    
    i2c_init();
    

    
    sendcommand(0x00); //Command stream
    sendcommand(0xAE); //Set display Off
    sendcommand(0xD5); //Set display clock divide ratio/oscillator frequency   Wire.write(0x80);
    sendcommand(0x80); //.kbv you omitted argument
    sendcommand(0xA8); //Set multiplex ratio
    sendcommand(0x3F);
    sendcommand(0xD3); //Set display offset
    sendcommand(0x00);
    sendcommand(0x40); //Set display start line
    sendcommand(0x8D); //Set charge pump
    sendcommand(0x14); //VCC generated by internal DC/DC circuit
    sendcommand(0xA1); //Set segment re-map
    sendcommand(0xC8); //Set COM output scan direction
    sendcommand(0xDA); //Set COM pins hardware configuration
    sendcommand(0x12);
    sendcommand(0x81); //Set contrast control
    sendcommand(0xCF);
    sendcommand(0xD9); //Set pre-changed period
    sendcommand(0xF1);
    sendcommand(0xDB); //Set VCOMH Deselected level
    sendcommand(0x40);
    sendcommand(0xA4); //Set entire display on/off
    sendcommand(0xA6); //Set normal/inverse display
    sendcommand(0x20); //Set memory address mode
    sendcommand(0x00); //Vertical
    sendcommand(0xAF); //Set display on
    
}

void Flush(){
    

    resetPosition();
    
    
    uint16_t j=0;     //.kbv needs 16-bit variable
    
    // set the Column and Page addresses to 0,0
    
    
    i2c_start(0x78);
    //I2C_Write(_i2c_address);
    i2c_write(0X40); // data not command
    for(j=0;j<1024;j++)
    {
        senddata(array[j]);
    }

    i2c_stop();
}

void sendcommand(unsigned char com)
{
    uint8_t control=0x00;
    i2c_start(0x78);    //begin transmitting
    i2c_write(control);                          //command mode
    i2c_write(com);
    i2c_stop();                    // stop transmitting
}

void senddata(unsigned char data){
    uint8_t datamode=0x40;
    
    i2c_start(0x78);
//    i2c_write(0x78);    //begin transmitting  .kbv (0x78) is in start()
    i2c_write(datamode);                          //data mode
    i2c_write(data);
    i2c_stop();
}

void resetPosition(void)
{
    
    sendcommand(0x22);
    sendcommand(0x00);
    sendcommand(0x07);

    sendcommand(0x21);
    sendcommand(0x00);
    sendcommand(0x7F);

    // also set display start line and display offset
    
}

void draw_pixel(int x, int y){
    if((x<0) || (x>=WIDTH) || (y<0) || (y>=HEIGHT)){ //Check for boundaries
        return;
    }
    else{
        array[x+(y/8)*WIDTH] |= _BV((y%8)); //Store pixel in array
    }
}



Note that your Flush() function can be dramatically improved:

    i2c_start(0x78);
    i2c_write(0X40); // data not command
    for(j=0;j<1024;j++) 
    {
        i2c_write(array[j]);
    }
    i2c_stop();

I suggest that you do some tidying up e.g.  single defines for SLAVE_ADDRESS,  DATAMODE, CONTROLMODE

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks it is working .what is difference between two library .and another question, how can i paste my code like you(in the box ).

emre

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your "library" looks much like the Fleury library.   It just has some additional block read and write functions.

So it should be "more" useful than Fleury.    I just used fleury because it was on my PC and I trust it.

 

You can  use ctl-D,ctl-K in AS7 to format your code nicely.   I choose spaces instead of tab.

You can paste code to a code-window in your message.   Look at the icons.   Choose the left-wedge,right-wedge icon 2nd from the end of the icons.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a lot of things to learn about programming and avr .Thanks for your patience

emre