Обсуждаем контроллеры компании Atmel.
Ответить

Re: Ардуино - запись звука

Пт июл 01, 2022 15:01:58

бсд 4 бита соответствует хексу - преобразовывать ничего не надо.

а вот обратно - только если повезёт :roll: (если в младшей тетраде не окажется записано число больше 9) тебе, похоже повезло... но тут все вопросы к источнику числа...

Re: Ардуино - запись звука

Пт июл 01, 2022 15:23:36

Как так получается что если я присваиваю переменной младшую тетраду шестнадцатиричного числа то получаю в переменной ее десятичное выражение и смогу вывести ее в lcd в десятичном виде.

А вот так: от 0 до 9 числа совпадают.

Изображение

Re: Ардуино - запись звука

Пт июл 01, 2022 16:27:38

Все понятно

Re: Ардуино - запись звука

Вт июл 26, 2022 10:13:17

olegue писал(а):а вот это надо бы попробовать

попробуй ещё добавить стабилизацию входа... как советует даташит.
Спойлер
Код:
ISR(TIMER2_COMPA_vect) {
ADMUX = 0x40; // set ADC to read pin A0, ADLAR to 1 (right adjust)

delay_us(10);                            // стабилизация входа...

sbi(ADCSRA, ADSC); // start ADC sample
while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
rsValue=ADCW;
...

стабилизация входа нужна чтобы после переключения мультиплексора напряжение "устаканилось"... ))

в твоём случае (с учетом ограничениями таймера = 45 мкс) можно не ставить задержку delay_us(10), а сделать по другому...

ISR(TIMER2_COMPA_vect) {
sbi(ADCSRA, ADSC); // start ADC sample
while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
rsValue=ADCW;


ADMUX = 0x41; // set ADC to read pin A1, ADLAR to 1 (right adjust)
sbi(ADCSRA, ADSC); // start ADC sample
while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
recByteCount++; // increment sample counter
bufByteCount++;
if (bufByteCount == 64 && bufWrite == 0) {
bufByteCount = 0;
bufWrite = 1;
} else if (bufByteCount == 64 & bufWrite == 1) {
bufByteCount = 0;
bufWrite = 0;
}

if (bufWrite == 0) {
buf00[bufByteCount] = (ADCW>>2);
}
if (bufWrite == 1) {
buf01[bufByteCount] = (ADCW>>2);
}

ADMUX = 0x40; // set ADC to read pin A0, ADLAR to 1 (right adjust)
}

в этом случае, при следующем прерывании таймера, мультиплексор уже окажется подключён к каналу 0.
а так как следующее прерывание таймера наступит через 45 мкс... то за это время напряжение на канале 0 уже "устаканится"... ))
 :tea:

стабилизация входа... нужна только при точных измерениях.
при записи звука точность не требуется.
 :tea:


Спойлер
Код:
[size=85][color=green]Добавлено after 32 minutes 21 second:[/color][/size]
а тут что ты делаешь ?

////////////// НАЧИНАЕМ С ОБРАБОТКИ ВХОДА А0 ////////////////////////
 
// Каждые 100 мс мы накапливаем значения (для усреднения)
 if (timerRSon==0){   // запустим таймер для отображения часов
  timerRS=millis();  // включим миллис
  timerRSon=1;
 
 }
 if (timerRSon==1){
  if (millis()-timerRS>50)
    {
      ////////////

      //rsValue=analogRead(A0);
     
         
          lcd.setCursor(0,0);
         ///sprintf(buffer, "Pow:%05i",rsValue);
         ///lcd.print(buffer);
 
      /////////////   
      SrV=SrV+rsValue;
      timerRSon=0;
   }
 }
// Каждые 1000 мс мы отображаем усредненное значение
  if (timerLCLon==0){   // запустим таймер для отображения часов
  timerLCL=millis();  // включим миллис
  timerLCLon=1;
 }
 if (timerLCLon==1){
  if (millis()-timerLCL>1000)
    {
      //lcd.setCursor(0,0);
     
      SrVmid=SrV/20;
      if (SrVmid<125) SrVmid=125;    // меньше 125 - это 0%
      procSrV=((SrVmid-125)*100)/194;  //в % макс -318(320), мин 125, 320-125=195   
      sprintf(buffer, "Power:%04i (%02i)",SrV/20,procSrV);
      lcd.print(buffer);
      //Show_time();
      timerLCLon=0;
     
      SrV=0;
      ///////////////////////
   }
 }

как ты подключаешь батарейку ? где схема ?
и зачем накапливаем ? и зачем усреднения ?
 :roll:

Цитирю сообщение полносттью потому что помогло. Теперь значения стоят как вкопанные!

Добавлено after 2 hours 8 minutes 57 seconds:
не могу понять! Запись начинается лишь спустя 3-4 секунды после нажатия на кнопку. В чем может быть проблема?
вот весь скетч
Спойлер
Код:
/* Dmitry OSIPOV. http://www.youtube.com/user/d36073?feature=watch
  Arduino Audio Recorder V.1-20160524.
  ----------
   Arduino Projects: Digital Audio Recorder.
  http://apcmag.com/arduino-projects-digital-audio-recorder.htm/
  ----------
  SD-карту лучше класс 10 и выше.
  Питание от батареи или аккумулятора.
  Микрофон подключить к pin (A5).
  ----------
  Download - sketch "Arduino Audio Recorder V.1-20160524"
  Библиотеку - SdFat.
  Фото.
  https://yadi.sk/d/zqi8-L5xruhFq
  + sketch оставлю в комментарии - под видео.
  ----------
*/
#include <LiquidCrystal_I2C.h>
#include <SdFat.h> // https://yadi.sk/d/zqi8-L5xruhFq
//#include <EEPROM.h>

