Introduction: ATTiny85 Connects to I2C OLED Display - Great Things Can Be Small
I recently came across a tiny OLED display which I also used for another project. This time I thought a tiny display can be driven by an [AT]Tiny processor :).
The vision is - "create a tiny gaming machine"
Well the first step is taken. At least something is happening on the display. Feel free to suggest a game idea.
Parts we need
- ATTiny85 break out board - CoPiino Connectable BrainZ from ebay ($6)
- OLED Display with SSD1306 driver from ebay ($5)
- AVR Programmer USBasp from ebay ($4)
- 5V/3.3V regulated voltage source
- some jumper wires
- Arduino IDE
Attention: The display module I used had an operation range from +3.3V to +5V. So I could easily connect +5V. You need to carefully check if your display also supports +5V otherwise use a regulated +3.3V power source !!
Edit:
- uploaded additional target project => demo for font and icons
- uploaded some pictures for font and icons
Step 1: Soldering the Board
The CoPiino Connectable BrainZ comes as soldering kit. So it needs some soldering. All parts are through-hole and can be soldered old fashioned with soldering iron.
Scope of supply:
- PCB 21x28mm with M3 fixing hole
- 1x ATTiny85-20PU
- 1x LED 3mm yellow
- 1x Resistor 1k
- 3x Resistors 4.7k
- 2x Capacitors 100nF
- 1x pin header angled 1x4
- 1x pin header angled 1x5
- 1x Straight header
- 2x3 (AVR ISP)
- 1x Receptacle angled 1x4
It took me 20mins to solder all parts.
Step 2: Programming the CoPiino Connectable BrainZ
This step is pretty forward. The required source code is attached to this step. All files need be extracted.
Included files are
- ATTiny_OLED_Bouncing_Ball.ino
- SSD1306_minimal.cpp
- SSD1306_minimal.h
- TinyWireM.cpp
- TinyWireM.h
- USI_TWI_Master.cpp
- USI_TWI_Master.h
1. With the Arduino IDE we open the ATTiny_OLED_Bouncing_Ball.ino
2. We need to use the menu "Sketch" - "Add File ... " and add all other files one by one
3. Connect the CoPiino Connectable BrainZ to the USBasp (see notes below)
4. Connect USBasp preferably to a USB hub
5. Arduino IDE: Compile and Upload
6. Check for completed Upload
7. Disconnect USB
8. done
notes:
For connecting the USBasp to the CoPiino Connectable BrainZ we apply these pin connections
ISP10PIN to ISP6PIN
Pin 9 to 1 [MISO]
Pin 2 to 2 [VCC]
Pin 7 to 3 [SCK]
Pin 1 to 4 [MOSI]
Pin 5 to 5 [RST]
Pin 2 to 6 [GND]
Step 3: Connect and Run
The display will be connected through I2C / TWI which are the signales SDA/SCL. Additionally we draw VCC and GND from the CoPiino Connectable BrainZ to the display. So all toghether we have 4 single cables between display and BrainZ.
Attention: The display module I used had an operation range from +3.3V to +5V. So I could easily connect +5V. You need to carefully check if your display also supports +5V otherwise use a regulated +3.3V power source !!
We then use our 5V/3.3V regulated power source and inject GND and VCC into the appropriate pins at the BrainZ module.
You will be enlightened by the nice moving ball in a grid on the display.
Congrats!
Now its time to make the next step. Any gaming idea that can be implemented?

