Делаем дозиметр!

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

Минимальный порог сигналки и будет от 100.

сейчас он от 10 лишь для того, что бы можно было проверять мне ее. Ибо источника радиации пока что нету что бы повышать фон.

Тобишь только допилить код сигналки и все? 

 

alexadresat
alexadresat аватар
Offline
Зарегистрирован: 22.02.2017

Раньше больше 3000 не наберал...

Колокольчик за графиком как-то не смотрится.

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019
/* ArDOs   v1.08.2
***Дозиметр на Ардуино
***IDE Arduino 1.8.8
  ветка форума arduino.ru/forum/proekty/delaem-dozimetr
  сайт srukami.inf.ua/ardos.html
*/
#include <util/delay.h> //уже есть
#include <EEPROM.h>//уже есть
#include <LCD5110_Graph.h>//нужно установить

//настройки /////////////начало
LCD5110 myGLCD(A1, A0, 12, 10, 11); //подключение дисплея
#define contrast 70 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
//#define UNO_DIP // если используется ArduinoUNO или плата на голой атмеге328 в корпусе DIP - раскомментируйте данную строчку. Это переключит чтение напряжения с делителя с ноги A6 на ногу A5.
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 0; //вторая ступень тревоги
byte del_BUZZ = 2;//длительность одиночного сигнала
#define  ADC_value 225  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255). Для значений делителя с сайта srukami 163. alexadresat 185. (Тестовая версия tekagi  67)
#define k_delitel 420 //коефициент делителя напряжения, зависит от вашего делителя. Для значений делителя с сайта srukami k_delitel 576. alexadresat 500 (Тестовая версия tekagi  1395)
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool podsvetka = 0; //подсветка
uint8_t graph_type = 1; //тип графика
bool alarm_sound = 0; //флаг индикации превышения порога звуком
float opornoe = 1.10; //делить на opornoe/10
#define save_DOZ 1 //как часто сохранять накопленную дозу например каждые 20мкР
#define geiger_counter_seconds 40 // число секунд для замера, соответствующее характеристикам счётчика. Для СБМ-20 равно 40.
byte beta_time = 5; //время замера бета излучения
uint8_t batproc = 0; // 1- отображать проценты. 0 - не отображать
float batusb = 4.30; // настройка напряжения, выше которого будет отображаться значек USB
float batmax = 4.15; //Настройка максимального значения напряжения акб для отображения. Обычно 4.20 вольта
float batnapruga = 3.20; //Настройка минимального значения напряжения акб для отображения. Зависит от работоспособности вашей схемы. Обычно 3.20 вольта by OfficialGalkin 
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFontRus[], MediumNumbers[], TinyFontRus[];
volatile uint8_t timer_seconds = 0; // для отсчёта секундных интервалов в прерывании
uint8_t beta_seconds = 0;
uint8_t count_and_dose_seconds = 0;
#define maxString 21 // для работы функции преобразования кодировки utf8us
char target[maxString + 1] = ""; // для работы функции преобразования кодировки utf8us
extern uint8_t logo_bat[], logo_bat_line[], logo_bat_usb[], logo_rag[], logo_tr[], beta_prev_1[], beta_prev_2[], beta_fon[], em_logo[], fon_poisk[], mkr[], mr[];
volatile int shet = 0;
volatile bool overflow_alarm = 0;
int8_t ind_ON = 1;  //0 - индикация выключена, 1 - включён бузер, 2 - светодиод, 3 - и бузер, и светодиод
uint8_t first_alarm_type = 1;  //1-3, 1 - только бузер, 2 - только вибро, 3 - и бузер, и вибро
byte periodical_alarm_variable = 0; // переменная для периодически повторяющейся тревожной сигнализации
uint8_t tr2 = 0; // сигналка 2 сработала
unsigned long gr_milis = 0, lcd_milis = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
uint16_t hv_adc, hv_400, shet_n = 0, shet_s = 0;
uint16_t fon = 0, fon_254 = 0;
int speed_nakT = 0, speed_nak = 0, result;
byte MIN, DAY, HOUR, MONTH; //для учёта времени дозы
uint16_t doza_vr = 0, fon_vr254 = 0, fon_vr_poisk = 0;
byte mass_p[84]; // массив для графика
byte m = 0, n_menu = 0, sys_menu = 0, sys_menu_1 = 0, sys_menu_2 = 0;
byte  mass_poisk[255]; // основной рабочий массив
byte val_kl = 0, val_ok = 0, menu = 0, zam_poisk_counter = 0;
byte sek = 0, minute = 0, bet_z = 0, gotovo = 0;
int  bet_z0 = 0, bet_z1 = 0, bet_r = 0;
float VCC = 0.0, doz_v = 0.0;
bool tr = 0, poisk = 1, fonarik = 0, toch, blink_data=1;
uint8_t GRAPH_max = 5; // максимальное значение за период отображения графика
uint8_t GRAPH_count = 0; // счётчик для поиска максимального значения для графика
#define key_pressed_left 1
#define key_pressed_right 2
#define key_pressed_ok 3
#define key_holded_left 4
#define key_holded_right 5
#define key_holded_ok 6
#define keys_not_pressed 0
uint8_t key_data = 0;
//-------------------------------------------------------------
void setup() {
  //-----------------------------------------------------------
  // настраиваем таймер на секундный интервал
  TCCR1A=(1<<WGM11); //режим14 FAST PWM 
  TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
if (F_CPU == 16000000UL) 
 {
  ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
 }
else if (F_CPU == 8000000UL) 
 {
  ICR1=31249;  // (8000000MHz /div256) -1 = 1 раз в секунду
 } 
  TIMSK1=(1<<TOIE1); //разрешить прерывание
  //-----------------------------------------------------------
// Serial.begin(115200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (1 << 0); PORTB &= ~(1 << 0); //пин вибры 8
  DDRC |= (0 << 4); PORTC &= ~(1 << 4); //пин пустой А4
  DDRC |= (0 << 5); PORTC &= ~(1 << 5); //пин пустой А5
  DDRB |= (1 << 1);//пин фонаря
  DDRC |= (1 << 3);//A3 дисплей GND
  DDRC |= (1 << 2);//A2 дисплей Light
  PORTC &= ~(1 << 3); //A3 дисплей GND
  PORTC  |= (1 << 2); //A2 дисплей Light
  eeprom_readS ();
  eeprom_readD ();
  lcd_init();
  attachInterrupt(0, Schet, FALLING);//прерываниям пин 2
  DDRB |= (1 << 5); //пины на выход
  DDRD |= (1 << 5);
  DDRD |= (1 << 6);
  DDRD |= (1 << 6);//пин бузера
  nakachka();
  clear_poisk_variables();
}
//-------------------------------------------------------------
void loop() 
{
key_data = get_key();  // вызываем функцию определения нажатия кнопок, присваивая возвращаемое ней значение переменной, которую далее будем использовать в коде
if (menu == 0) 
  {
    if (key_data == key_pressed_left)   //нажатие <<<
    {
      key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду 
      clear_poisk_variables();
    }
    if (key_data == key_holded_left) //удержание <<< фонарик  
  {
    fonarik = !fonarik; 
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
  }   
    if (key_data == key_holded_right) // удержание <<< подсветка
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
        podsvetka = !podsvetka;
    }   
    if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 4;
    shet = 0;
    bet_z0 = 0;
    bet_z1 = 0;
    bet_r = 0;
    bet_z = 0;
    gotovo = 0;
    sek = 0;
    minute = 0;
    }
 } 
if (menu == 3)
  {
    if (key_data == key_pressed_left)  //нажатие <<<
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    shet = 0; fon = 0; zam_poisk_counter = 0;
    for (int i = 0; i < 18; i++) { mass_poisk[i] = 0; }//чистим
  }
  } 
if (menu == 4) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    clear_poisk_variables();
    }
  }
if (fonarik == 0)  //фонарик
  {
    PORTB &= ~(1 << 1);//пин фонаря
  } 
else if (fonarik == 1) 
  {
    PORTB |= (1 << 1);//пин фонаря
  }
if (podsvetka == 1) 
  {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
else if (podsvetka == 0) 
  {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300)  //скорость отрисовки дисплея
  {
    lcd_milis = millis();
    blink_data = !blink_data;
    if (menu == 0) 
      {
        lcd_poisk();  //вывод на дисплей режима поиск
        poisk_f();    //вызов функции счёта и набора массива
      }
    if (menu == 1) 
      {
        lcd_menu();   //вывод на дисплей меню
        poisk_f();  //вызов функции счёта и набора массива 
      }
    if (menu == 2) 
      {
        lcd_sys();    //вывод на дисплей системного меню
        poisk_f();  //вызов функции счёта и набора массива
      }
    if (menu == 3) 
      {
//          zamer_200s(); //вывод на дисплей замер 180сек
        menu = 0;
      }
    if (menu == 4) 
      {
        zamer_beta();
      }
  }
//-------------------------------------------------------------------------------------------------------------
/* Костыль. Разностный замер и длительный замер вызываются с частотой отрисовки дисплея, 
поэтому сложно поймать нажатия кнопок внутри функций zamer_200s() и zamer_beta().
Возможно в будущем придётся разделить эти функции на обработку данных (вызывать с частотой loop'а) 
и вывод на дисплей (вызывать с частотой обновления дисплея)
*/
if (menu == 4)
{
    if ((key_data == key_pressed_ok) && (gotovo == 0))  //нажатие OK
    {
      key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
      gotovo = 1;
      switch (bet_z) //проверяем, находимся ли в первом или втором замере
      {
        case 0: //если в первом замере
          bet_z0 = 0; //обнуляем текущие показания замера 1
          shet = 0; //обнуляем счёт
        case 1: //если во втором замере
          bet_z1 = 0; //обнуляем текущие показания замера 2
          shet = 0; //обнуляем счёт            
      }
    }
}
//--------------------------------------------------------------------------------------------------------------  
generator();//накачка по обратной связи с АЦП
if (shet_s != shet) 
  {
    signa ();//подача сигнала о частичке
  }
if (key_data == key_pressed_ok) { //нажатие ок
if (menu == 2) 
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    sys_menu++;
    if (sys_menu > 7) 
      {
        sys_menu = 0;
      }
  }
if (menu == 1) 
  {
    key_data = 0;    // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    n_menu++;
    if (n_menu > 7) 
      {
        n_menu = 0;
      }
  }
if (menu == 0) 
  {
    key_data = 0;   // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 1;
  }
  } 
if (menu == 0)  // в меню по удержанию кнопки "ок" входим только из режима "поиск"
  {
    if (key_data == key_holded_ok)  //удержание OK
      {
        menu = 2; 
        key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
      }
  }
if (menu == 1) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
      {
        if (n_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду   
            treviga_1 = treviga_1 + 10;
            if (treviga_1<10) {treviga_1 = 10;}
            if (treviga_1>100) {treviga_1 = 10;}
          }
        if (n_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            treviga_2++;
            treviga_2 = constrain (treviga_2, 0, 6);
          }
        if (n_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            podsvetka = !podsvetka;
          }
        if (n_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            graph_type++;
            if (graph_type>1) {graph_type = 0;}
          }
        if (n_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            scrin_GRAF++;
            if (scrin_GRAF > 10) 
              {
                scrin_GRAF = 1;
              }
          }
        if (n_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            ind_ON++; 
            ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4
          }
        if (n_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            menu = 0;
          }
        if (n_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 2) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
      {
        if (sys_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду 
            opornoe = opornoe + 0.01;
            if (opornoe < 0.98) 
              {
                opornoe = 1.20;
              }
            if (opornoe > 1.20) 
              {
                opornoe = 0.98;
              }
          }
        if (sys_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            puls++;
            if (puls < 1) 
              {
                puls = 30;
              }
            else if (puls > 30) 
              {
                puls = 1;
              }
          }
        if (sys_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            time_doza = 0;//сброс накопленной дозы
            doz_v = 0;//сброс накопленной дозы
            eeprom_wrD ();
            myGLCD.clrScr();
            myGLCD.setFont(SmallFontRus);
            myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16);
            myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24);
            myGLCD.update();
            _delay_ms(1000);
          }
        if (sys_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
          }
        if (sys_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            batproc++;
            if (batproc > 2) {batproc = 0;}
          }
        if (sys_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            beta_time++;
            if (beta_time > 99) {beta_time = 1;}
          }
        if (sys_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (sys_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 1) 
  {
    if (key_data == key_pressed_left)  //нажатие <<<
      {
        if (n_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            treviga_1 = treviga_1 - 10;
            if (treviga_1<10) {treviga_1 = 100;}
            if (treviga_1>100) {treviga_1 = 100;}
          }
        if (n_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            treviga_2--;
            treviga_2 = constrain (treviga_2, 0, 6);
          }
        if (n_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            podsvetka = !podsvetka;
          }
        if (n_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            graph_type--;
            if (graph_type > 1) {graph_type = 1;}
          }
        if (n_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            scrin_GRAF--;
            if (scrin_GRAF < 1) 
              {
                scrin_GRAF = 10;
              }
          }
        if (n_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            ind_ON--; 
            ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4
          }
        if (n_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (n_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 2) 
  {
    
    if (sys_menu == 7) 
          {
         sys_menu_1 = 40;
         sys_menu_2 = 6;
          }
          else
          {
         sys_menu_1 = 0;
         sys_menu_2 = 0;
          }
    if (key_data == key_pressed_left)  //нажатие <<<
      {
        if (sys_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            opornoe = opornoe - 0.01;
            if (opornoe < 0.98) 
              {
                opornoe = 1.20;
              }
            else if (opornoe > 1.20) 
              {
                opornoe = 0.98;
              }
          }
        if (sys_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            puls--;
            if (puls < 1) 
              {
                puls = 30;
              }
            else if (puls > 30) 
              {
                puls = 1;
              }
          }
        if (sys_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            time_doza = 0;//сброс накопленной дозы
            doz_v = 0;//сброс накопленной дозы
            eeprom_wrD ();
            myGLCD.clrScr();
            myGLCD.setFont(SmallFontRus);
            myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16);
            myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24);
            myGLCD.update();
            _delay_ms(1000);
          }
        if (sys_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
          }
        if (sys_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            batproc--;
            if (batproc > 2) {batproc = 2;}
          }
        if (sys_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            beta_time--;
            if (beta_time > 99) {beta_time = 99;}
            if (beta_time < 1) {beta_time = 99;}
          }
        if (sys_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (sys_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
//------------------------------------------------------------------------------------------------------------------  
if (alarm_sound && (millis() - lcd_milis >= 300)) //если поднят флаг аварийного сигнала (плюс попользуемся интервалом обновления экрана)
  {
    periodical_alarm_variable++; 
    if (periodical_alarm_variable >= 4) {periodical_alarm_variable = 1;} // держим переменную в пределах
    PORTB |= (1 << 0); //включаем вибру
    if (periodical_alarm_variable  > 1 )
      {
        PORTB &= ~(1 << 0); // выключаем вибру  
      }
    if  (periodical_alarm_variable  < 3) // периодичный звук тревоги
      {
        #ifdef buzzer_active //если задефайнен активный бузер
        PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
        #else //пассивный
        tone (6, 500); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
        #endif
      }
    else 
      {
        #ifdef buzzer_active   //если задефайнен активный бузер
        PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
        #else //пассивный бузер
        noTone (6); //выключаем писк на 6й ноге
        #endif 
      }
  if ((millis() - alarm_milis) > 3000) // проверяем, не истекло ли время подачи сигнала тревоги
    {
      PORTB &= ~(1 << 0); // выключаем вибру
      periodical_alarm_variable = 0; // обнуляем переменную
      #ifdef buzzer_active   //если задефайнен активный бузер
      PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
      #else //пассивный бузер
      noTone (6); //выключаем писк на 6й ноге
      #endif 
      alarm_sound = 0; // сбрасываем флаг сигнала тревоги
    }
  }
//------------------------------------------------------------------------------------------------------------------
if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
    res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------------------------------------------------
void lcd_poisk() 
{//вывод на дисплей режима поиск
if (fon_254 < treviga_1) //проверяем тревогу
  {
    tr = 0;
  }
if (fon_254 > treviga_1) //проверяем тревогу
  {
    check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
switch (treviga_2) //проверяем, какое значение выбрано
      {
        case 0: 
          tr = 0;tr2 = 0;
          break;  
        case 1: 
          if (shet > 10 || fon > 10) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 2: 
          if (shet > 300 || fon > 300) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 3: 
          if (shet > 500 || fon > 500) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 4: 
          if (shet > 1000 || fon > 1000) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 5: 
          if (shet > 5000 || fon > 5000) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 6: 
          if (shet > 10000 || fon > 10000) {tr2 = 1;} else {tr2 = 0;}
          break;
      }
  
myGLCD.clrScr();
myGLCD.drawBitmap(0, 0, fon_poisk, 84, 48);
myGLCD.setFont(SmallFontRus);
if (tr == 1)  //опасно
  {
    myGLCD.drawBitmap(2, 26, logo_tr, 24, 8);
  }
myGLCD.drawLine(1, 21, zam_poisk_counter * 0.1 + 1, 21);
myGLCD.drawLine(1, 22, zam_poisk_counter * 0.1 + 1.4, 22);
myGLCD.drawLine(1, 23, zam_poisk_counter * 0.1 + 0.6, 23);
if (fon_254 > 0) {
myGLCD.setFont(TinyFontRus);
if (fon_254 >= 0 && fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);};
if (fon_254 >= 10 && fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);};
if (fon_254 >= 100 && fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);};
if (fon_254 >= 1000 && fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);};
if (fon_254 >= 10000 && fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);};
if (fon_254 >= 100000 && fon_254 <= 999999) {myGLCD.printNumI(fon_254, 2, 8);};
}
 
if (overflow_alarm && !blink_data) {myGLCD.drawBitmap(27, 7, em_logo, 37, 17);overflow_alarm = 0;}

else if ((zam_poisk_counter >= geiger_counter_seconds) || blink_data)
  {
    myGLCD.setFont(MediumNumbers);
    if (fon >= 0 && fon <= 9) {myGLCD.printNumI(fon, 52, 7);};
    if (fon >= 10 && fon <= 99) {myGLCD.printNumI(fon, 40, 7);};
    if (fon >= 100 && fon <= 999) {myGLCD.printNumI(fon, 28, 7);};
    if (fon >= 1000 && fon <= 9999) {myGLCD.printNumI(fon / 1000, 52, 7);};
    if (fon >= 10000 && fon <= 99999) {myGLCD.printNumI(fon / 1000, 40, 7);};
    if (fon >= 100000 && fon <= 999999) {myGLCD.printNumI(fon / 1000, 28, 7);};
  }
if (fon < 1000) {myGLCD.drawBitmap(66, 8, mkr, 16, 15);} else {myGLCD.drawBitmap(66, 8, mr, 16, 15);}

time_d ();
myGLCD.setFont(TinyFontRus);
ind_doze_time();  //вывод времени накопления дозы на дисплей    
myGLCD.setFont(SmallFontRus);
if (doz_v < 1000) 
  {
    if (doz_v < 100)
      {
        myGLCD.printNumF(doz_v, 1, 41, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41);
      }
    else
      {
        myGLCD.printNumF(doz_v, 1, 34, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41);
      }    
  }
if (doz_v >= 1000) 
  {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 41); myGLCD.print(utf8rus("мР"), RIGHT, 41);
  }

battery();
if (graph_type == 0)
  {
  for (uint8_t i = 0; i < 84; i ++)  //печатаем график
    {
      uint8_t max_pixel = map(mass_p[i], 0, GRAPH_max, 0, 15);
      myGLCD.drawLine(i + 0, 39, i + 0, 39 - max_pixel);
    }
  }
else if (graph_type == 1)
  {
  for (int i = 0; i < 84; i ++)  //печатаем график
    {
    if (mass_p[i] > 0) 
      {
        if (mass_p[i] <= 15) 
          {
            myGLCD.drawLine(i + 0, 39, i + 0, 39 - mass_p[i]);
          }
        if (mass_p[i] > 15) 
          {
            myGLCD.drawLine(i + 0, 39, i + 0, 39 - 15);
          }
      }
    }
  }

//------------------------------------------ Синалка 2 сработала ------------------------------------------------
if (tr2 == 1)
  {
           overflow_alarm = 1;
           #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
            }
          #else //пассивный бузер
            {
              if (blink_data){tone (6,1000,1000);} else {tone (6,3000,1000);}
            }
          #endif 
  }
//------------------------------------------------------------------------------------------------------
myGLCD.update();
}


