| |||||||
Опубликовано 2013-05-03 15:02:21 автором Ruslan Цифровой ВаттметрКупил я тут на днях велосипедное мотор-колесо. Давно мечтал, и вот оно, во всей красе!
Мотор постоянного тока, вентильный, 48в, 500ват. Китайцы обещают КПД около 85%, что уже неплохо для такой мощности.К нему в комплекте шёл контроллер 800 ватт, ручки газа и тормоза. Блок аккумуляторов - 4шт, 12в, 9а/часов и зарядное устройство к ним приобретал отдельно. Собрал я все это добро на свой старый горный велик
Первые впечатления от электротяги просто не передать словами! Крутящий момент максимальный с самого старта (разгоняется быстрей 50-кубового скутера), максималка 45 км/час. Обкатав все это дело, мне захотелось прикрутить к нему какую-то фичу, что-нибуть для индикации расходов энергии. Тут сам собой напросился цифровой ваттметр. В предыдущих статях мы научились мерять напряжение и ток.Для того, чтобы измерить потребляемую мощность, нужно напряжение умножить на ток: ВТ=В*А. По сути, ваттметр - это амперметр и вольтметр в едином устройстве. Давайте объединим схемы амперметра и вольтметра, описанные в предыдущих статьях, и получим схему ваттметра:
Ваттметр построен на микроконтроллере atmega8, который заслужено занимает статус народного. Ток, напряжение и мощность выводятся на Lcd-дисплей 16x2. На резисторах R8,R9 построен делитель напряжения с коэффициентом деления 11, источник опорного напряжения выполнен на регулируемом стабилитроне TL431 и настроен на напряжения 5.12 вольт.Ток измеряется путем измерения падения напряжения на шунте R2, далее напряжение на шунте усиливается операционным усилителем Lm358 и поступает на вход АЦП adc0. Программа написана на CodeVisionAVR
#include <mega8.h> #include <delay.h> #include <stdio.h>//библиотека в которой лежит функция sprintf // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x12 ;PORTD #endasm #include <lcd.h> #define ADC_VREF_TYPE 0x00 // 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) { char buffer[32]; //переменная в которой будет формироваться строка для вывода на lcd unsigned long int u; //переменная для хранения напряжения в миливольтах unsigned long int a; //переменная для хранения тока unsigned long int w; //переменная для хранения значений потребляемой мощности PORTB=0x00; DDRB=0x00; // Port C initialization PORTC=0x00; DDRC=0x00; // Port D initialization PORTD=0x00; DDRD=0x00; // Timer/Counter 0 initialization TCCR0=0x00; TCNT0=0x00; // Timer/Counter 1 initialization TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization MCUCR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00; // Analog Comparator initialization ACSR=0x80; SFIOR=0x00; // ADC initialization // ADC Clock frequency: 500,000 kHz // ADC Voltage Reference: AREF pin ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0x81; // LCD module initialization lcd_init(16); while (1) { a=read_adc(0); // читаем значения ацп с порта 0 u=read_adc(1); // читаем значения ацп с порта 1 /* 1. Измеряем ток Ток, протекающий через шунт, вичисляется по закону Ома: I=U/R R=0,1 ом, a U(падение напряжения на шунте) мы будем измерять. Так как АЦП у нас 10-битный, то максимальное число, которое вернет функция read_adc,() будет равно 1024, это число будет эквивалентом напряжения на входе adc0. Например, если read_adc() вернул 512 то это значит, что на вход adc0 ми подали половину опорного напряжения Чтобы вычислить реальное напряжение, нам нужно составить пропорцию: опорное напряжение - 1024 искомое напряжение - a У нас опорное напряжение=5.12 Искомое напряжение = 5.12*a/1024, или Искомое напряжение = 0,005*a для простоты переведём вольты в миливольты, домножив на 1000 Искомое напряжение = 0,005*a*1000 Здесь всё хорошо, но мы не учли коеффициент усиления ОУ расчитывается по формуле: Кус=1+R1/R2. Подставив, получим: Кус=(1+4)=5 Реальное напряжение = 0,005*a*1000/5, получаем просто a 2. Измеряем напряжение Дальше измеряем напряжение на резисторном делителе Составим пропорцию, как описано выше, и получим: Искомое напряжение = 0,005*u*1000 Надо еще учесть коеффициент резисторного делителя напряжения у нас он равен Кдел=(R1+R2)/R2. Подставив, получим: Кдел=(10+1)/1=11 Реальное напряжение = 0,005*u*1000*11 */ u=55*u; //вычисляем значения напряжения в миливольтах a=a*10; // вычисляем значения тока по закону Ома: I=U/R=a/100*1000=a*10 в милиамперах w=a*u; //вычисляем потребляемую мощность sprintf( buffer,"I=%u,%u U=%u,%u W=%u,%lu", a/1000, //Целая честь тока (a%1000)/10, //Дробная часть тока u/1000, // Целая часть напряжения (u%1000)/10, //Дробная часть напряжения w/1000000, // Целая часть мощности (w%1000000)/10000); //формируем строку для вывода lcd_clear(); //чистим дисплей перед выводом lcd_puts(buffer); //выводим сформированую строку на дисплей delay_ms(100); //делаем задержку }; } Для того, чтобы функция sprintf могла работать с переменными типа long int, необходимо провести дополнительные настройки. Для CodeVision AVR: Project->Configure->C compiler->(S)printf Features->Выбрать пункт "long,width,precision". Проект в протеусе и исходний код программы в архиве Watmeter.rar Комментарии - (10)
Добавить комментарийДля отправки комментария вы должны авторизоваться. |