программа для генератора Звуковых Частот

0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

Здраствуйте Дорогие Жители, посетитили, и просто проходящие мимо

начну с того что решил я написать генератор ЗЧ первая версия полумилась на УРА вот кому интересно

  int But1 = 2; // +1
  int But2 = 3; // +10
  int But3 = 4; // +100
  int But4 = 7; // -1
  int But5 = 6; // -10
  int But6 = 5; // -100
  int But7 = 8; // start
  int But8 = 9; // stop
  
  int val = 0;  // значение частоты
  int val1 = 0;  // пуск - стоп
  int steit1 =0; // состояние кнопки
  int steit2 =0; // состояние кнопки
  int steit3 =0; // состояние кнопки
  int steit4 =0; // состояние кнопки
  int steit5 =0; // состояние кнопки
  int steit6 =0; // состояние кнопки
  int steit7 =0; // состояние кнопки
  int steit8 =0; // состояние кнопки

  int gen = 10;

  byte smile[8] =
{
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
}; 

  #include <Wire.h>
  #include <LiquidCrystal_I2C.h>

  //                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
  LiquidCrystal_I2C lcd(0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);  // Set the LCD I2C address

void setup() {
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.createChar(1, smile);
  /////////////////////////////
  pinMode(But1 , INPUT);
  pinMode(But2 , INPUT);
  pinMode(But3 , INPUT);
  pinMode(But4 , INPUT);
  pinMode(But5 , INPUT);
  pinMode(But6 , INPUT);
  pinMode(But7 , INPUT);
  pinMode(But8 , INPUT);
  //////////////////////////////
  digitalWrite(But1 ,HIGH);
  digitalWrite(But2 ,HIGH);
  digitalWrite(But3 ,HIGH);
  digitalWrite(But4 ,HIGH);
  digitalWrite(But5 ,HIGH);
  digitalWrite(But6 ,HIGH);
  digitalWrite(But7 ,HIGH);
  digitalWrite(But8 ,HIGH);
  //////////////////////////////
  }

void loop() {
 
 lcd.home();
 lcd.clear();
 lcd.print(val);
 lcd.setCursor(5, 0);
 lcd.print(":Hz");
 
 lcd.setCursor(0, 1);
 if(val1 == 1){GEN();}
 else {noTone(gen);lcd.print("\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1");}
 if(val<=0){val=0;lcd.setCursor(10, 0);}
 
 BUTTON();
}
 void BUTTON(){
 steit1 = digitalRead(But1);
 steit2 = digitalRead(But2);
 steit3 = digitalRead(But3);
 steit4 = digitalRead(But4);
 steit5 = digitalRead(But5);
 steit6 = digitalRead(But6);
 steit7 = digitalRead(But7);
 steit8 = digitalRead(But8);
 ////////////////////////////
 if(steit1 == LOW){val = val + 1;delay(100);}
 //else {val = val;}
 if(steit2 == LOW){val = val + 10;delay(100);}
 //else {val = val;}
 if(steit3 == LOW){val = val + 100;delay(100);}
 //else {val = val;}
 ////////////////
 if(steit4 == LOW){val = val - 1;delay(100);}
 //else {val = val;}
 if(steit5 == LOW){val = val - 10;delay(100);}
 //else {val = val;}
 if(steit6 == LOW){val = val - 100;delay(100);}
 //else {val = val;}
 ////////////////
 if(steit7 == LOW){val1 = 1;}
 //else {val = val;}
 if(steit8 == LOW){val1 = 0;}
 //else {val1 = val1;}

 }
 void GEN(){
 Serial.println("Tone:");
 Serial.print(val);
 tone (gen,val);
 }
 
 

так сказать при обкатке оказалось что в кнопках можно потеряться! да и функционал маловат 

тогда было принято решение создать ver 2.0 тоесть (генератор+регулировка"громкости" ну и длительность сигнала в миллисекундах.

вот вторая программа напоминаю это ну типа BETTA 2.0



#include <RotaryEncoder.h>//инклюдим библиотеку
RotaryEncoder encoder(A2, A0);//переменная устанавливает ножки енкодера

//+++++++++++++++++++++++++++++++++++++
byte pb_00 = A1;
//-----------------------------------------------------------------------------
  int val = 0;  // значение частоты
  int val1 = 0;  // пуск - стоп
  int pwr = 0;
  int tim = 0;
  //////////////
  int klik = 0;
  int klik2 = 0;
  int klik3 = 0;
  
  //////////////
  int gen = 10;

  
//-----------------------------------------------------------------------------

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);  // Set the LCD I2C address