//-------------------------------------------------------------------------------------------------------
void lcd_menu()  //вывод на дисплей меню
{
myGLCD.clrScr();
myGLCD.setFont(TinyFontRus);
myGLCD.print(utf8rus("ПОРОГ 1"), 5, 0); myGLCD.printNumI(treviga_1, 52, 0); myGLCD.print("\xBC\xBD\xBE\xBF", RIGHT, 0);
myGLCD.print(utf8rus("СИГНАЛКА"), 5, 6); //пункт меню выбора индикации частиц
switch (treviga_2)
  {
  case 0:
    myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 6); //сигналка выключена. Сигнализация Порог 1 тоже отключется.
    break;  
  case 1:
    myGLCD.print(utf8rus("test 10 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 100 мкр/ч
    break;  
  case 2:
    myGLCD.print(utf8rus("300 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 300 мкр/ч
    break;  
  case 3:
    myGLCD.print(utf8rus("500 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 500 мкр/ч
    break; 
  case 4:
    myGLCD.print(utf8rus("1 \xBC\xBE\xBF"), RIGHT, 6); // 1000 мкр/ч
    break; 
  case 5:
    myGLCD.print(utf8rus("5 \xBC\xBE\xBF"), RIGHT, 6); // 5000 мкр/ч
    break; 
  case 6:
    myGLCD.print(utf8rus("10 \xBC\xBE\xBF"), RIGHT, 6); // 10000 мкр/ч
    break; 
    default:
    myGLCD.print("err", RIGHT, 6); //  если значение не равно 1,2,3,4,5,6 или 0 - выводим ошибку 
  }
myGLCD.print(utf8rus("ПОДСВЕТКА"), 5, 12); 
if (podsvetka)  { myGLCD.print(utf8rus("ВКЛ."), RIGHT, 12); }
else  { myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 12);  }
myGLCD.print(utf8rus("ТИП ГРАФИКА"), 5, 18); if (graph_type) {myGLCD.print(utf8rus("НОВЫЙ"), RIGHT, 18);} else { myGLCD.print(utf8rus("СТАРЫЙ"), RIGHT, 18);} //
myGLCD.print(utf8rus("ОБН. ГРАФИКА"), 5, 24); myGLCD.printNumI(scrin_GRAF, 60, 24); myGLCD.print(utf8rus("СЕК."), RIGHT, 24);//
myGLCD.print(utf8rus("ИНДИКАЦИЯ"), 5, 30); //пункт меню выбора индикации частиц
switch (ind_ON)
  {
  case 0:
    myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 30); //индикация выключена
    break;  
  case 1:
    myGLCD.print(utf8rus("ЗВУК"), RIGHT, 30); //индикация звуком
    break;  
  case 2:
    myGLCD.print(utf8rus("СВЕТ"), RIGHT, 30); //индикация светом
    break;  
  case 3:
    myGLCD.print(utf8rus("ЗВУК+СВЕТ"), RIGHT, 30); //индикация звуком и светом
    break; 
  case 4:
    myGLCD.print(utf8rus("ВИБРО"), RIGHT, 30); //индикация вибрацией
    break; 
    default:
    myGLCD.print("err", RIGHT, 30); //  если значение не равно 1,2,3 или 0 - выводим ошибку 
  }
myGLCD.print(utf8rus("ВЫХОД"), 5, 36);
myGLCD.print(utf8rus("СОХРАНИТЬ"), 5, 42);
myGLCD.print(">", 0, n_menu * 6);
myGLCD.update();
}
//----------------------------------------------------------------------------------------------------------------------
void lcd_sys()  //вывод на дисплей меню
{
VCC_read();
speed_nakachka ();//скорость накачки имлульсы/сек
myGLCD.clrScr();
myGLCD.setFont(TinyFontRus);
myGLCD.print(utf8rus("ОПОРН."), 5, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 53, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
myGLCD.print(utf8rus("НАКАЧКА"), 5, 6); myGLCD.printNumI(puls, 55, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
myGLCD.print(utf8rus("СБРОС ДОЗЫ"), 5, 12); 
myGLCD.print(utf8rus("----"), 5, 18);
if (batproc == 0)  { myGLCD.print(utf8rus("БАТ. "), 5, 24);myGLCD.print(utf8rus("БЕЗ ИНДИКАЦИИ"), RIGHT, 24); }  
if (batproc == 1)  { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("ПРОЦЕНТАМИ"), RIGHT, 24); }
if (batproc == 2)  { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("НАПРЯЖЕНИЕМ"), RIGHT, 24);  }
myGLCD.print(utf8rus("БЕТА"), 5, 30); myGLCD.printNumI(beta_time, 50, 30); myGLCD.print(utf8rus("МИНУТ"), RIGHT, 30);
myGLCD.print(utf8rus("ВЫХОД"), 5, 36);
myGLCD.print(utf8rus("СОХРАНИТЬ"), RIGHT, 36);
myGLCD.print(">",sys_menu_1 + 0, sys_menu * 6 - sys_menu_2);
myGLCD.print(utf8rus("СКОРОСТЬ"), 5, 43); myGLCD.printNumI(speed_nak, 40, 43); myGLCD.print(utf8rus("ИМП/СЕК"), RIGHT, 43);
myGLCD.update();
}
//---------------------------------------------------------------------------------------------------------------------
void zamer_beta() 
{// замер бета или продуктов
if (gotovo == 0) 
  {
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
      {
        res_first_alarm(); //сбрасываем сигнал тревоги
      }
    myGLCD.clrScr();
    myGLCD.setFont(TinyFontRus);
    if (bet_z == 0)
      {
        myGLCD.drawBitmap(0, 0, beta_prev_1, 84, 48);
      }
    else if (bet_z == 1)
      {
        myGLCD.drawBitmap(0, 0, beta_prev_2, 84, 48); 
      }
myGLCD.setFont(SmallFontRus);
myGLCD.print(utf8rus("НАЖМИТЕ OK"), CENTER, 36);
myGLCD.update();
  }  
if (gotovo == 1) 
  {
    if (timer_seconds != beta_seconds) 
      {
        beta_seconds = timer_seconds;
        sek++;
        toch = !toch;
        if (sek >= 60) 
          {
            sek = 0;
            minute++;
          }
      } 
    byte otsup = 0;
    if (minute > 9) 
      {
          otsup = 5;
      }
    byte otsupp = 0;
    if (beta_time > 9) 
      {
        if (beta_time > 99) 
        {
          otsupp = 10;
        }
      else 
        {
          otsupp = 5;
        } 
      }
    myGLCD.clrScr();
    myGLCD.drawBitmap(0, 0, beta_fon, 84, 48);
    battery();
    if  (bet_z < 2) //таймер выводим только пока идёт первый или второй замер
    {
      myGLCD.setFont(TinyFontRus);
      myGLCD.printNumI(minute, LEFT, 0);
      if (toch == 0) 
        {
          myGLCD.print(":", 5 + otsup, 0);
        }
      else 
        {
          myGLCD.print(" ", 5 + otsup, 0);
        } 
      if (sek < 10){myGLCD.printNumI(0, 10 + otsup, 0);myGLCD.printNumI(sek, 10 + otsup + 4, 0);} else {myGLCD.printNumI(sek, 10 + otsup, 0);} myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ИЗ"), 21 + otsup, 0); myGLCD.printNumI(beta_time, 32 + otsup, 0); myGLCD.print("\xBC", 37 + otsup + otsupp, 0);
    }
    else
    {
      myGLCD.setFont(TinyFontRus);myGLCD.print(utf8rus("РЕЗУЛЬТАТ..."), 0, 0);
    }
    myGLCD.setFont(SmallFontRus);
    myGLCD.printNumI(bet_z0, 2, 17); myGLCD.printNumI(bet_z1, 44, 17);
    if (bet_z < 2) 
    {
      myGLCD.print(utf8rus("Идёт замер"), 5, 33); myGLCD.printNumI(bet_z, 72, 33);
    }
    if (bet_z == 2) 
    {
      myGLCD.printNumI(bet_r, CENTER, 29); myGLCD.print(utf8rus("мкР/ч"), CENTER, 38);
    }
    myGLCD.update();
    if (bet_z == 0)  //первый замер
    {
      bet_z0 = bet_z0 + shet;
      shet = 0;
      if (minute >= beta_time) 
        {
          bet_z = 1;
          sek = 0;
          minute = 0;
          gotovo = 0; 
          tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге
        }
    }
    if (bet_z == 1)  //второй замер
  {
    bet_z1 = bet_z1 + shet;
    shet = 0;
    if (minute >= beta_time) 
      {
        bet_z = 2;
        sek = 0;
        minute = 0;
        tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге    
      }
    }
    if (bet_z == 2)  //результат
    {
      bet_r = bet_z1 - bet_z0;
//      bet_r = bet_r / (1.5 * beta_time);
      bet_r = bet_r / ((60.0/(float)geiger_counter_seconds) * (float)beta_time);
      if (bet_r < 0) {bet_r = 0;} // если результат отрицательный - выводим 0. Можно оставить вывод отрицательного результата, закомментировав данную строчку.
    }
  }
if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    clear_poisk_variables();
  }
}
//-------------------------------------------------------------------------------------------------------------
void poisk_f() //режим поиска
{
int16_t shet_gr = 0;
if (poisk == 1) 
  {
    if (timer_seconds != count_and_dose_seconds) 
      {
        count_and_dose_seconds = timer_seconds;
          for (int i = 0; i < 254; i++)  //сдвигаем
          {
            mass_poisk[i] = mass_poisk[i + 1];
          }
        mass_poisk[254] = shet;
        if ((zam_poisk_counter < 254) && (zam_poisk_counter < geiger_counter_seconds))  //первый набор массива
          {
            fon_vr_poisk = fon_vr_poisk + shet;             
            zam_poisk_counter++;
            fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); 
//            fon_254 = fon;
            fon_254 = 0;
          }
        else if ((zam_poisk_counter < 254) && (zam_poisk_counter == geiger_counter_seconds))  //
          {   
            zam_poisk_counter++;
            fon_vr_poisk = fon_vr_poisk + shet; 
            fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter)));
            fon_254 = fon;    
            fon_vr254 = fon_vr_poisk;
          }
        else if ((zam_poisk_counter < 254) && (zam_poisk_counter > geiger_counter_seconds))  //
          {
            fon_vr_poisk = 0;
            fon_vr254 = 0;
            for (int i = zam_poisk_counter; i > 0; i--) 
              {
                fon_vr254 = fon_vr254 + mass_poisk[254-i];
              }
            for (int j = 254 - geiger_counter_seconds; j < 255; j++) 
              { 
                fon_vr_poisk = fon_vr_poisk + mass_poisk[j];
              }
            fon = fon_vr_poisk;
//            fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/(float(zam_poisk_counter)));
            fon_254 = (float)fon_vr254*((float)geiger_counter_seconds/(float)zam_poisk_counter); 
            fon_vr254 = 0;
            zam_poisk_counter++;
          } 
        else if (zam_poisk_counter >= 254)  //набор массива
          {
            fon_vr_poisk = 0;
            fon_vr254 = 0;
            byte geiger_counter_seconds_reverse = 254 - geiger_counter_seconds;
            for (int i = 254; i > 0; i--) 
              {
                fon_vr254 = fon_vr254 + mass_poisk[i];
                if (i > geiger_counter_seconds_reverse)
                  {
                    fon_vr_poisk = fon_vr_poisk + mass_poisk[i];
                  }
              }
            fon = fon_vr_poisk;
            fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/254.0);
          }
        shet = 0;
        doz_v = doz_v + fon / 100.0 / 36.0;
        time_doza = time_doza + 1;
        if (doz_v - doza_vr >= save_DOZ)  //а не пора ли сохранить дозу ?
          {
            eeprom_wrD ();
            doza_vr = doz_v;
          }
//Serial.print(" zam_poisk_counter=");
//Serial.println(zam_poisk_counter);            
      }
    if (millis() - gr_milis >= scrin_GRAF * 1000) //счет для графика
      {
      gr_milis = millis();
      if (graph_type == 0)
        {
        val_ok = 0;//сброс удержания системного меню  
        for (uint8_t s = 254; s >= (255 - scrin_GRAF); s--) 
          {
            shet_gr = shet_gr + mass_poisk[s];
          }
        shet_gr = shet_gr / scrin_GRAF;
        for (int i = 0; i < 83; i++) // сдвигаем массив графика
          {
            mass_p[i] = mass_p[i + 1];
          }
        mass_p[82] = byte(shet_gr);
        if (GRAPH_count > 82) 
          {
            GRAPH_max = 5; 
            GRAPH_count = 0;
          }   
        for (int i = 0; i < 82; i++) 
          {
            if (mass_p[i] > GRAPH_max)
              {
                GRAPH_max = mass_p[i];
                GRAPH_count = 0;
              }
          }
        GRAPH_count++;     
        }
      if (graph_type == 1)
        {
          val_ok = 0;//сброс удержания системного меню
          shet_gr = shet - shet_n;
          if (shet_gr < 0) 
            {
              shet_gr = 1;
            }
          shet_n = shet;
          for (int i = 0; i < 83; i++) 
            {
              mass_p[i] = mass_p[i + 1];
            }
          mass_p[82] = byte(shet_gr);
            
        
        }       
      }
  }
}
//----------------------------------------------------------------------------------------------------------------

void clear_poisk_variables ()
{
shet = 0;
fon = 0;
fon_254 = 0;
zam_poisk_counter = 0;
GRAPH_max = 5;
GRAPH_count = 0;
fon_vr254 = 0;
fon_vr_poisk = 0;
for (uint8_t i = 0; i < 84; i++) { mass_p[i] = 0; } // чистим массив графика
for (uint8_t i = 0; i < 254; i++) { mass_poisk[i] = 0; } // чистим массив поиска  
}

void signa ()  //индикация каждой частички звуком светом
{
shet_s = shet;  
if (!alarm_sound && tr2 == 0) //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
    {
    if (!shet_s) {return;} //если залетели в функцию signa() при обнулении переменной shet_s - просто возвращаемся в точку вызова. Детальнее здесь: arduino.ru/forum/proekty/delaem-dozimetr?page=16#comment-318736
    switch (ind_ON) //проверяем, какой тип индикации выбран
      {
        case 0: //индикация выключена
          break;  
        case 1: //индикация звуком
          #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
            }
          #else //пассивный бузер
            {
              tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге
            }
          #endif 
          break;  
        case 2: //индикация светом
          PORTB |= (1 << 5); //включаем светодиод
          delay(del_BUZZ); //длительность одиночного сигнала
          PORTB &= ~(1 << 5); //выключаем светодиод
          break;
  
        case 3: //индикация звуком и светом
          #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTB |= (1 << 5); //включаем светодиод
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
              PORTB &= ~(1 << 5); //выключаем светодиод
            }
          #else //пассивный бузер
            {
              PORTB |= (1 << 5); //включаем светодиод
              tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге
              delay(del_BUZZ);//длительность одиночного сигнала
              PORTB &= ~(1 << 5);//выключаем светодиод
            }
          #endif 
          break; 
        case 4: // индикация вибрацией
          PORTB |= (1 << 0); //включаем вибру
          delay(del_BUZZ); //длительность одиночного сигнала
          PORTB &= ~(1 << 0); // выключаем вибру      
      } 
    }
