Conflict with Teensy 3.X and HX711 Libary, I think related to ShiftIn function

Status
Not open for further replies.

Tomek

Well-known member
Hello, I've been on an epic saga today learning about things I wish I didn't have to understand ;), and for the most part don't have to due to the grace and glory of those who make libraries and make embedded programming nifty things with the teensy "easy."

:)

But here's the deal, I think I have traced an issue I have using the Sparkfun HX711 loadcell reader on my Teensy 3.5. The same breakout board will give good values when I compile my test code for an UNO, and bad numbers when I compile for a Teensy. I think there's a function used that works differently on the Teensy than on the AVR.

HX711 gives me a 24-bit number in a simple two-wire protocol, and most libraries split that into 3 8-bits that get recombined into a padded 32-bit.

At first I chased what I saw to be the usual issues, doubles being actually-doubles with teensy, and people writing arduino libraries that aren't very explicitly on what an Int is, for example. Then I chased the code that combined the 3 8-bits into a padded 32-bit, thinking they were working differently due to [not really sure what reason, but I understand teensy can shift further than some processors in a single step]

But then I got to the point that I saw that the 3 8-bits that the Teensy was reading from the DOUT of the HX711 were not apparently the correct values.

I posted an issue to the library, here: https://github.com/bogde/HX711/issues/84

The .cpp file has a "read" function and it takes the reading from the HX711 using the following excerpt:
Code:
data[2] = shiftIn(DOUT, PD_SCK, MSBFIRST);
	data[1] = shiftIn(DOUT, PD_SCK, MSBFIRST);
	data[0] = shiftIn(DOUT, PD_SCK, MSBFIRST);

It seems shiftIn doesn't cause a compiling error on the Teensy, but it doesn't work the same as on the UNO...

Is this a really obvious issue that someone else can illuminate for me?
In the github issue I posted my 'solution' which was mashing together code from a raspberry pi HX711 library under the assumption the formatting would be more native to the Teensy. I have not fully tested it, but it seems to work. I have not yet understand the full context to the issue, and am eager to settle this more concretely.

If I have not posed a sensible question, I apologize, this realm of programming is far from whatever limited area I am comfortable with. I will be reviewing bitwise operations and all the relevant functions over the course of the next day, I just am about 16-hours into this saga of learning why the Teensy wasn't working with code that worked for the Arduino, and I am hopeful that my issues are relevant to other teensy users.

I will update this post if I get to the bottom of everything before anyone has a chance to explain.

But any help or pointers until then, will certainly be appreciated. :)!
 
As a first easy test, try lowering the speed in Tools > CPU Speed. 24 MHz is the slowest where USB still works.

Before we dig into the deeper details, do this test to see if the problem is simply that Teensy is running so much faster than Uno.
 
Slowing down to 24MHz with the original HX711 library doesn't work (same bad values.)

I am flustered that this morning I couldn't get the code last night to replicate "good" results. So my "fix" from the raspberry pi library is maybe not the answer...

I will also test at 120MHz just using some delayMicros(100) to slow down the HX711 library and do another check over my hardware. I have tried different boards. There are more things I could try though, including moving to 5V tolerant pins of the Teensy 3.5, and changing the HX711 to use all 5V logic (right now I have Vdd at 3.3V and Vcc at 5V, per the sparkfun board specs it should work fine.)


:S I am very much doubting what I thought happened last night when I 'got' the library to work. Maybe I made a mistake in what I uploaded, since I have several copies of the library now floating around as I modified a few of them. Or maybe I was just exhausted from obsessing over this issue for so many hours :S. I am sure if I knew more it would not seem as daunting of an issue.
 
even 24 mhz may be too fast..

try this slower code:
(as replacement for shiftIn)

Code:
uint8_t my_shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin)
{
        uint8_t mask, value=0;
        for (mask=0x80; mask; mask >>= 1) {
                digitalWrite(clockPin, HIGH);
                delayMicroseconds(1);
                if (digitalRead(dataPin)) value |= mask;
                digitalWrite(clockPin, LOW);
                delayMicroseconds(1);
        }
        return value;
}
 
This looks great! I tried it, and messed around with a few values.

I'm going to look into my hardware now more intensely. I'm sorry I thought I had the hardware side fully in control but I'm now doubting what I've seen. Although I used to see different values coming from the Teensy, I am now *only* seeing 11111111111111111111111111111s, which is insanely suspicious. Thanks for bearing with, will report back.

I still appreciated the last function suggestion. Glad to have been able to try it / it helps me understand better what is going on overall with ShiftIn.

even 24 mhz may be too fast..

try this slower code:
(as replacement for shiftIn)

