ATXMEGA256-A3BU communication with OLED SSD1306 using I2C (TWI)

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

Hello to all,

 

i have a question regarding communication between my ATXMEGA256-A3BU controller as a master and "0.96 128x64 OLED graphic display" with SSD1306 controller as a slave. I'm using Atmel Studio ASF. I saw that there is a library and driver for SSD1306 but only for SPI communication in ASF wizzard but i would like to use I2C communication for my project instead.
What is the best way to establish a communication ? Is it hard to convert this library that is available in ASF wizzard to work with I2C communication or should i use any opensource library from github instead ?
Thank you for your time.

Best Regards,
Matjaz

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

Changing from SPI interface to I2C interface is simple.   Just study the timing diagrams in the SSD1306 datasheet.

 

Note that some of the early Ebay SSD1306 displays do not ACK the I2C bus.

Please post an accurate photo of the pcb side of your display.  e.g. from Ebay link.

 

There might be a small difference in the Initialisation Commands

All the high level User commands will be identical.

 

If you can navigate through the treacle in ASF,   I will give you a medal.

 

David.

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

M4tjaz wrote:
Is it hard to convert this library that is available in ASF wizzard to work with I2C

Have you looked?

 

How  "hard" it's going to be for you is going to depend on your level of experience - so some background on that would be helpful in order to give an informed opinion...

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

david.prentice wrote:

Changing from SPI interface to I2C interface is simple.   Just study the timing diagrams in the SSD1306 datasheet.

 

Note that some of the early Ebay SSD1306 displays do not ACK the I2C bus.

Please post an accurate photo of the pcb side of your display.  e.g. from Ebay link.

 

There might be a small difference in the Initialisation Commands

All the high level User commands will be identical.

 

If you can navigate through the treacle in ASF,   I will give you a medal.

 

David.

Thank you for your answer David.  I will try to study these timing diagrams and report if i succeed.
I bought OLED display here: https://www.aliexpress.com/item/... (sorry for long link ...)
There are pictures of circuit under discription on that webpage if it helps.. =)
 

 

awneil wrote:

M4tjaz wrote:
Is it hard to convert this library that is available in ASF wizzard to work with I2C

Have you looked?

 

How  "hard" it's going to be for you is going to depend on your level of experience - so some background on that would be helpful in order to give an informed opinion...

 

Sorry i forgot to say that i'm fairly new to programming microcontrollers i know some basics but not much. So for me almost everything will be hard but i will try my best.

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

M4tjaz wrote:
 i'm fairly new to programming microcontrollers

So you should probably start with some basics before jumping into a project like this:

 

http://www.avrfreaks.net/comment...

 

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

awneil wrote:

M4tjaz wrote:
 i'm fairly new to programming microcontrollers

So you should probably start with some basics before jumping into a project like this:

 

http://www.avrfreaks.net/comment...

 

Thank you for advice, but i have managed to use my XMEGA256-A3BU to printf on putty interface via USB, write to microSD card, read 1Wire Temperature sensor and blink a LED. I'm doing datalogger for my master thesis and now i have this problem with OLED display that i need to manage... I just don't understand how can i write library on my own (from start), that's why i said i have no bascis, because i think that if i could do that i could say that i know how to program.

 

Best Regards,
Matjaz

Last Edited: Thu. Nov 16, 2017 - 11:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK - sounds like you're fairly well on the way, then.

 

Are you already using ASF for the rest of your project?

I'm not sure that it's going to be easy to bring just one bit of ASF into an existing non-ASF project ...

 

 

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

Googling "SSD1306 I2C" seems to give plenty of options ...

 

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

awneil wrote:

OK - sounds like you're fairly well on the way, then.

 

Are you already using ASF for the rest of your project?

I'm not sure that it's going to be easy to bring just one bit of ASF into an existing non-ASF project ...

 

 

Yes for the rest of the project i'm already using ASF. Now i created new ASF project, just to write something on OLED display to test if i can do that and then when i finish i'm planning to merge with the rest of my project. That's why i'm trying to use TWI and SSD1306 libraries that are in ASF wizzard so i won't create a mess and nothing will work when i merge all in one project.
What do you suggest, should i dig into the code and try to modificate SSD1306 so it will work with I2C ?
Thank you for your time.

Best Regards,
Matjaz

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

M4tjaz wrote:
 i created new ASF project, just to write something on OLED display to test if i can do that and then when i finish i'm planning to merge with the rest of my project.

Excellent. Very refreshing to hear someone who understands how to take a modular approach!

 

should i dig into the code and try to modificate SSD1306 so it will work with I2C ?

