I realize there are several posts on this topic - i have read so many of them. However, none of them seem to have a solution that works for me.
There is a post that mentions the DHT lib may be interfering with I2C, but there is not a solution for fixing it.
I know that there are a lot of variables in this problem, but I was hoping someone could look over my code and rule out anything in there that might be causing the issue.
A little about the setup:
I am using an Lolin D32 that connects to a Uno with three wires(SCL,SDA, COM). The wires between the two devices is about 24 inches long.
I repurposed a shielded ethernet wire and have the shielding connected to a ground source.
There are two 10k pull up(5v) resistors that are between the Uno and a level converter.
On the other side of the level converter there are no pull up resistors
The Uno has a Temp/Humidity sensor attached to it and uses the DHT lib.
There is a RTC that is connected directly to the 5v side of the level converter - I also have a version of this project that gets time from wifi, and does not include the RTC. The problem still happens so I have ruled out the RTC as an issue
The I2C wires do run next to some AC wires, but I have also tried to run this system without the AC wire on and I still get the same issue.
My code was making the page exceed the 9000 character limit so I have instead attached both files
Thank you in advance for reading this and offering any suggestions!
On the other side of the level converter there are no pull up resistors
I2C absolutely requires pullup resistors to function. Please post a hand drawn schematic diagram (not Fritzing) and a link to the data sheets or product pages for the sensors.
Explain "stops working". What should happen, and what happens instead? Why do you think this has to do with I2C?
By "stops working" I mean that the communication between my two boards stops working after successfully running for 10-30 minutes.
On the D32(Master) I am subscribing/publishing to an mqtt server. Data from the server is sent to the D32 over wifi then on to the Uno via I2c. The D32 is located outside of the structure(a chicken coop) so that it can get a better wifi signal.
The Uno(slave), located inside the coop is running a program that checks sensors and collects temp/humidity. That data is continually sent to the D32 which then updates the mqtt server.
When the boards first turn on, they both start communicating as expected. After 10-30 minutes of working properly, the communication between the D32 and Uno stops. When I reset the boards, the communication begins again.
This makes me think that the I2C is getting interrupted, or I hit some memory limit, or - i don't know...
I ran the same setup in my workshop to see if the problem happened there as well and it did.
I am using I2C because:
1- It is easy to set up(or so I thought)
2- it uses only 2 IO pins and my Uno uses most of the digital pins
Is UART or Serial a better option? I have avoided serial because, as I understand it, I could no longer debug with the monitor. UART looks like it uses 4 IO pins, which would mean I would have to use the tx and rx pins(unless I used a shiftIn - but I would rather not rebuild my entire board )
Interestingly, the I2C worked equally well(or poorly) when I had no pull-up resistors, OR when I included pull-up resistors on the 3.3v side in some other testing. But I deferred to other people's advice online and added pull-ups on the 5v side.
I do not have a datasheet for the level converter, but it seems like a common on. I have included a picture of one below. I don't know how it works exactly and was wondering if it already has pull-up resistors on it? I got it here.
Interestingly, the I2C worked equally well(or poorly) when I had no pull-up resistors,
I2C does NOT WORK AT ALL without pullup resistors, so if it ever works, they are there somewhere.
The diagram is useless, because it does not show all the connections. Where are your ground and power connections?
You still have not explained what you mean by "stops working", nor have you explained why you think that I2C communications are failing. However, as the question by PaulS suggests, you are misusing I2C. It is designed for chip to chip communications on one PCB.
jremington:
However, as the question by PaulS suggests, you are misusing I2C. It is designed for chip to chip communications on one PCB.
What? I2C is for chip to chip communications only?
How does it know that it's on one PCB?
If that truly is the case, then why are there pins for it on countless boards, including Arduino?
I see lots of posts from people using I2C comm between Raspberry Pi and Arduino. There are also tutorials on this site like: https://www.arduino.cc/en/Tutorial/MasterWriter
Are you suggesting that all of those posts are wrong?
jremington:
You still have not explained what you mean by "stops working", nor have you explained why you think that I2C communications are failing.
I'm not sure how I could explain this any differently, but I will give it a try:
When communication is "working", board1 will send an array of bytes to board2 via I2C. Board2 will receive the array and do something useful with it. Board2 will also send an array of bytes back to Board1 via I2C and that first board will do something useful with it.
I can get the above scenario to work, but only for a span of 20 minutes or so.
When this is "not working", neither of the two boards are successfully transmitting the byte arrays to the other board. I can tell that the data is not being transmitted because I am using a serial monitor on each board to see if the data is coming in from the other board.
As for my diagram, I assumed that showing the "5v/3v" text on there that people would assume that everything on the "3v" side of the line was connected to 3v. I also mentioned in my original post that the two boards are connected to one another with a "COM", which is something I have seen in many other posts here to represent a common ground connection. In the case of my setup, every device in the diagram, on both the 3v and 5v sides, shares a common ground(-) connection.
I am using a serial monitor on each board to see if the data is coming in from the other board.
All that means is that one or the other program has stopped working for some reason, which does not help in debugging your problem. A common cause of such behavior is use of String objects, which tend to corrupt memory and often lead to seemingly random program hangups.
I2C is designed for very short connections between chips on a PCB. The design principles can certainly be violated.
People are able to successfully use I2C over longer connections, but you can expect problems. This article explains them.
jremington:
People are able to successfully use I2C over longer connections, but you can expect problems.
I read somewhere that 'long' meant lengths of a meter or greater. I have a length of approx 24inches. Do you think my setup falls under 'long'?
jremington:
All that means is that one or the other program has stopped working for some reason, which does not help in debugging your problem.
Is it possible for just part of a program to stop running? When the I2C communication stops, I am still getting feedback from the boards via the serial monitor i.e. messages in the loop continue to show up in the monitor.
jremington:
A common cause of such behavior is use of String objects, which tend to corrupt memory and often lead to seemingly random program hangups.
I tried to replace 'String' with 'string' and 'char', but both of those broke my code. What could I use in place of String?
Right now, I suppose I should be asking the bigger question of whether or not I should even use I2C for my project. I have been messing around with Serial the past few days and I can get an array to send from one board to another. However, as soon as I try to send and receive using Serial, I get totally unexpected numbers data in my arrays. I am still pretty new to all of this and I don't understand Serial in the least. I read the 'Serial Basics' but nothing in there seems to reference Arduino-to-Arduino 2-way communication.
Do you have any suggestions for the most appropriate way to have two Arduinos share numeric data? They don't need to share the same data, but one board needs to pass 8 different numbers to one board and the other board needs to pass 6 numbers back.
Your comment has been super helpful. Thanks for your help and any insight you can give!
Certainly, but whether the problem becomes serious depends on the capacitance in the wiring, the values of the pullup resistors, etc.
I looked at your program and see that you do not appear to be using Strings, so that is unlikely to be the problem.
However, you don't seem to be treating I2C communications correctly. The following code, for example, does not necessarily read the number of bytes that are actually available, and may leave one byte "hanging" in the input buffer. That could easily lead to long term failures.
Personally, I use TTL-level serial RS232 for such communications tasks, as described in Serial Input Basics. There is no requirement to use a PC on one end, the information in that post applies to Arduino-Arduino communications. This type of serial communications is much easier to debug. You could use a Mega, with extra serial ports, or a software serial library like AltSoftSerial.
Finally, I strongly recommend that you get Arduino-Arduino communications working with 100% reliability before adding in the Wifi stuff.
Just a fast tip when you are sending from esp32 to uno is that int on arduino are 2 byte and on esp32 they are 4 byte long, to get around this you can use int16_t instead of int on esp32. Same problem with long (int32_t)
Not sure if this have anything to do with your problem or not, but its something that can cause problem (at least it has for me...)
Best of luck