Собираю контроллер ветрогенератора, в интернете нашел приемлемый проект - несложный и дешевый, с готовой прошивкой и схемой в протеусе.
http://articles.greenchip.com.ua/3-0-24-0.html
Кое-что нужно изменить/доработать в прошивке МК с измерением напряжения на шунте и заряда аккумулятора.
Кое-что мне просто не понятно, напишу по порядку.
У автора проекта максимальный ток заряда АКБ 10А (судя по протеусу). У меня макс. ток заряда будет 19А, поэтому желательно, делая с запасом, сделать шкалу до 25А. То есть при входе на МК 4,5вольт (усиливаем сигнал с шунта операционником) максимальный измеренный ток составлял 25А. Шунт уже подобрал - при 25А падение напряжение 375мВ, => коэффициент усиления ОУ равен 12.
Аналогично с измерением напряжения. Шкалу надо до 45вольт при 4,5вольтах на входе МК. Коэффициент делителя получится равен 10.
При настройке тока и напряжения через дисплей, у автора шаг настройки составляет 10 милливольт/миллиампер, получается очень медленно, хотелось чтобы шаг был 100 - но это на работоспособность не влияет - можно оставить и так.
Скорректировать это в прошивке я не могу - не хватает знаний.
И еще пара вопросов:
1. Зачем нужно опорное напряжение? Почему нельзя (или можно) задать в МК, что при входе на ногу 5воль это соответствует например 25А, а промежуточные значения он посчитает. В чем плюсы и минусы этих вариантов?
2. На схеме нет, но вроде в прошивке указан кварц 1МГц. В продаже такой не нашел, есть на 2 и 4, что нужно переделать чтоб применить их?
3. В строке где вычисляется напряжение в программе МК прибавляют 400 – не пойму зачем.
Ну вроде все, очень надеюсь на вашу помощь, автор проекта на связь не выходит.
Заранее большое спасибо.
программа вроде эта(у автора выложенно несколько, вроде все одинаковые)
Код: Выделить всё
#include <mega8.h>
#include <delay.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h>
#include <stdio.h> //библиотека в которой лежыт функция sprintf
int Af=4000,Uf=14200;
unsigned long int u; //переменная для хранения напряжения в миливольтах
unsigned long int a; //переменная для хранения тока
unsigned long int w; //переменная для хранения значений потребляемой мощности
void incSkvag()
{
if (OCR1AL!=0) OCR1AL--;
}
void decSkvag()
{
if (OCR1AL!=255) OCR1AL++;
}
#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;
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x64;
a=read_adc(3); // читаем значения ацп с порта 0
u=read_adc(5); // читаем значения ацп с порта 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
Измеряем напряжение Дальше измеряем напряжение на резисторном делителе Сложым пропорцию как описано выше и получим Искомое напряжения = 0,005*u*1000 Надо еще учесть коефициент резисторного делителя напряжения в нас он равен Кдел=(R1+R2)/R2 подставив получим Кдел=(10+1)/1=11 Рельное напряжения = 0,005*u*1000*11 */
u=55*u+400; //вычисляем значения напряжения в миливольтах
a=a*10; // вычесляем значения тока по закону ома I=U/R=a/100*1000=a*10, в милиамперах
w=a*u; //вычесляем потребляемую мощность
//регулировка напряжения и тока
if ( (a>Af) || (a>8000) )//регулировка по току
{
incSkvag();
}
else
{
if (u>Uf)//регулировка по напряжению
{
incSkvag();
}
else
{
decSkvag();
}
}
}
void main(void)
{
// Declare local variables here
unsigned char i=2,k[3][32];
sprintf( k[0],"Setup A=%i",Af);
sprintf( k[1],"Setup U=%i",Uf);
// Input/Output Ports initialization
PORTB=0b00011100;
DDRB= 0b00000010;
// Port C initialization
PORTC=0x00;
DDRC=0x00;
// Port D initialization
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 0,977 kHz
TCCR0=0x03;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: Fast PWM top=0x00FF
// OC1A output: Inverted
// 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=0xC1;
TCCR1B=0x0B;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0xff;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// 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=0x01;
// USART initialization
// USART disabled
UCSRB=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: AREF pin
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x81;
// SPI initialization
// SPI disabled
SPCR=0x00;
// TWI initialization
// TWI disabled
TWCR=0x00;
// Alphanumeric LCD initialization
lcd_init(16);
// Global enable interrupts
#asm("sei")
while (1)
{
sprintf( k[2],"I=%u,%uA U=%u,%uV\nW=%u,%lu K=%i",
a/1000, //Целая честь тока
(a%1000)/100, //Дробная часть тока
u/1000, // Целая часть напряжения
(u%1000)/100, //Дробная часть напряжения
w/1000000, // Целая часть мощности
(w%1000000)/100000, //Дробная часть мощности
OCR1AL
); //формируем строку для вывода
//---------------------------------------------------------------
//работа с кнопками
if (PINB.2==0)
{
//переключаем меню
if (++i>2) i=0;
}
if (PINB.3==0) //проверяем нажата ли кнопка плюс
{
if (i==0) {Af=Af+10; sprintf( k[i],"Setup A=%i ma",Af); }
if (i==1) {Uf=Uf+10; sprintf( k[i],"Setup U=%i mv",Uf); }
}
if (PINB.4==0) //проверяем нажата ли кнопка минус
{
if (i==0) { Af=Af-10; sprintf( k[i],"Setup A=%i ma",Af); }
if (i==1) { Uf=Uf-10; sprintf( k[i],"Setup U=%i mv",Uf);}
}
lcd_clear(); //чистим дисплей перед выводом
lcd_puts(k[i]); //выводим сформированую строку на дисплей
delay_ms(100); //делаем задержку
};
}