else // если активен сигнал тревоги, то только мигаем светодиодом (независимо от того, включён или нет светодиод в меню)
  {
      PORTB |= (1 << 5); //включаем светодиод
    delay(del_BUZZ);
    PORTB &= ~(1 << 5);//выключаем светодиод
  }
}
//-------------------------------------------------------------------------------------------------
void Schet()  //прерывание от счетчика на пин 2
{
shet++;
if (shet>250) {overflow_alarm = 1;} // детект приближения к переполнению переменной
}
//-------------------------------------------------------------------------------------------------
void generator() //накачка по обратной связи с АЦП
{
hv_adc  = Read_HV();
if (hv_adc < ADC_value)  //Значение АЦП при котором на выходе 400В
  {
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) 
      {
        asm("nop");
        c--;
      }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//--------------------------------------------------------------------------------------------------
byte Read_HV () 
{
ADCSRA = 0b11100111;
#ifdef UNO_DIP //если при компилляции выбрана плата ArduinoUNO
ADMUX = 0b11100101;//выбор внутреннего опорного 1,1В и А5 
#else // если используется промини, нано или голый камень в tqfp
ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
#endif  
for (int i = 0; i < 10; i++) 
  {
    while ((ADCSRA & 0x10) == 0);
    ADCSRA |= 0x10;
  }
result = 0;
for (int i = 0; i < 10; i++) 
  {
    while ((ADCSRA & 0x10) == 0);
    ADCSRA |= 0x10;
    result += ADCH;
  }
result /= 10;
return result;
}
//----------------------------------------------------------------------------------------------------
void battery()  //батарейка
{
if (bat_mill - millis() > 2000) 
  {
    bat_mill = millis();
    VCC_read();
  }
myGLCD.setFont(TinyFontRus);
byte batprocent = 99;
batprocent = ((VCC - batnapruga) * 100 / (batmax - batnapruga));
byte batline = 9; //Задаем длину линии батареи
batline = 0.1 * ((VCC - batnapruga) * 100 / (batmax - batnapruga)); //Зависимость длинны в пикселях от процента заряда

if (batproc == 1 && VCC < batusb && batprocent < 100) {myGLCD.printNumF(batprocent, 0, 58, 0);myGLCD.print("%", 66, 0);} // процент заряда
if (batproc == 2) {myGLCD.printNumF(VCC, 2, 54, 0);} // процент заряда
      if (batprocent > 5 && (VCC - batnapruga) > 0.01) //Проверяем процентный заряд акб 0.05 - 5%
        {
          if (VCC > batusb)
          {
  myGLCD.drawBitmap(71, 0, logo_bat_usb, 13, 5);
          }
            else
          {
  myGLCD.drawBitmap(71, 0, logo_bat, 13, 5);
  if (batprocent >= 100) {batline = 9;};
  myGLCD.drawBitmap(82 - batline, 1, logo_bat_line, batline + 1, 3);
          }
        }
      else //Если заряд меньше 5% мигаем пустой батарейкой
        {
          toch = !toch;
          if (toch == 0) 
          {
            myGLCD.drawBitmap(71, 0, logo_bat, 13, 5);
          }
          else 
          {
            myGLCD.drawBitmap(71, 0, logo_bat, 0, 0);
          } 
        }
}
//----------------------------------------------------------------------------------------------------
void VCC_read()  // Чтение напряжения батареи
{
ADCSRA = 0b11100111;
ADMUX = 0b01101110;//Выбор внешнего опорного+BG
_delay_ms(5);
while ((ADCSRA & 0x10) == 0);
ADCSRA |= 0x10;
byte resu = ADCH;
//ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
VCC = (opornoe * 255.0) / resu;
}
//----------------------------------------------------------------------------------------------------
void lcd_init() 
{
myGLCD.InitLCD();
myGLCD.setContrast(contrast);
myGLCD.clrScr();
myGLCD.drawBitmap(0, 0, logo_rag, 84, 48);
//myGLCD.setFont(SmallFontRus);
//  myGLCD.print(utf8rus("Ардуино+"), CENTER, 32);
//  myGLCD.print(utf8rus("Дозиметр v1.07"), CENTER, 40);
myGLCD.update();
_delay_ms(1000);
}
//----------------------------------------------------------------------------------------------------
void eeprom_wrS ()  //запись настроек в память
{
  EEPROM.write(0, 222);
  EEPROM.write(1, treviga_1);
  EEPROM.write(2, podsvetka);
  EEPROM.write(3, graph_type);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, ind_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(100, batproc);
  EEPROM.write(17, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFontRus);
  myGLCD.print(utf8rus("Сохранено"), CENTER, 20);
  myGLCD.update();
  _delay_ms(1000);
}
//-----------------------------------------------------------------------------------------------------
void eeprom_wrD ()  //запись настроек в память время накопления дозы
{
  EEPROM.put(9, time_doza);
  EEPROM.put(13, doz_v);   
}
//-----------------------------------------------------------------------------------------------------
void eeprom_readD ()  //чтение настроек из памяти время накопления дозы
{
  EEPROM.get(9, time_doza);
  EEPROM.get(13, doz_v);   
}
//-----------------------------------------------------------------------------------------------------
void eeprom_readS ()  //чтение настроек из памяти
{
  if (EEPROM.read(0) == 222) 
  {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    graph_type = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    ind_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    batproc = EEPROM.read(100);
    beta_time = EEPROM.read(17);
  }
_delay_ms(11);
}
//------------------------------------------------------------------------------------------------------
void nakachka() //первая накачка
{
byte n = 0;
while (n < 30) 
  {
    PORTD |= (1 << 5);//дергаем пин
    int c = puls;
    while (c > 0) 
      {
        asm("nop");
        c--;
      }
    PORTD &= ~(1 << 5);//дергаем пин
    n++;
    _delay_us(100);
  }
}
//------------------------------------------------------------------------------------------------------
void speed_nakachka ()  //скорость накачки имлульсы/сек
{
if (millis() - spNAK_milis >= 1000) 
  {
    spNAK_milis = millis();
    speed_nak = speed_nakT;
    speed_nakT = 0;
  }
}
//------------------------------------------------------------------------------------------------------
void time_d() 
{
  MONTH = time_doza / 2592000;
  DAY = (time_doza / 86400) % 30 ;
  HOUR = (time_doza / 3600) % 24 ;
  MIN = (time_doza / 60) % 60;
}
//------------------------------------------------------------------------------------------------------
void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
  if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
    {
      alarm_sound = 1; // поднимаем флаг аварийного сигнала
      alarm_milis = millis(); // запоминаем время начала тревоги
    }
}
//------------------------------------------------------------------------------------------------------
void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
{
   alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   PORTB &= ~(1 << 0); // выключаем вибру
   periodical_alarm_variable = 0; // обнуляем переменную
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
}
//------------------------------------------------------------------------------------------------------
void ind_doze_time() //вывод времени накопления дозы на дисплей
{
  myGLCD.setFont(TinyFontRus);
  if (MONTH) // если есть месяцы
    {
      myGLCD.printNumI(MONTH, 0, 43);
      if(MONTH>99)
        {
          myGLCD.print("M", 13, 43);
        }
      else if (MONTH>9)
        {
          myGLCD.print("M", 9, 43);
        }
      else
        {
          myGLCD.print("M", 5, 43);
        }
    myGLCD.printNumI(DAY, 18, 43);
    if (DAY > 9) 
      {
        myGLCD.print("\xBB", 26, 43);
      }
    else
      {
        myGLCD.print("\xBB", 23, 43);
      } 
    }
  else if (DAY) // если нет месяцев, но есть дни
    {
      myGLCD.printNumI(DAY, 0, 43);
      if (DAY > 9) 
        {
          myGLCD.print("\xBB", 9, 43);
        }
      else
        {
          myGLCD.print("\xBB", 5, 43);
        }
      myGLCD.printNumI(HOUR, 18, 43);
      if (HOUR > 9) 
        {
          myGLCD.print("\xBA", 26, 43);
        }
      else 
        {
          myGLCD.print("\xBA", 23, 43);
        }
    }
  else // если нет дней
    {
      myGLCD.printNumI(HOUR, 0, 43);
      if (HOUR > 9) 
        {
          myGLCD.print("\xBA", 9, 43);
        }
      else
        {
          myGLCD.print("\xBA", 5, 43);
        }
      myGLCD.printNumI(MIN, 18, 43);
      if (MIN > 9) 
        {
          myGLCD.print("\xBC", 26, 43);
        }
      else
        {
          myGLCD.print("\xBC", 23, 43);
        }
    }   

}
//--------------------------------------------------------------------------------------------------------
byte get_key() // Функция определения нажатия и удержания кнопок
{
// версия 1 - для кратковременного нажатия значение возвращается при отпускании кнопки, для длительного - пока кнопка остаётся нажатой, с заданным интервалом
uint8_t trigger_push_hold_counter = 10; // задержка триггера кратковременного/длительного нажатия (проходов функции, умноженных на задержку "milliseconds_between_increment")  
uint8_t milliseconds_between_increment = 50; // интервал в миллисекундах между инкрементом счётчика нажатой кнопки 
static uint8_t val_kp, val_kl, val_ok;
static uint32_t key_delay_millis;
static uint32_t key_delay_after_hold_millis;
if ((millis() - key_delay_millis) > milliseconds_between_increment) //обрабатываем нажатия инкрементом переменной только если после предыдущей обработки прошло не менее "milliseconds_between_increment" миллисекунд
  {
    if (!(PIND & (1 << PIND4)))  //нажатие >>>
    {
    val_kp++;  // инкрементируем счётчик
    if (val_kp > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши 
      {
       val_kp = 0; // сбрасываем счётчик 
       key_delay_after_hold_millis = millis(); // запоминаем время
       return key_holded_right; // возвращаем значение
      }
    }
    if (!(PIND & (1 << PIND7)))  //нажатие <<<
    {
    val_kl++;  // инкрементируем счётчик
    if (val_kl > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши
      {
        val_kl = 0; // сбрасываем счётчик
        key_delay_after_hold_millis = millis(); // запоминаем время 
        return key_holded_left; // возвращаем значение
      }   
    }
    if (!(PIND & (1 << PIND3)))  //нажатие OK
    {
    val_ok++; // инкрементируем счётчик
    if (val_ok > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши
      {
        val_ok = 0; // сбрасываем счётчик
        key_delay_after_hold_millis = millis(); // запоминаем время 
        return key_holded_ok; // возвращаем значение
      }       
    }
    key_delay_millis = millis(); // запоминаем время 
  }
if (val_ok > 0) //если клавиша OK перед этим была нажата 
  {
     if ((PIND & (1 << PIND3)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_ok = 0;  // сбрасываем счётчик
        return key_pressed_ok; // возвращаем значение
      }
  }
if (val_kp > 0) //если клавиша >>> перед этим была нажата 
  {
    if ((PIND & (1 << PIND4)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_kp = 0;  // сбрасываем счётчик 
        return key_pressed_right; // возвращаем значение
      }
  }
if (val_kl > 0) //если клавиша <<< перед этим была нажата 
  {
    if ((PIND & (1 << PIND7)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_kl = 0;  // сбрасываем счётчик  
        return key_pressed_left; // возвращаем значение
      }
  }
if (PIND & (1 << PIND4)) {val_kp = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
if (PIND & (1 << PIND7)) {val_kl = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
if (PIND & (1 << PIND3)) {val_ok = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
return 0; // если ни одна из кнопок не была нажата - возвращаем 0
}
//------------------------------------------------------------------------------------------------------------------------------
char *utf8rus(char *source) // функция преобразования utf8 для вывода кириллицы (by arduinec)
{
  int i,j,k;
  unsigned char n;
  char m[2] = { '0', '\0' };

  strcpy(target, ""); k = strlen(source); i = j = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }

    m[0] = n; strcat(target, m);
    j++; if (j >= maxString) break;
  }
  return target;
}

ISR (TIMER1_OVF_vect) // прерывание по таймеру, генерируемое каждую секунду
{ 
timer_seconds++ ; //инкремент переменной каждую секунду
if (timer_seconds > 59){timer_seconds = 0;}
}

// ________________ конец скетча, дальше можно не копировать _____________________



Чуть подправил сигналку 2. Выкинул одну глобальную переменную.

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

alexadresat пишет:

Колокольчик за графиком как-то не смотрится.

А колокольчик больше некуда деть. Хотел наверх, но там всего 5 пикселей свободно. 

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Дык надо было просто надпись "алярма" туда выводить, а колокольчик выкинуть.

alexadresat
alexadresat аватар
Offline
Зарегистрирован: 22.02.2017

Это косяк или что?

10 мкР/ч  -> и сразу 300 мкР/ч -> потом 500 мкР/ч -> 1 мР/ч -> 5 мР/ч -> 10 мР/ч  

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

В место 10 должно быть 100. 

 

Там написано Test 10.

Если нужно как конечная версия, то вот.

100 мкр > 250 мкр > 500 мкр > 1 мР > 5мР > 10мР

Вместо колокольчика, надпись - ВНИМАНИЕ!

 

/* ArDOs   v1.08.2
***Дозиметр на Ардуино
***IDE Arduino 1.8.8
  ветка форума arduino.ru/forum/proekty/delaem-dozimetr
  сайт srukami.inf.ua/ardos.html
*/
#include <util/delay.h> //уже есть
#include <EEPROM.h>//уже есть
#include <LCD5110_Graph.h>//нужно установить

//настройки /////////////начало
LCD5110 myGLCD(A1, A0, 12, 10, 11); //подключение дисплея
#define contrast 70 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
//#define UNO_DIP // если используется ArduinoUNO или плата на голой атмеге328 в корпусе DIP - раскомментируйте данную строчку. Это переключит чтение напряжения с делителя с ноги A6 на ногу A5.
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 0; //вторая ступень тревоги
byte del_BUZZ = 2;//длительность одиночного сигнала
#define  ADC_value 225  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255). Для значений делителя с сайта srukami 163. alexadresat 185. (Тестовая версия tekagi  67)
#define k_delitel 420 //коефициент делителя напряжения, зависит от вашего делителя. Для значений делителя с сайта srukami k_delitel 576. alexadresat 500 (Тестовая версия tekagi  1395)
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool podsvetka = 0; //подсветка
uint8_t graph_type = 1; //тип графика
bool alarm_sound = 0; //флаг индикации превышения порога звуком
float opornoe = 1.10; //делить на opornoe/10
#define save_DOZ 1 //как часто сохранять накопленную дозу например каждые 20мкР
#define geiger_counter_seconds 40 // число секунд для замера, соответствующее характеристикам счётчика. Для СБМ-20 равно 40.
byte beta_time = 5; //время замера бета излучения
uint8_t batproc = 0; // 1- отображать проценты. 0 - не отображать
float batusb = 4.30; // настройка напряжения, выше которого будет отображаться значек USB
float batmax = 4.15; //Настройка максимального значения напряжения акб для отображения. Обычно 4.20 вольта
float batnapruga = 3.20; //Настройка минимального значения напряжения акб для отображения. Зависит от работоспособности вашей схемы. Обычно 3.20 вольта by OfficialGalkin 
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFontRus[], MediumNumbers[], TinyFontRus[];
volatile uint8_t timer_seconds = 0; // для отсчёта секундных интервалов в прерывании
uint8_t beta_seconds = 0;
uint8_t count_and_dose_seconds = 0;
#define maxString 21 // для работы функции преобразования кодировки utf8us
char target[maxString + 1] = ""; // для работы функции преобразования кодировки utf8us
extern uint8_t logo_bat[], logo_bat_line[], logo_bat_usb[], logo_rag[], logo_tr[], beta_prev_1[], beta_prev_2[], beta_fon[], em_logo[], fon_poisk[], mkr[], mr[];
volatile int shet = 0;
volatile bool overflow_alarm = 0;
int8_t ind_ON = 1;  //0 - индикация выключена, 1 - включён бузер, 2 - светодиод, 3 - и бузер, и светодиод
uint8_t first_alarm_type = 1;  //1-3, 1 - только бузер, 2 - только вибро, 3 - и бузер, и вибро
byte periodical_alarm_variable = 0; // переменная для периодически повторяющейся тревожной сигнализации
uint8_t tr2 = 0; // сигналка 2 сработала
unsigned long gr_milis = 0, lcd_milis = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
uint16_t hv_adc, hv_400, shet_n = 0, shet_s = 0;
uint16_t fon = 0, fon_254 = 0;
int speed_nakT = 0, speed_nak = 0, result;
byte MIN, DAY, HOUR, MONTH; //для учёта времени дозы
uint16_t doza_vr = 0, fon_vr254 = 0, fon_vr_poisk = 0;
byte mass_p[84]; // массив для графика
byte m = 0, n_menu = 0, sys_menu = 0, sys_menu_1 = 0, sys_menu_2 = 0;
byte  mass_poisk[255]; // основной рабочий массив
byte val_kl = 0, val_ok = 0, menu = 0, zam_poisk_counter = 0;
byte sek = 0, minute = 0, bet_z = 0, gotovo = 0;
int  bet_z0 = 0, bet_z1 = 0, bet_r = 0;
float VCC = 0.0, doz_v = 0.0;
bool tr = 0, poisk = 1, fonarik = 0, toch, blink_data=1;
uint8_t GRAPH_max = 5; // максимальное значение за период отображения графика
uint8_t GRAPH_count = 0; // счётчик для поиска максимального значения для графика
#define key_pressed_left 1
#define key_pressed_right 2
#define key_pressed_ok 3
#define key_holded_left 4
#define key_holded_right 5
#define key_holded_ok 6
#define keys_not_pressed 0
uint8_t key_data = 0;
//-------------------------------------------------------------
void setup() {
  //-----------------------------------------------------------
  // настраиваем таймер на секундный интервал
  TCCR1A=(1<<WGM11); //режим14 FAST PWM 
  TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
if (F_CPU == 16000000UL) 
 {
  ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
 }
else if (F_CPU == 8000000UL) 
 {
  ICR1=31249;  // (8000000MHz /div256) -1 = 1 раз в секунду
 } 
  TIMSK1=(1<<TOIE1); //разрешить прерывание
  //-----------------------------------------------------------
// Serial.begin(115200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (1 << 0); PORTB &= ~(1 << 0); //пин вибры 8
  DDRC |= (0 << 4); PORTC &= ~(1 << 4); //пин пустой А4
  DDRC |= (0 << 5); PORTC &= ~(1 << 5); //пин пустой А5
  DDRB |= (1 << 1);//пин фонаря
  DDRC |= (1 << 3);//A3 дисплей GND
  DDRC |= (1 << 2);//A2 дисплей Light
  PORTC &= ~(1 << 3); //A3 дисплей GND
  PORTC  |= (1 << 2); //A2 дисплей Light
  eeprom_readS ();
  eeprom_readD ();
  lcd_init();
  attachInterrupt(0, Schet, FALLING);//прерываниям пин 2
  DDRB |= (1 << 5); //пины на выход
  DDRD |= (1 << 5);
  DDRD |= (1 << 6);
  DDRD |= (1 << 6);//пин бузера
  nakachka();
  clear_poisk_variables();
}
//-------------------------------------------------------------
void loop() 
{
key_data = get_key();  // вызываем функцию определения нажатия кнопок, присваивая возвращаемое ней значение переменной, которую далее будем использовать в коде
if (menu == 0) 
  {
    if (key_data == key_pressed_left)   //нажатие <<<
    {
      key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду 
      clear_poisk_variables();
    }
    if (key_data == key_holded_left) //удержание <<< фонарик  
  {
    fonarik = !fonarik; 
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
  }   
    if (key_data == key_holded_right) // удержание <<< подсветка
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
        podsvetka = !podsvetka;
    }   
    if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 4;
    shet = 0;
    bet_z0 = 0;
    bet_z1 = 0;
    bet_r = 0;
    bet_z = 0;
    gotovo = 0;
    sek = 0;
    minute = 0;
    }
 } 
if (menu == 3)
  {
    if (key_data == key_pressed_left)  //нажатие <<<
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    shet = 0; fon = 0; zam_poisk_counter = 0;
    for (int i = 0; i < 18; i++) { mass_poisk[i] = 0; }//чистим
  }
  } 
if (menu == 4) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    clear_poisk_variables();
    }
  }
if (fonarik == 0)  //фонарик
  {
    PORTB &= ~(1 << 1);//пин фонаря
  } 
else if (fonarik == 1) 
  {
    PORTB |= (1 << 1);//пин фонаря
  }
if (podsvetka == 1) 
  {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
else if (podsvetka == 0) 
  {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300)  //скорость отрисовки дисплея
  {
    lcd_milis = millis();
    blink_data = !blink_data;
    if (menu == 0) 
      {
        lcd_poisk();  //вывод на дисплей режима поиск
        poisk_f();    //вызов функции счёта и набора массива
      }
    if (menu == 1) 
      {
        lcd_menu();   //вывод на дисплей меню
        poisk_f();  //вызов функции счёта и набора массива 
      }
    if (menu == 2) 
      {
        lcd_sys();    //вывод на дисплей системного меню
        poisk_f();  //вызов функции счёта и набора массива
      }
    if (menu == 3) 
      {
//          zamer_200s(); //вывод на дисплей замер 180сек
        menu = 0;
      }
    if (menu == 4) 
      {
        zamer_beta();
      }
  }
//-------------------------------------------------------------------------------------------------------------
/* Костыль. Разностный замер и длительный замер вызываются с частотой отрисовки дисплея, 
поэтому сложно поймать нажатия кнопок внутри функций zamer_200s() и zamer_beta().
Возможно в будущем придётся разделить эти функции на обработку данных (вызывать с частотой loop'а) 
и вывод на дисплей (вызывать с частотой обновления дисплея)
*/
if (menu == 4)
{
    if ((key_data == key_pressed_ok) && (gotovo == 0))  //нажатие OK
    {
      key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
      gotovo = 1;
      switch (bet_z) //проверяем, находимся ли в первом или втором замере
      {
        case 0: //если в первом замере
          bet_z0 = 0; //обнуляем текущие показания замера 1
          shet = 0; //обнуляем счёт
        case 1: //если во втором замере
          bet_z1 = 0; //обнуляем текущие показания замера 2
          shet = 0; //обнуляем счёт            
      }
    }
}
//--------------------------------------------------------------------------------------------------------------  
generator();//накачка по обратной связи с АЦП
if (shet_s != shet) 
  {
    signa ();//подача сигнала о частичке
  }
if (key_data == key_pressed_ok) { //нажатие ок
if (menu == 2) 
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    sys_menu++;
    if (sys_menu > 7) 
      {
        sys_menu = 0;
      }
  }
if (menu == 1) 
  {
    key_data = 0;    // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    n_menu++;
    if (n_menu > 7) 
      {
        n_menu = 0;
      }
  }
if (menu == 0) 
  {
    key_data = 0;   // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 1;
  }
  } 
if (menu == 0)  // в меню по удержанию кнопки "ок" входим только из режима "поиск"
  {
    if (key_data == key_holded_ok)  //удержание OK
      {
        menu = 2; 
        key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
      }
  }
if (menu == 1) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
      {
        if (n_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду   
            treviga_1 = treviga_1 + 10;
            if (treviga_1<10) {treviga_1 = 10;}
            if (treviga_1>100) {treviga_1 = 10;}
          }
        if (n_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            treviga_2++;
            treviga_2 = constrain (treviga_2, 0, 6);
          }
        if (n_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            podsvetka = !podsvetka;
          }
        if (n_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            graph_type++;
            if (graph_type>1) {graph_type = 0;}
          }
        if (n_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            scrin_GRAF++;
            if (scrin_GRAF > 10) 
              {
                scrin_GRAF = 1;
              }
          }
        if (n_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            ind_ON++; 
            ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4
          }
        if (n_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            menu = 0;
          }
        if (n_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 2) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
      {
        if (sys_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду 
            opornoe = opornoe + 0.01;
            if (opornoe < 0.98) 
              {
                opornoe = 1.20;
              }
            if (opornoe > 1.20) 
              {
                opornoe = 0.98;
              }
          }
        if (sys_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            puls++;
            if (puls < 1) 
              {
                puls = 30;
              }
            else if (puls > 30) 
              {
                puls = 1;
              }
          }
        if (sys_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            time_doza = 0;//сброс накопленной дозы
            doz_v = 0;//сброс накопленной дозы
            eeprom_wrD ();
            myGLCD.clrScr();
            myGLCD.setFont(SmallFontRus);
            myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16);
            myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24);
            myGLCD.update();
            _delay_ms(1000);
          }
        if (sys_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
          }
        if (sys_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            batproc++;
            if (batproc > 2) {batproc = 0;}
          }
        if (sys_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            beta_time++;
            if (beta_time > 99) {beta_time = 1;}
          }
        if (sys_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (sys_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 1) 
  {
    if (key_data == key_pressed_left)  //нажатие <<<
      {
        if (n_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            treviga_1 = treviga_1 - 10;
            if (treviga_1<10) {treviga_1 = 100;}
            if (treviga_1>100) {treviga_1 = 100;}
          }
        if (n_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            treviga_2--;
            treviga_2 = constrain (treviga_2, 0, 6);
          }
        if (n_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            podsvetka = !podsvetka;
          }
        if (n_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            graph_type--;
            if (graph_type > 1) {graph_type = 1;}
          }
        if (n_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            scrin_GRAF--;
            if (scrin_GRAF < 1) 
              {
                scrin_GRAF = 10;
              }
          }
        if (n_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            ind_ON--; 
            ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4
          }
        if (n_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (n_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 2) 
  {
    
    if (sys_menu == 7) 
          {
         sys_menu_1 = 40;
         sys_menu_2 = 6;
          }
          else
          {
         sys_menu_1 = 0;
         sys_menu_2 = 0;
          }
    if (key_data == key_pressed_left)  //нажатие <<<
      {
        if (sys_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            opornoe = opornoe - 0.01;
            if (opornoe < 0.98) 
              {
                opornoe = 1.20;
              }
            else if (opornoe > 1.20) 
              {
                opornoe = 0.98;
              }
          }
        if (sys_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            puls--;
            if (puls < 1) 
              {
                puls = 30;
              }
            else if (puls > 30) 
              {
                puls = 1;
              }
          }
        if (sys_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            time_doza = 0;//сброс накопленной дозы
            doz_v = 0;//сброс накопленной дозы
            eeprom_wrD ();
            myGLCD.clrScr();
            myGLCD.setFont(SmallFontRus);
            myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16);
            myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24);
            myGLCD.update();
            _delay_ms(1000);
          }
        if (sys_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
          }
        if (sys_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            batproc--;
            if (batproc > 2) {batproc = 2;}
          }
        if (sys_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            beta_time--;
            if (beta_time > 99) {beta_time = 99;}
            if (beta_time < 1) {beta_time = 99;}
          }
        if (sys_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (sys_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
//------------------------------------------------------------------------------------------------------------------  
if (alarm_sound && (millis() - lcd_milis >= 300)) //если поднят флаг аварийного сигнала (плюс попользуемся интервалом обновления экрана)
  {
    periodical_alarm_variable++; 
    if (periodical_alarm_variable >= 4) {periodical_alarm_variable = 1;} // держим переменную в пределах
    PORTB |= (1 << 0); //включаем вибру
    if (periodical_alarm_variable  > 1 )
      {
        PORTB &= ~(1 << 0); // выключаем вибру  
      }
    if  (periodical_alarm_variable  < 3) // периодичный звук тревоги
      {
        #ifdef buzzer_active //если задефайнен активный бузер
        PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
        #else //пассивный
        tone (6, 500); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
        #endif
      }
    else 
      {
        #ifdef buzzer_active   //если задефайнен активный бузер
        PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
        #else //пассивный бузер
        noTone (6); //выключаем писк на 6й ноге
        #endif 
      }
  if ((millis() - alarm_milis) > 3000) // проверяем, не истекло ли время подачи сигнала тревоги
    {
      PORTB &= ~(1 << 0); // выключаем вибру
      periodical_alarm_variable = 0; // обнуляем переменную
      #ifdef buzzer_active   //если задефайнен активный бузер
      PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
      #else //пассивный бузер
      noTone (6); //выключаем писк на 6й ноге
      #endif 
      alarm_sound = 0; // сбрасываем флаг сигнала тревоги
    }
  }
//------------------------------------------------------------------------------------------------------------------
if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
    res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------------------------------------------------
void lcd_poisk() 
{//вывод на дисплей режима поиск
if (fon_254 < treviga_1) //проверяем тревогу
  {
    tr = 0;
  }
if (fon_254 > treviga_1) //проверяем тревогу
  {
    check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
switch (treviga_2) //проверяем, какое значение выбрано
      {
        case 0: 
          tr = 0;tr2 = 0;
          break;  
        case 1: 
          if (shet > 100 || fon > 100) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 2: 
          if (shet > 250 || fon > 250) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 3: 
          if (shet > 500 || fon > 500) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 4: 
          if (shet > 1000 || fon > 1000) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 5: 
          if (shet > 5000 || fon > 5000) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 6: 
          if (shet > 10000 || fon > 10000) {tr2 = 1;} else {tr2 = 0;}
          break;
      }
  
myGLCD.clrScr();
myGLCD.drawBitmap(0, 0, fon_poisk, 84, 48);
myGLCD.setFont(SmallFontRus);
myGLCD.drawLine(1, 21, zam_poisk_counter * 0.1 + 1, 21);
myGLCD.drawLine(1, 22, zam_poisk_counter * 0.1 + 1.4, 22);
myGLCD.drawLine(1, 23, zam_poisk_counter * 0.1 + 0.6, 23);
if (fon_254 > 0) {
myGLCD.setFont(TinyFontRus);
if (tr == 1) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);}
if (fon_254 >= 0 && fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);};
if (fon_254 >= 10 && fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);};
if (fon_254 >= 100 && fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);};
if (fon_254 >= 1000 && fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);};
if (fon_254 >= 10000 && fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);};
if (fon_254 >= 100000 && fon_254 <= 999999) {myGLCD.printNumI(fon_254, 2, 8);};
}
 
if (overflow_alarm && !blink_data) {myGLCD.drawBitmap(27, 7, em_logo, 37, 17);overflow_alarm = 0;}

else if ((zam_poisk_counter >= geiger_counter_seconds) || blink_data)
  {
    myGLCD.setFont(MediumNumbers);
    if (fon >= 0 && fon <= 9) {myGLCD.printNumI(fon, 52, 7);};
    if (fon >= 10 && fon <= 99) {myGLCD.printNumI(fon, 40, 7);};
    if (fon >= 100 && fon <= 999) {myGLCD.printNumI(fon, 28, 7);};
    if (fon >= 1000 && fon <= 9999) {myGLCD.printNumI(fon / 1000, 52, 7);};
    if (fon >= 10000 && fon <= 99999) {myGLCD.printNumI(fon / 1000, 40, 7);};
    if (fon >= 100000 && fon <= 999999) {myGLCD.printNumI(fon / 1000, 28, 7);};
  }
if (fon < 1000) {myGLCD.drawBitmap(66, 8, mkr, 16, 15);} else {myGLCD.drawBitmap(66, 8, mr, 16, 15);}

time_d ();
myGLCD.setFont(TinyFontRus);
ind_doze_time();  //вывод времени накопления дозы на дисплей    
myGLCD.setFont(SmallFontRus);
if (doz_v < 1000) 
  {
    if (doz_v < 100)
      {
        myGLCD.printNumF(doz_v, 1, 41, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41);
      }
    else
      {
        myGLCD.printNumF(doz_v, 1, 34, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41);
      }    
  }
if (doz_v >= 1000) 
  {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 41); myGLCD.print(utf8rus("мР"), RIGHT, 41);
  }

battery();
if (graph_type == 0)
  {
  for (uint8_t i = 0; i < 84; i ++)  //печатаем график
    {
      uint8_t max_pixel = map(mass_p[i], 0, GRAPH_max, 0, 15);
      myGLCD.drawLine(i + 0, 39, i + 0, 39 - max_pixel);
    }
  }
else if (graph_type == 1)
  {
  for (int i = 0; i < 84; i ++)  //печатаем график
    {
    if (mass_p[i] > 0) 
      {
        if (mass_p[i] <= 15) 
          {
            myGLCD.drawLine(i + 0, 39, i + 0, 39 - mass_p[i]);
          }
        if (mass_p[i] > 15) 
          {
            myGLCD.drawLine(i + 0, 39, i + 0, 39 - 15);
          }
      }
    }
  }

//------------------------------------------ Синалка 2 сработала ------------------------------------------------
if (tr2 == 1)
  {
           overflow_alarm = 1;
           #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
            }
          #else //пассивный бузер
            {
              if (blink_data){tone (6,1000,1000);} else {tone (6,3000,1000);}
            }
          #endif 
  }
//------------------------------------------------------------------------------------------------------
myGLCD.update();
}


//-------------------------------------------------------------------------------------------------------
void lcd_menu()  //вывод на дисплей меню
{
myGLCD.clrScr();
myGLCD.setFont(TinyFontRus);
myGLCD.print(utf8rus("ПОРОГ 1"), 5, 0); myGLCD.printNumI(treviga_1, 52, 0); myGLCD.print("\xBC\xBD\xBE\xBF", RIGHT, 0);
myGLCD.print(utf8rus("СИГНАЛКА"), 5, 6); //пункт меню выбора индикации частиц
switch (treviga_2)
  {
  case 0:
    myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 6); //сигналка выключена. Сигнализация Порог 1 тоже отключется.
    break;  
  case 1:
    myGLCD.print(utf8rus("100 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 100 мкр/ч
    break;  
  case 2:
    myGLCD.print(utf8rus("250 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 250 мкр/ч
    break;  
  case 3:
    myGLCD.print(utf8rus("500 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 500 мкр/ч
    break; 
  case 4:
    myGLCD.print(utf8rus("1 \xBC\xBE\xBF"), RIGHT, 6); // 1000 мкр/ч
    break; 
  case 5:
    myGLCD.print(utf8rus("5 \xBC\xBE\xBF"), RIGHT, 6); // 5000 мкр/ч
    break; 
  case 6:
    myGLCD.print(utf8rus("10 \xBC\xBE\xBF"), RIGHT, 6); // 10000 мкр/ч
    break; 
    default:
    myGLCD.print("err", RIGHT, 6); //  если значение не равно 1,2,3,4,5,6 или 0 - выводим ошибку 
  }
myGLCD.print(utf8rus("ПОДСВЕТКА"), 5, 12); 
if (podsvetka)  { myGLCD.print(utf8rus("ВКЛ."), RIGHT, 12); }
else  { myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 12);  }
myGLCD.print(utf8rus("ТИП ГРАФИКА"), 5, 18); if (graph_type) {myGLCD.print(utf8rus("НОВЫЙ"), RIGHT, 18);} else { myGLCD.print(utf8rus("СТАРЫЙ"), RIGHT, 18);} //
myGLCD.print(utf8rus("ОБН. ГРАФИКА"), 5, 24); myGLCD.printNumI(scrin_GRAF, 60, 24); myGLCD.print(utf8rus("СЕК."), RIGHT, 24);//
myGLCD.print(utf8rus("ИНДИКАЦИЯ"), 5, 30); //пункт меню выбора индикации частиц
switch (ind_ON)
  {
  case 0:
    myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 30); //индикация выключена
    break;  
  case 1:
    myGLCD.print(utf8rus("ЗВУК"), RIGHT, 30); //индикация звуком
    break;  
  case 2:
    myGLCD.print(utf8rus("СВЕТ"), RIGHT, 30); //индикация светом
    break;  
  case 3:
    myGLCD.print(utf8rus("ЗВУК+СВЕТ"), RIGHT, 30); //индикация звуком и светом
    break; 
  case 4:
    myGLCD.print(utf8rus("ВИБРО"), RIGHT, 30); //индикация вибрацией
    break; 
    default:
    myGLCD.print("err", RIGHT, 30); //  если значение не равно 1,2,3 или 0 - выводим ошибку 
  }
myGLCD.print(utf8rus("ВЫХОД"), 5, 36);
myGLCD.print(utf8rus("СОХРАНИТЬ"), 5, 42);
myGLCD.print(">", 0, n_menu * 6);
myGLCD.update();
}
//----------------------------------------------------------------------------------------------------------------------
void lcd_sys()  //вывод на дисплей меню
{
VCC_read();
speed_nakachka ();//скорость накачки имлульсы/сек
myGLCD.clrScr();
myGLCD.setFont(TinyFontRus);
myGLCD.print(utf8rus("ОПОРН."), 5, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 53, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
myGLCD.print(utf8rus("НАКАЧКА"), 5, 6); myGLCD.printNumI(puls, 55, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
myGLCD.print(utf8rus("СБРОС ДОЗЫ"), 5, 12); 
myGLCD.print(utf8rus("----"), 5, 18);
if (batproc == 0)  { myGLCD.print(utf8rus("БАТ. "), 5, 24);myGLCD.print(utf8rus("БЕЗ ИНДИКАЦИИ"), RIGHT, 24); }  
if (batproc == 1)  { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("ПРОЦЕНТАМИ"), RIGHT, 24); }
if (batproc == 2)  { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("НАПРЯЖЕНИЕМ"), RIGHT, 24);  }
myGLCD.print(utf8rus("БЕТА"), 5, 30); myGLCD.printNumI(beta_time, 50, 30); myGLCD.print(utf8rus("МИНУТ"), RIGHT, 30);
myGLCD.print(utf8rus("ВЫХОД"), 5, 36);
myGLCD.print(utf8rus("СОХРАНИТЬ"), RIGHT, 36);
myGLCD.print(">",sys_menu_1 + 0, sys_menu * 6 - sys_menu_2);
myGLCD.print(utf8rus("СКОРОСТЬ"), 5, 43); myGLCD.printNumI(speed_nak, 40, 43); myGLCD.print(utf8rus("ИМП/СЕК"), RIGHT, 43);
myGLCD.update();
}
//---------------------------------------------------------------------------------------------------------------------
void zamer_beta() 
{// замер бета или продуктов
if (gotovo == 0) 
  {
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
      {
        res_first_alarm(); //сбрасываем сигнал тревоги
      }
    myGLCD.clrScr();
    myGLCD.setFont(TinyFontRus);
    if (bet_z == 0)
      {
        myGLCD.drawBitmap(0, 0, beta_prev_1, 84, 48);
      }
    else if (bet_z == 1)
      {
        myGLCD.drawBitmap(0, 0, beta_prev_2, 84, 48); 
      }
myGLCD.setFont(SmallFontRus);
myGLCD.print(utf8rus("НАЖМИТЕ OK"), CENTER, 36);
myGLCD.update();
  }  
if (gotovo == 1) 
  {
    if (timer_seconds != beta_seconds) 
      {
        beta_seconds = timer_seconds;
        sek++;
        toch = !toch;
        if (sek >= 60) 
          {
            sek = 0;
            minute++;
          }
      } 
    byte otsup = 0;
    if (minute > 9) 
      {
          otsup = 5;
      }
    byte otsupp = 0;
    if (beta_time > 9) 
      {
        if (beta_time > 99) 
        {
          otsupp = 10;
        }
      else 
        {
          otsupp = 5;
        } 
      }
    myGLCD.clrScr();
    myGLCD.drawBitmap(0, 0, beta_fon, 84, 48);
    battery();
    if  (bet_z < 2) //таймер выводим только пока идёт первый или второй замер
    {
      myGLCD.setFont(TinyFontRus);
      myGLCD.printNumI(minute, LEFT, 0);
      if (toch == 0) 
        {
          myGLCD.print(":", 5 + otsup, 0);
        }
      else 
        {
          myGLCD.print(" ", 5 + otsup, 0);
        } 
      if (sek < 10){myGLCD.printNumI(0, 10 + otsup, 0);myGLCD.printNumI(sek, 10 + otsup + 4, 0);} else {myGLCD.printNumI(sek, 10 + otsup, 0);} myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ИЗ"), 21 + otsup, 0); myGLCD.printNumI(beta_time, 32 + otsup, 0); myGLCD.print("\xBC", 37 + otsup + otsupp, 0);
    }
    else
    {
      myGLCD.setFont(TinyFontRus);myGLCD.print(utf8rus("РЕЗУЛЬТАТ..."), 0, 0);
    }
    myGLCD.setFont(SmallFontRus);
    myGLCD.printNumI(bet_z0, 2, 17); myGLCD.printNumI(bet_z1, 44, 17);
    if (bet_z < 2) 
    {
      myGLCD.print(utf8rus("Идёт замер"), 5, 33); myGLCD.printNumI(bet_z, 72, 33);
    }
    if (bet_z == 2) 
    {
      myGLCD.printNumI(bet_r, CENTER, 29); myGLCD.print(utf8rus("мкР/ч"), CENTER, 38);
    }
    myGLCD.update();
    if (bet_z == 0)  //первый замер
    {
      bet_z0 = bet_z0 + shet;
      shet = 0;
      if (minute >= beta_time) 
        {
          bet_z = 1;
          sek = 0;
          minute = 0;
          gotovo = 0; 
          tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге
        }
    }
    if (bet_z == 1)  //второй замер
  {
    bet_z1 = bet_z1 + shet;
    shet = 0;
    if (minute >= beta_time) 
      {
        bet_z = 2;
        sek = 0;
        minute = 0;
        tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге    
      }
    }
    if (bet_z == 2)  //результат
    {
      bet_r = bet_z1 - bet_z0;
//      bet_r = bet_r / (1.5 * beta_time);
      bet_r = bet_r / ((60.0/(float)geiger_counter_seconds) * (float)beta_time);
      if (bet_r < 0) {bet_r = 0;} // если результат отрицательный - выводим 0. Можно оставить вывод отрицательного результата, закомментировав данную строчку.
    }
  }
if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    clear_poisk_variables();
  }
}
//-------------------------------------------------------------------------------------------------------------
void poisk_f() //режим поиска
{
int16_t shet_gr = 0;
if (poisk == 1) 
  {
    if (timer_seconds != count_and_dose_seconds) 
      {
        count_and_dose_seconds = timer_seconds;
          for (int i = 0; i < 254; i++)  //сдвигаем
          {
            mass_poisk[i] = mass_poisk[i + 1];
          }
        mass_poisk[254] = shet;
        if ((zam_poisk_counter < 254) && (zam_poisk_counter < geiger_counter_seconds))  //первый набор массива
          {
            fon_vr_poisk = fon_vr_poisk + shet;             
            zam_poisk_counter++;
            fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); 
//            fon_254 = fon;
            fon_254 = 0;
          }
        else if ((zam_poisk_counter < 254) && (zam_poisk_counter == geiger_counter_seconds))  //
          {   
            zam_poisk_counter++;
            fon_vr_poisk = fon_vr_poisk + shet; 
            fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter)));
            fon_254 = fon;    
            fon_vr254 = fon_vr_poisk;
          }
        else if ((zam_poisk_counter < 254) && (zam_poisk_counter > geiger_counter_seconds))  //
          {
            fon_vr_poisk = 0;
            fon_vr254 = 0;
            for (int i = zam_poisk_counter; i > 0; i--) 
              {
                fon_vr254 = fon_vr254 + mass_poisk[254-i];
              }
            for (int j = 254 - geiger_counter_seconds; j < 255; j++) 
              { 
                fon_vr_poisk = fon_vr_poisk + mass_poisk[j];
              }
            fon = fon_vr_poisk;
//            fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/(float(zam_poisk_counter)));
            fon_254 = (float)fon_vr254*((float)geiger_counter_seconds/(float)zam_poisk_counter); 
            fon_vr254 = 0;
            zam_poisk_counter++;
          } 
        else if (zam_poisk_counter >= 254)  //набор массива
          {
            fon_vr_poisk = 0;
            fon_vr254 = 0;
            byte geiger_counter_seconds_reverse = 254 - geiger_counter_seconds;
            for (int i = 254; i > 0; i--) 
              {
                fon_vr254 = fon_vr254 + mass_poisk[i];
                if (i > geiger_counter_seconds_reverse)
                  {
                    fon_vr_poisk = fon_vr_poisk + mass_poisk[i];
                  }
              }
            fon = fon_vr_poisk;
            fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/254.0);
          }
        shet = 0;
        doz_v = doz_v + fon / 100.0 / 36.0;
        time_doza = time_doza + 1;
        if (doz_v - doza_vr >= save_DOZ)  //а не пора ли сохранить дозу ?
          {
            eeprom_wrD ();
            doza_vr = doz_v;
          }
//Serial.print(" zam_poisk_counter=");
//Serial.println(zam_poisk_counter);            
      }
    if (millis() - gr_milis >= scrin_GRAF * 1000) //счет для графика
      {
      gr_milis = millis();
      if (graph_type == 0)
        {
        val_ok = 0;//сброс удержания системного меню  
        for (uint8_t s = 254; s >= (255 - scrin_GRAF); s--) 
          {
            shet_gr = shet_gr + mass_poisk[s];
          }
        shet_gr = shet_gr / scrin_GRAF;
        for (int i = 0; i < 83; i++) // сдвигаем массив графика
          {
            mass_p[i] = mass_p[i + 1];
          }
        mass_p[82] = byte(shet_gr);
        if (GRAPH_count > 82) 
          {
            GRAPH_max = 5; 
            GRAPH_count = 0;
          }   
        for (int i = 0; i < 82; i++) 
          {
            if (mass_p[i] > GRAPH_max)
              {
                GRAPH_max = mass_p[i];
                GRAPH_count = 0;
              }
          }
        GRAPH_count++;     
        }
      if (graph_type == 1)
        {
          val_ok = 0;//сброс удержания системного меню
          shet_gr = shet - shet_n;
          if (shet_gr < 0) 
            {
              shet_gr = 1;
            }
          shet_n = shet;
          for (int i = 0; i < 83; i++) 
            {
              mass_p[i] = mass_p[i + 1];
            }
          mass_p[82] = byte(shet_gr);
            
        
        }       
      }
  }
}
//----------------------------------------------------------------------------------------------------------------

