温度制御1 (PWM、オンオフ動作)の装置の性能を
下の表に示します。 使用したソフトを下に記載しておきます。 |
PWMオン時間 [%] | 初期の湯沸しポットの温度 [℃] | 20分後の湯沸しポットの温度 [℃] |
---|---|---|
5 | 21.3 | 23.3 |
10 | 23.3 | 30.2 |
15 | 30.2 | 38.7 |
20 | 38.7 | 49.5 |
25 | 49.5 | 61.7 |
30 | 61.7 | 74.2 |
35 | 74.2 | 75.5 |
How to Compile (コンパイルのしかた) プログラム /* * temp_ctrl2.c * * Created: 2017/03/14 22:27:59 * Author : User */ /* * short pwm_on_time; // PWMオン時間 (0 〜 100%) * 上記の変数 pwm_on_time を 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 0 * と変化させ、そのオン時間 (%) に対するポットの温度を RS-232C(115200 8-N-1)で出力する * * ATmega328P * * * Fuses(システムクロック:20MHz) * * * ディホルト Int. RC Osc. 水晶 外部クロック * DISABLED 2.7V 2.7V 2.7V * 8/8MHz 8MHz * EXTENDED 0xFF 0xFD 0xFD 0xFD * HIGH 0xD9 0xD9 0xD9 0xD9 * LOW 0x62 0xE2 0xF7 0xE0 */ #include <stdio.h> /* sprintf() */ #include <string.h> /* strlen() */ #include <avr/io.h> #include <avr/interrupt.h> ///#define F_CPU 20.0E6 /* 20 MHz */ ///#include <util/delay.h> #define USEC 1024 #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) typedef struct t_systim { short utime; /* 上位16bit */ unsigned long ltime; /* 下位32bit */ } SYSTIM; ///void delay_us(unsigned short t){while(t--) _delay_us(1);} ///void delay_ms(unsigned short t){while(t--) _delay_ms(1);} void initADC(void); void initTIMER(void); void get_tim(SYSTIM *p_tim); void initUSART0(void); void Send0(char *str); short ad_data; SYSTIM SYSCK; int main(void) { SYSTIM tim; static unsigned long ot[3]; float ondo; /* 温度 (0.0 〜 110.0℃) */ short pwm_on_time; /* PWMオン時間 (0 〜 100%) */ char buff[32], buff2[8]; int len; /* ATmega328P */ DDRB = 0b00000101; /* XTAL2 XTAL1 SCK MISO MOSI OC1B ----- LED */ DDRC = 0b00000000; /* xxxxx RESET ----- ----- ----- ----- ----- ----- */ DDRD = 0b00000000; /* ----- ----- ----- ----- ----- ----- TXD RXD */ PORTB = 0b00111010; PORTC = 0b00111110; PORTD = 0b11111100; initADC(); initTIMER(); initUSART0(); /* * WGM13 WGM12 WGM11 WGM10 動作種別 TOP値 * 1 1 1 1 高速PWM動作 OCR1A * * COM1A1 COM1A0 COM1B0 COM1B0 * 0 0 1 0 比較一致でLow、BOTTOMでHighをOC1Bピンへ出力(非反転動作) */ TCCR1A = 0b00100011; /* 一致時(OCR1B)Low, TOP->BOTTOM(OCR1A)でHighを */ /* OC1Bピンへ出力(非反転動作), 高速PWM動作 */ /// TCCR1B = 0b00011001; /* (1 / 20MHz) * 65535 = 3.3mS */ /// TCCR1B = 0b00011010; /* (8 / 20MHz) * 65535 = 26mS */ TCCR1B = 0b00011011; /* (64 / 20MHz) * 65535 = 210mS */ /// TCCR1B = 0b00011100; /* (256 / 20MHz) * 65535 = 839mS */ /// TCCR1B = 0b00011101; /* (1024 / 20MHz) * 65535 = 3355mS */ OCR1A = 0xffff; /* TOP->BOTTOMでHigh, 固定 */ OCR1B = 0; /* 一致時Low、可変(0はPWM出力on時間0%) */ sei(); Send0("START\r"); get_tim(&tim); ot[0] = tim.ltime; ot[1] = tim.ltime; ot[2] = tim.ltime; /* pwm_on_timeの初期値 */ pwm_on_time = 5; OCR1B = round(65535.0 * pwm_on_time / 100.0); while(1){ get_tim(&tim); if((unsigned long)(tim.ltime - ot[0]) >= 500000/USEC){ /* 500mS */ ot[0] = tim.ltime; PORTB ^= 0b00000001; } get_tim(&tim); if((unsigned long)(tim.ltime - ot[1]) >= 1000000/USEC){ /* 1S */ ot[1] = tim.ltime; /* 温度を得る 例 12.3℃ */ ondo = 1100.0 * ad_data / 10230; /* 0.0〜110.0℃ */ get_tim(&tim); if((unsigned long)(tim.ltime - ot[2]) >= 1200000000/USEC){ /* 20Min */ ot[2] = tim.ltime; /* pwm_on_time --> 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 */ if(5 <= pwm_on_time && pwm_on_time < 50) pwm_on_time += 5; else pwm_on_time = 0; OCR1B = round(65535.0 * pwm_on_time / 100.0); } /* 表示例 pwm_on_time = 10%, 14.2℃ */ sprintf(buff2, "%ld", round(ondo * 10)); len = strlen(buff2); buff2[len + 1] = buff2[len]; buff2[len] = buff2[len - 1]; buff2[len - 1] = '.'; sprintf(buff, "pwm_on_time = %d%%, %s℃\r", pwm_on_time, buff2); Send0(buff); } } } void initADC(void) { ADCSRA = 0b10101111; /* AD変換イネーブル, AD自動変換イネーブル,AD変換割り込みイネーブル */ /* 1/128クロック(最大変換時間=200uS @16MHz, 156uS @20MHz) */ ADCSRB = 0b00000011; /* タイマ/カウンタ0比較一致A */ ADMUX = 0b11000000; /* 基準電圧 = 1.1V(@atmega328p), 右詰, アナログ入力 = ADC0 */ } ISR(ADC_vect) { static long result; static short counter; result += ADC; counter++; if(counter >= 100){ counter = 0; ad_data = (short)(result / 100); result = 0; } } void initTIMER(void) { TCCR0A = 0b00000010; /* CTC動作 */ TCCR0B = 0b00000100; /* clk / 256 */ OCR0A = 80 - 1; /* (256 / 20MHz) * 80 = 1024uS */ TIMSK0 = 0b00000010; /* 比較A割り込み要求有効 */ } ISR(TIMER0_COMPA_vect) { if(++SYSCK.ltime == 0) ++SYSCK.utime; } void get_tim(SYSTIM *p_tim) { cli(); *p_tim = SYSCK; sei(); } void initUSART0(void) { UBRR0 = 21; /* U2X0 = 1, 115200ボー/20MHzクロック */ UCSR0A = 0b00000010; /* U2X0 = 1 */ UCSR0B = 0b00001000; /* 送信イネーブル */ UCSR0C = 0b00000110; /* 8ビット, パリティなし, ストップ・ビット1 */ } /* * 1データ送信 */ void Tx0(char data) { while((UCSR0A & _BV(5)) == 0) ; UDR0 = (unsigned char)data; } /* * 文字列を送信 */ void Send0(char *str) { while(*str != '\0'){ Tx0(*str); str++; } } |