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

Can't read data when using external crystal #45

Closed
dsafak opened this issue Sep 22, 2020 · 22 comments
Closed

Can't read data when using external crystal #45

dsafak opened this issue Sep 22, 2020 · 22 comments

Comments

@dsafak
Copy link

dsafak commented Sep 22, 2020

I am trying to use a 20mhz external oscillator with hx711 and according to its datasheet it is in spec.
When using 20mhz crystal, Reading data doesn't work and it only shows 0 and some high number when a force is applied.

I can read data with a quick test sketch I've made (didn't use the library) to check if all is working, so connections are right and oscillator is working.

@olkal
Copy link
Owner

olkal commented Sep 22, 2020

Hi, I have just tested the current library version with a HX711 modified with 20mhz crystal, and I have no issues. Also, as using an external crystal only changes the HX711 internal sampling rate, it should make no difference with respect to data transfer/library functions.

So IMO there must be something else wrong. Did you try with any of the library example files?

@dsafak
Copy link
Author

dsafak commented Sep 22, 2020

I have current library version and I connect the crystal directly across 13 and 14 pins according to datasheet.
I agree that it shouldn't make any difference and none of the hx711 libraries worked but the sketches where I modified
the reading method slightly.

I tried with the multiple loadcell example.

I also used 2 capacitors for connecting crystal but it wasn't required so it didn't matter.

I'll try with a single loadcell example and report back in couple minutes.

@olkal
Copy link
Owner

olkal commented Sep 22, 2020

Okay. Did you disable the internal oscillator by soldering off pin 14 from from the pcb pad (originally connected VCC)?
Here is a picture my HX711@20mhz:

58051875-9ee7bc80-7b53-11e9-922b-c91145bf967c

@dsafak
Copy link
Author

dsafak commented Sep 22, 2020

Yes, I did. I think it is originally connected to GND? but regardless those are disconnected and there is a 20mhz xtal across them now. To clarfiy it more, I then removed the xtal and soldered 2 jumper wires so now I can switch between internal and external on a breadboard, If I did wiring wrong, I can make a change easily.

tried read_1x_loadcell example, connections are correct and I can retrieve data in my own sketch but not with this library. It is odd.
Using library-wise I know I am not setti
ng it wrong. Electronically, I just connect a crystal between 2 legs and could test it with a sketch so it is also fine.

hx711working.zip

attached sketch is working I had to modify the shift function to get it to work.
Moved digitalWrite LOW below HIGH and then I have read the data. Otherwise it doesn't work for some reason.

@dsafak
Copy link
Author

dsafak commented Sep 22, 2020