void clear_poisk_variables ()
{
shet = 0;
fon = 0;
fon_254 = 0;
zam_poisk_counter = 0;
GRAPH_max = 5;
GRAPH_count = 0;
fon_vr254 = 0;
fon_vr_poisk = 0;
for (uint8_t i = 0; i < 84; i++) { mass_p[i] = 0; } // чистим массив графика
for (uint8_t i = 0; i < 254; i++) { mass_poisk[i] = 0; } // чистим массив поиска  
}

void signa ()  //индикация каждой частички звуком светом
{
shet_s = shet;  
if (!alarm_sound && tr2 == 0) //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
    {
    if (!shet_s) {return;} //если залетели в функцию signa() при обнулении переменной shet_s - просто возвращаемся в точку вызова. Детальнее здесь: arduino.ru/forum/proekty/delaem-dozimetr?page=16#comment-318736
    switch (ind_ON) //проверяем, какой тип индикации выбран
      {
        case 0: //индикация выключена
          break;  
        case 1: //индикация звуком
          #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
            }
          #else //пассивный бузер
            {
              tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге
            }
          #endif 
          break;  
        case 2: //индикация светом
          PORTB |= (1 << 5); //включаем светодиод
          delay(del_BUZZ); //длительность одиночного сигнала
          PORTB &= ~(1 << 5); //выключаем светодиод
          break;
  
        case 3: //индикация звуком и светом
          #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTB |= (1 << 5); //включаем светодиод
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
              PORTB &= ~(1 << 5); //выключаем светодиод
            }
          #else //пассивный бузер
            {
              PORTB |= (1 << 5); //включаем светодиод
              tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге
              delay(del_BUZZ);//длительность одиночного сигнала
              PORTB &= ~(1 << 5);//выключаем светодиод
            }
          #endif 
          break; 
        case 4: // индикация вибрацией
          PORTB |= (1 << 0); //включаем вибру
          delay(del_BUZZ); //длительность одиночного сигнала
          PORTB &= ~(1 << 0); // выключаем вибру      
      } 
    }
else // если активен сигнал тревоги, то только мигаем светодиодом (независимо от того, включён или нет светодиод в меню)
  {
      PORTB |= (1 << 5); //включаем светодиод
    delay(del_BUZZ);
    PORTB &= ~(1 << 5);//выключаем светодиод
  }
}
//-------------------------------------------------------------------------------------------------
void Schet()  //прерывание от счетчика на пин 2
{
shet++;
if (shet>250) {overflow_alarm = 1;} // детект приближения к переполнению переменной
}
//-------------------------------------------------------------------------------------------------
void generator() //накачка по обратной связи с АЦП
{
hv_adc  = Read_HV();
if (hv_adc < ADC_value)  //Значение АЦП при котором на выходе 400В
  {
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) 
      {
        asm("nop");
        c--;
      }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//--------------------------------------------------------------------------------------------------
byte Read_HV () 
{
ADCSRA = 0b11100111;
#ifdef UNO_DIP //если при компилляции выбрана плата ArduinoUNO
ADMUX = 0b11100101;//выбор внутреннего опорного 1,1В и А5 
#else // если используется промини, нано или голый камень в tqfp
ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
#endif  
for (int i = 0; i < 10; i++) 
  {
    while ((ADCSRA & 0x10) == 0);
    ADCSRA |= 0x10;
  }
result = 0;
for (int i = 0; i < 10; i++) 
  {
    while ((ADCSRA & 0x10) == 0);
    ADCSRA |= 0x10;
    result += ADCH;
  }
result /= 10;
return result;
}
//----------------------------------------------------------------------------------------------------
void battery()  //батарейка
{
if (bat_mill - millis() > 2000) 
  {
    bat_mill = millis();
    VCC_read();
  }
myGLCD.setFont(TinyFontRus);
byte batprocent = 99;
batprocent = ((VCC - batnapruga) * 100 / (batmax - batnapruga));
byte batline = 9; //Задаем длину линии батареи
batline = 0.1 * ((VCC - batnapruga) * 100 / (batmax - batnapruga)); //Зависимость длинны в пикселях от процента заряда

if (batproc == 1 && VCC < batusb && batprocent < 100) {myGLCD.printNumF(batprocent, 0, 58, 0);myGLCD.print("%", 66, 0);} // процент заряда
if (batproc == 2) {myGLCD.printNumF(VCC, 2, 54, 0);} // процент заряда
      if (batprocent > 5 && (VCC - batnapruga) > 0.01) //Проверяем процентный заряд акб 0.05 - 5%
        {
          if (VCC > batusb)
          {
  myGLCD.drawBitmap(71, 0, logo_bat_usb, 13, 5);
          }
            else
          {
  myGLCD.drawBitmap(71, 0, logo_bat, 13, 5);
  if (batprocent >= 100) {batline = 9;};
  myGLCD.drawBitmap(82 - batline, 1, logo_bat_line, batline + 1, 3);
          }
        }
      else //Если заряд меньше 5% мигаем пустой батарейкой
        {
          toch = !toch;
          if (toch == 0) 
          {
            myGLCD.drawBitmap(71, 0, logo_bat, 13, 5);
          }
          else 
          {
            myGLCD.drawBitmap(71, 0, logo_bat, 0, 0);
          } 
        }
}
//----------------------------------------------------------------------------------------------------
void VCC_read()  // Чтение напряжения батареи
{
ADCSRA = 0b11100111;
ADMUX = 0b01101110;//Выбор внешнего опорного+BG
_delay_ms(5);
while ((ADCSRA & 0x10) == 0);
ADCSRA |= 0x10;
byte resu = ADCH;
//ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
VCC = (opornoe * 255.0) / resu;
}
//----------------------------------------------------------------------------------------------------
void lcd_init() 
{
myGLCD.InitLCD();
myGLCD.setContrast(contrast);
myGLCD.clrScr();
myGLCD.drawBitmap(0, 0, logo_rag, 84, 48);
//myGLCD.setFont(SmallFontRus);
//  myGLCD.print(utf8rus("Ардуино+"), CENTER, 32);
//  myGLCD.print(utf8rus("Дозиметр v1.07"), CENTER, 40);
myGLCD.update();
_delay_ms(1000);
}
//----------------------------------------------------------------------------------------------------
void eeprom_wrS ()  //запись настроек в память
{
  EEPROM.write(0, 222);
  EEPROM.write(1, treviga_1);
  EEPROM.write(2, podsvetka);
  EEPROM.write(3, graph_type);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, ind_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(100, batproc);
  EEPROM.write(17, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFontRus);
  myGLCD.print(utf8rus("Сохранено"), CENTER, 20);
  myGLCD.update();
  _delay_ms(1000);
}
//-----------------------------------------------------------------------------------------------------
void eeprom_wrD ()  //запись настроек в память время накопления дозы
{
  EEPROM.put(9, time_doza);
  EEPROM.put(13, doz_v);   
}
//-----------------------------------------------------------------------------------------------------
void eeprom_readD ()  //чтение настроек из памяти время накопления дозы
{
  EEPROM.get(9, time_doza);
  EEPROM.get(13, doz_v);   
}
//-----------------------------------------------------------------------------------------------------
void eeprom_readS ()  //чтение настроек из памяти
{
  if (EEPROM.read(0) == 222) 
  {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    graph_type = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    ind_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    batproc = EEPROM.read(100);
    beta_time = EEPROM.read(17);
  }
_delay_ms(11);
}
//------------------------------------------------------------------------------------------------------
void nakachka() //первая накачка
{
byte n = 0;
while (n < 30) 
  {
    PORTD |= (1 << 5);//дергаем пин
    int c = puls;
    while (c > 0) 
      {
        asm("nop");
        c--;
      }
    PORTD &= ~(1 << 5);//дергаем пин
    n++;
    _delay_us(100);
  }
}
//------------------------------------------------------------------------------------------------------
void speed_nakachka ()  //скорость накачки имлульсы/сек
{
if (millis() - spNAK_milis >= 1000) 
  {
    spNAK_milis = millis();
    speed_nak = speed_nakT;
    speed_nakT = 0;
  }
}
//------------------------------------------------------------------------------------------------------
void time_d() 
{
  MONTH = time_doza / 2592000;
  DAY = (time_doza / 86400) % 30 ;
  HOUR = (time_doza / 3600) % 24 ;
  MIN = (time_doza / 60) % 60;
}
//------------------------------------------------------------------------------------------------------
void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
  if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
    {
      alarm_sound = 1; // поднимаем флаг аварийного сигнала
      alarm_milis = millis(); // запоминаем время начала тревоги
    }
}
//------------------------------------------------------------------------------------------------------
void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
{
   alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   PORTB &= ~(1 << 0); // выключаем вибру
   periodical_alarm_variable = 0; // обнуляем переменную
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
}
//------------------------------------------------------------------------------------------------------
void ind_doze_time() //вывод времени накопления дозы на дисплей
{
  myGLCD.setFont(TinyFontRus);
  if (MONTH) // если есть месяцы
    {
      myGLCD.printNumI(MONTH, 0, 43);
      if(MONTH>99)
        {
          myGLCD.print("M", 13, 43);
        }
      else if (MONTH>9)
        {
          myGLCD.print("M", 9, 43);
        }
      else
        {
          myGLCD.print("M", 5, 43);
        }
    myGLCD.printNumI(DAY, 18, 43);
    if (DAY > 9) 
      {
        myGLCD.print("\xBB", 26, 43);
      }
    else
      {
        myGLCD.print("\xBB", 23, 43);
      } 
    }
  else if (DAY) // если нет месяцев, но есть дни
    {
      myGLCD.printNumI(DAY, 0, 43);
      if (DAY > 9) 
        {
          myGLCD.print("\xBB", 9, 43);
        }
      else
        {
          myGLCD.print("\xBB", 5, 43);
        }
      myGLCD.printNumI(HOUR, 18, 43);
      if (HOUR > 9) 
        {
          myGLCD.print("\xBA", 26, 43);
        }
      else 
        {
          myGLCD.print("\xBA", 23, 43);
        }
    }
  else // если нет дней
    {
      myGLCD.printNumI(HOUR, 0, 43);
      if (HOUR > 9) 
        {
          myGLCD.print("\xBA", 9, 43);
        }
      else
        {
          myGLCD.print("\xBA", 5, 43);
        }
      myGLCD.printNumI(MIN, 18, 43);
      if (MIN > 9) 
        {
          myGLCD.print("\xBC", 26, 43);
        }
      else
        {
          myGLCD.print("\xBC", 23, 43);
        }
    }   

}
//--------------------------------------------------------------------------------------------------------
byte get_key() // Функция определения нажатия и удержания кнопок
{
// версия 1 - для кратковременного нажатия значение возвращается при отпускании кнопки, для длительного - пока кнопка остаётся нажатой, с заданным интервалом
uint8_t trigger_push_hold_counter = 10; // задержка триггера кратковременного/длительного нажатия (проходов функции, умноженных на задержку "milliseconds_between_increment")  
uint8_t milliseconds_between_increment = 50; // интервал в миллисекундах между инкрементом счётчика нажатой кнопки 
static uint8_t val_kp, val_kl, val_ok;
static uint32_t key_delay_millis;
static uint32_t key_delay_after_hold_millis;
if ((millis() - key_delay_millis) > milliseconds_between_increment) //обрабатываем нажатия инкрементом переменной только если после предыдущей обработки прошло не менее "milliseconds_between_increment" миллисекунд
  {
    if (!(PIND & (1 << PIND4)))  //нажатие >>>
    {
    val_kp++;  // инкрементируем счётчик
    if (val_kp > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши 
      {
       val_kp = 0; // сбрасываем счётчик 
       key_delay_after_hold_millis = millis(); // запоминаем время
       return key_holded_right; // возвращаем значение
      }
    }
    if (!(PIND & (1 << PIND7)))  //нажатие <<<
    {
    val_kl++;  // инкрементируем счётчик
    if (val_kl > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши
      {
        val_kl = 0; // сбрасываем счётчик
        key_delay_after_hold_millis = millis(); // запоминаем время 
        return key_holded_left; // возвращаем значение
      }   
    }
    if (!(PIND & (1 << PIND3)))  //нажатие OK
    {
    val_ok++; // инкрементируем счётчик
    if (val_ok > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши
      {
        val_ok = 0; // сбрасываем счётчик
        key_delay_after_hold_millis = millis(); // запоминаем время 
        return key_holded_ok; // возвращаем значение
      }       
    }
    key_delay_millis = millis(); // запоминаем время 
  }
if (val_ok > 0) //если клавиша OK перед этим была нажата 
  {
     if ((PIND & (1 << PIND3)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_ok = 0;  // сбрасываем счётчик
        return key_pressed_ok; // возвращаем значение
      }
  }
if (val_kp > 0) //если клавиша >>> перед этим была нажата 
  {
    if ((PIND & (1 << PIND4)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_kp = 0;  // сбрасываем счётчик 
        return key_pressed_right; // возвращаем значение
      }
  }
if (val_kl > 0) //если клавиша <<< перед этим была нажата 
  {
    if ((PIND & (1 << PIND7)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_kl = 0;  // сбрасываем счётчик  
        return key_pressed_left; // возвращаем значение
      }
  }
if (PIND & (1 << PIND4)) {val_kp = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
if (PIND & (1 << PIND7)) {val_kl = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
if (PIND & (1 << PIND3)) {val_ok = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
return 0; // если ни одна из кнопок не была нажата - возвращаем 0
}
//------------------------------------------------------------------------------------------------------------------------------
char *utf8rus(char *source) // функция преобразования utf8 для вывода кириллицы (by arduinec)
{
  int i,j,k;
  unsigned char n;
  char m[2] = { '0', '\0' };

  strcpy(target, ""); k = strlen(source); i = j = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }

    m[0] = n; strcat(target, m);
    j++; if (j >= maxString) break;
  }
  return target;
}

ISR (TIMER1_OVF_vect) // прерывание по таймеру, генерируемое каждую секунду
{ 
timer_seconds++ ; //инкремент переменной каждую секунду
if (timer_seconds > 59){timer_seconds = 0;}
}

// ________________ конец скетча, дальше можно не копировать _____________________



 

alexadresat
alexadresat аватар
Offline
Зарегистрирован: 22.02.2017

OfficialGalkin - Ну вот так получше. 

Dark-Dante
Offline
Зарегистрирован: 09.01.2018

tekagi пишет:

Похоже общими усилиями нашли ещё один косяк.

Версия 1.05: doz_v = doz_v + fon / 100.0 / 36.0; , счёт был 36 секунд.

Версия 1.062 doz_v = doz_v + fon / 100.0 / 40.0; , счёт использован 40секунд.

Учитывая, что вызов ведётся раз в секунду, логично предположить, что текущий уровень фона должен делиться на 3600, т.е. верхнее выражение верное. Видимо, при переходе к 40 секундам по ошибке было изменено и это значение. Но всё равно буду переделывать на другой алгоритм подсчёта.

Так 36 или 40? Поменял согласно этому посту на 36. Еще заметил что в режиме поиск диод моргает хаотично с бкззером, где искать косяк? В индикации кроме частоты буззера и времени в 5мкс ничего не менял?

В режиме разностного замера вспышки соответствуют щелчкам буззера, в поиске нет.

alexadresat пишет:

надпись Внимание! остается, так и должно быть?

Нет, это косяк, сам вчера с этим бодался час в своём скетче.

alexadresat
alexadresat аватар
Offline
Зарегистрирован: 22.02.2017

Dark-Dante - Все работает как надо, я разобрался. Пока во втором показометре доза превышает лилит до тех пор надпись Внимание! на экране.

alexadresat
alexadresat аватар
Offline
Зарегистрирован: 22.02.2017

OfficialGalkin - а может надпись Внимание! лучше сделать моргающей?

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Dark-Dante пишет:
Так 36 или 40? Поменял согласно этому посту на 36.

36. Там было ошибочно выставлено 40, видимо приняли за время счёта.

Dark-Dante пишет:
В индикации кроме частоты буззера и времени в 5мкс ничего не менял? В режиме разностного замера вспышки соответствуют щелчкaм буззера, в поиске нет.

На столе помигивает 1.08.2 с добавленым обратным отсчётом при бета-замере, баг не наблюдаю. Бузер активный.

Dark-Dante
Offline
Зарегистрирован: 09.01.2018

Это не из-за таймера, я вообщем спросил из-за чего может быть такое? Раньше не помню было так же или нет. Вчера, позавчера очень много изменений делал, но индикацию не трогал.

 

alexadresat пишет:

OfficialGalkin - а может надпись Внимание! лучше сделать моргающей?

Добавьте blink_data в 634 строку.

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

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

switch (ind_ON) //проверяем, какой тип индикации выбран
			{
				case 0: //индикация выключена
					break;	
				case 1: //индикация звуком
					#ifdef buzzer_active //если задефайнен активный бузер
						{
							PORTD |= (1 << 6); //включаем бузер 
							delay(del_BUZZ); //длительность одиночного сигнала
							PORTD &= ~(1 << 6); //выключаем бузер 
						}
					#else //пассивный бузер
						{
							tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге
						}
					#endif 
					break; 	
				case 2: //индикация светом
					PORTB |= (1 << 5); //включаем светодиод
					delay(del_BUZZ); //длительность одиночного сигнала
					PORTB &= ~(1 << 5); //выключаем светодиод
					break;
	
				case 3: //индикация звуком и светом
					#ifdef buzzer_active //если задефайнен активный бузер
						{
							PORTB |= (1 << 5); //включаем светодиод
							PORTD |= (1 << 6); //включаем бузер 
							delay(del_BUZZ); //длительность одиночного сигнала
							PORTD &= ~(1 << 6); //выключаем бузер 
							PORTB &= ~(1 << 5); //выключаем светодиод
						}
					#else //пассивный бузер
						{
							PORTB |= (1 << 5); //включаем светодиод
							tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге
							delay(del_BUZZ);//длительность одиночного сигнала
							PORTB &= ~(1 << 5);//выключаем светодиод
						}
					#endif 
					break; 
				case 4: // индикация вибрацией
					PORTB |= (1 << 0); //включаем вибру
					delay(del_BUZZ); //длительность одиночного сигнала
					PORTB &= ~(1 << 0); // выключаем вибру			
			} 

 

alexadresat
alexadresat аватар
Offline
Зарегистрирован: 22.02.2017

Dark-Dante - если можно напиши целиком строчку 634, как должно быть.

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Dark-Dante,

if ((tr == 1) && blink_data) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);}

Так можно прилепить мигание к любому выводимому на экран АрДоса элементу, период около 0,3с.

OfficialGalkin, обратите внимание на последовательность операторов if (...) else if (...). Всяко лучше такого:

if (tr == 1) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);}
if (fon_254 >= 0 && fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);}
if (fon_254 >= 10 && fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);}
if (fon_254 >= 100 && fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);}
if (fon_254 >= 1000 && fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);}
if (fon_254 >= 10000 && fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);}
if (fon_254 >= 100000 && fon_254 <= 999999) {myGLCD.printNumI(fon_254, 2, 8);}

 

alexadresat
alexadresat аватар
Offline
Зарегистрирован: 22.02.2017

tekagi - Благодарю!

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

Так?

myGLCD.clrScr();
myGLCD.drawBitmap(0, 0, fon_poisk, 84, 48);
myGLCD.setFont(SmallFontRus);
myGLCD.drawLine(1, 21, zam_poisk_counter * 0.1 + 1, 21);
myGLCD.drawLine(1, 22, zam_poisk_counter * 0.1 + 1.4, 22);
myGLCD.drawLine(1, 23, zam_poisk_counter * 0.1 + 0.6, 23);
if (fon_254 > 0) {
myGLCD.setFont(TinyFontRus);
if ((tr == 1) && blink_data) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);}
if (fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);}
else if (fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);}
else if (fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);}
else if (fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);}
else if (fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);}
else {myGLCD.printNumI(fon_254, 2, 8);};
}
 
if (overflow_alarm && !blink_data) {myGLCD.drawBitmap(27, 7, em_logo, 37, 17);overflow_alarm = 0;}

else if ((zam_poisk_counter >= geiger_counter_seconds) || blink_data)
  {
    myGLCD.setFont(MediumNumbers);
if (fon <= 9){myGLCD.printNumI(fon, 52, 7);}
else if (fon <= 99){myGLCD.printNumI(fon, 40, 7);}
else if (fon <= 999){myGLCD.printNumI(fon, 28, 7);}
else if (fon <= 9999){myGLCD.printNumI(fon / 1000, 52, 7);}
else if (fon <= 99999){myGLCD.printNumI(fon / 1000, 40, 7);}
else{myGLCD.printNumI(fon / 1000, 28, 7);}
  }

 

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Последние условия я бы всё же оставил else if. Особенно учитывая, что оно поверх фоновых нулей пишется. И зачем точки с запятой после фигурных скобок?

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