void setup()
{
  Serial.begin(9600);
  PCICR |= (1 << PCIE1);    
  PCMSK1 |= (1 << PCINT10) | (1 << PCINT8);  
 
  ///++++++++++++++++++++++++++++++++++++++
  pinMode(pb_00, INPUT); // конфигурируется пин для кнопки BUTTON_00.
  digitalWrite(pb_00, HIGH);
  //+++++++++++++++++++++++++++++++++++++++
  lcd.begin(16,2);
  
  //+++++++++++++++++++++++++++++++++++++++
  } 

ISR(PCINT1_vect) {encoder.tick(); }

void GEN(){Serial.println("Tone:");Serial.print(val);tone (gen,val,tim);}

void loop()
{
    static int time=0;
  //==============
    static int pos = 0;
    int newPos = encoder.getPosition();
    if (pos != newPos) {
    pos = newPos;}
    if(newPos<=0){encoder.setPosition(0);}
  //==============
   if(klik2==0){time=millis();klik3=time+10;if(klik3==time){if(val!=newPos){encoder.setPosition(val);}}
   if(klik==0){val = newPos;}
   if(klik==1){if(newPos>=1){val=val+10; encoder.setPosition(0);}if(newPos==-1){val=val-10;encoder.setPosition(0);}}
   if(klik==2){if(newPos>=1){val=val+100; encoder.setPosition(0);}if(newPos==-1){val=val-100;encoder.setPosition(0);}}
   if(klik==3){encoder.setPosition(val);} }
   
   if(klik2==1){
   if(klik==0){tim = newPos;}
   if(klik==1){if(newPos>=1){tim=tim+10; encoder.setPosition(0);}if(newPos==-1){tim=tim-10;encoder.setPosition(0);}}
   if(klik==2){if(newPos>=1){tim=tim+100; encoder.setPosition(0);}if(newPos==-1){tim=tim-100;encoder.setPosition(0);}}
   if(klik==3){encoder.setPosition(tim);} }
   
   if(klik2==2){ pwr = newPos;}
   if(klik>=3){klik=0;}
   if(klik2>=3){klik2=0;}
   Serial.println(time);
   Serial.println(klik3);
   
//+=+=+=+==========================================================
 
 BUTTON1();
 BUTTON_00();
//+=+=+=+==========================================================
}

void BUTTON1(){// кнопки генератора
 lcd.home();
 //lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(val);
 lcd.setCursor(5, 0);
 lcd.print(":Hz");
 lcd.setCursor(8, 0);
 lcd.print(char(255));
 lcd.setCursor(8, 1);
 lcd.print(char(255));
 lcd.setCursor(9, 0);
 lcd.print(tim);
 lcd.setCursor(13, 0);
 lcd.print(":Ms");
 lcd.setCursor(0, 1);
 lcd.print("Pwr:");
 lcd.setCursor(4, 1);
 lcd.print(pwr);
 lcd.setCursor(7, 1);
 lcd.print("%");
 if(val1==0){noTone(gen); lcd.setCursor(10, 1); lcd.print("STOP");}else{GEN(); lcd.setCursor(10, 1); lcd.print("START");}
 Serial.println(klik3);

 
 }

void BUTTON_00() {///обработчик кнопок
//=======================================================
static unsigned long  m =           millis();
       unsigned long nm =           millis();
static boolean        p = digitalRead(pb_00);
       boolean       np = digitalRead(pb_00);
//=================
if (np != p) {p = np; m = nm;}
//=======================================================
static byte         bounce      =   20; // длительность дребезга.
static boolean      b           =    0;
       boolean     nb;
//=================
static unsigned int doubleclick =  200; // длительность двойного клика.
static boolean      dc          =    0;
       boolean     ndc;
static byte          c          =    0;
//=================
if (nm - m > bounce) {nb = 1;} else {nb = 0;}

if (nm - m > doubleclick) {ndc = 1;} else {ndc = 0;}
if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}}

if (nb != b) {b = nb;
if (p == 0 && b == 0) {BUTTON_00_bounce_down();// нажатие кнопки.
++c;      if (c == 2) {BUTTON_00_doubleclick_down();} // двойной клик.
}
if (p == 1 && b == 1) {BUTTON_00_bounce_up();} // отпускание кнопки.
}
//=======================================================
static unsigned long timer = 10000; // длительность таймера, запускаемого одиночным кликом.
static boolean       t     =     0;
       boolean      nt;