Any particular reason why you don't just get a display with  SPI ?

Even if it's just to ensure that you have the library working before you start modifying it.

 

If the library is well-designed in a modular fashion, it shouldn't be hard to replace the SPI part with an I2C part ...

 

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

awneil wrote:

M4tjaz wrote:
 i created new ASF project, just to write something on OLED display to test if i can do that and then when i finish i'm planning to merge with the rest of my project.

Excellent. Very refreshing to hear someone who understands how to take a modular approach!

 

should i dig into the code and try to modificate SSD1306 so it will work with I2C ?

Any particular reason why you don't just get a display with  SPI ?

Even if it's just to ensure that you have the library working before you start modifying it.

 

If the library is well-designed in a modular fashion, it shouldn't be hard to replace the SPI part with an I2C part ...

 

 

Thank you.
Hehe actually for final project i will have to use I2C, because of lack of my experiance i already got my PCB made in that way that OLED display will connect to I2C without knowing that SPI is even better and faster way of communication.
But you are right, first i will use SPI communication to see if ASF library works for me and then i will modify it so it will work with I2C.
 

Matjaz

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

Note that it's not helpful to quote the entire post every time - just give enough for context.

 

If the context is clear, just use the 'Reply' button - the forum will automatically show which post it's a reply to

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

An option for you would be to get a cheap Arduino clone, ($3 USD), and start off with an Arduino library to drive the OLED display.

 

You can then see working initialization code, and working routines for sending data to the display.

 

Having a logic analyzer or an O'scope to see the I2C bus might be useful, if it doesn't all work as expected..., to help debug.

 

Once you have a working example up and running, it will be easier to write your own driver, if you can't find one.

 

JC

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

Hello again,

 

I have modified SSD1306 so that it uses TWI (I2C) communication instead of SPI. I made following changes...

I have changed conf_ssd1306.h,

in ssd1306.h i added

#elif defined(SSD1306_I2C_INTERFACE)
const uint8_t SLAVE = 0x78;
uint8_t addr = 0;
addr |= SLAVE << 1;
TWIE.MASTER.ADDR = addr;
while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
TWIE.MASTER.DATA = command;
while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
TWIE.MASTER.CTRLC = 0x03; // STOP bit
return;

 

and 

 

#elif defined(SSD1306_I2C_INTERFACE)
const uint8_t SLAVE = 0x78;
uint8_t addr = 0;
addr |= SLAVE << 1;
TWIE.MASTER.ADDR = addr;
while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
TWIE.MASTER.DATA = data;
while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
TWIE.MASTER.CTRLC = 0x03; // STOP bit
return;

 

in ssd1306.c i added

 

#define BAUDRATE 100000L

#elif defined(SSD1306_I2C_INTERFACE)
TWIE.CTRL = 0x00;
TWIE.MASTER.CTRLB = TWI_MASTER_SMEN_bm;
TWIE.MASTER.BAUD = BAUDRATE;
TWIE.MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
TWIE.MASTER.STATUS= TWI_MASTER_BUSSTATE_IDLE_gc;
return;

 

When i build and upload the code nothing happens, i have PULL-UP resistors on my OLED SS1306 display and i have set SCL and SDA as output. With my oscilloscope probe i get some signals but it seems that my SSD1306 OLED does not initialize correctly and i think the problem is with reset ssd1306_hard_reset(); at the beginning of void ssd1306_init(void) function.

I don't know how to modify the code bellow, because my controller doesn't have RESET pin..


#define ssd1306_reset_clear()    arch_ioport_set_pin_level(UG_2832HSWEG04_RESET, false)
#define ssd1306_reset_set()      arch_ioport_set_pin_level(UG_2832HSWEG04_RESET, true)

 

Thank you in advance for your time and help.

 

Best regards,
Matjaz

Attachment(s): 

Last Edited: Wed. Nov 29, 2017 - 08:44 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define ssd1306_reset_clear()    arch_ioport_set_pin_level(UG_2832HSWEG04_RESET, false)
#define ssd1306_reset_set()      arch_ioport_set_pin_level(UG_2832HSWEG04_RESET, true)

 

All these are used for is toggling the reset pin, which your module does not have.  There is probably a reset command on the I2C version.

Greg Muth

Portland, OR, US

Atmel Studio 7.0 on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

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

You will need to insert a "Control Byte" between sending/receiving the slave address and the actual data.  The control byte selects between Command or Data, and also has a bit the datasheet calls "continuation," which is probably an I2C Restart..?

 

EDIT: strike-through

Greg Muth

