MPR121 with HUZZAH32 : noise in cap sensor readings

Hello,

When running Adafruit's sketch to debug MPR121's "raw" data using cap.filteredData(i) & cap.baselineData(i), everything works just fine if using an Arduino UNO or an Arduino MEGA. When running it on a HUZZAH32, the filtered data keeps returning wild readings (65535, 32738, etc.) on several (not all, but almost never none) of the cap sensors. The HUZZAH32 is connected via USB to my laptop (same as the tests on the Arduinos). I2C ports on HUZZAH are 23 for SDA & 22 for SCL. I ran other sample programs (not involving MPR121) on the HUZZAH32 and it works fine (so the board is ok).

A brief sample of the monitor output from the 12 sensors´ filtered and base data looks like this:

Filt: 227 216 198 195 195 189 65535 205 65535 65535 65535 32738
Base: 224 216 196 192 192 188 212 1020 196 604 180 196
0x0
Filt: 65535 65535 197 195 65535 189 65535 205 65535 185 181 197
Base: 624 216 196 192 192 188 212 204 1020 184 180 196
0x0
Filt: 228 216 197 196 195 189 214 205 196 185 182 197
Base: 224 212 1020 192 1020 188 212 204 196 184 180 196
0x0

If I grab (i.e. touch) the USB cable feeding the HUZZAH32, all sensors go wild (it does not happen with the Arduinos), so there is clearly some issue with noise from the power line feeding the HUZZAH32. I tried with different USB cables with the same result.

Has anyone seen noise from the power line in the HUZZAH32 fed into the 12C channel? Or into the cap sensors of a MPR121?

Since I intend (eventually) to make this a wireless cap sensing solution (hence the need for a HUZZAH32), there won't be a USB cable. It will all be fed by a 1200mAh LiPO battery which may solve the noise problem from the power line. But, since there's is still a lot of coding ahead of this project, I'll need the USB tether.

Thinking it could be an speed compatibility issue (given the speed differences between Arduinos and HUZZAH32), I tested several clock speeds on the I2C channel (from 5k to 400k), changed crystal speed on the HUZZAH32 to 40MHz and 80MHZ, and added delays of up to 1 sec between readings, but got the same results (only slower, or faster).

Thanks in advance for any insights!

#include <Wire.h>
#include "Adafruit_MPR121.h"

#ifndef _BV
#define _BV(bit) (1 << (bit))
#endif

Adafruit_MPR121 cap1 = Adafruit_MPR121();

void setup() {
 Serial.begin(115200);
 Serial.println("MPR121");
  if (!cap1.begin(0x5A)) {Serial.println("5A Bad"); while (1); }
   else {Serial.println("5A Good"); }
   Wire.begin (23, 22, 4000);
}
 
void loop() {
  Serial.print("\t\t\t\t\t\t\t\t\t\t\t\t\t 0x"); Serial.println(cap1.touched(), HEX);
  Serial.print("Filt: ");
  for (uint8_t i=0; i<12; i++) {
    Serial.print(cap1.filteredData(i)); Serial.print("\t");
  }
  Serial.println();
  Serial.print("Base: ");
  for (uint8_t i=0; i<12; i++) {
    Serial.print(cap1.baselineData(i)); Serial.print("\t");
  }
  Serial.println();
  delay(1000);
}

This is basically a ESP32 processor.
https://www.adafruit.com/product/3405
This has a very different inside than the Uno or the Mega. I am assuming you are powering the MPR121 from 3V3 and not 5V.
If so, short of hacking the library I am not sure what you can do to make it work.

Thanks @Grumpy_Mike for your quick response. Indeed it's an ESP WROOM 32. According to Adafruit, it can run any Arduino base code installing the Expressif Arduino library (GitHub - espressif/arduino-esp32: Arduino core for the ESP32).

And your assumption is correct: I'm powering the MPR121 from 3V3. Although the same behavior is present when running the MPR121 from the USB (5V) supply (it has a built-in regulator and pullup resistors: Overview | Adafruit MPR121 12-Key Capacitive Touch Sensor Breakout Tutorial | Adafruit Learning System).

If I understood your comment, the I2C pins in the HUZZAH32 run logic at 3V3? (vs 5V in the MEGA). Should this make a difference? As I understand it, if it goes from 0V to 70% of VDD, the I2C bus will detect a signal. Is this correct?

I'm adding below a partial dump of the Arduino IDE debug for additional info.

Thanks!!

