ATTINY102 Multiple ADC read

Go To Last Post
38 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, 

I am trying to read multiple ADC values. Based on the ADC5 value I want to turn ON or OFF an LED Connected to PA1 and based on the ADC7 value I want to turn ON or OFF a led Connected to PA0. I have read multiple posts in the forum and tried to use the solution mentioned there as well. But did not have any luck. It looks like when I run only one ADC everything works just fine but after adding the code for the second ADC, both the LEDs turn ON or OFF based on either of the ADC value change. Or change their brightness. Any suggestion on what I am doing wrong?

 

Thank you.

 

Here is my code:

 

 

  1. #include<avr/io.h>
  2. #define F_CPU 8000000UL
  3.  
  4. void adc_setup_R()
  5. {    
  6.     ADCSRA|=(1<<ADEN);      //Enable ADC 
  7.     ADMUX=0b00000101; // Select ADC5
  8.     ADCSRB=0x00;           //free running mode
  9.     ADCSRA|=(1<<ADSC)|(1<<ADATE);   //Start ADC conversion and enable Auto trigger
  10.     //while(ADCSRA & (1<<ADSC)) {}  // wait for the conversion to be complete
  11. }
  12.  
  13. void adc_setup_L()
  14. {
  15.     ADCSRA|=(1<<ADEN);      //Enable ADC 
  16.     ADMUX=0b00000111; // Select ADC7
  17.     ADCSRB=0x00;           //free running mode
  18.     ADCSRA|=(1<<ADSC)|(1<<ADATE);   //Start ADC conversion and enable Auto trigger
  19.     //while(ADCSRA & (1<<ADSC)) {}  // wait for the conversion to be complete
  20. }
  21.  
  22. int main()
  23. {
  24.  
  25. DDRA =0b00000011;         //PA0 & PA1 as output
  26.  
  27.     while(1)
  28.     {
  29.         adc_setup_R();
  30.         int adc_val_1=(ADCH<<8)|ADCL;   //ADC Read
  31.         ADCSRA|=(1<<ADIF); //clearing the ADIF flag before starting the next conversion
  32.         
  33.         
  34.         adc_setup_L(); 
  35.         int adc_val_2=(ADCH<<8)|ADCL;   //ADC Read 
  36.         ADCSRA|=(1<<ADIF);  //clearing the ADIF flag before starting the next conversion
  37.  
  38.         if (adc_val_1>=250) 
  39.         {
  40.             PORTA=0b00000010;  
  41.         }        
  42.         else        
  43.         {
  44.             PORTA =0b00000000; 
  45.         }        
  46.     
  47.         if (adc_val_2>=250) 
  48.         {
  49.             PORTA=0b00000001;  
  50.         }
  51.         else        
  52.         {
  53.             PORTA =0b00000000; 
  54.         }
  55.  
  56.     }
  57.  
  58. }

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

imtiny wrote:

 

  1.         if (adc_val_1>=250) 
  2.         {
  3.             PORTA=0b00000010;  
  4.         }        
  5.         else        
  6.         {
  7.             PORTA =0b00000000; 
  8.         }        
  9.     
  10.         if (adc_val_2>=250) 
  11.         {
  12.             PORTA=0b00000001;  
  13.         }
  14.         else        
  15.         {
  16.             PORTA =0b00000000; 
  17.         }

 

    I think your problem is that you are changing the entire PORTA register each time either PA0 or PA1 needs changed.   For example, in the second conditional statement, setting PORTA to 0b00000000 or 0b00000001 will set PA1 to zero regardless, thus overriding the value set in the first conditional statement. 

    I would set the bits individually rather than the entire port:

 

  1.  if (adc_val_1>=250) 
  2.         {
  3.             PORTA |= (1<<PA1); 
  4.         }        
  5.         else        
  6.         {
  7.             PORTA  &= ~(1<<PA1);
  8.         }        
  9.     
  10.         if (adc_val_2>=250) 
  11.         {
  12.             PORTA |= (1<<PA0); 
  13.         }
  14.         else        
  15.         {
  16.             PORTA &= ~(1<<PA0);
  17.         }

    Good luck on your project!

 

    Jarrod

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jarrod,

Thank you for your reply. I have added the change that you have mentioned but no luck, I am having the same issue.
 

Here is the new code:

 

  1. #include<avr/io.h>
  2. #define F_CPU 8000000UL
  3. void adc_setup_R()
  4. {    
  5.     ADCSRA|=(1<<ADEN);      //Enable ADC 
  6.     ADMUX=0b00000101; // Select ADC5
  7.     ADCSRB=0x00;           //free running mode
  8.     ADCSRA|=(1<<ADSC)|(1<<ADATE);   //Start ADC conversion and enable Auto trigger
  9.     //while(ADCSRA & (1<<ADSC)) {}  // wait for the conversion to be complete
  10. }
  11. void adc_setup_L()
  12. {
  13.     ADCSRA|=(1<<ADEN);      //Enable ADC 
  14.     ADMUX=0b00000111; // Select ADC7
  15.     ADCSRB=0x00;           //free running mode
  16.     ADCSRA|=(1<<ADSC)|(1<<ADATE);   //Start ADC conversion and enable Auto trigger
  17.     //while(ADCSRA & (1<<ADSC)) {}  // wait for the conversion to be complete
  18. }
  19. int main()
  20. {
  21. DDRA =0b00000011;         //PA0 & PA1 as output
  22.     while(1)
  23.     {
  24.         adc_setup_R();
  25.         int adc_val_1=(ADCH<<8)|ADCL;   //ADC Read
  26.         ADCSRA|=(1<<ADIF); //clearing the ADIF flag before starting the next conversion
  27.         
  28.         
  29.         adc_setup_L(); 
  30.         int adc_val_2=(ADCH<<8)|ADCL;   //ADC Read 
  31.         ADCSRA|=(1<<ADIF);  //clearing the ADIF flag before starting the next conversion
  32.         if (adc_val_1>=250)
  33.         {
  34.             PORTA |= (1<<PA1);
  35.         }
  36.         else
  37.         {
  38.             PORTA  &= ~(1<<PA1);
  39.         }
  40.         
  41.         if (adc_val_2>=250)
  42.         {
  43.             PORTA |= (1<<PA0);
  44.         }
  45.         else
  46.         {
  47.             PORTA &= ~(1<<PA0);
  48.         }
  49.     }
  50. }
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, you don't want free running mode, you want to set the channel, then start A conversion

 

 

    //while(ADCSRA & (1<<ADSC)) {}  // wait for the conversion to be complete

 

Note this will be True (nonzero) during the conversion (ADSC bit=1 when busy), so you need to invert the logic  while( !(ADCSRA & (1<<ADSC) ) )

 

edit:

actually since this is a loop rather than jump , you want to use the true value while waiting, to force the wait

while( (ADCSRA & (1<<ADSC) ) )

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Wed. Apr 13, 2022 - 11:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you please explain a bit more? I have made a couple of changes but it looks like I did not understand your suggestion. I have inverted this in line  8,16 :

 

  1. while( ~(ADCSRA & (1<<ADSC) ) )  

 

Also have removed the free-running mode part on line 7,15 : 

 

  1. //ADCSRB=0x00;           //free running mode

 

And I also have selected the ADC pin first and then started ADC conversion on lines 6, 8 and 14, 16:

 

 

Here is the new code:

 

  1. #include<avr/io.h>
  2. #define F_CPU 8000000UL
  3. void adc_setup_R()
  4. {    
  5.     ADCSRA|=(1<<ADEN);      //Enable ADC 
  6.     ADMUX=0b00000101; // Select ADC5
  7.     //ADCSRB=0x00;           //free running mode
  8.     ADCSRA|=(1<<ADSC)|(1<<ADATE);   //Start ADC conversion and enable Auto trigger
  9.     while (~(ADCSRA & (1<<ADSC))) {}  // wait for the conversion to be complete
  10. }
  11. void adc_setup_L()
  12. {
  13.     ADCSRA|=(1<<ADEN);      //Enable ADC 
  14.     ADMUX=0b00000111; // Select ADC7
  15.     //ADCSRB=0x00;           //free running mode
  16.     ADCSRA|=(1<<ADSC)|(1<<ADATE);   //Start ADC conversion and enable Auto trigger
  17.     while (~(ADCSRA & (1<<ADSC))) {}  // wait for the conversion to be complete
  18. }
  19. int main()
  20. {
  21. DDRA =0b00000011;         //PA0 & PA1 as output
  22.     while(1)
  23.     {
  24.         adc_setup_R();
  25.         int adc_val_1=(ADCH<<8)|ADCL;   //ADC Read
  26.         ADCSRA|=(1<<ADIF); //clearing the ADIF flag before starting the next conversion
  27.         
  28.         
  29.         adc_setup_L(); 
  30.         int adc_val_2=(ADCH<<8)|ADCL;   //ADC Read 
  31.         ADCSRA|=(1<<ADIF);  //clearing the ADIF flag before starting the next conversion
  32.         if (adc_val_1>=250)
  33.         {
  34.             PORTA |= (1<<PA1);
  35.         }
  36.         else
  37.         {
  38.             PORTA  &= ~(1<<PA1);
  39.         }
  40.         
  41.         if (adc_val_2>=250)
  42.         {
  43.             PORTA |= (1<<PA0);
  44.         }
  45.         else
  46.         {
  47.             PORTA &= ~(1<<PA0);
  48.         }
  49.     }
  50. }
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

    I built a little breadboard circuit with two potentiometers on the ADCs and toyed around with your code (with the changes I suggested), and I finally found the problem - it's the Auto Trigger!  In both of your ADC setup functions, I removed the auto trigger bit set:

