基于Arduino和H桥生成PWM正弦波驱动电磁电机的频率控制咨询
问题根源
你修改f后输出没有变化,核心是两个问题:
- 计算正弦波样点时
f被约掉了:你用的公式2 * pi * f * n * dt里,dt = 1/(f*numSamples),代入计算后f直接消去,不管你把f设成多少,生成的sineSignal数组都是完全一样的20个半波绝对值采样点,波形本身不会有任何变化。 - 采样点延时是固定值:你写死了
delay(sampleFreq),也就是每个采样点停留2000ms,20个点走完整一个周期需要40秒,对应输出频率固定为0.025Hz,和你定义的f完全没有关联。
实现可变频率的修改方案
首先明确核心逻辑:输出正弦波的频率 = 1/(单周期采样点数 × 每个采样点的停留时间),你设置的numSamples=20就是单周期采样点数,只需要调整每个采样点的停留时间,就能直接控制输出频率。
修改后的参考代码如下:
const int DIR1_PIN = 4; const int DIR2_PIN = 5; const int PWM_PIN = 6; const int LED_PIN = 9; const int numSamples = 20; const float pi = 3.1415; float f = 1; // 按需修改这个值即可调整输出频率,单位Hz int sineSignal[numSamples]; int dir1Array[numSamples]; int dir2Array[numSamples]; void setup() { pinMode(LED_PIN, OUTPUT); pinMode(DIR1_PIN, OUTPUT); pinMode(DIR2_PIN, OUTPUT); pinMode(PWM_PIN, OUTPUT); // 正弦波表和输出频率无关,只生成一次即可 for (int n = 0; n < numSamples; n++) { // 这里直接用2πn/numSamples计算,不需要带f,结果和你之前的计算完全一致 sineSignal[n] = abs((int)(255 * sin(2 * pi * n / numSamples))); dir1Array[n] = n < numSamples / 2 ? HIGH : LOW; dir2Array[n] = n < numSamples / 2 ? LOW : HIGH; } } void loop() { // 根据目标频率计算每个采样点的停留时长,单位ms int sampleDelay = 1000 / (numSamples * f); for (int n = 0; n < numSamples; n++) { analogWrite(LED_PIN, sineSignal[n]); analogWrite(PWM_PIN, sineSignal[n]); digitalWrite(DIR1_PIN, dir1Array[n]); digitalWrite(DIR2_PIN, dir2Array[n]); delay(sampleDelay); } // 如果需要动态调整频率,比如外接电位器,直接在这里修改f的值即可,不需要重新生成波表 // 示例:f = map(analogRead(A0), 0, 1023, 1, 10); 即可实现1~10Hz的频率连续调节 }
补充说明
- 如果需要输出的频率较高(比如超过10Hz),
delay()的精度会不足,而且延时期间CPU无法处理其他任务,建议换成millis()实现非阻塞延时,或者用定时器中断触发射频输出,频率精度会高很多。 - 目前的方向切换是半周时直接跳变,如果电磁阀工作时有明显顿挫感,可以在H桥输出端加一级RC低通滤波,输出的正弦波形会更平滑。
内容的提问来源于stack exchange,提问作者Hadar
相关产品推荐
相关产品推荐