Ну так оно все равно выполняется, если все верхние не выполнились. Как и написано в вики. 

Vladikas
Offline
Зарегистрирован: 25.07.2013

А такое будет интересно, где дозиметр показывает на экране гистограмму распределения Пуассона в реальном времени?

Сверху три цифры (просто для отладки) - минимальное, среднее арифметическое, максимальное значение CPS. В консоль выводится дисперсия, статистическая ошибка ну и всё такое. На экране реальные данные от датчика СБТ-9 и СПДшного стрелочного индикатора.

В железе это пока ужас, но не думаю, что буду изобретать что-то новое, тут уже всё придумано давно.

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Разве что как отдельная прошивка для энтузиастов, с теми же параметрами в еепром (железо уже настроено). Памяти уже не хватает. Практической пользы особо не вижу, хоть и интересно. А вообще я за любое развитие проекта :)

З.Ы. Не держите дома СПД, ещё и в неупакованом виде. Редкая кака, сам светосостав сыпется и его пыль разносится по комнате. А попадание такой пылинки куда не надо чревато... В качестве домашнего КИ лучше использовать урановое стекло. Или, в крайнем случае, пакет калийных удобрений.

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

У меня была мысль перевести проект на atmega2560. Собрать дозиметр с экраном побольше.

медведь
Offline
Зарегистрирован: 31.07.2019

большой экран уже круто 

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Зачем? Дозиметр по определению должен быть небольшим, для постоянного ношения. И с микропотреблением, чего никогда не достигнуть с большим экраном (если это не е-инк). На больший камень переводить тоже смысла не вижу, и в текущем немыслимый простор для оптимизации, раньше делали на восьмой меге и тиньках, причём не уступающие в функционале. Даже АрДос на атмега8 существует, в теме выложен.
Кабы современные погромисты учились, вместо того, чтобы переходить на бОльшие системные требования, глядишь, и не пришлось бы каждые два года плашку памяти в комп докидывать, и телефон менять...

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

Экран всего по 10 пикселей больше. Такой-же монохромный. Тоже подключение. И стоит также. HX1230

Dark-Dante
Offline
Зарегистрирован: 09.01.2018

Это из-за того что колокольчик не влез?))

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

Передела бету (визуально)

Выкинуто 2 глобальные переменные. 

Обратный таймер от tekagi

В обратном таймере убран баг с -1 - й минутой 

Код

/* ArDOs   v1.08.2
***Дозиметр на Ардуино
***IDE Arduino 1.8.8
  ветка форума arduino.ru/forum/proekty/delaem-dozimetr
  сайт srukami.inf.ua/ardos.html
*/
#include <util/delay.h> //уже есть
#include <EEPROM.h>//уже есть
#include <LCD5110_Graph.h>//нужно установить

//настройки /////////////начало
LCD5110 myGLCD(A1, A0, 12, 10, 11); //подключение дисплея
#define contrast 70 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
//#define UNO_DIP // если используется ArduinoUNO или плата на голой атмеге328 в корпусе DIP - раскомментируйте данную строчку. Это переключит чтение напряжения с делителя с ноги A6 на ногу A5.
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 0; //вторая ступень тревоги
byte del_BUZZ = 2;//длительность одиночного сигнала
#define  ADC_value 225  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255). Для значений делителя с сайта srukami 163. alexadresat 185. (Тестовая версия tekagi  67)
#define k_delitel 420 //коефициент делителя напряжения, зависит от вашего делителя. Для значений делителя с сайта srukami k_delitel 576. alexadresat 500 (Тестовая версия tekagi  1395)
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool podsvetka = 0; //подсветка
uint8_t graph_type = 1; //тип графика
bool alarm_sound = 0; //флаг индикации превышения порога звуком
float opornoe = 1.10; //делить на opornoe/10
#define save_DOZ 1 //как часто сохранять накопленную дозу например каждые 20мкР
#define geiger_counter_seconds 40 // число секунд для замера, соответствующее характеристикам счётчика. Для СБМ-20 равно 40.
byte beta_time = 5; //время замера бета излучения
uint8_t batproc = 0; // 1- отображать проценты. 0 - не отображать
float batusb = 4.30; // настройка напряжения, выше которого будет отображаться значек USB
float batmax = 4.15; //Настройка максимального значения напряжения акб для отображения. Обычно 4.20 вольта
float batnapruga = 3.20; //Настройка минимального значения напряжения акб для отображения. Зависит от работоспособности вашей схемы. Обычно 3.20 вольта by OfficialGalkin 
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFontRus[], MediumNumbers[], TinyFontRus[];
volatile uint8_t timer_seconds = 0; // для отсчёта секундных интервалов в прерывании
uint8_t beta_seconds = 0;
uint8_t count_and_dose_seconds = 0;
#define maxString 21 // для работы функции преобразования кодировки utf8us
char target[maxString + 1] = ""; // для работы функции преобразования кодировки utf8us
extern uint8_t logo_bat[], logo_bat_line[], logo_bat_usb[], logo_rag[], logo_tr[], beta_prev_1[], beta_prev_2[], beta_fon[], bs[], em_logo[], fon_poisk[], mkr[], mr[];
volatile int shet = 0;
volatile bool overflow_alarm = 0;
int8_t ind_ON = 1;  //0 - индикация выключена, 1 - включён бузер, 2 - светодиод, 3 - и бузер, и светодиод
uint8_t first_alarm_type = 1;  //1-3, 1 - только бузер, 2 - только вибро, 3 - и бузер, и вибро
byte periodical_alarm_variable = 0; // переменная для периодически повторяющейся тревожной сигнализации
uint8_t tr2 = 0; // сигналка 2 сработала
unsigned long gr_milis = 0, lcd_milis = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
uint16_t hv_adc, hv_400, shet_n = 0, shet_s = 0;
uint16_t fon = 0, fon_254 = 0;
int speed_nakT = 0, speed_nak = 0, result;
byte MIN, DAY, HOUR, MONTH; //для учёта времени дозы
uint16_t doza_vr = 0, fon_vr254 = 0, fon_vr_poisk = 0;
byte mass_p[84]; // массив для графика
byte m = 0, n_menu = 0, sys_menu = 0, sys_menu_1 = 0, sys_menu_2 = 0;
byte  mass_poisk[255]; // основной рабочий массив
byte val_kl = 0, val_ok = 0, menu = 0, zam_poisk_counter = 0;
byte sek = 0, minute = 0, bet_z = 0, gotovo = 0;
int  bet_z0 = 0, bet_z1 = 0, bet_r = 0;
float VCC = 0.0, doz_v = 0.0;
bool tr = 0, poisk = 1, fonarik = 0, toch, blink_data=1;
uint8_t GRAPH_max = 5; // максимальное значение за период отображения графика
uint8_t GRAPH_count = 0; // счётчик для поиска максимального значения для графика
#define key_pressed_left 1
#define key_pressed_right 2
#define key_pressed_ok 3
#define key_holded_left 4
#define key_holded_right 5
#define key_holded_ok 6
#define keys_not_pressed 0
uint8_t key_data = 0;
//-------------------------------------------------------------
void setup() {
  //-----------------------------------------------------------
  // настраиваем таймер на секундный интервал
  TCCR1A=(1<<WGM11); //режим14 FAST PWM 
  TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
if (F_CPU == 16000000UL) 
 {
  ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
 }
else if (F_CPU == 8000000UL) 
 {
  ICR1=31249;  // (8000000MHz /div256) -1 = 1 раз в секунду
 } 
  TIMSK1=(1<<TOIE1); //разрешить прерывание
  //-----------------------------------------------------------
// Serial.begin(115200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (1 << 0); PORTB &= ~(1 << 0); //пин вибры 8
  DDRC |= (0 << 4); PORTC &= ~(1 << 4); //пин пустой А4
  DDRC |= (0 << 5); PORTC &= ~(1 << 5); //пин пустой А5
  DDRB |= (1 << 1);//пин фонаря
  DDRC |= (1 << 3);//A3 дисплей GND
  DDRC |= (1 << 2);//A2 дисплей Light
  PORTC &= ~(1 << 3); //A3 дисплей GND
  PORTC  |= (1 << 2); //A2 дисплей Light
  eeprom_readS ();
  eeprom_readD ();
  lcd_init();
  attachInterrupt(0, Schet, FALLING);//прерываниям пин 2
  DDRB |= (1 << 5); //пины на выход
  DDRD |= (1 << 5);
  DDRD |= (1 << 6);
  DDRD |= (1 << 6);//пин бузера
  nakachka();
  clear_poisk_variables();
}
//-------------------------------------------------------------
void loop() 
{
key_data = get_key();  // вызываем функцию определения нажатия кнопок, присваивая возвращаемое ней значение переменной, которую далее будем использовать в коде
if (menu == 0) 
  {
    if (key_data == key_pressed_left)   //нажатие <<<
    {
      key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду 
      clear_poisk_variables();
    }
    if (key_data == key_holded_left) //удержание <<< фонарик  
  {
    fonarik = !fonarik; 
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
  }   
    if (key_data == key_holded_right) // удержание <<< подсветка
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
        podsvetka = !podsvetka;
    }   
    if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 4;
    shet = 0;
    bet_z0 = 0;
    bet_z1 = 0;
    bet_r = 0;
    bet_z = 0;
    gotovo = 0;
    sek = 0;
    minute = 0;
    }
 } 
if (menu == 3)
  {
    if (key_data == key_pressed_left)  //нажатие <<<
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    shet = 0; fon = 0; zam_poisk_counter = 0;
    for (int i = 0; i < 18; i++) { mass_poisk[i] = 0; }//чистим
  }
  } 
if (menu == 4) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    clear_poisk_variables();
    }
  }
if (fonarik == 0)  //фонарик
  {
    PORTB &= ~(1 << 1);//пин фонаря
  } 
else if (fonarik == 1) 
  {
    PORTB |= (1 << 1);//пин фонаря
  }
if (podsvetka == 1) 
  {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
else if (podsvetka == 0) 
  {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300)  //скорость отрисовки дисплея
  {
    lcd_milis = millis();
    blink_data = !blink_data;
    if (menu == 0) 
      {
        lcd_poisk();  //вывод на дисплей режима поиск
        poisk_f();    //вызов функции счёта и набора массива
      }
    if (menu == 1) 
      {
        lcd_menu();   //вывод на дисплей меню
        poisk_f();  //вызов функции счёта и набора массива 
      }
    if (menu == 2) 
      {
        lcd_sys();    //вывод на дисплей системного меню
        poisk_f();  //вызов функции счёта и набора массива
      }
    if (menu == 3) 
      {
//          zamer_200s(); //вывод на дисплей замер 180сек
        menu = 0;
      }
    if (menu == 4) 
      {
        zamer_beta();
      }
  }
//-------------------------------------------------------------------------------------------------------------
/* Костыль. Разностный замер и длительный замер вызываются с частотой отрисовки дисплея, 
поэтому сложно поймать нажатия кнопок внутри функций zamer_200s() и zamer_beta().
Возможно в будущем придётся разделить эти функции на обработку данных (вызывать с частотой loop'а) 
и вывод на дисплей (вызывать с частотой обновления дисплея)
*/
if (menu == 4)
{
    if ((key_data == key_pressed_ok) && (gotovo == 0))  //нажатие OK
    {
      key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
      gotovo = 1;
      switch (bet_z) //проверяем, находимся ли в первом или втором замере
      {
        case 0: //если в первом замере
          bet_z0 = 0; //обнуляем текущие показания замера 1
          shet = 0; //обнуляем счёт
        case 1: //если во втором замере
          bet_z1 = 0; //обнуляем текущие показания замера 2
          shet = 0; //обнуляем счёт            
      }
    }
}
//--------------------------------------------------------------------------------------------------------------  
generator();//накачка по обратной связи с АЦП
if (shet_s != shet) 
  {
    signa ();//подача сигнала о частичке
  }
if (key_data == key_pressed_ok) { //нажатие ок
if (menu == 2) 
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    sys_menu++;
    if (sys_menu > 7) 
      {
        sys_menu = 0;
      }
  }
if (menu == 1) 
  {
    key_data = 0;    // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    n_menu++;
    if (n_menu > 7) 
      {
        n_menu = 0;
      }
  }
if (menu == 0) 
  {
    key_data = 0;   // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 1;
  }
  } 
if (menu == 0)  // в меню по удержанию кнопки "ок" входим только из режима "поиск"
  {
    if (key_data == key_holded_ok)  //удержание OK
      {
        menu = 2; 
        key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
      }
  }
if (menu == 1) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
      {
        if (n_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду   
            treviga_1 = treviga_1 + 10;
            if (treviga_1<10) {treviga_1 = 10;}
            if (treviga_1>100) {treviga_1 = 10;}
          }
        if (n_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            treviga_2++;
            treviga_2 = constrain (treviga_2, 0, 6);
          }
        if (n_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            podsvetka = !podsvetka;
          }
        if (n_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            graph_type++;
            if (graph_type>1) {graph_type = 0;}
          }
        if (n_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            scrin_GRAF++;
            if (scrin_GRAF > 10) 
              {
                scrin_GRAF = 1;
              }
          }
        if (n_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            ind_ON++; 
            ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4
          }
        if (n_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            menu = 0;
          }
        if (n_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду     
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 2) 
  {
    if (key_data == key_pressed_right)  //нажатие >>>
      {
        if (sys_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду 
            opornoe = opornoe + 0.01;
            if (opornoe < 0.98) 
              {
                opornoe = 1.20;
              }
            if (opornoe > 1.20) 
              {
                opornoe = 0.98;
              }
          }
        if (sys_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            puls++;
            if (puls < 1) 
              {
                puls = 30;
              }
            else if (puls > 30) 
              {
                puls = 1;
              }
          }
        if (sys_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            time_doza = 0;//сброс накопленной дозы
            doz_v = 0;//сброс накопленной дозы
            eeprom_wrD ();
            myGLCD.clrScr();
            myGLCD.setFont(SmallFontRus);
            myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16);
            myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24);
            myGLCD.update();
            _delay_ms(1000);
          }
        if (sys_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
          }
        if (sys_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            batproc++;
            if (batproc > 2) {batproc = 0;}
          }
        if (sys_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            beta_time++;
            if (beta_time > 99) {beta_time = 1;}
          }
        if (sys_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (sys_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 1) 
  {
    if (key_data == key_pressed_left)  //нажатие <<<
      {
        if (n_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            treviga_1 = treviga_1 - 10;
            if (treviga_1<10) {treviga_1 = 100;}
            if (treviga_1>100) {treviga_1 = 100;}
          }
        if (n_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            treviga_2--;
            treviga_2 = constrain (treviga_2, 0, 6);
          }
        if (n_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            podsvetka = !podsvetka;
          }
        if (n_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            graph_type--;
            if (graph_type > 1) {graph_type = 1;}
          }
        if (n_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            scrin_GRAF--;
            if (scrin_GRAF < 1) 
              {
                scrin_GRAF = 10;
              }
          }
        if (n_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            ind_ON--; 
            ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4
          }
        if (n_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (n_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
if (menu == 2) 
  {
    
    if (sys_menu == 7) 
          {
         sys_menu_1 = 40;
         sys_menu_2 = 6;
          }
          else
          {
         sys_menu_1 = 0;
         sys_menu_2 = 0;
          }
    if (key_data == key_pressed_left)  //нажатие <<<
      {
        if (sys_menu == 0) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            opornoe = opornoe - 0.01;
            if (opornoe < 0.98) 
              {
                opornoe = 1.20;
              }
            else if (opornoe > 1.20) 
              {
                opornoe = 0.98;
              }
          }
        if (sys_menu == 1) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            puls--;
            if (puls < 1) 
              {
                puls = 30;
              }
            else if (puls > 30) 
              {
                puls = 1;
              }
          }
        if (sys_menu == 2) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            time_doza = 0;//сброс накопленной дозы
            doz_v = 0;//сброс накопленной дозы
            eeprom_wrD ();
            myGLCD.clrScr();
            myGLCD.setFont(SmallFontRus);
            myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16);
            myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24);
            myGLCD.update();
            _delay_ms(1000);
          }
        if (sys_menu == 3) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
          }
        if (sys_menu == 4) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            batproc--;
            if (batproc > 2) {batproc = 2;}
          }
        if (sys_menu == 5) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            beta_time--;
            if (beta_time > 99) {beta_time = 99;}
            if (beta_time < 1) {beta_time = 99;}
          }
        if (sys_menu == 6) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            menu = 0;
          }
        if (sys_menu == 7) 
          {
            key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
            eeprom_wrS ();
            menu = 0;
          }
      }
  }
//------------------------------------------------------------------------------------------------------------------  
if (alarm_sound && (millis() - lcd_milis >= 300)) //если поднят флаг аварийного сигнала (плюс попользуемся интервалом обновления экрана)
  {
    periodical_alarm_variable++; 
    if (periodical_alarm_variable >= 4) {periodical_alarm_variable = 1;} // держим переменную в пределах
    PORTB |= (1 << 0); //включаем вибру
    if (periodical_alarm_variable  > 1 )
      {
        PORTB &= ~(1 << 0); // выключаем вибру  
      }
    if  (periodical_alarm_variable  < 3) // периодичный звук тревоги
      {
        #ifdef buzzer_active //если задефайнен активный бузер
        PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
        #else //пассивный
        tone (6, 500); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
        #endif
      }
    else 
      {
        #ifdef buzzer_active   //если задефайнен активный бузер
        PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
        #else //пассивный бузер
        noTone (6); //выключаем писк на 6й ноге
        #endif 
      }
  if ((millis() - alarm_milis) > 3000) // проверяем, не истекло ли время подачи сигнала тревоги
    {
      PORTB &= ~(1 << 0); // выключаем вибру
      periodical_alarm_variable = 0; // обнуляем переменную
      #ifdef buzzer_active   //если задефайнен активный бузер
      PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
      #else //пассивный бузер
      noTone (6); //выключаем писк на 6й ноге
      #endif 
      alarm_sound = 0; // сбрасываем флаг сигнала тревоги
    }
  }
//------------------------------------------------------------------------------------------------------------------
if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
    res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------------------------------------------------
void lcd_poisk() 
{//вывод на дисплей режима поиск
if (fon_254 < treviga_1) //проверяем тревогу
  {
    tr = 0;
  }
if (fon_254 > treviga_1) //проверяем тревогу
  {
    check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
switch (treviga_2) //проверяем, какое значение выбрано
      {
        case 0: 
          tr = 0;tr2 = 0;
          break;  
        case 1: 
          if (shet > 100 || fon > 100) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 2: 
          if (shet > 250 || fon > 250) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 3: 
          if (shet > 500 || fon > 500) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 4: 
          if (shet > 1000 || fon > 1000) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 5: 
          if (shet > 5000 || fon > 5000) {tr2 = 1;} else {tr2 = 0;}
          break;
        case 6: 
          if (shet > 10000 || fon > 10000) {tr2 = 1;} else {tr2 = 0;}
          break;
      }
  
myGLCD.clrScr();
myGLCD.drawBitmap(0, 0, fon_poisk, 84, 48);
myGLCD.setFont(SmallFontRus);
myGLCD.drawLine(1, 21, zam_poisk_counter * 0.1 + 1, 21);
myGLCD.drawLine(1, 22, zam_poisk_counter * 0.1 + 1.4, 22);
myGLCD.drawLine(1, 23, zam_poisk_counter * 0.1 + 0.6, 23);
if (fon_254 > 0) {
myGLCD.setFont(TinyFontRus);
if ((tr == 1) && blink_data) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);}
if (fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);}
else if (fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);}
else if (fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);}
else if (fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);}
else if (fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);}
else {myGLCD.printNumI(fon_254, 2, 8);};
}
 
if (overflow_alarm && !blink_data) {myGLCD.drawBitmap(27, 7, em_logo, 37, 17);overflow_alarm = 0;}

else if ((zam_poisk_counter >= geiger_counter_seconds) || blink_data)
  {
    myGLCD.setFont(MediumNumbers);
if (fon <= 9){myGLCD.printNumI(fon, 52, 7);}
else if (fon <= 99){myGLCD.printNumI(fon, 40, 7);}
else if (fon <= 999){myGLCD.printNumI(fon, 28, 7);}
else if (fon <= 9999){myGLCD.printNumI(fon / 1000, 52, 7);}
else if (fon <= 99999){myGLCD.printNumI(fon / 1000, 40, 7);}
else{myGLCD.printNumI(fon / 1000, 28, 7);}
  }





if (fon < 1000) {myGLCD.drawBitmap(66, 8, mkr, 16, 15);} else {myGLCD.drawBitmap(66, 8, mr, 16, 15);}

time_d ();
myGLCD.setFont(TinyFontRus);
ind_doze_time();  //вывод времени накопления дозы на дисплей    
myGLCD.setFont(SmallFontRus);
if (doz_v < 1000) 
  {
    if (doz_v < 100)
      {
        myGLCD.printNumF(doz_v, 1, 41, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41);
      }
    else
      {
        myGLCD.printNumF(doz_v, 1, 34, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41);
      }    
  }
if (doz_v >= 1000) 
  {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 41); myGLCD.print(utf8rus("мР"), RIGHT, 41);
  }

battery();
if (graph_type == 0)
  {
  for (uint8_t i = 0; i < 84; i ++)  //печатаем график
    {
      uint8_t max_pixel = map(mass_p[i], 0, GRAPH_max, 0, 15);
      myGLCD.drawLine(i + 0, 39, i + 0, 39 - max_pixel);
    }
  }
else if (graph_type == 1)
  {
  for (int i = 0; i < 84; i ++)  //печатаем график
    {
    if (mass_p[i] > 0) 
      {
        if (mass_p[i] <= 15) 
          {
            myGLCD.drawLine(i + 0, 39, i + 0, 39 - mass_p[i]);
          }
        if (mass_p[i] > 15) 
          {
            myGLCD.drawLine(i + 0, 39, i + 0, 39 - 15);
          }
      }
    }
  }

//------------------------------------------ Синалка 2 сработала ------------------------------------------------
if (tr2 == 1)
  {
           overflow_alarm = 1;
           #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
            }
          #else //пассивный бузер
            {
              if (blink_data){tone (6,1000,1000);} else {tone (6,3000,1000);}
            }
          #endif 
  }
//------------------------------------------------------------------------------------------------------
myGLCD.update();
}