#include <RTClib.h>

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

SdFat sd;
SdFile rec;
RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display
const int chipSelect = 4; /* Поменял на 10-pln */
unsigned long fileSize = 0L;
unsigned long waveChunk = 16;
unsigned int waveType = 1;
unsigned int numChannels = 1;
unsigned long sampleRate = 16000;
unsigned long bytesPerSec = 16000;
unsigned int blockAlign = 1;
unsigned int bitsPerSample = 8;
unsigned long dataSize = 0L;
unsigned long recByteCount = 0L;
unsigned long recByteSaved = 0L;
const int btnStart = 6;
const int btnStop = 5;
const int ledStart = 2;
const int ledStop = 3;
int recPressed = 0;
int stopPressed = 0;
unsigned long oldTime = 0L;
unsigned long newTime = 0L;
byte buf00[128]; // buffer array 1
byte buf01[128]; // buffer array 2
byte byte1, byte2, byte3, byte4;
unsigned int bufByteCount;
byte bufWrite;

unsigned long timer1;
int timer1on = 0;
//----------
//char NameRecord[4]; /* Имя нового - записываемого файла на SD-карту. */
//int RecordNumber; /* Номер записи - храним в EEPROM. в диапазоне 0..255. */
//char filename[12];

char filename[22];
char foldername[10];

unsigned long timerLCL;
int timerLCLon=0;

unsigned long timerRS;
int timerRSon=0;

int SrV,rsValue, procSrV, SrVmid;

char buffer[16] ;
void setup() { // THIS RUNS ONCE
//
  lcd.init();
   lcd.backlight();
  //lcd.setCursor(3,0);
  //lcd.print("Hello, world!");
 

//
 
  rtc.begin();
//EEPROM.put(0, 20000);
  Setup_timer2();
  Setup_ADC();

  pinMode(10, OUTPUT);
  pinMode(ledStart, OUTPUT);
  pinMode(ledStop, OUTPUT);
  pinMode(btnStop, INPUT_PULLUP);
  pinMode(btnStart, INPUT_PULLUP);

  if (sd.begin(chipSelect, SPI_FULL_SPEED)) { // initialise card on SPI to 8MHz SPI bus speed
    for (int dloop = 0; dloop < 4; dloop++) {
      digitalWrite(ledStart, !digitalRead(ledStart));
      delay(100);
    }
  } else {
      lcd.setCursor(0,1);
      lcd.print("SD Card not found");
    // if error, flash LED twice per second, until reset
    while (1) {
      digitalWrite(ledStart, !digitalRead(ledStart));
      delay(500);
    }
  }

}

void loop() { // THIS RUNS LOTS!
////////////// НАЧИНАЕМ С ОБРАБОТКИ ВХОДА А0 //////////////////////// 
// Каждые 50 мс мы накапливаем значения (для усреднения)
// if (timerRSon==0){   // запустим таймер для отображения часов
//  timerRS=millis();  // включим миллис
//  timerRSon=1; 
// }
// if (timerRSon==1){
//  if (millis()-timerRS>50)
//    {
//      SrV=SrV+rsValue;
//      timerRSon=0;
//   }
// }
// Каждые 500 мс мы отображаем усредненное значение
  if (timerLCLon==0){   // запустим таймер для отображения напряжения
  timerLCL=millis();  // включим миллис
  timerLCLon=1;
 }
 if (timerLCLon==1){
  if (millis()-timerLCL>500)
    {
      for (int i=0; i <= 20; i++){
         SrV=SrV+rsValue;
      }     
           
      SrVmid=SrV/21;
      if (SrVmid<125) SrVmid=125;    // меньше 125 - это 0%
      procSrV=((SrVmid-125)*100)/194;  //в % макс -318(320), мин 125, 320-125=195 
      //procSrV=((rsValue-125)*100)/194;  //в % макс -318(320), мин 125, 320-125=195   
      sprintf(buffer, "Power:%04i (%02i)",SrV/21,procSrV);
      // sprintf(buffer, "Power:%04i (%02i)",rsValue,procSrV);
       
      lcd.setCursor(0,0);
      lcd.print(buffer);
      //Show_time();
      timerLCLon=0;
     
      SrV=0;
      ///////////////////////
   }
   
 }

 ////////////// ЗДЕСЬ УЖЕ ОБРАБОТКА ВХОДА А1 ////////////////////////
 if (digitalRead(btnStart) == LOW && recPressed == 0) {
   
    DateTime now = rtc.now();
    String strFile,strFolder;  //declaring string.
    strFolder=String(now.timestamp(DateTime::TIMESTAMP_DATE));
    strFolder.replace("-", "");
    strFolder.toCharArray(foldername, sizeof(foldername));
    sd.mkdir(foldername);  // Создаю директорию - пробовал без этого - никак
    strFolder.concat("/");
    strFile=String(now.timestamp(DateTime::TIMESTAMP_TIME));
    strFile.replace(":", "-");
    strFile.concat(".wav");
    strFolder.concat(strFile);
    strFolder.toCharArray(filename, sizeof(filename));
   
    StartRec(); // launch StartRec method
    timer1on = 0;
  }
  else if (digitalRead(btnStart) == HIGH && recPressed == 1 && timer1on == 0)
    {
      timer1 = millis();
      timer1on = 1;
    }
    else if (digitalRead(btnStart) == LOW && recPressed == 1 && timer1on == 1) {
    timer1on = 0;
    }
   
  else if (digitalRead(btnStart) == HIGH && recPressed == 1 && timer1on == 1 && (millis() - timer1) > 2000)
  {
    StopRec(); // launch StopRec method
   
    /*         Поэтому (Делаем программную перезагрузку). */
    ((void (*)())0x0000)(); /* Делаем программную перезагрузку - Arduino */
  }
 
  if (recByteCount % 256 == 128 && recPressed == 1) {
    rec.write(buf00, 128);  // save buf01 to card
    recByteSaved += 128;
  }
  if (recByteCount % 256 == 0 && recPressed == 1) {
    rec.write(buf01, 128);  // save buf02 to card
    recByteSaved += 128;
  }
}

