I used a loop, looping a number of times determined by value read from the ADCH from the pot. Within the loop I call _delay_ms(10). I see that this is a crude system, and I could live with it. But, it has a few problems.
First, the main thing is the timing as set by the rotation of the pot feels non-linear. Most of the change is bunched up at one end of the pot rotation.
Second, at the slow end I notice a lag in response, as the loop needs to finish before the pot is read again.
Last, I know there must be a better way. I need a few suggestions to point me in the right direction. Your input is greatly appreciated!
I'm using an attiny13, avr-gcc and avrdude.
Here's a sample of the code I'm using at the moment.
Code: Select all
while ( 1 ) { // Main program
ADCSRA |= ( 1 << ADEN ); // Analog-Digital enable bit
ADCSRA |= ( 1 << ADSC ); // Discard first conversion
while ( ADCSRA & ( 1 << ADSC ) ); // wait until conversion is done
ADCSRA |= ( 1 << ADSC ); // start single conversion
while ( ADCSRA & ( 1 << ADSC ) ) // wait until conversion is done
ADCSRA &= ~( 1 << ADEN ); // shut down the ADC
//----------Set rate of blinking based on ADCH byte---------
for ( i = 0 ; i < ADCH ; i++ ) { // Loop x time until i reach ADCH value
_delay_ms( 10 ); // Loop delay
}
brightness = (uint8_t) rand(); // Need a random number from 0 - 255
OCR0A = brightness;
}
Here's the entire application in case it's relevant:
Code: Select all
/*
* Sample and Hold Demo. Flashes an LED at a random brightness at a rate set by a pot
* LED anode connected to pin 5, cathode to ground through a 470 ohm resistor
* B10K Pot center lug to pin 3, outer lugs to +5v and ground
* LED PB0 connected to pin 5
* Pot AD2 (PB4) connected to pin 3
*
*/
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#define LED PB0 // Define led ext output pin on PB0 pin 5
int main( void ) {
int i; // 8 bits integer - should be set in main?
uint8_t brightness = 0x00; // Holds the random value applied to OCR0A
// ******************************************************************
// *** Set up PWM ***
TCCR0A |= (1<<COM0A1) | (1<<WGM00); // PWM Phase correct mode 1
TCCR0B |= (1<<CS00);// --no prescale
TCNT0 = 0x00; // Timer/Counter Register
OCR0A = 0x12; // Output Compare Register A
DDRB |= (1<<PORTB0); // Set PB0 (Pin 5) as output
// ******************************************************************
// *******************************************************************
// *** Set up ADC ***
DDRB |= ( 1 << LED ); // Set output direction on LED
ADCSRA |= ( 1 << ADEN ) | // Analog-Digital enable bit
( 1 << ADPS1 ) | // set prescaler to 8 ( clock / 8 )
( 1 << ADPS0 ); // set prescaler to 8 ( clock / 8 )
ADMUX |= ( 1 << ADLAR ) | // AD result store in ( more significant bit in ADCH )
( 1 << MUX1 ); // Choose AD input AD2 ( PB4 ) pin 3
// *******************************************************************
while ( 1 ) { // Main program
ADCSRA |= ( 1 << ADEN ); // Analog-Digital enable bit
ADCSRA |= ( 1 << ADSC ); // Discard first conversion
while ( ADCSRA & ( 1 << ADSC ) ); // wait until conversion is done
ADCSRA |= ( 1 << ADSC ); // start single conversion
while ( ADCSRA & ( 1 << ADSC ) ) // wait until conversion is done
ADCSRA &= ~( 1 << ADEN ); // shut down the ADC
//----------Set rate of blinking based on ADCH byte---------
for ( i = 0 ; i < ADCH ; i++ ) { // Loop x time until i reach ADCH value
_delay_ms( 10 ); // Loop delay
}
brightness = (uint8_t) rand(); // Need a random number from 0 - 255
OCR0A = brightness;
}
return 0;
}