I2C not working on standalone ATMega328

Out of all the “unsolvable” issues I’ve come across these past year of learning and programming on Arduino this is by far the one that stuck for the longest.
I have seen other similar posts, but the solution was either ‘bad wiring’ or unintelligible. For the life of me, bad wiring is not the case here.

I have a 16x02 LCD with a PCF8574 I2C, connected as shown in attachment #1.

The problem:
With the ATMega328 ON the Arduino Uno board, everything works great. I2C scanners find it on 0x3F and all’s well. I had no pullup resistors in this configuration (found out later they were needed).

With the ATMega328 OFF the Arduino Uno board, the LCD displays white squares on top row and blank on the second row, meaning it doesn’t reckon being connected to the MCU. I have 4.7k pullups on both SDA and SCL lines, and have tried different values.

The story:
The whole circuit consists of a temperature sensor, a rotary encoder, 2 relays, a linear regulator, a (small) heating element and a couple transistors.
As said, everything works great when connected to the Arduino Uno, hence I moved it to its own PCB I made, and that’s when I found out the LCD wasn’t working. I put the MCU back on the Arduino and tried the LCD (only the LCD, at this point onwards I’m not involving any other components), and it worked like it should. Now I moved the MCU to a breadboard (attachment #2) and the LCD won’t work.

I have tried modifying twi.c on “[Arduino Install]\hardware\arduino\avr\libraries\Wire\src\utility” to disable the part where pullups are enabled on the MCU, but the results were the same.

These are the parts of my code that involve the LCD:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>

#define lowPwrFanSw 11
#define ltRelay 8
#define highPwrFanSw 7
#define heatSw 5
#define btnSetup 2

Encoder encSetup(3, 4);

LiquidCrystal_I2C lcd(0x3F, 16, 2);

void setup() {
  lcd.begin(16, 2);
  lcd.createChar(0, degree);
  lcd.createChar(1, iTilde);
  lcd.setCursor(3, 0);
  lcd.setCursor(4, 1);

  pinMode(ltRelay, OUTPUT);
  pinMode(heatSw, OUTPUT);
  pinMode(highPwrFanSw, OUTPUT);
  pinMode(lowPwrFanSw, OUTPUT);
  pinMode(btnSetup, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(btnSetup), btnInterrupt, FALLING);

  // Reset timer1
  TCCR1A = 0;

  // Restart timer on compare
  TCCR1B &= ~(1 << WGM13);
  TCCR1B |= (1 << WGM12);

  // Prescaler to 1024
  TCCR1B |= (1 << CS12);
  TCCR1B &= ~(1 << CS11);
  TCCR1B |= (1 << CS10);

  // Set compare value
  OCR1A = 62500;

  // Set interrupt for Timer1 overflow
  TIMSK1 = (1 << OCIE1A);

  // Enable global interrupts

Then follows loop() and some other functions but I don’t post it because the code worked and I only need to execute setup() to check if the LCD works.

Thanks to everyone in advance!

Atmega standalone w-lcd.png

The bare bones setup shown on the breadboard and the schematic lack decoupling caps. They are essential. See this tutorial.

That may not be the only problem, but adding 100 nF caps is an important first step.

Yes, forgot to mention that in my post. I have decoupling capacitors in my PCB setup exactly the same as in Gammon's tutorial, but not on the breadboard. I guess that means they don't really affect the LCD (althought they are needed for the MCU!).

Yes, do add some decoupling caps.

Looking at your code here:

void setup() {

As far as I know when you specify an address with Wire.begin(), as above, you are setting up as a slave. You cannot talk to the LCD if you are running as a slave.

Looking at your breadboard picture it is not clear if the two 4.7k pull-ups go to the individual I2C pins or both go to SDA. I assume you have that correct.


Thanks for the insight, that was something I tried when nothing else worked. Of course, it didn't work either lol but I kept it in the code. Just to be sure I tried it now withouth the address between parenthesis and it still won't budge. Same story with the Wire.setClock() command, tried it with and without.

I think the main issue here is that neither the LCD nor the MCU acknowledge having something connected to the SDA/SCL pins.

OK, I understand. Was a thought.

I must admit I do not understand what is going wrong. I use the 328P on a breadboard all the time and always use an I2C LCD display for debugging. I have never experienced a problem like this.

Just as a “by the way”, those I2C display adapters usually have on-board pull-ups.


Just one last point.

My I2C adapters look exactly like yours. However, with the address pins as supplied (none of them bridged), all of mine respond to address 0x27 by default.



For the first time in weeks I got a proper reading from the LCD!!!

It was really a lucky find, since I wasn't even trying lol

I was running an I2C Scanner (Nick Gammon's), like I did many many times before (with the LCD not beign found), but this time I tried to move the SCL's cable closer to the MCU (notice in my breadboard image it is a few holes apart) and accidentally touched the MCU's pin with the cable's tip.. voila! The I2C scanner found a device on 0x3F, which was my LCD's address in the first place!
So I ran my code but this time I waited until the code was uploaded, then took the SCL's wire out of the breadboard and touched the MCU's pin with it, and it worked!

I'm not sure if this is more comforting than baffling 'cause I have not the slightest sign of an idea as to what the :heart::heart::heart::heart::heart::heart::heart: hell is going on.

To keep in mind, like I said in my original post, the LCD and MCU used to be on a PCB with solder in between the MCU and the wires going to the LCD, and it still wouldn't work. So I wouldn't consider the breadboard's connections to be the problem.

Cheap Dupont wires are often not crimped properly.

Atmega standalone w-lcd.png

Those look like 470 ohm resistors.

Always, always, and always use proper power supply decoupling!

Those look like 470 ohm resistors.

You mean because of the colors? It’s yellow-violet-red, they’re 4.7k resistors!

Cheap Dupont wires are often not crimped properly.

It turns out the breadboard’s internal connection was the problem, not the wire nor the MCU.

However, I put the MCU and LCD back in the PCB and got the same as before, it’s not working. I checked and triple checked that all connections are OK, so I’m back at square one I guess…

I attached a picture of my PCB. The only thing I, as a total n00b, see kind of itchy is the fact that I placed the pullup resistors “after” the wires going to the LCD, instead of in-between the cables and the MCU pins. As fas as I know in electronics that doesn’t matter functionally speaking, but maybe because they’re acting as pullups and not just normal resistors… I don’t know. I’ve also rectified the previously modified twi.c in the Wire library, so that it activates the pullups on SCL and SDA as it normally would, but then I deactivate them in the setup() of my code, like so:

PORTC = PORTC | B11001111;

I’ve read many times those pullups are weak and I’d rather go without them.

Apart from that, you can see in the image I have proper decoupling capacitors on the 12v input, on the LM7805, also between VCC-GND and AVCC-GND.

Here it looked like yellow violet brown in the image.

I can assure you they're 4.7k, I've measured them :stuck_out_tongue:

The only thing I, as a total n00b, see kind of itchy is the fact that I placed the pullup resistors "after" the wires going to the LCD, instead of in-between the cables and the MCU pins. As fas as I know in electronics that doesn't matter functionally speaking, but maybe because they're acting as pullups and not just normal resistors... I don't know.

What do you think about this? Am I beign silly or could it affect the circuit even slighty?

Does not matter where you put them as long as they pull up the lines. You certainly have some strange things happening there.

Sorry I cannot be of more assistance.


Check all connections for shorts, continuity and proper resistance values using your multimeter.

Suspect even IC sockets, so start by putting probe tips right on the microprocessor pins.

Sorry for the late reply, I left the proyect for a while to clear my mind off it.

Got back to it recently, moved only the MCU and LCD to a new smaller PCB with crystal, 22pF caps, and 0.1uF caps on VCC and GND, now the LCD's working as intended.

Conclusion: there was someting fuzzy on the previous PCB. To date I still don't know what, I've checked the connections with a multimiter to no end.

Thanks to everyone for baring with the noob, much appreciated :slight_smile: