210 likes | 341 Views
Lab2: A/D Converter. Lab2: A/D Converter. This circuit connects a variable voltage to an A/D port on the AVR mcu. Your software running on the AVR mcu will read the digital value and display the percent and raw value of the voltage, V A as shown in Table 1.
E N D
Lab2: A/D Converter • This circuit connects a variable voltage to an A/D port on the AVR mcu. Your software running on the AVR mcu will read the digital value and display the percent and raw value of the voltage, VA as shown in Table 1. • The interface consists of some analog circuitry as well as wiring the analog circuit to the STK500 and running corresponding software on the AVR mcu. Each circuit requires a unique C-routine.
Atmeg16 We use ATmega16 having the same pin layout
Pin 40 = PA0 = ADC0 AD converter Channel 0 Pin 32 = AREF (= VTG on STK500 board) Pin 31 = GND = AVR board ground Use the AVR board ground
Port A also serves as AD inputs Pin layout is different from Atmeg16 Atmega8515 is at SCKT3000D3
Lab2: A/D Converter • Pre-Lab Assignments • Read the ATmega16/ATmega8515 on-line data book available in the course website, pages 202 through 220. • Read B, C, and O (course text), chapter 2. • Read the AVR STK500 User Guide, page 3-11 and pages 3-16 through 3-18. • Answer Pre-Lab Questions
Pre_lab questions • What is the range of an n-bit A/D converter? 2. Our ATmeg16/ATmega8515 has an 10-bit A/D converter. What is the resolution if the full-scale input range is 5V? 3. Briefly describe the two operating modes of the ADC in the ATmeg16/ATmega8515. 4. What are the ADC noise canceling techniques? 5. What two registers are used by the ADC and what are their purposes? ADCSRA ADMUX ADCW
ADCSRA bit definitions (Textbook: page 143) Bit 7 6 5 4 3 2 1 0 Bit7: ADC Enable bit Bit6: ADC start conversion bit Bit5: ADC free running bit Bit0-Bit2: ADC prescaler select bit ADCSRA=0xE9; /*enable ADC, free run, started, clock prescaler of 64 */ ADCSRA = 11101110
There are two operating modes of ADC: • In the interrupt-driven, (single-conversion) mode, only one conversion occurs after setting the start conversion bit and the bit must be set again before another conversion. • 2. In the free-running mode, successive conversions are restarted automatically once the first conversion completes.
Lab2 software requirements • The ADC program can use a 100 ms clock to trigger the ISR. The ISR set a flag and the actual work of reading the ADC and running the math can be done in main(). • Every 5 times through the ISR – i.e. every 500 ms – the ISR blinked an LED. This is done to provide a heartbeat signal. If the rest of the program is not working but the LED is blinking, we know that the P is OK and that the software is not hung. This was very useful in the troubleshooting phase. • Demo and produce Table 1
Table 1. ADC Measurements for Different Potentiometer Settings
Lab2 software requirement • For noise elimination you can make your program to measure the ADC channel 4 times, then throws out the highest and the lowest and takes an average of the remaining 2 data points. • This makes sure that outlying data points (flyers) do not affect the final result. • The main issue is an occasional data point that is obviously very far out of the normal band. The technique used for noise elimination can eliminate those data points. The resulting output was quite stable. Output data was solidly +/- 1 unit (5 mV) with an occasional jump to +/- 2 units.
main() Initialize peripherals in Atmeg16 P: Port B : output, initialized to all 1’s = LED’s off. Timer 1 : 278 s period, interrupt on, reload for 100 ms period. ADC: turn ADC on, enable the interrupt and set ADC clock to 115 kHz Wait until the ADC flag is set by the ISR. Clear the ADC flag. Initialize loop variables and select channel 1. Run ADC measure loop 4 times ………… more work.
Timer 1, ISR() Reload counter for 100 ms. Increment the 1-5 counter. If the 1-5 counter overflows, blink the heartbeat LED. Set the ADC flag. …….. ADC, ISR() Set the ADC done flag.
#include <mega16.h> // Standard Input/Output functions #include <stdio.h> char adcFlag = 0; char ledFlag = 0; char adcDone = 0; char count = 0; unsigned char led1 = 0xFF; unsigned char led2 = 0xFE; ….
// Timer 1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { // Reinitialize Timer 1 value TCNT1H=0xFE; TCNT1L=0x97; // Place your code here adcFlag = 1; // Increment the count // Every 5 times through (500 ms) blink the LED (heartbeat LED) …………..
interrupt [ADC_INT] void adc_isr(void) { adcDone = 1; } void main(void) // Main Control Loop while (1){ // When ADC flag is set by interrupt, // do conversion and show results // Wait for ISR to set flag // Wait until conversion is done while(adcDone == 0){ } // Get and process data volts = ADCW; //printf(" v = %d", volts); if(volts < loV){ loV = volts; } if(volts > hiV){ hiV = volts; } sumV += volts;
Another approach • write the read_adc function • main calls the read_adc function
This is another example of reading ADC output. while (1) { // Place your code here delay_ms(900); // delay 900 ms; ADC_sum=0; // initialize ADC_sum; for (i=0;i < 10; i++){ // start to sum 10 ADC samples; delay_ms(10); // take ADC sample every 10 ms; ADC_sum += read_adc(0); // read ADC output from PA0 and add to ADC_sum; } ADC_output = ADC_sum/10; // averaged ADC output; ADC_percent = ADC_output*25/256; // calculate percentage of ADC full range for current ADC output; printf("ADC Output = %4d ADC Percentage = %3d%%\r", ADC_output, ADC_percent); // Display ADC output to terminal; if (ADC_output > 0x0332) // threshold detection at 4.0V; PORTB = 0xFE; //turn on LED0 when ADC output > 4.0V; else PORTB = 0xFF; };