ATtiny202で正弦波を作るとノイズが乗るので、問題の切り分けのためにATtiny85で同じことをやってみる。
ATtiny85はブレッドボードに差してワイヤで接続。
ATtiny85ではきれいな正弦波が得られる。アンプを通して聞いても澄んだ音に聞こえる。このことから、やり方に問題はないはず。
プログラムの内容はATtiny202で行ったものと、当然、同じ。タイマ/カウンタを二つ使い、一つをPWMの発生に、もう一つを周期割込みに。割込みハンドラで予め用意した正弦波のテーブルに従ってPWMのデューティ比を変えるだけ。
コードは例によってBingチャットで作ったもの(をベースにしている)。
#include <avr/io.h>
#include <avr/cpufunc.h>
#include <avr/interrupt.h>
#include <math.h>
#define F_CPU 8000000UL
#define N_WAVE 32 /* 正弦波テーブルの数(一周期分) */
unsigned char wave[N_WAVE]; // 正弦波テーブル
volatile unsigned char i_wave; // 正弦波テーブルの参照ポインタ
volatile uint8_t pwm_value = 0;
void setup() {
float unit_deg;
int i;
i_wave = 0;
/* 正弦波テーブル作成 */
unit_deg = (2.0 * 3.141592) / (float)(N_WAVE);
for (i = 0; i < N_WAVE; i++) {
wave[i] = (unsigned int)((((sin(unit_deg * (float)i) + 1.0) / 2.0) * 255.0) + 0.5);
}
// タイマ/カウンタ0: 正弦波出力割込み周期設定 */
TCCR0A = (1 << WGM01); // CTCモード
TCCR0B = (1 << CS01); // プリスケーラ8でカウント開始
OCR0A = 31; // 周期を設定(32kHz)
TIMSK |= (1 << OCIE0A); // OCR0Aに一致したら割り込み発生
// タイマ/カウンタ1: 正弦波用PWM周波数設定 */
DDRB |= (1 << PB4); // PB4を出力に設定
TCCR1 |= (1 << CTC1) | (1 << COM1B1) | (1 << PWM1B);
GTCCR |= (1 << PWM1B) | (1 << COM1B0);
OCR1C = 255; // PWMの分解能は256
OCR1B = 127; // デューティ比50%
TCCR1 |= (1 << CS10); // タイマ/カウンタ1 を開始
}
/* 割込みハンドラ: 正弦波出力 */
ISR(TIM0_COMPA_vect) {
OCR1B = wave[i_wave];
i_wave++;
if (i_wave >= N_WAVE) {
i_wave = 0;
}
}
void loop() {
}
int main() {
setup();
sei();
while(1) {
loop();
}
}
うーん、ATtiny202では何がいけないんだろう?正弦波の下りカーブにだけノイズが乗るのは謎すぎる…。
コメント