1

Тема: Анализатор спектра LCD1602

Основная статья - http://rcl-radio.ru/?p=42903

Добавлено 5 режимов отображения полос, управление кнопкой D12 (10 К на GND, управление +5 В). Сигнал подается на вход А0 через разделительный конденсатор 0,1 мкФ.

  #define AUTO_GAIN 1       // автонастройка по громкости
  #define VOL_THR 45        // порог тишины (ниже него отображения на матрице не будет)
  #define LOW_PASS 40       // нижний порог чувствительности шумов (нет скачков при отсутствии звука)
  #define DEF_GAIN 120       // максимальный порог по умолчанию 
  #define FHT_N 256         // ширина спектра х2
  #define LOG_OUT 1
  #include <FHT.h> 
  #include <EEPROM.h>
  #include <LiquidCrystal.h>
  LiquidCrystal lcd(7, 6, 2, 3, 4, 5);// RS,E,D4,D5,D6,D7
      byte posOffset[16] = {2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}; // вч выше
      byte maxValue, maxValue_f,www=1,gain_sp = DEF_GAIN;
      float k = 0.1;
      int i1,yyy,spek;
      unsigned long gainTimer;

  void setup(){ 
        Serial.begin(9600);
        ADMUX  = 0b01100000; ADCSRA = 0b11010100; 
        lcd.begin(16, 2);
        pinMode(12,INPUT);
        spek = EEPROM.read(100);
}

  void loop(){
    if(digitalRead(12)==HIGH){spek++;EEPROM.update(100,spek); www=1;if(spek>5){spek=0;}delay(300);}

      if(spek==0&&www==1){
      byte v1[8] = {0, 0, 0, 0, 0, 0, 0, 4};
      byte v2[8] = {0, 0, 0, 0, 0, 0, 4, 4};
      byte v3[8] = {0, 0, 0, 0, 0, 4, 4, 4};
      byte v4[8] = {0, 0, 0, 0, 4, 4, 4, 4};
      byte v5[8] = {0, 0, 0, 4, 4, 4, 4, 4};
      byte v6[8] = {0, 0, 4, 4, 4, 4, 4, 4};
      byte v7[8] = {0, 4, 4, 4, 4, 4, 4, 4};
      byte v8[8] = {4, 4, 4, 4, 4, 4, 4, 4};
      lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);
      www=0;}

      if(spek==1&&www==1){
      byte v1[8] = {0, 0, 0, 0, 0, 0, 0, 14};
      byte v2[8] = {0, 0, 0, 0, 0, 0, 14, 14};
      byte v3[8] = {0, 0, 0, 0, 0, 14, 14, 14};
      byte v4[8] = {0, 0, 0, 0, 14, 14, 14, 14};
      byte v5[8] = {0, 0, 0, 14, 14, 14, 14, 14};
      byte v6[8] = {0, 0, 14, 14, 14, 14, 14, 14};
      byte v7[8] = {0, 14, 14, 14, 14, 14, 14, 14};
      byte v8[8] = {14, 14, 14, 14, 14, 14, 14, 14};
      lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);
      www=0;}

      if(spek==2&&www==1){
      byte v1[8] = {0, 0, 0, 0, 0, 0, 0, 10};
      byte v2[8] = {0, 0, 0, 0, 0, 0, 10, 10};
      byte v3[8] = {0, 0, 0, 0, 0, 10, 10, 10};
      byte v4[8] = {0, 0, 0, 0, 10, 10, 10, 10};
      byte v5[8] = {0, 0, 0, 10, 10, 10, 10, 10};
      byte v6[8] = {0, 0, 10, 10, 10, 10, 10, 10};
      byte v7[8] = {0, 10, 10, 10, 10, 10, 10, 10};
      byte v8[8] = {10, 10, 10, 10, 10, 10, 10, 10};
      lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);
      www=0;}

      if(spek==3&&www==1){
      byte v1[8] = {0, 0, 0, 0, 0, 0, 0, 27};
      byte v2[8] = {0, 0, 0, 0, 0, 0, 27, 27};
      byte v3[8] = {0, 0, 0, 0, 0, 27, 27, 27};
      byte v4[8] = {0, 0, 0, 0, 27, 27, 27, 27};
      byte v5[8] = {0, 0, 0, 27, 27, 27, 27, 27};
      byte v6[8] = {0, 0, 27, 27, 27, 27, 27, 27};
      byte v7[8] = {0, 27, 27, 27, 27, 27, 27, 27};
      byte v8[8] = {27, 27, 27, 27, 27, 27, 27, 27};
      lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);
      www=0;}

      if(spek==4&&www==1){
      byte v1[8] = {0, 0, 0, 0, 0, 0, 0, 31};
      byte v2[8] = {0, 0, 0, 0, 0, 0, 31, 31};
      byte v3[8] = {0, 0, 0, 0, 0, 31, 31, 31};
      byte v4[8] = {0, 0, 0, 0, 31, 31, 31, 31};
      byte v5[8] = {0, 0, 0, 31, 31, 31, 31, 31};
      byte v6[8] = {0, 0, 31, 31, 31, 31, 31, 31};
      byte v7[8] = {0, 31, 31, 31, 31, 31, 31, 31};
      byte v8[8] = {31, 31, 31, 31, 31, 31, 31, 31};
      lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);
      www=0;}

      if(spek==5&&www==1){
      byte v1[8] = {0, 0, 0, 0, 0, 0, 0, 21};
      byte v2[8] = {0, 0, 0, 0, 0, 0, 21, 21};
      byte v3[8] = {0, 0, 0, 0, 0, 21, 21, 21};
      byte v4[8] = {0, 0, 0, 0, 21, 21, 21, 21};
      byte v5[8] = {0, 0, 0, 21, 21, 21, 21, 21};
      byte v6[8] = {0, 0, 21, 21, 21, 21, 21, 21};
      byte v7[8] = {0, 21, 21, 21, 21, 21, 21, 21};
      byte v8[8] = {21, 21, 21, 21, 21, 21, 21, 21};
      lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);
      www=0;}
    
      analyzeAudio();   // функция FHT, забивает массив fht_log_out[] величинами по спектру

      for (int pos = 0; pos < 16; pos++) {  
        if (fht_log_out[posOffset[pos]] > maxValue) maxValue = fht_log_out[posOffset[pos]];
        lcd.setCursor(pos, 0);
        int posLevel = map(fht_log_out[posOffset[pos]], LOW_PASS, gain_sp, 0, 15);posLevel = constrain(posLevel, 0, 15);
        
  while(yyy<2){yyy++;delay(2);
    if (posLevel > 7) {lcd.write((uint8_t)posLevel-8);lcd.setCursor(pos, 1);lcd.write((uint8_t)7);} 
     else {lcd.print(" ");lcd.setCursor(pos, 1);lcd.write((uint8_t)posLevel); }}yyy=0;}

   if (AUTO_GAIN) {
    maxValue_f = maxValue * k + maxValue_f * (1 - k);
    if (millis() - gainTimer > 1500) {   
    if (maxValue_f > VOL_THR) gain_sp = maxValue_f;
      else gain_sp = 150;gainTimer = millis();}
      else {gain_sp = DEF_GAIN;}}
  }// loop

