Skip to content
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

ESP32 issue, clock speed too fast #75

Open
lemio opened this issue Jul 26, 2017 · 17 comments
Open

ESP32 issue, clock speed too fast #75

lemio opened this issue Jul 26, 2017 · 17 comments

Comments

@lemio
Copy link
Contributor

lemio commented Jul 26, 2017

I found a problem with this (and some of the other HX711 libraries), it seems like the library is too fast for the HX711 if the clock speed of the MCU is higher.

It seems that the real speed is actually below the minimal values in the data sheet
image

This was the image before
image

And this after
image

I changed the shiftIn to be slower:

uint8_t Q2HX711::shiftInSlow(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
    uint8_t value = 0;
    uint8_t i;

    for(i = 0; i < 8; ++i) {
        digitalWrite(clockPin, HIGH);
        delayMicroseconds(1);
        if(bitOrder == LSBFIRST)
            value |= digitalRead(dataPin) << i;
        else
            value |= digitalRead(dataPin) << (7 - i);
        digitalWrite(clockPin, LOW);
        delayMicroseconds(1);
    }
    return value;
}

and changed the GAIN part of read:

for (int i = 0; i < GAIN; i++) {
    digitalWrite(CLOCK_PIN, HIGH);
    delayMicroseconds(1);
    digitalWrite(CLOCK_PIN, LOW);
    delayMicroseconds(1);
  }
@robinmarlow
Copy link

After having this library working perfectly on an ESP8266 I thought i could just slot in a ESP32 as a replacement.... I am getting regular nonsense readings.

Bizarrely the first reading and then every 60s are 829.52kg, measurements between these are a constant 3.05kg.

The (recalibrated) software and hardware are unchanged - this timing issue seems likely.

How do I try your fix? You don't say which files are patched.

@lemio
Copy link
Contributor Author

lemio commented Aug 17, 2017

Can you try my fork, it is still not super optimal implemented, but when ESP_H is defined it will change to a slower shiftIn function. In a better update it should look at the clock speed to make it future proof for other boards... https://github.com/lemio/HX711

@robinmarlow
Copy link

Thank you! this fixes my problem of fluctating readings. Had to re-determine my zero & calibration factor, but now readings are consistent. Thank you again!

@frankleonrose
Copy link

Thanks @lemio for figuring this out. I wish I understood your original graph better.

In case anyone is interested, I wanted to work through the numbers so I'm sharing them here.

The requirement of 0.2µs for each of clock high and low yields 0.4µs per clock cycle or 2.5MHz. Assuming 30 instructions for each digitalWrite call (estimated with https://godbolt.org/g/UDjENF), 60 total for a full cycle, if a processor runs 2.5MHz * 60 = 150M instructions per second or faster it will be too fast.

That's why a 160MHz ESP32 is just too fast. And if digitalWrite takes fewer instructions to run or the specification for 0.4us cycle time is higher tolerance than the silicon can handle, the threshold frequency (150MHz) could be even lower.

@lemio
Copy link
Contributor Author

lemio commented Aug 23, 2017

The experiment shown in the graphs is a barrel (for brewing beer) which is having a valve (so slowly losing weight) what you can see it that it is not correct shifting the bits, because of that reason it sometimes is right (when there should be a 0 and there is a 0, but sometimes is fails when there should be a 1 but there is still a zero.

My proposal is to change the Arduino ecosystem, so other libraries could also benefit from this change. Without losing speed when using the 'old' version of shiftIn and shiftOut:

See this issue:

https://github.com/arduino/Arduino/issues/6561

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val, unsigned long maxSpeed = 0);
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, unsigned long maxSpeed = 0);

We could use the constant value of the F_CPU to change the bahaviour of the shiftIn and shiftOut if the maximum communication speed is defined. In this way more libraries and hardware in the Arduino ecosystem can use this configuration and have a limited shiftIn or shiftOut speed.

#ifdef F_CPU
if(F_CPU > maxSpeed * some_constant){

}

@frankleonrose I could only use some help on the speed comparison part, because do you know the ratio of pure clock speed vs the speed of the shiftIn/shiftOut (communication speed). Than we can relatively easily do a proposal for implementing it into the core Arduino functions.

@lemio lemio changed the title ESP32 issue, clock speed to fast ESP32 issue, clock speed too fast Aug 25, 2017
@robmacl
Copy link

robmacl commented Sep 4, 2017

I seem to be running into this issue on teensy3.2 also, with 96 MHz clock. So not just an ESP32 issue. I was searching for whether anyone had anything to say about shiftin being too fast (in general), because I suspected there might be an issue, since I saw there was no delay in the code. And I got this link to the very HX711 library I was using.

@robmacl
Copy link

robmacl commented Sep 4, 2017

I pulled lemio's patch, and after defeating the ESP32 conditional, it is working for me on teensy3.2.

@geekspeed
Copy link

I believe a solution exists here: https://youtu.be/iywsJB-T-mU

Looks like setting the esp32 to 80mhz solves the issue nicely

@squix78
Copy link

squix78 commented Apr 21, 2018

Hi guys. I tried @lemio 's branch but I still have the problem. Andreas Spiess' solution linked by @geekspeed but then I my scale doesn't wake up from deep sleep anymore, so slower CPU frequency is currently not an option. Is the slowed down shiftIn function still working for you guys? Or might this have been broken by a later SDK build? Did anybody ever hook up a logic analyzer to the hx711 to see what's going on? Any help appreciated...

@squix78
Copy link

squix78 commented Apr 22, 2018