ADCSRA|=(1<<ADSC)|(1<<ADATE);  //Start ADC conversion and enable Auto trigger

        is now just:

ADCSRA|=(1<<ADSC);

    I don't know why exactly that fixed the problem, though...

 

    Here's the complete working code that functioned correctly on my breadboard:

 

 

    #include<avr/io.h>
    #define F_CPU 8000000UL
    void adc_setup_R()
    {    
        ADCSRA|=(1<<ADEN);      //Enable ADC 
        ADMUX=0b00000101; // Select ADC5
        ADCSRB=0x00;           //free running mode
        ADCSRA|=(1<<ADSC);   //Start ADC conversion
        //while(ADCSRA & (1<<ADSC)) {}  // wait for the conversion to be complete
    }
    void adc_setup_L()
    {
        ADCSRA|=(1<<ADEN);      //Enable ADC 
        ADMUX=0b00000111; // Select ADC7
        ADCSRB=0x00;           //free running mode
        ADCSRA|=(1<<ADSC);   //Start ADC conversion
        //while(ADCSRA & (1<<ADSC)) {}  // wait for the conversion to be complete
    }
    int main()
    {
    DDRA =0b00000011;         //PA0 & PA1 as output
        while(1)
        {
            adc_setup_R();
            int adc_val_1=(ADCH<<8)|ADCL;   //ADC Read
            ADCSRA|=(1<<ADIF); //clearing the ADIF flag before starting the next conversion
            
            
            adc_setup_L(); 
            int adc_val_2=(ADCH<<8)|ADCL;   //ADC Read 
            ADCSRA|=(1<<ADIF);  //clearing the ADIF flag before starting the next conversion
            if (adc_val_1>=250)
            {
                PORTA |= (1<<PA1);
            }
            else
            {
                PORTA  &= ~(1<<PA1);
            }
            
            if (adc_val_2>=250)
            {
                PORTA |= (1<<PA0);
            }
            else
            {
                PORTA &= ~(1<<PA0);
            }
        }
    }

 

Jarrod

Last Edited: Tue. Apr 12, 2022 - 12:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

whoops...go back to number 2, I was thinking from your commenting out you needed to "jump out" of a forced loop, which would need to become true at that moment.  In that case you need the inversion.

With the while, being true, keeps you in the while loop until false 

while( (ADCSRA & (1<<ADSC) ) )  is correct for the while test.

 

You do not need free running /auto mode, just single conversion

set ADCSRA once as needed  (ADEN, ADPSxx as desired)   keep ADATE,ADIF, ADIE zero

ADCSRA = (1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) ; // FILL IN 0'S 1''S, divider: keep ADC<200kHz

 

each conversion:

adjust mux (ADMUX)

set ADCSRA ADSC bit to begin the conversion ADCSRA |= (1<<ADSC)

wait for ADSC bit to go low

Read ADC to get the result myval =ADC (no need to read hi & lo bytes)

that's all.

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Tue. Apr 12, 2022 - 03:44 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Jarrod,

Thanks for your suggestion. I tried your code, but sadly it still did not solve the issue. I have exactly the same setup as yours.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi  avrcandies,

I have tried your suggestion as well but still no luck. Here is the code based on your suggestion. Please correct me if I have incorrectly applied your suggestion.

 

Thanks again. 

 

 

 

 

 

