پروژه کنترل سرعت چرخش فن با توجه به دما – قسمت سوم
سوال: pwm چگونه سرعت موتور را کنترل میکند!؟( میکروکنترلر avr )
ابتدا فرکانس تایمر را حساب میکنیم و میبینم ک هر پالس میتواند چقد طول داشته باشد.
F_cpu=10MHz; à F_timer=F_cpu/64=156.250 KHz
timer=1/156.250k=64 us
دقت نمایید که در این پروژه از یک کریستال خارجی ۱۰ مگاهرتزی به عنوان کلاک میکروکنترلر avr در نظر گرفته شده است.
جدا از عملکرد عادی تایمر، هر سه تایمر در سه مد کاری می توانند کار کنند:
مد نرمال،
مد CTC
مد PWM
یعنی محتوای رجیستر TCNT0 هر۶۴ میکرو ثانیه یکبار افزایش می یابد. پس یک دوره کامل شمارش یا همان دوره تناوب پالس برابر با ۲۵۵*۶۴ یعنی ۱۶٫۳۲۰ میلی ثانیه. و دیوتی سایکل یا همان زمان وظیفه را رجیستر OCR0 تنظیم میکند که میتواند بین ۰ تا ۲۵۵ به آن نسبت داد.
به شکل خروجی پایه oc0 در چند دمای مختلفت دقت نمایید.(اگر ماکسیمم دما روی ۵۰ درجه باسد).
وقتی دما ۲۰ درجه باشد آنگاه زمان وضیفه برابر ۲۰/۵۰ یعنی ۴۰% dc= میباشد:
هرگاه ولتاژ به موتور اعمال شود شروع به چرخیدن می کند، و هرگاه ولتاژ اعمالی صفر شود رو به توقف می رود اما فوراً متوقف نمی شود، بلکه مدتی طول می کشد تا به طور کامل بایستد. اما قبل از این که کاملا متوقف شود، دوباره ولتاژی به موتور اعمال شده و شروع به چرخیدن می نماید. اما باز هم نیاز به زمانی دارد تا به سرعت نهایی برسد ولی قبل از آن دوباره ولتاژ صفر می شود و این روال به همین ترتیب تکرار و تکرار می شود. در نهایت تاثیر چنین ولتاژی بر روی موتور بدین صورت است که موتور همواره در حال چرخش است ولی در سرعتی کمتر از سرعت نهایی اش. هرچه زمان وظیفه بیشتر باشد سرعت چرخش موتور نیز بیشتر است.
کد کامل برنامه نوشته شده:
این سورس برای محیط کدویژن ( ۳٫۱۲ ) نوشته شده است. و میکرو کنترلر avr انتخاب شده atmega16a می باشد.
/*
* avr-lm35-dc-fan.c
*
* Created: 2016/12/10 08:24:39 ق.ظ
* Author: Reza.Ahmadi
* url: mrzx.ir
*/
#include <io.h>
#include <delay.h>
#asm
.equ __lcd_port=0x15 ;//PORTC
#endasm
#include <lcd.h>
#include <stdio.h> //for using Sprintf
#define Fan1 OCR0;
#define Fan2 PORTB.1
#define up PIND.2
#define down PIND.3
float T=0.0;
unsigned int PW=0;
unsigned char strLCD[16];
unsigned char Max_tmp=50;
void adc_init();
unsigned short int read_adc(unsigned char input_pin);
float read_temp();
void Timer0_init();
interrupt [TIM0_OVF] void timer0_isr();
void set_pw();
void set_max_tmp();
void def_chr(flash unsigned char* data,unsigned char chrcounter);
flash unsigned char degree[]={0x0e,0x11,0x11,0x11,0x0e,0x00,0x00,0x00};
void main(void)
{
DDRD=0x00;
lcd_init(16);
def_chr(degree,0);
lcd_putsf("-----Hello-----");
lcd_gotoxy(0,1);
lcd_putsf("MRZX.ir");
delay_ms(4000);
lcd_clear();
adc_init();
Timer0_init();
#asm("sei");
lcd_gotoxy(0,1);
sprintf(strLCD,">Max Temp=%d ",Max_tmp);
lcd_puts(strLCD);
while (1)
{
read_temp();
set_pw();
set_max_tmp();
}
}
void adc_init()
{
ACSR=0x80;
SFIOR=0x00;
ADMUX=(1<<REFS1)|(1<<REFS0);//using interenal 2.56v Voltage reference...
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(0<<ADPS0);//Enable ADC with Prescalar=Fcpu/16
}
unsigned short int read_adc(unsigned char input_pin)
{
ADMUX |=(input_pin&(0x07))|(1<<REFS1)|(1<<REFS0);
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
ADCSRA|=(1<<ADIF);
return (ADCW);
}
float read_temp()
{
T=(read_adc(0)*2.56/1024)*100 ;
return T;
}
//***********************//
void Timer0_init()
{
TCNT0=0x00;
TCCR0 |=(1<<CS00)|(1<<CS01) | (1<<WGM00)|(1<<WGM01)|(1<<COM01);//fcpu/64
TIMSK |= (1 << TOIE0);
DDRB=0xff;
}
interrupt [TIM0_OVF] void timer0_isr()
{
static int delay=0;
TCNT0=0x00;
TCCR0=0x00;
if(delay++>=1000)
{
lcd_gotoxy(0,0);
sprintf(strLCD,">Temp=%0.2f ",T);
lcd_puts(strLCD);
lcd_putchar(0);lcd_putchar('C');
delay=0;
}
OCR0=PW;
TCCR0 |=(1<<CS00)|(1<<CS01) | (1<<WGM00)|(1<<WGM01)|(1<<COM01);//fcpu/64
}
void set_pw()
{ if(T<=(Max_tmp/3))
{
PW=1;
Fan2=0;
}
else if(((Max_tmp/3)<T) && (T<Max_tmp) )
{
PW=(T/Max_tmp)*255;
Fan2=0;
}
else
{
PW=254;
Fan2=1;
}
}
void def_chr(flash unsigned char* data,unsigned char chrcounter)
{
unsigned char adrs;
char i=0;
//unsigned char adrs=0x40;
adrs=(chrcounter<<3)|0x40;
for(i=0;i<8;i++)
lcd_write_byte(adrs++,*data++);
}
void set_max_tmp()
{
if(down==0)
{
if(Max_tmp>=10)
{
Max_tmp -=5;
lcd_gotoxy(0,1);
sprintf(strLCD,">Max Temp=%d ",Max_tmp);
lcd_puts(strLCD);
while(down==0);
}
}
if(up==0)
if(Max_tmp<=85)
{
Max_tmp +=5;
lcd_gotoxy(0,1);
sprintf(strLCD,">Max Temp=%d ",Max_tmp);
lcd_puts(strLCD);
while(up==0);
}
}
دیدگاهتان را بنویسید