Menu

tiny85 clock and ADC issues

Help
Joe Kirby
2021-08-22
2021-08-30
1 2 > >> (Page 1 of 2)
  • Joe Kirby

    Joe Kirby - 2021-08-22

    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.

     
  • kent_twt4

    kent_twt4 - 2021-08-22

    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.

     
  • kent_twt4

    kent_twt4 - 2021-08-22

    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.

     
    • Anobium

      Anobium - 2021-08-23

      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.

       
      • Anobium

        Anobium - 2021-08-23

        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.


        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
  • Joe Kirby

    Joe Kirby - 2021-08-28

    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?

     
  • Anobium

    Anobium - 2021-08-28

    Can you remove your patch to test. Add, the #define and post the ASM. I want to see the resulting code.

     
  • Joe Kirby

    Joe Kirby - 2021-08-28

    The .bas is only a few hundred bytes, so I have included it as well.

     
  • Anobium

    Anobium - 2021-08-28

    OK. Thank you. The code is as expected (and, as you posted). So, the constant works.

    ;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
    ;Wait AD_Delay   'Execute the acquisition Delay
      ldi SysWaitTemp10US,2
      rcall Delay_10US
    ;Set ADEN On     'Take reading
      sbi ADCSRA,ADEN
    ;Set ADSC On
      sbi ADCSRA,ADSC
    ;Wait While ADSC On
    SysWaitLoop1:
      sbic  ADCSRA,ADSC
      rjmp  SysWaitLoop1
    

    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 ADC4
    channel. 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 the
    temperature sensor measurement. When the temperature sensor is enabled, the ADC converter can be used in
    single conversion mode to measure the voltage over the temperature sensor.
    */
    #define ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0X20 ) or 0X8F
    

    Does this correct? Do test. :-)

     
  • Anobium

    Anobium - 2021-08-28

    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.

    :-)

     
  • Joe Kirby

    Joe Kirby - 2021-08-28

    Same thing, .ASM attached..
    testing without delay

     

    Last edit: Joe Kirby 2021-08-28
  • Joe Kirby

    Joe Kirby - 2021-08-28

    No difference with the 10ms settling timer.

     
  • Anobium

    Anobium - 2021-08-28

    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.

     
  • Joe Kirby

    Joe Kirby - 2021-08-28

    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

     
    • Anobium

      Anobium - 2021-08-28

      Can you leave this with me? I will get a Tiny85 operational. Look back tomorrow.

      OK?

       
  • Joe Kirby

    Joe Kirby - 2021-08-28

    Will do, thanks

     
  • Anobium

    Anobium - 2021-08-29

    @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

    #CHIP tiny85, 8
    #OPTION Explicit
    #include <softserial.h> 'include the library. this is required.
    #DEFINE ADSpeed MediumSpeed
    
    'Config Serial UART:
    #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 datasheet
    The temperature measurement is based on an on-chip temperature sensor that is coupled to a single ended ADC4
    channel. 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 the
    temperature sensor measurement. When the temperature sensor is enabled, the ADC converter can be used in
    single 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 is
    approximately 1 LSB / C and the accuracy depends on the method of user calibration. Typically, the measurement
    accuracy after a single temperature calibration is ±10C, assuming calibration at room temperature. Better
    accuracies are achieved by using two temperature points for calibration.
    */
    
    #define ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0X20 ) or 0X8F: wait 100 ms
    
    'Main program
    
      dim IntTemp as Word
      DO
          IntTemp = READAD10(ADC4)
          Ser1Print IntTemp
    
          Ser1Send 10   'send line feed to terminal
          Ser1Send 13   'send new line to terminal
          WAIT 1 S
      LOOP
    

    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.

    #chip tiny85,8
    #option explicit
    
    #define RS232Out PORTB.2
    #define RS232In  PORTB.1
    
    #define ADREADPREREADCOMMAND ADMUX = ( ADMUX and 0X20 ) or 0X8F: wait 100 ms
    
    Dir RS232Out Out
    Dir RS232In  In
    Dim unadj_tmp as word
    
    #define SendALow Set RS232Out OFF
    #define SendAHigh Set RS232Out ON
    #define RecALow Set RS232In OFF
    #define RecAHigh Set RS232In ON
    
    InitSer 1, r9600, 1+WaitForStart, 8, 1, none, normal
    
    Do
      unadj_tmp = ReadAD10(ADC4)
      SerSend 1, "A"
      SerPrint 1, str(unadj_tmp)
      SerSend 1, 13
      SerSend 1, 10
      Wait 1 S
    Loop
    

    @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
  • Joe Kirby

    Joe Kirby - 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.

     
  • Anobium

    Anobium - 2021-08-29

    @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. :-)

     
  • Anobium

    Anobium - 2021-08-29

    Just did a quick calibrate....

    Just took the board out of the freezer....

    13:55:39.122> 252   -17
    13:55:40.124> 252   -17
    13:55:41.065> 252   -17
    13:55:42.060> 254   -15
    13:55:43.057> 254   -15
    13:55:44.053> 254   -15
    13:55:45.030> 254   -15
    13:55:45.980> 254   -15
    13:55:46.997> 254   -15
    13:55:47.927> 254   -15
    13:55:48.930> 254   -15
    13:55:49.943> 255   -14
    13:55:50.883> 256   -13
    13:55:51.847> 256   -13
    13:55:52.849> 258   -12
    13:55:53.852> 262   -8
    13:55:54.822> 262   -8
    13:55:55.825> 263   -7
    13:55:56.760> 263   -7
    13:55:57.713> 263   -7
    13:55:58.731> 264   -7
    13:55:59.733> 264   -7
    13:56:00.688> 266   -5
    13:56:01.637> 264   -7
    13:56:02.639> 264   -7
    13:56:03.594> 264   -7
    13:56:04.613> 268   -3
    

    My code..

    Dim real_temp as Integer
    
    ...
    
    real_temp=scale( unadj_tmp, 250, 304, -18, 28 )  '252 is -18c and 304 is 28c
    
    ....
    
    Send real_temp to serial
    
     
  • Frank Steinberg

    Frank Steinberg - 2021-08-29

    Hi!

    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

     
    • Anobium

      Anobium - 2021-08-29

      @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!

      :-)

       
  • kent_twt4

    kent_twt4 - 2021-08-29

    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?

     
  • Anobium

    Anobium - 2021-08-29

    The example shown is a single read of the ADC4/Temp.

    Change to the following to make multiple adc inputs.

    #DEFINE ADREADPREREADCOMMAND IF ADReadPort=4 then ADMUX = ( ADMUX and 0X20 ) or 0X8F: wait 100 ms
    

    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
    • kent_twt4

      kent_twt4 - 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.

       
1 2 > >> (Page 1 of 2)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.