arduino中使用tone()函数出错问题
我初学arduino,买了一套arduino套件。我在http://www.geek-workshop.com/thread-2433-1-1.html学习了使用红外遥控器,然后想到用遥控器控制板子发音演奏音乐。我使用A2接受红外信号,4口控制蜂鸣器。使用代码如下#include <IRremote.h>// 使用IRRemote函数库const int irReceiverPin = 2;// 红外接收器的 OUTPUT 引脚接在 PIN2 接口 定义irReceiverPin变量为PIN2接口
IRrecv irrecv(irReceiverPin); // 设置irReceiverPin定义的端口为红外信号接收端口
decode_results results; // 定义results变量为红外结果存放位置
void setup()
{
irrecv.enableIRIn(); // 启动红外解码
pinMode(4,OUTPUT); // 设置4口为输出模式
}
void loop()
{
int a;
if (irrecv.decode(&results)) {
switch(results.value){
case 16580863:(a=262);break;
case 16613503:(a=294);break;
case 16597183:(a=330);break;
case 16589023:(a=349);break;
case 16621663:(a=392);break;
case 16605343:(a=440);break;
case 16584943:(a=494);break;
case 16617583:(a=523);break;
case 16601263:(a=587);break;
case 16593103:(a=659);break;
case 16625743:(a=698);break;
case 16609423:(a=784);break;
case 16582903:(a=889);break;
case 16615543:(a=988);break;
case 16599223:(a=1046);break;
case 16591063:(a=1175);break;
case 16623703:(a=1318);break;
case 16607383:(a=1397);break;
case 16586983:(a=1568);break;
case 16619623:(a=1760);break;
case 16603303:(a=1976);break;
default:(a=0); // 使红外代码与频率对应
}
tone(4,a,300); // 4口发音,持续300毫秒
irrecv.resume(); // 继续等待接收下一组信号
}
delay(600); //延时600毫秒,做一个简单的消抖
}
结果编译出错,显示。
经过反复调试,发现故障在tone()函数,只要没有这个函数就能正常工作,比如这个程序能工作#include <IRremote.h>// 使用IRRemote函数库
const int irReceiverPin = 2;// 红外接收器的 OUTPUT 引脚接在 PIN2 接口 定义irReceiverPin变量为PIN2接口
IRrecv irrecv(irReceiverPin); // 设置irReceiverPin定义的端口为红外信号接收端口
decode_results results; // 定义results变量为红外结果存放位置
void setup()
{
irrecv.enableIRIn(); // 启动红外解码
pinMode(4,OUTPUT);
Serial.begin(9600);
}
void loop()
{
int a;
if (irrecv.decode(&results)) {
switch(results.value){
case 16580863:(a=262);break;
case 16613503:(a=294);break;
case 16597183:(a=330);break;
case 16589023:(a=349);break;
case 16621663:(a=392);break;
case 16605343:(a=440);break;
case 16584943:(a=494);break;
case 16617583:(a=523);break;
case 16601263:(a=587);break;
case 16593103:(a=659);break;
case 16625743:(a=698);break;
case 16609423:(a=784);break;
case 16582903:(a=889);break;
case 16615543:(a=988);break;
case 16599223:(a=1046);break;
case 16591063:(a=1175);break;
case 16623703:(a=1318);break;
case 16607383:(a=1397);break;
case 16586983:(a=1568);break;
case 16619623:(a=1760);break;
case 16603303:(a=1976);break;
default:(a=0);
}
Serial.println(a);
irrecv.resume(); // 继续等待接收下一组信号
}
delay(600); //延时600毫秒,做一个简单的消抖
}
请大家赐教,为啥tone()会出错,是不是与红外解码的库有矛盾,怎么解决?
我也出现了同样问题,有高人给解答一下吧!!! 4口不支持pwm
建议你换成3/5/6这样的输出口播放声音 本帖最后由 TylerTian 于 2015-7-15 14:46 编辑
出错是因为Arduino IDE 中的tone函数和IRremote函数中都用到了同一个定时器,对于这个问题目前还没有好的解决方法,如果你懂的话应该可以重新写一下IRremote.cpp,用一个不同的定时器,或者重新写tone函数也可以
这是在别的地方看到的一个可以代替tone函数的函数:
void newtone(byte tonePin, int frequency, int duration) {
int period = 1000000L / frequency;
int pulse = period / 2;
for (long i = 0; i < duration * 1000L; i += period) {
digitalWrite(tonePin, HIGH);
delayMicroseconds(pulse);
digitalWrite(tonePin, LOW);
delayMicroseconds(pulse);
}
} TylerTian 发表于 2015-7-15 14:42 static/image/common/back.gif
出错是因为Arduino IDE 中的tone函数和IRremote函数中都用到了同一个定时器,对于这个问题目前还没有好的解 ...
请问Arduino里面的自带函数在哪里可以看到实现原型?
比如说digitalWrite,delay,tone……
请问楼主解决了问题没有?我现在遇到同样的麻烦,烦请楼主赐教 本帖最后由 shouzama 于 2018-3-4 17:03 编辑
mnbvb 發表於 2018-3-3 20:54
請問樓主解決了問題沒有?我現在遇到同樣的麻煩,煩請樓主賜教
當初庫相衝時,我也發現了是它們動用到同一個計時器所造成,
要重寫 IR_REMOTE 或 TONE? 我覺得應該是 TONE 比較簡單,
上網找了一些資料後(因為資料比較雜,已記不得資料來源),
我自己寫了個函式,並且跟 TONE 進行比較,微調常數、修改程式...
反覆測試多次後,完成了取代 TONE 的自製函式
以下是我的測試程式(程式碼是基於 TONE 的範例程式進行修改
做成),可以在 BZ 硬體接線完成的狀態下,先上傳這個程式試試看
自製函式跟 TONE 函式聲音是否明顯不同(我是聽不出來有明顯差別 ^^" ):
==========================
#include <Pitches.h> //這份 .h 的音符定義檔我有重新改過,必要時請修改 melody 陣列定義內容
//定義 NOP (虛工指令)
#define NOP do { __asm__ __volatile__ ("nop"); } while (0)
#define SPEAKER 11 //定義喇叭接腳
//小蜜蜂 = 62
int melody[]= { Note_G5, Note_E5, Note_E5, 0, Note_F5, Note_D5, Note_D5, 0,
Note_C5, Note_D5, Note_E5, Note_F5, Note_G5, Note_G5, Note_G5, 0,
Note_G5, Note_E5, Note_E5, 0, Note_F5, Note_D5, Note_D5, 0,
Note_C5, Note_E5, Note_G5, Note_G5, Note_E5, 0,
Note_D5, Note_D5, Note_D5, Note_D5, Note_D5, Note_E5, Note_F5, 0,
Note_E5, Note_E5, Note_E5, Note_E5, Note_E5, Note_F5, Note_G5, 0,
Note_G5, Note_E5, Note_E5, 0, Note_F5, Note_D5, Note_D5, 0,
Note_C5, Note_E5, Note_G5, Note_G5, Note_C5, 0 };
int noteDurations[]={ 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 2, 2,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 2, 2 };
//撰寫自己的延時函式(以奈秒計)
void delayNANO( unsigned long NANO ) //無回傳值,引數 NANO 為延時奈秒值
{
for (unsigned long I=0; I< (unsigned int) (NANO*1.3) ; I++)
{ NOP; }
}
//撰寫自己的響音函式,引數:喇叭接腳定義 SPEAKER_PIN,音頻定義 FREQUENCY,節拍定義 TEMPO
void sz_tone( int SPEAKER_PIN, int FREQUENCY, unsigned long TEMPO )
{
pinMode( SPEAKER_PIN, OUTPUT); //定義喇叭接腳為輸出用
unsigned long CYCLE = 1000000/FREQUENCY; //一開始CYCLE*1000倍提高換算精確度,算出週期時間
unsigned long LOOP = ( TEMPO*1000 / CYCLE); //迴圈數(多=時間長)=分子*1000倍調回正常比例
if ( FREQUENCY == 0) //若頻率值為 0 (休止符)則延遲 TEMPO 時間不發聲
delay( TEMPO );
else //若頻率值不為 0 (非休止符) 則發聲
{
for ( unsigned long I=0; I < LOOP; I++ ) //發聲時間長短由 LOOP 設定
{
digitalWrite( SPEAKER_PIN, HIGH ); //發聲音
delayNANO( CYCLE/2 ); //延時1/2週期
digitalWrite( SPEAKER_PIN, LOW ); //不發聲音
delayNANO( CYCLE/2 ); //延時1/2週期
}
}
delay( int ( TEMPO*0.3 )); //暫停(音符間的區隔)
}
void setup()
{
}
void loop()
{
//先用自己寫的函式演奏小蜜峰,共 62 音符(含休止符)
for (int thisNote = 0; thisNote < 62; thisNote++)
{
int noteDuration = 1000 / noteDurations;
sz_tone(SPEAKER, melody, noteDuration); //函式內已內建音符區隔的暫停
}
delay(2000);
//再用標準 tone 函式演奏
for (int thisNote = 0; thisNote < 62; thisNote++)
{
// to calculate the note duration, take one second divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000 / noteDurations;
tone( SPEAKER, melody, noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(SPEAKER);
}
delay(2000);
}
==========================
函式已實測修正過 ^^ shouzama 发表于 2018-3-3 23:42
當初庫相衝時,我也發現了是它們動用到同一個計時器所造成,
要重寫 IR_REMOTE 或 TONE? 我覺得應該是 TON ...
:hug:厉害!
页:
[1]