void StartRec() { // begin recording process

  digitalWrite(ledStart, HIGH);
  digitalWrite(ledStop, LOW);
  recByteCount = 0;
  recByteSaved = 0;
  recPressed = 1; // recording button has been pressed
  stopPressed = 0;
  writeWavHeader();
  sbi (TIMSK2, OCIE2A); // enable timer interrupt, start grabbing audio

}

void StopRec() { // stop recording process, update WAV header, close file

  cbi (TIMSK2, OCIE2A); // disable timer interrupt
  writeOutHeader();
  digitalWrite(ledStart, LOW); // turn off recording LED
  digitalWrite(ledStop, HIGH); // light stop LED
  recPressed = 0;

}

void writeOutHeader() { // update WAV header with final filesize/datasize

  rec.seekSet(4);
  byte1 = recByteSaved & 0xff;
  byte2 = (recByteSaved >> 8) & 0xff;
  byte3 = (recByteSaved >> 16) & 0xff;
  byte4 = (recByteSaved >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.seekSet(40);
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.close();

}

void dateTime(uint16_t* date, uint16_t* time) {
  DateTime now = rtc.now();

  // return date using FAT_DATE macro to format fields
  *date = FAT_DATE(now.year(), now.month(), now.day());

  // return time using FAT_TIME macro to format fields
  *time = FAT_TIME(now.hour(), now.minute(), now.second());
}

void writeWavHeader() { // write out original WAV header to file

  recByteSaved = 0;
 
   SdFile::dateTimeCallback(dateTime);
   ////
 
   ////
   rec.open(filename, O_CREAT | O_TRUNC | O_RDWR); /* Имя нового - записываемого файла на SD-карту. */
   
  rec.write("RIFF");
  byte1 = fileSize & 0xff;
  byte2 = (fileSize >> 8) & 0xff;
  byte3 = (fileSize >> 16) & 0xff;
  byte4 = (fileSize >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.write("WAVE");
  rec.write("fmt ");
  byte1 = waveChunk & 0xff;
  byte2 = (waveChunk >> 8) & 0xff;
  byte3 = (waveChunk >> 16) & 0xff;
  byte4 = (waveChunk >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = waveType & 0xff;
  byte2 = (waveType >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = numChannels & 0xff;
  byte2 = (numChannels >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = sampleRate & 0xff;
  byte2 = (sampleRate >> 8) & 0xff;
  byte3 = (sampleRate >> 16) & 0xff;
  byte4 = (sampleRate >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = bytesPerSec & 0xff;
  byte2 = (bytesPerSec >> 8) & 0xff;
  byte3 = (bytesPerSec >> 16) & 0xff;
  byte4 = (bytesPerSec >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = blockAlign & 0xff;
  byte2 = (blockAlign >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = bitsPerSample & 0xff;
  byte2 = (bitsPerSample >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  rec.write("data");
  byte1 = dataSize & 0xff;
  byte2 = (dataSize >> 8) & 0xff;
  byte3 = (dataSize >> 16) & 0xff;
  byte4 = (dataSize >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);

}

void Setup_timer2() {

  TCCR2B = _BV(CS21);  // Timer2 Clock Prescaler to : 8
  TCCR2A = _BV(WGM21); // Interupt frequency  = 16MHz / (8 x 125 + 1) = 16000Hz
  OCR2A = 125; // Compare Match register set to 125 (было 90) Перешл на 16кгц

}

void Show_time(){   
  DateTime now = rtc.now();
      lcd.setCursor(1, 1);
      lcd.print(now.hour());
      lcd.print(":");
      lcd.print(now.minute());
      lcd.print(":");     
      lcd.print(now.second());
       }

void Setup_ADC() {

  ADMUX = 0x61; // set ADC to read pin A5, ADLAR to 1 (left adjust)
  sbi(ADCSRA, ADEN);  // включить модуль АЦП
  //sbi(ADCSRA, ADATE); // Непрерывный режим работы АЦП (это не прокатило) Экран стал пуст
  cbi(ADCSRA, ADPS2); // set prescaler to 8 / ADC clock = 2MHz
  sbi(ADCSRA, ADPS1);
  sbi(ADCSRA, ADPS0);
}

ISR(TIMER2_COMPA_vect) {
 ADMUX = 0x40; // set ADC to read pin A0, ADLAR to 1 (left adjust)
        sbi(ADCSRA, ADSC); // start ADC sample
        while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
        //rsValue=(ADCL|ADCH<<8);
        rsValue=ADCW;
 
ADMUX = 0x61; // set ADC to read pin A1, ADLAR to 1 (left adjust)
  sbi(ADCSRA, ADSC); // start ADC sample
  while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
  recByteCount++; // increment sample counter
  bufByteCount++;
  if (bufByteCount == 128 && bufWrite == 0) {
    bufByteCount = 0;
    bufWrite = 1;
  } else if (bufByteCount == 128 & bufWrite == 1) {
    bufByteCount = 0;
    bufWrite = 0;
  }

  if (bufWrite == 0) {
    buf00[bufByteCount] = ADCH;
  }
  if (bufWrite == 1) {
    buf01[bufByteCount] = ADCH;
  }
  // Добавил для стабилизации входа.
ADMUX = 0x40; // set ADC to read pin A0, ADLAR to 1 (left adjust)

  //  if (recByteCount % 128 < 64) { // determine which buffer to store sample into
  //    buf01[recByteCount % 64] = ADCH;
  //  } else {
  //    buf02[recByteCount % 64 ] = ADCH;
  //  }

}


Добавлено after 16 minutes 46 seconds:
фонарик зажигается сразу , а преобразование начинается только через 3-4 сек. Странная ситуация

Добавлено after 8 hours 32 minutes 33 seconds:
загрузил оригинал . и там такая же фигня. Запись начинает только со 3-4 секунды
Спойлер
Код:
// ----------
//
// APC magazine - Arduino Masterclass
// Project #18 - Digital Audio Recorder v2.0
// Darren Yates - 11 April 2014
//
// Includes the SdFat library - https://code.google.com/p/sdfatlib/downloads/list
//
// ----------

#include <SdFat.h>

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

SdFat sd;
SdFile rec;

const int chipSelect = 4;
unsigned long fileSize = 0L;
unsigned long waveChunk = 16;
unsigned int waveType = 1;
unsigned int numChannels = 1;
unsigned long sampleRate = 22050;
unsigned long bytesPerSec = 22050;
unsigned int blockAlign = 1;
unsigned int bitsPerSample = 8;
unsigned long dataSize = 0L;
unsigned long recByteCount = 0L;
unsigned long recByteSaved = 0L;
const int btnStart = 6;
const int btnStop = 5;
const int ledStart = 2;
const int ledStop = 3;
int recPressed = 0;
int stopPressed = 0;
unsigned long oldTime = 0L;
unsigned long newTime = 0L;
byte buf00[512]; // buffer array 1
byte buf01[512]; // buffer array 2
byte byte1, byte2, byte3, byte4;
unsigned int bufByteCount;
byte bufWrite;

void setup() { // THIS RUNS ONCE

  Setup_timer2();
  Setup_ADC();

  pinMode(10, OUTPUT);
  pinMode(ledStart, OUTPUT);
  pinMode(ledStop, OUTPUT);
  pinMode(btnStop, INPUT_PULLUP);
  pinMode(btnStart, INPUT_PULLUP);
 
  if (sd.begin(chipSelect, SPI_FULL_SPEED)) { // initialise card on SPI to 8MHz SPI bus speed
    for (int dloop = 0; dloop < 4; dloop++) {
      digitalWrite(ledStart,!digitalRead(ledStart));
      delay(100);
    }
  } else { // if error, flash LED twice per second, until reset
    while(1) {
      digitalWrite(ledStart,!digitalRead(ledStart));
      delay(500);
    }
  }

}

void loop() { // THIS RUNS LOTS!

  if (digitalRead(btnStart) == LOW && recPressed == 0) {
    StartRec(); // launch StartRec method
    recPressed=1;
  }
  if (digitalRead(btnStart) == HIGH && recPressed == 1){
    StopRec(); // launch StopRec method
  }
 
  if (recByteCount % 1024 == 512 && recPressed == 1) { rec.write(buf00,512); recByteSaved+= 512; } // save buf01 to card
  if (recByteCount % 1024 == 0 && recPressed == 1) { rec.write(buf01,512); recByteSaved+= 512; } // save buf02 to card

}

void StartRec() { // begin recording process

  digitalWrite(ledStart,HIGH);
  digitalWrite(ledStop,LOW);
  recByteCount = 0;
  recByteSaved = 0;
  recPressed = 1; // recording button has been pressed
  stopPressed = 0;
  writeWavHeader();
  sbi (TIMSK2, OCIE2A); // enable timer interrupt, start grabbing audio

}

void StopRec() { // stop recording process, update WAV header, close file
   
  cbi (TIMSK2, OCIE2A); // disable timer interrupt
  writeOutHeader();
  digitalWrite(ledStart,LOW); // turn off recording LED
  digitalWrite(ledStop,HIGH); // light stop LED
  recPressed = 0;
 
}
 
void writeOutHeader() { // update WAV header with final filesize/datasize

  rec.seekSet(4);
  byte1 = recByteSaved & 0xff;
  byte2 = (recByteSaved >> 8) & 0xff;
  byte3 = (recByteSaved >> 16) & 0xff;
  byte4 = (recByteSaved >> 24) & 0xff; 
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.seekSet(40);
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.close();
 
}

void writeWavHeader() { // write out original WAV header to file

  recByteSaved = 0;
  rec.open("rec99999.wav", O_CREAT | O_TRUNC | O_RDWR);
  rec.write("RIFF");
  byte1 = fileSize & 0xff;
  byte2 = (fileSize >> 8) & 0xff;
  byte3 = (fileSize >> 16) & 0xff;
  byte4 = (fileSize >> 24) & 0xff; 
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.write("WAVE");
  rec.write("fmt ");
  byte1 = waveChunk & 0xff;
  byte2 = (waveChunk >> 8) & 0xff;
  byte3 = (waveChunk >> 16) & 0xff;
  byte4 = (waveChunk >> 24) & 0xff; 
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = waveType & 0xff;
  byte2 = (waveType >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = numChannels & 0xff;
  byte2 = (numChannels >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = sampleRate & 0xff;
  byte2 = (sampleRate >> 8) & 0xff;
  byte3 = (sampleRate >> 16) & 0xff;
  byte4 = (sampleRate >> 24) & 0xff; 
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = bytesPerSec & 0xff;
  byte2 = (bytesPerSec >> 8) & 0xff;
  byte3 = (bytesPerSec >> 16) & 0xff;
  byte4 = (bytesPerSec >> 24) & 0xff; 
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = blockAlign & 0xff;
  byte2 = (blockAlign >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = bitsPerSample & 0xff;
  byte2 = (bitsPerSample >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  rec.write("data");
  byte1 = dataSize & 0xff;
  byte2 = (dataSize >> 8) & 0xff;
  byte3 = (dataSize >> 16) & 0xff;
  byte4 = (dataSize >> 24) & 0xff; 
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);

}

void Setup_timer2() {

  TCCR2B = _BV(CS21);  // Timer2 Clock Prescaler to : 8
  TCCR2A = _BV(WGM21); // Interupt frequency  = 16MHz / (8 x 90 + 1) = 22191Hz
  OCR2A = 90; // Compare Match register set to 90

}

void Setup_ADC() {

  ADMUX = 0x61; // set ADC to read pin A5, ADLAR to 1 (left adjust)
  cbi(ADCSRA,ADPS2); // set prescaler to 8 / ADC clock = 2MHz
  sbi(ADCSRA,ADPS1);
  sbi(ADCSRA,ADPS0);
}

ISR(TIMER2_COMPA_vect) {

  sbi(ADCSRA, ADSC); // start ADC sample
  while(bit_is_set(ADCSRA, ADSC));  // wait until ADSC bit goes low = new sample ready
  recByteCount++; // increment sample counter
  bufByteCount++;
  if (bufByteCount == 512 && bufWrite == 0) {
    bufByteCount = 0;
    bufWrite = 1;
  } else if (bufByteCount == 512 & bufWrite == 1) {
    bufByteCount = 0;
    bufWrite = 0;
  }

  if (bufWrite == 0) { buf00[bufByteCount] = ADCH; }
  if (bufWrite == 1) { buf01[bufByteCount] = ADCH; }
 

//  if (recByteCount % 1024 < 512) { // determine which buffer to store sample into
//    buf01[recByteCount % 512] = ADCH;
//  } else {
//    buf02[recByteCount % 512] = ADCH;
//  }

}


Добавлено after 23 minutes 24 seconds:
Нашел проблему. На карте было 5000 файлов. Очистил карту - проблема решилась . Запись теперь сразу пишется, без задержек.

Добавлено after 1 hour 37 minutes 51 second:
Подскажите плз,как мне теперь сделать проигрывание файлов в этом же скетче. Какие могут быть варианты?

у меня есть сложный вариант. Вот отсюда http://avr-start.ru/?p=1874
код для Меги8

Спойлер
Код:
#include <mega8.h>
#include "diskio.h"
#include "pff.h"
 
unsigned char buffer[512];   /* буфер в который копируется инфа с флешки */
volatile unsigned int count; //счетчик скопированных данных
 
interrupt [TIM2_COMP] void timer2_comp_isr(void) //прерывание в котором подставляются значения
{
    OCR1A = buffer[count]; //выводим звук на динамик
   if (++count >= 512) //увеличиваем счетчик
      count = 0;  //если 512 обнуляем
}
 
void main(void)
{   
    unsigned int br;         /* счетчик чтения/записи файла */     
    unsigned char buf = 0;   //переменная определяющая какая часть буфера читается
    FATFS fs;         /* Рабочая область (file system object) для логических дисков */
 
PORTB=0x00;
DDRB=0x02;  //дрыгаем шимом ocr1a
 
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Fast PWM top=0x00FF
// OC1A output: Non-Inv.
TCCR1A=0x81;
TCCR1B=0x09;
TCNT1=0x00;
OCR1A=0x00;
 
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 250,000 kHz
// Mode: CTC top=OCR2
TCCR2=0x0B;
TCNT2=0x00;
//OCR2=0x1E; //настройка регистра сравнения для 8кГц
OCR2=0xA;    //для 22кГц
 
#asm("sei")
// Timer(s)/Counter(s) Interrupt(s) initialization
 
 
if(disk_initialize()==0) //инициализируем флешку
{
  pf_mount(&fs);  //монтируем файловую систему     
  pf_open("1.wav");  //открываем вавку
  pf_lseek(44);     //перемещаем указатель на 44 
  pf_read(buffer, 512,&br); //в первый раз заглатываем сразу 512байт
  TIMSK=0x80; //врубаем музон
  while(1)
  {
     if(!buf && count>255) //если воспроизвелось больше 255 байт, 
     {                     
        pf_read(&buffer[0], 256,&br);//то читаем в первую половину буфера инфу с флешки
        buf=1;
        if (br < 256) //если буфер не содержит 256 значений значит конец файла
   break;
     } 
     if(buf && count<256)
     {
        pf_read(&buffer[256], 256,&br); // читаем во вторую часть буфера с флешки
        buf = 0;
        if (br < 256)
   break;
     }
 
  }
  TIMSK = 0x00; //глушим все
  pf_mount(0x00); //демонтируем фат
}
 
while (1)
      {
 
 
      }
}


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

Добавлено after 1 minute 45 seconds:
и что бы она не конфликтовала с текущим кодом.

Re: Ардуино - запись звука

Вт июл 26, 2022 12:51:47

ты решил нас добить своими библиотеками... )) сделай всё на чистом AVR да и всё )) :facepalm:

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

в сети столько проектов интересных... работа со звуком...
начиная от самодельного GSM телефона...
GSM.jpg
(68.36 KiB) Скачиваний: 28

набор.jpg
(26.91 KiB) Скачиваний: 27

телефон.jpg
(62.76 KiB) Скачиваний: 35

...
есть простое управление с телефона...
авто.jpg
(58.6 KiB) Скачиваний: 22

есть ГОЛОСОВОЕ управление с телефона... говоришь "лампочка гори !"... и лампочка горит))
команды голосом.jpg
(52.67 KiB) Скачиваний: 26

:)

Добавлено after 3 minutes 47 seconds:
а лучше сделал бы самодельный типа Скайп))
схема.jpg
(50.42 KiB) Скачиваний: 32

через бесплатный Wi-Fi...
1.jpg
(39.78 KiB) Скачиваний: 29

живое общение намного интересней чем просто писать/читать флешки))
VoIP.jpg
(49.16 KiB) Скачиваний: 33

:tea:

Re: Ардуино - запись звука

Вт июл 26, 2022 15:09:54

Это все в планах. Про номеранобератель идея - крутая. Я тоже как то об этом думал.

Добавлено after 35 seconds:
но надо сначало порешать с выводом звука

Добавлено after 1 hour 29 minutes 41 second:
есть ГОЛОСОВОЕ управление с телефона... говоришь "лампочка гори !"... и лампочка горит))



