I am having a few issues with the attached file. First, the clock seems to be really messed up. Even though I say 'r9600' in the InitSer call, the actual baud rate is 1200. Along the same lines, 'Wait 1 S' is about 8 seconds.
Second, I am trying to use the internal temperature sensor. No matter what I do, it seems to return 0xFF. As far as that goes, not matter which ADC I try, it returns 0xFF. I am wondering if the timing issues are causing problems. Any suggestions?
AVR's come from the factory with the internal clock at 1 Mhz. You must change the fuse selection to 8 Mhz in whatever programmer is being used. You can verify by changing the chip define to 1MHz.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Haven't fooled with the internal temperature before with the AVR. But I will say the GCB library is not recognizing the fact that ADC4 is an internal register/function. This would require some work to fix or fire a one off adc function/sub that will correctly set the MUX bits.
My goto solution is to use a cheap MCP9700/9701 analog temp sensor.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There is way to add specific instructions to the ADC library to resolve this issue. Add the following to your code. You will need the latest patches ( see below).
#DEFINE ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0XF0 ) or 0X0F
This will instruct the compiler to add the instructions ( ADMUX and 0XF0 ) or 0X0F just before the ADC operation. As per Table 17-4. Input Channel Selections in the ATTINY85 datasheet. The constant ADREADPREREADCOMMAND tells the compiler to do this. I had added this to the PIC section of the compiler years ago to workaround the type of issue Joe has come across.
This is covered in the Help. See ADC Optimisation Help. Noting this was only just implemented for the AVR chips.
The reason why I cannot simply code the ADC4 to the internal ... ATMEL do not use have a consistent register bit config for the internal temp sensor
Tiny85 = ADMUX.MUX[3:0] to '1111' enables the temperature sensor.
Mega328p = ADMUX.MUX[3:0] to '1000' enables the temperature sensor.
So, the ADREADPREREADCOMMAND workaround will enable the resolution of the issue.
Apologies for taking so long to reply. Day jobs interfere so much in the fun stuff.
kent_twt4 - Thank you for the fuse hint. That bit worked wonderfully! (Sorry, I couldn't resist.)
As for the A/D problem, I am using Fedora, so I built a patched version of the executable and put the patches in place. I see the following in the .ASM -
;ADREADPREREADCOMMAND 'add user code here
ldi SysTemp2,240
in SysTemp3,ADMUX
and SysTemp3,SysTemp2
mov SysTemp1,SysTemp3
ldi SysTemp2,15
or SysTemp1,SysTemp2
out ADMUX,SysTemp1
Next, I tried
#define ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0X00 ) or 0X8F
which should clear the entire ADMUX register and set it to 1.1V and ADC4. I also tried with a fresh chip Still no joy. Could it be a timing issue?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
OK. Thank you. The code is as expected (and, as you posted). So, the constant works.
;ADREADPREREADCOMMAND 'add user code hereldiSysTemp2,240inSysTemp3,ADMUXandSysTemp3,SysTemp2movSysTemp1,SysTemp3ldiSysTemp2,15orSysTemp1,SysTemp2outADMUX,SysTemp1;Wait AD_Delay 'Execute the acquisition DelayldiSysWaitTemp10US,2rcallDelay_10US;Set ADEN On 'Take readingsbiADCSRA,ADEN;Set ADSC OnsbiADCSRA,ADSC;Wait While ADSC OnSysWaitLoop1:
sbicADCSRA,ADSCrjmpSysWaitLoop1
I think I did not understand the datasheet. We need to clear everything except ADLAR and the set 1.1v and ADC4 using MUX[3:0] bits in ADMUX.
Remove the existing ADREADPREREADCOMMAND line and replace with this...
/*The temperature measurement is based on an on-chip temperature sensor that is coupled to a single ended ADC4channel. Selecting the ADC4 channel by writing the MUX[3:0] bits in ADMUX register to “1111” enables the temperature sensor. The internal 1.1V reference must also be selected for the ADC reference source in thetemperature sensor measurement. When the temperature sensor is enabled, the ADC converter can be used insingle conversion mode to measure the voltage over the temperature sensor.*/#defineADREADPREREADCOMMANDADMUX=(ADMUXand0X20)or0X8F
Does this correct? Do test. :-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So, we now have Enable AD and start conversion,
then, ADC4 (Temp Sensor) and Ref voltage = 1.1V,
then, settling time min 10 ms,
then, finally read the ADC
Nope. Same thing. ASM reflects that you are setting ADEN prior to the call. I am starting to wonder if the issue is the AD or something about the processing and printing of the results. I connected a pot between Vcc and ground. I used 0X03 as the or value, which I think should set Vcc as Vref and ADC3 (pin 2) as input connected to the wiper of the pot. I also changed ReadAD10 to read ADC3.
Still get FF as the output. The attached asm is before I made the ADC3 changes mentioned above
@Joe. See below. The read is returning results. If I put the ATTINY85 in the freezer... I get nice decline of values with a steady decrease as the chip gets colder. The lowest reading was 240 in the freezer, and, 300 when the chip on top of my router!
You will need to calibrate etc .to get meaningful man readable temperature values. I have some recollection of the first reading being bogus but I may be wrong - we need a AVR person to help on this point.
I ported to the optimised serial software. The code is a lot smaller.
#CHIP tiny85, 8#OPTION Explicit#include<softserial.h> 'include the library. this is required.#DEFINE ADSpeed MediumSpeed'ConfigSerialUART:#DEFINE SER1_BAUD 9600 'baudrate must be defined#DEFINE SER1_TXPORT PORTB 'I/O port (without .bit) must be defined#DEFINE SER1_TXPIN 2 'portbit must be defined/*17.12 of te datasheetThe temperature measurement is based on an on-chip temperature sensor that is coupled to a single ended ADC4channel. Selecting the ADC4 channel by writing the MUX[3:0] bits in ADMUX register to “1111” enables the temperature sensor. The internal 1.1V reference must also be selected for the ADC reference source in thetemperature sensor measurement. When the temperature sensor is enabled, the ADC converter can be used insingle conversion mode to measure the voltage over the temperature sensor.The measured voltage has a linear relationship to the temperature as described in Table 17-2 The sensitivity isapproximately 1 LSB / C and the accuracy depends on the method of user calibration. Typically, the measurementaccuracy after a single temperature calibration is ±10C, assuming calibration at room temperature. Betteraccuracies are achieved by using two temperature points for calibration.*/#define ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0X20 ) or 0X8F: wait 100 ms'MainprogramdimIntTempasWordDOIntTemp=READAD10(ADC4)Ser1PrintIntTempSer1Send10'sendlinefeedtoterminalSer1Send13'sendnewlinetoterminalWAIT1SLOOP
Your code, a lot larger.
Correct the SerSend to SerPrint for the string. I think this was the issue in your code. I only noticed this after creating the other program! I do not use this version of software serial...ever.
@Anobium
So, after creating a few links to account for FileNameCase, things work splendidly! I thank you so very much for the effort and guidance. I am off to do some calibration and learn softserial.
@steini63
My fuse settings are 0xE2. IIUC 0xE1 selectes the 16Mhz High Frequency PLL source.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
@Joe. Good luck! I am always learning and I just figured out the default Low fuses in 0xE2 - the Tiny85 I have is on a board with a different fuse setting - the Tiny85 has a bootloader with USB interface. :-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
My fuse settings are 0xE2. IIUC 0xE1 selectes the 16Mhz High Frequency PLL source.
Low Fuse ...
0xE1 (Anobium) and
0xE2 (Joe Kirby)
both mean that PLL Clock is enabled, so the clock speed is around 16 MHz, see https://www.engbedded.com/fusecalc/
In order for the compiler to calculate the correct timing for soft serial, the chip statement must of course also be set accordingly:
#chip tiny85, 16
Frank
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
@steini63 Thank you. The Digispark bootloader has a prereq of a specific set of fuses - so, this does explain everything. I need to use these little AVRs more often!
:-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have been following along with interest, and got the internal temp to work manually, but haven't downloaded the library yet. Does using the constant
'#define ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0X20 ) or 0X8F: wait 100 ms
allow for multiple adc inputs to be used in the same program?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So, this will only apply the ADMUX changes for the internal temp sensor.
There is no general case that is needed. As the AVRs are not consistent with ADMUX
The ADREADPREREADCOMMAND constant was implemented a few years ago for PIC. Works very well as this enables changes to the ADC read whilst leveraging the standard ADC commands.
There is more detail on the constant here I have just added the multiple ADC discussed as an example.
Last edit: Anobium 2021-08-29
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am having a few issues with the attached file. First, the clock seems to be really messed up. Even though I say 'r9600' in the InitSer call, the actual baud rate is 1200. Along the same lines, 'Wait 1 S' is about 8 seconds.
Second, I am trying to use the internal temperature sensor. No matter what I do, it seems to return 0xFF. As far as that goes, not matter which ADC I try, it returns 0xFF. I am wondering if the timing issues are causing problems. Any suggestions?
Thanks.
AVR's come from the factory with the internal clock at 1 Mhz. You must change the fuse selection to 8 Mhz in whatever programmer is being used. You can verify by changing the chip define to 1MHz.
Haven't fooled with the internal temperature before with the AVR. But I will say the GCB library is not recognizing the fact that ADC4 is an internal register/function. This would require some work to fix or fire a one off adc function/sub that will correctly set the MUX bits.
My goto solution is to use a cheap MCP9700/9701 analog temp sensor.
I can resolve this in a few moments. I do as Kent recommends to resolve the issue in the library. I will post a fix shortly.
There is way to add specific instructions to the ADC library to resolve this issue. Add the following to your code. You will need the latest patches ( see below).
This will instruct the compiler to add the instructions
( ADMUX and 0XF0 ) or 0X0F
just before the ADC operation. As per Table 17-4. Input Channel Selections in the ATTINY85 datasheet. The constantADREADPREREADCOMMAND
tells the compiler to do this. I had added this to the PIC section of the compiler years ago to workaround the type of issue Joe has come across.This is covered in the Help. See ADC Optimisation Help. Noting this was only just implemented for the AVR chips.
The reason why I cannot simply code the ADC4 to the internal ... ATMEL do not use have a consistent register bit config for the internal temp sensor
Tiny85 = ADMUX.MUX[3:0] to '1111' enables the temperature sensor.
Mega328p = ADMUX.MUX[3:0] to '1000' enables the temperature sensor.
So, the ADREADPREREADCOMMAND workaround will enable the resolution of the issue.
See https://sourceforge.net/projects/gcbasic/files/Release%20Candidates/Patches/ for the ZIP ( ensure you have the latest release installed! ) then apply the patches in the ZIP..
Last edit: Anobium 2021-08-23
Apologies for taking so long to reply. Day jobs interfere so much in the fun stuff.
kent_twt4 - Thank you for the fuse hint. That bit worked wonderfully! (Sorry, I couldn't resist.)
As for the A/D problem, I am using Fedora, so I built a patched version of the executable and put the patches in place. I see the following in the .ASM -
Next, I tried
which should clear the entire ADMUX register and set it to 1.1V and ADC4. I also tried with a fresh chip Still no joy. Could it be a timing issue?
Can you remove your patch to test. Add, the #define and post the ASM. I want to see the resulting code.
The .bas is only a few hundred bytes, so I have included it as well.
OK. Thank you. The code is as expected (and, as you posted). So, the constant works.
I think I did not understand the datasheet. We need to clear everything except ADLAR and the set 1.1v and ADC4 using MUX[3:0] bits in ADMUX.
Remove the existing ADREADPREREADCOMMAND line and replace with this...
Does this correct? Do test. :-)
And, you may need still need to add a delay. Like:
#define ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0X20 ) or 0X8F: wait 10 ms
The minimum settling delay is 1 ms, so, I use 10 ms. Test. And, validate setting.
:-)
Same thing, .ASM attached..
testing without delay
Last edit: Joe Kirby 2021-08-28
No difference with the 10ms settling timer.
See the attached. Replace the .h file.
I have moved the new code below set ADEN = 1
So, we now have Enable AD and start conversion,
then, ADC4 (Temp Sensor) and Ref voltage = 1.1V,
then, settling time min 10 ms,
then, finally read the ADC
Fingers crossed.
Nope. Same thing. ASM reflects that you are setting ADEN prior to the call. I am starting to wonder if the issue is the AD or something about the processing and printing of the results. I connected a pot between Vcc and ground. I used 0X03 as the or value, which I think should set Vcc as Vref and ADC3 (pin 2) as input connected to the wiper of the pot. I also changed ReadAD10 to read ADC3.
Still get FF as the output. The attached asm is before I made the ADC3 changes mentioned above
Can you leave this with me? I will get a Tiny85 operational. Look back tomorrow.
OK?
Will do, thanks
@Joe. See below. The read is returning results. If I put the ATTINY85 in the freezer... I get nice decline of values with a steady decrease as the chip gets colder. The lowest reading was 240 in the freezer, and, 300 when the chip on top of my router!
You will need to calibrate etc .to get meaningful man readable temperature values. I have some recollection of the first reading being bogus but I may be wrong - we need a AVR person to help on this point.
I ported to the optimised serial software. The code is a lot smaller.
I have loaded as a demo in GitHub. See here
Your code, a lot larger.
Correct the SerSend to SerPrint for the string. I think this was the issue in your code. I only noticed this after creating the other program! I do not use this version of software serial...ever.
@steini63
I am not a huge user of the Tiny85 but the BPS is twice that specified... so, this code is set to 9600 but the actual is 19200.
Fuses are. So, 8mHz. I assume.
Low High Extended
0xE1 0xDF 0xFF
Frank - Can you help me understand what I am doing wrong?
Last edit: Anobium 2021-08-29
@Anobium
So, after creating a few links to account for FileNameCase, things work splendidly! I thank you so very much for the effort and guidance. I am off to do some calibration and learn softserial.
@steini63
My fuse settings are 0xE2. IIUC 0xE1 selectes the 16Mhz High Frequency PLL source.
@Joe. Good luck! I am always learning and I just figured out the default Low fuses in 0xE2 - the Tiny85 I have is on a board with a different fuse setting - the Tiny85 has a bootloader with USB interface. :-)
Just did a quick calibrate....
Just took the board out of the freezer....
My code..
Hi!
Low Fuse ...
0xE1 (Anobium) and
0xE2 (Joe Kirby)
both mean that PLL Clock is enabled, so the clock speed is around 16 MHz, see
https://www.engbedded.com/fusecalc/
In order for the compiler to calculate the correct timing for soft serial, the chip statement must of course also be set accordingly:
Frank
@steini63 Thank you. The Digispark bootloader has a prereq of a specific set of fuses - so, this does explain everything. I need to use these little AVRs more often!
:-)
I have been following along with interest, and got the internal temp to work manually, but haven't downloaded the library yet. Does using the constant
'#define ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0X20 ) or 0X8F: wait 100 ms
allow for multiple adc inputs to be used in the same program?
The example shown is a single read of the ADC4/Temp.
Change to the following to make multiple adc inputs.
So, this will only apply the ADMUX changes for the internal temp sensor.
There is no general case that is needed. As the AVRs are not consistent with ADMUX
The ADREADPREREADCOMMAND constant was implemented a few years ago for PIC. Works very well as this enables changes to the ADC read whilst leveraging the standard ADC commands.
There is more detail on the constant here I have just added the multiple ADC discussed as an example.
Last edit: Anobium 2021-08-29
OK that makes more sense, and understood about the general case, Thanks.
I get "0" on first read, so I believe in throwing the very first reading out in initialization as you noted.