Опубликовано 2013-04-30 12:35:19 автором Electrod Цифровий вольтметр на мікроконтролері
Сьогодні ми будемо робити цифровий вольтметр на мікроконтролері . Повторивши і усвідомивши матеріал у цій статті , ви дізнаєтеся , як за допомогою мікроконтролера можна виміряти напругу і вивести її на lcd дисплей. Для повторення нам знадобиться мікроконтролер atmega8 , lcd 16x2 знакосинтезуючих , пару резисторів , лінійний стабілізатор напруги lm317 , для живлення мікроконтролера , ну, начебто , все.
Принципова схема пристрою представлена нижче
Для вимірювання напруги використовується вбудований в мікроконтролер АЦП - аналого -цифровий перетворювач ( ADC- Analog - to - Digital Converter ) . Він перетворює аналоговий сигнал в цифровий. Для роботи АЦП потрібне джерело опорної напруги і напруги , яку ми хочемо оцифрувати (вона повинно бути менше опорної ) . У нашому випадку ми опорну напруга будемо брати з виводу живлення АЦП AVCC . Детальніше про використання АЦП в avr написано в статті " Використання АЦП AVR " . Напруга на вивід АЦП подається через резистивний дільник R1 R2 , тому що вхід у нас низьковольтний , від 0 до 5 вольт , а вимірювати нам потрібно напругу від 0 до 20 вольт. Для цього потрібно використовувати дільник з коефіцієнтом ділення 4 , тобто коли на вхід резистивного дільника подаватиметься 20 вольт , на вході АЦП буде 5 вольт Приступаємо до програмної частини проекту . У CodeVision AVR переходимо на вкладку Tools - > CodeWizardAVR для запуску автогенератора коду. Далі у вкладці Chip вибираємо мікроконтролер Atmega8 і встановлюємо частоту 1 Mhz . Переходимо у вкладку ADC (АЦП ) і тут ставимо галочку біля ADC Enable , вибираємо джерело опорної напруги Volt. Ref : тут три варіанти
- AREF pin - опорна напруга буде братися з ніжки aref
- AVCC pin - опорна напруга буде братися з ніжки живлення АЦП avcc
- Int . , cap on aref - підключити внутрішні конденсатори на ніжку aref
ul >
Ми вибираємо AVCC pin , після цього вибираємо частоту роботи АЦП 500 Khz
Всі налаштування за АЦП виконані. Тепер нам потрібно підключити lcd . Переходимо у вкладку LCD , і вибираємо порт , до якого буде підключений lcd , у мене це PORTD . Тепер всі налаштування виконані , потрібно згенерувати код . Для цього натискаємо File - > Generate , Save and exit і даємо імена вихідних файлів
Вихідний код проекту
# include <mega8.h>
# include <stdio.h>// бібліотека, в якій лежить функція sprintf
# include <delay.h>
// Alphanumeric LCD Module functions
# asm
. equ __ lcd_port = 0x12 ; PORTD
# endasm
# include <lcd.h>
# define ADC_VREF_TYPE 0x40
// Read the AD conversion result
unsigned int read_adc ( unsigned char adc_input )
{
ADMUX = adc_input | ( ADC_VREF_TYPE & 0xff ) ;
// Delay needed for the stabilization of the ADC input voltage
delay_us ( 10 ) ;
// Start the AD conversion
ADCSRA | = 0x40 ;
// Wait for the AD conversion to complete
while ( ( ADCSRA & 0x10 ) == 0 ) ;
ADCSRA | = 0x10 ;
return ADCW ;
}
void main ( void )
{
// Declare your local variables here
char buffer [ 32 ] ; // змінна, в якій буде формуватися рядок для виведення на lcd
int adc ; // змінна для запису значень АЦП
int v ; // змінна для збереження значення реальної напруги в мілівольтах
// Input / Output Ports initialization
// Port B initialization
PORTB = 0x00;
DDRB = 0x00;
// Port C initialization
PORTC = 0x00;
DDRC = 0x00;
// Port D initialization
PORTD = 0x00;
DDRD = 0x00;
// Timer / Counter 0 initialization
// Clock source : System Clock
// Clock value : Timer 0 Stopped
TCCR0 = 0x00;
TCNT0 = 0x00;
// Timer / Counter 1 initialization
// Clock source : System Clock
// Clock value : Timer1 Stopped
// Mode: Normal top = FFFFh
// OC1A output : Discon .
// OC1B output : Discon .
// Noise Canceler : Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt : Off
// Input Capture Interrupt : Off
// Compare A Match Interrupt : Off
// Compare B Match Interrupt : Off
TCCR1A = 0x00;
TCCR1B = 0x00;
TCNT1H = 0x00;
TCNT1L = 0x00;
ICR1H = 0x00;
ICR1L = 0x00;
OCR1AH = 0x00;
OCR1AL = 0x00;
OCR1BH = 0x00;
OCR1BL = 0x00;
// Timer / Counter 2 initialization
// Clock source : System Clock
// Clock value : Timer2 Stopped
// Mode: Normal top = FFh
// OC2 output : Disconnected
ASSR = 0x00;
TCCR2 = 0x00;
TCNT2 = 0x00;
OCR2 = 0x00;
// External Interrupt ( s ) initialization
// INT0 : Off
// INT1 : Off
MCUCR = 0x00;
// Timer ( s ) / Counter ( s ) Interrupt ( s ) initialization
TIMSK = 0x00;
// Analog Comparator initialization
// Analog Comparator : Off
// Analog Comparator Input Capture by Timer / Counter 1 : Off
ACSR = 0x80 ;
SFIOR = 0x00;
// ADC initialization
// ADC Clock frequency : 500,000 kHz
// ADC Voltage Reference : AVCC pin
ADMUX = ADC_VREF_TYPE & 0xff ;
ADCSRA = 0x81 ;
// LCD module initialization
lcd_init ( 16 ) ;
while ( 1 )
{
adc = read_adc (0); // Читаємо АЦП з порту 0
/* так як АЦП у нас 10-бітний , то максимальне число , яке поверне функція , read_adc ()
дорівнюватиме 1024 , це число буде еквівалентою напруги на вході adc0 .
Наприклад , якщо read_adc ( ) повернув 512 , то це означає , що на вхід adc0 ми подали половину опорної напруги
Щоб обчислити реальну напругу , нам потрібно скласти пропорцію
опорна напруга - 1024
шукана напруга - adc
У нас опорна напруга = 5.12
Шуканa напруга = 5.12 * adc/1024 , або шукана напруга = 0,005 * adc
для простоти переведемо вольти в мілівольти , домноживши на 1000
Шукана напруга = 0,005 * adc * 1000
Тут все добре , але ми не врахували коефіціент резисторного дільника напруги
У нас він дорівнює Кдел = (R1 + R2) / R2. Підставивши , отримаємо
Кдел = ( 15 +5 ) / 5 = 4
Реальна напруга = 0,005 * adc * 1000 * 4
*/
v = 20 * adc ;
sprintf ( buffer , "V = % i mv " , v ) ; // формуємо рядок для виведення
lcd_clear (); // чистимо дисплей перед виводом
lcd_puts ( buffer ) ; // виводимо сформований рядок на дисплей
delay_us ( 700 ) ; // робимо затримку
} ;
}
Все необхідне для реалізації вольтметра знаходиться в архіві Voltmeter.rar
Комментарии - (1) rvk говорит: Добрый день!
С простым вольтметром все понятно. Спасибо большое!
Есть двухканальный вольметр или больше, 3, 4 канала. Они все паралленые. Вход один резистивные делители разные. Как в таком случае работать програмно?
например: 1 канал - 0.00 9.99 В, 2 - 10.0 - 99.9 В
подаем напряжение больше 10 В и что? лапа микроконтроллера, корорая делителем расчитана до 10 В сгорает? А если подать 100 В? Поможет ли в этом случае стабилитрон?
Вот таким вопросом я задаюсь!
Поможете с этим разобраться?
Я задаюсь вопросом:
Добавить комментарийДля отправки комментария вы должны авторизоваться.
|