Code:

 

    #include<avr/io.h>
    #define F_CPU 8000000UL
    
    void adc_setup_R()
    {
        ADMUX=0b00000101; // Select ADC5
        ADCSRA |= (1<<ADSC);
        while (!(ADCSRA & (1<<ADSC))) {}  // wait for the conversion to be complete
    }
    
    void adc_setup_L()
    {   
        ADMUX=0b00000111; // Select ADC7
        ADCSRA |= (1<<ADSC);
        while (!(ADCSRA & (1<<ADSC))) {}  // wait for the conversion to be complete
    }
    
    int main()
    {
        ADCSRA = (1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) ;
        DDRA =0b00000011;         //PA0 & PA1 as output
        while(1)
        {
            adc_setup_R();
            int adc_val_1=(ADCH<<8)|ADCL;   //ADC Read        
            
            adc_setup_L();
            int adc_val_2=(ADCH<<8)|ADCL;   //ADC Read
            
            if (adc_val_1>=500)
            {
                PORTA |= (1<<PA1);
            }
            else
            {
                PORTA  &= ~(1<<PA1);
            }
            
            if (adc_val_2>=500)
            {
                PORTA |= (1<<PA0);
            }
            else
            {
                PORTA &= ~(1<<PA0);
            }
        }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As soon as you set the bit, it is true, and will stay true until ADC finished...so you want true to keep it in the loop while true

 

So while (stay looping while this is true...)

is just

while (  ADCSRA & (1<<ADSC)   )  { doingnothing}

 

An alternative (which you are not not using) would be to detect false to leave an endless loop, such as goto or break

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Wed. Apr 13, 2022 - 11:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

imtiny wrote:
I tried your code, but sadly it still did not solve the issue. I have exactly the same setup as yours.

    Would you mind posting a schematic of your setup?  Maybe it's a hardware issue.

    Here's some code you can try.  It also works on my breadboard.  It uses a single function to setup the ADC, and a separate function adc_read() takes a reading.  The  int channel parameter is passed in, and the function reads that ADC channel.  Hope it works.  

 

 

#include <avr/io.h>
#define F_CPU 8000000UL

void adc_setup()
{
    ADCSRA |= (1<<ADEN);  // Enable ADC
    ADCSRB = 0x00;           //free running mode
    ADMUX = (1<<REFS0);
}

int adc_read(int channel)
{
    ADMUX = channel;
    ADCSRA |= (1<<ADSC);              // Start conversion
    while(! (ADCSRA & (1<<ADIF)));  // Wait for conversion to be complete
    ADCSRA |= (1<<ADIF);              // Clear ADIF flag before the next conversion
    return (ADC);
}

int main()
{
    DDRA = 0b00000011;         //PA0 & PA1 as output
    adc_setup();
    while(1)
    {
        int adc_val_1 = adc_read(0b00000101);  // Read ADC5
        int adc_val_2 = adc_read(0b00000111);  // Read ADC7

        if (adc_val_1 >= 250)
        {
            PORTA |= (1<<PA1);
        }
        else
        {
            PORTA  &= ~(1<<PA1);
        }

        if (adc_val_2 >= 250)
        {
            PORTA |= (1<<PA0);
        }
        else
        {
            PORTA &= ~(1<<PA0);
        }
    }
}

 

Jarrod

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can look at bit ADSC bit, no t need to do anything

ADSC will read as one as long as a conversion is in progress. When the conversion is complete, it returns to zero

 

uint16_t adc_read(uint8_t  channel)
{
    ADMUX = (ADMUX & 0xF0) | (channel & 0x0F) ;  //kill old channel selectors, KEEP other ref bits, add in channel bits

    ADCSRA |= (1<<ADSC);              // Start conversion
    while(ADCSRA & (1<<ADSC));  // Wait for conversion to be complete (ADSC bit=1, while waiting)
    return (ADC);
}

 

Also you should preferably use uint16_t  ,not int

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Apr 16, 2022 - 04:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Jarro,

First of all, thanks a lot for still staying in the loop and for all of your helpful suggestions and sample code, I really appreciate it smiley. I have included my circuit diagram below. Regarding your code, do I need to add any library for the "ADC"  because in your code you have added the line:

 

  1. return (ADC);

 

If I build the code I get an error:

 

 

As it's an undeclared variable I thought that I might be missing a library.

 

But later I just created a variable just underneath the "while (!" line:

 

  1. int adc_read(int channel)
  2. {
  3.     ADMUX = channel;
  4.     ADCSRA |= (1<<ADSC);              // Start conversion
  5.     while(! (ADCSRA & (1<<ADIF)));  // Wait for conversion to be complete
  6.     uint16_t ADC= (ADCH<<8)|ADCL;
  7.     ADCSRA |= (1<<ADIF);              // Clear ADIF flag before the next conversion
  8.     return (ADC);

 

But no luck.

 

Thanks again, Here is the circuit diagram:

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello avrcandies,

Thanks again for the suggestion. I have changed all the "int" variables to "uint8_t" and tried your version of the adc_read() loop but still no luck. Would it be possible to share your complete code for the ATTIMy102 ADC program?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

You need to show your code, so it is easy to see the latest...note the adc value will be 16 bits (uint16_t) not 8

also, what do you mean "doesn't work"

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Apr 18, 2022 - 12:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks. 

what do you mean "doesn't work"

 

Does not matter what value I choose for "adc_val_1" or "adc_val_2". The LED only turns ON at 15mV or above. I have replaced the "RX1", "RX2" & "RX3" with 100k potentiometers. So it's a basic voltage divider.

 

Here is the latest code:
 

 

 

  1. #include <avr/io.h>
  2. #define F_CPU 8000000UL
  3. void adc_setup()
  4. {
  5.     ADCSRA |= (1<<ADEN);  // Enable ADC
  6.     ADCSRB = 0x00;        //free running mode
  7.     ADMUX = (1<<REFS0);
  8. }
  9. uint16_t adc_read(uint8_t  channel)
  10. {
  11.     ADMUX = (ADMUX & 0xF0) | (channel & 0x0F) ;  //kill old channel selectors, KEEP other ref bits, add in channel bits
  12.     ADCSRA |= (1<<ADSC);              // Start conversion            // Start conversion
  13.     while(ADCSRA & (1<<ADSC));  // Wait for conversion to be complete (ADSC bit=1, while waiting)
  14.     uint16_t ADC= (ADCL<<8)|ADCH;
  15.     ADCSRA |= (1<<ADIF);              // Clear ADIF flag before the next conversion
  16.     return (ADC);    
  17. }
  18. int main()
  19. {
  20.     DDRA = 0b00000011;         //PA0 & PA1 as output
  21.     adc_setup();
  22.     while(1)
  23.     {
  24.         uint16_t adc_val_1 = adc_read(0b00000101);  // Read ADC5
  25.         uint16_t adc_val_2 = adc_read(0b00000111);  // Read ADC7
  26. if (adc_val_1 >= 1000)
  27.         {
  28.             PORTA |= (1<<PA1);
  29.         }
  30.         else
  31.         {
  32.             PORTA  &= ~(1<<PA1);
  33.         }
  34.         if (adc_val_2 >= 1000)
  35.         {
  36.             PORTA |= (1<<PA0);
  37.         }
  38.         else
  39.         {
  40.             PORTA &= ~(1<<PA0);
  41.         }
  42.     }
  43. }

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are doing yourself a huge disservice drawing in such a haphazard manner.  Show your chip and what it connects to.  This is not some huge schematic that requires you to break off different pieces due to lack of room or due to extreme complexity.  You merely ended up with a big scattering like a car wreck.  Drawing up connections to an 8 pin chip is about as basic as it comes and show be both clear and straightforward.  Here is an example I spent about 7 minutes throwing together.  

Note you can look at it and IMMEDIATELY can see EXACTLY how things are connected.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Apr 18, 2022 - 12:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  1. uint16_t ADC= (ADCL<<8)|ADCH;
  2.     ADCSRA |= (1<<ADIF);              // Clear ADIF flag before the next conversion

 

Get rid of these lines completely (note you read the ADC at your return statement)  ADIF is not used at all.

 

The schematic is so unreadable, it is not clear how you are applying any voltage if all the pins are hooked to leds and fets.  Do you have a pot hooked to a pin?  where?

Make sure to use a multimeter at the ADC pine and gnd ...you are close to having it work!

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Apr 18, 2022 - 12:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks. Here is the current version of the schematic that represents the current setup. I am powering the circuit with the AVRISP Mkll Programmer. 

 

 

 

If I remove this line from the code: 
 

  1. uint16_t ADC= (ADCL<<8)|ADCH;

 

I get this error: 

 

 

That's why I asked previously if I need to add a library to use the keyword "ADC".

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I get this error: 

Where?  What line?  I believe ADC is the correct name for the combined register pair.

 I believe you just need to say return ADC  ...check for editing goofs

 

someone else seems to be doing similar

https://www.avrfreaks.net/forum/...

 

you schematic looks somewhat better now!

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Apr 18, 2022 - 01:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Its on Line 13:

 

  1. #include <avr/io.h>
  2. #define F_CPU 8000000UL
  3. void adc_setup()
  4. {
  5.     ADCSRA |= (1<<ADEN);  // Enable ADC
  6.     ADCSRB = 0x00;        //free running mode
  7.     ADMUX = (1<<REFS0);
  8. }
  9. uint16_t adc_read(uint8_t  channel)
  10. {
  11.     ADMUX = (ADMUX & 0xF0) | (channel & 0x0F) ;  //kill old channel selectors, KEEP other ref bits, add in channel bits
  12.     ADCSRA |= (1<<ADSC);              // Start conversion            // Start conversion
  13.     return ADC;    
  14. }
  15. int main()
  16. {
  17.     DDRA = 0b00000011;         //PA0 & PA1 as output
  18.     adc_setup();
  19.     while(1)
  20.     {
  21.         uint16_t adc_val_1 = adc_read(0b00000101);  // Read ADC5
  22.         uint16_t adc_val_2 = adc_read(0b00000111);  // Read ADC7
  23. if (adc_val_1 >= 1000)
  24.         {
  25.             PORTA |= (1<<PA1);
  26.         }
  27.         else
  28.         {
  29.             PORTA  &= ~(1<<PA1);
  30.         }
  31.         if (adc_val_2 >= 1000)
  32.         {
  33.             PORTA |= (1<<PA0);
  34.         }
  35.         else
  36.         {
  37.             PORTA &= ~(1<<PA0);
  38.         }
  39.     }
  40. }
Last Edited: Mon. Apr 18, 2022 - 01:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried both 

return ADC;

and 

 

return (ADC);

But in both cases I get the same error on line 13:

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

imtiny wrote:
But in both cases I get the same error on line 13:

Please post your chip-include file that your AVR/IO.H invokes.  What is the file name?  What ADC info is therein? 

 

Toolchain?  Version?  Complete build sequence log?  (i.e. not just those error messages -- invocation sequence at least)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


On a different note, what value is your pot?  Normally you might just bring out only the wiper and have no 10K resistor  (going from 0 to Avcc).  If the pot value isn't very compatible with 10k, you may get very little change of voltage (if using the 1.1 internal Vref, that may be ok; if you want to go to Avcc, you won't get there). A 10K pot with your setup would go from 0 to halfway, which is mostly fine for the internal 1.1V ref.

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your reply. I only was able to locate the " build sequence log ", where do I get the other information?

Here is the complete build log:
 

------ Build started: Project: line_follower_robot_v1, Configuration: Debug AVR ------
Build started.
Project "line_follower_robot_v1.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "C:\Users\Documents\Atmel Studio\7.0\line_follower_robot_v1\line_follower_robot_v1\line_follower_robot_v1.cproj" (target "Build" depends on it):
    Task "RunCompilerTask"
        Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
        C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe all --jobs 8 --output-sync 
        Building file: .././main.c
        Invoking: AVR/GNU C Compiler : 5.4.0
        .././main.c: In function 'adc_read':
C:\Users\Documents\Atmel Studio\7.0\line_follower_robot_v1\line_follower_robot_v1\main.c(15,12): error: 'ADC' undeclared (first use in this function)
             return ADC; 
                    ^
C:\Users\Documents\Atmel Studio\7.0\line_follower_robot_v1\line_follower_robot_v1\main.c(15,12): info: each undeclared identifier is reported only once for each function it appears in
C:\Users\Documents\Atmel Studio\7.0\line_follower_robot_v1\line_follower_robot_v1\main.c(16,1): warning: control reaches end of non-void function [-Wreturn-type]
         }
         ^
        make: *** [main.o] Error 1
        "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\include"  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=attiny102 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny102" -c -std=gnu99 -MD -MP -MF "main.d" -MT"main.d" -MT"main.o"   -o "main.o" ".././main.c" 
C:\Users\Documents\Atmel Studio\7.0\line_follower_robot_v1\line_follower_robot_v1\Debug\Makefile(76,1): error: recipe for target 'main.o' failed
    Done executing task "RunCompilerTask" -- FAILED.
Done building target "CoreBuild" in project "line_follower_robot_v1.cproj" -- FAILED.
Done building project "line_follower_robot_v1.cproj" -- FAILED.

Build FAILED.
========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi thanks, I am using a 100K pot. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