Portland, OR, US

Atmel Studio 7.0 on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

Last Edited: Thu. Nov 30, 2017 - 06:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg_Muth thank you for your response. I haven't even notice that i must do that..

Is this correct way of doing it ?

 

Writing several data to OLED:

#elif defined(SSD1306_I2C_INTERFACE)

	const uint8_t SLAVE = 0x78;
	
	uint8_t addr = 0;
	uint8_t control = 0x40; // Co=0, D/C=1
	addr |= SLAVE << 1;
		
	TWIE.MASTER.ADDR = addr;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
	
	TWIE.MASTER.ADDR = control;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
		
	TWIE.MASTER.DATA = data;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
	TWIE.MASTER.CTRLC = 0x03; // STOP bit
		
	return;
	

Writing command to OLED:

#elif defined(SSD1306_I2C_INTERFACE)
	const uint8_t SLAVE = 0x78;
	
	uint8_t addr = 0;
	uint8_t control = 0x00; // Co=0, D/C=0
	addr |= SLAVE << 1;
	
	TWIE.MASTER.ADDR = addr;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
	
	TWIE.MASTER.ADDR = control;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
	
	TWIE.MASTER.DATA = command;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
	TWIE.MASTER.CTRLC = 0x03; // STOP bit
	
	return;

Thank you again.

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

I found out, that i have to have the line of code in blue color in order to get signal on SDA and SCL pin... But my OLED display still doesn't function...
Anybody have an idea what to check next ?

	sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_TWI);	//Mora bit, ce ne ne daje na izhodu nic
	TWIE.CTRL = 0x00;							//SDA hold time OFF and normal TWI operation with two-pin interface
	TWIE.MASTER.CTRLB = TWI_MASTER_SMEN_bm;
	TWIE.MASTER.BAUD = 0x4b;			//set baudrate (OBVEZNO PREJ KO ENABLAS MASTER mode)
	TWIE.MASTER.CTRLA = TWI_MASTER_ENABLE_bm;	//enable MASTER mode
	TWIE.MASTER.STATUS= TWI_MASTER_BUSSTATE_IDLE_gc;
	delay_ms(10);	

Thank you in advance =) 

Last Edited: Thu. Nov 30, 2017 - 01:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_TWI);

 

The ASF function sysclk_init() turns off all peripheral clocks.  If you use the ASF function  to initialize a peripheral, ASF turns the clock back on.  Otherwise you must do so explicitly as above.  Since you are already using ASF, why are you not using it for the TWI modules?

 

EDIT: The code above that includes the "control byte" looks reasonable to me, although I have done little with I2C, so I'm not the best person to answer that question.

Greg Muth

Portland, OR, US

Atmel Studio 7.0 on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

Last Edited: Thu. Nov 30, 2017 - 03:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for explanation. First i tried to use it, but then i decided to do it this way because it is more clear to see what i'm doing in code..

I figure it out that i was using wrong SLAVE address, it's not 0x78 but 0x3C.. And now i'm again stuck specifically at this part of code as you see bellow. It looks like i'm calling SLAVE but he isn't responding.. 

 

#elif defined(SSD1306_I2C_INTERFACE)

	const uint8_t SLAVE = 0x3C;
	uint8_t addr = 0;
	uint8_t control_1 = 0x40; // Co=0, D/C=1

	addr |= SLAVE << 1;

	TWIE.MASTER.ADDR = addr;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
	delay_us(SSD1306_LATENCY); // At least 3us

	TWIE.MASTER.ADDR = control_1;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
	delay_us(SSD1306_LATENCY); // At least 3us

	TWIE.MASTER.DATA = data;
	while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm));
	delay_us(SSD1306_LATENCY); // At least 3us
	TWIE.MASTER.CTRLC = 0x03; // STOP bit

 

Last Edited: Fri. Dec 1, 2017 - 09:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay i figure it out why the SLAVE didn't respond, i accidently didn't enable peripheral clock for TWIE.. But still i have a non working OLED display.
I tried to program the same OLED display with Arduino and it is working ...
Does anybody have any other idea what else should i try so it will work with my XMEGA too?

 

Best regards,
Matjaz

Attachment(s): 

Last Edited: Fri. Dec 1, 2017 - 10:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why are you doing a read-modify-write here:

addr |= SLAVE << 1;

Try:

addr = SLAVE << 1;

Greg Muth

Portland, OR, US

Atmel Studio 7.0 on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

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

I tried but without changes.. I solved problem using TWI ASF module.

Thank you all for your help and time.

 

Best Regards,
Matjaz