You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino Uno按键电话玩具SD卡音频播放故障求助

Arduino Uno按键电话玩具组合后无法播放SD卡音频

问题描述

我制作了一款基于Arduino Uno的按键电话玩具,使用旧按键、SD卡读卡器和低音质扬声器。各组件单独测试均工作正常,但组合后无法播放SD卡中存储的音频——按键、SD读卡器、扬声器各自功能正常,找不到解决办法,附上代码及设备图片:

设备外观
设备接线

原代码

#include <Arduino.h>
#include <Keypad.h>
#include <SD.h>                      // need to include the SD library
//#define SD_ChipSelectPin 53  //example uses hardware SS pin 53 on Mega2560
#define SD_ChipSelectPin 4  //using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h>           //  also need to include this library...
#include <SPI.h>


// C++ code

//#define buzer A0;

TMRpcm tmrpcm;
unsigned long time = 0;


const byte ROWS = 4;
const byte COLS = 4;

byte rowPins[ROWS] = {A5, A4, A3, A2};
byte colPins[COLS] = {5, 3, 2, 0};

char keys[ROWS][COLS] ={
    {'3','2','1','a'},
    {'*','0','9','b'},
    {'7','6','5','c'},
    {'.','8',',','d'},
};

Keypad klawiatura = Keypad(makeKeymap(keys), rowPins,colPins,ROWS,COLS);

String tekst;
const String tel_book[3] = {"","123","321"}; // tu wpisujemy numery pod którymi znajdują sie scieżki dźwiękowe
char* track_list[3] = {"","test.wav","0002.wav"}; // tu wpisujemy nazwy ścieżek dźwiekowych
int lokalizator;

void setup()
{
  tmrpcm.speakerPin = 10; //5,6,11 or 46 on Mega, 9 on Uno, Nano, etc
  //Complimentary Output or Dual Speakers:
  //pinMode(10,OUTPUT); Pin pairs: 9,10 Mega: 5-2,6-7,11-12,46-45 
  
  Serial.begin(9600);
  pinMode(13,OUTPUT); //LED Connected to analog pin 0 | w sumie to nie wiem ale bez tego nie działa
  if (!SD.begin(SD_ChipSelectPin)) {  // sprawdza czy karta sd jest poprawnie zainstalowana na miejscu
    Serial.println("SD fail");  
    return;   // jeśli nie to wyłącza program

  }
  else{   
    Serial.println("SD ok");
  }
  tmrpcm.volume(4);
  tmrpcm.play("test.wav"); // odgrywa testowy dźwięk po włączeniu urządzenia
  
}

void loop()
{
  char klawisz = klawiatura.getKey(); // pobiera dane z klawiatury i przypisuje do zmiennej
  if (klawisz)
  {
    tekst += klawisz; //wybieranie numeru
    Serial.println(tekst);
    if (tekst.length()==3) // gdy długość numeru jest odpowiednia zaczyna szukac go w książce telefonicznej
    {
        for (int i = 0; i < sizeof(tel_book)/sizeof(*tel_book); i++)
        {
            if (tel_book[i] == tekst)
            {
                lokalizator = i+1; // po znaleziemiu odpowiedniego numeru wybiera jego pozycje z listy
                //Serial.println(i);
                //delay(1000);
                //Serial.println(lokalizator);
                Serial.println("corect num");
                tekst = "";
                return;
            }else{
              tmrpcm.play("0001.wav");// odtworzenie informacji o błednie wybranym numerze
              Serial.println("wrong num");
              lokalizator = 0;
              tekst = "";
              return; 
            }
            
        }
           // wcześniej odnaleziony numer inicjuje odtworzenie odpowiedniej ścieżki dźwiękowej
      tmrpcm.play(track_list[lokalizator]); // to powinno już działac ale jeszcze nie wiem czy tak jak chce  
      tekst = "";
    }
    
  }
  

}

问题分析与修复

代码存在几个关键逻辑错误,导致组合后无法正确触发音频播放:

  1. 循环逻辑错误:匹配电话号码的for循环中,只要第一个元素不匹配就立刻执行错误分支返回,根本不会检查后续的电话号码。比如输入123时,i=0时tel_book[0]是空字符串,不匹配就直接播放错误音频返回,永远到不了i=1的匹配逻辑。
  2. 播放代码位置错误:正确匹配后的播放代码被放在for循环外面,但因为匹配成功后直接return了,这段代码永远不会被执行。
  3. 变量初始化问题:lokalizator没有初始值,可能导致意外行为。

修正后的代码

#include <Arduino.h>
#include <Keypad.h>
#include <SD.h>
#define SD_ChipSelectPin 4
#include <TMRpcm.h>
#include <SPI.h>

TMRpcm tmrpcm;

const byte ROWS = 4;
const byte COLS = 4;
byte rowPins[ROWS] = {A5, A4, A3, A2};
byte colPins[COLS] = {5, 3, 2, 1}; // 将原0号引脚替换为1号,避免串口RX冲突

char keys[ROWS][COLS] ={
    {'3','2','1','a'},
    {'*','0','9','b'},
    {'7','6','5','c'},
    {'.','8',',','d'},
};

Keypad klawiatura = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

String tekst;
const String tel_book[3] = {"", "123", "321"};
char* track_list[3] = {"", "test.wav", "0002.wav"};
int lokalizator = 0; // 初始化变量

void setup()
{
  tmrpcm.speakerPin = 10;
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  
  if (!SD.begin(SD_ChipSelectPin)) {
    Serial.println("SD fail");
    return;
  }
  Serial.println("SD ok");
  
  tmrpcm.volume(4);
  tmrpcm.play("test.wav");
}

void loop()
{
  char klawisz = klawiatura.getKey();
  if (klawisz)
  {
    tekst += klawisz;
    Serial.println(tekst);
    
    if (tekst.length() == 3)
    {
      bool numFound = false;
      // 从i=1开始遍历,跳过空字符串元素
      for (int i = 1; i < sizeof(tel_book)/sizeof(*tel_book); i++)
      {
        if (tel_book[i] == tekst)
        {
          lokalizator = i;
          Serial.println("correct num");
          tmrpcm.play(track_list[lokalizator]); // 匹配成功后立即播放音频
          numFound = true;
          break;
        }
      }
      
      // 所有号码都不匹配时播放错误提示
      if (!numFound)
      {
        tmrpcm.play("0001.wav");
        Serial.println("wrong num");
      }
      
      tekst = ""; // 重置输入字符串,等待下一次输入
    }
  }
}

额外注意事项

  • 音频文件格式:确保SD卡中的WAV文件为8位、单声道、采样率≤32kHz,文件名采用8.3格式(如0001.wav),无中文或特殊字符。
  • 引脚冲突:原代码中按键列引脚使用了0号(串口RX),会影响串口调试和按键读取,已替换为1号引脚,若使用其他引脚需确保无冲突。
  • 电源稳定性:SD卡读卡器和扬声器同时工作时电流需求较高,建议使用外部5V电源供电,避免USB口供电不足导致的异常。

内容的提问来源于stack exchange,提问作者pawko774

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 00:00:54