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

mixing analogReference(INTERNAL4V096); and analogReference(DEFAULT); with analogRead and analogDiffRead Not allowed? #27

Closed
macron0 opened this issue Jul 19, 2020 · 9 comments

Comments

@macron0
Copy link

macron0 commented Jul 19, 2020

Hi. I am not sure this is an actual issue but I don't know where else to ask.

I tried :
analogReference(DEFAULT);output = analogDiffRead(A0, A1, GAIN_1) ; and this returned results around +- 2500. Well below the 4064 limit.
The thing is the current sensor I try to read (ACS758LCB-050b) is very sensitive to the voltage it gets supplied. When I power every thing via usb only the voltage on the board and also the ACS is 4.60 and it returns +-2330 when there is no current. When I power it from batteries it runs at's 5.06 volts and the ACS returns 2530 So I tried reading the LGT8F328P boards own voltage via A7 but this is always returns 4064 with the default reference. So I added a voltage divider (2 680k resisters) and I changed the analogReference to INTERNAL4V096. This works great. Now I can actually see the difference in my vcc when it is powered from usb or battery.

But now my results from the differential reads are 4064 instead of around 2500. I tried changing analogReference(DEFAULT); and delay(100) and than read and change it back to analogReference(INTERNAL4V096) but this has no effect.

Is what I try to do impossible?

I am trying to do an differential read because I read somewhere that this reduces noise becuase the noise cancels each other out. But this was the documentation if the ads1115 volt sensor. So I sort of asumed this would be true here too. I am using gain_1 so that means no amplification. Am I wrong and does the differential read not affect the noise?

Thank you for your work. This make those littleboards very cool and useable.

@dbuezas
Copy link
Owner

dbuezas commented Jul 20, 2020

Hi @macron0!
That's a hairy bug you found. I'm not sure what's going on.
Regarding if making a differential read is worth it for noise reduction: it does sound reasonable to me, although I'm not sure if you would have to compensate for the input offset voltage. You can do that by shorting the pins and measuring what zero looks like.

Please try this:

analogReference(INTERNAL4V096);
  
// your other measurements

analogReference(DEFAULT);
VCAL = 0x1A;
DACON = 0x03;
ADCSRD = 0x00;
ADMUX = 0x00;

output = analogDiffRead(A0, A1, GAIN_1);

Also please do the same, but this time use these pins:

output = analogDiffRead(A2, A1, GAIN_1);

I'll need to check the datasheet to see exactly what these are doing, but if you try this and report back, we'll know where to look :)