а без телефона каккие есть варианты ГОЛОСОВОГО управления ? чисто на ардуино

Добавлено after 26 seconds:
ну или на АВР

Re: Ардуино - запись звука

Вт июл 26, 2022 21:45:32

звук...

на ардуино + флешке можно сделать... автоответчик))
в совсем старых телефона автоответчик делали на кассетах))
1.jpg
(36.49 KiB) Скачиваний: 32

в не таких старых телефонах автоответчик делали на флешке... встроенная флешка...
2.jpg
(39.06 KiB) Скачиваний: 29

:roll:
ещё можно сделать голосовое оповещение )) тупо записать на флешку разные короткие сообщения... а затем ардуина будет их воспроизводить в зависимости на какую кнопку нажать))

записываешь команды... потом нажимаем на кнопки... Ардуина говорить голосом все команды))
голосовой ответчик.jpg
(74.66 KiB) Скачиваний: 32

аналогичным образом работал автоответчик на старых телефонных станциях...
АТС.jpg
(105.07 KiB) Скачиваний: 34

связисты его называли "Какаду" ))
какаду.jpg
(42.82 KiB) Скачиваний: 32

))
набираешь служебный номер типа 097...
а автоответчик АТС тебе говорит: "температура воздуха в центре города +20 градусов".