//-------------------------------------------------------------------------------------------------------
void lcd_menu()  //вывод на дисплей меню
{
myGLCD.clrScr();
myGLCD.setFont(TinyFontRus);
myGLCD.print(utf8rus("ПОРОГ 1"), 5, 0); myGLCD.printNumI(treviga_1, 52, 0); myGLCD.print("\xBC\xBD\xBE\xBF", RIGHT, 0);
myGLCD.print(utf8rus("СИГНАЛКА"), 5, 6); //пункт меню выбора индикации частиц
switch (treviga_2)
  {
  case 0:
    myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 6); //сигналка выключена. Сигнализация Порог 1 тоже отключется.
    break;  
  case 1:
    myGLCD.print(utf8rus("100 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 100 мкр/ч
    break;  
  case 2:
    myGLCD.print(utf8rus("250 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 250 мкр/ч
    break;  
  case 3:
    myGLCD.print(utf8rus("500 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 500 мкр/ч
    break; 
  case 4:
    myGLCD.print(utf8rus("1 \xBC\xBE\xBF"), RIGHT, 6); // 1000 мкр/ч
    break; 
  case 5:
    myGLCD.print(utf8rus("5 \xBC\xBE\xBF"), RIGHT, 6); // 5000 мкр/ч
    break; 
  case 6:
    myGLCD.print(utf8rus("10 \xBC\xBE\xBF"), RIGHT, 6); // 10000 мкр/ч
    break; 
    default:
    myGLCD.print("err", RIGHT, 6); //  если значение не равно 1,2,3,4,5,6 или 0 - выводим ошибку 
  }
myGLCD.print(utf8rus("ПОДСВЕТКА"), 5, 12); 
if (podsvetka)  { myGLCD.print(utf8rus("ВКЛ."), RIGHT, 12); }
else  { myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 12);  }
myGLCD.print(utf8rus("ТИП ГРАФИКА"), 5, 18); if (graph_type) {myGLCD.print(utf8rus("НОВЫЙ"), RIGHT, 18);} else { myGLCD.print(utf8rus("СТАРЫЙ"), RIGHT, 18);} //
myGLCD.print(utf8rus("ОБН. ГРАФИКА"), 5, 24); myGLCD.printNumI(scrin_GRAF, 60, 24); myGLCD.print(utf8rus("СЕК."), RIGHT, 24);//
myGLCD.print(utf8rus("ИНДИКАЦИЯ"), 5, 30); //пункт меню выбора индикации частиц
switch (ind_ON)
  {
  case 0:
    myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 30); //индикация выключена
    break;  
  case 1:
    myGLCD.print(utf8rus("ЗВУК"), RIGHT, 30); //индикация звуком
    break;  
  case 2:
    myGLCD.print(utf8rus("СВЕТ"), RIGHT, 30); //индикация светом
    break;  
  case 3:
    myGLCD.print(utf8rus("ЗВУК+СВЕТ"), RIGHT, 30); //индикация звуком и светом
    break; 
  case 4:
    myGLCD.print(utf8rus("ВИБРО"), RIGHT, 30); //индикация вибрацией
    break; 
    default:
    myGLCD.print("err", RIGHT, 30); //  если значение не равно 1,2,3 или 0 - выводим ошибку 
  }
myGLCD.print(utf8rus("ВЫХОД"), 5, 36);
myGLCD.print(utf8rus("СОХРАНИТЬ"), 5, 42);
myGLCD.print(">", 0, n_menu * 6);
myGLCD.update();
}
//----------------------------------------------------------------------------------------------------------------------
void lcd_sys()  //вывод на дисплей меню
{
VCC_read();
speed_nakachka ();//скорость накачки имлульсы/сек
myGLCD.clrScr();
myGLCD.setFont(TinyFontRus);
myGLCD.print(utf8rus("ОПОРН."), 5, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 53, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
myGLCD.print(utf8rus("НАКАЧКА"), 5, 6); myGLCD.printNumI(puls, 55, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
myGLCD.print(utf8rus("СБРОС ДОЗЫ"), 5, 12); 
myGLCD.print(utf8rus("----"), 5, 18);
if (batproc == 0)  { myGLCD.print(utf8rus("БАТ. "), 5, 24);myGLCD.print(utf8rus("БЕЗ ИНДИКАЦИИ"), RIGHT, 24); }  
if (batproc == 1)  { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("ПРОЦЕНТАМИ"), RIGHT, 24); }
if (batproc == 2)  { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("НАПРЯЖЕНИЕМ"), RIGHT, 24);  }
myGLCD.print(utf8rus("БЕТА"), 5, 30); myGLCD.printNumI(beta_time, 50, 30); myGLCD.print(utf8rus("МИНУТ"), RIGHT, 30);
myGLCD.print(utf8rus("ВЫХОД"), 5, 36);
myGLCD.print(utf8rus("СОХРАНИТЬ"), RIGHT, 36);
myGLCD.print(">",sys_menu_1 + 0, sys_menu * 6 - sys_menu_2);
myGLCD.print(utf8rus("СКОРОСТЬ"), 5, 43); myGLCD.printNumI(speed_nak, 40, 43); myGLCD.print(utf8rus("ИМП/СЕК"), RIGHT, 43);
myGLCD.update();
}
//---------------------------------------------------------------------------------------------------------------------
void zamer_beta() 
{// замер бета или продуктов
if (gotovo == 0) 
  {
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
      {
        res_first_alarm(); //сбрасываем сигнал тревоги
      }
    myGLCD.clrScr();
    myGLCD.setFont(TinyFontRus);
    if (bet_z == 0)
      {
        myGLCD.drawBitmap(0, 0, beta_prev_1, 84, 48);
      }
    else if (bet_z == 1)
      {
        myGLCD.drawBitmap(0, 0, beta_prev_2, 84, 48); 
      }
myGLCD.setFont(SmallFontRus);
myGLCD.print(utf8rus("НАЖМИТЕ OK"), CENTER, 36);
myGLCD.update();
  }  
if (gotovo == 1) 
  {
    if (timer_seconds != beta_seconds) 
      {
        beta_seconds = timer_seconds;
        sek++;
        toch = !toch;
        if (sek >= 60) 
          {
            sek = 0;
            minute++;
          }
      } 

    myGLCD.clrScr();
    myGLCD.drawBitmap(0, 0, beta_fon, 84, 48);
    battery();
if  (bet_z < 2) //таймер выводим только пока идёт первый или второй замер
  {
  myGLCD.setFont(SmallFontRus);
  if (toch == 0) 
    {
      myGLCD.drawBitmap(41, 33, bs, 0, 0);
    }
  else 
    {
      myGLCD.drawBitmap(41, 33, bs, 3, 9);
    } 
  myGLCD.setFont(MediumNumbers);
  if ((beta_time - minute -1) >= 0) {
  if ((beta_time - minute -1) <= 9) 
    {
      myGLCD.print("0", 12, 29);
      myGLCD.printNumI((beta_time - minute -1), 24, 29);  
    }
  else
    {
      myGLCD.printNumI((beta_time - minute -1), 12, 29);
    }
  }
  else
  {
      myGLCD.print("0", 12, 29);myGLCD.print("0", 24, 29);
  }
  byte sektemp = 0;
  if (sek == 0) 
  {
  sektemp = 60;
  }
  else
  {
  sektemp = sek;
  }
  
  if (((60 - sek) <= 9) || (sektemp == 60)) 
    {
      myGLCD.print("0", 49, 29);
      myGLCD.printNumI((60 - sektemp), 61, 29); 
    }
  else
    {
      myGLCD.printNumI((60 - sektemp), 49, 29); 
    }   
  }



//myGLCD.setFont(MediumNumbers);
//myGLCD.printNumI(0, 10 + otsup, 0);
//myGLCD.printNumI(sek, 10 + otsup + 4, 0);


    if (bet_z < 2) {myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ИДЕТ ЗАМЕР"), 0, 0); myGLCD.printNumI(bet_z, 44, 0);}
    if (bet_z == 0 && blink_data) 
    {
       myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z0, 2, 19);
    }
    if (bet_z == 1) 
    {
       myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z0, 2, 19); 
       if (blink_data) {myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z1, 44, 19);}
    }
    if (bet_z == 2) 
    {
      myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z0, 2, 19); myGLCD.printNumI(bet_z1, 44, 19);
      myGLCD.setFont(MediumNumbers);myGLCD.printNumI(bet_r, CENTER, 29); 
      myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ИТОГО"), 0, 0); myGLCD.print(utf8rus("\xBC\xBD\xBE\xBF"), 26, 0);
    }
    myGLCD.update();
    if (bet_z == 0)  //первый замер
    {
      bet_z0 = bet_z0 + shet;
      shet = 0;
      if (minute >= beta_time) 
        {
          bet_z = 1;
          sek = 0;
          minute = 0;
          gotovo = 0; 
          tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге
        }
    }
    if (bet_z == 1)  //второй замер
  {
    bet_z1 = bet_z1 + shet;
    shet = 0;
    if (minute >= beta_time) 
      {
        bet_z = 2;
        sek = 0;
        minute = 0;
        tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге    
      }
    }
    if (bet_z == 2)  //результат
    {
      bet_r = bet_z1 - bet_z0;
//      bet_r = bet_r / (1.5 * beta_time);
      bet_r = bet_r / ((60.0/(float)geiger_counter_seconds) * (float)beta_time);
      if (bet_r < 0) {bet_r = 0;} // если результат отрицательный - выводим 0. Можно оставить вывод отрицательного результата, закомментировав данную строчку.
    }
  }
if (key_data == key_pressed_right)  //нажатие >>>
  {
    key_data = 0;  // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду
    menu = 0;
    clear_poisk_variables();
  }
}
//-------------------------------------------------------------------------------------------------------------
void poisk_f() //режим поиска
{
int16_t shet_gr = 0;
if (poisk == 1) 
  {
    if (timer_seconds != count_and_dose_seconds) 
      {
        count_and_dose_seconds = timer_seconds;
          for (int i = 0; i < 254; i++)  //сдвигаем
          {
            mass_poisk[i] = mass_poisk[i + 1];
          }
        mass_poisk[254] = shet;
        if ((zam_poisk_counter < 254) && (zam_poisk_counter < geiger_counter_seconds))  //первый набор массива
          {
            fon_vr_poisk = fon_vr_poisk + shet;             
            zam_poisk_counter++;
            fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); 
//            fon_254 = fon;
            fon_254 = 0;
          }
        else if ((zam_poisk_counter < 254) && (zam_poisk_counter == geiger_counter_seconds))  //
          {   
            zam_poisk_counter++;
            fon_vr_poisk = fon_vr_poisk + shet; 
            fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter)));
            fon_254 = fon;    
            fon_vr254 = fon_vr_poisk;
          }
        else if ((zam_poisk_counter < 254) && (zam_poisk_counter > geiger_counter_seconds))  //
          {
            fon_vr_poisk = 0;
            fon_vr254 = 0;
            for (int i = zam_poisk_counter; i > 0; i--) 
              {
                fon_vr254 = fon_vr254 + mass_poisk[254-i];
              }
            for (int j = 254 - geiger_counter_seconds; j < 255; j++) 
              { 
                fon_vr_poisk = fon_vr_poisk + mass_poisk[j];
              }
            fon = fon_vr_poisk;
//            fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/(float(zam_poisk_counter)));
            fon_254 = (float)fon_vr254*((float)geiger_counter_seconds/(float)zam_poisk_counter); 
            fon_vr254 = 0;
            zam_poisk_counter++;
          } 
        else if (zam_poisk_counter >= 254)  //набор массива
          {
            fon_vr_poisk = 0;
            fon_vr254 = 0;
            byte geiger_counter_seconds_reverse = 254 - geiger_counter_seconds;
            for (int i = 254; i > 0; i--) 
              {
                fon_vr254 = fon_vr254 + mass_poisk[i];
                if (i > geiger_counter_seconds_reverse)
                  {
                    fon_vr_poisk = fon_vr_poisk + mass_poisk[i];
                  }
              }
            fon = fon_vr_poisk;
            fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/254.0);
          }
        shet = 0;
        doz_v = doz_v + fon / 100.0 / 36.0;
        time_doza = time_doza + 1;
        if (doz_v - doza_vr >= save_DOZ)  //а не пора ли сохранить дозу ?
          {
            eeprom_wrD ();
            doza_vr = doz_v;
          }
//Serial.print(" zam_poisk_counter=");
//Serial.println(zam_poisk_counter);            
      }
    if (millis() - gr_milis >= scrin_GRAF * 1000) //счет для графика
      {
      gr_milis = millis();
      if (graph_type == 0)
        {
        val_ok = 0;//сброс удержания системного меню  
        for (uint8_t s = 254; s >= (255 - scrin_GRAF); s--) 
          {
            shet_gr = shet_gr + mass_poisk[s];
          }
        shet_gr = shet_gr / scrin_GRAF;
        for (int i = 0; i < 83; i++) // сдвигаем массив графика
          {
            mass_p[i] = mass_p[i + 1];
          }
        mass_p[82] = byte(shet_gr);
        if (GRAPH_count > 82) 
          {
            GRAPH_max = 5; 
            GRAPH_count = 0;
          }   
        for (int i = 0; i < 82; i++) 
          {
            if (mass_p[i] > GRAPH_max)
              {
                GRAPH_max = mass_p[i];
                GRAPH_count = 0;
              }
          }
        GRAPH_count++;     
        }
      if (graph_type == 1)
        {
          val_ok = 0;//сброс удержания системного меню
          shet_gr = shet - shet_n;
          if (shet_gr < 0) 
            {
              shet_gr = 1;
            }
          shet_n = shet;
          for (int i = 0; i < 83; i++) 
            {
              mass_p[i] = mass_p[i + 1];
            }
          mass_p[82] = byte(shet_gr);
            
        
        }       
      }
  }
}
//----------------------------------------------------------------------------------------------------------------

void clear_poisk_variables ()
{
shet = 0;
fon = 0;
fon_254 = 0;
zam_poisk_counter = 0;
GRAPH_max = 5;
GRAPH_count = 0;
fon_vr254 = 0;
fon_vr_poisk = 0;
for (uint8_t i = 0; i < 84; i++) { mass_p[i] = 0; } // чистим массив графика
for (uint8_t i = 0; i < 254; i++) { mass_poisk[i] = 0; } // чистим массив поиска  
}

void signa ()  //индикация каждой частички звуком светом
{
shet_s = shet;  
if (!alarm_sound && tr2 == 0) //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
    {
    if (!shet_s) {return;} //если залетели в функцию signa() при обнулении переменной shet_s - просто возвращаемся в точку вызова. Детальнее здесь: arduino.ru/forum/proekty/delaem-dozimetr?page=16#comment-318736
    switch (ind_ON) //проверяем, какой тип индикации выбран
      {
        case 0: //индикация выключена
          break;  
        case 1: //индикация звуком
          #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
            }
          #else //пассивный бузер
            {
              tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге
            }
          #endif 
          break;  
        case 2: //индикация светом
          PORTB |= (1 << 5); //включаем светодиод
          delay(del_BUZZ); //длительность одиночного сигнала
          PORTB &= ~(1 << 5); //выключаем светодиод
          break;
  
        case 3: //индикация звуком и светом
          #ifdef buzzer_active //если задефайнен активный бузер
            {
              PORTB |= (1 << 5); //включаем светодиод
              PORTD |= (1 << 6); //включаем бузер 
              delay(del_BUZZ); //длительность одиночного сигнала
              PORTD &= ~(1 << 6); //выключаем бузер 
              PORTB &= ~(1 << 5); //выключаем светодиод
            }
          #else //пассивный бузер
            {
              PORTB |= (1 << 5); //включаем светодиод
              tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге
              delay(del_BUZZ);//длительность одиночного сигнала
              PORTB &= ~(1 << 5);//выключаем светодиод
            }
          #endif 
          break; 
        case 4: // индикация вибрацией
          PORTB |= (1 << 0); //включаем вибру
          delay(del_BUZZ); //длительность одиночного сигнала
          PORTB &= ~(1 << 0); // выключаем вибру      
      } 
    }