(reason: analogReference(DEFAULT) is not reseting all registers to their default state, this code does exactly that. I obtained it by checking what registers analogReference touches and then printing their before and after states. I'm also asking to try the other pin combination because that one completely skips the analog muxer)

@macron0
Copy link
Author

macron0 commented Jul 20, 2020

Hi dbuezas. Thank you very much for your reply and your suggestion.

It turned out that adding this was enough to fix my problem:

analogReference(DEFAULT);
//VCAL = 0x1A;
//DACON = 0x03;
ADCSRD = 0x00;
//ADMUX = 0x00;

Uncommenting the others did not change anything. But maybe I should use it anyway to be safe?

Here are my results. Funny that the Single/analogRead returns lower values than the analogDiffRead.

A7=is connected to the vcc of the board via a voltage divider (2x 10k resistors)
Reading 2 volts on A1 (a0 and a2 are 0) ref=default Reading a7 (4.69v) ref=INTERNAL4V096
20:34:35.185 -> Diff a0 a1: 1772 single: 1755
20:34:35.233 -> Diff a2 a1: 1760 single: 1743
20:34:35.233 -> A7: 4V096 single: 2351 (x2=4702)

Reading 2 volts on A1 (a0 and a2 are 0) ref=default Reading a7 (4.96v) ref=INTERNAL4V096
20:39:18.622 -> Diff a0 a1: 1681 single: 1667
20:39:18.670 -> Diff a2 a1: 1684 single: 1668
20:39:18.718 -> A7: 4V096 single: 2481 (x2=4962)

If I run it without the fix I get these results:
20:51:08.015 -> Diff a0 a1: 4064 single: 4064
20:51:08.015 -> Diff a2 a1: 4064 single: 4064
20:51:08.062 -> A7: 4V096 single: 2355

You did solve my problem. Thank you again.

One little thing. When trying the all_vs_all.ino example it sets serial speed to 230400. Very cool and fast but after this I could no longer upload schetches until I figured out that it worked if I pressed the reset button just after I clicked the upload button in arduino ide. Changing the speed down to 115200 fixed it.

@dbuezas
Copy link
Owner

dbuezas commented Jul 20, 2020

🎉🎉🎉 Yey!
I see, then the call to analogReference was leaving the BGEN bit of ADCSRD as 1 and since everything else was off, the internal 1.024v internal reference was active.

This is a bug, I'll fix it in the next release.

Here's the ADCSRD register for reference:
image

Regarding to the inability to reset after all_vs_all: I also got other reports of people that had to reset manually before uploading. That's really funky. I guess the old bootloader these boards come with has some small bugs... But glad to hear you got it working again.

@nulllaborg
Copy link

Hi. I am not sure this is an actual issue but I don't know where else to ask.

I tried :
analogReference(DEFAULT);output = analogDiffRead(A0, A1, GAIN_1) ; and this returned results around +- 2500. Well below the 4064 limit.
The thing is the current sensor I try to read (ACS758LCB-050b) is very sensitive to the voltage it gets supplied. When I power every thing via usb only the voltage on the board and also the ACS is 4.60 and it returns +-2330 when there is no current. When I power it from batteries it runs at's 5.06 volts and the ACS returns 2530 So I tried reading the LGT8F328P boards own voltage via A7 but this is always returns 4064 with the default reference. So I added a voltage divider (2 680k resisters) and I changed the analogReference to INTERNAL4V096. This works great. Now I can actually see the difference in my vcc when it is powered from usb or battery.

But now my results from the differential reads are 4064 instead of around 2500. I tried changing analogReference(DEFAULT); and delay(100) and than read and change it back to analogReference(INTERNAL4V096) but this has no effect.

Is what I try to do impossible?

I am trying to do an differential read because I read somewhere that this reduces noise becuase the noise cancels each other out. But this was the documentation if the ads1115 volt sensor. So I sort of asumed this would be true here too. I am using gain_1 so that means no amplification. Am I wrong and does the differential read not affect the noise?

Thank you for your work. This make those littleboards very cool and useable.

maybe fix nulllaborg/arduino_nulllab@78371c9#diff-730eea5c79180832efce2d49c3984db0483ccb3b41cf80941cb0cd616488aa6a
i will fix all lgt328P mcu issue

@andrey-belokon
Copy link

Hi
I have installed 1.0.6 core, but my code not working correct without reset ADCSRD to zero after analogReference(DEFAULT).
Is this bug fixed?

@LaZsolt
Copy link
Collaborator

LaZsolt commented Apr 30, 2022

This has not yet been corrected.

The problem is not with the BGEN bit, it's with the REFS2 bit. The REFS2 bit should be zero in all cases except for the 4.096V selection, I think. #27 (comment)

@LaZsolt
Copy link
Collaborator

LaZsolt commented May 30, 2022

@andrey-belokon
@macron0

Today I finished testing my modification on function analogReference(). Works great.
The modified code is available here: https://github.com/dbuezas/lgt8fx/discussions/207
The test program: https://github.com/LaZsolt/LGT8F328P_diff_amp_test

About the reason of modification:
When analogReference(INTERNAL4V096) is selected the REFS2 bit of the ADCSRD register is set.
At the second call of analogReference() which select other than INTERNAL4V096 or INTERNAL2V048 the REFS2 bit not cleared.
So I moved cbi(ADCSRD, REFS2); few lines earlier to ensure to clear REFS2 bit:

void analogReference(uint8_t mode)
{
	analog_reference = mode;

#if defined(__LGT8FX8E__) || defined(__LGT8FX8P__)
	#if defined(__LGT8FX8E__)
	if (analog_reference == INTERNAL2V56) {
		VCAL = VCAL2;
	} else {
		VCAL = _VCAL_1_;
	}
	#else
	// set analog reference for ADC/DAC

moved here cbi(ADCSRD, REFS2);

	if (analog_reference == EXTERNAL) {
		DACON = (DACON & 0x0C) | 0x1;
		if((PMX2 & 0x2) == 0x2) {
			GPIOR0 = PMX2 & 0xfd;
			PMX2 = 0x80; 
			PMX2 = GPIOR0;
		}
	} else if(analog_reference == DEFAULT) {
		DACON &= 0x0C;
	} else {
		DACON = (DACON & 0x0C) | 0x2;

deleted from here cbi(ADCSRD, REFS2);

		if(analog_reference == INTERNAL2V048) {
			VCAL = VCAL2;	// 2.048V
		} else if(analog_reference == INTERNAL4V096) {
			sbi(ADCSRD, REFS2);
			VCAL = VCAL3;	// 4.096V
		} else	{
			VCAL = VCAL1;	// 1.024V
		}
	}
	#endif

	ADMUX = (analog_reference << 6);
#endif
}   // end of analogReference()

On the other hand in differential_amplifier.cpp some ADC control bits are redefined. This can have unpredictable results.
Eg: SPN defined first in file lgtx8p.h and later used in file wiring_analog.c
So I made some correction in file differential_amplifier.cpp in my lgt8fx repository: https://github.com/LaZsolt/lgt8fx/tree/master/lgt8f/libraries/differential_amplifier

@dwillmore
Copy link
Collaborator

Has this fix been committed to a release? If so, please close this issue.

@LaZsolt
Copy link
Collaborator

LaZsolt commented Jan 16, 2023

Yes this fix been committed to the latest release.

@LaZsolt LaZsolt closed this as completed Jan 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants