arduinoでPWMの周波数を変える方法について
A0でDuty比、A1で周波数を変化させます。
出力はD10にしました。
参考までにソースコードを末尾に載せます。(D10の出力固定です。動作保証はしません)
細かい設定については参考先参照願います。
データシート読むの苦手です。
TCCR0はタイマのカウントにも使用していて
TCCR2は周期を細かく変えるのに向いてないみたいなので、
TCCR1(D9,D10ピン)を使用することにしました。
参考:
ATMEGA328Pのデータシート
日々 ほげほげ 研究所
garret lab
作成したプログラム
/*
2016/10/10
D10の出力周波数・Dutyを変化させる
(20kHz, 24%設定)
A0、A1の値で周波数・Dutyを変化させる予定
*/
int Vol_duty = A0; //
int Vol_freq = A1; //
int PWMPin = 10; // select the pin for PWM
int ledPin = 13; // select the pin for the LED
int Value_duty = 0; //
int Value_freq = 0; //
int u = 0; //
void setup() {
// declare the ledPin as an OUTPUT:
pinMode(ledPin, OUTPUT);
pinMode(ledPin, OUTPUT);
// シリアルポートを9600 bps[ビット/秒]で初期化
Serial.begin(9600);
//f=fc/(2*TOP*r) ( fc = 16MHz )
//Show Table 16-4. Waveform Generation Mode Bit Description
TCCR1A &= B11111100;
TCCR1A |= B00000001;//
TCCR1B &= B11100111;
TCCR1B |= B00010000;//
//Show Table 16-5. Clock Select Bit Description
//value of r, 1 8 64 256 1024
TCCR1B &= B11111000;
TCCR1B |= B00010010;// 8分周
//Value of TOP
OCR1A = 50; //change freq
}
void monitor(){
Serial.println("Check values");
Serial.println(TCCR1A,BIN);//COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10
Serial.println(TCCR1B,BIN);//ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
Serial.println(OCR1A,BIN);//value of TOP
Serial.println(OCR1B,BIN);//PWM on value
Serial.println("u");
Serial.println(u);
// Serial.println(OCR2B,BIN);
}
void change_reg(){
u = Value_freq * 20;
if( u > 3900 ){
TCCR1B &= B11100000;
TCCR1B |= B00010010;// 8分周
OCR1A = 1000000/u;
} else {
TCCR1B &= B11100000;
TCCR1B |= B00010011;// 64分周
OCR1A = 125000/u;
}
}
void loop() {
// read the value from the sensor:
Value_duty = analogRead(Vol_duty) >> 2; //0~255;
// Value_freq = analogRead(Vol_freq); //100 ~ 20000[Hz]
// turn the ledPin on
digitalWrite(ledPin, HIGH);
// stop the program for milliseconds:
delay(50);
// turn the ledPin off:
digitalWrite(ledPin, LOW);
// stop the program for for milliseconds:
delay(50);
if(Value_freq == 1000) Value_freq = 0;
Value_freq += 5; //chenge freq
if(Value_freq > 1000) Value_freq = 1000; //20kHz相当
if(Value_freq < 50) Value_freq = 50; //1kHz相当
change_reg(); //change OCR1A, TCCR1B
Value_duty = OCR1A >> 1; //50%
analogWrite(PWMPin,Value_duty);
monitor(); //debug用
}