причём четко слышно что это "склейка"... иногда даже из разных голосов)) это же кто-то сидел записывал))
:))

набираешь служебный номер типа 085...
а автоответчик АТС тебе говорит: "наберите номер вашего телефона".
набираешь номер своего телефона с помощью дтмф клавиатуры...
дтмф.jpg
(52.78 KiB) Скачиваний: 25

а автоответчик АТС тебе говорит: "на вашем счету 100 рублей".
:)
всё это умеет делать и Ардуина)) можно сделать управление с любого телефона с помощью дтмф кодов...
Адруина всё оцифрует... и расшифрует команду...
частоты.jpg
(44.25 KiB) Скачиваний: 25

затем голосов скажет "кнопка один нажата"... )) и т.д.
:))
ещё ардуина умеет синтезировать простые сигналы... типа генератор сигналов))

с голосовым управлением чуть сложнее...
:roll:

конкретно тут голосовое правление сделали на сервисе гугла... голос распознаёт сервер гугл))
команды голосом.jpg
(55.09 KiB) Скачиваний: 28

аналогично работает и яндекс станция алиса...
https://www.youtube.com/watch?v=Kru5-hfMKTU
короче... всё работает через Интернет))

теоретически можно сделать свой сервер распознавания голоса...
надо подумать...
:roll:

простейший вариант - записать в ардуину сначала набор голосовых команд...

потом при поступлении новой голосовой команды Ардуина просто сравнивает новую команду с ранее записанными...

при совпадении Ардуина выполняет команду...
голосовое управление.jpg
(97.32 KiB) Скачиваний: 31

это Ардуина умеет))
:)
вопрос только в точности сравнения... но над этим можно поработать))
:tea:

Re: Ардуино - запись звука

Вс июл 31, 2022 09:47:26

подскажите пож, правильно ли я понимаю тему.

Atmega328, биты ADCH и ADCL

Известно,что у этого МК один АЦП, и он 10ти битный. У меня вопрос по результату преобразования.

1. Результат преобразования всегда 10ти битный? Вне зависимости от "других настроек"?
2. Если я читаю только ADCH то получаю 8битный результат?

Вывод: "битность" результата зависит от того как я его считываю (выше написал)?

Добавлено after 3 minutes 46 seconds:
но так как ADCH и ADCL 8ми битные регистры,то потенциально резушьтат может быть 16ти битный. Это, как я понял для совместимости сделано со старшими моделями?

Re: Ардуино - запись звука

Вс июл 31, 2022 09:56:39

Как ни странно ( :) ), все ответы - в документации чипа.

ATmega328, стр. 246:
10-bit Resolution
СпойлерWhen ADCL is read, the ADC Data Register is not updated until ADCH is read. Consequently, if the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read ADCH. Otherwise, ADCL must be read first, then ADCH.