//=================
if (nm - m > timer) {nt = 1;} else {nt = 0;}
if (nt != t) {t = nt;
if (p == 1 && t == 1) {BUTTON_00_timer_up();} // срабатывание таймера, запускаемого одиночным кликом.
}
//=======================================================
static unsigned int retention = 2000; // длительность удержания кнопки до срабатывания таймера.
static boolean      r         =    0;
       boolean     nr;
//=================
if (nm - m > retention) {nr = 1;} else {nr = 0;}
if (nr != r) {r = nr;
if (p == 0 && r == 1) {BUTTON_00_retention_down();} // срабатывание таймера, запускаемого удержанием кнопки.
}
//=======================================================
}

void BUTTON_00_bounce_down() {klik++;encoder.setPosition(0);} // подпрограмма, содержащая всё, что должно происходить при нажатии кнопки.
void BUTTON_00_bounce_up() {lcd.clear();} // подпрограмма, содержащая всё, что должно происходить при отпускании кнопки.
void BUTTON_00_doubleclick_down() {klik=0; klik2++; klik3++;} // подпрограмма, содержащая всё, что должно происходить при двойном клике.
void BUTTON_00_timer_up() {Serial.println("3");} // подпрограмма, содержащая всё, что должно происходить при срабатывании таймера, запущенного одиночным кликом кнопки.
void BUTTON_00_retention_down() {static int fi = 0;  fi++; if(fi==1){val1=1;}else{val1=0;fi = 0;} klik =0;} // подпрограмма, содержащая всё, что должно происходить при после срабатывания таймера, запущенного нажатием и удержанием кнопки.

управление энкодером от авто магнитолы или "СД-олы" ;) естественно с кнопочкй все тот же i2c 1602 

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

вот библиотека на энкодер https://yadi.sk/d/vtDkM8DJn6YkR

 

Radjah
Offline
Зарегистрирован: 06.08.2014

Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.

Buldakov
Offline
Зарегистрирован: 17.01.2016

А чем вам стандартная программа генератора звуковых частот не подходит типа SpectraPlus

http://rutracker.org/forum/viewtopic.php?t=2755857

 

0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

Buldakov пишет:

А чем вам стандартная программа генератора звуковых частот не подходит типа SpectraPlus

http://rutracker.org/forum/viewtopic.php?t=2755857

 

мобильностью! самое главное

0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

Radjah пишет:

Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.

критикуйте я люблю критику!;-) а главное подробнее! и с примерами кода

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Radjah пишет:

Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.

С памятью ясно.

А что вам в форматировании кода не пронравилось?

 

Buldakov
Offline
Зарегистрирован: 17.01.2016

Ну главный недостаток. Формирует вроде не синус, а прямоуголку. Это уже не то. Сделать простейший ЦАП на матрице резисторов.

http://cxem.net/arduino/arduino62.php

http://robocraft.ru/blog/2911.htm

только резисторы обязательно точностью 1 процент.(или лучше подобрать по тестеру из 5 процентных.) Номиналом от 1 до 10 ком. Будет гораздо лучше. Мне больше нравится вариант с таблицей отсчетов синуса. Но на высоких частотах минимальный шаг по частоте будет большим. Если он важен.

Можно написать алгоритм работы DDS типа AD9832. и тогда отсчеты времени синусоиды будут не расчетные для заданной частоты умноженное на фиксированное значение, а наоборот. типа сейчас на частоте 100 гц 8 отсчетов и на частоте 1000 гц - тоже 8 отсчетов. А будет на частоте 100 гц 80 отсчетов на частоте 1000 гц 8 отсчетов , а на частоте 1100 гц 7,5 отсчетов. поскольку дробное число получить нельзя - мы берем 8 , но из таблицы берем уже другое значение амплитуды (для значения фазы например 18 градусов)

 

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Radjah пишет:

Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.

бери линейку и бей себе по пальцам - кто тебе запрещает?

*чел разобрал всё по полочкам, вместо развесистой лапши в два символа на одну строку - скромный я.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

вместо этого 

