Introduction: Serial I2C HD44780-compatible LCD for ATTINY85

This instructable will show you how to use an LCD and I2C module to display data from an ATTINY85. The intent of the schematic above it to show the connection needed to display data. Note that pull-up resistors are needed for the I2C module.

Step 1: Modify Liquid Crystal Display Library

The following two libraries will need to be installed in your Arduino environment.

1. NewliquidCrystal_1.3.4 written by F Malpartida which can be found at the following link New Liquid Crystal Display Driver
2. TinyWireM

The NewLiquidCrystal library has to be modified to make it work with the ATTINY chips. Modify the following file accordingly.

Find the following file I2CIO.cpp and make the modification below:

Line 33 replace with:

#if (ARDUINO > 100)

Line 34 “#include <../Wire/Wire.h>” replace with

#if defined(__AVR_ATtiny84__) || (__AVR_ATtiny2313__) || defined (__AVR_ATtiny85__)

#include "TinyWireM.h" // include this if ATtiny84 or ATtiny85 or ATtiny2313

#define Wire TinyWireM


#include "Wire.h" // original lib include


Step 2: Source Code

#include <LiquidCrystal.I2C.h>

#include <usi_twi_master.h>

#include <tinywirem.h>


//To wire your Lcd I2C Display to your ATtiny85, connect the following pins :


//ATtiny85 Pin1 –> NC

//ATtiny85 Pin2 –> NC

//ATtiny85 Pin3 –> NC

//ATtiny85 Pin4 –> Ground

//ATtiny85 Pin5 –> LCD Sda

//ATtiny85 Pin6 –> NC

//ATtiny85 Pin7 –> LCD Scl

//ATtiny85 Pin8 –> +5V


LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup()


lcd.begin(16, 2);

//3 flash introduction

for (int i = 0; i< 3; i++)








lcd.setCursor(2, 0);


lcd.setCursor(6, 1);



void loop()



Step 3: Notes

I am using the latest (at the time of this writing) arduino core (IDE version 1.6.2).

Please note that I have referenced and modified according the following information:

Use a LCD i2c with attiny84

How to control LCD Display with ATtiny85

I hope this instruction helps as I spent many hours trying to figure out how to get these libraries to work with the ATTINY.

Note update Feb 07, 2016. After upgrading to the newer version of Arduino (1.6.7) if you are using Visual Studio with Visual Micro this code will not work. There appears to be an issue with the #define statements not being passed in. If you get an error do to Wire.h then this was the reason. Hopefully they will fix this issue.

Upate: Feb 09, 2016. The fix for the Visual Micro is to install the latest as of this date.


Thijxx (author)2016-09-25

Followed the steps exactly and the IDE returns this error:

/home/thijs/.arduino15/packages/ATTinyCore/hardware/avr/1.1.1/libraries/Wire/Wire.cpp: In member function 'void TwoWire::setClock(uint32_t)':

/home/thijs/.arduino15/packages/ATTinyCore/hardware/avr/1.1.1/libraries/Wire/Wire.cpp:85:3: error: 'TWBR' was not declared in this scope

TWBR = ((F_CPU / frequency) - 16) / 2;

diy_bloke (author)2016-06-02

Forgive me if I keep making remarks/ask questions, but the original I2CIO.cpp line 33 checks on ARDUINO<10000 to load /Wire/Wire.h and otherwise to load Wire.h
Basically what this means is that below IDE version 1.6.x it needs to load Wire.h from the Wire subdirectory and for >=1.6 to load it directly from the top directory.
You have changed that into ARDUINO >100 to load Wire.h from the top directory, which basically means that IDE 1.0 and greater now load the Wire.h from the top directory. Now that may well be OK, in fact the Malpartida library is the only one I know to refer to /Wire/Wire.h, but should one suddenly get problems while using IDE 1.0, this might cause that problem. I guess I have to try it out myself some time.
Considering that the adapted (Bro Hogan) library uses:

#if defined(__AVR_ATtiny85__) || (__AVR_ATtiny2313__)
#include "TinyWireM.h" // include this if ATtiny85 or ATtiny2313
#include <Wire.h> // original lib include

I guess it is OK.
Also, I am guessing that your line:

#if defined(__AVR_ATtiny84__) || (__AVR_ATtiny2313__) || defined (__AVR_ATtiny85__)

should maybe be:

#if defined(__AVR_ATtiny84__) || (__AVR_ATtiny2313__) || (__AVR_ATtiny85__)

Anyway, dont take my various remarks as criticism. Good work

diy_bloke (author)2016-06-02

Just one more remark. Instead of

<LiquidCrystal.I2C.h>, I presume you mean

<LiquidCrystal_I2C.h> as that is the name in the Malpartida library
You make a seperate call to the USI_TWI_Master, whereas the examples for the Arduino do not mention that. Is that specifically needed?
Instead of

I presume you mean


diy_bloke (author)2016-03-05

great. I was just wondering why you make the changes in the LiquidCrystal_I2C_ByVac.h file and not in the LiquidCrystal_I2C.h file, after all that is the file you are calling and the "ByVac" file is ony for a specific board as I understand

sognatore (author)diy_bloke2016-03-05

You are correct there was no need to modify those files. In some of my later projects I do not reference the LiquidCrystal_I2C_ByVac.h only the LiquidCrystal_I2C.h as the change in I2CIO.cpp was only needed. Thank you for pointing out this mistake i will update the above code.

diy_bloke (author)sognatore2016-03-06

thanks, i was already doubting myself :-)

DIY Hacks and How Tos (author)2016-01-03

Cool project. Thanks for sharing.