Folks, I'd appreciate a little help with my project. This is my first attempt to use the ADC on the ATtiny85. Eventually, the project will evolve, but at the moment, it is a stripped-to-the-bones attempt to get a result from the ADC.
My sketch is below. The intention of the sketch is to get a voltage from a pot and light one of three LEDs, depending on whether the pot is in the lower third, middle- or upper third of its travel. It appears to work in AS7 (by writing the "pot" value into the ASC register after the conversion), but when I put it on a chip, it lights one LED, and moving the pot does not cause it to light a different LED. If I power it off, turn the pot, then power it on, the correct LED comes on, but that one stays on, and turning the pot does not change the LED on the fly.
The sketch is below.
There are a few lines to set up the ADC. These poke individual bits so I could play with them individually to see what they do.
The intention is ...
Set up the ADC
convert: ; get pot reading into R16
This function works. Given a value in R16, it discovers what third of (0...255) R16 is in, and lights the appropriate LED.
This function also works, and delays about a second.
.org 0x0 rjmp main ; Reset - Address 0 reti ; INT0 reti ; Pin Change Interrupt Request 0 reti ; Timer/Counter1 Compare Match A reti ; Timer/Counter1 Overflow reti ; Timer/Counter0 Overflow reti ; EEPROM Ready reti ; Analog Comparator reti ; ADC Conversion Complete reti ; Timer/Counter1 Compare Match B reti ; TCC0_cmpA_handler ; Timer/Counter0 Compare Match A reti ; Timer/Counter0 Compare Match B reti ; Watchdog Time-out reti ; USI START reti ; USI Overflow ;======================== ; ISRs go here ;======================== main: ; Load stack register LDI R16, HIGH(RAMEND) ; Upper byte OUT SPH,R16 ; to stack pointer LDI R16, LOW(RAMEND) ; Lower byte OUT SPL,R16 ; to stack pointer ;=================================================== ; initialise ADC PB3-Red, PB4-Yellow, PB1-Green ; _____ ; PB5 |* | VCC ; (Red) PB3 | | PB2 (Pot in) ; (Yellow) PB4 | | PB1 (Green) ; GND |_____| PB0 (to FET) ; ;=================================================== ; ATTINY 85 at 1MHz ;=================================================== ; set direction reg ldi R16,(1<<PB0)|(1<<PB1)|(1<<PB3)|(1<<PB4) ; PB3-Red, PB4-Yellow, PB1-Green, PB0-FET out DDRB,R16 ; PB0 drives pulses to LED via FET sbi DIDR0,ADC1D ; ADC1 (PB2) is analog, not digital sbi ADCSRA, ADEN ; ADC Enable sbi ADCSRA, ADPS1 ;\_ Prescaler to div_8 for 125 khz sampling sbi ADCSRA, ADPS0 ;/ sbi ADMUX, ADLAR ; all msb's will be in ADCH sbi ADMUX, MUX0 ; single-ended on ADC2 (PB4 - pin 3) convert: ; get pot reading into R16 sbi ADCSRA,ADSC ; START conversion. I see bit-6 get set in ADCSRA. NOTE: the Cycle Counter = 11 cbi ADCSRA,ADIF ; this does not clear ADIF in AS7, so I guess it is controlled by the hardware. ; I have not discovered how to clear it, so this is probably the crux of my problem. ; Wait for ADSC to go low again. wait_adif: ; NOTE: The datasheet says that at the end of conversion, sbic ADCSRA,ADSC ; ADSC will go false again. It does in AS7, but when I test it with sbic, rjmp wait_adif ; the rjmp is not skipped, so I deduce that ADSC was not, in fact, false. ; If I run the program down to the nop on the next line, I find that ADIF has gone true. ; I experimented with waiting for ADIF to go true, but the result is the same as testing ADSC false. ; That is also the reason why I manually reset ADIF a few lines above. ; copy the pot reading to R16 nop in R16,adch rcall light_led rjmp convert ;=================================================================== light_led: ; PB3-Red, PB4-Yellow, PB1-Green cpi R16,86 brlo red cpi R16,171 brlo yellow green: ldi R17,(1<<PB1) out PORTB,R17 ; Green ret ;rjmp convert yellow: ldi R17,(1<<PB4) out PORTB,R17 ; Yellow ret ; rjmp convert red: ldi R17,(1<<PB3) out PORTB,R17 ; Red ret ;=================================================================== delay: ldi R20,249 ldi R21,249 ldi R22,6 d2: dec R20 brne d2 ldi R20,249 dec R21 brne d2 ldi R21,249 dec R22 brne d2 ret
There's obviously something about the ADC I have not understood. Can somebody please explain what I'm missing?