void BUTTON_00() {///обработчик кнопок

возьми это #1 class BUTTON {

Radjah
Offline
Зарегистрирован: 06.08.2014

bodriy2014 пишет:

Radjah пишет:

Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.

С памятью ясно.

А что вам в форматировании кода не пронравилось?

 

Нулевая читаемость условий в одну строку.

Нулевая наглядность вложенности.

Километровые                                 разрывы                                    между                          операторами.

Ctrl+T

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Radjah пишет:

Нулевая наглядность вложенности.

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

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

*так уж получилось, что я пишу код аналогично - операции кода в одну строку, а не один оператор на одну строку.

Radjah
Offline
Зарегистрирован: 06.08.2014

У меня глаза вытекают от такого "стиля". Я не хочу считать скобки, я хочу видеть отступы.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Radjah пишет:

У меня глаза вытекают от такого "стиля". Я не хочу считать скобки, я хочу видеть отступы.

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

if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}}

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

if (ndc != dc) {
  dc = ndc;
  if (dc == 1) {
    c = 0;
  }
}

так называемое, каноническое форматирование превращающее, логически связные и читаемые строки в развесистое нечто, растянутое на километры текста.

*для понимания сути проблемы - что это? 
аутизм - тебя раздражает, когда кто-то твои личные вещи расставил не так, как ты считаешь нужным.
снобизм - документы должны быть оформлены в полном соответсвии твоему статусу.
 
**Лешак мне шото подобное пыталася рассказать, но не смог аргументировать ничем от слова НИЧЕМ.
0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

Buldakov пишет:

 

http://cxem.net/arduino/arduino62.php

 

 

это интересно 

а вод http://robocraft.ru/blog/2911.htm

ошибка 404
0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

Клапауций 322 пишет:

вместо этого 

void BUTTON_00() {///обработчик кнопок

возьми это #1 class BUTTON {

на этом все и построено

0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

Клапауций 322 пишет:

Radjah пишет:

У меня глаза вытекают от такого "стиля". Я не хочу считать скобки, я хочу видеть отступы.

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

if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}}

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

if (ndc != dc) {
  dc = ndc;
  if (dc == 1) {
    c = 0;
  }
}

так называемое, каноническое форматирование превращающее, логически связные и читаемые строки в развесистое нечто, растянутое на километры текста.

*для понимания сути проблемы - что это? 
аутизм - тебя раздражает, когда кто-то твои личные вещи расставил не так, как ты считаешь нужным.
снобизм - документы должны быть оформлены в полном соответсвии твоему статусу.
 
**Лешак мне шото подобное пыталася рассказать, но не смог аргументировать ничем от слова НИЧЕМ.

спасибо за подержку всё в одну строку мне читать проще ладно это не главное главное в том что код работает

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

0259 пишет:

на этом все и построено

у тебя построено на этом http://arduino.ru/forum/programmirovanie/titanovyi-velosiped-dlya-taktovoi-knopki

а, нужно на этом http://arduino.ru/forum/programmirovanie/klass-titanovyi-velosiped-dlya-taktovoi-knopki

Radjah
Offline
Зарегистрирован: 06.08.2014

Так пиши всё в одну строку, оно тоже будет работать, а можно вообще написать в машинных кодах, они тоже будут работать.

Компилятору вообще срать, если это не питон.

Код должен быть человекочитаемым. Если код сложно читать, то автор кода мудак и рукожоп, который не умеет в форматирование кода.

Встречают по одёжке.

 

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Radjah пишет:

Код должен быть человекочитаемым. Если код сложно читать, то автор кода мудак и рукожоп, который не умеет в форматирование кода.

код читаемый - тебе об этом сказали несколько человек в треде.
я тебя просил аргументировать своё мнение, а не оскорблять людей по признаку выбора ими стиля форматирования кода.

Radjah пишет:

Встречают по одёжке.

ок. теперь иди в пень и не возвращайся.

Radjah
Offline
Зарегистрирован: 06.08.2014

Опа! Теперь у клапуция бомбит. %)

> не оскорблять

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

Ну ок.

> код читаемый - тебе об этом сказали несколько человек в треде.

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

И да. Аргументация уровня "мы не на экзамене по русскому языку" ITT.

0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

Radjah пишет:

Так пиши всё в одну строку, оно тоже будет работать, а можно вообще написать в машинных кодах, они тоже будут работать.

Компилятору вообще срать, если это не питон.

Код должен быть человекочитаемым. Если код сложно читать, то автор кода мудак и рукожоп, который не умеет в форматирование кода.

Встречают по одёжке.

 


Мне читать удобно если тебе не удобно подробный глаза об забор

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Radjah пишет:
Опа! Теперь у клапуция бомбит. %)

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

Radjah пишет:
аутизм

снобизм

ок - аутизм и снобизм для тебя являются оскорбительными словами.

Radjah пишет:
Я показал этот опус людям, которые давно занимаются разработкой ПО, они мне сказали, что так пишут код только мудаки.

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

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

0259 пишет:

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

не знаю, как в твоей библиотеке но в с этой библиотекой http://www.pjrc.com/teensy/td_libs_Encoder.html можно:

1. писать значение переменной в объект энкодера... encoder1.write(n); где n - требуемое значение, с которого тебе нужно начинать отсчёт.

2. создать отдельные объекты энкодера для настройки каждого параметра - тебе не нужно будет дёргаться, перезаписывать значение энкодера, накрученное тобой будет спокойно лежать в объектах и ждать, когда ты кнопками переключишься на работу именно с этим объектом.

RotaryEncoder encoder1(A2, A0); // параметр 1
RotaryEncoder encoder2(A2, A0); // параметр 2
RotaryEncoder encoder3(A2, A0); // параметр 3

*предпочитаю второй вариант.

0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

Клапауций 322 пишет:

0259 пишет:

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

не знаю, как в твоей библиотеке но в с этой библиотекой http://www.pjrc.com/teensy/td_libs_Encoder.html можно:

1. писать значение переменной в объект энкодера... encoder1.write(n); где n - требуемое значение, с которого тебе нужно начинать отсчёт.

2. создать отдельные объекты энкодера для настройки каждого параметра - тебе не нужно будет дёргаться, перезаписывать значение энкодера, накрученное тобой будет спокойно лежать в объектах и ждать, когда ты кнопками переключишься на работу именно с этим объектом.

RotaryEncoder encoder1(A2, A0); // параметр 1
RotaryEncoder encoder2(A2, A0); // параметр 2
RotaryEncoder encoder3(A2, A0); // параметр 3

*предпочитаю второй вариант.

спасибо в моей тоже это реализовано 

encoder.setPosition(0);

0259
0259 аватар
Offline
Зарегистрирован: 30.03.2014

вот готовый код 



#include <RotaryEncoder.h>//инклюдим библиотеку
RotaryEncoder encoder(A2, A0);//переменная устанавливает ножки енкодера

//+++++++++++++++++++++++++++++++++++++
byte pb_00 = A1;
//-----------------------------------------------------------------------------
  int val = 0;  // значение частоты
  int val1 = 0;  // пуск - стоп
  int pwr = 0;
  int tim = 0;
  //////////////
  int klik = 0;
  int klik2 = 0;
  int klik3 = 0;
  /////////////
  int test0 = 1;
  int test1 = 1;
  int test2 = 1;
  //////////////
  int gen = 10;

  
//-----------------------------------------------------------------------------

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);  // Set the LCD I2C address

void setup()
{
  Serial.begin(9600);
  PCICR |= (1 << PCIE1);    
  PCMSK1 |= (1 << PCINT10) | (1 << PCINT8);  
 
  ///++++++++++++++++++++++++++++++++++++++
  pinMode(pb_00, INPUT); // конфигурируется пин для кнопки BUTTON_00.
  digitalWrite(pb_00, HIGH);
  //+++++++++++++++++++++++++++++++++++++++
  lcd.begin(16,2);
  
  //+++++++++++++++++++++++++++++++++++++++
  } 

ISR(PCINT1_vect) {encoder.tick(); }

void GEN(){Serial.println("Tone:");Serial.print(val);tone (gen,val,tim);}

void loop()
{
    
  //==============
    static int pos = 0;
    int newPos = encoder.getPosition();
    if (pos != newPos) {
    pos = newPos;}
    if(newPos<=0){encoder.setPosition(0);}
  //==============
   if(klik2==0){if(test0==0){encoder.setPosition(val); test0=1;}
   if(klik==0){val = newPos;}
   if(klik==1){if(newPos>=1){val=val+10; encoder.setPosition(0);}if(newPos==-1){val=val-10;encoder.setPosition(0);}}
   if(klik==2){if(newPos>=1){val=val+100; encoder.setPosition(0);}if(newPos==-1){val=val-100;encoder.setPosition(0);}}
   if(klik==3){encoder.setPosition(val);} }
   
   if(klik2==1){if(test1==0){encoder.setPosition(tim);test1=1;}
   if(klik==0){tim = newPos;}
   if(klik==1){if(newPos>=1){tim=tim+10; encoder.setPosition(0);}if(newPos==-1){tim=tim-10;encoder.setPosition(0);}}
   if(klik==2){if(newPos>=1){tim=tim+100; encoder.setPosition(0);}if(newPos==-1){tim=tim-100;encoder.setPosition(0);}}
   if(klik==3){encoder.setPosition(tim);} }
   
   if(klik2==2){if(test2==0){encoder.setPosition(pwr);test2=1;} 
   if(klik==0){pwr = newPos;}
   if(klik==1){encoder.setPosition(pwr);}klik=0;}
   
   
   if(klik>=3){klik=0;}
   if(klik2>=3){klik2=0;}
   if(klik3==3){klik3=0;}
      
//+=+=+=+==========================================================
 
 BUTTON1();
 BUTTON_00();
//+=+=+=+==========================================================
}

