Skip to content

I2C and SPI not working alongside each other #912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Manuauto opened this issue Dec 10, 2017 · 18 comments
Closed

I2C and SPI not working alongside each other #912

Manuauto opened this issue Dec 10, 2017 · 18 comments

Comments

@Manuauto
Copy link

Manuauto commented Dec 10, 2017

EBikeMainProject_V2_ESP32_RTCDebug.zip

Hardware:

Board: DOIT ESP32 Devkit v1
Core Installation/update date: 10. Dec. 2017
IDE name: Arduino IDE 1.8.5 / Visual Micro
Flash Frequency: 80Mhz
Upload Speed: 921600

DS3231, ILI9341
Libraries: Adafruit_GFX, Adafruit_ILI9341, RTClib or Rtc by Makuna

RTC on Pins:
22, 21
Display:
16, 17, 5, 18, 19, 23
(GPIO Pin Numbers)

Description:

I want to use an ILI9341 SPI Display and an I2C RTC Module (DS3231) in a project of mine.
These devices themselves work fine with no problems. Whenever I initialize the instance for the Display, the RTC Data seems to be corrupted or invalid.
I have tried two different RTC Libraries with no difference.

The strange thing is that I get valid time and date information from the RTC with a display running after my projects was without power for about a day. I have added pull-up resistors (4.7k) with no success. The RTC should be OK with 3.3V, I have tested it on an Arduino down to 2.3V.

Sketch:

`//Libraries
#include <Wire.h> //required for I2C
#include <RtcDS3231.h>

#include <SPI.h> //For Display
#include <Adafruit_GFX.h> //For Display
#include <Adafruit_ILI9341.h> //For Display

#define _cs 17 // goes to TFT CS
#define _dc 16 // goes to TFT DC
#define _mosi 23 // goes to TFT MOSI
#define _sclk 18 // goes to TFT SCK/CLK
#define _rst 5 // goes to TFT RESET
#define _miso 19 // Not connected

RtcDS3231 Rtc(Wire);
Adafruit_ILI9341 tft = Adafruit_ILI9341(_cs, _dc, _rst);

//////////////////////////

void setup() {
Serial.begin(9600);

Serial.print("compiled: ");
Serial.print(__DATE__);
Serial.println(__TIME__);

Rtc.Begin();

RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
printDateTime(compiled);
Serial.println();

if (!Rtc.IsDateTimeValid()) 
{
    
    Serial.println("RTC lost confidence in the DateTime!");

    Rtc.SetDateTime(compiled);
}

if (!Rtc.GetIsRunning())
{
    Serial.println("RTC was not actively running, starting now");
    Rtc.SetIsRunning(true);
}

RtcDateTime now = Rtc.GetDateTime();
if (now < compiled) 
{
    Serial.println("RTC is older than compile time!  (Updating DateTime)");
    Rtc.SetDateTime(compiled);
}
else if (now > compiled) 
{
    Serial.println("RTC is newer than compile time. (this is expected)");
}
else if (now == compiled) 
{
    Serial.println("RTC is the same as compile time! (not expected but all is fine)");
}

// never assume the Rtc was last configured by you, so
// just clear them to your needed state
Rtc.Enable32kHzPin(false);
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);

//tft.begin(); //UNCOMMENT THIS and RTC stops working
//tft.setRotation(3);
//tft.fillScreen(BLACK);
Serial.println("Started");
}

void loop() {

if (!Rtc.IsDateTimeValid())
{
// Common Causes:
//1) the battery on the device is low or even missing and the power line was disconnected
Serial.println("RTC lost confidence in the DateTime!");
}

RtcDateTime now = Rtc.GetDateTime();
printDateTime(now);
Serial.println();

RtcTemperature temp = Rtc.GetTemperature();
Serial.print(temp.AsFloat());
Serial.println("C");

delay(1000); // ten seconds

}

#define countof(a) (sizeof(a) / sizeof(a[0]))

void printDateTime(const RtcDateTime& dt)
{
char datestring[20];

snprintf_P(datestring, 
        countof(datestring),
        PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
        dt.Month(),
        dt.Day(),
        dt.Year(),
        dt.Hour(),
        dt.Minute(),
        dt.Second() );
Serial.print(datestring);

}`

Debug Messages:

