Hi, new user here. First up, thank you for GCBasic, it's a great software to work with.
I am working on a voltmeter based on ATmega328P and have decided to use the internal 1.1V reference since it's believed to be pretty stable. To increase the accuracy of the measurements, I need to find the exact voltage on the AREF pin (by measuring it with a multimeter then using it in my code), but with GCBasic it's always around 0.16V instead of 1.1V (it's like it doesn't get powered on). Here's my code:
#chip mega328p, 1
#config osc = int
Dim pmm_temp As Word
#define AD_REF_SOURCE AD_REF_256
pmm_temp = ReadAD10(ADC5) ;Take a reading to enable the ADC
Do
Loop
On the other hand, with this Arduino sketch, I get 1.08V on AREF, as expected:
The quick answer is to go ahead and set those ADMUX bits in your program code prior to reading the adc as a work around. Have not looked at the library so it may, or may not, be the problem :)
Set REFS0 ON
Set REFS1 ON
pmm_temp = ReadAD10(ADC5) ;Take a reading to enable the ADC
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for the input. I have looked inside a-d.h and it seems like the ReadAD functions overwrite the contents of REFS0 and REFS1 registers when called, but that's not a big problem.
The issue seems to be a hardware one, after some experiments it looks like the 1.1V reference is connected to the AREF pin only while a reading takes place. Probably ATMEL thought it would save power. I thought that when the internal reference is selected it would be connected to the AREF pin at all times.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The data sheet mentions adding a capacitor to Aref to add noise immunity protection. It took a 100uf cap for me to get a stable reading on my UNO! The reading was 1.088-1.091V.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
According to my UNO R3 schematic there is a 100nF capacitor connected to AREF (Pin 21). Seems to me that this would be quite sufficient for stabilization of the internal AREF voltage. Anything over 1 uF would seem to be overkill unless possibly Vcc/AVcc is noisy due to a dodgy power source or poor grounding. Having to use a a monster capacitor for stable readings may be indicative of underlying problems.
A quality power source and good grounding are paramount to good and stable ADC readings. If the Arduino UNO is being powered by the USB Port, then a good quality USB cable should be used. Not one of the cheap unshieded ones. I use a shielded cable that also has a noise filter near the output (printer) end.
*** Setting the ADMUX bits REFSx in GCB source code will not do anything because they will be overridden at ADC acquisition time.
With the default settings and a good USB Cable that supplies the power, I get very stable readings with the AVREF set to the internal 1.1V internal reference. The ADC voltage is supplied by a 10K pot to Arduino "A1". My TEK DVM reads 1.098 at the AVREF pin and 1.093 V when the ADC value just barely reaches 255.
Here is my working Code:
#chip mega328p, 16
'I2C Stuff
HI2CMode Master
#define HI2C_DATA
'Set up LCD
#define LCD_IO 10
#define LCD_I2C_Address_1 0x7E
#define AD_REF_SOURCE AD_REF_256 '1.1V for Arduino Uno R3 (328P)
#define AD_VREF_DELAY 1 ms ' Must be 1 ms or greater
#Define AD_DELAY 2 10 us ' Default setting
#Define ADSpeed MediumSpeed ' Default setting
Wait 500 ms 'stabilize
'read ADC and Display Value
Do
AD_Val = readad(AN1)
Locate 0,0
Print AD_VAL : LCDSPACE 2
Loop
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
@William, just to be clear the a-d readings were just fine with the clone UNO and the 1.1V Aref specified using the inbuilt a-d library. Using an unknown quality wall wart to power up the UNO, could be it. Lots of long wires on the breadboard waving around in the air, that also could also be it. Good idea on using the USB port for power, I need to change over.
Irregardless, now that we have shown it's possible to measure Aref voltage, I won't be revisting this anytime soon :)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If the ADC reads are taking place at a low sampling rate, the AVREF looks like a sawtooth since it cycles on/off with every acquisition. To get a valid reading at low sample rates, the DVM must be able to read DC Peak Voltage. Otherwise the rate must be increased so that the 100nF capacitor on the AVREF pin does not have time to discharge between acquisitions. Reading every 10 ms allows an accurate AVREF voltage measurement, even with a cheap DVM.
Having a 100uF capacitor on the AVREF pin probably explains why one AVREF measurement was good and another was not so good. The 100uF cap cannot discharge between readings, even at relatively low sample rates. But I suspect the first few readings might not be very accurate until the 100uF cap fully charges, unless the AD_VREF_DELAY is increased significanly.
Posted By Kent:
Irregardless, now that we have shown it's possible to measure Aref voltage, I won't be revisting this anytime soon :)
Me Either :)
Last edit: William Roth 2017-03-11
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Are you really operating the 328P at 1 MHz with the internal oscillator ? I would suggest a 16MHz Crystal instead unless you really need 1 MHz .... ? If this is the case then we must assume that are not using an UNO and that you may have not fitted any capacitor at all on AVREF. There must be at least a 100nF cap fitted there and another fitted on Vcc/AVcc
Your test code for GCB does not have the ADC inside a loop so only one sample is taken and you will never get a good measurement. Put the ADREAD function inside a loop with a sample rate of 10 ms and then measure the voltage. Like this:
#chip mega328p, 1
#config osc = int
Dim pmm_temp As Word
#define AD_REF_SOURCE AD_REF_256
Do
pmm_temp = ReadAD10(ADC5) ;Take a reading to enable the ADC
wait 10 ms
Loop
Last edit: William Roth 2017-03-11
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Heh, my try had a really low sample rate, I did not realize the MUX bits got cleared on exit from adc reading. Nor did I think to use Max reading on the DVM either. So that explains it, for me at least, Thanks!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Indeed, I had used 1 MHz, since it was the default speed,b utit can be changed to anything (i'm not tied to it in any way). In the end i'll probably go with 16 MHz as you suggested. I have the whole circuit on a breadboard, it's more easy to fiddle with :). The setup I have is like this:
A coil of 10 uH between +5V and AVCC
An electrolytic cap of 2.2uF and an 100nF cap between AVCC and GND (they are in parallel)
A capacitor of 100nF from ARef to GND
Regarding the reference going on / off, here's what I found in the datasheet:
The reference is on during the following situations:
1. When the BOD is enabled (by programming the BODLEVEL [2..0] Fuse Bits).
2. When the bandgap reference is connected to the Analog Comparator (by setting the
ACBG bit in ACSR).
3. When the ADC is enabled. [this is what i'm interested in]
Thus, when the BOD is not enabled, after setting the ACBG bit or enabling the ADC, the > user must always allow the reference to start up before the output from the Analog
Comparator or ADC is used.
If we look in the a-d.h header of GCBasic, at line 1215 the ADC is turned on and at line 1222 it's turned off. This explains the fluctuations, etc. So to counter this and be able to measure the internal Vref accurately (i only have a simple, 3 1/2 digit multimeter without peak power measurement) I have used this code:
#chip mega328p, 1
#config osc = int
ADMUX = 5 ;e.g. ADC5
;Use internal ref
Set REFS0 On
Set REFS1 On
;Set a prescaler
SET ADPS2 On
SET ADPS1 On
;Turn on ADC
Set ADEN On
;Wait 10 s with the ADC on (the 1.1V reference is now also on). One can measure Aref
Wait 10 S
;Here we'd normally make a conversion
;Turn off the ADC
Set ADEN Off
;Finished
Do
Loop
With it, I can read a stable 1085 mV. I will keep digging and playing with the code, might also make a small ADC lib (I also want to implement oversampling).
Thanks for the input.
Last edit: alex_t 2017-03-13
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I haven't yet needed to change uno ref v for my a-d experiments. Can I assume it's not an issue and if I do want to change it from the supply rail ref it's all sorted?
I down loaded GCB for pic use but used a uno more. The only code I've done on a uno is GCB. No sketch c install or anything arduino except xloader which I've erased since getting flash hex working and that was me using the wrong com port. Wish more people who find c difficult but basic easier knew GCB is supporting arduino even more and the arduino can be programmed in basic and run fast.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There's no problem with the way GCBasic works. The only issue I had is that with the current AD library the ADC is turned on only while the reading is taking place. This also means that the internal 1.1V reference is on only while the reading takes place. Not being on all the time, I couldn't measure its exact voltage (to use in my calculations). With the above code, the ADC (and thus internal reference) is kept on long enough for one to take a reading of the reference voltage on pin 21 of ATmega328P.
Depending on your needs, you can use any reference you want, GCBasic will handle it just fine :).
I'm sure that more people will come over and try GCBasic. It already is very powerful and I bet it will get even better. Hopefully some of us beginners will be able to help as well.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm enjoying using GCB. Wish I'd come across it earlier. As a beginner, I only post things that don't work with picaxe like glcd. I wrote my own plot and line draw in picaxe basic..have a laff :)
picaxe 28x2 (pic 18f25k22) at 64mhz ext xtal https://www.youtube.com/watch?v=kL3c1wry9ok&t=3s
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi, new user here. First up, thank you for GCBasic, it's a great software to work with.
I am working on a voltmeter based on ATmega328P and have decided to use the internal 1.1V reference since it's believed to be pretty stable. To increase the accuracy of the measurements, I need to find the exact voltage on the AREF pin (by measuring it with a multimeter then using it in my code), but with GCBasic it's always around 0.16V instead of 1.1V (it's like it doesn't get powered on). Here's my code:
On the other hand, with this Arduino sketch, I get 1.08V on AREF, as expected:
Any idea what I'm doing wrong?
Best regards.
The quick answer is to go ahead and set those ADMUX bits in your program code prior to reading the adc as a work around. Have not looked at the library so it may, or may not, be the problem :)
Thanks for the input. I have looked inside a-d.h and it seems like the ReadAD functions overwrite the contents of REFS0 and REFS1 registers when called, but that's not a big problem.
The issue seems to be a hardware one, after some experiments it looks like the 1.1V reference is connected to the AREF pin only while a reading takes place. Probably ATMEL thought it would save power. I thought that when the internal reference is selected it would be connected to the AREF pin at all times.
The data sheet mentions adding a capacitor to Aref to add noise immunity protection. It took a 100uf cap for me to get a stable reading on my UNO! The reading was 1.088-1.091V.
Hi,
According to my UNO R3 schematic there is a 100nF capacitor connected to AREF (Pin 21). Seems to me that this would be quite sufficient for stabilization of the internal AREF voltage. Anything over 1 uF would seem to be overkill unless possibly Vcc/AVcc is noisy due to a dodgy power source or poor grounding. Having to use a a monster capacitor for stable readings may be indicative of underlying problems.
A quality power source and good grounding are paramount to good and stable ADC readings. If the Arduino UNO is being powered by the USB Port, then a good quality USB cable should be used. Not one of the cheap unshieded ones. I use a shielded cable that also has a noise filter near the output (printer) end.
*** Setting the ADMUX bits REFSx in GCB source code will not do anything because they will be overridden at ADC acquisition time.
With the default settings and a good USB Cable that supplies the power, I get very stable readings with the AVREF set to the internal 1.1V internal reference. The ADC voltage is supplied by a 10K pot to Arduino "A1". My TEK DVM reads 1.098 at the AVREF pin and 1.093 V when the ADC value just barely reaches 255.
Here is my working Code:
@William, just to be clear the a-d readings were just fine with the clone UNO and the 1.1V Aref specified using the inbuilt a-d library. Using an unknown quality wall wart to power up the UNO, could be it. Lots of long wires on the breadboard waving around in the air, that also could also be it. Good idea on using the USB port for power, I need to change over.
Irregardless, now that we have shown it's possible to measure Aref voltage, I won't be revisting this anytime soon :)
Measuring the AVREF:
If the ADC reads are taking place at a low sampling rate, the AVREF looks like a sawtooth since it cycles on/off with every acquisition. To get a valid reading at low sample rates, the DVM must be able to read DC Peak Voltage. Otherwise the rate must be increased so that the 100nF capacitor on the AVREF pin does not have time to discharge between acquisitions. Reading every 10 ms allows an accurate AVREF voltage measurement, even with a cheap DVM.
Having a 100uF capacitor on the AVREF pin probably explains why one AVREF measurement was good and another was not so good. The 100uF cap cannot discharge between readings, even at relatively low sample rates. But I suspect the first few readings might not be very accurate until the 100uF cap fully charges, unless the AD_VREF_DELAY is increased significanly.
Me Either :)
Last edit: William Roth 2017-03-11
@Alex ..
Are you really operating the 328P at 1 MHz with the internal oscillator ? I would suggest a 16MHz Crystal instead unless you really need 1 MHz .... ? If this is the case then we must assume that are not using an UNO and that you may have not fitted any capacitor at all on AVREF. There must be at least a 100nF cap fitted there and another fitted on Vcc/AVcc
Your test code for GCB does not have the ADC inside a loop so only one sample is taken and you will never get a good measurement. Put the ADREAD function inside a loop with a sample rate of 10 ms and then measure the voltage. Like this:
Last edit: William Roth 2017-03-11
Heh, my try had a really low sample rate, I did not realize the MUX bits got cleared on exit from adc reading. Nor did I think to use Max reading on the DVM either. So that explains it, for me at least, Thanks!
Indeed, I had used 1 MHz, since it was the default speed,b utit can be changed to anything (i'm not tied to it in any way). In the end i'll probably go with 16 MHz as you suggested. I have the whole circuit on a breadboard, it's more easy to fiddle with :). The setup I have is like this:
Regarding the reference going on / off, here's what I found in the datasheet:
If we look in the a-d.h header of GCBasic, at line 1215 the ADC is turned on and at line 1222 it's turned off. This explains the fluctuations, etc. So to counter this and be able to measure the internal Vref accurately (i only have a simple, 3 1/2 digit multimeter without peak power measurement) I have used this code:
With it, I can read a stable 1085 mV. I will keep digging and playing with the code, might also make a small ADC lib (I also want to implement oversampling).
Thanks for the input.
Last edit: alex_t 2017-03-13
I haven't yet needed to change uno ref v for my a-d experiments. Can I assume it's not an issue and if I do want to change it from the supply rail ref it's all sorted?
I down loaded GCB for pic use but used a uno more. The only code I've done on a uno is GCB. No sketch c install or anything arduino except xloader which I've erased since getting flash hex working and that was me using the wrong com port. Wish more people who find c difficult but basic easier knew GCB is supporting arduino even more and the arduino can be programmed in basic and run fast.
There's no problem with the way GCBasic works. The only issue I had is that with the current AD library the ADC is turned on only while the reading is taking place. This also means that the internal 1.1V reference is on only while the reading takes place. Not being on all the time, I couldn't measure its exact voltage (to use in my calculations). With the above code, the ADC (and thus internal reference) is kept on long enough for one to take a reading of the reference voltage on pin 21 of ATmega328P.
Depending on your needs, you can use any reference you want, GCBasic will handle it just fine :).
I'm sure that more people will come over and try GCBasic. It already is very powerful and I bet it will get even better. Hopefully some of us beginners will be able to help as well.
I'm enjoying using GCB. Wish I'd come across it earlier. As a beginner, I only post things that don't work with picaxe like glcd. I wrote my own plot and line draw in picaxe basic..have a laff :)
picaxe 28x2 (pic 18f25k22) at 64mhz ext xtal https://www.youtube.com/watch?v=kL3c1wry9ok&t=3s
Sweet, keep it up :).