So I finally had time to attach the logic analyzer. You'll see a updated shiftIn function with a delay of 10us between the digitalWrite's for the clock. The clock looks perfect to me, but the presented data seems to be a bit odd, especially that spike that disappears too quickly. Does anybody have an idea? Or is this just a sampling problem?
screen shot 2018-04-22 at 07 47 40
screen shot 2018-04-22 at 07 51 07
screen shot 2018-04-22 at 07 57 55
screen shot 2018-04-22 at 08 04 11

@nae9
Copy link

nae9 commented May 4, 2018

Hello Mans!
I have ESP32 dduino and HX711. I send 26 pulses to CLK pin but It seemed that at some times HX711 recieves 25 or 27 pulses! And some times i have point from wrong channel and wrong gain :).
My collegue have lecroy HDO6000-MS, tomorrow i will see all... Oops! - only at monday.

@robmacl
Copy link

robmacl commented May 4, 2018

This is an obvious point, but even if reducing the clock speed helps, that doesn't rule out some stupid problem. I found that the HX711 board I got on ebay had a really dumb problem.
ebay link Unless you added it externally there was no connection between two of the grounds. IIRC, I had to install a jumper from the E- (excitation -) to the GND input. Because the actual chip ground pin (the supply and the reference for digial I/O) was connected to the E- net. If your board has this problem then there will be no continuity between pin 5 on the chip and the board's ground (power -) connection.

FWIW, if you look at the HX711 data sheet, the supply situation may be slightly confusing because it has an internal regulator on the power supply that uses an external pass transistor. And also the only ground pin is labelled AGND, which might lead you to think it didn't need to be connected to the digital ground.

@squix78
Copy link

squix78 commented May 5, 2018

I could solve the issue without slowing down the ESP32. Here is my read() method. It does not allow to read with different gain or from the B port but I don't have anymore glitches:

long HX711::read() {
  int buffer;
  buffer = 0;

  while (digitalRead(DOUT) == HIGH) {
    yield();
  }
  delayMicroseconds(1);

  for (uint8_t i = 0; i < 24; i++)
  {
      digitalWrite(PD_SCK, HIGH);
      delayMicroseconds(1);
      digitalWrite(PD_SCK, LOW);
      delayMicroseconds(1);
      buffer = buffer << 1 ;

      if (digitalRead(DOUT) == HIGH)
      {
          buffer ++;
      } 


  }

// CHANNEL A, gain 128
  digitalWrite(PD_SCK, HIGH);
  digitalWrite(PD_SCK, LOW);


  buffer = buffer ^ 0x800000;

  return static_cast<long>(buffer);
}

I think the main difference is to first send the complete pulse and then read the DOUT signal. This way the HX711 has more time to produce the signal...

@nae9
Copy link

nae9 commented May 8, 2018

Lecroy showes no short glitches in CLOCK from ESP32. It seemed that some times ESP interrupt CLOCK sequency and do something else (may be WiFi maintains), then return to plot CLOCK. And if clk sequensy more 50us then glitch appears. (HX711 with GND to E- shortage)
img_20180508_141403

img_20180508_150646

@nae9
Copy link

nae9 commented May 14, 2018

I disable interrupts when CLOCKing:

    // in HX711.cpp file...
    long HX711::read() {
// wait for the chip to become ready
while (!is_ready()) {
	// Will do nothing on Arduino but prevent resets of ESP8266 (Watchdog Issue)
	yield();
}

unsigned long value = 0;
uint8_t data[3] = { 0 };
uint8_t filler = 0x00;

portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&mux); // ----------------------- "interrupt OFF"

// pulse the clock pin 24 times to read the data
data[2] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
data[1] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
data[0] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);

// set the channel and the gain factor for the next reading using the clock pin
for (unsigned int i = 0; i < GAIN; i++) {
	digitalWrite(PD_SCK, HIGH);
	#ifdef ESP_H
	delayMicroseconds(1);
	#endif
	digitalWrite(PD_SCK, LOW);
	#ifdef ESP_H
	delayMicroseconds(1);
	#endif
}

portEXIT_CRITICAL(&mux); //----------------------- "interrupt ON"

// Replicate the most significant bit to pad out a 32-bit signed integer
if (data[2] & 0x80) {
	filler = 0xFF;
} else {
	filler = 0x00;
}

// Construct a 32-bit signed integer
value = ( static_cast<unsigned long>(filler) << 24
		| static_cast<unsigned long>(data[2]) << 16
		| static_cast<unsigned long>(data[1]) << 8
		| static_cast<unsigned long>(data[0]) );

return static_cast<long>(value);}

CLOCK stable now, no glitches by 48 hours period yet.

jjxie added a commit to jjxie/ARTangibleVisualization that referenced this issue Jul 3, 2018
It is said from a post that the ESP32 is too fast for HX711, thus will output wierd data. After slow down the CPU, althoug the board processes much slower, but the data is much more accurate and stable. The resources: bogde/HX711#75
@amotl
Copy link
Contributor

amotl commented Feb 17, 2019

Dear @lemio, @robmacl and @nae9,

we just pushed some amendments [1] to this popular library where we rebundled some pieces which have been loosely floating around here. While being at it, we also cherry-picked your valuable contributions and suggestions which not have been merged yet, thanks again. For more details, please follow the issue referenced above.

As we actually don't have any hardware on our workbench, we will be happy to hear about successful reports from the community running this on a real iron, actually on as much as possible things supported by the Arduino framework. Maybe you can afford some minutes to check whether the status quo works as expected if you still have a MCU and a HX711 breakout around?

We will appreciate your feedback, thanks already.

With kind regards,
Andreas.

[1] https://github.com/hiveeyes/HX711/tree/spring-cleaning

@bdureau
Copy link

bdureau commented May 2, 2024

I got It to work with ESPS32 however I never managed to get more that 8 reading per second. Has anybody managed to get it working with 80 measure per second? I use the same HX711 module with other Arduino board an I can do 80 measures per second

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

9 participants