複数のADCチャネルから読み取り値を取得し、それらを単一の信号に結合し、この信号をPWMを介して出力するATMega328P用のプログラムを作成しています。
シングル変換モードを使用して、ADC ポーリングをチャンネルあたり 50Hz に戻すことに成功しました。PWM 生成には Timer/Counter2 を使用し、Timer/Counter2 の比較値を設定するために必要な計算には Timer/Counter1 を使用しています。これは、Timer/Counter1 の ISR です。
// Interrupt service routine called to generate PWM compare values
ISR(TIMER1_COMPA_vect)
{
// Grab most recent ADC reading for ADC0
uint32_t sensor_value_0 = adc_readings[0];
// Get current value for base waveform from wavetable stored in sinewave_data
uint32_t sample_value_0 = pgm_read_byte(&sinewave_data[sample_0]);
// Multiply these two values together
// In other words, use the ADC reading to modulate the amplitude of base wave
uint32_t sine_0 = (sample_value_0 * sensor_value_0) >> 10;
// Do the same thing for ADC2
uint32_t sensor_value_1 = adc_readings[1];
uint32_t sample_value_1 = pgm_read_byte(&sinewave_data[sample_1]);
uint32_t sine_1 = (sample_value_1 * sensor_value_1) >> 10;
// Add channels together, divide by two, set compare register for PWM
OCR2A = (sine_0 + sine_1) >> 1;
// Move successive ADC base waves through wavetable at integral increments
// i.e., ADC0 is carried by a 200Hz sine wave, ADC1 at 300Hz, etc.
sample_0 += 2;
sample_1 += 3;
// Wrap back to front of wavetable, if necessary
if (sample_0 >= sinewave_length) {
sample_0 = 0;
}
if (sample_1 >= sinewave_length) {
sample_1 = 0;
}
} // END - Interrupt service routine called to generate PWM compare values
私の問題は、PWM 出力が得られないことです。または のどちらsensor_value_0
かsensor_value_1
を設定し1024
、もう一方sensor_value_
を ADC から読み取るように設定した場合、1 つの完全振幅成分波と振幅変調された成分波が得られます。ただし、ハードコードされたモック振幅に別の値を選択した場合、それほど幸運ではありません (1023
たとえば、 )。それ以外の値では、PWM 出力が得られません。両方 の を同じ ADC チャネルを見るように設定sensor_value_
すると、2 つの成分波の振幅が同じように変調されることが予想されます。代わりに、PWM 出力が得られません。私にとって最も紛らわしいのは、厳密に 2 の累乗であるハードコードされた振幅の値を選択した場合、すべてがうまくいくということです。
2 の累乗の部分全体が、これを私が見ていない少し厄介な問題のように思わせます。私が明らかに見逃していたに違いないものが見えますか?ヒントをいただければ幸いです。
( SO で可能な限り整理するために、ソース全体をここに投稿しました。)