При чтении ADCL регистр данных ADC не обновляется до тех пор, пока не будет прочитан ADCH. Следовательно, если в результате останется корректируется и требуется не более 8-битной точности, достаточно прочитать ADCH. В противном случае ADCL должен быть сначала читать, потом ADCH.
Вложения
328_adc.jpg
(77.94 KiB) Скачиваний: 29

Re: Ардуино - запись звука

Вс июл 31, 2022 10:35:34

olegue писал(а):Atmega328, биты ADCH и ADCL

Atmega328, регистры ADCH и ADCL
olegue писал(а):1. Результат преобразования всегда 10ти битный? Вне зависимости от "других настроек"?

да.
olegue писал(а):2. Если я читаю только ADCH то получаю 8битный результат?

результат зависит от того как настроен АЦП...
olegue писал(а):Вывод: "битность" результата зависит от того как я его считываю (выше написал)?

результат зависит от того как настроен АЦП...
olegue писал(а):но так как ADCH и ADCL 8ми битные регистры,то потенциально резушьтат может быть 16ти битный.

да.
olegue писал(а):Это, как я понял для совместимости сделано со старшими моделями?

нет.
просто 10-ти битный результат не влез в один регистр...
пришлось делать два регистра...
ADCH = 00000011
ADCL = 11111111
итого: 10 бит.

Re: Ардуино - запись звука

Вс июл 31, 2022 10:45:26

т.е если я делаю
rs=ADCW, то получаю в rs 10ти битное представление результата

а если выравнивают влево (ADLAR=1) и делаю rs=ADCH, то получаю 8битное представление результата?

Re: Ардуино - запись звука

Вс июл 31, 2022 11:09:33

Два резултата (ADCL и ADCH): по 8 бит.
Для 10 бит: необх. собрать результат: rs = ADCH << 8 | ADCL;
Для 8 бит: чтение только ADCH при ADLAR = 1 (mode = Left Adjust)

в некоторых компиляторах (avr-gcc) уже сделано, просто берете то, что нужно:
int16_t rs = ADCW;

И нужно дождаться времени конверсии. Лучше всего: проверив соответствующий бит:
напр. while (bit_is_set(ADCSRA, ADSC));

С 8 битами / против 10 бит / выигрываете время, но теряете разрешение.

Re: Ардуино - запись звука

Вс июл 31, 2022 14:05:28

//ADLAR=1
// Выравнивание результата в левую сторону < (8-бит):
// ADCH // 1111 1111 - читать вторым (или первым, тогда последние 2 бит потеряем)
// ADCL // 0000 0011 - читать первым

//ADLAR=0
// Выравнивание результата в правую сторону > (10-бит):
// ADCH // 0000 0011 - читать вторым
// ADCL // 1111 1111 - читать первым

:roll:

я всегда делаю так:
//ADLAR=0
// Выравнивание результата в правую сторону > (10-бит):
// ADCH // 0000 0011 - читать вторым
// ADCL // 1111 1111 - читать первым

rs=ADCW, получаю в rs 10-ти битное представление результата.
:tea:

Re: Ардуино - запись звука

Вт авг 02, 2022 10:00:11

мнне нужно обрабатывать 1-2-3 нажатие в пределах времени. посмотрите опытным глазом

flag=0
count=0

if (digitalRead(5) ==LOW && timerON==0) //нажали
{
timerON=1; // включим таймер
timer=millis();
}


if (digitalRead(5) ==LOW && timerON==1 && millis()-timer<600 && flag==0 && count<3) //нажали, таймер включен
{
count++; // зачтем нажатие
flag=1; // флаг регистрации состояния кнопки (нажата/отпущена)
}


if (digitalRead(5) ==HIGH && timerON=1) //отпустили кнопку в пределах времени работы таймера
{
flag=0; //

}

if (millis()-timer>600) {timerON=0;} // отключу таймер (время вышло)

далее в переменной count должно быть количество нажатий.

Re: Ардуино - запись звука

Вт авг 02, 2022 12:35:26

не вижу антидребезг...
дребезг.jpg
(34.43 KiB) Скачиваний: 24

:roll:

Добавлено after 18 minutes 44 seconds:
мы делали отдельные кнопки))
https://www.youtube.com/watch?v=qWojRM-tjP0

антидребезг...


мы опрашивали кнопки отдельно в прерывании... устанавливали флаг нажатия кнопки...

interrupt [TIM0_OVF] void timer0_ovf_isr(void) // 4.000.000/8=500.000/256= цикл 1.953 ,125
{
if (PIND.5==0) flag_k0 = 1; // флаг кнопки 0 // (........) 0- Вкл(Выкл)меню
if (PIND.6==0) flag_k1 = 1; // флаг кнопки 1 // (........) 1- Выбор меню / Вкл(Выкл) LCD
if (PINB.0==0) flag_k3 = 1; // флаг кнопки 3 // (....1...) 3- Вкл(Выкл) фары
//if (PINC.4==0) flag_k4 = 1; // флаг кнопки 4 // скорость
if (PIND.7==0) flag_k5 = 1; // флаг кнопки 5 // (..1.....) 5- Вкл(Выкл) резервный аккумулятор
if (PINC.3==0) flag_k6 = 1; // флаг кнопки 6 // (.1......) 6- Вкл выгрузка
if (PINC.5==0) flag_k7 = 1; // флаг кнопки 7 // 7- круиз-контроль
}


а антидребезг делали в основной программе...

