Автору большое спасибо за проект именно с этим LCD экраном, больше нигде найти не смог, а хотелось чуть больше чем 1602 экран..
Собрал все работает, кнопка режимы переключает, сделал задержку на включение усилка, чтоб щелчков при включении не было сделал.. графики пляшут, красиво..
НО при проверка не генераторе частоты оказалось что пляшут они в совершенно случайном порядке. до 1кГц еще есть какая-то зависимость (несколько полосок вместе двигаются с левого до правого края), но дальше - чистый набор шумов и гармоник на дисплее в случайных местах и случайной высоты!
Что я уже только не пробовал, и все коды приведенные выше, и входные пины менять и библиотеки переподгружать, и значения подбирать - все одно и тоже... Голову сломал уже! Буду крайне благодарен за хоть какую-то подсказку!
Мне кажется что проблема именно в коде, что-то не правильно он интерпертирует, поскольку все остальное - отображение надписей на дисплее, и работа реле работает четко. А подключить там что-то не так невозможно.. вход через конденсатор на a2...
#define AUTO_GAIN 0 // автонастройка по громкости
#define VOL_THR 35 // порог тишины (ниже него отображения на матрице не будет)
#define LOW_PASS 30 // нижний порог чувствительности шумов (нет скачков при отсутствии звука)
#define DEF_GAIN 80 // максимальный порог по умолчанию
#define FHT_N 256 // ширина спектра х2
#define LOG_OUT 1
#include <FHT.h>
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#define PIN_RELAY 2
#define AUDIO_IN 16
#define printByte(args) write(args);
double prevVolts = 100.0;
// --------------- БИБЛИОТЕКИ ---------------
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
LiquidCrystal lcd(6, 7, 8, 9, 10, 11);
byte posOffset[20] = {10, 16, 18, 20, 24, 30, 34, 40, 44, 50, 54, 56, 58, 60, 62, 64, 68, 70, 72, 74}; // вч выш
byte maxValue, maxValue_f,ww=1,gain_sp = DEF_GAIN;
float k = 0.1;
int i1,yyy,spek;
unsigned long gainTimer;
void setup(){
Serial.begin(9600);Wire.begin();lcd.begin(20,4);// LCD 20X4
pinMode(12,INPUT);
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
analogReference(EXTERNAL);
spek = EEPROM.read(100);
lcd.print("MUTED, please wait.. ");delay(200);
lcd.print("*");delay(150);
lcd.print("*");delay(150);
lcd.print("*");delay(150);
lcd.print("*");delay(100);
lcd.print("*");delay(100);
lcd.print("*");delay(100);
lcd.print("*");delay(50);
lcd.print("*");delay(50);
lcd.print("*");delay(50);
lcd.print("*");delay(50);
lcd.print("*");delay(50);
lcd.print("*");delay(50);
lcd.print("*");delay(50);
lcd.print("*");delay(50);
lcd.print("*");delay(50);
lcd.print("*");delay(300);
lcd.clear();
pinMode(PIN_RELAY, OUTPUT); // Объявляем пин реле как выход
digitalWrite(PIN_RELAY, HIGH); // Выключаем реле - посылаем высокий сигнал
lcd.print(" ON AIR! ENJOY!");delay(200);
}
void loop(){
if(digitalRead(12)==HIGH){spek++;EEPROM.update(100,spek); ww=1;if(spek>5){spek=0;}delay(300);}
if(spek==0&&ww==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);
ww=0;}
if(spek==1&&ww==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);
ww=0;}
if(spek==2&&ww==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);
ww=0;}
if(spek==3&&ww==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);
ww=0;}
if(spek==4&&ww==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);
ww=0;}
if(spek==5&&ww==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);
ww=0;}
analyzeAudio(); // функция FHT, забивает массив fht_log_out[] величинами по спектру
for (int pos = 0; pos < 20; pos++) {
if (fht_log_out[posOffset[pos]] > maxValue) maxValue = fht_log_out[posOffset[pos]];
int posLevel = map(fht_log_out[posOffset[pos]], LOW_PASS, gain_sp, 0, 31);
posLevel = constrain(posLevel, 0, 31);
if(posLevel<7){
lcd.setCursor(pos, 0);lcd.print(" ");
lcd.setCursor(pos, 1);lcd.print(" ");
lcd.setCursor(pos, 2);lcd.print(" ");
lcd.setCursor(pos, 3);lcd.write((uint8_t)posLevel);}
if(posLevel>7&&posLevel<15){
lcd.setCursor(pos, 0);lcd.print(" ");
lcd.setCursor(pos, 1);lcd.print(" ");
lcd.setCursor(pos, 3);lcd.write((uint8_t)7);lcd.setCursor(pos, 2);lcd.write((uint8_t)posLevel-8);}
if(posLevel>15&&posLevel<23){
lcd.setCursor(pos, 0);lcd.print(" ");
lcd.setCursor(pos, 3);lcd.write((uint8_t)7);
lcd.setCursor(pos, 2);lcd.write((uint8_t)7);lcd.setCursor(pos, 1);lcd.write((uint8_t)posLevel-16);}
if(posLevel>23&&posLevel<31){
lcd.setCursor(pos, 3);lcd.write((uint8_t)7);
lcd.setCursor(pos, 2);lcd.write((uint8_t)7);
lcd.setCursor(pos, 1);lcd.write((uint8_t)7);lcd.setCursor(pos, 0);lcd.write((uint8_t)posLevel-24);}
}
if (AUTO_GAIN) {
maxValue_f = maxValue * k + maxValue_f * (1 - k);
if (millis() - gainTimer > 10) {
if (maxValue_f > VOL_THR) gain_sp = maxValue_f;
else gain_sp = 100;
gainTimer = millis();}
else {gain_sp = DEF_GAIN;}}
}// loop
void analyzeAudio() {
for (int i = 0 ; i < FHT_N ; i++) {
int sample = analogRead(AUDIO_IN);
fht_input[i] = sample; // put real data into bins
}
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
}