else // если активен сигнал тревоги, то только мигаем светодиодом (независимо от того, включён или нет светодиод в меню)
  {
      PORTB |= (1 << 5); //включаем светодиод
    delay(del_BUZZ);
    PORTB &= ~(1 << 5);//выключаем светодиод
  }
}
//-------------------------------------------------------------------------------------------------
void Schet()  //прерывание от счетчика на пин 2
{
shet++;
if (shet>250) {overflow_alarm = 1;} // детект приближения к переполнению переменной
}
//-------------------------------------------------------------------------------------------------
void generator() //накачка по обратной связи с АЦП
{
hv_adc  = Read_HV();
if (hv_adc < ADC_value)  //Значение АЦП при котором на выходе 400В
  {
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) 
      {
        asm("nop");
        c--;
      }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//--------------------------------------------------------------------------------------------------
byte Read_HV () 
{
ADCSRA = 0b11100111;
#ifdef UNO_DIP //если при компилляции выбрана плата ArduinoUNO
ADMUX = 0b11100101;//выбор внутреннего опорного 1,1В и А5 
#else // если используется промини, нано или голый камень в tqfp
ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
#endif  
for (int i = 0; i < 10; i++) 
  {
    while ((ADCSRA & 0x10) == 0);
    ADCSRA |= 0x10;
  }
result = 0;
for (int i = 0; i < 10; i++) 
  {
    while ((ADCSRA & 0x10) == 0);
    ADCSRA |= 0x10;
    result += ADCH;
  }
result /= 10;
return result;
}
//----------------------------------------------------------------------------------------------------
void battery()  //батарейка
{
if (bat_mill - millis() > 2000) 
  {
    bat_mill = millis();
    VCC_read();
  }
myGLCD.setFont(TinyFontRus);
byte batprocent = 99;
batprocent = ((VCC - batnapruga) * 100 / (batmax - batnapruga));
byte batline = 9; //Задаем длину линии батареи
batline = 0.1 * ((VCC - batnapruga) * 100 / (batmax - batnapruga)); //Зависимость длинны в пикселях от процента заряда

if (batproc == 1 && VCC < batusb && batprocent < 100) {myGLCD.printNumF(batprocent, 0, 58, 0);myGLCD.print("%", 66, 0);} // процент заряда
if (batproc == 2) {myGLCD.printNumF(VCC, 2, 54, 0);} // процент заряда
      if (batprocent > 5 && (VCC - batnapruga) > 0.01) //Проверяем процентный заряд акб 0.05 - 5%
        {
          if (VCC > batusb)
          {
  myGLCD.drawBitmap(71, 0, logo_bat_usb, 13, 5);
          }
            else
          {
  myGLCD.drawBitmap(71, 0, logo_bat, 13, 5);
  if (batprocent >= 100) {batline = 9;};
  myGLCD.drawBitmap(82 - batline, 1, logo_bat_line, batline + 1, 3);
          }
        }
      else //Если заряд меньше 5% мигаем пустой батарейкой
        {
          toch = !toch;
          if (toch == 0) 
          {
            myGLCD.drawBitmap(71, 0, logo_bat, 13, 5);
          }
          else 
          {
            myGLCD.drawBitmap(71, 0, logo_bat, 0, 0);
          } 
        }
}
//----------------------------------------------------------------------------------------------------
void VCC_read()  // Чтение напряжения батареи
{
ADCSRA = 0b11100111;
ADMUX = 0b01101110;//Выбор внешнего опорного+BG
_delay_ms(5);
while ((ADCSRA & 0x10) == 0);
ADCSRA |= 0x10;
byte resu = ADCH;
//ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
VCC = (opornoe * 255.0) / resu;
}
//----------------------------------------------------------------------------------------------------
void lcd_init() 
{
myGLCD.InitLCD();
myGLCD.setContrast(contrast);
myGLCD.clrScr();
myGLCD.drawBitmap(0, 0, logo_rag, 84, 48);
//myGLCD.setFont(SmallFontRus);
//  myGLCD.print(utf8rus("Ардуино+"), CENTER, 32);
//  myGLCD.print(utf8rus("Дозиметр v1.07"), CENTER, 40);
myGLCD.update();
_delay_ms(1000);
}
//----------------------------------------------------------------------------------------------------
void eeprom_wrS ()  //запись настроек в память
{
  EEPROM.write(0, 222);
  EEPROM.write(1, treviga_1);
  EEPROM.write(2, podsvetka);
  EEPROM.write(3, graph_type);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, ind_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(100, batproc);
  EEPROM.write(17, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFontRus);
  myGLCD.print(utf8rus("Сохранено"), CENTER, 20);
  myGLCD.update();
  _delay_ms(1000);
}
//-----------------------------------------------------------------------------------------------------
void eeprom_wrD ()  //запись настроек в память время накопления дозы
{
  EEPROM.put(9, time_doza);
  EEPROM.put(13, doz_v);   
}
//-----------------------------------------------------------------------------------------------------
void eeprom_readD ()  //чтение настроек из памяти время накопления дозы
{
  EEPROM.get(9, time_doza);
  EEPROM.get(13, doz_v);   
}
//-----------------------------------------------------------------------------------------------------
void eeprom_readS ()  //чтение настроек из памяти
{
  if (EEPROM.read(0) == 222) 
  {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    graph_type = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    ind_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    batproc = EEPROM.read(100);
    beta_time = EEPROM.read(17);
  }
_delay_ms(11);
}
//------------------------------------------------------------------------------------------------------
void nakachka() //первая накачка
{
byte n = 0;
while (n < 30) 
  {
    PORTD |= (1 << 5);//дергаем пин
    int c = puls;
    while (c > 0) 
      {
        asm("nop");
        c--;
      }
    PORTD &= ~(1 << 5);//дергаем пин
    n++;
    _delay_us(100);
  }
}
//------------------------------------------------------------------------------------------------------
void speed_nakachka ()  //скорость накачки имлульсы/сек
{
if (millis() - spNAK_milis >= 1000) 
  {
    spNAK_milis = millis();
    speed_nak = speed_nakT;
    speed_nakT = 0;
  }
}
//------------------------------------------------------------------------------------------------------
void time_d() 
{
  MONTH = time_doza / 2592000;
  DAY = (time_doza / 86400) % 30 ;
  HOUR = (time_doza / 3600) % 24 ;
  MIN = (time_doza / 60) % 60;
}
//------------------------------------------------------------------------------------------------------
void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
  if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
    {
      alarm_sound = 1; // поднимаем флаг аварийного сигнала
      alarm_milis = millis(); // запоминаем время начала тревоги
    }
}
//------------------------------------------------------------------------------------------------------
void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
{
   alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   PORTB &= ~(1 << 0); // выключаем вибру
   periodical_alarm_variable = 0; // обнуляем переменную
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
}
//------------------------------------------------------------------------------------------------------
void ind_doze_time() //вывод времени накопления дозы на дисплей
{
  myGLCD.setFont(TinyFontRus);
  if (MONTH) // если есть месяцы
    {
      myGLCD.printNumI(MONTH, 0, 43);
      if(MONTH>99)
        {
          myGLCD.print("M", 13, 43);
        }
      else if (MONTH>9)
        {
          myGLCD.print("M", 9, 43);
        }
      else
        {
          myGLCD.print("M", 5, 43);
        }
    myGLCD.printNumI(DAY, 18, 43);
    if (DAY > 9) 
      {
        myGLCD.print("\xBB", 26, 43);
      }
    else
      {
        myGLCD.print("\xBB", 23, 43);
      } 
    }
  else if (DAY) // если нет месяцев, но есть дни
    {
      myGLCD.printNumI(DAY, 0, 43);
      if (DAY > 9) 
        {
          myGLCD.print("\xBB", 9, 43);
        }
      else
        {
          myGLCD.print("\xBB", 5, 43);
        }
      myGLCD.printNumI(HOUR, 18, 43);
      if (HOUR > 9) 
        {
          myGLCD.print("\xBA", 26, 43);
        }
      else 
        {
          myGLCD.print("\xBA", 23, 43);
        }
    }
  else // если нет дней
    {
      myGLCD.printNumI(HOUR, 0, 43);
      if (HOUR > 9) 
        {
          myGLCD.print("\xBA", 9, 43);
        }
      else
        {
          myGLCD.print("\xBA", 5, 43);
        }
      myGLCD.printNumI(MIN, 18, 43);
      if (MIN > 9) 
        {
          myGLCD.print("\xBC", 26, 43);
        }
      else
        {
          myGLCD.print("\xBC", 23, 43);
        }
    }   

}
//--------------------------------------------------------------------------------------------------------
byte get_key() // Функция определения нажатия и удержания кнопок
{
// версия 1 - для кратковременного нажатия значение возвращается при отпускании кнопки, для длительного - пока кнопка остаётся нажатой, с заданным интервалом
uint8_t trigger_push_hold_counter = 10; // задержка триггера кратковременного/длительного нажатия (проходов функции, умноженных на задержку "milliseconds_between_increment")  
uint8_t milliseconds_between_increment = 50; // интервал в миллисекундах между инкрементом счётчика нажатой кнопки 
static uint8_t val_kp, val_kl, val_ok;
static uint32_t key_delay_millis;
static uint32_t key_delay_after_hold_millis;
if ((millis() - key_delay_millis) > milliseconds_between_increment) //обрабатываем нажатия инкрементом переменной только если после предыдущей обработки прошло не менее "milliseconds_between_increment" миллисекунд
  {
    if (!(PIND & (1 << PIND4)))  //нажатие >>>
    {
    val_kp++;  // инкрементируем счётчик
    if (val_kp > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши 
      {
       val_kp = 0; // сбрасываем счётчик 
       key_delay_after_hold_millis = millis(); // запоминаем время
       return key_holded_right; // возвращаем значение
      }
    }
    if (!(PIND & (1 << PIND7)))  //нажатие <<<
    {
    val_kl++;  // инкрементируем счётчик
    if (val_kl > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши
      {
        val_kl = 0; // сбрасываем счётчик
        key_delay_after_hold_millis = millis(); // запоминаем время 
        return key_holded_left; // возвращаем значение
      }   
    }
    if (!(PIND & (1 << PIND3)))  //нажатие OK
    {
    val_ok++; // инкрементируем счётчик
    if (val_ok > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши
      {
        val_ok = 0; // сбрасываем счётчик
        key_delay_after_hold_millis = millis(); // запоминаем время 
        return key_holded_ok; // возвращаем значение
      }       
    }
    key_delay_millis = millis(); // запоминаем время 
  }
if (val_ok > 0) //если клавиша OK перед этим была нажата 
  {
     if ((PIND & (1 << PIND3)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_ok = 0;  // сбрасываем счётчик
        return key_pressed_ok; // возвращаем значение
      }
  }
if (val_kp > 0) //если клавиша >>> перед этим была нажата 
  {
    if ((PIND & (1 << PIND4)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_kp = 0;  // сбрасываем счётчик 
        return key_pressed_right; // возвращаем значение
      }
  }
if (val_kl > 0) //если клавиша <<< перед этим была нажата 
  {
    if ((PIND & (1 << PIND7)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши
      {
        val_kl = 0;  // сбрасываем счётчик  
        return key_pressed_left; // возвращаем значение
      }
  }
if (PIND & (1 << PIND4)) {val_kp = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
if (PIND & (1 << PIND7)) {val_kl = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
if (PIND & (1 << PIND3)) {val_ok = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded")
return 0; // если ни одна из кнопок не была нажата - возвращаем 0
}
//------------------------------------------------------------------------------------------------------------------------------
char *utf8rus(char *source) // функция преобразования utf8 для вывода кириллицы (by arduinec)
{
  int i,j,k;
  unsigned char n;
  char m[2] = { '0', '\0' };

  strcpy(target, ""); k = strlen(source); i = j = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }

    m[0] = n; strcat(target, m);
    j++; if (j >= maxString) break;
  }
  return target;
}

ISR (TIMER1_OVF_vect) // прерывание по таймеру, генерируемое каждую секунду
{ 
timer_seconds++ ; //инкремент переменной каждую секунду
if (timer_seconds > 59){timer_seconds = 0;}
}

// ________________ конец скетча, дальше можно не копировать _____________________



Графика

// файл gif.c
// должен находиться в папке со скетчем

#include <avr/pgmspace.h>
#ifndef fontdatatype
#define fontdatatype const uint8_t
#endif


const unsigned char PROGMEM logo_bat[] =
{0xe,0x1f,0x11,0x11,
0x11,0x11,0x11,0x11,
0x11,0x11,0x11,0x11,
0x1f};
 
const unsigned char PROGMEM logo_bat_line[] =
{0x7,0x7,0x7,0x7,
0x7,0x7,0x7,0x7,
0x7,0x7};

const unsigned char PROGMEM logo_bat_usb[] =
{0xf,0x10,0x10,0xf,
0x0,0x17,0x15,0x1d,
0x0,0x1f,0x15,0x15,
0xa
};
 
const unsigned char PROGMEM  logo_tr[] =
{ 0x0C, 0x12, 0x21, 0x0C, 0x00, 0x10, 0x28, 0x26, 0x61, 0x61, 0x26, 0x28,
  0x10, 0x00, 0x0C, 0x21, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};



const unsigned char PROGMEM  fon_poisk[] =
{0xc0,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0xc0,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,
0x40,0x40,0x40,0xc0,
0xff,0x0,0x10,0x10,
0x10,0x0,0x10,0x10,
0x10,0x0,0xd0,0x50,
0x90,0x0,0x90,0x10,
0x10,0x0,0x10,0x10,
0x10,0x0,0x10,0x10,
0x10,0x0,0xff,0x0,
0x0,0x7e,0x3d,0x3,
0x3,0x3,0x3,0x3,
0x3,0x3d,0x7e,0x0,
0x0,0x7e,0x3d,0x3,
0x3,0x3,0x3,0x3,
0x3,0x3d,0x7e,0x0,
0x0,0x7e,0x3d,0x3,
0x3,0x3,0x3,0x3,
0x3,0x3d,0x7e,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0xff,
0xff,0x10,0x17,0x13,
0x17,0x10,0x17,0x12,
0x15,0x10,0x17,0x11,
0x14,0x13,0x10,0x13,
0x12,0x17,0x10,0x17,
0x13,0x17,0x10,0x17,
0x15,0x10,0xff,0x0,
0x0,0x3f,0x5e,0x60,
0x60,0x60,0x60,0x60,
0x60,0x5e,0x3f,0x0,
0x0,0x3f,0x5e,0x60,
0x60,0x60,0x60,0x60,
0x60,0x5e,0x3f,0x0,
0x0,0x3f,0x5e,0x60,
0x60,0x60,0x60,0x60,
0x60,0x5e,0x3f,0x0,
0x0,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x0,0xff,
0xff,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0xff,
0xff,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0xff,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0};
const unsigned char PROGMEM  mkr[] =
{0x7c,0x8,0x10,0x8,
0x7c,0x0,0x7c,0x10,
0x10,0x28,0x44,0x0,
0x7f,0x9,0x9,0x6,
0x1,0x1d,0x21,0x21,
0x7d,0x1,0x79,0x15,
0x15,0x79,0x1,0x39,
0x45,0x45,0x45,0x1};
const unsigned char PROGMEM  mr[] =
{0x0,0x0,0x7c,0x8,
0x10,0x8,0x7c,0x0,
0x0,0x7f,0x9,0x9,
0x6,0x0,0x0,0x0,
0x1,0x1d,0x21,0x21,
0x7d,0x1,0x79,0x15,
0x15,0x79,0x1,0x39,
0x45,0x45,0x45,0x1};
  
const unsigned char PROGMEM  em_logo[] =
{0x0,0x0,0x0,0x20,
0x30,0x38,0x98,0xd8,
0xf8,0xf0,0xf0,0xee,
0xce,0x8e,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0xe0,
0xc0,0x80,0x0,0x0,
0x0,0x0,0x18,0x18,
0x18,0x1c,0xf,0x87,
0xc7,0xef,0x7d,0x38,
0x10,0x1,0x3,0x3,
0x3,0x3,0x0,0x0,
0x7,0x7,0x7,0x7,
0x7,0x7,0x7,0x7,
0x7,0x7,0x7,0x7,
0x3f,0x1f,0xf,0x7,
0x2,0x0,0x0,0x0,
0x0,0x0,0x0,0x1,
0x1,0x1,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0};

const unsigned char PROGMEM logo_rag[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xF8, 0xF8,
  0xF8, 0xF8, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8,
  0xF8, 0xF8, 0x78, 0x78, 0x78, 0x78, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0,
  0xC0, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF8, 0x98, 0x18,
  0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0x9F, 0x81,
  0x81, 0x81, 0x9F, 0xFF, 0xFF, 0xFC, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFC, 0x1E, 0x0F, 0x0F, 0x0F, 0x06, 0x00, 0xFF, 0xFF,
  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xCF, 0xFF, 0xFF,
  0xFF, 0xFF, 0x00, 0xFC, 0xFF, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x36,
  0x78, 0x78, 0x78, 0x36, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF, 0xFC,
  0x00, 0xFC, 0xFE, 0xFF, 0xEF, 0xC7, 0xC7, 0x8F, 0x0F, 0x0E, 0x00, 0x00,
  0x00, 0x00, 0x00, 0xC0, 0xFC, 0xFF, 0xFF, 0xFF, 0x1F, 0x07, 0x07, 0x07,
  0x07, 0x07, 0x07, 0x07, 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0xC0, 0x00, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
  0xFF, 0xFF, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x7E, 0x7F, 0x3F, 0x3F,
  0x0F, 0x07, 0x00, 0x01, 0x0F, 0x1E, 0x38, 0x70, 0x60, 0xF0, 0xFE, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0x60, 0x70, 0x38, 0x1F, 0x07, 0x01,
  0x00, 0x79, 0xF9, 0xF1, 0xF3, 0xF7, 0xFF, 0xFF, 0x7F, 0x3E, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,
  0x00, 0x7C, 0x24, 0x24, 0x24, 0x18, 0x00, 0x60, 0x3C, 0x24, 0x3C, 0x60,
  0x00, 0x0C, 0x50, 0x50, 0x50, 0x3C, 0x00, 0x7C, 0x20, 0x10, 0x08, 0x7C,
  0x00, 0x7C, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38,
  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x60, 0x3E, 0x23, 0x3F, 0x60, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38,
  0x00, 0x28, 0x44, 0x54, 0x54, 0x28, 0x00, 0x7C, 0x20, 0x10, 0x08, 0x7C,
  0x00, 0x7C, 0x08, 0x10, 0x08, 0x7C, 0x00, 0x38, 0x54, 0x54, 0x54, 0x18,
  0x00, 0x04, 0x04, 0x7C, 0x04, 0x04, 0x00, 0x7C, 0x24, 0x24, 0x24, 0x18,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,
  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x36, 0x49, 0x49, 0x49, 0x36};


// заставка БЕТА режима первая
const unsigned char PROGMEM beta_prev_1[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x05,
  0x02, 0x00, 0x1F, 0x15, 0x11, 0x00, 0x1B, 0x1F, 0x1B, 0x00, 0x1F, 0x0C,
  0x1F, 0x00, 0x1F, 0x07, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x05,
  0x02, 0x00, 0x1E, 0x05, 0x1E, 0x00, 0x11, 0x15, 0x0A, 0x00, 0x1F, 0x04,
  0x1F, 0x00, 0x0E, 0x11, 0x0E, 0x00, 0x0E, 0x11, 0x0A, 0x00, 0x01, 0x1F,
  0x01, 0x00, 0x1F, 0x04, 0x1F, 0x00, 0x0E, 0x11, 0x0E, 0x00, 0x1F, 0x01,
  0x01, 0x00, 0x0E, 0x11, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x15, 0x0A, 0x00,
  0x1E, 0x05, 0x1E, 0x00, 0x1F, 0x07, 0x1F, 0x00, 0x1F, 0x15, 0x11, 0x00,
  0x1F, 0x05, 0x02, 0x00, 0x1E, 0x05, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x71, 0x41,
  0xF1, 0x01, 0xE1, 0x11, 0xA1, 0x01, 0x11, 0xF1, 0x11, 0x01, 0xE1, 0x51,
  0xE1, 0x01, 0xF1, 0x41, 0xF1, 0x01, 0xE1, 0x11, 0xE1, 0x01, 0xF1, 0x51,
  0xA1, 0x01, 0xF1, 0xC1, 0xF1, 0x01, 0x11, 0xF1, 0x11, 0x01, 0xF1, 0x51,
  0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0xF1, 0x11, 0xF1, 0x01, 0xF1, 0x51,
  0x21, 0x01, 0xF1, 0xC1, 0xF1, 0x01, 0xF1, 0x51, 0x91, 0x01, 0xE1, 0x11,
  0xE1, 0x01, 0xF1, 0x51, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x40, 0xF1, 0x01,
  0xE0, 0x50, 0xE0, 0x01, 0x00, 0x00, 0xF0, 0x11, 0xF0, 0x00, 0x71, 0x40,
  0xF1, 0x00, 0xE1, 0x10, 0xA1, 0x00, 0x10, 0xF1, 0x10, 0x00, 0x71, 0x41,
  0xF0, 0x00, 0xF1, 0xE0, 0x11, 0xE0, 0x00, 0x01, 0x00, 0xF0, 0x41, 0x91,
  0x01, 0xF0, 0xE0, 0x10, 0xE0, 0x00, 0xF1, 0x50, 0xA1, 0x00, 0xF1, 0x50,
  0x10, 0x00, 0x11, 0xF0, 0x11, 0x00, 0x71, 0x41, 0xF0, 0x00, 0x00, 0x01,
  0xF0, 0xC0, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
  0x01, 0xF0, 0x81, 0x80, 0x80, 0xF0, 0x01, 0xC0, 0x21, 0x10, 0x21, 0xC1,
  0x00, 0x70, 0x80, 0xE1, 0x80, 0x70, 0x00, 0xF1, 0x20, 0xC0, 0x21, 0xF1,
  0x00, 0xF0, 0x01, 0x80, 0x61, 0xF0, 0x00, 0x10, 0x10, 0xF1, 0x10, 0x11,
  0x00, 0xF1, 0x90, 0x91, 0x90, 0x10, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
  0x01, 0xE0, 0x10, 0x11, 0x10, 0xE0, 0x01, 0xF1, 0x80, 0x40, 0x20, 0x10,
  0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x01, 0x01, 0x01, 0x07,
  0x00, 0x07, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07,
  0x00, 0x07, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
  0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  
// заставка БЕТА режима вторая
const unsigned char PROGMEM beta_prev_2[] =

  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x11, 0x15, 0x0A, 0x00, 0x1E, 0x05, 0x1E, 0x00,
  0x1F, 0x07, 0x1F, 0x00, 0x1F, 0x15, 0x11, 0x00, 0x1F, 0x05, 0x02, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x0E, 0x00, 0x1F, 0x15, 0x1D, 0x00,
  0x1F, 0x05, 0x02, 0x00, 0x1E, 0x05, 0x1E, 0x00, 0x11, 0x15, 0x0A, 0x00,
  0x1F, 0x10, 0x1F, 0x30, 0x1E, 0x05, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, 0x51,
  0xA1, 0x01, 0xE1, 0x51, 0xE1, 0x01, 0xF1, 0x11, 0xF1, 0x01, 0xE1, 0x11,
  0xE1, 0x01, 0xE1, 0x11, 0xF1, 0x01, 0xF1, 0x41, 0xF1, 0x01, 0xF1, 0xC1,
  0xF1, 0x01, 0x11, 0xF1, 0x11, 0x01, 0xF1, 0x51, 0x11, 0x01, 0x01, 0x01,
  0x01, 0x01, 0xF1, 0x41, 0x91, 0x01, 0xF1, 0xE1, 0x11, 0xE1, 0x01, 0xF1,
  0x51, 0xA1, 0x01, 0xF1, 0x51, 0x11, 0x01, 0x11, 0xF1, 0x11, 0x01, 0x71,
  0x41, 0xF1, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
  0x00, 0x00, 0xF0, 0xC0, 0xF0, 0x00, 0x10, 0x50, 0xA0, 0x00, 0xF1, 0x71,
  0xF0, 0x00, 0xF1, 0x50, 0x11, 0x00, 0xF1, 0x50, 0x21, 0x00, 0xA0, 0x51,
  0xF0, 0x00, 0xF1, 0x50, 0x11, 0x00, 0xF1, 0x70, 0xF1, 0x00, 0xF1, 0x40,
  0x81, 0xF0, 0x00, 0xF1, 0x70, 0xF0, 0x01, 0x01, 0x01, 0x00, 0xF0, 0x50,
  0xA0, 0x00, 0xF1, 0x50, 0x11, 0x00, 0xF1, 0xC0, 0xF1, 0x00, 0xF0, 0x51,
  0x11, 0x00, 0xE0, 0x11, 0xA1, 0x01, 0x10, 0xF0, 0x11, 0x00, 0xF0, 0x51,
  0xA1, 0x00, 0xE0, 0x10, 0xE0, 0x00, 0xF0, 0x70, 0xF0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x71, 0x41, 0xF0, 0x00, 0xE1, 0x10,
  0xA1, 0x00, 0x11, 0xF1, 0x11, 0x00, 0xE1, 0x50, 0xE0, 0x00, 0xF1, 0x40,
  0xF1, 0x00, 0xE1, 0x11, 0xE1, 0x00, 0xF1, 0x50, 0xA1, 0x00, 0xF1, 0xC1,
  0xF0, 0x01, 0x10, 0xF1, 0x10, 0x01, 0xF0, 0x50, 0x10, 0x00, 0x01, 0x01,
  0x00, 0x00, 0xF1, 0x11, 0xF1, 0x00, 0xF1, 0x51, 0x23, 0x00, 0xF1, 0xC1,
  0xF1, 0x00, 0xF0, 0x51, 0xD0, 0x00, 0xE0, 0x11, 0xE0, 0x00, 0xF1, 0x51,
  0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF1, 0xC0, 0xF1, 0x00, 0x03, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01,
  0x00, 0xF0, 0x80, 0x81, 0x80, 0xF0, 0x01, 0xC0, 0x21, 0x10, 0x21, 0xC0,
  0x01, 0x70, 0x80, 0xE1, 0x80, 0x70, 0x01, 0xF1, 0x20, 0xC0, 0x21, 0xF0,
  0x01, 0xF0, 0x00, 0x81, 0x60, 0xF0, 0x01, 0x11, 0x11, 0xF0, 0x10, 0x10,
  0x00, 0xF0, 0x91, 0x90, 0x91, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x01, 0xE0, 0x11, 0x11, 0x11, 0xE0, 0x00, 0xF1, 0x80, 0x40, 0x21, 0x10,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x01, 0x01, 0x01, 0x07,
  0x00, 0x07, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07,
  0x00, 0x07, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
  0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

const unsigned char PROGMEM beta_fon[] =
{0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xc0,0xc0,0xc0,0xc0,
0xff,0xff,0xc1,0xae,
0xb6,0xba,0xc1,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xdd,0xb6,0xb6,0xa2,
0xc9,0xff,0xdf,0xab,
0xab,0xab,0x87,0xff,
0x83,0xf7,0xef,0xf7,
0x83,0xff,0xc7,0xab,
0xab,0xab,0xe7,0xff,
0x83,0xdb,0xdb,0xdb,
0xe7,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xbd,
0x80,0xbf,0xff,0xff,
0xff,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0xff,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0xff,
0xff,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x1f,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0xff,
0xff,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0xff,
0xff,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0xff};

const unsigned char PROGMEM bs[] =
{0xc7,0xc7,0xc7,0x1,
0x1,0x1};
//----------------------------------------------------------------------
// Секция шрифтов


// Font size    : 6x8 pixels
fontdatatype SmallFontRus[] PROGMEM={
0x06,0x08,0x20,0x5F,
0x00,0x00,0x00,0x00,0x00,0x00,  // <space>
0x00,0x00,0x00,0x2F,0x00,0x00,  // !
0x00,0x00,0x07,0x00,0x07,0x00,  // "
0x00,0x14,0x7F,0x14,0x7F,0x14,  // #
0x00,0x24,0x2A,0x7F,0x2A,0x12,  // $
0x00,0x23,0x13,0x08,0x64,0x62,  // %
0x00,0x36,0x49,0x55,0x22,0x50,  // &
0x00,0x00,0x05,0x03,0x00,0x00,  // '
0x00,0x00,0x1C,0x22,0x41,0x00,  // (
0x00,0x00,0x41,0x22,0x1C,0x00,  // )
0x00,0x14,0x08,0x3E,0x08,0x14,  // *
0x00,0x08,0x08,0x3E,0x08,0x08,  // +
0x00,0x00,0x00,0xA0,0x60,0x00,  // ,
0x00,0x08,0x08,0x08,0x08,0x08,  // -
0x00,0x00,0x60,0x60,0x00,0x00,  // .
0x00,0x20,0x10,0x08,0x04,0x02,  // /

0x00,0x3E,0x51,0x49,0x45,0x3E,  // 0
0x00,0x00,0x42,0x7F,0x40,0x00,  // 1
0x00,0x42,0x61,0x51,0x49,0x46,  // 2
0x00,0x21,0x41,0x45,0x4B,0x31,  // 3
0x00,0x18,0x14,0x12,0x7F,0x10,  // 4
0x00,0x27,0x45,0x45,0x45,0x39,  // 5
0x00,0x3C,0x4A,0x49,0x49,0x30,  // 6
0x00,0x01,0x71,0x09,0x05,0x03,  // 7
0x00,0x36,0x49,0x49,0x49,0x36,  // 8
0x00,0x06,0x49,0x49,0x29,0x1E,  // 9
0x00,0x00,0x36,0x36,0x00,0x00,  // :
0x00,0x00,0x56,0x36,0x00,0x00,  // ;
0x00,0x08,0x14,0x22,0x41,0x00,  // <
0x00,0x14,0x14,0x14,0x14,0x14,  // =
0x00,0x00,0x41,0x22,0x14,0x08,  // >
0x00,0x02,0x01,0x51,0x09,0x06,  // ?

0x00,0x32,0x49,0x59,0x51,0x3E,  // @
0x00,0x7C,0x12,0x11,0x12,0x7C,  // A
0x00,0x7F,0x49,0x49,0x49,0x36,  // B
0x00,0x3E,0x41,0x41,0x41,0x22,  // C
0x00,0x7F,0x41,0x41,0x22,0x1C,  // D
0x00,0x7F,0x49,0x49,0x49,0x41,  // E
0x00,0x7F,0x09,0x09,0x09,0x01,  // F
0x00,0x3E,0x41,0x49,0x49,0x7A,  // G
0x00,0x7F,0x08,0x08,0x08,0x7F,  // H
0x00,0x00,0x41,0x7F,0x41,0x00,  // I
0x00,0x20,0x40,0x41,0x3F,0x01,  // J
0x00,0x7F,0x08,0x14,0x22,0x41,  // K
0x00,0x7F,0x40,0x40,0x40,0x40,  // L
0x00,0x7F,0x02,0x0C,0x02,0x7F,  // M
0x00,0x7F,0x04,0x08,0x10,0x7F,  // N
0x00,0x3E,0x41,0x41,0x41,0x3E,  // O

0x00,0x7F,0x09,0x09,0x09,0x06,  // P
0x00,0x3E,0x41,0x51,0x21,0x5E,  // Q
0x00,0x7F,0x09,0x19,0x29,0x46,  // R
0x00,0x46,0x49,0x49,0x49,0x31,  // S
0x00,0x01,0x01,0x7F,0x01,0x01,  // T
0x00,0x3F,0x40,0x40,0x40,0x3F,  // U
0x00,0x1F,0x20,0x40,0x20,0x1F,  // V
0x00,0x3F,0x40,0x38,0x40,0x3F,  // W
0x00,0x63,0x14,0x08,0x14,0x63,  // X
0x00,0x07,0x08,0x70,0x08,0x07,  // Y
0x00,0x61,0x51,0x49,0x45,0x43,  // Z
0x00,0x00,0x7F,0x41,0x41,0x00,  // [
0xAA,0x55,0xAA,0x55,0xAA,0x55,  // <backslash>
0x00,0x00,0x41,0x41,0x7F,0x00,  // ]
0x00,0x04,0x02,0x01,0x02,0x04,  // ^
0x00,0x40,0x40,0x40,0x40,0x40,  // _

0x00,0x00,0x03,0x05,0x00,0x00,  // `
0x00,0x7C,0x12,0x11,0x12,0x7C,  // a
0x00,0x7F,0x49,0x49,0x49,0x36,  // b
0x00,0x7F,0x49,0x49,0x49,0x36,  // c
0x00,0x7F,0x01,0x01,0x01,0x01,  // d
0x00,0x60,0x3E,0x23,0x3F,0x60,  // e
0x00,0x7F,0x49,0x49,0x49,0x41,  // f
0x00,0x77,0x08,0x3E,0x08,0x77,  // g
0x00,0x22,0x49,0x49,0x5D,0x36,  // h
0x00,0x00,0x44,0x7D,0x40,0x00,  // i
0x00,0x40,0x80,0x84,0x7D,0x00,  // j
0x00,0x7F,0x10,0x28,0x44,0x00,  // k
0x00,0x00,0x41,0x7F,0x40,0x00,  // l
0x00,0x7C,0x04,0x18,0x04,0x78,  // m
0x00,0x7C,0x08,0x04,0x04,0x78,  // n
0x00,0x38,0x44,0x44,0x44,0x38,  // o

0x00,0xFC,0x24,0x24,0x24,0x18,  // p
0x00,0x18,0x24,0x24,0x18,0xFC,  // q
0x00,0x7C,0x08,0x04,0x04,0x08,  // r
0x00,0x48,0x54,0x54,0x54,0x20,  // s
0x00,0x04,0x3F,0x44,0x40,0x20,  // t
0x00,0x3C,0x40,0x40,0x20,0x7C,  // u
0x00,0x1C,0x20,0x40,0x20,0x1C,  // v
0x00,0x3C,0x40,0x30,0x40,0x3C,  // w
0x00,0x44,0x28,0x10,0x28,0x44,  // x
0x00,0x1C,0xA0,0xA0,0xA0,0x7C,  // y
0x00,0x44,0x64,0x54,0x4C,0x44,  // z
0x00,0x00,0x10,0x7C,0x82,0x00,  // {
0x00,0x00,0x00,0xFF,0x00,0x00,  // |
0x00,0x00,0x82,0x7C,0x10,0x00,  // }
0x00,0x00,0x06,0x09,0x09,0x06,  // ~
//-----------------------------------
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  //
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 

0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 

0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x7E,0x4B,0x4A,0x4B,0x42,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 

0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  //
0x00,0x00,0x00,0x00,0x00,0x20,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x38,0x55,0x54,0x55,0x58,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  //
0x00,0x00,0x00,0x00,0x00,0x00,  //
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 
0x00,0x00,0x00,0x00,0x00,0x00,  // 

0x00,0x00,0x03,0x05,0x00,0x00,  // 
0x00,0x7C,0x12,0x11,0x12,0x7C,  // 
0x00,0x7F,0x49,0x49,0x49,0x30,  // 
0x00,0x7F,0x49,0x49,0x49,0x36,  // 
0x00,0x7F,0x01,0x01,0x01,0x01,  // 
0x00,0x60,0x3E,0x23,0x3F,0x60,  // 
0x00,0x7F,0x49,0x49,0x49,0x41,  //
0x00,0x77,0x08,0x3E,0x08,0x77,  // 
0x00,0x22,0x49,0x49,0x5D,0x36,  // 
0x00,0x7F,0x30,0x08,0x06,0x7F,  // 
0x00,0x7F,0x30,0x19,0x0C,0x7F,  // 
0x00,0x7F,0x08,0x08,0x14,0x63,  // 
0x00,0x40,0x7E,0x01,0x01,0x7F,  // 
0x00,0x7F,0x02,0x0C,0x02,0x7F,  // 
0x00,0x7F,0x08,0x08,0x08,0x7F,  // 
0x00,0x3E,0x41,0x41,0x41,0x3E,  // 

0x00,0x7F,0x01,0x01,0x01,0x7F,  // 
0x00,0x7F,0x09,0x09,0x09,0x06,  // 
0x00,0x3E,0x41,0x41,0x41,0x22,  // 
0x00,0x01,0x01,0x7F,0x01,0x01,  // 
0x00,0x07,0x48,0x48,0x48,0x3F,  // 
0x00,0x0E,0x11,0x7F,0x11,0x0E,  // 
0x00,0x63,0x14,0x08,0x14,0x63,  // 
0x00,0x3F,0x20,0x20,0x3F,0x60,  // 
0x00,0x07,0x08,0x08,0x08,0x7F,  // 
0x00,0x7F,0x40,0x7E,0x40,0x7F,  // 
0x00,0x3F,0x20,0x3F,0x20,0x7F,  // 
0x40,0x01,0x7F,0x48,0x48,0x30,  // 
0x00,0x7F,0x48,0x30,0x00,0x7F,  // 
0x00,0x7F,0x48,0x48,0x30,0x00,  // 
0x41,0x49,0x49,0x49,0x3E,0x00,  // 
0x00,0x7F,0x08,0x3E,0x41,0x3E,
0x00,0x46,0x29,0x19,0x09,0x7F,
//-----------------------------------
//0x00,0x00,0x00,0x00,0x00,0x00,
//0x00,0x7C,0x10,0x7C,0x44,0x7C,
0x00,0x20,0x54,0x54,0x54,0x78,  // 
0x00,0x3C,0x4A,0x4A,0x4A,0x30,  // 
0x00,0x7C,0x54,0x54,0x54,0x28,  // 
0x00,0x7C,0x04,0x04,0x04,0x00,  // 
0x00,0x60,0x3C,0x24,0x3C,0x60,  // 
0x00,0x38,0x54,0x54,0x54,0x18,  // 
0x00,0x6C,0x10,0x7C,0x10,0x6C,  // 
0x00,0x28,0x44,0x54,0x54,0x28,  // 
0x00,0x7C,0x20,0x10,0x08,0x7C,  // 
0x00,0x7C,0x20,0x12,0x08,0x7C,  // 
0x00,0x7C,0x10,0x10,0x28,0x44,  // 
0x00,0x40,0x7C,0x04,0x04,0x7C,  // 
0x00,0x7C,0x08,0x10,0x08,0x7C,  // 
0x00,0x7C,0x10,0x10,0x10,0x7C,  // 
0x00,0x38,0x44,0x44,0x44,0x38,  // 

0x00,0x7C,0x04,0x04,0x04,0x7C,  // 
0x00,0x7C,0x24,0x24,0x24,0x18,  // 
0x00,0x38,0x44,0x44,0x44,0x28,  // 
0x00,0x04,0x04,0x7C,0x04,0x04,  // 
0x00,0x0C,0x50,0x50,0x50,0x3C,  // 
0x00,0x18,0x24,0x7C,0x24,0x18,  // 
0x00,0x44,0x28,0x10,0x28,0x44,  // 
0x00,0x3C,0x20,0x20,0x3C,0x60,  // 
0x00,0x1C,0x20,0x20,0x7C,0x00,  // 
0x00,0x7C,0x40,0x78,0x40,0x7C,  // 
0x00,0x3C,0x20,0x3C,0x20,0x7C,  // 
0x40,0x04,0x7C,0x50,0x50,0x20,  //
0x00,0x7C,0x50,0x70,0x00,0x7C,  // 
0x00,0x7C,0x50,0x50,0x20,0x00,  // 
0x44,0x54,0x54,0x54,0x38,0x00,  // 
0x00,0x7C,0x10,0x7C,0x44,0x7C,
0x00,0x48,0x54,0x34,0x14,0x7C,
};

/*
fontdatatype rus_4x6[] PROGMEM =
{
0x04, 0x08, 0xC0, 0x20,
0x00, 0x3c, 0x12, 0x3c,                        // Code for char А
0x00, 0x3E, 0x2A, 0x12,                        // Code for char Б
0x00, 0x3E, 0x2A, 0x14,                        // Code for char В
0x00, 0x3E, 0x02, 0x02,                        // Code for char Г
0x00, 0x30, 0x1E, 0x30,                        // Code for char Д
0x00, 0x3E, 0x2A, 0x22,                        // Code for char Е
0x00, 0x36, 0x3E, 0x36,                        // Code for char Ж
0x00, 0x22, 0x2A, 0x14,                        // Code for char З
0x00, 0x3E, 0x18, 0x3E,                        // Code for char И
0x00, 0x3E, 0x19, 0x3E,                        // Code for char Й
0x00, 0x3E, 0x08, 0x22,                        // Code for char К
0x00, 0x3C, 0x02, 0x3E,                        // Code for char Л
0x00, 0x3E, 0x0E, 0x3E,                        // Code for char М
0x00, 0x3E, 0x08, 0x3E,                        // Code for char Н
0x00, 0x1C, 0x22, 0x1C,                        // Code for char О
0x00, 0x3E, 0x02, 0x3E,                        // Code for char П
0x00, 0x3E, 0x0A, 0x04,                        // Code for char Р
0x00, 0x1C, 0x22, 0x14,                        // Code for char С
0x00, 0x02, 0x3E, 0x02,                        // Code for char Т
0x00, 0x06, 0x28, 0x1E,                        // Code for char У
0x00, 0x1C, 0x3E, 0x1C,                        // Code for char Ф
0x00, 0x36, 0x08, 0x36,                        // Code for char Х
0x00, 0x1E, 0x10, 0x2E,                        // Code for char Ц
0x00, 0x0E, 0x08, 0x3E,                        // Code for char Ч
0x00, 0x3E, 0x38, 0x3E,                        // Code for char Ш
0x00, 0x1E, 0x1C, 0x3E,                        // Code for char Щ
0x00, 0x3E, 0x28, 0x10,                        // Code for char Ъ
0x3E, 0x30, 0x00, 0x3E,                        // Code for char Ы
0x00, 0x3E, 0x28, 0x10,                        // Code for char Ь
0x00, 0x14, 0x2A, 0x1C,                        // Code for char Э
0x3E, 0x08, 0x3E, 0x3E,                        // Code for char Ю
0x00, 0x34, 0x0A, 0x3E,                        // Code for char Я
};
*/

fontdatatype TinyFontRus[] PROGMEM =
{
0x04, 0x06, 0x20, 0x5f,
0x00, 0x00, 0x00, 0x03, 0xa0, 0x00, 0xc0, 0x0c, 0x00, 0xf9, 0x4f, 0x80, 0x6b, 0xeb, 0x00, 0x98, 0x8c, 0x80, 0x52, 0xa5, 0x80, 0x03, 0x00, 0x00,  // Space, !"#$%&'
0x01, 0xc8, 0x80, 0x89, 0xc0, 0x00, 0x50, 0x85, 0x00, 0x21, 0xc2, 0x00, 0x08, 0x40, 0x00, 0x20, 0x82, 0x00, 0x00, 0x20, 0x00, 0x18, 0x8c, 0x00,  // ()*+,-./
0xfa, 0x2f, 0x80, 0x4b, 0xe0, 0x80, 0x5a, 0x66, 0x80, 0x8a, 0xa5, 0x00, 0xe0, 0x8f, 0x80, 0xea, 0xab, 0x00, 0x72, 0xa9, 0x00, 0x9a, 0x8c, 0x00,  // 01234567
0xfa, 0xaf, 0x80, 0x4a, 0xa7, 0x00, 0x01, 0x40, 0x00, 0x09, 0x40, 0x00, 0x21, 0x48, 0x80, 0x51, 0x45, 0x00, 0x89, 0x42, 0x00, 0x42, 0x66, 0x00,  // 89:;<=>?
0x72, 0xa6, 0x80, 0x7a, 0x87, 0x80, 0xfa, 0xa5, 0x00, 0x72, 0x25, 0x00, 0xfa, 0x27, 0x00, 0xfa, 0xa8, 0x80, 0xfa, 0x88, 0x00, 0x72, 0x2b, 0x00,  // @ABCDEFG
0xf8, 0x8f, 0x80, 0x8b, 0xe8, 0x80, 0x8b, 0xe8, 0x00, 0xf8, 0x8d, 0x80, 0xf8, 0x20, 0x80, 0xf9, 0x0f, 0x80, 0xf9, 0xcf, 0x80, 0x72, 0x27, 0x00,  // HIJKLMNO
0xfa, 0x84, 0x00, 0x72, 0x27, 0x40, 0xfa, 0x85, 0x80, 0x4a, 0xa9, 0x00, 0x83, 0xe8, 0x00, 0xf0, 0x2f, 0x00, 0xe0, 0x6e, 0x00, 0xf0, 0xef, 0x00,  // PQRSTUVW
0xd8, 0x8d, 0x80, 0xc0, 0xec, 0x00, 0x9a, 0xac, 0x80, 0x03, 0xe8, 0x80, 0xc0, 0x81, 0x80, 0x8b, 0xe0, 0x00, 0x42, 0x04, 0x00, 0x08, 0x20, 0x80,  // XYZ[\]^_
0x02, 0x04, 0x00, 0x31, 0x23, 0x80, 0xf9, 0x23, 0x00, 0x31, 0x24, 0x80, 0x31, 0x2f, 0x80, 0x31, 0x62, 0x80, 0x23, 0xea, 0x00, 0x25, 0x53, 0x80,  // `abcdefg
0xf9, 0x03, 0x80, 0x02, 0xe0, 0x00, 0x06, 0xe0, 0x00, 0xf8, 0x42, 0x80, 0x03, 0xe0, 0x00, 0x79, 0x87, 0x80, 0x39, 0x03, 0x80, 0x31, 0x23, 0x00,  // hijklmno
0x7d, 0x23, 0x00, 0x31, 0x27, 0xc0, 0x78, 0x84, 0x00, 0x29, 0x40, 0x00, 0x43, 0xe4, 0x00, 0x70, 0x27, 0x00, 0x60, 0x66, 0x00, 0x70, 0x67, 0x00,  // pqrstuvw
0x48, 0xc4, 0x80, 0x74, 0x57, 0x80, 0x59, 0xe6, 0x80, 0x23, 0xe8, 0x80, 0x03, 0x60, 0x00, 0x8b, 0xe2, 0x00, 0x61, 0x0c, 0x00,                     // zyx{|}~
0x00, 0x00, 0x1E, // Index: 95 (0x005F)  Character: 0x007F ('')
0x01, 0x07, 0x96, // Index: 96 (0x0060)  Character: 0x0080 ('?')
0x00, 0x07, 0x90, // Index: 97 (0x0061)  Character: 0x0081 ('?')
0x00, 0x30, 0x00, // Index: 98 (0x0062)  Character: 0x0082 ('?')
0x00, 0x00, 0x00, // Index: 99 (0x0063)  Character: 0x0083 ('?')
0x0C, 0x00, 0x00, // Index: 100 (0x0064)  Character: 0x0084 ('?')
0x00, 0x00, 0x00, // Index: 101 (0x0065)  Character: 0x0085 ('?')
0x00, 0x00, 0x00, // Index: 102 (0x0066)  Character: 0x0086 ('?')
0x00, 0x00, 0x00, // Index: 103 (0x0067)  Character: 0x0087 ('?')
0x00, 0x00, 0x00, // Index: 104 (0x0068)  Character: 0x0088 ('?')
0x00, 0x00, 0x00, // Index: 105 (0x0069)  Character: 0x0089 ('?')
0x00, 0x00, 0x00, // Index: 106 (0x006A)  Character: 0x008A ('?')
0x00, 0x01, 0x0A, // Index: 107 (0x006B)  Character: 0x008B ('?')
0x00, 0x00, 0x00, // Index: 108 (0x006C)  Character: 0x008C ('?')
0x01, 0xE3, 0x12, // Index: 109 (0x006D)  Character: 0x008D ('?')
0x01, 0x07, 0x96, // Index: 110 (0x006E)  Character: 0x008E ('?')
0x01, 0xE0, 0xDE, // Index: 111 (0x006F)  Character: 0x008F ('?')
0x01, 0xE1, 0x80, // Index: 112 (0x0070)  Character: 0x0090 ('?')
0x01, 0x00, 0x00, // Index: 113 (0x0071)  Character: 0x0091 ('?')
0x01, 0x00, 0x00, // Index: 114 (0x0072)  Character: 0x0092 ('?')
0x40, 0x00, 0x00, // Index: 115 (0x0073)  Character: 0x0093 ('?')
0x00, 0x00, 0x00, // Index: 116 (0x0074)  Character: 0x0094 ('?')
0x00, 0x00, 0x00, // Index: 117 (0x0075)  Character: 0x0095 ('?')
0x00, 0x00, 0x00, // Index: 118 (0x0076)  Character: 0x0096 ('?')
0x00, 0x00, 0x00, // Index: 119 (0x0077)  Character: 0x0097 ('?')
0x00, 0x00, 0x00, // Index: 120 (0x0078)  Character: 0x0098 ('')
0x00, 0x00, 0x00, // Index: 121 (0x0079)  Character: 0x0099 ('?')
0x00, 0x00, 0x00, // Index: 122 (0x007A)  Character: 0x009A ('?')
0x00, 0x02, 0x84, // Index: 123 (0x007B)  Character: 0x009B ('?')
0x00, 0x00, 0x00, // Index: 124 (0x007C)  Character: 0x009C ('?')
0x00, 0x00, 0x00, // Index: 125 (0x007D)  Character: 0x009D ('?')
0x00, 0x00, 0x00, // Index: 126 (0x007E)  Character: 0x009E ('?')
0x00, 0x00, 0x00, // Index: 127 (0x007F)  Character: 0x009F ('?')
0x00, 0x00, 0x00, // Index: 128 (0x0080)  Character: 0x00A0 (' ')
0x00, 0x00, 0x00, // Index: 129 (0x0081)  Character: 0x00A1 ('?')
0x00, 0x00, 0x00, // Index: 130 (0x0082)  Character: 0x00A2 ('?')
0x00, 0x00, 0x9C, // Index: 131 (0x0083)  Character: 0x00A3 ('?')
0x00, 0x00, 0x00, // Index: 132 (0x0084)  Character: 0x00A4 ('¤')
0x00, 0x00, 0x00, // Index: 133 (0x0085)  Character: 0x00A5 ('?')
0x00, 0x00, 0x00, // Index: 134 (0x0086)  Character: 0x00A6 ('¦')
0x00, 0x00, 0x00, // 0xA7  
0x03, 0xFF, 0xFF, // 0xA8   |||
0x00, 0x0F, 0xFF, // 0xA9    ||
0x00, 0x00, 0x3F, // 0xAA     |
0x82, 0x08, 0x20, // 0xAB 1-
0xC3, 0x0C, 0x30, // 0xAC 2-
0xE3, 0x8E, 0x38, // 0xAD 3-
0xF3, 0xCF, 0x3C, // 0xAE 4-
0xFB, 0xEF, 0xBE, // 0xAF 5-
0x3C, 0xF3, 0xCF, // 0xB0 5_
0x3C, 0xF3, 0xCF, // 0xB1 4_
0x1C, 0x71, 0xC7, // 0xB2 3_
0x0C, 0x30, 0xC3, // 0xB3 2_
0x04, 0x10, 0x41, // 0xB4 1_
0xFF, 0xFF, 0xFF, // 0xB5 ||||
0xFF, 0xFF, 0xC0, // 0xB6 |||
0xFF, 0xF0, 0x00, // 0xB7 ||
0xFC, 0x00, 0x00, // 0xB8 |
0x38, 0xA2, 0x80, // 0xB9 с
0x30, 0x43, 0x80, // 0xBA ч
0x18, 0xC1, 0x80, // 0xBB д 
0x38, 0xC3, 0x80, // 0xBC м
0x38, 0x42, 0x80, // 0xBD к
0xFA, 0x84, 0x8C, // 0xBE Р/
0x40, 0xC1, 0x0E, // 0xBF /ч
0x7A, 0x87, 0x80, // А
0xFA, 0xAB, 0x80, // Б
0xFA, 0xA5, 0x00, // В
0xFA, 0x08, 0x00, // Г
0x1B, 0xC1, 0x80, // Д
0xFA, 0xA8, 0x80, // Е
0xDB, 0xED, 0x80, // Ж
0x8A, 0xA5, 0x00, // З
0xF8, 0xCF, 0x80, // И
0x7A, 0xC7, 0x80, // Й
0xF8, 0x89, 0x80, // К
0x7A, 0x0F, 0x80, // Л
0xFB, 0x8F, 0x80, // М
0xF8, 0x8F, 0x80, // Н
0x72, 0x27, 0x00, // О
0xFA, 0x0F, 0x80, // П
0xFA, 0x84, 0x00, // Р
0x72, 0x28, 0x80, // С
0x83, 0xE8, 0x00, // Т
0xE8, 0xAF, 0x00, // У
0x73, 0xE7, 0x00, // Ф
0x89, 0xC8, 0x80, // Х
0xF8, 0x2F, 0x83, // Ц
0xE0, 0x8F, 0x80, // Ч
0xF8, 0xEF, 0x80, // Ш
0xF8, 0xEF, 0xC0, // Щ
0x83, 0xE2, 0x84, // Ъ
0xF8, 0xA1, 0x3E, // Ы
0xF8, 0xA1, 0x00, // Ь
0x8A, 0xA7, 0x00, // Э
0xF9, 0xC8, 0x9C, // Ю
0x5A, 0x8F, 0x80, // Я
};

 

MacMillan
Offline
Зарегистрирован: 25.10.2016

Поэксперементировал я с MC34063, и с кольцами и с гантелькой...потом вообще работать перестало, похоже что МС-ка не выдержала, даёт какие то всплески и молчит.

Нашёл гантельку, диаметр шляпы - 1см. Откопал из запасов неплохие релюшки на 10А от Omron...т.к я их нигде не используию и они достались мне бесплатно из принтеров, то решено было раскурочить и смотать оттуда провод. Провод кстати оч тонкий, наверное 0,063, замерить нечем, в сравнении есть только 0,2мм. Гантельку за ноги зажал в патрон дрели и намотал на глаз "сколько то там". Наверное пол-гантели в толщину. Подпаялся, замерил - 34,5 mH. Замотал пару слоёв лентой фум. Сверху первичка проводом 0,2мм - 50 витков. Лента фум сверху. 

У меня есть генератор шим с Али до 150 кГц с регулировкой скважности, ослик DSO203. Через полевик (STP65NF06) подключил генератор к гантельке. На выходе у гантельки Диод FR-607 и плёнка Suntan 1000V 10nF. Запитал всё это через литий с защитой и через мультиметр с замером тока.

Результаты были интересные. Сначала я думал, что нормально юзать гантельку под частотой 20-50кГц, при это добиться 400 Вольт оказалось возможно скважностью 50-60%, потребление было около 40мА (т.е это потребление только гантельки, диода, кондёра и транзистора без затвора (ЗЫ:затвор питается соответственно от генератора, который в свою очередь работал от USB)). Я полазил в верхних частотах 60+кГц, там дела обстаяли ещё хуже, околонулевые напряжения на выходе.

Тут я попёр в нижний диапозон...и тут началось главное! Чем ниже я опускался, тем меньше потреблялся ток и понижался % скважности. Лучше всего гантелька с моей намоткой работала как раз на частоте ШИМ ардуино 400-600 Гц, при этом скважность была 1%, а потребление тока было в районе 1,7 мА (и это при 4В)! Это конечно не рекордные 1мА, но разница с тем что я делал раньше ощутима. 

Позже попробую тоже самое с кольцом. Если будет тоже самое, то буду думали либо о переходе на Ардуину в качестве ШИМ контроллера, либо буду заставлять работать 34063 на частотах меньше килогерца (хотя по даташиту это не возможно).

PS: а вообще за последние пару лет я построил более десятка ИИП, мощностью конечно больше 100 ватт, но на разных топологиях. Считал всегда на проге Старичка. Но вот это реально первая импульсная маленькая схема, с которой такие проблемы. К тому же гантельку не посчитать, а результаты кольца не верные. Хочется и ток пониже и напряжение без просадок...и на контроллере низковольтнои и ничего не выходит. От части Joiner прав, чтоб использовать внешний специализированный контроллер ИИП, а не ардуину, ведь в нормальных полноценных устройствах не отдают контроль таким устройствам. Как минимум ардуина может зависнуть, и если на маленьком маломощном устройстве это "ничего страшного", то на 10 амперном полумосте это может закончиться пожаром, а TL494 и ей подобные не страдают от этого. К тому же скорость реакции контроллера ИИП по фидбэку или по усилителю ошибки во много раз быстрее реакции любого контроллера. В нашей теме то понятно, накачка медленная и хватит тупого кода по типу "if V>400 else PWM STep -1".

Joiner
Offline
Зарегистрирован: 04.09.2014

MacMillan пишет:

Поэксперементировал я с MC34063, и с кольцами и с гантелькой.... 

Позже попробую тоже самое с кольцом. Если будет тоже самое, то буду думали либо о переходе на Ардуину в качестве ШИМ контроллера, либо буду заставлять работать 34063 на частотах меньше килогерца (хотя по даташиту это не возможно).

Буржуины в каком-то своем высоковольтном преобразователе на MC34063, при помощи дополнительных деталек, добиваются очень короткого импульса. Я  по аналогии спаял схему, у меня получился импульс 400 наносекунд. И еще они рекомендуют настроить микросхемку на частоту не более 10 килогерц. Моя схема работает на частоте 6 килогерц. Ключ еще не подключал. Експерименты продолжу. И интересно было бы услышать резуьтаты Ваших опытов.

Dark-Dante
Offline
Зарегистрирован: 09.01.2018

OfficialGalkin, а где баг по таймеру был? На вскидку код таймера тот же.

MacMillan
Offline
Зарегистрирован: 25.10.2016

Joiner пишет:
Моя схема работает на частоте 6 килогерц.

Частотозадающий конденсатор какой ёмкости?

MacMillan
Offline
Зарегистрирован: 25.10.2016

  Померил кольцо. Такая же история, на низких частотах, порядка 1-1,5кГц самый высокий КПД - минимум скважности и тока при максимуме напряжения. Ток у кольца оказался где то на 1мА больше чем у гантельки. Подключил всё это к МС-ке, Ст поставил на 22 нФ, это где то 1,5 кГц. Выдаёт максимум 220 вольт. Менял и полярность подключения - не помогает. Есть ощущение, что их не подружить. С обычным генератором я получил больше 1000 В с подключеным осликом через 90 Мом и напрямую подключеным мультиметром на 10Мом. И это при скважности меньше 10%

На днях попробую банальное тупое управление через ардуину, только не через стандартный PWM, а через сторонний PWM.h, там можно скважность до 16bit делать и частоту любую до 2МГц. 

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Dark-Dante, там же, где я и говорил. В строке 881 костыль, чуть выше условие его активации на последней минуте (хотя достаточно было последней секунды). Это не найденное решение, а маскировка бага.

медведь
Offline
Зарегистрирован: 31.07.2019

понимаю но маленький экран не всегда удобно если он будет чуть больше бдет норм плюс можно выводить больше информацыи

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

Ну больший экран разве что для красоты. Для более красивого оформления. А информации и так достаточно, все что нужно выведено. 

Dark-Dante
Offline
Зарегистрирован: 09.01.2018

tekagi пишет:
Dark-Dante, там же, где я и говорил. В строке 881 костыль, чуть выше условие его активации на последней минуте (хотя достаточно было последней секунды). Это не найденное решение, а маскировка бага.

Понял. У меня бага нет, так как строку я эту выбросил сразу.

Enotikus
Offline
Зарегистрирован: 19.08.2019

Привет я уже давно смотрю твои видео и повторяю твой дозиметр.И я хочу согласиться со сталкерами ведь дисплей легко разбить.У меня давно завалялись модули от ардуино и я нашел ардуино нано и цифровой дисплей с китая (TM1637) можешь дополнить самую первую схему с ардуино  из этих двух компонентов? Я буду очень благодарен.И вот тебе лайфхак, с алиэкспрес можно заказать коробку для самоделок по твоему размеру просто введи в поиск  "Пластиковый корпус для DIY". Надеюсь что из этого что то получится.

Dark-Dante
Offline
Зарегистрирован: 09.01.2018

Ага, уже пошел пилить под все дисплеи и счётчики с али))
OficialGalkin, а в чём вы картинки рисуете для файла гиф.ц?

1707
Offline
Зарегистрирован: 08.02.2017

Всем привет. Смотрю изменеий фура пронеслась на крайних страница. Будут ли какие то правки в платы (схему) и что с прошивками и их описанием и изменениями?

Так же вопрос, можно ли подцепиться к ардуинке esp8266 к примеру и передавать онлайн данные на сайт какого нибудь народного контроля?

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Глобально ничего не менялось, разве что супрессор в схему добавился.

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

Muxi
Offline
Зарегистрирован: 22.01.2019

Тоже хочу собрать прибор для отправки данных на radmon, но не могу придумать, что делать с питанием и защитой от сырости. Литий и мороз не дружат, да и где-то читал, что сбм-20 с морозами тоже не очень. Если кто видел хорошие схемки, или может помочь, буду рад.

P.s. в теме наткнулся на пост, где Вы (tekagi) говорите про планы по проверке тлеющего, можете рассказать на словах хотябы, как это работает?

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Питание лучше внешнее, сетевое. Тогда и нагреватель с термостабилизацией поставить можно. Про нестабильную работу СБМ при отрицательныx температрах тоже упоминания встречал. Ну и корпус обязательно герметичный, чтобы конденсата не было. Качественная электрическая распредкоробка в помощь, там и уплотнитель по периметру, и сальники зажимные поставить можно. Только не брать белые и полупрозрачные, они уф боятся и за пару лет рассыпаются.

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

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

Я вот хочу свою плату развести. Хотелось бы на 16mhz что бы чип работал, но тогда надо что бы было питание 5 вольт. А это надо повышайку делать. При 3.8 вольтах уже 8 mhz частоту надо делать. Иначе могут быть глюки как мне сказал один человек. У меня ардуино нано на 2.9 даже работает на 16mhz, но он говорит что просто повезло и что многие будут глючить. 

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

Dark-Dante
Offline
Зарегистрирован: 09.01.2018

OfficialGalkin, в какой программе графику рисуете для файла гиф.ц?

OfficialGalkin
OfficialGalkin аватар
Offline
Зарегистрирован: 29.06.2019

В Paint стандартном либо Paint . NET

Сохраняю в бмп и конвертирую онлайн.

http://pavelk.ru/konverter-kartinok-dlya-lcd-oled-128x64-displeya

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

OfficialGalkin, кто мешает использовать на 8 МГц?

Dark-Dante
Offline
Зарегистрирован: 09.01.2018

OfficialGalkin пишет:

Хотелось бы на 16mhz что бы чип работал, но тогда надо что бы было питание 5 вольт. А это надо повышайку делать. При 3.8 вольтах уже 8 mhz частоту надо делать. Иначе могут быть глюки

При повторении Ардоса тоже задавался этим вопросом. Глючить будет один камень из ста, хотя даташит говорит об обратном, но около 30 конструкций на 328й работающие от лития на 16, а то и 20-22 мГц говорят о том что разработчики просто перестраховались, так что не создавайте себе проблем на ровном месте, работает- не трогайте.

Muxi
Offline
Зарегистрирован: 22.01.2019

Гуру, расскажите, как в этой схеме работает повышайка

Чем данная схема хуже/лучше той, что используется в ардосе?

tekagi
tekagi аватар
Offline
Зарегистрирован: 07.10.2016

Такой же step-up, как и в АрДосе. Только дроссель не двухобмоточный и транзистор высоковольтный биполярный, что на кпд скажется не лучшим образом. И делитель на два мега есть будет, как не в себя.

http://electrik.info/main/praktika/1112-dcdc-preobrazovateli.html