uint8_t HX711_ADC::conversion24bit()  //read 24 bit data, store in dataset and start the next conversion
{
	...
	{ //read 24 bit data + set gain and start next conversion
		if(SCK_DELAY) delayMicroseconds(1); // could be required for faster mcu's, set value in config.h
		digitalWrite(sckPin, 1);
                if(SCK_DELAY) delayMicroseconds(1); // could be required for faster mcu's, set value in config.h
		digitalWrite(sckPin, 0);
		if (i < (24)) 
		{
			dout = digitalRead(doutPin);
			data = data << 1;
			if (dout) 
			{
				data++;
			}
		...
}

Editing this part of conversion24bit function and all starts working, I have a little more noise then 80sps, not sure if this is expected or not, but it starts functioning.

Config is set to 1 samples and no delays.

@olkal
Copy link
Owner

olkal commented Sep 22, 2020

It could very well be that your change: SCK 1 > SCK 0 > read DOUT is more correct then the library's SCK 1 > read DOUT > SCK 0. If so it's an easy fix if that's what needed. Strange thing is that I don't know of anyone else that have had the same issue. Can I ask what kind of MCU are you using, is it particulary slow or fast?

BTW; yes you're right, pin 14 to GND enables the internal clock.

@dsafak
Copy link
Author

dsafak commented Sep 22, 2020

I am using atmel32u4 on an Arduino Leonardo so nothing special, somehow this change makes it work and the other doesn't I am trying to figure out why because according to datasheet it should work either way.

and more suprisingly none of the available hx711 libraries seem to work in my case.

I also tried it with just an empty sketch and with a sketch which is really heavy (where I actually need to use the library) and it didn't work in both without this change.

@olkal
Copy link
Owner

olkal commented Sep 22, 2020

I have never tried the library with the 32u4. I don't fully understand what is happening other than that it seems to be timing related, but I will move the digitalWrite LOW anyway if it can improve library compability. Studying the data sheet, it is also done like this in the driver example on page 8. however, I need to do some testing first to check that the change works okay with other MCU's.

@dsafak
Copy link
Author

dsafak commented Sep 22, 2020

Sadly, I don't have anything else around right now to test with exact hx711 and crystal setup, but I also believe it is a timing issue.
Thank you for paying attention to my issue, hope it just works fine on all MCUs so the change can be moved to master.

@olkal
Copy link
Owner

olkal commented Sep 22, 2020

I did some testing with Uno, Due and ESP8266, all good. Changes implemented in new release 1.2.2.

@dsafak
Copy link
Author

dsafak commented Sep 23, 2020

I have investigated this further and this is a timing issue (I added microsecond delays by 1 each time and encountered exact same issue at some point not really far from 0 microseconds).

There was one more issue with 20mhz crystal.
With internal crystal at 80SPS, load cell at rest (no weight) reads 90K (offset is 0 so it just reads)
When using 20mhz crystal it was dropping to 68K at rest, so this got me wondering why?

I thought it is because of Arduino's digitalWrite() function speed and maybe I am losing some data (I am still not sure),
so I loaded the test sketch I've shared 7 messages above and switched digitalWrites with FastGPIO library. Nothing have changed about what is being read still around same 90K and 68K.
BUT,
With digitalWrite()
At 80SPS with internal oscillator the noise is around 400 units.
At 144SPS with external oscillator noise is around 1600 units.
with FastGPIO
At 80SPS with internal oscillator the noise is around 400 units.
At 144SPS with external oscillator noise is around 400 units.

This can be done just by writing into registers directly to set High and Low,
I just wanted to use a library to save myself some time.

I thought this issue is kind of okay to also include this information.
I guess writing into registers for setting pins high and low is not an option for a library targeting many devices.
But these are my findings.

@olkal
Copy link
Owner

olkal commented Sep 23, 2020

Lots of strange things here...
Direct port manipulation for faster writing is difficult with a library, yes.
I did some testing today with a 32u4 together with 20mhz HX711, and it seems to work fine here, also with the previous library version. Could there be something wrong with your HX711 module? Do you have another one to test with?

@dsafak
Copy link
Author

dsafak commented Sep 24, 2020

How does it work for you with previous version but doesn't work for me is strange.

When I put a counter for a second and read load cell data and then read counter after a second, I get 145 with 20mhz, and 84 with internal oscillator. Serial plotter also moves faster and slower when I change oscillator.
I don't know why with 20mhz it reads about 30K less at rest. about 65K vs 90K.
Also I can't really point a finger at why there is more noise with digitalWrite vs Port manipulation.
Port manipulation brings noise back to exactly internal oscillator levels.

But it is functioning as expected when there is a force applied on it, so I can't point fingers at anything.

I tried with 2 different Arduino, one is a normal clone, the other one is a little special and has better quality. They are both running 32u4 @ 16mhz.
2 Different HX711s, cheap regular ones thought.
A new sketch just with bare minimum to read load cell.
tried digital pins 2-3, 3-4, 8-9
4-5 different 20mhz crystals but all bought at the same time from same store.
At this point I wonder what if they are not 20 but 20.1mhz 20.2mhz? Maybe messes up with timing?
or my Cheap hx711s have to do something with this? but they are the only ones available here.
I can't think of anything else.

so it's not the 32u4, not the Arduino board, not hx711(same IC cheap or expensive board anyway, right?)

doesn't work with old version of library, works with new version.
At this point I really hope your 32u4s were running faster than 16mhz at that was why old one worked for oyu.

One more question did you observe a drop in the read value switcihng between 80 and 144SPS as I have?
and more noise with 144SPS with digitalWrite?

About direct port manipulation,
I am writing more methods into library to enable direct port manipulation right now, I have some issues and trying to fix them.

@dsafak
Copy link
Author

dsafak commented Sep 24, 2020

One more think, what capacitors are you using? Maybe that is why we are seeing different results.

@olkal
Copy link
Owner

olkal commented Sep 24, 2020

On the crystal? I think it's 22pF

@dsafak
Copy link
Author

dsafak commented Sep 24, 2020

Thanks, I'll try but what do you think, I think I have tried enough different hardware.
I tried with 33pF and without any, nothing was different.

it is either crystal, capacitor or cheap hx711 (shouldn't be this one).

Are you sure it is working on old version with 32u4 @ 16mhz? This is really strange.

@olkal
Copy link
Owner

olkal commented Sep 24, 2020

Yes, it's working fine with my 32u4 16mhz mini (china manufactured) also with old version library with the digitalWrite(sckPin, 0) in original position. Tested with 20mhz + internal osc, high rate and low rate. I don't see any noticable difference in noise changing from 20mhz to internal osc.

I do see an offset in the output value comparing internal and external osc. but not much, its aprox. 2.5gr on a 1000gr load cell, so 0.25%.

The Arduino 32u4 modules use a "real" crystal, not ceramic oscilator, so MCU frequency should be accurate within 50ppm and same as yours.

@dsafak
Copy link
Author

dsafak commented Sep 24, 2020

I didn't know the last bit about 32u4. The noise offset looks to be right in line with my experience.
Noise is so important for my project so I was talking about raw reading noise, so it is normal for you to not see any noticible noise but there was in raw data about 200-500 vs 800-1600.
(Filter is also disabled because latency is also important, so no filter either just raw data)

so all looks inline with what I see here, so it must be my crystals I suppose, but lets assume they are a little over 20mhz, I still don't think it should cause such issue, maybe it does mess up with timings. They all say "20mhz" on them thought, maybe I should measure them for real, the measurementI do on arduino isn't that accurate but still lays right on 145sps (should be 144 with exact 20mhz but again not accurate)... well...

About library and pulsing with port manipulation.
at first I was converting every method and naming them "xxxWPM"
then I realized it isn't really required.

I implemented a real simple method into the library,
void pulseUsingPortManipulation(byte aDDRB, byte aDDRC, byte aDDRD);
So you do everything as before, but if you call this method like,
loadcell.pulseUsingPortManipulation(B00000000, B10000000, B00000000);
This will set a flag and inside conversion24bit() method, Port manipulation will be used to pulse pin13 (for arduino leonardo).
I didn't touch the digitalRead as it wasn't necessary.

I don't plan to map ports to pin numbers arduino, it even changes between arduino type to arduino type, so when this method is used, correct register should be put into parameters for the correct pin, this is kinda low level and a special case anyway.

At least this is the plan. Works with single loadcell, all good, no issues.
Gonna test it with multiple loadcells.

@olkal
Copy link
Owner

olkal commented Sep 24, 2020

I added some lines in the library .cpp file to roughly measure digital write time:

{ //read 24 bit data + set gain and start next conversion
		long t; //add
		t = micros(); //add
		if(SCK_DELAY) delayMicroseconds(1); // could be required for faster mcu's, set value in config.h
		digitalWrite(sckPin, 1);
		if(SCK_DELAY) delayMicroseconds(1); // could be required for faster mcu's, set value in config.h
		digitalWrite(sckPin, 0);
		if (i == 0) Serial.println(micros() - t); //add
		if (i < (24)) ....

The result was 16us, sometimes 20us. That is for 2x digital write + some time to read the micros() value so I suppose each digital write is about 6-7us. Could you try the same?

@olkal
Copy link
Owner

olkal commented Sep 24, 2020

I just measured with oscilloscope using my 32u4 and library latest version: the SCK high time is 6.6us, well within the required range of 0.2-50us in the H711 data sheet.

@dsafak
Copy link
Author

dsafak commented Sep 24, 2020

I don't have access to an oscilloscope right now but I did the changes and measured with my Arduino.
I got 12-16 in serial monitor -> Works.
Old library 16-20 -> Doesn't work.

My knowledge about how things work as of right now ends here, so I wonder if increasing xtal to 20mhz reduces the time windows?

@olkal
Copy link
Owner

olkal commented Dec 15, 2020

Closed due to no activity

@olkal olkal closed this as completed Dec 15, 2020
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

2 participants