Code:
uint8_t my_shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin)
{
        uint8_t mask, value=0;
        for (mask=0x80; mask; mask >>= 1) {
                digitalWrite(clockPin, HIGH);
                delayMicroseconds(1);
                if (digitalRead(dataPin)) value |= mask;
                digitalWrite(clockPin, LOW);
                delayMicroseconds(1);
        }
        return value;
}
 
Hey!

I am back to getting good values. I have some things to look into. There was a damaged wire that may have made Vdd disconnected for moments. A5 and A4 pins seem dead now (my DOUT and SCK.)

I'm going to try and backtrack to understand what went wrong. I suspect either it was *always* a hardware issue, or I had some real issues and then a hardware issue as I moved the board around a bunch.

I will try the old code that didn't work later as I don't think the hardware issue that I had much of today was always an issue. I also have not fully tested the weights to confirm that it's working now.

Can't do it tonight because a friend from out of town is visiting. Hopefully in the next couple days.
 
UPDATE:

Original HX711 library code does not work compiled at 120Mhz or 24Mhz on the Teensy.

Frank B, your code works though! Compiled at 120Mhz or 24Mhz. :)!

I am a little confused why at 24Mhz teensy would be meaningfully faster than the 20Mhz arduino in this situation, so I don't totally know what's up. I also had a report on the github issue that the original code works for them on a Due, which is presumably faster than a 24Mhz compiled Teensy.

The only changes my code has thanks to Frank B:
Code:
	// pulse the clock pin 24 times to read the data
	/*data[2] = shiftIn(DOUT, PD_SCK, MSBFIRST);
	data[1] = shiftIn(DOUT, PD_SCK, MSBFIRST);
	data[0] = shiftIn(DOUT, PD_SCK, MSBFIRST);*/
	data[2] = my_shiftIn_msbFirst(DOUT,PD_SCK);
	data[1] = my_shiftIn_msbFirst(DOUT,PD_SCK);
	data[0] = my_shiftIn_msbFirst(DOUT,PD_SCK);

And
Code:
[uint8_t HX711::my_shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin){
        uint8_t mask, value=0;
        for (mask=0x80; mask; mask >>= 1) {
                digitalWrite(clockPin, HIGH);
                delayMicroseconds(1);
                if (digitalRead(dataPin)) value |= mask;
                digitalWrite(clockPin, LOW);
                delayMicroseconds(1);
        }
        return value;
}

As well as the required protofunctions in the .cpp and .h


What complicated this is that partway through all the debugging I damaged my board and killed an HX711 due to disconnected the Vdd a bunch (and killed the corresponding analog pins on the teensy that I was hooked up to.) So I basically had one night at midnight in which I was thinking "all right! It's fixed! Woooohh!" then the next morning I was thinking "wait shit, am I losing it? It's not working anymore."

The fix was real, I replicated that the original code doesn't work still for me, and I think I've done things thoroughly (i hope) such that I'm not wasting anyones time :). I don't know if/what the HX711 library code should be updated, but I will at least update the issue tracker in case someone else shows up having the same issues as me.
 
I've just added delays to the core-shiftIn function: https://github.com/PaulStoffregen/cores/blob/master/teensy3/pins_teensy.c#L1146
Yes, it will work with every F_CPU and every Teensy 3.x /LC this way.

:O, cool. :)

Is there anything I can do to ensure due diligence about the bug? Meaning, making sure the change is a necessary change. The only thing I could think of today was what I last posted, that I replicated again after fixing the hardware issue and found that your code with the microdelay worked, but the default HX711 code did not. I also checked that the default HX711 code did not work at 24Mhz (or 48, or 120). I could probably actually test it at <24Mhz, by adding LEDs to indicate whether the value is reporting wrong (I know a range of what to expect as values for the given load cell when unloaded.)

The other thought is perhaps over the weekend I could fix up another board with fewer wires and just the HX711.

Anyhow, thank you so much for the help :).
 
Well, the Datasheet https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/hx711_english.pdf, page 5, states that the "typical" time needs to be 1 us. The AVR-Controllers are not that fast and slow enough - Teensys are incredible fast, and the fixed delay of 1 microsecond ensures that that it runs with the same speed on every teensy.

The original shiftIn might work below 24Mhz.

I'd say, this fix should go into the the teensy core to ensure AVR compatibility and reliable timing - but that's up to Paul - I'm sure he reads this(?)
Maybe one of the the readers here wants to make a pull-request. I don't feel like it.
 
Last edited:
Hard for me to say what is right or wrong. hx711 library relies on Arduino being slow enough. That seems to be the library fault. On the other hand, users like me are *hard* stuck in a situation like this, so being compatible with avr is nice.


Hopefully Paul sees this and gives input.


Thank you so much Frank for being so thorough in helping me out :).
 
Status
Not open for further replies.
Back
Top