void analyzeAudio() { 
 while(i1 < FHT_N){i1++; 
    do{ADCSRA |= (1 << ADSC);} 
    while((ADCSRA & (1 << ADIF)) == 0);fht_input[i1] = (ADCL|ADCH << 8);}i1=0;
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_log(); // take the output of the fht
}
 
  

2 (2023-09-24 14:11:02 отредактировано ivashka777)

Re: Анализатор спектра LCD1602

Добрый день.
Нельзя ли чуть подробней про переключение кнопкой управления режимами отображения (10 К на GND, управление +5 В)?
Как, конкретно ее включить? Что такое 10 К на землю (резистор, сопротивлением 10 кОм соединить на землю с чем?)?
Если можно, схему. Спасибо!

3

Re: Анализатор спектра LCD1602

http://forum.rcl-radio.ru/uploads/images/2023/09/29e4d8e30e253aa1b131c194821a7a8a.png

4 (2023-09-24 18:14:41 отредактировано ivashka777)

Re: Анализатор спектра LCD1602

А, к ардуино, к какому контакту? К D12?
Спасибо за оперативный ответ!

5

Re: Анализатор спектра LCD1602

да

6 (2023-09-27 21:04:12 отредактировано ivashka777)

Re: Анализатор спектра LCD1602

Здравствуйте.
Возможна ли сборка устройства с применением платы Arduino nano на MEGA168PA?
Или на ней не хватит памяти?