/////////////////////////////////////////////////////////////////////////
///////////////////////////////////// (....1...) 3- Вкл(Выкл) фары
//if ( (PINB.0==0) && (k3==0) ) { // цикл 31,25 ms
if ( (flag_k3) && (k3==0) ) { // цикл 31,25 ms
k3++; // счёт
// kb3 = ~kb3; // kb3 - буфер
PORTB.1=1; // звук зуммер - вкл.

k = k ^ 0b00001000; // (....1...) 3- Вкл(Выкл) фары

};
if ( (8>k3) && (k3) ) {k3++;}; // счёт
if (k3 == 8) {
PORTB.1=0; // звук зуммер - выкл.
k3++;
};
///////////////////////////////
if ( (PINB.0==1) && (k3 == 9) ) {k3++;};
if (k3 > 9) {k3++;}; // счёт
if (k3 == 17) {
k3=0; // сброс
flag_k3=0; // сброс
};
/////////////////////////////////////////////////////////////////////////

:roll:

хотя можно всё делать и в основной программе...

/////////////////////////////////////////////////////////////////////////
///////////////////////////////////// (....1...) 3- Вкл(Выкл) фары
if ( (PINB.0==0) && (k3==0) ) { // цикл 31,25 ms
//if ( (flag_k3) && (k3==0) ) { // цикл 31,25 ms
k3++; // счёт
// kb3 = ~kb3; // kb3 - буфер
PORTB.1=1; // звук зуммер - вкл.

k = k ^ 0b00001000; // (....1...) 3- Вкл(Выкл) фары

};
if ( (8>k3) && (k3) ) {k3++;}; // счёт
if (k3 == 8) {
PORTB.1=0; // звук зуммер - выкл.
k3++;
};
///////////////////////////////
if ( (PINB.0==1) && (k3 == 9) ) {k3++;};
if (k3 > 9) {k3++;}; // счёт
if (k3 == 17) {
k3=0; // сброс
flag_k3=0; // сброс
};
/////////////////////////////////////////////////////////////////////////

но отдельно в прерывании работало стабильней))
:tea:
Вложения
пульт.c
(104.49 KiB) Скачиваний: 41

Re: Ардуино - запись звука

Вт авг 02, 2022 12:43:48

мы опрашивали кнопки отдельно в прерывании... устанавливали флаг нажатия кнопки...

interrupt [TIM0_OVF] void timer0_ovf_isr(void) // 4.000.000/8=500.000/256= цикл 1.953 ,125
{
if (PIND.5==0) flag_k0 = 1; // флаг кнопки 0 // (........) 0- Вкл(Выкл)меню
if (PIND.6==0) flag_k1 = 1; // флаг кнопки 1 // (........) 1- Выбор меню / Вкл(Выкл) LCD
if (PINB.0==0) flag_k3 = 1; // флаг кнопки 3 // (....1...) 3- Вкл(Выкл) фары
//if (PINC.4==0) flag_k4 = 1; // флаг кнопки 4 // скорость
if (PIND.7==0) flag_k5 = 1; // флаг кнопки 5 // (..1.....) 5- Вкл(Выкл) резервный аккумулятор
if (PINC.3==0) flag_k6 = 1; // флаг кнопки 6 // (.1......) 6- Вкл выгрузка
if (PINC.5==0) flag_k7 = 1; // флаг кнопки 7 // 7- круиз-контроль
}

это просто ужас какой-то. Мало того, что явное сравнение с нулём вместо !, так ещё и бесполезное. И зачем столько флагов? "Мы" совершенно не умеет работать с битами? "Мы" не знает логических операций?

Re: Ардуино - запись звука

Вт авг 02, 2022 13:05:01

Эх, Роман, лучше бы Вы мой код прокоментировали. Я в своем разобраться не могу. А вы мне эту простыню подсовываете.

Re: Ардуино - запись звука

Вт авг 02, 2022 13:05:35

if (PIND.5==0) flag_k0 = 1;
или
if (! PIND.5) flag_k0 = 1;
как хотим так и пишем))
:tea:

А ещё мы знаем скорость выполнения инструкций процессором при битовых операциях... С учётом того что мы находимся в прерывании...
Но тебе это не понять))
:tea:

Re: Ардуино - запись звука

Вт авг 02, 2022 13:08:12

Код:
flag=0;
count=0;

loop()

if (digitalRead(5) ==LOW && timerON==0) //нажали
 {
    timerON=1; // включим таймер
    timer=millis();
 }
if (digitalRead(5) ==LOW && timerON==1 && millis()-timer<600 && flag==0 && count<3) //нажали, таймер включен
 {
    count++; // зачтем нажатие
    flag=1; // флаг регистрации состояния кнопки (нажата/отпущена)
 }
if (digitalRead(5) ==HIGH && timerON=1) //отпустили кнопку в пределах времени работы таймера
 {
  flag=0; //
 }
if (millis()-timer>600) {timerON=0;} // отключу таймер (время вышло)
} //loop





скажите че будет если я просто зажму кнопку , получу ли я count 1?

Re: Ардуино - запись звука

Вт авг 02, 2022 13:13:39

лучше бы Вы мой код прокоментировали

а чё там комментировать... антидребезг добавить надо... да и всё))

опрашиваем кнопку на "нажатие":

if (digitalRead(5) ==LOW && timerON==0) //нажали
{
timerON=1; // включим таймер
timer=millis();
}

после того как нажали... надо включить таймер и немножко подождать... чтоб напряжение на кнопке "устаканилось" ))
дребезг при нажатии.jpg
(38.12 KiB) Скачиваний: 25

и только потом уже опрашивать кнопку на "отпускание":

if (digitalRead(5) ==HIGH && timerON=1) //отпустили кнопку в пределах времени работы таймера
{
flag=0; //

}
:roll:
Ответить