Filt: [  4196][I][esp32-hal-i2c.c:1156] i2cProcQueue(): Bus busy, reinit
227	216	197	196	195	190	214	205	196	185	181	196	
Base: 224	216	1020	192	192	1020	212	204	1020	[  4207][I][esp32-hal-i2c.c:1156] i2cProcQueue(): Bus busy, reinit
[  4207][W][esp32-hal-i2c.c:1437] i2cCheckLineState(): invalid state sda(23)=0, scl(22)=1
[  4214][D][esp32-hal-i2c.c:1445] i2cCheckLineState(): Recovered after 1 Cycles
1020	180	196	
													 0x0
Filt: 227	216	198	195	195	190	214	205	196	65500	182	197	
Base: 224	216	196	192	192	188	212	204	196	184	180	196	
													 0x0
Filt: 227	216	197	[  6288][D][esp32-hal-i2c.c:1371] i2cProcQueue():  Gross Timeout Dead start=0x185d, end=0x188f, =50, max=50 error=1
[  6288][E][esp32-hal-i2c.c:336] i2cDumpI2c(): i2c=0x3ffbdb68
[  6293][I][esp32-hal-i2c.c:337] i2cDumpI2c(): dev=0x60013000 date=0x16042000
[  6299][I][esp32-hal-i2c.c:339] i2cDumpI2c(): lock=0x3ffb90dc
[  6305][I][esp32-hal-i2c.c:341] i2cDumpI2c(): num=0
[  6310][I][esp32-hal-i2c.c:342] i2cDumpI2c(): mode=1
[  6314][I][esp32-hal-i2c.c:343] i2cDumpI2c(): stage=3
[  6319][I][esp32-hal-i2c.c:344] i2cDumpI2c(): error=1
[  6324][I][esp32-hal-i2c.c:345] i2cDumpI2c(): event=0x3ffb9164 bits=200
[  6331][I][esp32-hal-i2c.c:346] i2cDumpI2c(): intr_handle=0x3ffb9198
[  6337][I][esp32-hal-i2c.c:347] i2cDumpI2c(): dq=0x3ffb9278
[  6342][I][esp32-hal-i2c.c:348] i2cDumpI2c(): queueCount=2
[  6347][I][esp32-hal-i2c.c:349] i2cDumpI2c(): queuePos=1
[  6352][I][esp32-hal-i2c.c:350] i2cDumpI2c(): errorByteCnt=0
[  6358][I][esp32-hal-i2c.c:351] i2cDumpI2c(): errorQueue=2
[  6363][I][esp32-hal-i2c.c:352] i2cDumpI2c(): debugFlags=0x00000000
[  6369][I][esp32-hal-i2c.c:329] i2cDumpDqData(): Debug Buffer not Enabled
[  6376][I][esp32-hal-i2c.c:372] i2cDumpInts(): Debug Buffer not Enabled
65535	[  6393][I][esp32-hal-i2c.c:1156] i2cProcQueue(): Bus busy, reinit
195	190	65535	205	196	185	182	65535	
Base: 224	216	196	1020	[  6399][I][esp32-hal-i2c.c:1156] i2cProcQueue(): Bus busy, reinit
[  6400][W][esp32-hal-i2c.c:1437] i2cCheckLineState(): invalid state sda(23)=0, scl(22)=1
[  6408][D][esp32-hal-i2c.c:1445] i2cCheckLineState(): Recovered after 3 Cycles
608	188	212	204	196	184	180	196	
													 0x0
Filt: 227	216	197	196	195	65535	214	205	196	185	182	196	
Base: 224	216	196	192	192	1020	212	1020	196	1020	180	1020	
													 0x0