7

Re: Анализатор спектра LCD1602

Скетч использует 8816 байт (61%) памяти устройства. Всего доступно 14336 байт.data section exceeds available space in board

Глобальные переменные используют 1228 байт (119%) динамической памяти, оставляя -204 байт для локальных переменных. Максимум: 1024 байт.

Не хватит.

8 (2023-10-02 17:43:28 отредактировано ivashka777)

Re: Анализатор спектра LCD1602

Подскажите пожалуйста, как правильно установить библиотеку FHT.h?
Скачиваю архив по вашей ссылке, распаковываю содержимое в папку "libraries", но после загрузки скетча (из первого сообщения данной темы), получаю сообщение с предупреждением:
Скетч использует 8816 байт (28%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1228 байт (59%) динамической памяти, оставляя 820 байт для локальных переменных. Максимум: 2048 байт.
Неверная библиотека найдена в C:\Users\имя пользователя\Documents\Arduino\libraries\reorder_table_creator: нет заголовочных файлов (.h), найденных в C:\Users\имя пользователя\Documents\Arduino\libraries\reorder_table_creator
.
Если в "libraries" удалить папку "reorder_table_creator", то все нормально, никаких ошибок нет.
Спасибо.

9

Re: Анализатор спектра LCD1602

Распаковывать не надо, zip добавить через ардуино иде (вкладка добавить библиотеку)

10

Re: Анализатор спектра LCD1602

Я так и пытался сделать, но всегда получаю сообщение:
"Выбранная папка/zip файл не содержит корректных библиотек"
sad

11

Re: Анализатор спектра LCD1602

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

12 (2023-09-29 17:50:47 отредактировано ivashka777)

Re: Анализатор спектра LCD1602

Да, с этим архивом все отлично.
Спасибо!

13 (2023-09-30 22:25:33 отредактировано ivashka777)

Re: Анализатор спектра LCD1602

Здравствуйте.
Собрал по вашей схеме два анализатора спектра. Залил скетч из первого сообщения. Но, анализатор не заработал (хотя запись прошла успешно). Записал скетч со страницы проекта "http://rcl-radio.ru/?p=42903" и все заработало.
http://forum.rcl-radio.ru/uploads/images/2023/09/e6527ba5afb97efc8b033e2818a201e9.jpg
На фото работа устройства:
левый индикатор - все работает - залит старый скетч,
правый индикатор - только кубики - залит скетч из первого сообщения этой ветки.
Подскажите, что я сделал не так?
sad

14

Re: Анализатор спектра LCD1602

Пины подключения LCD в скетчах отличаются, Вы это учитывали при загрузке скетча.

15 (2023-10-02 17:41:56 отредактировано ivashka777)

Re: Анализатор спектра LCD1602

Нет конечно!
В ардуино я не специалист, и нигде не было указано, что нужно по другому распаивать индикатор.
На странице проекта лишь надпись "Обновление скетча — http://forum.rcl-radio.ru/viewtopic.php?id=51"
То, что для него нужно менять подключение LCD нигде ни слова sad .
А под старую распиновку пинов LCD нельзя сделать новый скетч с переключением режимов?
Конструкция уже собрана и менять в ней теперь что либо довольно проблематично.
Спасибо.

16

Re: Анализатор спектра LCD1602

LiquidCrystal lcd(7, 6, 2, 3, 4, 5);// RS,E,D4,D5,D6,D7

заменить на

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

и все

17

Re: Анализатор спектра LCD1602

Заменил, залил, все работает! Режимы переключаются.
Спасибо!

18

Re: Анализатор спектра LCD1602

Здравствуйте, подскажите как в этом скетче сменить аналоговый вход например на А1

19

Re: Анализатор спектра LCD1602

Мне кажется что для таких устройств надо на входе простейший компрессор ставить.
Иначе это будет резкая дергалка.

20

Re: Анализатор спектра LCD1602

Здравствуйте, подскажите как в этом скетче сменить аналоговый вход например на А1

ADMUX  = 0b01100000;
заменить на
ADMUX  = 0b01100001;