void BUTTON1(){// кнопки генератора
 lcd.home();
 //lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(val);
 lcd.setCursor(5, 0);
 lcd.print(":Hz");
 lcd.setCursor(8, 0);
 lcd.print(char(255));
 lcd.setCursor(8, 1);
 lcd.print(char(255));
 lcd.setCursor(9, 0);
 lcd.print(tim);
 lcd.setCursor(13, 0);
 lcd.print(":Ms");
 lcd.setCursor(0, 1);
 lcd.print("Pwr:");
 lcd.setCursor(4, 1);
 lcd.print(pwr);
 lcd.setCursor(7, 1);
 lcd.print("%");
 if(val1==0){noTone(gen); lcd.setCursor(10, 1); lcd.print("STOP");}else{GEN(); lcd.setCursor(10, 1); lcd.print("START");}
 }

void BUTTON_00() {///обработчик кнопок
//=======================================================
static unsigned long  m =           millis();
       unsigned long nm =           millis();
static boolean        p = digitalRead(pb_00);
       boolean       np = digitalRead(pb_00);
//=================
if (np != p) {p = np; m = nm;}
//=======================================================
static byte         bounce      =   20; // длительность дребезга.
static boolean      b           =    0;
       boolean     nb;
//=================
static unsigned int doubleclick =  200; // длительность двойного клика.
static boolean      dc          =    0;
       boolean     ndc;
static byte          c          =    0;
//=================
if (nm - m > bounce) {nb = 1;} else {nb = 0;}

if (nm - m > doubleclick) {ndc = 1;} else {ndc = 0;}
if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}}

if (nb != b) {b = nb;
if (p == 0 && b == 0) {BUTTON_00_bounce_down();// нажатие кнопки.
++c;      if (c == 2) {BUTTON_00_doubleclick_down();} // двойной клик.
}
if (p == 1 && b == 1) {BUTTON_00_bounce_up();} // отпускание кнопки.
}
//=======================================================
static unsigned long timer = 10000; // длительность таймера, запускаемого одиночным кликом.
static boolean       t     =     0;
       boolean      nt;
//=================
if (nm - m > timer) {nt = 1;} else {nt = 0;}
if (nt != t) {t = nt;
if (p == 1 && t == 1) {BUTTON_00_timer_up();} // срабатывание таймера, запускаемого одиночным кликом.
}
//=======================================================
static unsigned int retention = 2000; // длительность удержания кнопки до срабатывания таймера.
static boolean      r         =    0;
       boolean     nr;
//=================
if (nm - m > retention) {nr = 1;} else {nr = 0;}
if (nr != r) {r = nr;
if (p == 0 && r == 1) {BUTTON_00_retention_down();} // срабатывание таймера, запускаемого удержанием кнопки.
}
//=======================================================
}

void BUTTON_00_bounce_down() {klik++;encoder.setPosition(0);} // подпрограмма, содержащая всё, что должно происходить при нажатии кнопки.
void BUTTON_00_bounce_up() {lcd.clear();} // подпрограмма, содержащая всё, что должно происходить при отпускании кнопки.
void BUTTON_00_doubleclick_down() {klik=0; klik2++; klik3++;if(klik3==1){test0=0;}if(klik2==2){test1=0;}if(klik3==3){test2=0;}} // подпрограмма, содержащая всё, что должно происходить при двойном клике.
void BUTTON_00_timer_up() {Serial.println("3");} // подпрограмма, содержащая всё, что должно происходить при срабатывании таймера, запущенного одиночным кликом кнопки.
void BUTTON_00_retention_down() {static int fi = 0;  fi++; if(fi==1){val1=1;}else{val1=0;fi = 0;} klik =0;} // подпрограмма, содержащая всё, что должно происходить при после срабатывания таймера, запущенного нажатием и удержанием кнопки.

пока еше переменная pwr не чего не делает