Participated in the
Mind for Design
65 Comments
3 years ago
I did it.
5 years ago
Hi, I have had a lot of success with your library on ATtiny85. Now I'm trying to get it to work on the ATtiny84 as well. I cannot compile any sketches that work on tiny85 because for some reason the lines of code with the USI are not working. I thought that since tiny84 and tiny85 both use a USI rather than physical I2C support this should work... The error message is below. Thanks!
/var/folders/tr/zp_0970j0ld4_wq_yx8vnw_r0000gn/T/arduino_build_400141/sketch/USI_TWI_Master.cpp: In function 'void USI_TWI_Master_Initialise()':
USI_TWI_Master.cpp:52: error: 'PORT_USI' was not declared in this scope
PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state.
^
USI_TWI_Master.cpp:52: error: 'PIN_USI_SDA' was not declared in this scope
PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state.
^
USI_TWI_Master.cpp:53: error: 'PIN_USI_SCL' was not declared in this scope
PORT_USI |= (1<<PIN_USI_SCL); // Enable pullup on SCL, to set high as released state.
^
USI_TWI_Master.cpp:55: error: 'DDR_USI' was not declared in this scope
DDR_USI |= (1<<PIN_USI_SCL); // Enable SCL as output.
^
/var/folders/tr/zp_0970j0ld4_wq_yx8vnw_r0000gn/T/arduino_build_400141/sketch/USI_TWI_Master.cpp: In function 'unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char*, unsigned char)':
USI_TWI_Master.cpp:200: error: 'PORT_USI' was not declared in this scope
PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.
^
USI_TWI_Master.cpp:200: error: 'PIN_USI_SCL' was not declared in this scope
PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.
^
USI_TWI_Master.cpp:205: error: 'DDR_USI' was not declared in this scope
DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.
^
USI_TWI_Master.cpp:205: error: 'PIN_USI_SDA' was not declared in this scope
DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.
^
USI_TWI_Master.cpp:238: error: 'DDR_USI' was not declared in this scope
DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.
^
USI_TWI_Master.cpp:238: error: 'PIN_USI_SDA' was not declared in this scope
DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.
^
/var/folders/tr/zp_0970j0ld4_wq_yx8vnw_r0000gn/T/arduino_build_400141/sketch/USI_TWI_Master.cpp: In function 'unsigned char USI_TWI_Master_Transfer(unsigned char)':
USI_TWI_Master.cpp:280: error: 'PIN_USI' was not declared in this scope
while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.
^
USI_TWI_Master.cpp:280: error: 'PIN_USI_SCL' was not declared in this scope
while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.
^
USI_TWI_Master.cpp:288: error: 'DDR_USI' was not declared in this scope
DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output.
^
USI_TWI_Master.cpp:288: error: 'PIN_USI_SDA' was not declared in this scope
DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output.
^
/var/folders/tr/zp_0970j0ld4_wq_yx8vnw_r0000gn/T/arduino_build_400141/sketch/USI_TWI_Master.cpp: In function 'unsigned char USI_TWI_Master_Start()':
USI_TWI_Master.cpp:298: error: 'PORT_USI' was not declared in this scope
PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.
Reply 5 years ago
Did you try to use these renames?
#if defined(__AVR_ATtiny84__) | defined(__AVR_ATtiny44__)
#define DDR_USI DDRA
#define PORT_USI PORTA
#define PIN_USI PINA
#define PORT_USI_SDA PORTA6
#define PORT_USI_SCL PORTA4
#define PIN_USI_SDA PINA6
#define PIN_USI_SCL PINA4
#endif
Reply 4 years ago
Hi, tswaehn
where exactly would pdf I put that to port programs because like Alex I have the display working on the tiny85 but not on the tiny84
Reply 5 years ago
Hi Alex,
thanks for you message. I pretty much thing you have your fingers at absolute correct location. Its only about the definition of pinnings for the serial transfer unit. I know a lot about TINY85, but not yet had much to do with the TINY84. BUT I guess its just a matter of naming, ...
Reply 5 years ago
Hi Alex,
according to the web the naming is different from Tiny85 to Tiny84. Additionally some registers are missing. Porting the programs from Tiny85 to Tiny84 seems to be more than re-compiling - unfortunately. :(
Reply 5 years ago
Thanks for your response. Adding those pin definitions for (__AVR_ATtiny84__) | defined(__AVR_ATtiny44__) worked perfectly. It actually does look like direct ports of previous sketches are possible. Since the definitions you provided are independent of the ATtiny core in use it should work with any core, right?
Reply 5 years ago
yes, this should work generally to port code from ATiny85 to ATiny84.
Question 4 years ago
which Pins are used from the tiny? I don't use breakout Boards.
Answer 4 years ago
And here as well, i tried it manually:
SDA=5
SCL=7
Question 4 years ago
Hello,
Thank you for your instruction, but it does not work for me, i was searching for a IDE version or a Date, to assume, which Arduino IDE version you're using, the Value in the picture says 0100, but I have 1.8.1, so the numbers are not compareable.
I've tried 1MHz, 8MHz and 16MHz
So, here is my problem, when i try to compile, i get this:
Arduino: 1.8.1 (Windows 10), Board: "ATtiny25/45/85, ATtiny85, Internal 8 MHz"
C:\Program Files (x86)\Arduino\libraries\SSD1306_minimal\SSD1306_minimal.cpp: In member function 'void SSD1306_Mini::displayX(int)':
C:\Program Files (x86)\Arduino\libraries\SSD1306_minimal\SSD1306_minimal.cpp:156:34: error: call of overloaded 'send(uint16_t)' is ambiguous
Wire.send( i*16 + k + off);
^
C:\Program Files (x86)\Arduino\libraries\SSD1306_minimal\SSD1306_minimal.cpp:156:34: note: candidates are:
In file included from C:\Program Files (x86)\Arduino\libraries\SSD1306_minimal\SSD1306_minimal.h:36:0,
from C:\Program Files (x86)\Arduino\libraries\SSD1306_minimal\SSD1306_minimal.cpp:26:
C:\Program Files (x86)\Arduino\libraries\TinyWireM/TinyWireM.h:65:10: note: void USI_TWI::send(uint8_t)
void send(uint8_t b) { write(b); }
^
C:\Program Files (x86)\Arduino\libraries\TinyWireM/TinyWireM.h:67:10: note: void USI_TWI::send(int)
void send(int n) { write((uint8_t)n); }
^
exit status 1
Fehler beim Kompilieren für das Board ATtiny25/45/85.
so, what is the point her, could you please help me out?
Answer 4 years ago
Ok I found it by myself, I thought the
USI_TWI_Master.cpp
USI_TWI_Master.h
is an extra library, so i copied them into an extra folder, now the files are inside the ...Arduino\libraries\TinyWireM\ folder and it works.
5 years ago
Can you help me please. I have 128x32 display conected to Attiny85 and your library works, but text is very hard to read beacouse diferent screen size. Can you help me modify your library to fit 128x32 screen OLED display. Tnx
Reply 5 years ago
What is the display model number?
Reply 4 years ago
I'm guessing I'm using a similar display to VolosR; it's this one: https://www.aliexpress.com/item/0-91-Inch-128x32-I...
It seems to be pretty much the same as this one from Adafruit: https://www.adafruit.com/product/931
Using your instructions, I've gotten it to display things, but the text and images are squashed, like it's skipping every other line of pixels. Messing with the code, the only thing I've been able to achieve is making the text completely disappear. Any ideas what needs to change to support 32-pixel high displays?
Reply 4 years ago
Hi David,
From the top of my head it could be the display aspect ratio. My display comes at 128x64px. Your display looks like 128x32px.
What do you think?
Reply 4 years ago
I just double checked the code. It looks like this library is optimized for the 128x64px display. However can be done to make it running on the 128x32px display as well.
Reply 4 years ago
OK, cool! Any pointers on where I should start trying to modify it for 128x32px?
Reply 4 years ago
Hi David,
This is just a starter and may work: I would check out for any location in the source files that has something to do with 128 and 64. Try to replace the 64 with 32.
Best
Sven
Reply 4 years ago
OK, I tried that, but the result is still the same. There were only 2 spots I found to change where it was 64 decimal, not 0x64, and they were both in loops: lines 454 and 472 of SSD1306_minimal.cpp. I also changed the multiplex ratio from 0x3F to 0x1F (line 326) because if I don't change that, everything's on the top half of the screen and the bottom half just has noise on it.
I also had to make a couple of small changes to data types in order to get it to compile. I've uploaded my code to GitHub: https://github.com/whitelynx/digispark-i2c-oled/tr... (the changes I've done to attempt to get it working for a 128x32px display are in this commit: https://github.com/whitelynx/digispark-i2c-oled/co...)