программа для генератора Звуковых Частот
- Войдите на сайт для отправки комментариев
Здраствуйте Дорогие Жители, посетитили, и просто проходящие мимо
начну с того что решил я написать генератор ЗЧ первая версия полумилась на УРА вот кому интересно
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
Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.
А чем вам стандартная программа генератора звуковых частот не подходит типа SpectraPlus
http://rutracker.org/forum/viewtopic.php?t=2755857
А чем вам стандартная программа генератора звуковых частот не подходит типа SpectraPlus
http://rutracker.org/forum/viewtopic.php?t=2755857
мобильностью! самое главное
Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.
критикуйте я люблю критику!;-) а главное подробнее! и с примерами кода
Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.
С памятью ясно.
А что вам в форматировании кода не пронравилось?
Ну главный недостаток. Формирует вроде не синус, а прямоуголку. Это уже не то. Сделать простейший ЦАП на матрице резисторов.
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 градусов)
Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.
бери линейку и бей себе по пальцам - кто тебе запрещает?
*чел разобрал всё по полочкам, вместо развесистой лапши в два символа на одну строку - скромный я.
вместо этого
voidBUTTON_00() {///обработчик кнопоквозьми это #1
classBUTTON {Я бы линейкой по пальцам бил за такой отношение к памяти и форматирование кода.
С памятью ясно.
А что вам в форматировании кода не пронравилось?
Нулевая наглядность вложенности.
Километровые разрывы между операторами.
Ctrl+T
Нулевая наглядность вложенности.
Radjah, теперь мне тоже самое повтори про наглядность вложенности, что бы я прочувствовал и насладился всей гаммой твоих страданий при чтении кода.
у тебя что в редакторе подстветка парных скобок не работает или монитор размером с полстены, что весь код в него влазит и у тебя шея не отваливается просматривать весь код?
*так уж получилось, что я пишу код аналогично - операции кода в одну строку, а не один оператор на одну строку.
У меня глаза вытекают от такого "стиля". Я не хочу считать скобки, я хочу видеть отступы.
У меня глаза вытекают от такого "стиля". Я не хочу считать скобки, я хочу видеть отступы.
ок. открой мне религиозную или иную причину, почему тебе сложно прочитать, например такую строку, которая является логически законченным участком кода, выполняющим определённую функцию
if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}}почему тебе нужно, что бы это выглядело так, иначе тебя поразит апоклепсический удар.
if (ndc != dc) { dc = ndc; if (dc == 1) { c = 0; } }так называемое, каноническое форматирование превращающее, логически связные и читаемые строки в развесистое нечто, растянутое на километры текста.
http://cxem.net/arduino/arduino62.php
это интересно
а вод http://robocraft.ru/blog/2911.htm
вместо этого
voidBUTTON_00() {///обработчик кнопоквозьми это #1
classBUTTON {на этом все и построено
У меня глаза вытекают от такого "стиля". Я не хочу считать скобки, я хочу видеть отступы.
ок. открой мне религиозную или иную причину, почему тебе сложно прочитать, например такую строку, которая является логически законченным участком кода, выполняющим определённую функцию
if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}}почему тебе нужно, что бы это выглядело так, иначе тебя поразит апоклепсический удар.
if (ndc != dc) { dc = ndc; if (dc == 1) { c = 0; } }так называемое, каноническое форматирование превращающее, логически связные и читаемые строки в развесистое нечто, растянутое на километры текста.
спасибо за подержку всё в одну строку мне читать проще ладно это не главное главное в том что код работает
на этом все и построено
у тебя построено на этом http://arduino.ru/forum/programmirovanie/titanovyi-velosiped-dlya-taktovoi-knopki
а, нужно на этом http://arduino.ru/forum/programmirovanie/klass-titanovyi-velosiped-dlya-taktovoi-knopki
Так пиши всё в одну строку, оно тоже будет работать, а можно вообще написать в машинных кодах, они тоже будут работать.
Компилятору вообще срать, если это не питон.
Код должен быть человекочитаемым. Если код сложно читать, то автор кода мудак и рукожоп, который не умеет в форматирование кода.
Встречают по одёжке.
Код должен быть человекочитаемым. Если код сложно читать, то автор кода мудак и рукожоп, который не умеет в форматирование кода.
Встречают по одёжке.
ок. теперь иди в пень и не возвращайся.
Опа! Теперь у клапуция бомбит. %)
> не оскорблять
> аутизм - тебя раздражает, когда кто-то твои личные вещи расставил не так, как ты считаешь нужным.
> снобизм - документы должны быть оформлены в полном соответсвии твоему статусу.
Ну ок.
> код читаемый - тебе об этом сказали несколько человек в треде.
Я показал этот опус людям, которые давно занимаются разработкой ПО, они мне сказали, что так пишут код только мудаки.
И да. Аргументация уровня "мы не на экзамене по русскому языку" ITT.
Так пиши всё в одну строку, оно тоже будет работать, а можно вообще написать в машинных кодах, они тоже будут работать.
Компилятору вообще срать, если это не питон.
Код должен быть человекочитаемым. Если код сложно читать, то автор кода мудак и рукожоп, который не умеет в форматирование кода.
Встречают по одёжке.
Мне читать удобно если тебе не удобно подробный глаза об забор
меня? - нет. я раз и навсегда желаю выяснить у представителя Секты Канонического Стиля Форматирования Кода, почему адептов этой секты бомбит от моего кода и как этот факт можно использовать с целью манипуляции их сознанием.
снобизм
ок - аутизм и снобизм для тебя являются оскорбительными словами.
ок. а, сам можешь сформулировать суть своих претензий? без мудаков, которые обзывают кого-попало мудакими?
но вот загвостка не могу сделать так чтобы при втором круге регулирования параметров старые не сбрасывались в ноль а начиналась регулировка с того на чем остановился
не знаю, как в твоей библиотеке но в с этой библиотекой http://www.pjrc.com/teensy/td_libs_Encoder.html можно:
1. писать значение переменной в объект энкодера... encoder1.write(n); где n - требуемое значение, с которого тебе нужно начинать отсчёт.
2. создать отдельные объекты энкодера для настройки каждого параметра - тебе не нужно будет дёргаться, перезаписывать значение энкодера, накрученное тобой будет спокойно лежать в объектах и ждать, когда ты кнопками переключишься на работу именно с этим объектом.
*предпочитаю второй вариант.
но вот загвостка не могу сделать так чтобы при втором круге регулирования параметров старые не сбрасывались в ноль а начиналась регулировка с того на чем остановился
не знаю, как в твоей библиотеке но в с этой библиотекой http://www.pjrc.com/teensy/td_libs_Encoder.html можно:
1. писать значение переменной в объект энкодера... encoder1.write(n); где n - требуемое значение, с которого тебе нужно начинать отсчёт.
2. создать отдельные объекты энкодера для настройки каждого параметра - тебе не нужно будет дёргаться, перезаписывать значение энкодера, накрученное тобой будет спокойно лежать в объектах и ждать, когда ты кнопками переключишься на работу именно с этим объектом.
*предпочитаю второй вариант.
спасибо в моей тоже это реализовано
encoder.setPosition(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 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 не чего не делает