It appears some scoundrel has forgotten or removed ADC from the tiny102 pak definitions!  In that case, read and combine ADCL & ADCH.  You must ensure the code reads them in the correct order (I don't recall which one needs read first).

 

Also 100K not super good...you see 0 to 20 k knobbing gets you 70% of the way

 

If the pot is 10K, you get    2K is straighter, but you don't go as high 

 

 Using wiper direct is needed if you want to get to 100% 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Apr 18, 2022 - 08:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Do you see something like the above after you build your project?   After you build, what Dependencies do you see?  io.h?  iotn102.h perhaps?  Do you see in io.h where your particular chip-include file is invoked?  When you look into that file, what items do you see that are ADC-related? 

 

When I look at this copy

https://github.com/microchip-pic...

indeed I see no _SFR_IO16 entries.  The GCC gurus will need to help clarify.  I'm sure the person that sent you on the snip hunt verified the information before posting.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Mon. Apr 18, 2022 - 08:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you.

 

In the "io. h" file there is nothing related to ADC (I used the ctrl+F to search the keyword ADC). In the "iotn102.h" file there are several mentions of ADC that includes the "ADCL" and "ADCH" but not the barebone "ADC". I have included both the content of the files below:

Here is the "io.h" file:

 

/* Copyright (c) 2002,2003,2005,2006,2007 Marek Michalkiewicz, Joerg Wunsch
   Copyright (c) 2007 Eric B. Weddington
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.

   * Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.

   * Neither the name of the copyright holders nor the names of
     contributors may be used to endorse or promote products derived
     from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE. */

/* $Id$ */

/** \file */
/** \defgroup avr_io <avr/io.h>: AVR device-specific IO definitions
    \code #include <avr/io.h> \endcode

    This header file includes the apropriate IO definitions for the
    device that has been specified by the <tt>-mmcu=</tt> compiler
    command-line switch.  This is done by diverting to the appropriate
    file <tt>&lt;avr/io</tt><em>XXXX</em><tt>.h&gt;</tt> which should
    never be included directly.  Some register names common to all
    AVR devices are defined directly within <tt>&lt;avr/common.h&gt;</tt>,
    which is included in <tt>&lt;avr/io.h&gt;</tt>,
    but most of the details come from the respective include file.

    Note that this file always includes the following files:
    \code 
    #include <avr/sfr_defs.h>
    #include <avr/portpins.h>
    #include <avr/common.h>
    #include <avr/version.h>
    \endcode
    See \ref avr_sfr for more details about that header file.

    Included are definitions of the IO register set and their
    respective bit values as specified in the Atmel documentation.
    Note that inconsistencies in naming conventions,
    so even identical functions sometimes get different names on
    different devices.

    Also included are the specific names useable for interrupt
    function definitions as documented
    \ref avr_signames "here".

    Finally, the following macros are defined:

    - \b RAMEND
    <br>
    The last on-chip RAM address.
    <br>
    - \b XRAMEND
    <br>
    The last possible RAM location that is addressable. This is equal to 
    RAMEND for devices that do not allow for external RAM. For devices 
    that allow external RAM, this will be larger than RAMEND.
    <br>
    - \b E2END
    <br>
    The last EEPROM address.
    <br>
    - \b FLASHEND
    <br>
    The last byte address in the Flash program space.
    <br>
    - \b SPM_PAGESIZE
    <br>
    For devices with bootloader support, the flash pagesize
    (in bytes) to be used for the \c SPM instruction. 
    - \b E2PAGESIZE
    <br>
    The size of the EEPROM page.
    
*/

#ifndef _AVR_IO_H_
#define _AVR_IO_H_

#include <avr/sfr_defs.h>

#if defined (__AVR_AT94K__)
#  include <avr/ioat94k.h>
#elif defined (__AVR_AT43USB320__)
#  include <avr/io43u32x.h>
#elif defined (__AVR_AT43USB355__)
#  include <avr/io43u35x.h>
#elif defined (__AVR_AT76C711__)
#  include <avr/io76c711.h>
#elif defined (__AVR_AT86RF401__)
#  include <avr/io86r401.h>
#elif defined (__AVR_AT90PWM1__)
#  include <avr/io90pwm1.h>
#elif defined (__AVR_AT90PWM2__)
#  include <avr/io90pwmx.h>
#elif defined (__AVR_AT90PWM2B__)
#  include <avr/io90pwm2b.h>
#elif defined (__AVR_AT90PWM3__)
#  include <avr/io90pwmx.h>
#elif defined (__AVR_AT90PWM3B__)
#  include <avr/io90pwm3b.h>
#elif defined (__AVR_AT90PWM216__)
#  include <avr/io90pwm216.h>
#elif defined (__AVR_AT90PWM316__)
#  include <avr/io90pwm316.h>
#elif defined (__AVR_AT90PWM161__)
#  include <avr/io90pwm161.h>
#elif defined (__AVR_AT90PWM81__)
#  include <avr/io90pwm81.h>
#elif defined (__AVR_ATmega8U2__)
#  include <avr/iom8u2.h>
#elif defined (__AVR_ATmega16M1__)
#  include <avr/iom16m1.h>
#elif defined (__AVR_ATmega16U2__)
#  include <avr/iom16u2.h>
#elif defined (__AVR_ATmega16U4__)
#  include <avr/iom16u4.h>
#elif defined (__AVR_ATmega32C1__)
#  include <avr/iom32c1.h>
#elif defined (__AVR_ATmega32M1__)
#  include <avr/iom32m1.h>
#elif defined (__AVR_ATmega32U2__)
#  include <avr/iom32u2.h>
#elif defined (__AVR_ATmega32U4__)
#  include <avr/iom32u4.h>
#elif defined (__AVR_ATmega32U6__)
#  include <avr/iom32u6.h>
#elif defined (__AVR_ATmega64C1__)
#  include <avr/iom64c1.h>
#elif defined (__AVR_ATmega64M1__)
#  include <avr/iom64m1.h>
#elif defined (__AVR_ATmega128__)
#  include <avr/iom128.h>
#elif defined (__AVR_ATmega128A__)
#  include <avr/iom128a.h>
#elif defined (__AVR_ATmega1280__)
#  include <avr/iom1280.h>
#elif defined (__AVR_ATmega1281__)
#  include <avr/iom1281.h>
#elif defined (__AVR_ATmega1284__)
#  include <avr/iom1284.h>
#elif defined (__AVR_ATmega1284P__)
#  include <avr/iom1284p.h>
#elif defined (__AVR_ATmega128RFA1__)
#  include <avr/iom128rfa1.h>
#elif defined (__AVR_ATmega1284RFR2__)
#  include <avr/iom1284rfr2.h>
#elif defined (__AVR_ATmega128RFR2__)
#  include <avr/iom128rfr2.h>
#elif defined (__AVR_ATmega2564RFR2__)
#  include <avr/iom2564rfr2.h>
#elif defined (__AVR_ATmega256RFR2__)
#  include <avr/iom256rfr2.h>
#elif defined (__AVR_ATmega2560__)
#  include <avr/iom2560.h>
#elif defined (__AVR_ATmega2561__)
#  include <avr/iom2561.h>
#elif defined (__AVR_AT90CAN32__)
#  include <avr/iocan32.h>
#elif defined (__AVR_AT90CAN64__)
#  include <avr/iocan64.h>
#elif defined (__AVR_AT90CAN128__)
#  include <avr/iocan128.h>
#elif defined (__AVR_AT90USB82__)
#  include <avr/iousb82.h>
#elif defined (__AVR_AT90USB162__)
#  include <avr/iousb162.h>
#elif defined (__AVR_AT90USB646__)
#  include <avr/iousb646.h>
#elif defined (__AVR_AT90USB647__)
#  include <avr/iousb647.h>
#elif defined (__AVR_AT90USB1286__)
#  include <avr/iousb1286.h>
#elif defined (__AVR_AT90USB1287__)
#  include <avr/iousb1287.h>
#elif defined (__AVR_ATmega644RFR2__)
#  include <avr/iom644rfr2.h>
#elif defined (__AVR_ATmega64RFR2__)
#  include <avr/iom64rfr2.h>
#elif defined (__AVR_ATmega64__)
#  include <avr/iom64.h>
#elif defined (__AVR_ATmega64A__)
#  include <avr/iom64a.h>
#elif defined (__AVR_ATmega640__)
#  include <avr/iom640.h>
#elif defined (__AVR_ATmega644__)
#  include <avr/iom644.h>
#elif defined (__AVR_ATmega644A__)
#  include <avr/iom644a.h>
#elif defined (__AVR_ATmega644P__)
#  include <avr/iom644p.h>
#elif defined (__AVR_ATmega644PA__)
#  include <avr/iom644pa.h>
#elif defined (__AVR_ATmega645__)
#  include <avr/iom645.h>
#elif (defined __AVR_ATmega645A__)
#include <avr/iom645a.h>
#elif (defined __AVR_ATmega645P__)
#include <avr/iom645p.h>
#elif defined (__AVR_ATmega6450__)
#  include <avr/iom6450.h>
#elif (defined __AVR_ATmega6450A__)
#include <avr/iom6450a.h>
#elif (defined __AVR_ATmega6450P__)
#include <avr/iom6450p.h>
#elif defined (__AVR_ATmega649__)
#  include <avr/iom649.h>
#elif (defined __AVR_ATmega649A__)
#include <avr/iom649a.h>
#elif defined (__AVR_ATmega6490__)
#  include <avr/iom6490.h>
#elif (defined __AVR_ATmega6490A__)
#include <avr/iom6490a.h>
#elif (defined __AVR_ATmega6490P__)
#include <avr/iom6490p.h>
#elif defined (__AVR_ATmega649P__)
#  include <avr/iom649p.h>
#elif defined (__AVR_ATmega64HVE__)
#  include <avr/iom64hve.h>
#elif defined (__AVR_ATmega64HVE2__)
#  include <avr/iom64hve2.h>
#elif defined (__AVR_ATmega103__)
#  include <avr/iom103.h>
#elif defined (__AVR_ATmega32__)
#  include <avr/iom32.h>
#elif defined (__AVR_ATmega32A__)
#  include <avr/iom32a.h>
#elif defined (__AVR_ATmega323__)
#  include <avr/iom323.h>
#elif defined (__AVR_ATmega324P__)
#  include <avr/iom324p.h>
#elif (defined __AVR_ATmega324A__)
#include <avr/iom324a.h>
#elif defined (__AVR_ATmega324PA__)
#  include <avr/iom324pa.h>
#elif defined (__AVR_ATmega325__)
#  include <avr/iom325.h>
#elif (defined __AVR_ATmega325A__)
#include <avr/iom325a.h>
#elif defined (__AVR_ATmega325P__)
#  include <avr/iom325p.h>
#elif defined (__AVR_ATmega325PA__)
#  include <avr/iom325pa.h>  
#elif defined (__AVR_ATmega3250__) 
#  include <avr/iom3250.h>
#elif (defined __AVR_ATmega3250A__)
#include <avr/iom3250a.h>
#elif defined (__AVR_ATmega3250P__)
#  include <avr/iom3250p.h>
#elif defined (__AVR_ATmega3250PA__)
#  include <avr/iom3250pa.h>  
#elif defined (__AVR_ATmega328P__)
#  include <avr/iom328p.h>
#elif (defined __AVR_ATmega328__)
#include <avr/iom328.h>
#elif defined (__AVR_ATmega329__)
#  include <avr/iom329.h>
#elif (defined __AVR_ATmega329A__)
#include <avr/iom329a.h>
#elif defined (__AVR_ATmega329P__) 
#  include <avr/iom329p.h>
#elif (defined __AVR_ATmega329PA__)
#include <avr/iom329pa.h>
#elif (defined __AVR_ATmega3290PA__)
#include <avr/iom3290pa.h>
#elif defined (__AVR_ATmega3290__)
#  include <avr/iom3290.h>
#elif (defined __AVR_ATmega3290A__)
#include <avr/iom3290a.h>
#elif defined (__AVR_ATmega3290P__)
#  include <avr/iom3290.h>
#elif defined (__AVR_ATmega32HVB__)
#  include <avr/iom32hvb.h>
#elif defined (__AVR_ATmega32HVBREVB__)
#  include <avr/iom32hvbrevb.h>
#elif defined (__AVR_ATmega406__)
#  include <avr/iom406.h>
#elif defined (__AVR_ATmega16__)
#  include <avr/iom16.h>
#elif defined (__AVR_ATmega16A__)
#  include <avr/iom16a.h>
#elif defined (__AVR_ATmega161__)
#  include <avr/iom161.h>
#elif defined (__AVR_ATmega162__)
#  include <avr/iom162.h>
#elif defined (__AVR_ATmega163__)
#  include <avr/iom163.h>
#elif defined (__AVR_ATmega164P__)
#  include <avr/iom164p.h>
#elif (defined __AVR_ATmega164A__)
#include <avr/iom164a.h>
#elif defined (__AVR_ATmega164PA__)
#  include <avr/iom164pa.h>
#elif defined (__AVR_ATmega165__)
#  include <avr/iom165.h>
#elif defined (__AVR_ATmega165A__)
#  include <avr/iom165a.h>
#elif defined (__AVR_ATmega165P__)
#  include <avr/iom165p.h>
#elif defined (__AVR_ATmega165PA__)
#  include <avr/iom165pa.h>
#elif defined (__AVR_ATmega168__)
#  include <avr/iom168.h>
#elif defined (__AVR_ATmega168A__)
#  include <avr/iom168a.h>
#elif defined (__AVR_ATmega168P__)
#  include <avr/iom168p.h>
#elif defined (__AVR_ATmega168PA__)
#  include <avr/iom168pa.h>
#elif defined (__AVR_ATmega168PB__)
#  include <avr/iom168pb.h>
#elif defined (__AVR_ATmega169__)
#  include <avr/iom169.h>
#elif (defined __AVR_ATmega169A__)
#include <avr/iom169a.h>
#elif defined (__AVR_ATmega169P__)
#  include <avr/iom169p.h>
#elif defined (__AVR_ATmega169PA__)
#  include <avr/iom169pa.h>
#elif defined (__AVR_ATmega8HVA__)
#  include <avr/iom8hva.h>
#elif defined (__AVR_ATmega16HVA__)
#  include <avr/iom16hva.h>
#elif defined (__AVR_ATmega16HVA2__)
#  include <avr/iom16hva2.h>
#elif defined (__AVR_ATmega16HVB__)
#  include <avr/iom16hvb.h>
#elif defined (__AVR_ATmega16HVBREVB__)
#  include <avr/iom16hvbrevb.h>
#elif defined (__AVR_ATmega8__)
#  include <avr/iom8.h>
#elif defined (__AVR_ATmega8A__)
#  include <avr/iom8a.h>
#elif defined (__AVR_ATmega48__)
#  include <avr/iom48.h>
#elif defined (__AVR_ATmega48A__)
#  include <avr/iom48a.h>
#elif defined (__AVR_ATmega48PA__)
#  include <avr/iom48pa.h>
#elif defined (__AVR_ATmega48PB__)
#  include <avr/iom48pb.h>
#elif defined (__AVR_ATmega48P__)
#  include <avr/iom48p.h>
#elif defined (__AVR_ATmega88__)
#  include <avr/iom88.h>
#elif defined (__AVR_ATmega88A__)
#  include <avr/iom88a.h>
#elif defined (__AVR_ATmega88P__)
#  include <avr/iom88p.h>
#elif defined (__AVR_ATmega88PA__)
#  include <avr/iom88pa.h>
#elif defined (__AVR_ATmega88PB__)
#  include <avr/iom88pb.h>
#elif defined (__AVR_ATmega8515__)
#  include <avr/iom8515.h>
#elif defined (__AVR_ATmega8535__)
#  include <avr/iom8535.h>
#elif defined (__AVR_AT90S8535__)
#  include <avr/io8535.h>
#elif defined (__AVR_AT90C8534__)
#  include <avr/io8534.h>
#elif defined (__AVR_AT90S8515__)
#  include <avr/io8515.h>
#elif defined (__AVR_AT90S4434__)
#  include <avr/io4434.h>
#elif defined (__AVR_AT90S4433__)
#  include <avr/io4433.h>
#elif defined (__AVR_AT90S4414__)
#  include <avr/io4414.h>
#elif defined (__AVR_ATtiny22__)
#  include <avr/iotn22.h>
#elif defined (__AVR_ATtiny26__)
#  include <avr/iotn26.h>
#elif defined (__AVR_AT90S2343__)
#  include <avr/io2343.h>
#elif defined (__AVR_AT90S2333__)
#  include <avr/io2333.h>
#elif defined (__AVR_AT90S2323__)
#  include <avr/io2323.h>
#elif defined (__AVR_AT90S2313__)
#  include <avr/io2313.h>
#elif defined (__AVR_ATtiny4__)
#  include <avr/iotn4.h>
#elif defined (__AVR_ATtiny5__)
#  include <avr/iotn5.h>
#elif defined (__AVR_ATtiny9__)
#  include <avr/iotn9.h>
#elif defined (__AVR_ATtiny10__)
#  include <avr/iotn10.h>
#elif defined (__AVR_ATtiny20__)
#  include <avr/iotn20.h>
#elif defined (__AVR_ATtiny40__)
#  include <avr/iotn40.h>
#elif defined (__AVR_ATtiny2313__)
#  include <avr/iotn2313.h>
#elif defined (__AVR_ATtiny2313A__)
#  include <avr/iotn2313a.h>
#elif defined (__AVR_ATtiny13__)
#  include <avr/iotn13.h>
#elif defined (__AVR_ATtiny13A__)
#  include <avr/iotn13a.h>
#elif defined (__AVR_ATtiny25__)
#  include <avr/iotn25.h>
#elif defined (__AVR_ATtiny4313__)
#  include <avr/iotn4313.h>
#elif defined (__AVR_ATtiny45__)
#  include <avr/iotn45.h>
#elif defined (__AVR_ATtiny85__)
#  include <avr/iotn85.h>
#elif defined (__AVR_ATtiny24__)
#  include <avr/iotn24.h>
#elif defined (__AVR_ATtiny24A__)
#  include <avr/iotn24a.h>
#elif defined (__AVR_ATtiny44__)
#  include <avr/iotn44.h>
#elif defined (__AVR_ATtiny44A__)
#  include <avr/iotn44a.h>
#elif defined (__AVR_ATtiny441__)
#  include <avr/iotn441.h>
#elif defined (__AVR_ATtiny84__)
#  include <avr/iotn84.h>
#elif defined (__AVR_ATtiny84A__)
#  include <avr/iotn84a.h> 
#elif defined (__AVR_ATtiny841__)
#  include <avr/iotn841.h> 
#elif defined (__AVR_ATtiny261__)
#  include <avr/iotn261.h>
#elif defined (__AVR_ATtiny261A__)
#  include <avr/iotn261a.h>
#elif defined (__AVR_ATtiny461__)
#  include <avr/iotn461.h>
#elif defined (__AVR_ATtiny461A__)
#  include <avr/iotn461a.h>
#elif defined (__AVR_ATtiny861__)
#  include <avr/iotn861.h>
#elif defined (__AVR_ATtiny861A__)
#  include <avr/iotn861a.h>
#elif defined (__AVR_ATtiny43U__)
#  include <avr/iotn43u.h>
#elif defined (__AVR_ATtiny48__)
#  include <avr/iotn48.h>
#elif defined (__AVR_ATtiny88__)
#  include <avr/iotn88.h>
#elif defined (__AVR_ATtiny828__)
#  include <avr/iotn828.h>
#elif defined (__AVR_ATtiny87__)
#  include <avr/iotn87.h>
#elif defined (__AVR_ATtiny167__)
#  include <avr/iotn167.h>
#elif defined (__AVR_ATtiny1634__)
#  include <avr/iotn1634.h>
#elif defined (__AVR_AT90SCR100__)
#  include <avr/io90scr100.h>
#elif defined (__AVR_ATxmega8E5__)
#  include <avr/iox8e5.h>
#elif defined (__AVR_ATxmega16A4__)
#  include <avr/iox16a4.h>
#elif defined (__AVR_ATxmega16A4U__)
#  include <avr/iox16a4u.h>
#elif defined (__AVR_ATxmega16C4__)
#  include <avr/iox16c4.h>
#elif defined (__AVR_ATxmega16D4__)
#  include <avr/iox16d4.h>
#elif defined (__AVR_ATxmega16E5__)
#  include <avr/iox16e5.h>
#elif defined (__AVR_ATxmega32A4__)
#  include <avr/iox32a4.h>
#elif defined (__AVR_ATxmega32A4U__)
#  include <avr/iox32a4u.h>
#elif defined (__AVR_ATxmega32C3__)
#  include <avr/iox32c3.h>
#elif defined (__AVR_ATxmega32C4__)
#  include <avr/iox32c4.h>
#elif defined (__AVR_ATxmega32D3__)
#  include <avr/iox32d3.h>
#elif defined (__AVR_ATxmega32D4__)
#  include <avr/iox32d4.h>
#elif defined (__AVR_ATxmega32E5__)
#  include <avr/iox32e5.h>
#elif defined (__AVR_ATxmega64A1__)
#  include <avr/iox64a1.h>
#elif defined (__AVR_ATxmega64A1U__)
#  include <avr/iox64a1u.h>
#elif defined (__AVR_ATxmega64A3__)
#  include <avr/iox64a3.h>
#elif defined (__AVR_ATxmega64A3U__)
#  include <avr/iox64a3u.h>
#elif defined (__AVR_ATxmega64A4U__)
#  include <avr/iox64a4u.h>
#elif defined (__AVR_ATxmega64B1__)
#  include <avr/iox64b1.h>
#elif defined (__AVR_ATxmega64B3__)
#  include <avr/iox64b3.h>
#elif defined (__AVR_ATxmega64C3__)
#  include <avr/iox64c3.h>
#elif defined (__AVR_ATxmega64D3__)
#  include <avr/iox64d3.h>
#elif defined (__AVR_ATxmega64D4__)
#  include <avr/iox64d4.h>
#elif defined (__AVR_ATxmega128A1__)
#  include <avr/iox128a1.h>
#elif defined (__AVR_ATxmega128A1U__)
#  include <avr/iox128a1u.h>
#elif defined (__AVR_ATxmega128A4U__)
#  include <avr/iox128a4u.h>
#elif defined (__AVR_ATxmega128A3__)
#  include <avr/iox128a3.h>
#elif defined (__AVR_ATxmega128A3U__)
#  include <avr/iox128a3u.h>
#elif defined (__AVR_ATxmega128B1__)
#  include <avr/iox128b1.h>
#elif defined (__AVR_ATxmega128B3__)
#  include <avr/iox128b3.h>
#elif defined (__AVR_ATxmega128C3__)
#  include <avr/iox128c3.h>
#elif defined (__AVR_ATxmega128D3__)
#  include <avr/iox128d3.h>
#elif defined (__AVR_ATxmega128D4__)
#  include <avr/iox128d4.h>
#elif defined (__AVR_ATxmega192A3__)
#  include <avr/iox192a3.h>
#elif defined (__AVR_ATxmega192A3U__)
#  include <avr/iox192a3u.h>
#elif defined (__AVR_ATxmega192C3__)
#  include <avr/iox192c3.h>
#elif defined (__AVR_ATxmega192D3__)
#  include <avr/iox192d3.h>
#elif defined (__AVR_ATxmega256A3__)
#  include <avr/iox256a3.h>
#elif defined (__AVR_ATxmega256A3U__)
#  include <avr/iox256a3u.h>
#elif defined (__AVR_ATxmega256A3B__)
#  include <avr/iox256a3b.h>
#elif defined (__AVR_ATxmega256A3BU__)
#  include <avr/iox256a3bu.h>
#elif defined (__AVR_ATxmega256C3__)
#  include <avr/iox256c3.h>
#elif defined (__AVR_ATxmega256D3__)
#  include <avr/iox256d3.h>
#elif defined (__AVR_ATxmega384C3__)
#  include <avr/iox384c3.h>
#elif defined (__AVR_ATxmega384D3__)
#  include <avr/iox384d3.h>
#elif defined (__AVR_ATA5702M322__)
#  include <avr/ioa5702m322.h>
#elif defined (__AVR_ATA5782__)
#  include <avr/ioa5782.h>
#elif defined (__AVR_ATA5790__)
#  include <avr/ioa5790.h>
#elif defined (__AVR_ATA5790N__)
#  include <avr/ioa5790n.h>
#elif defined (__AVR_ATA5791__)
#  include <avr/ioa5791.h>
#elif defined (__AVR_ATA5831__)
#  include <avr/ioa5831.h>
#elif defined (__AVR_ATA5272__)
#  include <avr/ioa5272.h>
#elif defined (__AVR_ATA5505__)
#  include <avr/ioa5505.h>
#elif defined (__AVR_ATA5795__)
#  include <avr/ioa5795.h>
#elif defined (__AVR_ATA6285__)
#  include <avr/ioa6285.h>
#elif defined (__AVR_ATA6286__)
#  include <avr/ioa6286.h>
#elif defined (__AVR_ATA6289__)
#  include <avr/ioa6289.h>
#elif defined (__AVR_ATA6612C__)
#  include <avr/ioa6612c.h>
#elif defined (__AVR_ATA6613C__)
#  include <avr/ioa6613c.h>
#elif defined (__AVR_ATA6614Q__)
#  include <avr/ioa6614q.h>
#elif defined (__AVR_ATA6616C__)
#  include <avr/ioa6616c.h>
#elif defined (__AVR_ATA6617C__)
#  include <avr/ioa6617c.h>
#elif defined (__AVR_ATA664251__)
#  include <avr/ioa664251.h>
#elif defined (__AVR_ATA8210__)
#  include <avr/ioa8210.h>
#elif defined (__AVR_ATA8510__)
#  include <avr/ioa8510.h>
/* avr1: the following only supported for assembler programs */
#elif defined (__AVR_ATtiny28__)
#  include <avr/iotn28.h>
#elif defined (__AVR_AT90S1200__)
#  include <avr/io1200.h>
#elif defined (__AVR_ATtiny15__)
#  include <avr/iotn15.h>
#elif defined (__AVR_ATtiny12__)
#  include <avr/iotn12.h>
#elif defined (__AVR_ATtiny11__)
#  include <avr/iotn11.h>
#elif defined (__AVR_M3000__)
#  include <avr/iom3000.h>
#elif defined (__AVR_DEV_LIB_NAME__)
#  define __concat__(a,b) a##b
#  define __header1__(a,b) __concat__(a,b)
#  define __AVR_DEVICE_HEADER__ <avr/__header1__(io,__AVR_DEV_LIB_NAME__).h>
#  include __AVR_DEVICE_HEADER__
#else
#  if !defined(__COMPILING_AVR_LIBC__)
#    warning "device type not defined"
#  endif
#endif

#include <avr/portpins.h>

#include <avr/common.h>

#include <avr/version.h>

#if __AVR_ARCH__ >= 100
#  include <avr/xmega.h>
#endif

/* Include fuse.h after individual IO header files. */
#include <avr/fuse.h>

/* Include lock.h after individual IO header files. */
#include <avr/lock.h>

#endif /* _AVR_IO_H_ */
 

 

 

 

Here is the "iotn102.h" file:

 

 

 

/*
 * Copyright (C) 2020, Microchip Technology Inc. and its subsidiaries ("Microchip")
 * All rights reserved.
 *
 * This software is developed by Microchip Technology Inc. and its subsidiaries ("Microchip").
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 *     1. Redistributions of source code must retain the above copyright notice, this list of
 *        conditions and the following disclaimer.
 *
 *     2. Redistributions in binary form must reproduce the above copyright notice, this list
 *        of conditions and the following disclaimer in the documentation and/or other
 *        materials provided with the distribution. Publication is not required when
 *        this file is used in an embedded application.
 *
 *     3. Microchip's name may not be used to endorse or promote products derived from this
 *        software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY MICROCHIP "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MICROCHIP BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT LIMITED TO
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWSOEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _AVR_ATTINY102_H_INCLUDED
#define _AVR_ATTINY102_H_INCLUDED

#ifndef _AVR_IO_H_
#  error "Include <avr/io.h> instead of this file."
#endif

#ifndef _AVR_IOXXX_H_
#  define _AVR_IOXXX_H_ "iotn102.h"
#else
#  error "Attempt to include more than one <avr/ioXXX.h> file."
#endif

/* Registers and associated bit numbers */

#define PINA    _SFR_IO8(0x00)
#define PINA7   7
#define PINA6   6
#define PINA5   5
#define PINA4   4
#define PINA3   3
#define PINA2   2
#define PINA1   1
#define PINA0   0

#define DDRA    _SFR_IO8(0x01)
#define DDRA7   7
// Inserted "DDA7" from "DDRA7" due to compatibility
#define DDA7    7
#define DDRA6   6
// Inserted "DDA6" from "DDRA6" due to compatibility
#define DDA6    6
#define DDRA5   5
// Inserted "DDA5" from "DDRA5" due to compatibility
#define DDA5    5
#define DDRA4   4
// Inserted "DDA4" from "DDRA4" due to compatibility
#define DDA4    4
#define DDRA3   3
// Inserted "DDA3" from "DDRA3" due to compatibility
#define DDA3    3
#define DDRA2   2
// Inserted "DDA2" from "DDRA2" due to compatibility
#define DDA2    2
#define DDRA1   1
// Inserted "DDA1" from "DDRA1" due to compatibility
#define DDA1    1
#define DDRA0   0
// Inserted "DDA0" from "DDRA0" due to compatibility
#define DDA0    0

#define PORTA   _SFR_IO8(0x02)
#define PORTA7  7
#define PORTA6  6
#define PORTA5  5
#define PORTA4  4
#define PORTA3  3
#define PORTA2  2
#define PORTA1  1
#define PORTA0  0

#define PUEA    _SFR_IO8(0x03)
#define PUEA7   7
#define PUEA6   6
#define PUEA5   5
#define PUEA4   4
#define PUEA3   3
#define PUEA2   2
#define PUEA1   1
#define PUEA0   0

#define PINB    _SFR_IO8(0x04)
#define PINB3   3
#define PINB2   2
#define PINB1   1
#define PINB0   0

#define DDRB    _SFR_IO8(0x05)
#define DDRB3   3
// Inserted "DDB3" from "DDRB3" due to compatibility
#define DDB3    3
#define DDRB2   2
// Inserted "DDB2" from "DDRB2" due to compatibility
#define DDB2    2
#define DDRB1   1
// Inserted "DDB1" from "DDRB1" due to compatibility
#define DDB1    1
#define DDRB0   0
// Inserted "DDB0" from "DDRB0" due to compatibility
#define DDB0    0

#define PORTB   _SFR_IO8(0x06)
#define PORTB3  3
#define PORTB2  2
#define PORTB1  1
#define PORTB0  0

#define PUEB    _SFR_IO8(0x07)
#define PUEB3   3
#define PUEB2   2
#define PUEB1   1
#define PUEB0   0

#define UDR     _SFR_IO8(0x08)

/* Combine UBRRL and UBRRH */
#define UBRR    _SFR_IO16(0x09)

#define UBRRL   _SFR_IO8(0x09)
#define UBRRH   _SFR_IO8(0x0A)

#define UCSRD   _SFR_IO8(0x0B)
#define SFDE    5
#define RXS     6
#define RXSIE   7

#define UCSRC   _SFR_IO8(0x0C)
#define UCPOL   0
#define UCSZ0   1
#define UCSZ1   2
#define USBS    3
#define UPM0    4
#define UPM1    5
#define UMSEL0  6
#define UMSEL1  7

#define UCSRB   _SFR_IO8(0x0D)
#define TXB8    0
#define RXB8    1
#define UCSZ2   2
#define TXEN    3
#define RXEN    4
#define UDRIE   5
#define TXCIE   6
#define RXCIE   7

#define UCSRA   _SFR_IO8(0x0E)
#define MPCM    0
#define U2X     1
#define UPE     2
#define DOR     3
#define FE      4
#define UDRE    5
#define TXC     6
#define RXC     7

#define PCMSK0  _SFR_IO8(0x0F)
#define PCINT0  0
#define PCINT1  1
#define PCINT2  2
#define PCINT3  3
#define PCINT4  4
#define PCINT5  5
#define PCINT6  6
#define PCINT7  7

#define PCMSK1  _SFR_IO8(0x10)
#define PCINT8  0
#define PCINT9  1
#define PCINT10 2
#define PCINT11 3

#define PCIFR   _SFR_IO8(0x11)
#define PCIF0   0
#define PCIF1   1

#define PCICR   _SFR_IO8(0x12)
#define PCIE0   0
#define PCIE1   1

#define EIMSK   _SFR_IO8(0x13)
#define INT0    0

#define EIFR    _SFR_IO8(0x14)
#define INTF0   0

#define EICRA   _SFR_IO8(0x15)
#define ISC00   0
#define ISC01   1

#define PORTCR  _SFR_IO8(0x16)
#define BBMA    0
#define BBMB    1

#define DIDR0   _SFR_IO8(0x17)
#define ADC0D   0
#define ADC1D   1
#define ADC2D   2
#define ADC3D   3
#define ADC4D   4
#define ADC5D   5
#define ADC6D   6
#define ADC7D   7
#define AIN0D   0
#define AIN1D   1

/* Reserved [0x18] */

#define ADCL    _SFR_IO8(0x19)

#define ADCH    _SFR_IO8(0x1A)

#define ADMUX   _SFR_IO8(0x1B)
#define MUX0    0
#define MUX1    1
#define MUX2    2
#define REFS0   6
#define REFS1   7

#define ADCSRB  _SFR_IO8(0x1C)
#define ADTS0   0
#define ADTS1   1
#define ADTS2   2
#define ADLAR   7

#define ADCSRA  _SFR_IO8(0x1D)
#define ADPS0   0
#define ADPS1   1
#define ADPS2   2
#define ADIE    3
#define ADIF    4
#define ADATE   5
#define ADSC    6
#define ADEN    7

#define ACSRB   _SFR_IO8(0x1E)
#define ACPMUX  0
#define ACOE    1

#define ACSRA   _SFR_IO8(0x1F)
#define ACIS0   0
#define ACIS1   1
#define ACIC    2
#define ACIE    3
#define ACI     4
#define ACO     5
#define ACBG    6
#define ACD     7

/* Reserved [0x20..0x21] */

/* Combine ICR0L and ICR0H */
#define ICR0    _SFR_IO16(0x22)

#define ICR0L   _SFR_IO8(0x22)
#define ICR0H   _SFR_IO8(0x23)

/* Combine OCR0BL and OCR0BH */
#define OCR0B   _SFR_IO16(0x24)

#define OCR0BL  _SFR_IO8(0x24)
#define OCR0BH  _SFR_IO8(0x25)

/* Combine OCR0AL and OCR0AH */
#define OCR0A   _SFR_IO16(0x26)

#define OCR0AL  _SFR_IO8(0x26)
#define OCR0AH  _SFR_IO8(0x27)

/* Combine TCNT0L and TCNT0H */
#define TCNT0   _SFR_IO16(0x28)

#define TCNT0L  _SFR_IO8(0x28)
#define TCNT0H  _SFR_IO8(0x29)

#define TIFR0   _SFR_IO8(0x2A)
#define TOV0    0
#define OCF0A   1
#define OCF0B   2
#define ICF0    5

#define TIMSK0  _SFR_IO8(0x2B)
#define TOIE0   0
#define OCIE0A  1
#define OCIE0B  2
#define ICIE0   5

#define TCCR0C  _SFR_IO8(0x2C)
#define FOC0B   6
#define FOC0A   7

#define TCCR0B  _SFR_IO8(0x2D)
#define CS00    0
#define CS01    1
#define CS02    2
#define WGM02   3
#define WGM03   4
#define ICES0   6
#define ICNC0   7

#define TCCR0A  _SFR_IO8(0x2E)
#define WGM00   0
#define WGM01   1
#define COM0B0  4
#define COM0B1  5
#define COM0A0  6
#define COM0A1  7

#define GTCCR   _SFR_IO8(0x2F)
#define PSR     0
#define REMAP   1
#define TSM     7

/* Reserved [0x30] */

#define WDTCSR  _SFR_IO8(0x31)
#define WDE     3
#define WDP0    0
#define WDP1    1
#define WDP2    2
#define WDP3    5
#define WDIE    6
#define WDIF    7

#define NVMCSR  _SFR_IO8(0x32)
#define NVMBSY  7

#define NVMCMD  _SFR_IO8(0x33)

#define VLMCSR  _SFR_IO8(0x34)
#define VLM0    0
#define VLM1    1
#define VLM2    2
#define VLMIE   6
#define VLMF    7

#define PRR     _SFR_IO8(0x35)
#define PRTIM0  0
#define PRADC   1
#define PRUSART 2

#define __AVR_HAVE_PRR    ((1<<PRTIM0)|(1<<PRADC)|(1<<PRUSART))
#define __AVR_HAVE_PRR_PRTIM0
#define __AVR_HAVE_PRR_PRADC
#define __AVR_HAVE_PRR_PRUSART

#define CLKPSR  _SFR_IO8(0x36)
#define CLKPS0  0
#define CLKPS1  1
#define CLKPS2  2
#define CLKPS3  3

#define CLKMSR  _SFR_IO8(0x37)
#define CLKMS0  0
#define CLKMS1  1

/* Reserved [0x38] */

#define OSCCAL  _SFR_IO8(0x39)

#define SMCR    _SFR_IO8(0x3A)
#define SE      0
#define SM0     1
#define SM1     2
#define SM2     3

#define RSTFLR  _SFR_IO8(0x3B)
#define PORF    0
#define EXTRF   1
#define WDRF    3

#define CCP     _SFR_IO8(0x3C)
#define CCP0    0
#define CCP1    1
#define CCP2    2
#define CCP3    3
#define CCP4    4
#define CCP5    5
#define CCP6    6
#define CCP7    7

/* SP [0x3D..0x3E] */

/* SREG [0x3F] */

/* Values and associated defines */

#define SLEEP_MODE_IDLE (0x00<<1)
#define SLEEP_MODE_ADC (0x01<<1)
#define SLEEP_MODE_PWR_DOWN (0x02<<1)
#define SLEEP_MODE_STANDBY (0x04<<1)

/* Interrupt vectors */
/* Vector 0 is the reset vector */
/* External Interrupt Request 0 */
#define INT0_vect            _VECTOR(1)
#define INT0_vect_num        1

/* Pin Change Interrupt Request 0 */
#define PCINT0_vect            _VECTOR(2)
#define PCINT0_vect_num        2

/* Pin Change Interrupt Request 1 */
#define PCINT1_vect            _VECTOR(3)
#define PCINT1_vect_num        3

/* Timer/Counter0 Input Capture */
#define TIM0_CAPT_vect            _VECTOR(4)
#define TIM0_CAPT_vect_num        4

/* Timer/Counter0 Overflow */
#define TIM0_OVF_vect            _VECTOR(5)
#define TIM0_OVF_vect_num        5

/* Timer/Counter Compare Match A */
#define TIM0_COMPA_vect            _VECTOR(6)
#define TIM0_COMPA_vect_num        6

/* Timer/Counter Compare Match B */
#define TIM0_COMPB_vect            _VECTOR(7)
#define TIM0_COMPB_vect_num        7

/* Analog Comparator */
#define ANA_COMP_vect            _VECTOR(8)
#define ANA_COMP_vect_num        8

/* Watchdog Time-out */
#define WDT_vect            _VECTOR(9)
#define WDT_vect_num        9

/* Vcc Voltage Level Monitor */
#define VLM_vect            _VECTOR(10)
#define VLM_vect_num        10

/* ADC Conversion complete */
#define ADC_vect            _VECTOR(11)
#define ADC_vect_num        11

/* USART RX Start */
#define USART_RXS_vect            _VECTOR(12)
#define USART_RXS_vect_num        12

/* USART RX Complete */
#define USART_RXC_vect            _VECTOR(13)
#define USART_RXC_vect_num        13

/* USART Data register empty */
#define USART_DRE_vect            _VECTOR(14)
#define USART_DRE_vect_num        14

/* USART Tx Complete */
#define USART_TXC_vect            _VECTOR(15)
#define USART_TXC_vect_num        15

#if (defined(__ASSEMBLER__) || defined(__IAR_SYSTEMS_ASM__))
#  define _VECTORS_SIZE 32
#else
#  define _VECTORS_SIZE 32U
#endif

/* Constants */

#if (defined(__ASSEMBLER__) || defined(__IAR_SYSTEMS_ASM__))
#  define SPM_PAGESIZE 128
#  define FLASHSTART   0x0000
#  define FLASHEND     0x03FF
#else
#  define SPM_PAGESIZE 128U
#  define FLASHSTART   0x0000U
#  define FLASHEND     0x03FFU
#endif
#if (defined(__ASSEMBLER__) || defined(__IAR_SYSTEMS_ASM__))
#  define RAMSTART     0x0040
#  define RAMSIZE      32
#  define RAMEND       0x005F
#else
#  define RAMSTART     0x0040U
#  define RAMSIZE      32U
#  define RAMEND       0x005FU
#endif
#define XRAMEND      RAMEND

/* Fuses */

#define FUSE_MEMORY_SIZE 1

/* Fuse Byte */
#define FUSE_RSTDISBL    (unsigned char)~_BV(0)
#define FUSE_WDTON       (unsigned char)~_BV(1)
#define FUSE_CKOUT       (unsigned char)~_BV(2)
#define FUSE_SELFPROGEN  (unsigned char)~_BV(3)
#define LFUSE_DEFAULT    (0xFF)

/* Lock Bits */
#define __LOCK_BITS_EXIST

/* Signature */
#define SIGNATURE_0 0x1E
#define SIGNATURE_1 0x90
#define SIGNATURE_2 0x0C

/* Properties */
#define CCP_IOREG_gc 0xD8      // IOREG signature for Change Protect
#define   CCP_SPM_gc 0xE7      // SPM signature for Change Protect

#endif /* #ifdef _AVR_ATTINY102_H_INCLUDED */

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
You must ensure the code reads them in the correct order (I don't recall which one needs read first).

Isn't that what OP was doing before some one seemed to imply that using the 16-bit access would cure the OP's problem?

avrcandies wrote:
Read ADC to get the result myval =ADC (no need to read hi & lo bytes)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I mentioned in #27 , the ADC is not in the pak, that is why you have the issue.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How do I do that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do I need to update the .h files somehow? or do I need to download it from a particular place?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is standard and usual advice to just read ADC...but they apparently forgot it in this particular pack...here it is in the tiny 261

 

#define ADCW    _SFR_IO16(0x04)
#ifndef __ASSEMBLER__
#define ADC     _SFR_IO16(0x04)
#endif

#define ADCL    _SFR_IO8(0x04)
#define ADCH    _SFR_IO8(0x05)

 

Rather than mod the file, you could just read the H & L registers (in the proper order) and combine

I wonder how many paks have this missing?  It's not uncommon for paks to have various bits AWOL, or sudden name changes from the norm.   When you get this "unknown name" error...go look at your pak

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Regarding the POT, The lowest voltage that I'm reading is 0 V or a few millivolts and the highest value is around 2.9V. And in the halfway position it is around 2.7 V. So If I set the login to turn ON the LED at around 2.7V  and set the ADC comparison value to 830 or 850, I should still get a noticeable amount of potentiometer movement before the LED turns ON or OFF, right? 

 

But anyway, I never thought that a linear POT would behave almost like a LOG POT, thanks for sharing this info smiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you. So in a way, I need to create a line that will combine the ADCL and ADCH, right? Something like this: 

 

 

uint16_t ADC= (ADCL<<8)|ADCH;

 

or 

 

uint16_t ADC= (ADCH<<8)|ADCL;

 

 

I tried both of them in the loop as I mentioned earlier but never got any result. reference code: post#16. In post #18 you mentioned removing this line:

 

ADCSRA |= (1<<ADIF); 

 

I did that as well but same result.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The curve is just due to the normal divider equation, varying one of the resistors nothing super special.

 

forget about ADIF

 

ADCL must be read first in order to avoid locking the data registers from getting updated by the next conversion result.

so the low must be read first.  You can have 2 lines of code, so you enforce the ordering of these volatile registers.

If you combine general calculations into one line you don't always ensure you get the order you want, compliers can try to be helpful and rearrange things to "improve" normal calculations, so care and caution are bywords.  These registers are treated as volatiles, so access is guaranteed.  If I get wacky results, I might take a look at the generated code "just to be sure"  Using ADC firmly buries any such considerations under the rug. 

Using ADC firmly buries any such considerations under the rug.   https://www.avrfreaks.net/forum/...

 

As a simple example, given the expression:

   x = y + z;

This expression is evaluated for its side effects and there is a sequence point following this evaluation. So what we can rely on is that the sub-expression (y + z) must be evaluated before the temporary result (called an r-value) is assigned to x generating a side effect. However, we cannot rely on the order that y and z is read from memory, because, of course, in theory it shouldn’t matter (the order of sub-expression evaluation is Unspecified behaviour).

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Apr 18, 2022 - 10:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Finally, it's working, I followed your idea of separately reading ADCL and ADCH and also reading the ADCL first smileysmiley. Thanks a lot.....

 

And Thank you everyone for helping me learn a ton of programming and debugging steps to narrow down the error.

 

 

Here is the code if someone faces the same issue:

 

 

#include <avr/io.h>
#define F_CPU 8000000UL

void adc_setup()
{
    ADCSRA |= (1<<ADEN);  // Enable ADC
    ADCSRB = 0x00;        //free running mode
    ADMUX = (1<<REFS0);
}

int adc_read(uint16_t channel)
{
    ADMUX = channel;
    ADCSRA |= (1<<ADSC);              // Start conversion
    while(! (ADCSRA & (1<<ADIF)));  // Wait for conversion to be complete
    uint8_t ADC_L = ADCL;
    uint8_t ADC_H = ADCH;
    uint16_t ADC= (ADC_H<<8)|ADC_L;
    //ADCSRA |= (1<<ADIF);              // Clear ADIF flag before the next conversion
    return (ADC);
    
    
}

int main()
{
    DDRA = 0b00000011;         //PA0 & PA1 as output
    adc_setup();
    while(1)
    {
        uint16_t adc_val_1 = adc_read(0b00000101);  // Read ADC5
        uint16_t adc_val_2 = adc_read(0b00000111);  // Read ADC7

if (adc_val_1 >= 900)
        {
            PORTA |= (1<<PA1);
        }
        else
        {
            PORTA  &= ~(1<<PA1);
        }

        if (adc_val_2 >= 900)
        {
            PORTA |= (1<<PA0);
        }
        else
        {
            PORTA &= ~(1<<PA0);
        }
    }
}