Data is transmitted using only 2 wire over i2c with the PCF8574.
Lcd driver is based upon Peter Fleury's lcd driver.
Setup parameters can be found in file lcdpcf8574.h and pcf8574.h
This library was developed on Eclipse, built with avr-gcc on Atmega8 @ 1MHz.
Issues fix:
- If you have problem making this library works with Arduino Uno and QAPASS LCD with Funduino I2C interface, please read the comment above "Matt Alizadeh June 1, 2018 at 2:56 PM" by Matt Alizadeh
Changelog
- 02: added CGRAM, custom char functions by Péter Papp
- 01: first release
Code
Notes
- read risk disclaimer
- excuse my bad english
Hello Davide.
ReplyDeleteI have a problem I want to use this code with the atmega328.
But I can't get it working I get error afther errror and when I fix one error I get an other, I struggling for almost 3 day's so it's time to ask for help.
Can you help me converting this code so it work with a atmega328? I would really appreciate it thank you.
Best regards Tom
E-mail: tomklijn@outlook.com
to me, it compiles and works on atmega328p without any compiling error.
Deletecheck you wiring, check you fuses, check you cpu frequency, try debug using uart.
Hi David,
ReplyDeleteI am using atmega168 and avr studio I am new to this stuff and my screen is just showing one solid block of squares in one line only. Do I need to set the port and pin numbers for TWI in some file. I saw that none of the headers files set the port numbers.
Appreciate your help,
Thanks
yes, you have to setup pin number in file: lcdpcf8574.h
DeleteI apologoze for bothering you again, but figure out that pin numbers are hardwired so we do not need to use them, but you are running it a 4Mhz frequency, I am trying to so it at 8Mhz, in what places should I change the code. Also I used the meter to check ao,a1,a2 and all three report avoltage of 4.9v. this means they are tied high, so my address will be 0x27, correct? I am using PCF8574T. The program is hanging somewhere in lcd_init. Any help will be appreciated.
Deletei'm running it at 1Mhz, but i've run it at 8Mhz on other project only changing the i2c speed.
Deletethe only problem i've encountered during my experiments, is when pin connection are wrong.
debug using logic analizer on the pcf8574 lines, or simply using uart output to check where it stucks.
Well, we have to use a multimeter to match the LCD pins to the PCF8574T pins, on our board they were totally different. After setting the pins correctly in LCDPCF8574.h file, the code worked like a charm
DeleteThanks for all the help.
good! ;)
DeleteI also get solid block of squares in one line only but I can't get this even to compile... i keep getting some compile errors about LCD_DISP_ON_BLINK and 2, or 3 other lines.
DeleteTo be clear i really don't understand all this stuff what it mean and avr studio is quite strange to me, but even i know that my pin connections are different I could fix that later based on Your previous advice for lcdpcf8574.h.
For now i don't know how to get compile ok. My mcu is Atmega168 @8MHz internall. I'm trying to get this to work just to know does my pcf8574t chip is still live at all because i'm also trying to controll lcd on such was using some other programming method.
Please sir i need help. For You it's maybe 5minutes of work, can you provide me with hex file just to burn it to my mcu?
pcf8574 adress is 0x20, and my connection is like this
http://mmdolze.users.sourceforge.net/images/myLoS-i2c.png but my and my backlight is npn transistor so turned on is PCF_P7=1
i use atmega168
Hello,
Deletetry Eclipse with avrgcc and AVR plugin, it's very simple to use it and compile it with Eclipse avr plugin.
Or you can write your own makefile. There are a few tutorial out there.
Yes, i could compile it for you, but every time you have to make a change, you have to ask me to compile, and it could not bring anything to your knowledge :)
i really don't know how to do anything of that. Write my own makefile? hah, good one... :) I don't know even #C at all. That's why I'm using Flowcode, programming mcu by putting blocks around but there are also some tricky issues about i2c LCD that gives me a headache and matrix multimedia support sucks.
DeleteActually I'm medical worker and electronics is just my hobby, complete noob :)
I don't think that i will need that hex more than one (this) time, simply to check my hardware to know am I doing something wrong in Flowcode or my PCF8574 chip is simply dead for some reason and that's why I don't get normal result on LCD. that's all
at least i would be happy with zip that include avr studio solution and all those .c and .h included so I can look around and try to understand what is what and how things should be done.
Ok. For neebie you should consider working with Arduino, which is really simple! Just import that code in your avr studio project. Keep in mind that you will have to change some registers in order to make this works on mega16. Give it a try to arduino, the LCD i2c library is really simple.
Deletei don't have arduino and as far as i saw how it works it also need some knowledge about #C... also arduino IDE won't work on my laptop, i don't know why and i don't care, i will not use it.
Deleteand i did tried already to import code in avr studio, as I said before i get build errors. registers to change?! i don't know how to do that
never mind. i will continue my fight with Flowcode. thanks
Ali, could you please post your pin configuration?
DeleteI have the PCF8574T too.
Thanks!
Hi David,
ReplyDeleteNice work, but I'm having trouble getting it to work.
I'm using a 20x4 LCD from YwRobot, which comes with a PCF8574. I have it connected to analog pins 4 (SDA) and 5 (SCL) on an ATmega328P. I have made the following connections, which I believe are correct: DATA0 = 4, DATA1 = 5, DATA2 = 6, DATA3 = 7, RS = 0, RW = 1, EN = 2. The backlight seems to just be connected to Vcc (which pin should I set it to?).
I am not sure what address to use. I've tried both 0x20 and 0x27 (this worked when I used the LCD with an Arduino library some time ago).
Any idea what the problem might be?
hello,
Deleteat first try with a 16x2 LCD, HD44780, pretty standard and a cheap PCF8574 board-
Then when you are shure it works, test it with your hardware.
Anyway, pin numbers are in file: lcdpcf8574.h
I don't have one :( My LCD is a HD44780 though. I have set the pin numbers in lcdpcf8574.h.
DeleteDavide, thank you for your library!
ReplyDeleteThe pins for PCF8574T I2C LCD adapter (bought from Ebay):
#define LCD_DATA0_PIN 4
#define LCD_DATA1_PIN 5
#define LCD_DATA2_PIN 6
#define LCD_DATA3_PIN 7
#define LCD_RS_PIN 0
#define LCD_RW_PIN 1
#define LCD_E_PIN 2
#define LCD_LED_PIN 3
Thank you for sharing your feedback!
Deleteand address into 0x27
Delete#define PCF8574_ADDRBASE (0x27) //device base address
Thank you Maciej.
DeleteMaciej, this has just saved me after a day of debugging thanks for posting. I have the same setting requirements.
DeleteLooking for an assembly version of this, is there a way to concert the c to assembly? I can read assembly but not c well. Thanks. Even compile it with avr studio and send me the hex and I will decompile it.
ReplyDeleteThanks
Hello, I can send you a compiled hex or the compiler lss avrgcc file, which contains the assembly. Keep in mind that it will be assembly code from the compiler, so it can not be so "clean". Anyway, just send me an email, or give me your address and i will reply with the code.
Deleteadmin at tipsntricks dot ca
Deleteyou've got mail ;)
DeleteHello,
ReplyDeleteI used this library to run PCF8574T on ATmega16A. I got cheap ebay display with I2C backpack ( PCF8574T) module. I changed pins in .h file and communication works ok (Im able to write something on display), but there is no backlight. The thing is that there is backlight for some ms, but when display init method starts, it turns off backlight somehow and I cant figure out why. Its some kind of invert mode I think.
If you got any ideas, please share. Thanks,
The setup pin for the lcd light is LCD_LED_PIN (lcdpcf8574.h). The function to light up and down is lcd_led. In normal mode lcd_led(1) will turn the led on, lcd_led(0) off, in inverted mode, it works inverted, so 1 to off, o to on.
DeleteIt your board works and it's all connected properly, this is the way it should work.
It could also be your hardware that is damaged.
You can double check your wiring, and try different pins.
Problem solved! Thank you very much!
DeleteThank you for your feedback ;)
DeleteThis comment has been removed by the author.
Deleteim using this files with ATmega32. i have this module
ReplyDeletehttp://www.ebay.com/itm/310565362720?_trksid=p2059210.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT
i had already used the based libraries about lcd 2x16 and works fine. so i dont have edit my code as it use same functions.
i've change the
F_CPU with my xtal freq.
also i change the adress to 0x27 (A0,A1,A2 = 4.8V)
and finally change pins several times with different combination.
i had build circuit with module and lcd on breadboard and connections with wires. to make sure that pins corresponding right.
nothing works :(
Check your hardware with other libraries, or with Arduino. So you will be sure that your hardware works, and what the pin of your hardware are.
DeleteYou could also check where your code stops working, using a serial debugger.
thanks for reply.
Deletei can't use debugger now. im trying to add i2c in an already working circuit with FTDI and atmega32. my uart its reserved from ftdi chip
my hardware works perfectly. checked with arduino hardware, arduino ide and arduino libraries.
DeleteSo, it could be the I2C library, you have to check the bus using a logic analizer, or debug in other way to check where your code stop working.
DeleteThe code was tested using avrgcc.
This comment has been removed by the author.
Delete1- gnd
Delete2- vcc-
3- contrast-
4- rs- pcf0
5- rw- pcf1
6- e- pcf2
7- db0-
8- db1-
9- db2-
10- db3-
11- db4- pcf4
12- db5- pcf5
13- db6- pcf6
14- db7- pcf7
15- +led- led_jumper
16- -led- led_jumper
this is my pin diagram
Deletei tried define:
ReplyDelete#define LCD_DATA0_PIN 4
#define LCD_DATA1_PIN 5
#define LCD_DATA2_PIN 6
#define LCD_DATA3_PIN 7
#define LCD_RS_PIN 0
#define LCD_RW_PIN 1
#define LCD_E_PIN 2
#define LCD_LED_PIN 3
but nothing works :(
Check if your I2C works, check the output of your PCF8574 with a multimeter.
DeleteHack the code to test every pin output using pcf8574_setoutputpin funcion.
thanks for advice davide. i will...
DeleteIt works!
DeleteThere was connection error on breadboard!
Works perfectly...!
thank you Davide!
glad to ear this ;)
DeleteI have another problem.
ReplyDeletei had made a project with atmega32 which communicates with pc via ft232rl.
pc sends data through ftdi (uart) to atmega32 and while sends data, the mcu interrupted.
the atmega32 while its not in interrupt routine, it running a code which measuring a distance with HCSR04.
now, while i running the pc program for sending data to mcu, my main routine stop to work and in lcd i see only data from pc and not from ultrasonic sensor.
it working without i2c.
Try to put a watchdog, to test if the mcu restart.
DeleteI mean.. if the mcu restarts when the data is sent. Then, debug your HCSR04 routine.
DeleteStart at small steps, try at first with a simple ADC read routine, then attach your distance sensor code.
Hello everyone,
ReplyDeleteI had a problem with compilation that code . Something like " Poisoned SIG_USART_DATA nad SIG_USART_RECV . So I found and changed that uasrt.h file and uart.c file into almost the same ( now SIG_USART_DATA is UART_UDRE_vect for example ) the rest is same. Compillation is without any problems, but nothing appeared on my LCD :( I have been trying to resolve that problem for 8 hours. I am using pcf8574T and I changed pins :(
Do you know what should I do?
I would add that I am using that set http://www.ebay.com/itm/Arduino-IIC-I2C-TWI-162-1602-16X2-Serial-Blue-LCD-Module-Display-Screen-/190573003243 and ATMEGA8 .
I took that new files ( uart.h and uart.c ) from that site http://mmdolze.users.sourceforge.net/use-a-lcd-with-twi.html
DeleteUart is there just for debug purpose. You could also remove that, or use anyother library. What i can say is that on HD44780 based LCD wiring is really important. So double chek it. Also, you could use a logic analyzer to debug the pcl8574 to lcd bus. Check that pcl8574 output works as desider, debug the output editing the code. Compile using avrgcc. Compile using your actual micro F_CPU. Check SCL_CLOCK of the twimaseter.c
DeleteHope this helps.
Thanks for answer, I will try to remove uart files. Can u only please tell me about configuration of pins for that: http://www.ebay.com/itm/Arduino-IIC-I2C-TWI-162-1602-16X2-Serial-Blue-LCD-Module-Display-Screen-/190573003243
DeleteHow it should looks like:
#define LCD_DATA0_PIN 0 /**< pin for 4bit data bit 0 */
#define LCD_DATA1_PIN 1 /**< pin for 4bit data bit 1 */
#define LCD_DATA2_PIN 2 /**< pin for 4bit data bit 2 */
#define LCD_DATA3_PIN 3 /**< pin for 4bit data bit 3 */
#define LCD_RS_PIN 4 /**< pin for RS line */
#define LCD_RW_PIN 5 /**< pin for RW line */
#define LCD_E_PIN 6 /**< pin for Enable line */
#define LCD_LED_PIN 7 /**< pin for Led */
To be honest I don't get it. What are that numbers from 0-7? Are they numbers of P0-P7 ?
Thanks for answer ;)
Hello, for that module, you have to trace out the pinout using a multimeter or whatelse.
DeleteAs example: LCD_RS_PIN -> 4 means that the pcl8574 P4 output goes to RS input pin of your 16x2 HD44780 based lcd.
This comment has been removed by the author.
ReplyDeleteHi David
ReplyDeleteThank you for libraries
Works fine in AtmelStudio6
I added the library into a new project and wrote in Project\Properties\Toolchain\AVR/GNU C Compiler\Symbols: F_CPU = 16000000UL
and comment string #include PCF8574_I2CFLEURYPATH in pcf8574.c
"F_CPU = 16000000UL" for Atmega328P for other chips another frequency
Good luck to everyone!
Thanks for your feedback!
DeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi David,
ReplyDeleteI have a quick question. Where do I set the i2c device id in your code? The default device id 0x27 and the device id of my i2c lcd backpack is 0x3F.
Thanks,
-Justin
Hello, it's in the pcf8574.h file: look at this PCF8574_ADDRBASE definition.
DeleteThis comment has been removed by the author.
ReplyDeleteHi Davide,
ReplyDeleteI'm trying to use a LCD2004A/PCF8574T with an atmega328P but after hours of debugging I still can't get it to work.
I already checked the pin mapping between the lcd display and the attached port expander by using a multimeter.
See here:
P0 -> RS
P1 -> RW
P2 -> E
P3 -> not connected to any of the lcd pins
P4 -> D4
P5 -> D5
P6 -> D6
P7 -> D7
The pin mapping and wiring shouldn't be the problem. I found out that my code hangs in the following while-loop in the i2c_start function.
while( !(TWCR & (1<<TWINT)) );
It seems that the TWINT flag never changes and therefore causes the program to hang in the while-loop.
In order to ensure there's no hardware issue I tested the i2c communication with the LiquidCrystal_I2C library from the Arduino IDE and it all worked fine. I could send text to my LCD display via i2c.
But I really want to use your code because it's completely written in C and not in C++ like the Arduino library.
Do you have an idea why the program freezes in the following code section?
uint8_t i2c_start(uint8_t address)
{
// reset TWI control register
TWCR = 0;
// transmit START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait for end of transmission
while( !(TWCR & (1<<TWINT)) ); // The program freezes at this point
Thanks in advance.
Hello, good explanation, and debugging! So, now I'm out of my main PC, but one first question is. Check with another SCL clock, and/or test your F_CPU settings, and you atmega fuse setting. Also, are you compiling it with avrgcc?
DeleteHello Davide,
Deletethanks for your reply.
Today I changed the SCL from 100000UL (100 KHz) to 400 KHz and 1.7 MHz, but none of these configurations worked. My F_CPU is at 16 MHz. According to the datasheet of the port expander (pcf8574) it requires an i2c SCL of 100 KHz to work properly, so I made my changes undone and set it back to 100 KHz.
In order to program my atmega328p I'm using an Arduino Uno with the "ArduinoISP" sketch installed on it. Further I'm using avrdude to uploaded the compiled .hex file of my C program to my atmega328p with the following fuse configuration.
lfuse: 0xe6
hfuse: 0xd9
This is my complete parameter chain of avrdude:
-U lfuse:w:0xe6:m -U hfuse:w:0xd9:m -e -F -v -patmega328p -carduino -P COM3 -b19200 -D -Uflash:w:"$(ProjectDir)Debug\$(ItemFileName).hex":i -C"C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf"
And yes I think I'm using avrgcc as a compiler, at least the project properties claims that.
Do you think it might have something to do with the fuse config?
Best regards,
Frans
So, if you are compiling for 16Mhz ( One simple think could be check it using UART debugging ). Check the PCF8574_ADDRBASE, is that the same of the Arduino library? Try this library: http://davidegironi.blogspot.it/2013/03/pcf8574-gpio-expander-library-for-avr.html Can you pull up/down any of the GPIO pin (check it with a multimeter)?
DeleteFrans & Davide,
DeleteI have exact same setup and same problem. 16MHz, Atmega328P Arduno Uno with Fundino I2C interface. Already confirmed that pins defined in header file are correct by connections test.
My code can't pass that while loop in i2c_start() function.
Do any of you know the root cause and the solution?
I'd appreciate it a lot if you share.
Cheers
Matt
I forgot to mention I'm using avr-gcc and the address is 0x27 as all 3 address pins on i2c interface are connected to Vcc.
DeleteLooking forward to hearing from you.
Matt
This comment has been removed by the author.
DeleteFinally solved!
DeleteThe root cause of problem was that PC4 & PC5 pins were not configured as output and was not set to high initially. Here is the list of changes need to be done on original code to let Arduino Uno and QAPASS LCD with Funduino I2C interface work:
1. PORTC PC4 and PC5 may need to be configured as output and initiated to 1 in beginning of main():
DDRC |= _BV(DDC5) | _BV(DDC4);
PORTC |= _BV(DDC5) | _BV(DDC4);
2. The value of LCD_DATA0_PIN, etc might need to change based on the connections of P7-0 on PCF8574 to LCD pins. No change needed in my case.
3. F_CPU should be defined as 16000000UL.
4. SCL_CLOCK should be defined 100000L ( it was 10000L which was causing overflow in TWBR initialised value, i.e. 0x81 instead of 0x318)
5. Value of PCF8574_ADDRBASE might need to change based on 3 address input bits of PCF8574 (0x27 in my case, where it was 0x20).
These corrections solved the problem on my setup and worked OK.
Cheers
Matt
Thank you for sharing your solution!
DeleteThis comment has been removed by the author.
ReplyDeleteThanks for this code...works like a champ. Used the pinout posted by Andrew (April 22, 2014), device address of 0x27, F_CPU=1MHz. Hardest part for this newbie was climbing the "make" learning curve to compile the code. Once that's accomplished, life gets much easier.
ReplyDeleteHello, and thank you for this feedback!
DeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHello. Step 1, debug your pcf8754 output. Check that the library really put a pin up and down, using the pcf8574_setoutputpinhigh function and a multimeter.
DeleteHello,
ReplyDeleteGreat Library, but I was wondering how I set it up to control multiple displays. I have a PCF8574 connected to each display and each '8574 has a unique address.
Any help on this would be greatly appreciated.
JIm
Hello, this libary was built to drive one display at time, anyway, if you want to drive more than one you can do it by changing functions in lcdpcf8574 files. You should built up an array of deviceid, then add the deviceid variable to all the funcitions. This is one way to do what you need, not the only one.
DeleteThanks, but I guess I should have been a little more clearer in my question. I do not want to update multiple displays with the same information, but have multiple displays with different information driven off the same I2C bus, with each display being serviced individually. How does one add the Device ID to teh functions?
ReplyDeleteJim
Yes, i understaind it. You have to implement multiple deviceid on the lcdpcf8574 library. This library cant at present drive one display. If you implement an array of multimple device id, you can drive many display at the same time.
DeleteI've implemented a libray based upon this, to drive up to 8 LCD display. It will be soon online.
DeleteI am guessing I would have to create multiple lines of these in the .h file:
ReplyDelete#define LCD_PCF8574_INIT 1 //init pcf8574
#define LCD_PCF8574_DEVICEID 0 //device id, addr = pcf8574 base addr + LCD_PCF8574_DEVICEID
As I see the DEVICE ID in the .c file, but I am wondering how in my main code I tell the library what display I want to talk to.
Sorry to be a bother, but I just think I am missing one key piece to this.
JIm
Great libraries. Got them to work with an atmega328p at 16000000Hz on 20x4 lcd. Thank you so much.
ReplyDeleteThank you!
DeleteThis comment has been removed by the author.
DeleteCame up with a problem after changing 20x4 blue series lcd screen to a green lcd series screen.Screen sometimes started up perfectly other times just produced garbage. Reliability was restored by adding 20ms delays after the lcd_e_toggle function calls in lcd_write function. This would seem a rather heavy handed solution if the problem is an iniation issue. I'll keep looking.
DeleteIs your AVR using the internal oscillator, or an external crystal? Also did you set up the clock frequencies in the .H files properly?
DeleteJIm
This comment has been removed by the author.
DeleteThis comment has been removed by the author.
DeleteThanks for your reply. External crystal at 16000000hz.
DeleteF_CPU has been defined correctly at all appropriate locations.
A pwm timer has been included in the code to verify clock speed.
oops 20 micro secs!
DeleteI am unable to successfully get the libraries to work, I get many errors in the twimaster. I am trying to use an ATmega325PA 16Mhz on a (20x4). I'm assuming its a little change but I just can't figure it out. Any assistance would be greatly appreciated.
ReplyDeleteTWXX undeclared (first use in this function)
DeleteHello, are you compiling with avr-gcc? This project is tested for this compiler usinc Eclipse.
DeleteDweck,
DeleteTake a look at your threads on AVRfreaks. I just posted there that the Mega325 WILL NOT work with Davides library, nor Peter Fleury's, and I explained why too.
I have a demo that you may have to get you going if you want it.
Jim
I am using this library in AVR-GCC and it does work Dweck as I recommended it to you on AVRfreaks. IF you want you can ZIP up your Studio project and post it in your thread and I can take a look
ReplyDeleteJIm
Hello, I'm sorry but I have no time to check your project, hope you understaind. So, is that a compile error, or a runtime error?
DeleteDAvide,
ReplyDeleteI was offering to help out Dweck as he has a thread going on AVRfreaks. I was not asking you to look at anything.
Jim
Ups, I'm sorry, it's my mistake part due to my bad english, and part due to the fact that usually people ask me to look at their project. Any help is apriciated. Thank you for you help James.
DeleteThis comment has been removed by the author.
DeleteNo Problem. Happy to help if I can
ReplyDeleteJim
Davide,
ReplyDeleteCongratulations! Your code works nice. My display is 20x4 and works. But, he write the text slowly. What's happen?
Thank you! It could be your I2C clock. Set it on twimaster.c. If you set your ATmega to run @ 8Mhz or more you could even set the clock at 100kbit/s (#define SCL_CLOCK 100000L)
DeleteThe schematic shown must be for a rather old version of the I2C-to-HD44780 character LCDs. All the ones available in 2016 have been updated to have 3 address offset solder pad jumpers. Also, the LED backlight driver circuit has a 2-pin push-on jumper to cut/supply power to the backlight LED.
ReplyDeleteNote that the series resistor to current-limit the backlight LED should be connected to the transistor's collector pin, not the emitter pin, just the same as with a NPN transistor. Emitter resistors are used exclusively to compensate for temperature drift in linear applications. There is no need for to do this for digital drive circuits.
I have redrawn the schematic and can make it available to you, but there is no way for me to attach the file to this message.
Hello, thank you for your suggestion. I've updated the schematics.
DeleteHi Davide,
ReplyDeleteI don't understand the lcd_read() function
In particular the line:
data = pcf8574_getoutputpin(LCD_PCF8574_DEVICEID, LCD_DATA0_PIN) << 4;
Isn't pcf8574_getinput() supposed to be the right one to apply the <<4?
Grazie
Ciao
Hello, you are right. There Peter Fleury use a trick, he read the PORT register - 2, so he read the PIN register.
DeleteLook at the read function here: http://pastebin.com/TF0ugKNa expires in 1 month. Let me know if it works, I will update the library.
Good job , but the most popular lcd model have "0x27" adress and in "twimaster.c" "F_CPU" is 4MHz , not 1MHz. I don't know Why?
ReplyDeleteThank you! You have to define the F_CPU according to your crystal. Anyway the twimaster it is setup only if any F_CPU directive is used.
DeleteThis comment has been removed by the author.
ReplyDeleteHello Davide! Trying to make your library works with AT90USB647. Looks like teh I2C is working, but I get no ack from display. I tried two differente brands with no luck.
ReplyDeleteI´m using an Agilent MSO-X2024 to inspect the protocol. I see the start, the slave addres (0x20) but no ack is sent back. This very same display works in Arduino. I adjust the speed to 100KHz. Any suggestion where to look? Thank you!
Hello. What's your micro freq.? I suggest you to check the pcf8574_setoutput function at first, just set pin on port to see if it works. Most of the time is a pcf8574 does not works is a problem of device id or timing.
DeleteThank you for your fast reply. Just found the problem. I´m in to it since 8AM (now 17:37PM). My problem was I have two displays with diffent addresses plus the pins were mixed up. I had a lot of problems converting to work for AT90USB647 too. Since I did not work with coding frequently, I had a rad time. But now everything is working great. Thank you for sharing the code.
DeleteThis comment has been removed by the author.
ReplyDeletei am new to atmel can you please help me how to include this library and how to use it.
ReplyDeleteHello, if you use Eclipe with the AVR plugin, you just have to create a new project, copy this project files in the source folder of that new project and compile it. There are many Eclipse + AVR tutorial online you can take a look at.
DeleteThis comment has been removed by a blog administrator.
ReplyDeletei was copied your code to a atmel's project. I was trying to fix bug but 4 errors i can't fix.
ReplyDeletehttps://plus.google.com/u/0/115791314223391483867/posts/cNN5UwzCGsN
Can you help me?
Hello, i think you are compiling twice some .c files. It is a few that i do not use ATmel Studio. You have to understaind why the Studio is trying to compling twice, or you can use Eclipse IDE + the AVR plugin, it is much more simple to me to handle a project with that IDE.
DeleteThis comment has been removed by the author.
ReplyDeleteHi mr. Davide my name is Tomislav and I have a problem. I am getting an error: Error 5 too many arguments to function 'uart_init'.
ReplyDeleteI am working with atmega16 in AVR studio. I can not campile it.
Tnx
Hello, This is compiled and tested using avr-gcc. About the uart library, I use the P.Fleury one, you can get it from his website here: http://homepage.hispeed.ch/peterfleury/avr-software.html
DeleteAs a suggestion, at first try to compile the P.Fleury sample project, then when you are sure the uart lib work, shift to this one.
Hi mr. Davide Iam getting Error 2 ../pcf8574/pcf8574.h: No such file or directory. I I copied all .h files to AVR install folder but when I compiled the program it doesnt see it. Can you tell me what's the problem. Tnx in advance.
ReplyDeleteHello, this error means that your compiler does not found this file. Try also to reference it in your project.
DeleteHi David,
ReplyDeleteThis is a very useful library. I missed only one fuction. This was a custom character handling, so I created the necessary functions. If you think it's useful so please add it to the source code.
- Prototype definitions in the lcdpcf8574.h
___________________________________________
/**
@brief Clear CGRAM
@param void
@return none
*/
extern void lcd_clear_CGRAM (void);
/**
@brief Create custom character in CGRAM
@param charnum: Character position in CGRAM. You can define maximum 8 chars.
@param values[]: Custom character descriptor pointer.
@return 0 - The custom character successfully created
@return 1 - If the charnum greater than 7. You can define maximum 8 chars.
*/
uint8_t lcd_create_custom_char (uint8_t charnum, const uint8_t * values);
- Implementations in the lcdpcf8574.c
_____________________________________
/*************************************************************************
Clear CGRAM
*************************************************************************/
void lcd_clear_CGRAM() {
register uint8_t addressCounter = 0;
for (; addressCounter < 64; addressCounter++) {
lcd_command((1 << LCD_CGRAM) + addressCounter);
lcd_putc(0x00);
}
}
/*************************************************************************
Define custom character in CGRAM
Inputs: charnum: Character position in CGRAM. You can define maximum 8 chars.
values[]: Custom character descriptor pointer.
Returns: 0 - The custom character successfully created
1 - If the charnum greater than 7. You can define maximum 8 chars.
*************************************************************************/
uint8_t lcd_create_custom_char(uint8_t charnum, const uint8_t * values) {
register uint8_t j = 0;
const uint8_t *p = values;
if (charnum > 7) {
return 1;
}
lcd_command((1 << LCD_CGRAM) + charnum * 8); // set CGRAM address charnum * 8 byte
for (; j < 8; j++) {
lcd_putc (*(p + j)); // write 8 byte data (one character) to CGRAM
}
return (0);
}
- How to use in your project
____________________________
1. Define the custom character (example the degree sign):
const uint8_t degree[8] PROGMEM = {
0b00001100,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
2. Create a custom character in the LCD CGRAM. This is the first from eight. (practically in the initialisation method):
lcd_clear_CGRAM(); // Clear CGRAM
uint8_t buf[8];
for (n = 0; n < 8; n++) {
buf[n] = pgm_read_byte_near (& degree[n]);
}
lcd_create_custom_char (0, buf); // Write custom char to CGRAM
3. Show custom character in your code:
lcd_putc(0x00);
Best Regards
Peter
Hello, thank you Peter. Please check this new version. https://expirebox.com/download/c83014ec3308bbe60d009e3025eb749b.html
DeleteI've add your name in the comment on lcdpcf8574.h. If it's all ok to you I will publish it.
Hi David,
ReplyDeleteI checked the new version and everything is OK. Thank you for your effort.
Best Regards
Peter
Thank you, code update has been added.
Deleteyour link i think was broke sir, can u repair it ?
ReplyDeleteHello, I think it was a sourceforge temporary problem. Now I can download it.
Deletethank's sir your code work fine, but i have issue when I using usart (RX TX). if I use library lcdi2c and
Deleteserial library together, the usart not work.
Hello, try the new P.Fleury library. The version I'm using here is the older one.
DeleteHi Davide, How can i integrate this lib to CodeVisionAVR? Thanks
ReplyDeleteHello, I think the only way is to port it to CodeVisionAVR compiler.
DeleteThanks Davide, I found a way to create lib from your C file, but so many error occurred.
DeleteDo i need just include lcdpcf8574.h to my code or which one? Your source code which has i2cmaster.h, lcdpcf8574.h, pcf8574.h, uart.h makes me confuse.
You have at least to include and compile files in lcdpcf8574, pcf8574 and i2chw. But you can also use another i2c library, if so you can use your and not use the i2chw one. Uart library is there just for debug purpose.
DeleteThanks Davide for your info.
DeleteWhen I try to compile your main.c it gives me a bunch of undefined reference errors. Any advice?
ReplyDeleteHello, you have to compile also libraries, adding those to your project. If you are using Eclipse IDE it really simple, you just have to add files to your project src.
DeleteTHANK YOU DAVIDE!!!!!!
ReplyDeleteI saw in your software that a UART is initialized. I also see a uart used in the main,c. Do I have to use UART anywhere. I am only interested in the LCD ans pcf8574T use.
ReplyDeleteHi Davide.
ReplyDeleteI'm developing a system that allows to set a square wave period, then, once setted, it drives a led with a square wave with the setted period. It also uses an I2C LCD for the user interface, that uses your library. Anyway if i set the period, the output square wave isn't consistent, with heavy random period variation.
May your library affecting the precision of the internal timer?
Hi Davide!
ReplyDeleteWhen I call lcd_getxy() function. It always return with 17 value. Why is it? You have any idea?
Thanks
Dani
This function (lcd_getxy()) is not present in lcdpcf8574.h
DeleteThanks.
ReplyDeleteWorks on Atmega16.
My device PCF8574 need to change adres
#define PCF8574_ADDRBASE (0x3F) //device base address
in pcf8574.h
If set
#define F_CPU 8000000UL
I2C works on 400kHz
/* I2C clock in Hz */
#define SCL_CLOCK 400000L
Thank you for sharing.
DeleteHoly cats this man is patient - I can't believe what people ask.
ReplyDeleteAnyhow after much debugging, throwing a Saleae I was convinced the code was working. Just throwing this out there. If the code is running and you can see through Uart debugging that its not hung etc. Try this - while the code is running adjust the potentiometer at the back of your i2c display. Yes folks sometimes it can be this simple. Your welcome :)… Thanks for the awesome code...
Thank you for sharing your experience
DeleteHi
ReplyDeletetnx for your library but when i tring to use it and smulate circuit in proteus,nothing happen . even atmega8 pins cant creat i2c pulses when i scoped sda and scl pins.
can you help me ?
Hello, check with a logic analyzer the i2c line.
DeleteThis comment has been removed by a blog administrator.
ReplyDeletethanks brother!! it worked. you are our hero!!!
ReplyDeleteThank you for this comment!
DeleteThis comment has been removed by the author.
ReplyDeleteHello MHMLD, avrdude can not find the input file "can't open input file". You can try this gui here if it helps, https://blog.adafruit.com/2013/02/19/avrdudess-a-gui-for-avrdude/. Or use Eclipse IDE with AVR plugin, that is much more simple.
DeleteI will try. Thanks a lot
DeleteHi David. The code compiles but when i send the code to my atmega328p the output is this:
ReplyDeleteavrdude.exe: Device signature = 0x1e950f (probably m328p)
avrdude.exe: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude.exe: erasing chip
avrdude.exe: warning: cannot set sck period. please check for usbasp firmware update.
avrdude.exe: reading input file "C:\Users\magda\Desktop\GccLibrary1\GccLibrary1\Debug\libGccLibrary1.hex"
avrdude.exe: can't open input file C:\Users\xxxxxx\Desktop\GccLibrary1\GccLibrary1\Debug\libGccLibrary1.hex: No such file or directory
avrdude.exe: read from file 'C:\Users\xxxxxx\Desktop\GccLibrary1\GccLibrary1\Debug\libGccLibrary1.hex' failed
avrdude.exe: safemode: Fuses OK (E:FF, H:D9, L:E2)
avrdude.exe done. Thank you.
Can you help me pls???
Hello MHMLB, look at my reply above.
DeleteHello Davide. I endend up to install the eclipse ide. But my output was this:
ReplyDeleteaviso: ‘SIG_UART_DATA’ appears to be a misspelled signal handler, missing __vector prefix [-Wmisspelled-isr] uart.c
aviso: ‘SIG_UART_RECV’ appears to be a misspelled signal handler, missing __vector prefix [-Wmisspelled-isr] uart.c
aviso: #warning "Compiler optimizations disabled; functions from won't work as designed" [-Wcpp] teste_atmega line 112, external location: /usr/lib/avr/include/util/delay.h C/C++ Problem
erro fatal: lcdpcf8574/lcdpcf8574.h: Ficheiro ou directoria inexistente main.c /teste_atmega line 18 C/C++ Problem
erro: tentativa de usar "SIG_UART_DATA" envenenado uart.c /Teste/uart line 87 C/C++ Problem
erro: tentativa de usar "SIG_UART_RECV" envenenado uart.c /Teste/uart line 86 C/C++ Problem
make: *** [subdir.mk:23: main.o] Error 1 teste_atmega C/C++ Problem
make: *** [uart/subdir.mk:20: uart/uart.o] Error 1 Teste C/C++ Problem
nota: in expansion of macro ‘UART0_RECEIVE_INTERRUPT’ uart.c
nota: in expansion of macro ‘UART0_TRANSMIT_INTERRUPT’ uart.c
Can you help me??? I always used the atmel studio and I have had difficulties
Hello MHMLB. You have to add the folders in the compile path. "Ficheiro ou directoria inexistente", your compiler can not find the lcdpcf8574.h file. Take a look here https://www.instructables.com/id/How-to-get-started-with-Eclipse-and-AVR/
DeleteSorry for being so anoying but now the errors are those...
Delete#warning "Compiler optimizations disabled; functions from won't work as designed" [-Wcpp] Test line 112, external location: /usr/lib/avr/include/util/delay.h C/C++ Problem
erro fatal: ../i2chw/i2cmaster.h: Ficheiro ou directoria inexistente pcf8574.c /Test line 25 C/C++ Problem
make: *** [subdir.mk:32: pcf8574.o] Error 1 Test C/C++ Problem
Can you help me pls?
You keep having the same error, you just have to add the folder as "source" in the Eclipse project.
DeleteWell the error now is in the file pcf8574.c in include PCF8574_I2CFLEURYPATH. I cant understant....sorry again for being so anoying xd
DeleteHello MHMLB. You have specify the correct relative path of the library. It's the relative to library one.
DeleteHey Davide, first thanks for the libary it works fine. My Question is, why i cant pull R/W directly to GND? If i do the display shows nothing.. thanks
ReplyDeleteHello Florian. Thank you. The Rear/Write pin put the LCD between Read/Write mode. It's just because it does not works like this, for further information you can take a look here: https://www.sparkfun.com/datasheets/LCD/HD44780.pdf as example look at "Interfacing to the MPU" figure 9.
DeleteHey Davide, I've been using your code on an Atmega 8 with a 20x4 LCD display and it works very well. I was just wondering if there was away to speed it up so text appears instantaneously on the screen rather than scrolling across?
ReplyDeleteHello Ben you could try to speed up the I2C speed.
DeleteHi Davide,I can set the output pins ok but how to read the input pins?I think I should use getinputpin()? but how to see the out put then?
ReplyDeleteHello, if you need you can use pcf8574_getinputpin.
DeleteHi,
ReplyDeleteI have problem with LCD 2004A. If I'm printing for example one char in loop it will not print anything on line4. When cursor should move to line4 it will move to line2. I did some debugging but I cant find the root cause of this issue.
#define LCD_LINES 4 /**< number of visible lines of the display */
#define LCD_DISP_LENGTH 20 /**< visibles characters per line of the display */
while(1) {
lcd_putc('A');
_delay_ms(50);
lcd_putc('a');
_delay_ms(50);
}
Dear mba, now I do not have any 4 lines LCD to help you.
DeleteThis library it's based on the P.Fleury one, did you check it with native Fleury? http://www.peterfleury.epizy.com/avr-software.html?i=1
Thank you David. I will check it.
DeleteYou should change the line LCD_DISP_LENGTH to 80 as LCD 20x4 have 80 characters. Also change the line TEXT_WRAPPING (I think, it below few lines from LCD_DISP_LENGTH) and change it to 0.
DeleteHi Davide. so I spent 3 days searching for i2c lib for atmega16A and here I am here. it seems to work with a lot of people here but not with me . I fixed all the errors that appear and it compiled without errors on Atmel studio 7 but nothing on UART or on i2c lcd.. I am using proteus.. plz I am disparate for help
ReplyDeleteHello Alaa, try using avrgcc as compiler, double check you wiring, do not use simulators, use real hardware. If you have, use a logic analizer.
DeleteHi, Did you write this library for Arduino?
ReplyDeleteOf course, I know that Arduino has its own library, but I am more interested in your library and I really like the way letters and numbers are printed on the screen.
Of course, it would be great if there was a way to add that to the Arduino libraries.
Also, thank you very much for this excellent library ...
Hello Mohammed, thank you for having appreciated my work, unluckily this is just a avrgcc library, I think you can easly move this to the Arduino framework.
DeleteHi, great work!
ReplyDeleteI want to know if there is a way to read with MCU what the lcd shows?
Hello, thank you.
DeleteNot with this driver.
Hello Davide,
ReplyDeleteYour library is very nice and works fine. I have one question. I am using atmega328p on aruino board and I want to use on SPI one more device (GY-906 IR temp sensor). Is it somehow possible? I tried use your example, but into while(1) loop I put my working code before lcd_puts() to read temperature from sesor via SPI. But this not works (display is not showing anything) and on first look I think, that lcd needs to be again addressed after reading temperature. Generally, how should it be done correctly? I mean communicate with lcd and another SPI device/s with your library.
Hello, yes it's possible. You can use two SPI. At first, you should initialize SPI once. Then, I would check the GY-906 reading using something like the UART. Then I would check the lcd usage. Then, only after both works, I will put all togheter.
DeleteHello,
DeleteThanks for your reply. Yes, this is exactly what i did. GY-906 with SPI works in my test project. LCD also works in test project. Now I am connecting both these parts. In my main loop i have code as shown bellow. When I comment part beggining with "i2c_start(GY905ADDR+I2C_WRITE);" and ending with "i2c_stop();", then LCD is working and writing some text from code bellow this section. But when I remove comment, display is not showing anythink. It must stuck somewhere on SPI GY-906 sesor section I uncommented. Do you have some idea? I can provide some way whole project if it can help.
lcd_led(led); //set led
//led = !led; //invert led for next loop
//Start of temp sesor section
i2c_start(GY905ADDR+I2C_WRITE);
// RAM read from 0x07 address
i2c_write(0x07);
//read data
i2c_rep_start(GY905ADDR+I2C_READ);
data_low = i2c_readAck();
data_high = i2c_readAck();
pec = i2c_readNak();
i2c_stop();
//0.02 degrees per LSB (measurement resolution)
float tempFactor = 0.02;
float tempData = 0x0000;
//Temperature conversion, MSB is error bit
//This masks off the error bit and concatenate data
tempData = (float)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;
//Convert data to Celsius
float celsius = (tempData - 273.15);
// Convert float to string
sprintf(out_str, "IR Temp (C) = %.3f\r\n", celsius);
//End of temp sensor section
lcd_gotoxy(1, 0);
lcd_puts(out_str);
Hello,
DeleteSo at the end I solved the problem. Code was stuck on line "i2c_write(0x07);". Problem was, that for testing GY-906 I used Peter Fleury library directly downloaded from his web page with SCL_CLOCK 100000L in twimaster.c file. Your LCD library had difference in this define, SCL_CLOCK 10000L. So I solved this by changing 10000L clock to 100000L clock in your project. Now it works, sensor and LCD, both on SPI bus. I am not sure, why you have like this, but it can be cunfusing for another peoples.
Great! Thank you for sharing, this may helps other people! Miy SCL clocl is set to 10000L cause this project is running @ 1MHz.
DeleteHello Davide,
ReplyDeleteThank you for your library. It worked great with me (ATmega328P and LCD 20x4 i2c) after I change some define line in your lcdpcf8574.h file. But there is a small problem. My refresh rate is quite slow (I can see the clear progress invidually), although I increased the SCL_CLOCK up to 100000L and 400000L, my F_CPU change to 16Mhz, all defined in the main.c file in the src folder. So I wonder that maybe I can increase my screen refresh rate somehow?
Thank you for your library. Have a nice day!
Hello, thank you. You should try editing the lcd_write function, although I haven't noticed that slow speed, indeed I've to slow the display loop down if I do not want the screen to "flicker".
DeleteHello David,
ReplyDeleteThe first of all - thank you so much for you library it is very useful and I appreciate your work.
Looks like I found a bug in lcdpcf8574, the mode "LCD_WRAP_LINES" doesn't make sense for 20x4 display. Please take a look addressing of the typical LCD 20x4:
line0: 00-13
line1: 40-53
line2: 14-27
line3: 54-67
If the "LCD_WRAP_LINES==1 && LCD_LINES==4" the following code works out:
if( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);
}
else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE3,0);
}
else if ( pos == LCD_START_LINE3+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE4,0);
}
else if ( pos == LCD_START_LINE4+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
}
So it makes a mess, if you use position (0,2) it happens in (0,1) instead and if you use (0,3) it happens in (0,2) place instead. Because in 20x4 LCD address space is split between odd and even lines.
So maybe disable the mode for 20x4 LCD ?
Thank you,
Alex
Hello, thank you for your post. I don't have a 20x4 now. I've to think about this, first of all, have you changed the LCD_DISP_LENGTH macro from 16 to 20?
DeleteYes I did, I used 20
DeleteAs i said I do not have a 20x4 right now. You can disable this mode just setting LCD_WRAP_LINES to 0. Anyway if it happens to me to have a 20x4 or you find a way to solve this please share this. Also consider that this library is based on the P.Fleury one (http://www.peterfleury.epizy.com/avr-software.html), there are a few post on avr-freaks about this library, I'ven't find this kind of error there. But if you find this, please tell me.
DeleteDavid, I'd disabled, I posted it here only to let you know that such issue exist, maybe someone reads this post and also find a solution in disabling.
Delete