0
\$\begingroup\$

I am trying to get a simple IR sensor to work on my an attiny85. To do this I first wrote some code to setup the ADC and the perform an operation based on the outcome. Because the code didn't function as expected I decided to test if some code where I simply do one ADC conversion and then turn on an LED works. This did however not work. The cause of this seems to be that the attiny stops executing code after the ADC conversion. I am running the attiny at internal 8Mhz clock and the ADC is hooked up to ground through a 200 ohm resistor.

The following code does not turn on the pin at PB0:

#include <avr/io.h>
#include <util/delay.h>

int main(void) {

DDRB |= _BV(DDB0); //set PB0 to output

ADMUX = _BV(ADLAR) | _BV(MUX1); //set ADC 2, left adjust result
ADCSRA = _BV(ADPS1) | _BV(ADPS2); //prescaler 64
ADCSRA |= _BV(ADEN); //enable ADC

while(1) {

    ADCSRA |= _BV(ADSC); //start conversion
    while (ADCSRA & _BV(ADSC)); //wait for conversion to end
    uint8_t adc_result = ADCH; //adc results (should be 0)

    PORTB |= _BV(PORTB0); //set PB0 to high


}

return(0);
}

When I, however, put the "PORTB |= _BV(PORTB0);" line at the start of the loop, so before the ADC conversion, the line does execute and the LED at PB0 does turn on.

Also commenting out the line "ADCSRA |= _BV(ADSC);" makes the code run fine and makes PB0 go high. So I am pretty certain that the attiny somehow crashes when executing that line.

Disabling interrupts using "cli()" does not solve the problem either.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ When you initialize the ADC before your loop you're using "ADCSRA =", but you should probably use "ADCSRA |=" instead. I'm not familiar with the ATtiny though so ... \$\endgroup\$
    – brhans
    Mar 29, 2017 at 15:36
  • \$\begingroup\$ @brhans You're right, I was just moving around lines to try to get it to work. It's not the cause of the problem though, I just tested it and no result. I'll edit the post right away. \$\endgroup\$ Mar 29, 2017 at 15:41
  • \$\begingroup\$ Your code seems correct. The only thing I can recommend is moving definition of adc_result variable to either the head of main() or outside of main --to make it global so that it can be accessed from everywhere. Or maybe remove that line and test again if LED turns on. Some C compilers don't allow variable definiton at the middle of a scope though, they force you to define at the begining of a scope instead. \$\endgroup\$ Mar 29, 2017 at 15:55

2 Answers 2

1
\$\begingroup\$

I do not have any Attiny85 but I used your code and I write it to Attiny13.

The code I used:

#include <avr/io.h>

uint8_t adc_result = 0;

int main( void ) {

    DDRB |= ( 1 << DDB0 ); //set PB0 to output
    ADMUX  |= ( 1 << ADLAR ) | ( 1 << MUX1 ); //set ADC 2 (PB4), left adjust result
    ADCSRA |= ( 1 << ADEN ); //enable ADC
    ADCSRA |= ( 1 << ADPS1 ) | ( 1 << ADPS2 ); //prescaler 64

    while ( 1 ) {

        ADCSRA |= ( 1 << ADSC ); //start conversion

        while ( ADCSRA & ( 1 << ADSC ) );//wait for conversion to end

        adc_result = ADCH; //adc results (should be 0)

        PORTB ^= ( 1 << PB0 ); //Toggle LED at PB0 

    }

    return( 0 );
}   

As you can see I slightly modified the code because My C compilers do not recognize _BV macro so, I replace it with (1 << x) instead. And I also Toggle the led (PB0).

And the signal at PB0 pin looks like this:

enter image description here

Notice the signal frequency is around 5.2MHz.

So it's is very interesting why this code don't work at attiny85.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I tried the code and it didn't work as well however when I changed my fuse settings as described in my answer your code executed properly on the attiny85 as well. thanks for helping though! \$\endgroup\$ Mar 29, 2017 at 19:14
1
\$\begingroup\$

So I solved the problem.

For some reason the code started working when I changed the fuse settings to divide the internal clock by 8 so that I have an internal clock of 1 Mhz instead of 8 Mhz. I do not know why but for some reason this caused the ADC to not crash.

New fuse settings: -U lfuse:w:0x62:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m

Old fuse settings: -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.