Sketch uses 167906 bytes (12%) of program storage space. Maximum is 1310720 bytes.
Global variables use 11708 bytes (3%) of dynamic memory, leaving 283204 bytes for local variables. Maximum is 294912 bytes.
esptool.py v2.1
Connecting........__
Chip is ESP32D0WDQ6 (revision 1)
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 8192 bytes to 47...

Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 10922.6 kbit/s)...
Hash of data verified.
Flash params set to 0x022f
Compressed 11120 bytes to 7467...

Writing at 0x00001000... (100 %)
Wrote 11120 bytes (7467 compressed) at 0x00001000 in 0.1 seconds (effective 977.6 kbit/s)...
Hash of data verified.
Compressed 169056 bytes to 95319...

Writing at 0x00010000... (16 %)
Writing at 0x00014000... (33 %)
Writing at 0x00018000... (50 %)
Writing at 0x0001c000... (66 %)
Writing at 0x00020000... (83 %)
Writing at 0x00024000... (100 %)
Wrote 169056 bytes (95319 compressed) at 0x00010000 in 1.4 seconds (effective 993.0 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 122...

Writing at 0x00008000... (100 %)
Wrote 3072 bytes (122 compressed) at 0x00008000 in 0.0 seconds (effective 3072.0 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting...

NOTE: The attached file contains both my full project and the smaller Debug file which does produce the same error.

@beegee-tokyo
Copy link
Contributor

beegee-tokyo commented Dec 10, 2017

I have SPI and I2C running perfectly in parallel on my ESP32. Different devices (TSL2561 light sensor and ILI9163 TFT display) but it runs without problems.
Had problems when I started because the TFT display library was not optimized for the ESP32. After initializing the TFT all kind of different problems (OTA not working, I2C data corrupted, data from a DHT11 sensor corrupted) until I switched the TFT display library to TFT_eSPI. This library supports the ILI9341 as well. I think it is compatible with the Adafruit GFX library. So maybe you can give it a try.

Update
Another thing I did was to separate sensor readings and display output into different tasks. You can see the code in my repo ESP32-Weatherstation

@Manuauto
Copy link
Author

Manuauto commented Dec 10, 2017

Thank you for your suggestion. Unfortunately it did not work.
The issue seems to be in the esp32-core itself.

i2c communications on ESP32
SDA / SCL read very unstable

For now I will have to wait. In the meantime, there is no other option to order a SPI-compatible RTC (DS3234 )...
Unfortunately the RTC of the ESP32 itself is not implemented too.

@beegee-tokyo
Copy link
Contributor

beegee-tokyo commented Dec 10, 2017

Too bad it didn't help.
Did you try to put the RTC reading/writing into a separate task and/or disable task switching while it is done?

Just out of interest, you defined

#define _cs 17 // goes to TFT CS
#define _dc 16 // goes to TFT DC
#define _mosi 23 // goes to TFT MOSI
#define _sclk 18 // goes to TFT SCK/CLK
#define _rst 5 // goes to TFT RESET

Default CS (SS) for VSPI is GPIO 5, but you chose GPIO 17, any specific reason for this?

@Manuauto
Copy link
Author

Manuauto commented Dec 10, 2017

Thanks for pointing that out. I actually noticed that too just after you posted your first answer. I swapped the pins around but unfortunately it did not help.

What do you mean by "putting * into a separate task"? Something with FreeRTOS?

@beegee-tokyo
Copy link
Contributor

If you look into my code ESP32-Weatherstation check light.cpp or temperature.cpp. The functions are a wraparound of Arduino for FreeRTOS tasks. I use timer triggered tasks to read out the sensors. You could use these to access the RTC separate from the main loop.
Or you can try to use

void vTaskExitCritical( portMUX_TYPE *mux );
void vTaskEnterCritical( portMUX_TYPE *mux );

around the functions that access the RTC.

@stickbreaker
Copy link
Contributor

@Manuauto I have a fork of arduino-esp32 at stickbreaker/arduino-esp32 that is a rewrite of the I2C subsection. You might try it and see if your I2C process work correctly. @me-no-dev is reviewing my code for inclusion into this main branch.

Chuck.

@Manuauto
Copy link
Author

@stickbreaker Thank you for the suggestion. I actually found out about this fork on another opened issue.
Unfortunately it did not work. It only gave me error messages in the Serial Monitor. The I2C RTC itself did not work. I just exttracted the archive into my \Arduino\hardware\espressif\esp32 folder (on Windows).
Was that correct?

@stickbreaker
Copy link
Contributor

@Manuauto yes, my fork is a dropin replacement for this branch.

My fork only changes a few files
\espressif\esp32\libraries\Wire*
\espressif\esp32\cores\esp32\esp32-hal-i2c.*
\espressif\esp32\cores\esp32\esp32-hal-log.h

If you copy these files over your existing arduino-esp32 installation you will be using my I2C revision.

Chuck.

@lonerzzz
Copy link
Contributor

@Manuauto Are you still having the issue?

@Manuauto
Copy link
Author

Currently I have decided not to implement a I2C RTC and instead to use a SPI RTC. Therefore I haven't tried further.
The last time I tried (which is now about 9 days ago), the issue was still there. Whether it still exists I do not know for sure. As I described in another post, I had issues with the I2C drop-in too.

@HollisTech
Copy link

@stickbreaker first, thanks for building the working version of arduino wire i2c for the esp32. Now, is there any hope this is going to get incorporated into the official repo? It seems to be in "pull request in review state" now for over a month.

Also even with your changes, until I moved my sensor processing into a single high-priority task and put the wifi into a separate low priority task I was still getting i2c timeouts, but at least they were recoverable.

@stickbreaker
Copy link
Contributor

@HollisTech the 'owner' of this repo @me-no-dev was working on merging it last month, but I haven't seen any posting or responses from him for 3+ weeks. So, don't know the what the current status is. My repo is just a step on the path toward SLAVE mode. Still working on it.

I haven't done any priority testing. I have been rumination about a 'driver model' that would use a separate task that uses queues to pass commands and data from 'apps' to a higher priority control process. But, I haven't need it yet.

Chuck.

@HollisTech
Copy link

my concern is that I'm using platformio and that really doesn't seem to support alternate branches very well (maybe it does, but I can't seem to get it to work.) I'm back to using the mainline repo, and it works as long as I have all the sensor io on one very high priority thread locked to a cpu and wifi off on a separate cpu at low priority, but that is very fragile and hackish and your approach just looks more robust. Anyway, thanks.

@stickbreaker
Copy link
Contributor

@HollisTech you can do a manual insert until @me-no-dev decides on how to transmorgifiy it.
The only files needed are:

libraries/Wire/src/Wire.h
libraries/Wire/src/Wire.cpp
cores/esp32/esp32-hal-i2c.h
cores/esp32/esp32-hal-i2c.cpp
cores/esp32/esp32-hal-log.h

Chuck

@HollisTech
Copy link

@stickbreaker yeah I know that but that doesn't work for me as I keep everything under CI and git, so manual mucking with common components is fine for figuring out what the problem is, but not for checking stuff in and having a build server build and test the output. Anyway - thanks. I've worked around the issues, and hopefully i2c will actually get fixed one day.

@krzychb
Copy link

krzychb commented Jan 14, 2018

I want to use an ILI9341 SPI Display and an I2C RTC Module (DS3231) in a project of mine.
These devices themselves work fine with no problems. Whenever I initialize the instance for the Display, the RTC Data seems to be corrupted or invalid.

I have noticed similar issue when driving ePaper display with SPI and reading BMP180 sensor over I2C in separate / concurrent tasks in the esp-idf environment. I was getting randomly some corrupted readings from the BMP180.

To quickly check if this is the issue of concurrent operation of SPI and I2C, I have added a semaphore to manage access to both resources, so only one of them may be active at any given moment of time.

The corrupted I2C readings from the BMP180 were gone with this workaround.

@Hexman64
Copy link

@stickbreaker please note that me and a bunch of people just got rid of our I2C problems on the esp32 by using the files you provided. I wonder how a product can be on the market that long with a major unfixed issue when there's a contributor like you who provides the necessary information on how to handle it.
Please don't give up on updating it when necessary as long as the 'official' libraries do not include a required fix. Thank you so much for sharing your ready-to-use work with us!!!

See the esp32 forum - only some of the people who found your working solution:
https://www.esp32.com/viewtopic.php?f=19&t=5094&start=30

@copercini
Copy link
Contributor

The I2C core was changed to @stickbreaker code officially after 13dcfe5 (thanks @stickbreaker), Let's close issues with old code and if have problems with the new code, open new issues =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants