-
Notifications
You must be signed in to change notification settings - Fork 7.6k
i2C problems #1071
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
Comments
@dnienhis try substituting my version of the I2C subsytem. just grab my release 0.1.2 at stickbreaker/arduino-esp32 release 0.1.2 The current main stream esp32 library is unreliable my version works, but there are issues with merging it. Chuck. |
Thanks Chuck - I updated with your files and still get nothing back from the DS1307. Checked GPIO21 & GPIO22 with scope - no signal on either pin. Then went easter egging with scope - found what looks like might be the SCL (and i'm speculating) on the GPIO1 pin - that's the only pin i see any changes on? Also, compiled the i2C_Scanner example you included and it found no devices (mine is at 0x68). Never Mind the 'no signal on either pin' i had a couple wires come out of the prototype board - signals still there but DS1307 still not responding correctly :( |
I just downloaded a fresh copy of everything and all appears to be fine now. Thx! |
Thank you Chuck! For the very first time, since I bought the esp32, I have been able to reliably read the I2C bus - over longer timespans - without it hanging. Your work ist truely appreciated. Using: arduino-esp32-stickbreaker-V0.2.0.zip Now I can give this thing a new chance - was about to throw it in the garbage. |
@68gt500 good car, but i lusted after a Mach 1 Now if i can just get Slave and Multi-master. Chuck |
Hello Chuck,
thanks, we are a Ford crazed family..
I actually do own a 68 GT500, my son in law has a 69 Mach 1.
Keep up the good work!
Greetings
Michael
Von: "chuck todd" <[email protected]>
An: "espressif/arduino-esp32" <[email protected]>
Kopie: "68gt500" <[email protected]>, "Mention"
<[email protected]>
Datum: 07.04.2018 09:49
Betreff: Re: [espressif/arduino-esp32] i2C problems (#1071)
@68gt500 good car, but i lusted after a Mach 1
Now if i can just get Slave and Multi-master.
Chuck
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
@DeanGreenhough yes, just replace the existing files with the ones from the zip archive. esp* in to cores/esp32/ Chuck. |
Hi Chuck I woke up at 4 am, just to check, thank you so much for your work, this has caused me weeks of issues and has made my weekend, month maybe even year!!!! Bless you Chuck...Big Thumbs Up |
Chuck Just to confirm, the issue is with the esp core library?, I assume this will get sorted out in development? As this has caused me so much pain, thought maybe I should at least try to have a basic understanding of why there is an issue. regards Dean |
@DeanGreenhough the Main branch i2c hardware abstraction layer(HAL) is based on a polling model. It tries to control the hardware by reading status bits in a tight loop, but, the esp32 environment is a multi process, interrupt driven RTOS. WiFi, Serial, Timer ... or some other hi priority task "interrupts" this tight loop. This interruption results in missing a status change. The i2c HAL will only work reliably as a very simple sketch. My HAL is designed to use the hardwares capabilities instead of work around them. For more info read the Wiki in my fork. Chuck. |
Chuck Thank you very much for your detailed and patient replies, as instructed I will head over to WiKi. Many thanks for enlightening me on an almost impossible task. Very grateful and still chuckling at the stability over 5000 loops, no errors. |
Thanks for your work Chuck I had weird issues with I2C and no clues what problem I was facing and then your code fixed everything (arduino-esp32-stickbreaker-V0.2.0.zip on PlateformIO). |
Hi everybody, I was facing several problems using I2C until I found the @stickbreaker branch, thank you very much!!! Now I can debug why my I2C code is not working with my sensor. Any idea when espressif will add this bugfix to their main branch? |
There is a staging branch in this repo stickbreaker-i2c. So, work is progressing. Chuck. |
Many thanks for this "github.com/stickbreaker/arduino-esp32" (latest v24May18) software - it fixed my i2c hanging issue perfectly! FYI. I was using a "NodeMCU-32S" with Arduino-IDE and the latest "github.com/espressif/arduino-esp32" software. I was having an issue with an i2c LED 8x8Matrix consistently hanging the i2c bus every 6 hours or so (requiring an "ESP.restart();" to recover from). Your above i2c software has fixed this (1 week running now without any hangs - yay!) |
@Rob58329 You're welcome. I would recommend you try the staging branch of the official repo. Instead of my repo. espressif-arduino/tree/stickbreaker-i2c We need a lot of testing before it is moved into the main branch. So far there have not been any issues found, but me-no-dev is being caucus before it replaces the existing i2c subsystem. Chuck. |
Thank you very much Stickbreaker. I am completely new in this fascinating field. My project has scaled from Arduino Uno to ESP32, going through Arduino Mega and ESP8266. I almost went crazy looking for the reason why my DS1307 and my keypad (with PCF8574) stopped working well with the ESP32 if they worked perfectly with the previous ones. I believe that today I will sleep calmly. |
@stickbreaker thank you for the library but am still having a bit of an issue. am trying to using the esp32 with accelorometer and gyroscope module (gy 512). |
@hazee007 open a new issue, post your code. I'll have to see your code before I can advise. There are no delays encoded in the drive, But, the i2c slave device can stretch SCL to pause communications. I use it to animate a 128x64 oled display at 50frames/sec. So it is pretty fast! Chuck. |
am using the acceleormeter gyroscope module for step count... base on the movement of the sensor. it works well on both ardunio and esp8266 as long as theres not delay within the loop. but with esp 32 it not counting the steps. Heres my code below.
#include "Wire.h"#include "SPI.h"#include "SD.h"
#define MPU6050_ACCEL_XOUT_H 0x3B // R #define MPU6050_PWR_MGMT_1 0x6B // R/W#define MPU6050_PWR_MGMT_2 0x6C // R/W#define MPU6050_WHO_AM_I 0x75 // R
#define MPU6050_I2C_ADDRESS 0x68typedef union accel_t_gyro_union{ struct { uint8_t x_accel_h; uint8_t x_accel_l; uint8_t y_accel_h; uint8_t y_accel_l; uint8_t z_accel_h; uint8_t z_accel_l; uint8_t t_h; uint8_t t_l; uint8_t x_gyro_h; uint8_t x_gyro_l; uint8_t y_gyro_h; uint8_t y_gyro_l; uint8_t z_gyro_h; uint8_t z_gyro_l; } reg; struct { int16_t x_accel; int16_t y_accel; int16_t z_accel; int16_t temperature; int16_t x_gyro; int16_t y_gyro; int16_t z_gyro; } value;};
// Use the following global variables and access functions to help store the overall// rotation angle of the sensorunsigned long last_read_time;float last_x_angle; // These are the filtered anglesfloat last_y_angle;float last_z_angle; float last_gyro_x_angle; // Store the gyro angles to compare driftfloat last_gyro_y_angle;float last_gyro_z_angle;
void set_last_read_angle_data(unsigned long time, float x, float y, float z, float x_gyro, float y_gyro, float z_gyro) { last_read_time = time; last_x_angle = x; last_y_angle = y; last_z_angle = z; last_gyro_x_angle = x_gyro; last_gyro_y_angle = y_gyro; last_gyro_z_angle = z_gyro;}
inline unsigned long get_last_time() {return last_read_time;}inline float get_last_x_angle() {return last_x_angle;}inline float get_last_y_angle() {return last_y_angle;}inline float get_last_z_angle() {return last_z_angle;}inline float get_last_gyro_x_angle() {return last_gyro_x_angle;}inline float get_last_gyro_y_angle() {return last_gyro_y_angle;}inline float get_last_gyro_z_angle() {return last_gyro_z_angle;}
// Use the following global variables and access functions// to calibrate the acceleration sensorfloat base_x_accel;float base_y_accel;float base_z_accel;
float base_x_gyro;float base_y_gyro;float base_z_gyro;
int read_gyro_accel_vals(uint8_t* accel_t_gyro_ptr) { accel_t_gyro_union* accel_t_gyro = (accel_t_gyro_union *) accel_t_gyro_ptr; int error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) accel_t_gyro, sizeof(*accel_t_gyro)); uint8_t swap; #define SWAP(x,y) swap = x; x = y; y = swap
SWAP ((*accel_t_gyro).reg.x_accel_h, (*accel_t_gyro).reg.x_accel_l); SWAP ((*accel_t_gyro).reg.y_accel_h, (*accel_t_gyro).reg.y_accel_l); SWAP ((*accel_t_gyro).reg.z_accel_h, (*accel_t_gyro).reg.z_accel_l); SWAP ((*accel_t_gyro).reg.t_h, (*accel_t_gyro).reg.t_l); SWAP ((*accel_t_gyro).reg.x_gyro_h, (*accel_t_gyro).reg.x_gyro_l); SWAP ((*accel_t_gyro).reg.y_gyro_h, (*accel_t_gyro).reg.y_gyro_l); SWAP ((*accel_t_gyro).reg.z_gyro_h, (*accel_t_gyro).reg.z_gyro_l);
return error;}
// The sensor should be motionless on a horizontal surface// while calibration is happeningvoid calibrate_sensors() { int num_readings = 10; float x_accel = 0; float y_accel = 0; float z_accel = 0; float x_gyro = 0; float y_gyro = 0; float z_gyro = 0; accel_t_gyro_union accel_t_gyro; //Serial.println("Starting Calibration");
// Discard the first set of values read from the IMU read_gyro_accel_vals((uint8_t *) &accel_t_gyro); // Read and average the raw values from the IMU for (int i = 0; i < num_readings; i++) { read_gyro_accel_vals((uint8_t *) &accel_t_gyro); x_accel += accel_t_gyro.value.x_accel; y_accel += accel_t_gyro.value.y_accel; z_accel += accel_t_gyro.value.z_accel; x_gyro += accel_t_gyro.value.x_gyro; y_gyro += accel_t_gyro.value.y_gyro; z_gyro += accel_t_gyro.value.z_gyro; delay(100); } x_accel /= num_readings; y_accel /= num_readings; z_accel /= num_readings; x_gyro /= num_readings; y_gyro /= num_readings; z_gyro /= num_readings; // Store the raw calibration values globally base_x_accel = x_accel; base_y_accel = y_accel; base_z_accel = z_accel; base_x_gyro = x_gyro; base_y_gyro = y_gyro; base_z_gyro = z_gyro; //Serial.println("Finishing Calibration");}
//const int chipSelect = 4;void setup(){ int error; uint8_t c;
Serial.begin(9600); // Initialize the 'Wire' class for the I2C-bus. Wire.begin();
// Serial.print("Initializing SD card...");//// // see if the card is present and can be initialized:// if (!SD.begin(chipSelect)) {// Serial.println("Card failed, or not present");// // don't do anything more:// return;// }// Serial.println("card initialized.");
error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1); error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1);
// Clear the 'sleep' bit to start the sensor. MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0); //Initialize the angles calibrate_sensors(); set_last_read_angle_data(millis(), 0, 0, 0, 0, 0, 0);}
float x,y,z;int count=0,prev=0;int threshold=3;
void loop(){ int error; double dT; accel_t_gyro_union accel_t_gyro;// SaveData(); // Read the raw values. error = read_gyro_accel_vals((uint8_t*) &accel_t_gyro); // Get the time of reading for rotation computations unsigned long t_now = millis();
// Convert gyro values to degrees/sec float FS_SEL = 131; float gyro_x = (accel_t_gyro.value.x_gyro - base_x_gyro)/FS_SEL; float gyro_y = (accel_t_gyro.value.y_gyro - base_y_gyro)/FS_SEL; float gyro_z = (accel_t_gyro.value.z_gyro - base_z_gyro)/FS_SEL; // Get raw acceleration values //float G_CONVERT = 16384; float accel_x = accel_t_gyro.value.x_accel; float accel_y = accel_t_gyro.value.y_accel; float accel_z = accel_t_gyro.value.z_accel; // Get angle values from accelerometer float RADIANS_TO_DEGREES = 180/3.14159; //float accel_vector_length = sqrt(pow(accel_x,2) + pow(accel_y,2) + pow(accel_z,2)); float accel_angle_y = atan(-1*accel_x/sqrt(pow(accel_y,2) + pow(accel_z,2)))*RADIANS_TO_DEGREES; float accel_angle_x = atan(accel_y/sqrt(pow(accel_x,2) + pow(accel_z,2)))*RADIANS_TO_DEGREES; float accel_angle_z = atan(sqrt(pow(accel_x,2) + pow(accel_y,2))/accel_z)*RADIANS_TO_DEGREES;; //float accel_angle_z = 0; // Compute the (filtered) gyro angles float dt =(t_now - get_last_time())/1000.0; float gyro_angle_x = gyro_x*dt + get_last_x_angle(); float gyro_angle_y = gyro_y*dt + get_last_y_angle(); float gyro_angle_z = gyro_z*dt + get_last_z_angle(); // Compute the drifting gyro angles float unfiltered_gyro_angle_x = gyro_x*dt + get_last_gyro_x_angle(); float unfiltered_gyro_angle_y = gyro_y*dt + get_last_gyro_y_angle(); float unfiltered_gyro_angle_z = gyro_z*dt + get_last_gyro_z_angle(); // Apply the complementary filter to figure out the change in angle - choice of alpha is // estimated now. Alpha depends on the sampling rate... float alpha = 0.96; float angle_x = alpha*gyro_angle_x + (1.0 - alpha)*accel_angle_x; float angle_y = alpha*gyro_angle_y + (1.0 - alpha)*accel_angle_y; float angle_z = gyro_angle_z; //Accelerometer doesn't give z-angle // Update the saved data with the latest values set_last_read_angle_data(t_now, angle_x, angle_y, angle_z, unfiltered_gyro_angle_x, unfiltered_gyro_angle_y, unfiltered_gyro_angle_z);
//Finding the magnitude of acceleration from the combined data from gyroscope and accelerometer. int mag=sqrt(pow(x-angle_x,2)+pow(y-angle_y,2)+pow(z-angle_z,2)); //If the magnitude is greater than threshold and the previous magnitude is lesser than threshold value increase count. if(mag>=threshold && prev<threshold) { count+=1; Serial.print("steps= "); Serial.println(count); }
prev = mag; x=angle_x; y=angle_y; z=angle_z; // Delay so we don't swamp the serial port delay(100); //Serial.write(10);}int MPU6050_read(int start, uint8_t *buffer, int size){ int i, n, error;
Wire.beginTransmission(MPU6050_I2C_ADDRESS); n = Wire.write(start); if (n != 1) return (-10);
n = Wire.endTransmission(false); // hold the I2C-bus if (n != 0) return (n);
// Third parameter is true: relase I2C-bus after data is read. Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true); i = 0; while(Wire.available() && i<size) { buffer[i++]=Wire.read(); } if ( i != size) return (-11);
return (0); // return : no error}
int MPU6050_write(int start, const uint8_t *pData, int size){ int n, error;
Wire.beginTransmission(MPU6050_I2C_ADDRESS); n = Wire.write(start); // write the start address if (n != 1) return (-20);
n = Wire.write(pData, size); // write data bytes if (n != size) return (-21);
error = Wire.endTransmission(true); // release the I2C-bus if (error != 0) return (error);
return (0); // return : no error}
int MPU6050_write_reg(int reg, uint8_t data){ int error;
error = MPU6050_write(reg, &data, 1);
return (error);}
//void SaveData() {// // open the file. note that only one file can be open at a time,// // so you have to close this one before opening another.// File dataFile = SD.open("step.txt", FILE_WRITE);//// // if the file is available, write to it:// if (dataFile) {// dataFile.println();// dataFile.print("steps= ");// dataFile.println(count); // dataFile.close();// }// // if the file isn't open, pop up an error:// else {// Serial.println("error opening datalog.txt");// }// //} any suggestions will be helpful
regards.Azeez.
On Wednesday, November 28, 2018, 5:09:40 PM GMT+4, chuck todd <[email protected]> wrote:
@hazee007 open a new issue, post your code. I'll have to see your code before I can advise.
There are no delays encoded in the drive, But, the i2c slave device can stretch SCL to pause communications.
I use it to animate a 128x64 oled display at 50frames/sec. So it is pretty fast!
Chuck.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
|
am sorry but can u plz give mi an idea what i can do tried, removing the wire.endTransmission(false); but still having the same issue.
Thank you.
On Wednesday, November 28, 2018, 7:04:23 PM GMT+4, chuck todd <[email protected]> wrote:
Wire.endTransmission(false); will return 7 to indicate ReSTART is queued until a STOP is encountered.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Open a new issue, your problem has nothing to do with this issue. Post your current code in the new issue using "markup" commands. The "markup" commands cause github to render the code in a readable format. Make it easier for me to help you. |
Sorry was sending from my mail just saw this now, heres the code. #define MPU6050_ACCEL_XOUT_H 0x3B // R #define MPU6050_I2C_ADDRESS 0x68 // Use the following global variables and access functions to help store the overall void set_last_read_angle_data(unsigned long time, float x, float y, float z, float x_gyro, float y_gyro, float z_gyro) { inline unsigned long get_last_time() {return last_read_time;} // Use the following global variables and access functions float base_x_gyro; int read_gyro_accel_vals(uint8_t* accel_t_gyro_ptr) { accel_t_gyro_union* accel_t_gyro = (accel_t_gyro_union *) accel_t_gyro_ptr; int error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) accel_t_gyro, sizeof(*accel_t_gyro)); uint8_t swap; SWAP ((*accel_t_gyro).reg.x_accel_h, (*accel_t_gyro).reg.x_accel_l); return error; // The sensor should be motionless on a horizontal surface //Serial.println("Starting Calibration"); // Discard the first set of values read from the IMU // Read and average the raw values from the IMU // Store the raw calibration values globally //Serial.println("Finishing Calibration"); //const int chipSelect = 4; Serial.begin(9600); error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1); error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1); // Clear the 'sleep' bit to start the sensor. //Initialize the angles float x,y,z; void loop() // Read the raw values. // Get the time of reading for rotation computations // Convert gyro values to degrees/sec // Get raw acceleration values // Get angle values from accelerometer float accel_angle_z = atan(sqrt(pow(accel_x,2) + pow(accel_y,2))/accel_z)*RADIANS_TO_DEGREES;; // Compute the (filtered) gyro angles // Compute the drifting gyro angles // Apply the complementary filter to figure out the change in angle - choice of alpha is // Update the saved data with the latest values //Finding the magnitude of acceleration from the combined data from gyroscope and accelerometer. //If the magnitude is greater than threshold and the previous magnitude is lesser than threshold value increase count. prev = mag; // Delay so we don't swamp the serial port Wire.beginTransmission(MPU6050_I2C_ADDRESS); n = Wire.endTransmission(false); // hold the I2C-bus // Third parameter is true: relase I2C-bus after data is read. return (0); // return : no error int MPU6050_write(int start, const uint8_t *pData, int size) Wire.beginTransmission(MPU6050_I2C_ADDRESS); n = Wire.write(pData, size); // write data bytes error = Wire.endTransmission(true); // release the I2C-bus return (0); // return : no error int MPU6050_write_reg(int reg, uint8_t data) error = MPU6050_write(reg, &data, 1); return (error); ` |
Please fill the info fields, it helps to get you faster support ;)
If you have a Guru Meditation Error, please decode it:
https://github.com/me-no-dev/EspExceptionDecoder
----------------------------- Remove above -----------------------------
Hardware:
Board: Espressif ESP32 ESP32-DEVKITC
Core Installation/update date: 25 Jan 18
IDE name: Arduino IDE 1.8.5 - Windows 10
Flash Frequency: 80 Mhz
Upload Speed: 921600
Description:
Trying to read time from the Adafruit DS1307 Board (https://www.adafruit.com/product/3296) - completely functional with ESP8266 & Arduino UNO over i2C - unable to read from ESP32. This is the test/demo code supplied by Adafruit - also using their library - the only thing I changed was adding and removing the #include <WiFi.h> when compiling for ESP32.
On the ESP32 I connected the i2C signals as follows:
SCL - GPIO21
SDA - GPIO22
(the connections didn't match up with what i'd read online - i found these via Oscilliscope & trial & error while running demo code below).
I'm attaching Oscilliscope captures from each of the three test scenarios.
This is my first time to post so please 'be gentle' LOL !
Arduino UNO





ESP32 Dev
ESP32 Dev
ESP32 Dev
ESP-8266
Sketch:
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//#include <WiFi.h>
#include <Wire.h>
#include "RTClib.h"
#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
#define Serial SerialUSB
#endif
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup () {
#ifndef ESP8266
while (!Serial); // for Leonardo/Micro/Zero
#endif
Serial.begin(9600);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(DATE), F(TIME)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
}
void loop () {
DateTime now = rtc.now();
Serial.println();
}
Debug Messages:
The text was updated successfully, but these errors were encountered: