Микрофон2

nail2007
Offline
Зарегистрирован: 08.12.2017

Всем привет!

Прошу прощения, что создаю новую тему по старому вопросу. Не нашел как можно удалить старую тему.

В ходе разбирательств с работой микрофона и ардуино нашел библиотеку для записи аудио файлов на сд карту. Большими усилиями я переделал найденные примеры в сети и получил код для записи на карту звуков определенной длительности (задается в начале скетча). Запись начинается путем нажатия на кнопку. Используются Ардуино Нано, МАХ9814, Модуль для микроСД карт HW-125.

Проблема в том, что если скетч из примера работает идеально, то мой не записывает данные на карту.

К сожалению, я не понимаю где ошибка в коде. Может быть кто-то на форуме ее найдет.

Инициализация микросд карты проходит норм - в мониторе порта SD OK

При нажатии на кнопку идет сообщения о старте записи, а далее об ее окончании

#include <SD.h>
#include <SPI.h>
#include <TMRpcm.h>
#include <EEPROM.h>

#define SD_ChipSelectPin 4  //using digital pin 4 on arduino nano 328, can use other pins , CS
#define microphone_pin A0
TMRpcm audio;   // create an object for use in this sketch 
int RecordNumber;
char FileName[10];

const int buttonPin = 8;     // the number of the pushbutton pin
const int ledPin =  6;      // the number of the LED pin

int buttonState;         // variable for reading the pushbutton status
int recordState = 0;  // if the recording is going on
int recordTime = 3; // sec

void setup() {
  pinMode(ledPin, OUTPUT); // initialize the LED pin as an output
  pinMode(buttonPin, INPUT_PULLUP);   // initialize the pushbutton pin as an input
  pinMode(12,OUTPUT);  //Pin pairs: 9,10 Mega: 5-2,6-7,11-12,46-45, MISO
  Serial.begin(9600);
  
  if (!SD.begin(SD_ChipSelectPin)) {  
    Serial.println("sd faild"); 
    return;
  }else{
    Serial.println("SD OK"); 
  }
  // The audio library needs to know which CS pin to use for recording
  audio.CSPin = SD_ChipSelectPin;
  RecordNumber = EEPROM.read(0);
}


void loop() {
  buttonState = digitalRead(buttonPin);
  if (buttonState == LOW) {
    Serial.println("button is pressed");
    RecordNumber++;
    EEPROM.write(0, RecordNumber);
    sprintf(FileName,"Audio_%d.wav", RecordNumber); 
    audio.startRecording(FileName,16000,microphone_pin); 
    Serial.println("recording start");
    digitalWrite(ledPin, HIGH);
    delay(recordTime*1000); 
    audio.stopRecording(FileName); 
    Serial.println("recording stopped");
    digitalWrite(ledPin, LOW); 
    } 
}

 

b707
Offline
Зарегистрирован: 26.05.2017

А зачем вы заказываете запись 16сек длиной, а прерываете ее через три?
Скажу честно, я не знаю точно как это работает, но скорее всего это приводит к сбросу записи и ничего не сохраняется либо же файл получается "битый".

nail2007
Offline
Зарегистрирован: 08.12.2017

Здравствуйте!

Если Вы про 44 строчку, то 16000 это задается частота дискретизации

b707
Offline
Зарегистрирован: 26.05.2017

nail2007 пишет:

Проблема в том, что если скетч из примера работает идеально, то мой не записывает данные на карту.

а если сравнить ваш скетч и пример - в чем разница? она вроде должна быть очевидна, там кода-то всего ничего

nail2007
Offline
Зарегистрирован: 08.12.2017

Разница большая. Вот стандартный пример из библиотеки

#include <SD.h>
#include <SPI.h>
#include <TMRpcm.h>

//#define SD_ChipSelectPin 53  //example uses hardware SS pin 53 on Mega2560
#define SD_ChipSelectPin 10  //using digital pin 4 on arduino nano 328, can use other pins
#define microphone_pin A0
TMRpcm audio;   // create an object for use in this sketch 

void setup() {
  
  pinMode(12,OUTPUT);  //Pin pairs: 9,10 Mega: 5-2,6-7,11-12,46-45
  
  Serial.begin(9600);
  
  if (!SD.begin(SD_ChipSelectPin)) {  
    Serial.println("sd faild"); 
    return;
  }else{
    Serial.println("SD OK"); 
  }
  // The audio library needs to know which CS pin to use for recording
  audio.CSPin = SD_ChipSelectPin;
}


void loop() {
  
    if(Serial.available()){                          //Send commands over serial to play
      switch(Serial.read()){
        
        case 'r': audio.startRecording("test.wav",16000,microphone_pin); Serial.println("recording start"); break;    //Record at 16khz sample rate on pin A0
        case 's': audio.stopRecording("test.wav"); Serial.println("recording stopped"); break;              //Stop recording
      }
    }
}

Тут пример из видео на ютубе

#include <SD.h>
#include <SPI.h>
#include <TMRpcm.h>
#include <EEPROM.h>

#define ENABLE_DEBUG        //Включение вывода отладочной информации через Serial. Только для отладки! Закоментировать эту строку перед заливкой в готовое устройство!

#define SD_ChipSelectPin 10  //

#define ledStart 2         /* PIN LED Start */
#define ledStop 3          /* PIN LED Stop */
#define MicPin A1          // Аналоговый пин, к которму подключен микрофон

char NameRecord[10];        // Имя нового - записываемого файла на SD-карту
int RecordNumber;           // Номер записи - храним в EEPROM. в диапазоне от 0 до 32767
byte Recording = 0;         // Переменная определяет идет сейчас запись или нет
                            //-----------------------------------------------
int RecInterval = 5;        //! Минимальная продолжительность записи в секундах !
                            //-----------------------------------------------
unsigned long TimeInterval = 0; // Переменная для вычисления времени
int MaxAnalogPinValue = 1000;   // Уровень сигнала на аналоговом входе при котором произойдет старт записи
                                // Значение подбирается индивидуально! (100 - 1023)
int SaveADC1 = 0;
int SaveADC2 = 0;

unsigned int sample;
unsigned int signalMax = 0;
unsigned int signalMin = 256;
unsigned int peakToPeak = 0;
#define peakToPeakMinLevel 200   // Уровень срабатывания на звук. Значение подбирается индивидуально!
                                // Максимальное значение - 255

TMRpcm audio;   // create an object for use in this sketch 

void setup() {
    #if defined (ENABLE_DEBUG)
        Serial.begin(9600);
    #endif
    
    pinMode(ledStart, OUTPUT);
    pinMode(ledStop, OUTPUT);
    //audio.speakerPin = 11; //5,6,11 or 46 on Mega, 9 on Uno, Nano, etc
    pinMode(10,OUTPUT);  //Pin pairs: 9,10 Mega: 5-2,6-7,11-12,46-45
    
    if (!SD.begin(SD_ChipSelectPin)) {  
        digitalWrite(ledStop, LOW);
        digitalWrite(ledStart, LOW);
        return;
    }else{
        digitalWrite(ledStop, LOW);
        digitalWrite(ledStart, HIGH);
    }
    analogReference(EXTERNAL);
    // The audio library needs to know which CS pin to use for recording
    audio.CSPin = SD_ChipSelectPin;
    
    RecordNumber = EEPROM.read(0);
    RecInterval = RecInterval * 1000;
}


void loop() {
    if (Recording == 0){
        int AnR = analogRead(MicPin);
        #if defined (ENABLE_DEBUG)
            Serial.print("Analog level: ");
            Serial.println(AnR);
        #endif
        if (AnR >= MaxAnalogPinValue) {
            #if defined (ENABLE_DEBUG)
                Serial.print("Start recording! File: ");
                Serial.print(RecordNumber+1);
                Serial.println(".wav");
            #endif
            StartRec();
        }
    }
    
    if (Recording == 1){
        sample = ADCH;
        if (sample < 256)
        {
            if (sample > signalMax)
            {
                signalMax = sample;  // save just the max levels
            }
            else if (sample < signalMin)
            {
                signalMin = sample;  // save just the min levels
            }
        }
        #if defined (ENABLE_DEBUG)
            Serial.print("Max MIC signal: ");
            Serial.println(signalMax);
        #endif
        if (millis() - TimeInterval >= RecInterval) {
            peakToPeak = signalMax - signalMin;
            signalMax = 0;
            signalMin = 256;
            #if defined (ENABLE_DEBUG)
                Serial.print("peakToPeak = ");
                Serial.println(peakToPeak);
            #endif
            if (peakToPeak < peakToPeakMinLevel) {
                analogRead(MicPin);
                StopRec();
                #if defined (ENABLE_DEBUG)
                    Serial.println("Recording stopped");
                #endif
            }else{
                TimeInterval = millis()-1;
                #if defined (ENABLE_DEBUG)
                    Serial.println("Continue recording...");
                #endif
            }
        }
    }
}

void StartRec() {                   // begin recording process
    SaveADC1 = ADCSRA;
    SaveADC2 = ADCSRB;
    Recording = 1;
    digitalWrite(ledStop, HIGH);
    digitalWrite(ledStart, LOW);
    RecordNumber++;
    if (RecordNumber > 32766)  = 0;      // небольшое огриничение в номерации файлов
    EEPROM.write(0, RecordNumber);                  // Сохранение в EEPROM номера последнего аудиофайла
    TimeInterval = millis();                        // Запоминаем  millis для отсчета времени записи
    sprintf(NameRecord,"%d.wav", RecordNumber);     // создаем название файла из номера и расширения ".wav"
    audio.startRecording(NameRecord, 16000, MicPin, 0);// Старт записи
}

void StopRec() {                    // stop recording process, close file
    audio.stopRecording(NameRecord);// Стоп записи
    digitalWrite(ledStop, LOW);
    digitalWrite(ledStart, HIGH);
    Recording = 0;
    ADCSRA = SaveADC1;
    ADCSRB = SaveADC2;
}

Я брал некоторые команды из второго скетча.

И хотел сделать так, чтобы ардуина записывала трек определенной длины

b707
Offline
Зарегистрирован: 26.05.2017

обратите внимание, что в обоих примерах кода не используется delay(). а у вас - оно присутсвует именно во время записи.

Поскольку delay() блокирует контроллер, вероятно МК не может записывать звук в это время

nail2007
Offline
Зарегистрирован: 08.12.2017

ага, а как тогда можно сделать так, чтобы он записывал звук именно определенное время.

 

b707
Offline
Зарегистрирован: 26.05.2017
nail2007
Offline
Зарегистрирован: 08.12.2017

спасибо! попробую сегодня-завтра. отпишусь о результатах.

Upper
Offline
Зарегистрирован: 23.06.2020

По моему delay() в данном случае не виновен.

Проверить можно изменив заведомо рабочий скетч примера, добавив после команды старта команду  delay(30000) (числом 30000 а не переменной для определенности)  и команду окончания записи.

Дополнено позже. ошибочно написал 30000 вместо 3000

nail2007
Offline
Зарегистрирован: 08.12.2017

Всем привет!

Мы с другом сидели с кодом часа два и поняли в чем ошибка.

строчка 10

char FileName[10];

в ней задаются биты для имени файла. их было недостаточно. то есть здесь нужно вставить большее значение)

делэй не при чем )

Upper
Offline
Зарегистрирован: 23.06.2020

Строка 22 из первого сообщения не мешает?
pinMode(12,OUTPUT);

(на симуляторе для UNO мешает, т.к. 12 это MISO и используется для обмена с SD)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

НАДА БОООЛЬШЕ БИТОВ!!!  для имени файла, всё дело в этом!!!

Пидец.  Не угадал. 

nail2007
Offline
Зарегистрирован: 08.12.2017

Upper пишет:

Строка 22 из первого сообщения не мешает?
pinMode(12,OUTPUT);

(на симуляторе для UNO мешает, т.к. 12 это MISO и используется для обмена с SD)

нет, не мешает) к 12 пину как раз подключается MISO :)