Filt: 227	216	197	196	195	190	214	205	196	185	182	197	
Base: 224	[  8490][D][esp32-hal-i2c.c:1371] i2cProcQueue():  Gross Timeout Dead start=0x20f7, end=0x2129, =50, max=50 error=1
[  8490][E][esp32-hal-i2c.c:336] i2cDumpI2c(): i2c=0x3ffbdb68
[  8494][I][esp32-hal-i2c.c:337] i2cDumpI2c(): dev=0x60013000 date=0x16042000
[  8501][I][esp32-hal-i2c.c:339] i2cDumpI2c(): lock=0x3ffb90dc
[  8507][I][esp32-hal-i2c.c:341] i2cDumpI2c(): num=0
[  8512][I][esp32-hal-i2c.c:342] i2cDumpI2c(): mode=1
[  8516][I][esp32-hal-i2c.c:343] i2cDumpI2c(): stage=3
[  8521][I][esp32-hal-i2c.c:344] i2cDumpI2c(): error=1
[  8526][I][esp32-hal-i2c.c:345] i2cDumpI2c(): event=0x3ffb9164 bits=200
[  8532][I][esp32-hal-i2c.c:346] i2cDumpI2c(): intr_handle=0x3ffb9198
[  8539][I][esp32-hal-i2c.c:347] i2cDumpI2c(): dq=0x3ffb9278
[  8544][I][esp32-hal-i2c.c:348] i2cDumpI2c(): queueCount=2
[  8549][I][esp32-hal-i2c.c:349] i2cDumpI2c(): queuePos=1
[  8554][I][esp32-hal-i2c.c:350] i2cDumpI2c(): errorByteCnt=-1
[  8560][I][esp32-hal-i2c.c:351] i2cDumpI2c(): errorQueue=0
[  8565][I][esp32-hal-i2c.c:352] i2cDumpI2c(): debugFlags=0x00000000
[  8571][I][esp32-hal-i2c.c:329] i2cDumpDqData(): Debug Buffer not Enabled
[  8578][I][esp32-hal-i2c.c:372] i2cDumpInts(): Debug Buffer not Enabled
1020	[  8595][I][esp32-hal-i2c.c:1156] i2cProcQueue(): Bus busy, reinit
608	192	192	188	212	204	196	184	180	196	
													 0x0
Filt: 227	216	197	196	195	190	214	205	65535	185	181	197	
Base: 224	216	196	192	192	188	212	612	196	184	180	196	
													 0x0
Filt: 227	216	197	196	195	190	214	204	196	185	182	197	
Base: 224	1020	[ 10622][I][esp32-hal-i2c.c:1156] i2cProcQueue(): Bus busy, reinit
[ 10623][W][esp32-hal-i2c.c:1437] i2cCheckLineState(): invalid state sda(23)=0, scl(22)=1
[ 10626][D][esp32-hal-i2c.c:1445] i2cCheckLineState(): Recovered after 9 Cycles
196	192	192	188	1020	204	608	184	1020	196	
													 0x0
Filt: 227	216	197	195	195	190	214	205	196	185	181	197	
Base: 224	216	196	192	192	188	212	204	196	184	180	196	

So you are running a breakout board with a MPR121 on it. That is a different matter. You said just an MPR121 so naturally I assumed that this was just a chip, because why on Earth should anyone need a board with it soldered on as it is a lot cheaper to use a chip. You can get them in a through hole mounting, not just the surface mount chip you have on that board.

A partly dump tells you nothing sorry. This is just the compiler output not a debug output.

I don’t read that as it being able to cope with any library written by Adafruit.

In fact my faith in the quality of Adafruit software has been dented recently as a library I wanted to use didn’t work correctly. The example code had commented out a line that clearly showed the error so they knew about it. When I raised a GitHub issue on this I was told it could be cured by updating the core code, they even posted an example they said worked with it but it didn’t. Then silence for two months now.

It is probably best if you ask Adafruit directly if there board is supported on their platform.

It has to do with Expessif's implementation of I2C for Arduino compatibility in their ESP32: ESP32-S2 I2C does not honor repeated-start (no stop) in API? · Issue #4729 · espressif/arduino-esp32 · GitHub.

I posted it here in the hopes that someone from Arduino would be interested in ensuring their compatibility with other boards

On the Arduino IDE, select Tools, Core Debug Level, Debug (or Verbose if preferred) and you'll get a debug output on the serial monitor for every loop in your sketch

Your are right that their technical support leaves a lot to be desired

Why should Arduino want to do this? They have to make a living and they sell hardware. the fact that other people are jumping on the band wagon and making profit from their hard work is irksome for them and I don't blame them.

Adafruit sell ESP32 based boards so this in in there own interest.

I

I would not come to that conclusion it is very vague and clutching at straws and makes little sense.

Yes.

No.

The I2C bus uses a passive pull down signal. If you power the MPR121 board, that board will have pull up resistors on it to the power rail. It is that signal going into a 3V3 system that overloads the processor, not that it is not going up high enough.

FIXED: So it was an instability in the Arduino I2C implementation of the ESP32. The fix can be found at Implement Thread-Safe I2C based on ESP-IDF API by me-no-dev · Pull Request #5683 · espressif/arduino-esp32 · GitHub

This PR is a complete refactoring of Wire Library and I2C HAL in order to use IDF instead of current Register manipulation approach. It implements Thread-safe Arduino Wire.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.