Analogue I/O Example

The example below demonstrates the use of the Analogue to digital converter (ADC) and  timer configured to generate a Pulse Width Modulated (PWM) signal for analogue input and output respectively in microprocessors. A 1kohm Potentiometer is attached to 5V and ground and the wiper is attached to A0 to provide a variable input voltage to the ADC as shown below. The PWM output is sent to the LED attached to pin 13.

Potentiometer to provide a variable voltage input to the ADC

Potentiometer to provide a variable voltage input to the ADC

* LED_Dimmer.c
* The example demonstrates the use of the analogue input to measure an input voltage. A variable
* input voltage can easily be created on the Arduino board by connecting a potentiometer between
* Vcc and ground and connecting the wiper to A0.
* In this example the measured input voltage is then used to control the mark to space ratio of
* a pulse width modulated signal created using timer1. This output can be connected to the LED
* on the board that is attached to pin 13 in order to control the brightness of the LED
* Created: 03/11/2011 09:10:49
* Author: Benn

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

// Function Prototypes
void adc_init(void); //Function to initialize/configure the ADC
uint16_t read_adc(uint8_t channel); //Function to read an arbitrary analogue channel/pin
void timer1_init(void); //Function to initialize timer 1 as a 10bit PWM

int main(void)
// Local Variables
uint16_t adc_value; //Variable used to store the value read from the ADC

adc_init(); //Setup the ADC
timer1_init(); //Configure PWM clock

{ //Infinite loop
adc_value = read_adc(0); //Read one ADC channel
OCR1C = adc_value; //set PWM duty cycle for channel A
_delay_ms(50); //You can tweak this value to have slower or faster readings or for max speed remove this line

void adc_init(void){
ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)); //16MHz/128 = 125kHz the ADC reference clock
ADMUX |= (1<<REFS0); //Voltage reference from Avcc (5v)
ADCSRA |= (1<<ADEN); //Turn on ADC
ADCSRA |= (1<<ADSC); //Do an initial conversion because this one is the slowest and to ensure that everything is up and running

uint16_t read_adc(uint8_t channel)
ADMUX &= 0xF0; //Clear the older channel that was read
ADMUX |= channel; //Defines the new ADC channel to be read
ADCSRA |= (1<<ADSC); //Starts a new conversion
while(ADCSRA & (1<<ADSC)); //Wait until the conversion is done
return ADCW; //Returns the ADC value of the chosen channel

void timer1_init(void)
DDRB = (1<<PB7); //Set PWM pins OC1C from timer 1 as output
TCCR1A = ((1<<COM1C1)|(1<<WGM11)|(1<<WGM10)); //Enable PWM mode using output compare register C and set the WGM bits for fast 10 bit PWM mode
TCCR1B = ((1<<CS11)|(1<<CS10)|(1<<WGM12)); //Set clock prescaler to 32

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s