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

Surikat
Offline
Зарегистрирован: 13.07.2016

bodriy2014 пишет:

Текущая моя схема и скетч

//Питание и индикация счетчика Гейгера
#include <util/delay.h>

//настройки /////////////начало
#define ADC_HV A2  //пин замера высокого
#define ADC 190  //значение АЦП при котором 400В с учетом вашего делителя напряжения
#define puls 4  //тонкая настройка длинны импульса высоковольтного транса
#define led 13  //пин светика
#define buzz 8  //пин бузера
bool led_ON = 1;  //включить индикацию светодтодом (1)
bool buzz_ON = 0;  //включить индикацию бузером (1)
//настройки //////////////конец

int hv_adc, shet_s;
volatile int shet = 0;
unsigned long mil_s = 0;

void setup() {
  analogReference(INTERNAL);
  pinMode(5, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(buzz, OUTPUT);
  nakachka();//первая накачка
  attachInterrupt(0, Schet, FALLING);//прерываниям пин 2
}

void loop() {
  generator();//накачка по обратной связи с АЦП
  signa ();//подача сигнала о частичке
}
void signa () { //индикация каждой частички звуком или светом
  if (shet_s != shet) {
    shet_s = shet;
    if (led_ON == 1) {
      digitalWrite(led, HIGH);
    }
    if (buzz_ON == 1) {
      digitalWrite(buzz, HIGH);
    }
  }
  if (millis() - mil_s >= 10) {
    mil_s = millis();
    digitalWrite(led, LOW);
    digitalWrite(buzz, LOW);
  }
}

void Schet() { //прерывание от счетчика на пин 2
  detachInterrupt(0);
  shet++;
  attachInterrupt(0, Schet, FALLING);
}

void generator() {//накачка по обратной связи с АЦП
  hv_adc = analogRead(A2);
  if (hv_adc < ADC) { //Значение АЦП при котором на выходе 400В
    PORTD |= (1 << 5); //дергаем пин 5
    int c = puls;
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//дергаем пин 5
  }
}

void nakachka() {//первая накачка
  byte n = 0;
  while (n < 20) {
    PORTD |= (1 << 5);//дергаем пин
    int c = puls;
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//дергаем пин
    n++;
    _delay_us(100);
  }
}

 

схема работает?

Surikat
Offline
Зарегистрирован: 13.07.2016

bodriy2014 пишет:

Текущая моя схема и скетч

//Питание и индикация счетчика Гейгера
#include <util/delay.h>

//настройки /////////////начало
#define ADC_HV A2  //пин замера высокого
#define ADC 190  //значение АЦП при котором 400В с учетом вашего делителя напряжения
#define puls 4  //тонкая настройка длинны импульса высоковольтного транса
#define led 13  //пин светика
#define buzz 8  //пин бузера
bool led_ON = 1;  //включить индикацию светодтодом (1)
bool buzz_ON = 0;  //включить индикацию бузером (1)
//настройки //////////////конец

int hv_adc, shet_s;
volatile int shet = 0;
unsigned long mil_s = 0;

void setup() {
  analogReference(INTERNAL);
  pinMode(5, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(buzz, OUTPUT);
  nakachka();//первая накачка
  attachInterrupt(0, Schet, FALLING);//прерываниям пин 2
}

void loop() {
  generator();//накачка по обратной связи с АЦП
  signa ();//подача сигнала о частичке
}
void signa () { //индикация каждой частички звуком или светом
  if (shet_s != shet) {
    shet_s = shet;
    if (led_ON == 1) {
      digitalWrite(led, HIGH);
    }
    if (buzz_ON == 1) {
      digitalWrite(buzz, HIGH);
    }
  }
  if (millis() - mil_s >= 10) {
    mil_s = millis();
    digitalWrite(led, LOW);
    digitalWrite(buzz, LOW);
  }
}

void Schet() { //прерывание от счетчика на пин 2
  detachInterrupt(0);
  shet++;
  attachInterrupt(0, Schet, FALLING);
}

void generator() {//накачка по обратной связи с АЦП
  hv_adc = analogRead(A2);
  if (hv_adc < ADC) { //Значение АЦП при котором на выходе 400В
    PORTD |= (1 << 5); //дергаем пин 5
    int c = puls;
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//дергаем пин 5
  }
}

void nakachka() {//первая накачка
  byte n = 0;
  while (n < 20) {
    PORTD |= (1 << 5);//дергаем пин
    int c = puls;
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//дергаем пин
    n++;
    _delay_us(100);
  }
}

 

схема работает?

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

Это только кусочки схем, и те с момента написания поста менялись. Полные смотрите на сайте автора.

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

Добавил режим аварийной сигнализации и возможность выбора бузера (активный или пассивный) при компиляции. Альфа-версия, нестабильная. Возможно, буду переделывать.

/* ArDOs   v1063_beta    без режима сна
***Дозиметр на Ардуино
***IDE Arduino 1.8.2
  ветка форума 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); //подключение дисплея
//LCD5110 myGLCD(12, 11, 10, A4, A5); //подключение дисплея
#define contrast 60 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
#define first_alarm_duration 15000 //длительность сигнала тревоги при превышении первого аварийного порога в миллисекундах
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 60; //вторая ступень тревоги
byte del_BUZZ = 11;//длительность одиночного сигнала
//byte ton_BUZZ = 11; //тональность буззера
#define  ADC 163  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255)
#define k_delitel 576 //коефициент дельтеля напряжения, зависит от вашего делителя.
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool buzz_ON = 1;  //включить индикацию бузером (1)
bool podsvetka = 0; //подсветка
bool alarm_sound = 0; //флаг индикации превышения порога звуком
bool son_OK = 0; //разрешение или запрет сна
float opornoe = 1.10; //делить на opornoe/10
#define son_t 40 //время засыпания в секундах
#define save_DOZ 20 //как часто сохранять накопленную дозу например каждые 20мкР
byte beta_time = 5; //время замера бета излучения
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFont[], MediumNumbers[], TinyFont[];
extern uint8_t logo_bat[], logo_rag[], logo_tr[], gif_chast_1[], gif_chast_2[];
volatile int shet = 0;
unsigned long t_milis = 0, gr_milis = 0, lcd_milis = 0, toch_milis = 0, timer_mil = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
int hv_adc, hv_400, shet_s = 0, fon = 0, shet_gr = 0, shet_n = 0;
int speed_nakT = 0, speed_nak = 0, time_sh_l = 0, MIN, HOUR, result;
int doza_vr = 0, val_dr_pr = 0, val_dr_OK = 0;
byte mass_p[84], mass_toch[201], m = 0, n_menu = 0, sys_menu = 0, mass_36[41];
byte val_kl = 0, val_ok = 0, menu = 0, zam_180p = 0, zam_36p = 0, gif_x = 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, stat_percent = 99.0;
bool tr = 0, poisk = 1, fonarik = 0, g_fl = 0, toch;
//-------------------------------------------------------------
void setup() {
  //Serial.begin(19200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (0 << 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();
}
//-------------------------------------------------------------
void loop() {
  if (menu == 0) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      menu = 3;
      shet = 0; zam_180p = 0; fon = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 4;
      shet = 0;
      bet_z0 = 0;
      bet_z1 = 0;
      bet_r = 0;
      bet_z = 0;
      gotovo = 0;
      sek = 0;
      minute = 0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (menu == 4) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 0;
      shet = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (fonarik == 0) { //фонарик
    PORTB &= ~(1 << 1);//пин фонаря
  } else if (fonarik == 1) {
    PORTB |= (1 << 1);//пин фонаря
  }
  if (podsvetka == 1) {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
  if (podsvetka == 0) {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    if (menu == 0) {
      lcd_poisk();//вывод на дисплей режима поиск
      poisk_f();
    }
    if (menu == 1) {
      lcd_menu();//вывод на дисплей меню
    }
    if (menu == 2) {
      lcd_sys();//вывод на дисплей системного меню
    }
    if (menu == 3) {
      zamer_200s();//вывод на дисплей замер 180сек
    }
    if (menu == 4) {
      zamer_beta();
    }
  }
  generator();//накачка по обратной связи с АЦП
  if (shet_s != shet) {
    signa ();//подача сигнала о частичке
  }
  if (!(PIND & (1 << PIND3))) { //нажатие ок
    _delay_ms(500);//антидребезг
    OK();
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1++;
      }
      if (n_menu == 1) {
        treviga_2++;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF++;
        if (scrin_GRAF > 10) {
          scrin_GRAF = 1;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe + 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls++;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time++;
      }
    }
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1--;
      }
      if (n_menu == 1) {
        treviga_2--;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF--;
        if (scrin_GRAF < 1) {
          scrin_GRAF = 10;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe - 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls--;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time--;
      }
    }
  }

    if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------
void OK () { //нажатие ОК
  if (!(PIND & (1 << PIND3))) { //удержаиние OK
    val_ok++;
    if (val_ok == 10) {
      val_ok = 0;
      menu = 2;
    }
  }
  if (menu == 2) {
    sys_menu++;
    if (sys_menu > 5) {
      sys_menu = 0;
    }
  }
  if (menu == 1) {
    n_menu++;
    if (n_menu > 7) {
      n_menu = 0;
    }
  }
  if (menu == 0) {
    menu = 1;
  }
  if (menu == 3) {
    menu = 1;
  }
}
//--------------------------------------------------------------
void gif_nabor() {
  myGLCD.drawLine(0, 24, 84, 24); myGLCD.drawLine(0, 38, 84, 38);
  for (int i = 83 - zam_180p * 0.47; i < 84; i++) {
    myGLCD.drawLine(i, 24, i, 38);
  }
  g_fl = !g_fl;
  if (g_fl == 0) {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_1, 8, 8);
  } else {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_2, 8, 8);
  }
  if (zam_180p < 200) {
    gif_x = gif_x + 1;
    if (gif_x >= 83 - zam_180p * 0.47) {
      gif_x = 0;
    }
    myGLCD.print("ANALIZ", CENTER, 40);
  }

  if (zam_180p >= 200) {
    myGLCD.print("OBNOVLENIE", CENTER, 40);
  }
}
//--------------------------------------------------------------
void zamer_200s() {
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("%", 20, 0); myGLCD.printNumF(stat_percent, 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
      if (alarm_sound)  //сбрасываем сигнал тревоги первого уровня, если активен
    {
       res_first_alarm(); //сбрасываем сигнал тревоги 
    }
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  gif_nabor();
  battery();
  myGLCD.update();
  if (millis() - toch_milis >= 1000) {
    toch_milis = millis();
    for (int i = 0; i < 200; i++) { //сдвигаем
      mass_toch[i] = mass_toch[i + 1];
    }
    mass_toch[199] = shet;
    shet = 0;
    if (zam_180p < 200) { //первый набор массива
      zam_180p++;
      int fon_vr1 = 0;
      for (int i = 200 - zam_180p; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 * (40.0 / zam_180p);
    }
    if (zam_180p >= 200) { //набор массива
      int fon_vr1 = 0;
      for (int i = 0; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 / 5;
    }
    if (zam_180p <= 36) {
      stat_percent = stat_percent - 2.0;
    }
    if (zam_180p > 36 && zam_180p <= 72) {
      stat_percent = stat_percent - 0.3;
    }
    if (zam_180p > 72 && zam_180p <= 100) {
      stat_percent = stat_percent - 0.2;
    }
    if (zam_180p > 100 && zam_180p <= 200) {
      stat_percent = stat_percent - 0.1;
    }
    if (stat_percent < 5) {
      stat_percent = 5.0;
    }
  }
  if (!(PIND & (1 << PIND7))) { //нажатие <<<
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
    if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
      val_kl++;
      if (val_kl == 6) {
        val_kl = 0;
        fonarik = !fonarik;
      }
    }
  }
}
//--------------------------------------------------------------
void lcd_poisk() {//вывод на дисплей режима поиск
  if (shet < treviga_1 && fon < treviga_1) {//проверяем тревогу
    tr = 0;
  }
  if (shet > treviga_1 || fon > treviga_1) {//проверяем тревогу
  	check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  if (tr == 1) { //опасно
    myGLCD.drawBitmap(0, 0, logo_tr, 24, 8);
  }
  myGLCD.print("%", 20, 0); myGLCD.printNumF(100 - (zam_36p * 2.0), 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  time_d ();
  myGLCD.setFont(TinyFont);
  myGLCD.printNumI(HOUR, 0, 26);
  if (HOUR >= 9) {
    myGLCD.print("h", 13, 26);
  }
  if (HOUR < 9) {
    myGLCD.print("h", 5, 26);
  }
  myGLCD.printNumI(MIN, 18, 26);
  if (MIN >= 9) {
    myGLCD.print("m", 26, 26);
  }
  if (MIN < 9) {
    myGLCD.print("m", 23, 26);
  }
  myGLCD.setFont(SmallFont);
  if (doz_v < 1000) {
    myGLCD.printNumF(doz_v, 1, 41, 24); myGLCD.print("uR", RIGHT, 24);
  }
  if (doz_v >= 1000) {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 24); myGLCD.print("mR", RIGHT, 24);
  }
  myGLCD.drawLine(0, 32, 83, 32);//верхняя
  battery();
  for (int i = 0; i < 82; i ++) { //печатаем график
    if (mass_p[i] > 0) {
      if (mass_p[i] <= 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - mass_p[i]);
      }
      if (mass_p[i] > 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - 15);
      }
    }
  }
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_menu() { //вывод на дисплей меню
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPASN.1", 0, 0); myGLCD.printNumI(treviga_1, CENTER, 0); myGLCD.print("uR/h", RIGHT, 0);
  myGLCD.print("OPASN.2", 0, 6); myGLCD.printNumI(treviga_2, CENTER, 6); myGLCD.print("uR/h", RIGHT, 6);
  myGLCD.print("PODSV.", 0, 12); myGLCD.printNumI(podsvetka, CENTER, 12);
  myGLCD.print("------", 0, 18); myGLCD.printNumI(son_OK, CENTER, 18); myGLCD.print("on/off", RIGHT, 18);//usr
  myGLCD.print("POISK.", 0, 24); myGLCD.printNumI(scrin_GRAF, CENTER, 24); myGLCD.print("SEK", RIGHT, 24);
  myGLCD.print("ZVUK", 0, 30); myGLCD.printNumI(buzz_ON, CENTER, 30);
  myGLCD.print("OUT", 0, 36);
  myGLCD.print("SAVE", 0, 42);
  myGLCD.print(">", 30, n_menu * 6);
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_sys() { //вывод на дисплей меню
  VCC_read();
  speed_nakachka ();//скорость накачки имлульсы/сек
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPORN", 0, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 55, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
  hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
  myGLCD.print("NAKAH", 0, 6); myGLCD.printNumI(puls, CENTER, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
  myGLCD.print("DOZA", 0, 12); myGLCD.print(">>", CENTER, 12); myGLCD.print("SBROS", RIGHT, 12);
  myGLCD.print("OUT", 0, 18);
  myGLCD.print("SAVE", 0, 24);
  myGLCD.print("BETA", 0, 30); myGLCD.printNumI(beta_time, CENTER, 30); myGLCD.print("MIN", RIGHT, 30);
  myGLCD.print(">", 30, sys_menu * 6);
  myGLCD.print("SPEED N", 0, 40); myGLCD.printNumI(speed_nak, CENTER, 40); myGLCD.print("imp/sek", RIGHT, 40);
  myGLCD.update();
}
//-------------------------------------------------------------
void zamer_beta() {// замер бета или продуктов
  if (gotovo == 0) {
    if (!(PIND & (1 << PIND3))) { //нажатие OK
      gotovo = 1;
    }
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
    {
       res_first_alarm(); //сбрасываем сигнал тревоги
    }
    myGLCD.clrScr();
    myGLCD.setFont(SmallFont);
    myGLCD.print("Zamer ", 20, 10); myGLCD.printNumI(bet_z, 55, 10);
    myGLCD.print("nagmi OK", CENTER, 20);
    myGLCD.update();
  }
  if (gotovo == 1) {
    timer_soft();
    byte otsup = 0;
    if (minute > 9) {
      otsup = 5;
    }
    myGLCD.clrScr();
    battery();
    myGLCD.setFont(TinyFont);
    myGLCD.printNumI(minute, LEFT, 0);
    if (toch == 0) {
      myGLCD.print(":", 5 + otsup, 0);
    } else {
      myGLCD.print(" ", 5 + otsup, 0);
    }
    myGLCD.printNumI(sek, 10 + otsup, 0); myGLCD.print("time", 23 + otsup, 0);
    myGLCD.drawLine(0, 8, 83, 8);
    myGLCD.setFont(SmallFont);
    myGLCD.drawLine(40, 8, 40, 28);
    myGLCD.print("Zamer0", LEFT, 10); myGLCD.print("Zamer1", RIGHT, 10);
    myGLCD.printNumI(bet_z0, LEFT, 20); myGLCD.printNumI(bet_z1, RIGHT, 20);
    myGLCD.drawLine(0, 28, 83, 28);
    if (bet_z < 2) {
      myGLCD.print("Idet zamer", CENTER, 30); myGLCD.printNumI(bet_z, RIGHT, 30);
      myGLCD.printNumI(bet_r, CENTER, 38);
    }
    if (bet_z == 2) {
      myGLCD.print("Rezultat", CENTER, 30);
      myGLCD.printNumI(bet_r, CENTER, 38); myGLCD.print("mkR/h", RIGHT, 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;
      }
    }
    if (bet_z == 1) { //второй замер
      bet_z1 = bet_z1 + shet;
      shet = 0;
      if (minute >= beta_time) {
        bet_z = 2;
        sek = 0;
        minute = 0;
      }
    }
    if (bet_z == 2) { //результат
      bet_r = bet_z1 - bet_z0;
      bet_r = bet_r / (1.5 * beta_time);
    }
  }
  if (!(PIND & (1 << PIND4))) { //нажатие >>>
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
  }
}
//-------------------------------------------------------------
void poisk_f() {//режим поиска
  if (poisk == 1) {
    if (millis() - gr_milis >= scrin_GRAF * 1000) { //счет для графика
      gr_milis = millis();
      val_ok = 0;//сброс удержания системного меню
      shet_gr = shet - shet_n;
      if (shet_gr < 0) {
        shet_gr = 1;
      }
      mass_p[m] = shet_gr ;
      shet_n = shet;
      if (m < 82) {
        m++;
      }
      if (m == 82) {
        for (int i = 0; i < 83; i++) {
          mass_p[i] = mass_p[i + 1];
        }
        mass_p[82] = shet_gr;
      }
    }
    if (millis() - toch_milis >= 1000) {
      toch_milis = millis();
      for (int i = 0; i < 40; i++) { //сдвигаем
        mass_36[i] = mass_36[i + 1];
      }
      mass_36[40] = shet;
      if (zam_36p < 40) { //первый набор массива
        zam_36p++;
        fon = fon + shet;
      }
      if (zam_36p >= 40) { //набор массива
        int fon_vr1 = 0;
        for (int i = 0; i < 40; i++) {
          fon_vr1 = fon_vr1 + mass_36[i];
        }
        fon = fon_vr1;
      }
      shet = 0;
      doz_v = doz_v + fon / 100.0 / 40.0;
      time_doza = time_doza + 1;
      if (doz_v - doza_vr >= save_DOZ) { //а не пора ли сохранить дозу ?)
        eeprom_wrD ();
        doza_vr = doz_v;
      }
    }
  }
}
//-------------------------------------------------------------
void signa () { //индикация каждой частички звуком светом
  shet_s = shet;  
    if (alarm_sound) //если поднят флаг аварийного сигнала
	{
  #ifdef buzzer_active //если задефайнен активный бузер
		PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
  #else //пассивный
  tone (6, 1300); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
  #endif
		if ((millis() - alarm_milis) > first_alarm_duration) // проверяем, не истекло ли время подачи сигнала тревоги_
		{
    #ifdef buzzer_active   //если задефайнен активный бузер
		PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
    #else //пассивный бузер
    noTone (6); //выключаем писк на 6й ноге
    #endif 
		alarm_sound = 0; // сбрасываем флаг сигнала тревоги
		}		
		PORTB |= (1 << 5); //включаем светодиод
		delay(del_BUZZ);
		PORTB &= ~(1 << 5);//выключаем светодиод
	}
	else //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
	{
if ((buzz_ON == 1) && (shet_s > 0))  //включаем бузер
  #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    
  }
  //generator();//накачка по обратной связи с АЦП
}
//-------------------------------------------------------------
void Schet() { //прерывание от счетчика на пин 2
  shet++;
}
//-------------------------------------------------------------
void generator() {//накачка по обратной связи с АЦП
  hv_adc  = Read_HV();
  if (hv_adc < ADC) { //Значение АЦП при котором на выходе 400В
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//-------------------------------------------------------------
byte Read_HV () {
  ADCSRA = 0b11100111;
  ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
  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.drawBitmap(59, 0, logo_bat, 24, 8);
  myGLCD.setFont(TinyFont);
  myGLCD.printNumF(VCC, 2, 63, 2);
}
//-------------------------------------------------------------
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(SmallFont);
  myGLCD.print("Arduino+", CENTER, 32);
  myGLCD.print("Dosimetr v1.06", 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, son_OK);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, buzz_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(13, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("Save OK", CENTER, 24);
  myGLCD.update();
  _delay_ms(1000);
}
//-------------------------------------------------------------
void eeprom_wrD () { //запись настроек в память время накопления дозы
  byte hi = time_doza >> 8;
  byte low = time_doza;
  EEPROM.write(9, hi);
  EEPROM.write(10, low);
  hi = int(doz_v) >> 8;
  low = int(doz_v);
  EEPROM.write(11, hi);
  EEPROM.write(12, low);
}
//-------------------------------------------------------------
void eeprom_readD () { //чтание настроек из памяти время накопления дозы
  byte hi  = EEPROM.read(9);
  byte low  = EEPROM.read(10);
  time_doza = (hi << 8) | low;
  hi  = EEPROM.read(11);
  low  = EEPROM.read(12);
  doz_v = (hi << 8) | low;
}
//-------------------------------------------------------------
void eeprom_readS () { //чтание настроек из памяти
  if (EEPROM.read(0) == 222) {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    son_OK = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    buzz_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    beta_time = EEPROM.read(13);
  }
  _delay_ms(10);
}
//-------------------------------------------------------------
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() {
  HOUR = time_doza / 3600;
  MIN = (time_doza / 60) % 60;
}
//-------------------------------------------------------------
void timer_soft() {
  if (millis() - timer_mil >= 1000) {
    timer_mil = millis();
    sek++;
    toch = !toch;
    if (sek > 60) {
      sek = 0;
      minute++;
    }
  }
}


void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
	if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
		{
		alarm_sound = 1; // поднимаем флаг аварийного сигнала
		alarm_milis = millis(); // запоминаем время начала тревоги
		}  
}


void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
  {
    alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
  }

Не забываем подставлять свои значения делителя и ADC.

Переключиться на активный бузер можно раскомментировав строчку

//#define buzzer_active //если используется активный бузер

Длительность сигнала аварии задаётся строчкой

#define first_alarm_duration 15000 

Для ручного сброса сигнала тревоги достаточно зайти и выйти в режим разностного замера (текущие показания при этом останутся, значок аварии на экране тоже, авария сработает повторно только после снижения фона ниже порога и последующего повышения) или режим анализа, то есть длительного замера (при этом текущие показания сбросятся, если окружающий фон остаётся выше уровня порога тревоги - сигнал сработает снова). Если во время работы сигнала тревоги фон опустится ниже порога - сигнал выключится. Включение тревоги не зависит от настройки ZVUK в меню, она отвечает лишь за озвучивание продетектированных частиц.

В режимах анализа и разностного замера аварийная сигнализация не задействована!

ortus
Offline
Зарегистрирован: 16.10.2017

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

 

ortus
Offline
Зарегистрирован: 16.10.2017

Нашел причину, скорее дребезг на 6 пине, сейчас перерезал цепь, данный баг исчез...

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

По звуковому? При высоком фоне от КИ тоже баг пропал?

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

Я бы ещё посоветовал повесить кондёры по 0,1 непосредственно на входах ардуинки 4, 3, 7 на землю. Можно и подтяжки по 10К на Vcc. Ну и блокировочные керамику и электролиты по питанию по плате разбросать.

Прошивка с тревогой сейчас исправно тикает на столе, на слабенький КИ реагирует как положено.

В базовую схему изменений не вносили?

ortus
Offline
Зарегистрирован: 16.10.2017

Схема базовая, без изменений, при высоких фонах редко, но все равно выбивает в анализ и изредко в первичное меню в замер выкидывает крайне редко, сейчас накинул ограничительный резистор на бузер в 270 Ом, при совсем высоких уровнях выбило в анализ один раз, услышал сигнал аварии, режим интересен, просить сделать прирывистым не буду, этот вариант впринципе норм, изменился звук прилета частичек, не привычно, привык к брутальному пощелкиванию бузера)))), но щелчек стал более информативен, сегодня брал на работу, за шумом станка не слышно вообще, сейчас стал звук более звонким и более громким, что однозначно плюс, по сути отпадает смысл в генераторных бузерах и в усилителях. Из минусов сейчас наблюдаю за прибором, есть пропуски частичек, но тольуо при запуске, светодиод моргает, в графике отображается прилет цифровая индикация отрабатывает, после секунд 5-6 появляется звук, буду еще тестить на всех режимах, при норм фоне, среднем и повышанном с крайне сильным.... Сейчас еще раз проверю все что можно...

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

ortus пишет:

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

Можно подобрать под свои хотелки. В строчке

    tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге

можно задать желаемую частоту и длительность озвучивания частицы. Если длительность сделать 1-5 - будет щелчок.

Мне пассивного бузера не хватило, тихий слишком. Поставил активный с транзисторным ключом.

 

ortus пишет:

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

Не озвучивает отдельные частицы или задержка включения тревоги?

ortus
Offline
Зарегистрирован: 16.10.2017

Погонял на всех режимах, отрабатывает как положенно, вылетов не было, все же авария норм, можно сделать повторяемость сигнала в равные промежутки времени, к примеру длительность сигнала аварии затем такая же длительность тишины, затем снова сигнал и до тех пор пока фон выше выставленного значения и останется ввести режим сон с сохранением вывода аварии в остальном же все норм и полностью устраивает кроме двух моментов, надобность в втором уровне аварии отпадает и мне очень не ясен режим анализа, в главном окне и так все понятно без данного режима.... Спасибо за оперативную правку кода!!! ЗЫ: задержка пропала с заменой резистора на бузер! Отрабатывает как положено!

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

Режим анализа - замерить фон в определённом месте / от определённого источника с максимальной точностью. При входе в режим обнуляется массив скользящего окна и усреднение ведётся за более длительный промежуток времени (пока производится набор шкалы). Если в общем - поднесли/положили прибор к нужному объекту/месту, включили режим анализа и не трогаем до окончания измерения. Получаем максимально возможный для применённого датчика результат. В обычном поисковом режиме результат будет менее точным из-за меньшего размера скользящего окна.

Разностный режим был бы более полезен, если бы была допилена возможность использовать более чувствительные датчики (особенно слюдники), СБМ20 всё же грубоват для этих целей.

По сигналу тревоги, возможно, буду ещё ковыряться.

Режим сна (с выходом по тревоге или кнопке "меню") был, bodriy2014 его убрал на время добавления и отладки режимов длительного и разностного замеров. Вернуть мне не пока по зубам :(

ortus
Offline
Зарегистрирован: 16.10.2017

Спорить не буду на счет полезности режима анализ ( в понимании данного режима, как он должен быть) но Вы сами сказали - не с СБМ-20, и я полностью с Вами согласен, данный датчик подходит для приборов класса "показометр", стоял бы хотя бы СБТ11А то да, режим окажется крайне полезен и то не в том варианте выводимой информации, а с поэтапной фиксацией замеров по гамме, гамме+бетте, гамме+ беттее+ альфе, вот тогда да, режим себя полностью оправдывает и будет крайне востребован, с СБТ- 20 задача проста, выявить очаг и вовремя свалить, без замеров на более достоверные и точные результаты, для бытового применения более подходит режим замера, где даже с СБМ-20 можно выявить расхождения в дозе по продуктам, воде и тд и то при условии как минимум часового замера на каждый замер пустой кюветы и с содержимым.... Хотя, что я здесь распинаюсь, Вы и так все это прекрасно знаете и без меня...

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

Для замера беты как раз разрабатывался разностный режим :) Можно замерить пустую кювету, затем кювету с образцом, и получить разницу, соответствующую суммарной гамме и бете от образца, а можно замерить образец без экрана и с экраном, и получить представление о плотности потока бета излучения. И здесь слюдник предпочтительнее. Фактически этот режим копия принципа работы радиометра "Бета" или схожего режима "Припяти" (его bodriy2014 и брал за образец).
А режим анализ для тех случаев, когда мы не можем получить данные о фоне в отсутствии образца. К примеру гранитная набережная, пещера, помещение, лес и т.д.

ortus
Offline
Зарегистрирован: 16.10.2017

Жесткую бету заметте))) и то свежим датчиком,  у меня датчик 82 года выпуска, по сути возраст у него более 30 лет, иногда затухающий треск проскакивает, видно умирает((( кстати подключал сбт-11 и сбт-11а, увы, оба присмерти... кстати забыл сказать тем у кого нет сбм в Питере есть контора занимающаяся распродажей списанного медицинского оборудования и иного имущества, так вот у них есть в наличии и датчики и приборы (дпхи, мастер, дозиметры других типов, и датчики сбм20 по 300 р за штуку, ) если админы форума не против выложу ссыль, может кто и решит проблему с поиском датчиков, https://deltarezerv.ru/g7756429-dozimetry. Я у них покупал дп5в

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

Ахтунг! Найден серьёзный косяк в режиме разностного замера! Счёт начинался не с момента запуска измерения, а сразу при входе в режим и по окончанию первого замера, и эти значения добавлялись к измеренным за заданный промежуток времени (после нажатия "ок" в полях "Zamer 0" и "Zamer 1" уже присутствовали значения, набранные за время, пока на экране была надпись "nagmi OK". Добавил обнуление значений по нажатию "ОК" и озвучивание окончания интервалов замера.

/* ArDOs   v1.063.2  без режима сна
***Дозиметр на Ардуино
***IDE Arduino 1.8.2
  ветка форума 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); //подключение дисплея
//LCD5110 myGLCD(12, 11, 10, A4, A5); //подключение дисплея
#define contrast 60 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
#define first_alarm_duration 7000 //длительность сигнала тревоги при превышении первого аварийного порога в миллисекундах
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 60; //вторая ступень тревоги
byte del_BUZZ = 11;//длительность одиночного сигнала
//byte ton_BUZZ = 11; //тональность буззера
#define  ADC 163  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255)
#define k_delitel 576 //коефициент дельтеля напряжения, зависит от вашего делителя.
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool buzz_ON = 1;  //включить индикацию бузером (1)
bool podsvetka = 0; //подсветка
bool alarm_sound = 0; //флаг индикации превышения порога звуком
bool son_OK = 0; //разрешение или запрет сна
float opornoe = 1.10; //делить на opornoe/10
#define son_t 40 //время засыпания в секундах
#define save_DOZ 20 //как часто сохранять накопленную дозу например каждые 20мкР
byte beta_time = 5; //время замера бета излучения
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFont[], MediumNumbers[], TinyFont[];
extern uint8_t logo_bat[], logo_rag[], logo_tr[], gif_chast_1[], gif_chast_2[];
volatile int shet = 0;
unsigned long t_milis = 0, gr_milis = 0, lcd_milis = 0, toch_milis = 0, timer_mil = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
int hv_adc, hv_400, shet_s = 0, fon = 0, shet_gr = 0, shet_n = 0;
int speed_nakT = 0, speed_nak = 0, time_sh_l = 0, MIN, HOUR, result;
int doza_vr = 0, val_dr_pr = 0, val_dr_OK = 0;
byte mass_p[84], mass_toch[201], m = 0, n_menu = 0, sys_menu = 0, mass_36[41];
byte val_kl = 0, val_ok = 0, menu = 0, zam_180p = 0, zam_36p = 0, gif_x = 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, stat_percent = 99.0;
bool tr = 0, poisk = 1, fonarik = 0, g_fl = 0, toch;
//-------------------------------------------------------------
void setup() {
  //Serial.begin(19200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (0 << 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();
}
//-------------------------------------------------------------
void loop() {
  if (menu == 0) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      menu = 3;
      shet = 0; zam_180p = 0; fon = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 4;
      shet = 0;
      bet_z0 = 0;
      bet_z1 = 0;
      bet_r = 0;
      bet_z = 0;
      gotovo = 0;
      sek = 0;
      minute = 0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (menu == 4) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 0;
      shet = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (fonarik == 0) { //фонарик
    PORTB &= ~(1 << 1);//пин фонаря
  } else if (fonarik == 1) {
    PORTB |= (1 << 1);//пин фонаря
  }
  if (podsvetka == 1) {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
  if (podsvetka == 0) {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    if (menu == 0) {
      lcd_poisk();//вывод на дисплей режима поиск
      poisk_f();
    }
    if (menu == 1) {
      lcd_menu();//вывод на дисплей меню
    }
    if (menu == 2) {
      lcd_sys();//вывод на дисплей системного меню
    }
    if (menu == 3) {
      zamer_200s();//вывод на дисплей замер 180сек
    }
    if (menu == 4) {
      zamer_beta();
    }
  }
  generator();//накачка по обратной связи с АЦП
  if (shet_s != shet) {
    signa ();//подача сигнала о частичке
  }
  if (!(PIND & (1 << PIND3))) { //нажатие ок
    _delay_ms(500);//антидребезг
    OK();
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1++;
      }
      if (n_menu == 1) {
        treviga_2++;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF++;
        if (scrin_GRAF > 10) {
          scrin_GRAF = 1;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe + 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls++;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time++;
      }
    }
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1--;
      }
      if (n_menu == 1) {
        treviga_2--;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF--;
        if (scrin_GRAF < 1) {
          scrin_GRAF = 10;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe - 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls--;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time--;
      }
    }
  }

    if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------
void OK () { //нажатие ОК
  if (!(PIND & (1 << PIND3))) { //удержаиние OK
    val_ok++;
    if (val_ok == 10) {
      val_ok = 0;
      menu = 2;
    }
  }
  if (menu == 2) {
    sys_menu++;
    if (sys_menu > 5) {
      sys_menu = 0;
    }
  }
  if (menu == 1) {
    n_menu++;
    if (n_menu > 7) {
      n_menu = 0;
    }
  }
  if (menu == 0) {
    menu = 1;
  }
  if (menu == 3) {
    menu = 1;
  }
}
//--------------------------------------------------------------
void gif_nabor() {
  myGLCD.drawLine(0, 24, 84, 24); myGLCD.drawLine(0, 38, 84, 38);
  for (int i = 83 - zam_180p * 0.47; i < 84; i++) {
    myGLCD.drawLine(i, 24, i, 38);
  }
  g_fl = !g_fl;
  if (g_fl == 0) {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_1, 8, 8);
  } else {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_2, 8, 8);
  }
  if (zam_180p < 200) {
    gif_x = gif_x + 1;
    if (gif_x >= 83 - zam_180p * 0.47) {
      gif_x = 0;
    }
    myGLCD.print("ANALIZ", CENTER, 40);
  }

  if (zam_180p >= 200) {
    myGLCD.print("OBNOVLENIE", CENTER, 40);
  }
}
//--------------------------------------------------------------
void zamer_200s() {
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("%", 20, 0); myGLCD.printNumF(stat_percent, 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
      if (alarm_sound)  //сбрасываем сигнал тревоги первого уровня, если активен
    {
       res_first_alarm(); //сбрасываем сигнал тревоги 
    }
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  gif_nabor();
  battery();
  myGLCD.update();
  if (millis() - toch_milis >= 1000) {
    toch_milis = millis();
    for (int i = 0; i < 200; i++) { //сдвигаем
      mass_toch[i] = mass_toch[i + 1];
    }
    mass_toch[199] = shet;
    shet = 0;
    if (zam_180p < 200) { //первый набор массива
      zam_180p++;
      int fon_vr1 = 0;
      for (int i = 200 - zam_180p; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 * (40.0 / zam_180p);
    }
    if (zam_180p >= 200) { //набор массива
      int fon_vr1 = 0;
      for (int i = 0; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 / 5;
    }
    if (zam_180p <= 36) {
      stat_percent = stat_percent - 2.0;
    }
    if (zam_180p > 36 && zam_180p <= 72) {
      stat_percent = stat_percent - 0.3;
    }
    if (zam_180p > 72 && zam_180p <= 100) {
      stat_percent = stat_percent - 0.2;
    }
    if (zam_180p > 100 && zam_180p <= 200) {
      stat_percent = stat_percent - 0.1;
    }
    if (stat_percent < 5) {
      stat_percent = 5.0;
    }
  }
  if (!(PIND & (1 << PIND7))) { //нажатие <<<
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
    if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
      val_kl++;
      if (val_kl == 6) {
        val_kl = 0;
        fonarik = !fonarik;
      }
    }
  }
}
//--------------------------------------------------------------
void lcd_poisk() {//вывод на дисплей режима поиск
  if (shet < treviga_1 && fon < treviga_1) {//проверяем тревогу
    tr = 0;
  }
  if (shet > treviga_1 || fon > treviga_1) {//проверяем тревогу
    check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  if (tr == 1) { //опасно
    myGLCD.drawBitmap(0, 0, logo_tr, 24, 8);
  }
  myGLCD.print("%", 20, 0); myGLCD.printNumF(100 - (zam_36p * 2.0), 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  time_d ();
  myGLCD.setFont(TinyFont);
  myGLCD.printNumI(HOUR, 0, 26);
  if (HOUR >= 9) {
    myGLCD.print("h", 13, 26);
  }
  if (HOUR < 9) {
    myGLCD.print("h", 5, 26);
  }
  myGLCD.printNumI(MIN, 18, 26);
  if (MIN >= 9) {
    myGLCD.print("m", 26, 26);
  }
  if (MIN < 9) {
    myGLCD.print("m", 23, 26);
  }
  myGLCD.setFont(SmallFont);
  if (doz_v < 1000) {
    myGLCD.printNumF(doz_v, 1, 41, 24); myGLCD.print("uR", RIGHT, 24);
  }
  if (doz_v >= 1000) {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 24); myGLCD.print("mR", RIGHT, 24);
  }
  myGLCD.drawLine(0, 32, 83, 32);//верхняя
  battery();
  for (int i = 0; i < 82; i ++) { //печатаем график
    if (mass_p[i] > 0) {
      if (mass_p[i] <= 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - mass_p[i]);
      }
      if (mass_p[i] > 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - 15);
      }
    }
  }
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_menu() { //вывод на дисплей меню
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPASN.1", 0, 0); myGLCD.printNumI(treviga_1, CENTER, 0); myGLCD.print("uR/h", RIGHT, 0);
  myGLCD.print("OPASN.2", 0, 6); myGLCD.printNumI(treviga_2, CENTER, 6); myGLCD.print("uR/h", RIGHT, 6);
  myGLCD.print("PODSV.", 0, 12); myGLCD.printNumI(podsvetka, CENTER, 12);
  myGLCD.print("------", 0, 18); myGLCD.printNumI(son_OK, CENTER, 18); myGLCD.print("on/off", RIGHT, 18);//usr
  myGLCD.print("POISK.", 0, 24); myGLCD.printNumI(scrin_GRAF, CENTER, 24); myGLCD.print("SEK", RIGHT, 24);
  myGLCD.print("ZVUK", 0, 30); myGLCD.printNumI(buzz_ON, CENTER, 30);
  myGLCD.print("OUT", 0, 36);
  myGLCD.print("SAVE", 0, 42);
  myGLCD.print(">", 30, n_menu * 6);
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_sys() { //вывод на дисплей меню
  VCC_read();
  speed_nakachka ();//скорость накачки имлульсы/сек
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPORN", 0, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 55, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
  hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
  myGLCD.print("NAKAH", 0, 6); myGLCD.printNumI(puls, CENTER, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
  myGLCD.print("DOZA", 0, 12); myGLCD.print(">>", CENTER, 12); myGLCD.print("SBROS", RIGHT, 12);
  myGLCD.print("OUT", 0, 18);
  myGLCD.print("SAVE", 0, 24);
  myGLCD.print("BETA", 0, 30); myGLCD.printNumI(beta_time, CENTER, 30); myGLCD.print("MIN", RIGHT, 30);
  myGLCD.print(">", 30, sys_menu * 6);
  myGLCD.print("SPEED N", 0, 40); myGLCD.printNumI(speed_nak, CENTER, 40); myGLCD.print("imp/sek", RIGHT, 40);
  myGLCD.update();
}
//-------------------------------------------------------------
void zamer_beta() {// замер бета или продуктов
  if (gotovo == 0) {
    if (!(PIND & (1 << PIND3))) { //нажатие OK
      gotovo = 1;
      switch (bet_z) //проверяем, находимся ли в первом или втором замере
      {
        case 0: //если в первом замере
      bet_z0 = 0; //обнуляем текущие показания замера 1
      shet = 0; //обнуляем счёт
        case 1: //если во втором замере
      bet_z1 = 0; //обнуляем текущие показания замера 2
      shet = 0; //обнуляем счёт            
      }
    }
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
    {
       res_first_alarm(); //сбрасываем сигнал тревоги
    }
    myGLCD.clrScr();
    myGLCD.setFont(SmallFont);
    myGLCD.print("Zamer ", 20, 10); myGLCD.printNumI(bet_z, 55, 10);
    myGLCD.print("nagmi OK", CENTER, 20);
    myGLCD.update();
  }
  if (gotovo == 1) {
    timer_soft();
    byte otsup = 0;
    if (minute > 9) {
      otsup = 5;
    }
    myGLCD.clrScr();
    battery();
    myGLCD.setFont(TinyFont);
    myGLCD.printNumI(minute, LEFT, 0);
    if (toch == 0) {
      myGLCD.print(":", 5 + otsup, 0);
    } else {
      myGLCD.print(" ", 5 + otsup, 0);
    }
    myGLCD.printNumI(sek, 10 + otsup, 0); myGLCD.print("time", 23 + otsup, 0);
    myGLCD.drawLine(0, 8, 83, 8);
    myGLCD.setFont(SmallFont);
    myGLCD.drawLine(40, 8, 40, 28);
    myGLCD.print("Zamer0", LEFT, 10); myGLCD.print("Zamer1", RIGHT, 10);
    myGLCD.printNumI(bet_z0, LEFT, 20); myGLCD.printNumI(bet_z1, RIGHT, 20);
    myGLCD.drawLine(0, 28, 83, 28);
    if (bet_z < 2) {
      myGLCD.print("Idet zamer", CENTER, 30); myGLCD.printNumI(bet_z, RIGHT, 30);
      myGLCD.printNumI(bet_r, CENTER, 38);
    }
    if (bet_z == 2) {
      myGLCD.print("Rezultat", CENTER, 30);
      myGLCD.printNumI(bet_r, CENTER, 38); myGLCD.print("mkR/h", RIGHT, 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,70); //генерим писк 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,70); //генерим писк 2000Гц 70миллисекунд на 6й ноге		
      }
    }
    if (bet_z == 2) { //результат
      bet_r = bet_z1 - bet_z0;
      bet_r = bet_r / (1.5 * beta_time);
    }
  }
  if (!(PIND & (1 << PIND4))) { //нажатие >>>
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
  }
}
//-------------------------------------------------------------
void poisk_f() {//режим поиска
  if (poisk == 1) {
    if (millis() - gr_milis >= scrin_GRAF * 1000) { //счет для графика
      gr_milis = millis();
      val_ok = 0;//сброс удержания системного меню
      shet_gr = shet - shet_n;
      if (shet_gr < 0) {
        shet_gr = 1;
      }
      mass_p[m] = shet_gr ;
      shet_n = shet;
      if (m < 82) {
        m++;
      }
      if (m == 82) {
        for (int i = 0; i < 83; i++) {
          mass_p[i] = mass_p[i + 1];
        }
        mass_p[82] = shet_gr;
      }
    }
    if (millis() - toch_milis >= 1000) {
      toch_milis = millis();
      for (int i = 0; i < 40; i++) { //сдвигаем
        mass_36[i] = mass_36[i + 1];
      }
      mass_36[40] = shet;
      if (zam_36p < 40) { //первый набор массива
        zam_36p++;
        fon = fon + shet;
      }
      if (zam_36p >= 40) { //набор массива
        int fon_vr1 = 0;
        for (int i = 0; i < 40; i++) {
          fon_vr1 = fon_vr1 + mass_36[i];
        }
        fon = fon_vr1;
      }
      shet = 0;
      doz_v = doz_v + fon / 100.0 / 40.0;
      time_doza = time_doza + 1;
      if (doz_v - doza_vr >= save_DOZ) { //а не пора ли сохранить дозу ?)
        eeprom_wrD ();
        doza_vr = doz_v;
      }
    }
  }
}
//-------------------------------------------------------------
void signa () { //индикация каждой частички звуком светом
  shet_s = shet;  
    if (alarm_sound) //если поднят флаг аварийного сигнала
  {
  #ifdef buzzer_active //если задефайнен активный бузер
    PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
  #else //пассивный
  tone (6, 1300); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
  #endif
    if ((millis() - alarm_milis) > first_alarm_duration) // проверяем, не истекло ли время подачи сигнала тревоги_
    {
    #ifdef buzzer_active   //если задефайнен активный бузер
    PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
    #else //пассивный бузер
    noTone (6); //выключаем писк на 6й ноге
    #endif 
    alarm_sound = 0; // сбрасываем флаг сигнала тревоги
    }   
    PORTB |= (1 << 5); //включаем светодиод
    delay(del_BUZZ);
    PORTB &= ~(1 << 5);//выключаем светодиод
  }
  else //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
  {
if ((buzz_ON == 1) && (shet_s > 0))  //включаем бузер
  #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    
  }
  //generator();//накачка по обратной связи с АЦП
}
//-------------------------------------------------------------
void Schet() { //прерывание от счетчика на пин 2
  shet++;
}
//-------------------------------------------------------------
void generator() {//накачка по обратной связи с АЦП
  hv_adc  = Read_HV();
  if (hv_adc < ADC) { //Значение АЦП при котором на выходе 400В
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//-------------------------------------------------------------
byte Read_HV () {
  ADCSRA = 0b11100111;
  ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
  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.drawBitmap(59, 0, logo_bat, 24, 8);
  myGLCD.setFont(TinyFont);
  myGLCD.printNumF(VCC, 2, 63, 2);
}
//-------------------------------------------------------------
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(SmallFont);
  myGLCD.print("Arduino+", CENTER, 32);
  myGLCD.print("Dosimetr v1.06", 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, son_OK);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, buzz_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(13, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("Save OK", CENTER, 24);
  myGLCD.update();
  _delay_ms(1000);
}
//-------------------------------------------------------------
void eeprom_wrD () { //запись настроек в память время накопления дозы
  byte hi = time_doza >> 8;
  byte low = time_doza;
  EEPROM.write(9, hi);
  EEPROM.write(10, low);
  hi = int(doz_v) >> 8;
  low = int(doz_v);
  EEPROM.write(11, hi);
  EEPROM.write(12, low);
}
//-------------------------------------------------------------
void eeprom_readD () { //чтание настроек из памяти время накопления дозы
  byte hi  = EEPROM.read(9);
  byte low  = EEPROM.read(10);
  time_doza = (hi << 8) | low;
  hi  = EEPROM.read(11);
  low  = EEPROM.read(12);
  doz_v = (hi << 8) | low;
}
//-------------------------------------------------------------
void eeprom_readS () { //чтание настроек из памяти
  if (EEPROM.read(0) == 222) {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    son_OK = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    buzz_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    beta_time = EEPROM.read(13);
  }
  _delay_ms(10);
}
//-------------------------------------------------------------
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() {
  HOUR = time_doza / 3600;
  MIN = (time_doza / 60) % 60;
}
//-------------------------------------------------------------
void timer_soft() {
  if (millis() - timer_mil >= 1000) {
    timer_mil = millis();
    sek++;
    toch = !toch;
    if (sek > 60) {
      sek = 0;
      minute++;
    }
  }
}


void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
  if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
    {
    alarm_sound = 1; // поднимаем флаг аварийного сигнала
    alarm_milis = millis(); // запоминаем время начала тревоги
    }  
}


void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
  {
    alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
  }

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

ImaSoft
ImaSoft аватар
Offline
Зарегистрирован: 22.09.2015

tekagi пишет:

Ахтунг! Найден серьёзный косяк в режиме разностного замера! Счёт начинался не с момента запуска измерения, а сразу при входе в режим и по окончанию первого замера, и эти значения добавлялись к измеренным за заданный промежуток времени (после нажатия "ок" в полях "Zamer 0" и "Zamer 1" уже присутствовали значения, набранные за время, пока на экране была надпись "nagmi OK". Добавил обнуление значений по нажатию "ОК" и озвучивание окончания интервалов замера.

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

Да да ... припоминаю есть такое...

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

ImaSoft, Вы второй баг (учёт фона в меню) в своей версии фиксили? Решение не подскажете?

ImaSoft
ImaSoft аватар
Offline
Зарегистрирован: 22.09.2015

tekagi пишет:

ImaSoft, Вы второй баг (учёт фона в меню) в своей версии фиксили? Решение не подскажете?

Не совсем допонимаю, в чем проблема, вы можете снять видео и показать это?

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

Мде. Фотик для макро видео не годится совершенно...

Видео здесь.

Чем дольше находишься в меню - тем выше скакнут показания после выхода в режим поиска. Похоже, в меню (как пользовательском, так и системном) не реализован учёт, просто переменная инкрементируется в прерывании, но не обнуляется, и данные в массив не пишутся. После выхода из меню всё насчитанное добавляется одним махом.

Разобраться в коде Бодрого пока не могу...

ImaSoft
ImaSoft аватар
Offline
Зарегистрирован: 22.09.2015

Такс понял о чем вы!

Ищите код:

if (millis() - lcd_milis >= 100) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    if (menu == 0) {
      lcd_poisk();//вывод на дисплей режима поиск
      poisk_f();
    }
    if (menu == 1) {
      lcd_menu();//вывод на дисплей меню
    }
    if (menu == 2) {
      lcd_sys();//вывод на дисплей системного меню
    }
    if (menu == 3) {
      zamer_180s();//вывод на дисплей замер 180сек
    }
  }

Меняете на:

if (millis() - lcd_milis >= 100) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    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_180s();//вывод на дисплей замер 180сек
    }

  Должно все получиться...

 

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

Принял, спасибо, буду экспериментировать.

UPD. Вроде работает.

/* ArDOs   v1.063.3_beta    без режима сна
***Дозиметр на Ардуино
***IDE Arduino 1.8.2
  ветка форума 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); //подключение дисплея
//LCD5110 myGLCD(12, 11, 10, A4, A5); //подключение дисплея
#define contrast 60 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
#define first_alarm_duration 7000 //длительность сигнала тревоги при превышении первого аварийного порога в миллисекундах
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 60; //вторая ступень тревоги
byte del_BUZZ = 11;//длительность одиночного сигнала
//byte ton_BUZZ = 11; //тональность буззера
#define  ADC 163  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255)
#define k_delitel 576 //коефициент дельтеля напряжения, зависит от вашего делителя.
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool buzz_ON = 1;  //включить индикацию бузером (1)
bool podsvetka = 0; //подсветка
bool alarm_sound = 0; //флаг индикации превышения порога звуком
bool son_OK = 0; //разрешение или запрет сна
float opornoe = 1.10; //делить на opornoe/10
#define son_t 40 //время засыпания в секундах
#define save_DOZ 20 //как часто сохранять накопленную дозу например каждые 20мкР
byte beta_time = 5; //время замера бета излучения
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFont[], MediumNumbers[], TinyFont[];
extern uint8_t logo_bat[], logo_rag[], logo_tr[], gif_chast_1[], gif_chast_2[];
volatile int shet = 0;
unsigned long t_milis = 0, gr_milis = 0, lcd_milis = 0, toch_milis = 0, timer_mil = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
int hv_adc, hv_400, shet_s = 0, fon = 0, shet_gr = 0, shet_n = 0;
int speed_nakT = 0, speed_nak = 0, time_sh_l = 0, MIN, HOUR, result;
int doza_vr = 0, val_dr_pr = 0, val_dr_OK = 0;
byte mass_p[84], mass_toch[201], m = 0, n_menu = 0, sys_menu = 0, mass_36[41];
byte val_kl = 0, val_ok = 0, menu = 0, zam_180p = 0, zam_36p = 0, gif_x = 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, stat_percent = 99.0;
bool tr = 0, poisk = 1, fonarik = 0, g_fl = 0, toch;
//-------------------------------------------------------------
void setup() {
  //Serial.begin(19200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (0 << 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();
}
//-------------------------------------------------------------
void loop() {
  if (menu == 0) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      menu = 3;
      shet = 0; zam_180p = 0; fon = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 4;
      shet = 0;
      bet_z0 = 0;
      bet_z1 = 0;
      bet_r = 0;
      bet_z = 0;
      gotovo = 0;
      sek = 0;
      minute = 0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (menu == 4) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 0;
      shet = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (fonarik == 0) { //фонарик
    PORTB &= ~(1 << 1);//пин фонаря
  } else if (fonarik == 1) {
    PORTB |= (1 << 1);//пин фонаря
  }
  if (podsvetka == 1) {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
  if (podsvetka == 0) {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    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сек
    }
    if (menu == 4) {
      zamer_beta();
    }
  }
  generator();//накачка по обратной связи с АЦП
  if (shet_s != shet) {
    signa ();//подача сигнала о частичке
  }
  if (!(PIND & (1 << PIND3))) { //нажатие ок
    _delay_ms(500);//антидребезг
    OK();
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1++;
      }
      if (n_menu == 1) {
        treviga_2++;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF++;
        if (scrin_GRAF > 10) {
          scrin_GRAF = 1;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe + 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls++;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time++;
      }
    }
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1--;
      }
      if (n_menu == 1) {
        treviga_2--;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF--;
        if (scrin_GRAF < 1) {
          scrin_GRAF = 10;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe - 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls--;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time--;
      }
    }
  }

    if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------
void OK () { //нажатие ОК
  if (!(PIND & (1 << PIND3))) { //удержаиние OK
    val_ok++;
    if (val_ok == 10) {
      val_ok = 0;
      menu = 2;
    }
  }
  if (menu == 2) {
    sys_menu++;
    if (sys_menu > 5) {
      sys_menu = 0;
    }
  }
  if (menu == 1) {
    n_menu++;
    if (n_menu > 7) {
      n_menu = 0;
    }
  }
  if (menu == 0) {
    menu = 1;
  }
  if (menu == 3) {
    menu = 1;
  }
}
//--------------------------------------------------------------
void gif_nabor() {
  myGLCD.drawLine(0, 24, 84, 24); myGLCD.drawLine(0, 38, 84, 38);
  for (int i = 83 - zam_180p * 0.47; i < 84; i++) {
    myGLCD.drawLine(i, 24, i, 38);
  }
  g_fl = !g_fl;
  if (g_fl == 0) {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_1, 8, 8);
  } else {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_2, 8, 8);
  }
  if (zam_180p < 200) {
    gif_x = gif_x + 1;
    if (gif_x >= 83 - zam_180p * 0.47) {
      gif_x = 0;
    }
    myGLCD.print("ANALIZ", CENTER, 40);
  }

  if (zam_180p >= 200) {
    myGLCD.print("OBNOVLENIE", CENTER, 40);
  }
}
//--------------------------------------------------------------
void zamer_200s() {
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("%", 20, 0); myGLCD.printNumF(stat_percent, 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
      if (alarm_sound)  //сбрасываем сигнал тревоги первого уровня, если активен
    {
       res_first_alarm(); //сбрасываем сигнал тревоги 
    }
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  gif_nabor();
  battery();
  myGLCD.update();
  if (millis() - toch_milis >= 1000) {
    toch_milis = millis();
    for (int i = 0; i < 200; i++) { //сдвигаем
      mass_toch[i] = mass_toch[i + 1];
    }
    mass_toch[199] = shet;
    shet = 0;
    if (zam_180p < 200) { //первый набор массива
      zam_180p++;
      int fon_vr1 = 0;
      for (int i = 200 - zam_180p; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 * (40.0 / zam_180p);
    }
    if (zam_180p >= 200) { //набор массива
      int fon_vr1 = 0;
      for (int i = 0; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 / 5;
    }
    if (zam_180p <= 36) {
      stat_percent = stat_percent - 2.0;
    }
    if (zam_180p > 36 && zam_180p <= 72) {
      stat_percent = stat_percent - 0.3;
    }
    if (zam_180p > 72 && zam_180p <= 100) {
      stat_percent = stat_percent - 0.2;
    }
    if (zam_180p > 100 && zam_180p <= 200) {
      stat_percent = stat_percent - 0.1;
    }
    if (stat_percent < 5) {
      stat_percent = 5.0;
    }
  }
  if (!(PIND & (1 << PIND7))) { //нажатие <<<
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
    if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
      val_kl++;
      if (val_kl == 6) {
        val_kl = 0;
        fonarik = !fonarik;
      }
    }
  }
}
//--------------------------------------------------------------
void lcd_poisk() {//вывод на дисплей режима поиск
  if (shet < treviga_1 && fon < treviga_1) {//проверяем тревогу
    tr = 0;
  }
  if (shet > treviga_1 || fon > treviga_1) {//проверяем тревогу
    check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  if (tr == 1) { //опасно
    myGLCD.drawBitmap(0, 0, logo_tr, 24, 8);
  }
  myGLCD.print("%", 20, 0); myGLCD.printNumF(100 - (zam_36p * 2.0), 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  time_d ();
  myGLCD.setFont(TinyFont);
  myGLCD.printNumI(HOUR, 0, 26);
  if (HOUR >= 9) {
    myGLCD.print("h", 13, 26);
  }
  if (HOUR < 9) {
    myGLCD.print("h", 5, 26);
  }
  myGLCD.printNumI(MIN, 18, 26);
  if (MIN >= 9) {
    myGLCD.print("m", 26, 26);
  }
  if (MIN < 9) {
    myGLCD.print("m", 23, 26);
  }
  myGLCD.setFont(SmallFont);
  if (doz_v < 1000) {
    myGLCD.printNumF(doz_v, 1, 41, 24); myGLCD.print("uR", RIGHT, 24);
  }
  if (doz_v >= 1000) {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 24); myGLCD.print("mR", RIGHT, 24);
  }
  myGLCD.drawLine(0, 32, 83, 32);//верхняя
  battery();
  for (int i = 0; i < 82; i ++) { //печатаем график
    if (mass_p[i] > 0) {
      if (mass_p[i] <= 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - mass_p[i]);
      }
      if (mass_p[i] > 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - 15);
      }
    }
  }
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_menu() { //вывод на дисплей меню
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPASN.1", 0, 0); myGLCD.printNumI(treviga_1, CENTER, 0); myGLCD.print("uR/h", RIGHT, 0);
  myGLCD.print("OPASN.2", 0, 6); myGLCD.printNumI(treviga_2, CENTER, 6); myGLCD.print("uR/h", RIGHT, 6);
  myGLCD.print("PODSV.", 0, 12); myGLCD.printNumI(podsvetka, CENTER, 12);
  myGLCD.print("------", 0, 18); myGLCD.printNumI(son_OK, CENTER, 18); myGLCD.print("on/off", RIGHT, 18);//usr
  myGLCD.print("POISK.", 0, 24); myGLCD.printNumI(scrin_GRAF, CENTER, 24); myGLCD.print("SEK", RIGHT, 24);
  myGLCD.print("ZVUK", 0, 30); myGLCD.printNumI(buzz_ON, CENTER, 30);
  myGLCD.print("OUT", 0, 36);
  myGLCD.print("SAVE", 0, 42);
  myGLCD.print(">", 30, n_menu * 6);
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_sys() { //вывод на дисплей меню
  VCC_read();
  speed_nakachka ();//скорость накачки имлульсы/сек
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPORN", 0, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 55, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
  hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
  myGLCD.print("NAKAH", 0, 6); myGLCD.printNumI(puls, CENTER, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
  myGLCD.print("DOZA", 0, 12); myGLCD.print(">>", CENTER, 12); myGLCD.print("SBROS", RIGHT, 12);
  myGLCD.print("OUT", 0, 18);
  myGLCD.print("SAVE", 0, 24);
  myGLCD.print("BETA", 0, 30); myGLCD.printNumI(beta_time, CENTER, 30); myGLCD.print("MIN", RIGHT, 30);
  myGLCD.print(">", 30, sys_menu * 6);
  myGLCD.print("SPEED N", 0, 40); myGLCD.printNumI(speed_nak, CENTER, 40); myGLCD.print("imp/sek", RIGHT, 40);
  myGLCD.update();
}
//-------------------------------------------------------------
void zamer_beta() {// замер бета или продуктов
  if (gotovo == 0) {
    if (!(PIND & (1 << PIND3))) { //нажатие OK
      gotovo = 1;
      switch (bet_z) //проверяем, находимся ли в первом или втором замере
      {
        case 0: //если в первом замере
      bet_z0 = 0; //обнуляем текущие показания замера 1
      shet = 0; //обнуляем счёт
        case 1: //если во втором замере
      bet_z1 = 0; //обнуляем текущие показания замера 2
      shet = 0; //обнуляем счёт            
      }
    }
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
    {
       res_first_alarm(); //сбрасываем сигнал тревоги
    }
    myGLCD.clrScr();
    myGLCD.setFont(SmallFont);
    myGLCD.print("Zamer ", 20, 10); myGLCD.printNumI(bet_z, 55, 10);
    myGLCD.print("nagmi OK", CENTER, 20);
    myGLCD.update();
  }
  if (gotovo == 1) {
    timer_soft();
    byte otsup = 0;
    if (minute > 9) {
      otsup = 5;
    }
    myGLCD.clrScr();
    battery();
    myGLCD.setFont(TinyFont);
    myGLCD.printNumI(minute, LEFT, 0);
    if (toch == 0) {
      myGLCD.print(":", 5 + otsup, 0);
    } else {
      myGLCD.print(" ", 5 + otsup, 0);
    }
    myGLCD.printNumI(sek, 10 + otsup, 0); myGLCD.print("time", 23 + otsup, 0);
    myGLCD.drawLine(0, 8, 83, 8);
    myGLCD.setFont(SmallFont);
    myGLCD.drawLine(40, 8, 40, 28);
    myGLCD.print("Zamer0", LEFT, 10); myGLCD.print("Zamer1", RIGHT, 10);
    myGLCD.printNumI(bet_z0, LEFT, 20); myGLCD.printNumI(bet_z1, RIGHT, 20);
    myGLCD.drawLine(0, 28, 83, 28);
    if (bet_z < 2) {
      myGLCD.print("Idet zamer", CENTER, 30); myGLCD.printNumI(bet_z, RIGHT, 30);
      myGLCD.printNumI(bet_r, CENTER, 38);
    }
    if (bet_z == 2) {
      myGLCD.print("Rezultat", CENTER, 30);
      myGLCD.printNumI(bet_r, CENTER, 38); myGLCD.print("mkR/h", RIGHT, 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,70); //генерим писк 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,70); //генерим писк 2000Гц 70миллисекунд на 6й ноге		
      }
    }
    if (bet_z == 2) { //результат
      bet_r = bet_z1 - bet_z0;
      bet_r = bet_r / (1.5 * beta_time);
    }
  }
  if (!(PIND & (1 << PIND4))) { //нажатие >>>
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
  }
}
//-------------------------------------------------------------
void poisk_f() {//режим поиска
  if (poisk == 1) {
    if (millis() - gr_milis >= scrin_GRAF * 1000) { //счет для графика
      gr_milis = millis();
      val_ok = 0;//сброс удержания системного меню
      shet_gr = shet - shet_n;
      if (shet_gr < 0) {
        shet_gr = 1;
      }
      mass_p[m] = shet_gr ;
      shet_n = shet;
      if (m < 82) {
        m++;
      }
      if (m == 82) {
        for (int i = 0; i < 83; i++) {
          mass_p[i] = mass_p[i + 1];
        }
        mass_p[82] = shet_gr;
      }
    }
    if (millis() - toch_milis >= 1000) {
      toch_milis = millis();
      for (int i = 0; i < 40; i++) { //сдвигаем
        mass_36[i] = mass_36[i + 1];
      }
      mass_36[40] = shet;
      if (zam_36p < 40) { //первый набор массива
        zam_36p++;
        fon = fon + shet;
      }
      if (zam_36p >= 40) { //набор массива
        int fon_vr1 = 0;
        for (int i = 0; i < 40; i++) {
          fon_vr1 = fon_vr1 + mass_36[i];
        }
        fon = fon_vr1;
      }
      shet = 0;
      doz_v = doz_v + fon / 100.0 / 40.0;
      time_doza = time_doza + 1;
      if (doz_v - doza_vr >= save_DOZ) { //а не пора ли сохранить дозу ?)
        eeprom_wrD ();
        doza_vr = doz_v;
      }
    }
  }
}
//-------------------------------------------------------------
void signa () { //индикация каждой частички звуком светом
  shet_s = shet;  
    if (alarm_sound) //если поднят флаг аварийного сигнала
  {
  #ifdef buzzer_active //если задефайнен активный бузер
    PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
  #else //пассивный
  tone (6, 1300); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
  #endif
    if ((millis() - alarm_milis) > first_alarm_duration) // проверяем, не истекло ли время подачи сигнала тревоги_
    {
    #ifdef buzzer_active   //если задефайнен активный бузер
    PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
    #else //пассивный бузер
    noTone (6); //выключаем писк на 6й ноге
    #endif 
    alarm_sound = 0; // сбрасываем флаг сигнала тревоги
    }   
    PORTB |= (1 << 5); //включаем светодиод
    delay(del_BUZZ);
    PORTB &= ~(1 << 5);//выключаем светодиод
  }
  else //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
  {
if ((buzz_ON == 1) && (shet_s > 0))  //включаем бузер
  #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    
  }
  //generator();//накачка по обратной связи с АЦП
}
//-------------------------------------------------------------
void Schet() { //прерывание от счетчика на пин 2
  shet++;
}
//-------------------------------------------------------------
void generator() {//накачка по обратной связи с АЦП
  hv_adc  = Read_HV();
  if (hv_adc < ADC) { //Значение АЦП при котором на выходе 400В
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//-------------------------------------------------------------
byte Read_HV () {
  ADCSRA = 0b11100111;
  ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
  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.drawBitmap(59, 0, logo_bat, 24, 8);
  myGLCD.setFont(TinyFont);
  myGLCD.printNumF(VCC, 2, 63, 2);
}
//-------------------------------------------------------------
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(SmallFont);
  myGLCD.print("Arduino+", CENTER, 32);
  myGLCD.print("Dosimetr v1.06", 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, son_OK);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, buzz_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(13, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("Save OK", CENTER, 24);
  myGLCD.update();
  _delay_ms(1000);
}
//-------------------------------------------------------------
void eeprom_wrD () { //запись настроек в память время накопления дозы
  byte hi = time_doza >> 8;
  byte low = time_doza;
  EEPROM.write(9, hi);
  EEPROM.write(10, low);
  hi = int(doz_v) >> 8;
  low = int(doz_v);
  EEPROM.write(11, hi);
  EEPROM.write(12, low);
}
//-------------------------------------------------------------
void eeprom_readD () { //чтание настроек из памяти время накопления дозы
  byte hi  = EEPROM.read(9);
  byte low  = EEPROM.read(10);
  time_doza = (hi << 8) | low;
  hi  = EEPROM.read(11);
  low  = EEPROM.read(12);
  doz_v = (hi << 8) | low;
}
//-------------------------------------------------------------
void eeprom_readS () { //чтание настроек из памяти
  if (EEPROM.read(0) == 222) {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    son_OK = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    buzz_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    beta_time = EEPROM.read(13);
  }
  _delay_ms(10);
}
//-------------------------------------------------------------
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() {
  HOUR = time_doza / 3600;
  MIN = (time_doza / 60) % 60;
}
//-------------------------------------------------------------
void timer_soft() {
  if (millis() - timer_mil >= 1000) {
    timer_mil = millis();
    sek++;
    toch = !toch;
    if (sek > 60) {
      sek = 0;
      minute++;
    }
  }
}


void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
  if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
    {
    alarm_sound = 1; // поднимаем флаг аварийного сигнала
    alarm_milis = millis(); // запоминаем время начала тревоги
    }  
}


void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
  {
    alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
  }

 

ortus
Offline
Зарегистрирован: 16.10.2017

Работает! Только у меня перестал выходить во второе меню с накачкой и опорным. И еще возник вопрос, на ардуинке остались порты что бы прикрутить вот этот датчик i2c/spi bmp280 3.3?

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

Порты и2ц свободны, на них планировали повесить модуль ртц/еепром (я его и на плате распаял) для логирования фона и дозы с привязкой ко времени. 

Зачем в радиометре метеостанция - ума не приложу :) Вот наоборот - совсем другое дело.

Вход в меню второго уровня работает, просто удерживать чуть дольше приходится.

ortus
Offline
Зарегистрирован: 16.10.2017

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

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

ortus пишет:

Странно, сколько не пробовал выйти в второй уровень меню - не получается!

А так?

/* ArDOs   v1.063.3_beta    без режима сна
***Дозиметр на Ардуино
***IDE Arduino 1.8.2
  ветка форума 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); //подключение дисплея
//LCD5110 myGLCD(12, 11, 10, A4, A5); //подключение дисплея
#define contrast 60 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
#define first_alarm_duration 7000 //длительность сигнала тревоги при превышении первого аварийного порога в миллисекундах
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 60; //вторая ступень тревоги
byte del_BUZZ = 11;//длительность одиночного сигнала
//byte ton_BUZZ = 11; //тональность буззера
#define  ADC 163  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255)
#define k_delitel 576 //коефициент дельтеля напряжения, зависит от вашего делителя.
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool buzz_ON = 1;  //включить индикацию бузером (1)
bool podsvetka = 0; //подсветка
bool alarm_sound = 0; //флаг индикации превышения порога звуком
bool son_OK = 0; //разрешение или запрет сна
float opornoe = 1.10; //делить на opornoe/10
#define son_t 40 //время засыпания в секундах
#define save_DOZ 20 //как часто сохранять накопленную дозу например каждые 20мкР
byte beta_time = 5; //время замера бета излучения
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFont[], MediumNumbers[], TinyFont[];
extern uint8_t logo_bat[], logo_rag[], logo_tr[], gif_chast_1[], gif_chast_2[];
volatile int shet = 0;
unsigned long t_milis = 0, gr_milis = 0, lcd_milis = 0, toch_milis = 0, timer_mil = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
int hv_adc, hv_400, shet_s = 0, fon = 0, shet_gr = 0, shet_n = 0;
int speed_nakT = 0, speed_nak = 0, time_sh_l = 0, MIN, HOUR, result;
int doza_vr = 0, val_dr_pr = 0, val_dr_OK = 0;
byte mass_p[84], mass_toch[201], m = 0, n_menu = 0, sys_menu = 0, mass_36[41];
byte val_kl = 0, val_ok = 0, menu = 0, zam_180p = 0, zam_36p = 0, gif_x = 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, stat_percent = 99.0;
bool tr = 0, poisk = 1, fonarik = 0, g_fl = 0, toch;
//-------------------------------------------------------------
void setup() {
  //Serial.begin(19200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (0 << 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();
}
//-------------------------------------------------------------
void loop() {
  if (menu == 0) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      menu = 3;
      shet = 0; zam_180p = 0; fon = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 4;
      shet = 0;
      bet_z0 = 0;
      bet_z1 = 0;
      bet_r = 0;
      bet_z = 0;
      gotovo = 0;
      sek = 0;
      minute = 0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (menu == 4) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 0;
      shet = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (fonarik == 0) { //фонарик
    PORTB &= ~(1 << 1);//пин фонаря
  } else if (fonarik == 1) {
    PORTB |= (1 << 1);//пин фонаря
  }
  if (podsvetka == 1) {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
  if (podsvetka == 0) {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    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сек
    }
    if (menu == 4) {
      zamer_beta();
    }
  }
  generator();//накачка по обратной связи с АЦП
  if (shet_s != shet) {
    signa ();//подача сигнала о частичке
  }
  if (!(PIND & (1 << PIND3))) { //нажатие ок
    _delay_ms(500);//антидребезг
    OK();
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1++;
      }
      if (n_menu == 1) {
        treviga_2++;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF++;
        if (scrin_GRAF > 10) {
          scrin_GRAF = 1;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe + 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls++;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time++;
      }
    }
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1--;
      }
      if (n_menu == 1) {
        treviga_2--;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF--;
        if (scrin_GRAF < 1) {
          scrin_GRAF = 10;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe - 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls--;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time--;
      }
    }
  }

    if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------
void OK () { //нажатие ОК
  if (!(PIND & (1 << PIND3))) { //удержаиние OK
    val_ok++;
    if (val_ok >= 7) {
      val_ok = 0;
      menu = 2;
    }
  }
  if (menu == 2) {
    sys_menu++;
    if (sys_menu > 5) {
      sys_menu = 0;
    }
  }
  if (menu == 1) {
    n_menu++;
    if (n_menu > 7) {
      n_menu = 0;
    }
  }
  if (menu == 0) {
    menu = 1;
  }
  if (menu == 3) {
    menu = 1;
  }
}
//--------------------------------------------------------------
void gif_nabor() {
  myGLCD.drawLine(0, 24, 84, 24); myGLCD.drawLine(0, 38, 84, 38);
  for (int i = 83 - zam_180p * 0.47; i < 84; i++) {
    myGLCD.drawLine(i, 24, i, 38);
  }
  g_fl = !g_fl;
  if (g_fl == 0) {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_1, 8, 8);
  } else {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_2, 8, 8);
  }
  if (zam_180p < 200) {
    gif_x = gif_x + 1;
    if (gif_x >= 83 - zam_180p * 0.47) {
      gif_x = 0;
    }
    myGLCD.print("ANALIZ", CENTER, 40);
  }

  if (zam_180p >= 200) {
    myGLCD.print("OBNOVLENIE", CENTER, 40);
  }
}
//--------------------------------------------------------------
void zamer_200s() {
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("%", 20, 0); myGLCD.printNumF(stat_percent, 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
      if (alarm_sound)  //сбрасываем сигнал тревоги первого уровня, если активен
    {
       res_first_alarm(); //сбрасываем сигнал тревоги 
    }
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  gif_nabor();
  battery();
  myGLCD.update();
  if (millis() - toch_milis >= 1000) {
    toch_milis = millis();
    for (int i = 0; i < 200; i++) { //сдвигаем
      mass_toch[i] = mass_toch[i + 1];
    }
    mass_toch[199] = shet;
    shet = 0;
    if (zam_180p < 200) { //первый набор массива
      zam_180p++;
      int fon_vr1 = 0;
      for (int i = 200 - zam_180p; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 * (40.0 / zam_180p);
    }
    if (zam_180p >= 200) { //набор массива
      int fon_vr1 = 0;
      for (int i = 0; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 / 5;
    }
    if (zam_180p <= 36) {
      stat_percent = stat_percent - 2.0;
    }
    if (zam_180p > 36 && zam_180p <= 72) {
      stat_percent = stat_percent - 0.3;
    }
    if (zam_180p > 72 && zam_180p <= 100) {
      stat_percent = stat_percent - 0.2;
    }
    if (zam_180p > 100 && zam_180p <= 200) {
      stat_percent = stat_percent - 0.1;
    }
    if (stat_percent < 5) {
      stat_percent = 5.0;
    }
  }
  if (!(PIND & (1 << PIND7))) { //нажатие <<<
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
    if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
      val_kl++;
      if (val_kl == 6) {
        val_kl = 0;
        fonarik = !fonarik;
      }
    }
  }
}
//--------------------------------------------------------------
void lcd_poisk() {//вывод на дисплей режима поиск
  if (shet < treviga_1 && fon < treviga_1) {//проверяем тревогу
    tr = 0;
  }
  if (shet > treviga_1 || fon > treviga_1) {//проверяем тревогу
    check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  if (tr == 1) { //опасно
    myGLCD.drawBitmap(0, 0, logo_tr, 24, 8);
  }
  myGLCD.print("%", 20, 0); myGLCD.printNumF(100 - (zam_36p * 2.0), 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  time_d ();
  myGLCD.setFont(TinyFont);
  myGLCD.printNumI(HOUR, 0, 26);
  if (HOUR >= 9) {
    myGLCD.print("h", 13, 26);
  }
  if (HOUR < 9) {
    myGLCD.print("h", 5, 26);
  }
  myGLCD.printNumI(MIN, 18, 26);
  if (MIN >= 9) {
    myGLCD.print("m", 26, 26);
  }
  if (MIN < 9) {
    myGLCD.print("m", 23, 26);
  }
  myGLCD.setFont(SmallFont);
  if (doz_v < 1000) {
    myGLCD.printNumF(doz_v, 1, 41, 24); myGLCD.print("uR", RIGHT, 24);
  }
  if (doz_v >= 1000) {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 24); myGLCD.print("mR", RIGHT, 24);
  }
  myGLCD.drawLine(0, 32, 83, 32);//верхняя
  battery();
  for (int i = 0; i < 82; i ++) { //печатаем график
    if (mass_p[i] > 0) {
      if (mass_p[i] <= 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - mass_p[i]);
      }
      if (mass_p[i] > 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - 15);
      }
    }
  }
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_menu() { //вывод на дисплей меню
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPASN.1", 0, 0); myGLCD.printNumI(treviga_1, CENTER, 0); myGLCD.print("uR/h", RIGHT, 0);
  myGLCD.print("OPASN.2", 0, 6); myGLCD.printNumI(treviga_2, CENTER, 6); myGLCD.print("uR/h", RIGHT, 6);
  myGLCD.print("PODSV.", 0, 12); myGLCD.printNumI(podsvetka, CENTER, 12);
  myGLCD.print("------", 0, 18); myGLCD.printNumI(son_OK, CENTER, 18); myGLCD.print("on/off", RIGHT, 18);//usr
  myGLCD.print("POISK.", 0, 24); myGLCD.printNumI(scrin_GRAF, CENTER, 24); myGLCD.print("SEK", RIGHT, 24);
  myGLCD.print("ZVUK", 0, 30); myGLCD.printNumI(buzz_ON, CENTER, 30);
  myGLCD.print("OUT", 0, 36);
  myGLCD.print("SAVE", 0, 42);
  myGLCD.print(">", 30, n_menu * 6);
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_sys() { //вывод на дисплей меню
  VCC_read();
  speed_nakachka ();//скорость накачки имлульсы/сек
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPORN", 0, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 55, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
  hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
  myGLCD.print("NAKAH", 0, 6); myGLCD.printNumI(puls, CENTER, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
  myGLCD.print("DOZA", 0, 12); myGLCD.print(">>", CENTER, 12); myGLCD.print("SBROS", RIGHT, 12);
  myGLCD.print("OUT", 0, 18);
  myGLCD.print("SAVE", 0, 24);
  myGLCD.print("BETA", 0, 30); myGLCD.printNumI(beta_time, CENTER, 30); myGLCD.print("MIN", RIGHT, 30);
  myGLCD.print(">", 30, sys_menu * 6);
  myGLCD.print("SPEED N", 0, 40); myGLCD.printNumI(speed_nak, CENTER, 40); myGLCD.print("imp/sek", RIGHT, 40);
  myGLCD.update();
}
//-------------------------------------------------------------
void zamer_beta() {// замер бета или продуктов
  if (gotovo == 0) {
    if (!(PIND & (1 << PIND3))) { //нажатие OK
      gotovo = 1;
      switch (bet_z) //проверяем, находимся ли в первом или втором замере
      {
        case 0: //если в первом замере
      bet_z0 = 0; //обнуляем текущие показания замера 1
      shet = 0; //обнуляем счёт
        case 1: //если во втором замере
      bet_z1 = 0; //обнуляем текущие показания замера 2
      shet = 0; //обнуляем счёт            
      }
    }
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
    {
       res_first_alarm(); //сбрасываем сигнал тревоги
    }
    myGLCD.clrScr();
    myGLCD.setFont(SmallFont);
    myGLCD.print("Zamer ", 20, 10); myGLCD.printNumI(bet_z, 55, 10);
    myGLCD.print("nagmi OK", CENTER, 20);
    myGLCD.update();
  }
  if (gotovo == 1) {
    timer_soft();
    byte otsup = 0;
    if (minute > 9) {
      otsup = 5;
    }
    myGLCD.clrScr();
    battery();
    myGLCD.setFont(TinyFont);
    myGLCD.printNumI(minute, LEFT, 0);
    if (toch == 0) {
      myGLCD.print(":", 5 + otsup, 0);
    } else {
      myGLCD.print(" ", 5 + otsup, 0);
    }
    myGLCD.printNumI(sek, 10 + otsup, 0); myGLCD.print("time", 23 + otsup, 0);
    myGLCD.drawLine(0, 8, 83, 8);
    myGLCD.setFont(SmallFont);
    myGLCD.drawLine(40, 8, 40, 28);
    myGLCD.print("Zamer0", LEFT, 10); myGLCD.print("Zamer1", RIGHT, 10);
    myGLCD.printNumI(bet_z0, LEFT, 20); myGLCD.printNumI(bet_z1, RIGHT, 20);
    myGLCD.drawLine(0, 28, 83, 28);
    if (bet_z < 2) {
      myGLCD.print("Idet zamer", CENTER, 30); myGLCD.printNumI(bet_z, RIGHT, 30);
      myGLCD.printNumI(bet_r, CENTER, 38);
    }
    if (bet_z == 2) {
      myGLCD.print("Rezultat", CENTER, 30);
      myGLCD.printNumI(bet_r, CENTER, 38); myGLCD.print("mkR/h", RIGHT, 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,70); //генерим писк 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,70); //генерим писк 2000Гц 70миллисекунд на 6й ноге		
      }
    }
    if (bet_z == 2) { //результат
      bet_r = bet_z1 - bet_z0;
      bet_r = bet_r / (1.5 * beta_time);
    }
  }
  if (!(PIND & (1 << PIND4))) { //нажатие >>>
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
  }
}
//-------------------------------------------------------------
void poisk_f() {//режим поиска
  if (poisk == 1) {
    if (millis() - gr_milis >= scrin_GRAF * 1000) { //счет для графика
      gr_milis = millis();
      val_ok = 0;//сброс удержания системного меню
      shet_gr = shet - shet_n;
      if (shet_gr < 0) {
        shet_gr = 1;
      }
      mass_p[m] = shet_gr ;
      shet_n = shet;
      if (m < 82) {
        m++;
      }
      if (m == 82) {
        for (int i = 0; i < 83; i++) {
          mass_p[i] = mass_p[i + 1];
        }
        mass_p[82] = shet_gr;
      }
    }
    if (millis() - toch_milis >= 1000) {
      toch_milis = millis();
      for (int i = 0; i < 40; i++) { //сдвигаем
        mass_36[i] = mass_36[i + 1];
      }
      mass_36[40] = shet;
      if (zam_36p < 40) { //первый набор массива
        zam_36p++;
        fon = fon + shet;
      }
      if (zam_36p >= 40) { //набор массива
        int fon_vr1 = 0;
        for (int i = 0; i < 40; i++) {
          fon_vr1 = fon_vr1 + mass_36[i];
        }
        fon = fon_vr1;
      }
      shet = 0;
      doz_v = doz_v + fon / 100.0 / 40.0;
      time_doza = time_doza + 1;
      if (doz_v - doza_vr >= save_DOZ) { //а не пора ли сохранить дозу ?)
        eeprom_wrD ();
        doza_vr = doz_v;
      }
    }
  }
}
//-------------------------------------------------------------
void signa () { //индикация каждой частички звуком светом
  shet_s = shet;  
    if (alarm_sound) //если поднят флаг аварийного сигнала
  {
  #ifdef buzzer_active //если задефайнен активный бузер
    PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
  #else //пассивный
  tone (6, 1300); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
  #endif
    if ((millis() - alarm_milis) > first_alarm_duration) // проверяем, не истекло ли время подачи сигнала тревоги_
    {
    #ifdef buzzer_active   //если задефайнен активный бузер
    PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
    #else //пассивный бузер
    noTone (6); //выключаем писк на 6й ноге
    #endif 
    alarm_sound = 0; // сбрасываем флаг сигнала тревоги
    }   
    PORTB |= (1 << 5); //включаем светодиод
    delay(del_BUZZ);
    PORTB &= ~(1 << 5);//выключаем светодиод
  }
  else //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
  {
if ((buzz_ON == 1) && (shet_s > 0))  //включаем бузер
  #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    
  }
  //generator();//накачка по обратной связи с АЦП
}
//-------------------------------------------------------------
void Schet() { //прерывание от счетчика на пин 2
  shet++;
}
//-------------------------------------------------------------
void generator() {//накачка по обратной связи с АЦП
  hv_adc  = Read_HV();
  if (hv_adc < ADC) { //Значение АЦП при котором на выходе 400В
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//-------------------------------------------------------------
byte Read_HV () {
  ADCSRA = 0b11100111;
  ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
  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.drawBitmap(59, 0, logo_bat, 24, 8);
  myGLCD.setFont(TinyFont);
  myGLCD.printNumF(VCC, 2, 63, 2);
}
//-------------------------------------------------------------
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(SmallFont);
  myGLCD.print("Arduino+", CENTER, 32);
  myGLCD.print("Dosimetr v1.06", 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, son_OK);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, buzz_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(13, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("Save OK", CENTER, 24);
  myGLCD.update();
  _delay_ms(1000);
}
//-------------------------------------------------------------
void eeprom_wrD () { //запись настроек в память время накопления дозы
  byte hi = time_doza >> 8;
  byte low = time_doza;
  EEPROM.write(9, hi);
  EEPROM.write(10, low);
  hi = int(doz_v) >> 8;
  low = int(doz_v);
  EEPROM.write(11, hi);
  EEPROM.write(12, low);
}
//-------------------------------------------------------------
void eeprom_readD () { //чтание настроек из памяти время накопления дозы
  byte hi  = EEPROM.read(9);
  byte low  = EEPROM.read(10);
  time_doza = (hi << 8) | low;
  hi  = EEPROM.read(11);
  low  = EEPROM.read(12);
  doz_v = (hi << 8) | low;
}
//-------------------------------------------------------------
void eeprom_readS () { //чтание настроек из памяти
  if (EEPROM.read(0) == 222) {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    son_OK = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    buzz_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    beta_time = EEPROM.read(13);
  }
  _delay_ms(10);
}
//-------------------------------------------------------------
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() {
  HOUR = time_doza / 3600;
  MIN = (time_doza / 60) % 60;
}
//-------------------------------------------------------------
void timer_soft() {
  if (millis() - timer_mil >= 1000) {
    timer_mil = millis();
    sek++;
    toch = !toch;
    if (sek > 60) {
      sek = 0;
      minute++;
    }
  }
}


void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
  if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
    {
    alarm_sound = 1; // поднимаем флаг аварийного сигнала
    alarm_milis = millis(); // запоминаем время начала тревоги
    }  
}


void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
  {
    alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
  }

 

ortus
Offline
Зарегистрирован: 16.10.2017

Увы, по прежнему выйти не могу(((((((

 

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

Кумыса на форуме нет, мейл у Вас какой? Или отпишитесь мне, t.e.k.a.g.i на яндексе.

ortus
Offline
Зарегистрирован: 16.10.2017
if (millis() - lcd_milis >= 300) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    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сек
    }

закоментил строчку, стало выходить в системное меню.... странно...

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

Зато по выходу из меню будет скачок фона. В функции poisk_f() происходит сброс переменной, ответственной за детектирование удержания кнопки "меню". Но эта же функция ответственна за счёт фона. То есть вернулись к багу.

Попробуйте уменьшить значение в строке

    if (val_ok >= 7) {

 

ortus
Offline
Зарегистрирован: 16.10.2017

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

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

Залейте этот тестовый скетч , откройте сериал монитор (19200), понажимайте с удержанием меню и скиньте сюда лог под спойлер.

/* ArDOs   v1.063.3_beta    без режима сна
***Дозиметр на Ардуино
***IDE Arduino 1.8.2
  ветка форума 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); //подключение дисплея
//LCD5110 myGLCD(12, 11, 10, A4, A5); //подключение дисплея
#define contrast 60 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
#define first_alarm_duration 7000 //длительность сигнала тревоги при превышении первого аварийного порога в миллисекундах
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 60; //вторая ступень тревоги
byte del_BUZZ = 11;//длительность одиночного сигнала
//byte ton_BUZZ = 11; //тональность буззера
#define  ADC 163  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255)
#define k_delitel 576 //коефициент дельтеля напряжения, зависит от вашего делителя.
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool buzz_ON = 1;  //включить индикацию бузером (1)
bool podsvetka = 0; //подсветка
bool alarm_sound = 0; //флаг индикации превышения порога звуком
bool son_OK = 0; //разрешение или запрет сна
float opornoe = 1.10; //делить на opornoe/10
#define son_t 40 //время засыпания в секундах
#define save_DOZ 15 //как часто сохранять накопленную дозу например каждые 20мкР
byte beta_time = 5; //время замера бета излучения
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFont[], MediumNumbers[], TinyFont[];
extern uint8_t logo_bat[], logo_rag[], logo_tr[], gif_chast_1[], gif_chast_2[];
volatile int shet = 0;
unsigned long t_milis = 0, gr_milis = 0, lcd_milis = 0, toch_milis = 0, timer_mil = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
int hv_adc, hv_400, shet_s = 0, fon = 0, shet_gr = 0, shet_n = 0;
int speed_nakT = 0, speed_nak = 0, time_sh_l = 0, MIN, HOUR, result;
int doza_vr = 0, val_dr_pr = 0, val_dr_OK = 0;
byte mass_p[84], mass_toch[201], m = 0, n_menu = 0, sys_menu = 0, mass_36[41];
byte val_kl = 0, val_ok = 0, menu = 0, zam_180p = 0, zam_36p = 0, gif_x = 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, stat_percent = 99.0;
bool tr = 0, poisk = 1, fonarik = 0, g_fl = 0, toch;
//-------------------------------------------------------------
void setup() {
  Serial.begin(19200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (0 << 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();
}
//-------------------------------------------------------------
void loop() {
  if (menu == 0) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      menu = 3;
      shet = 0; zam_180p = 0; fon = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 4;
      shet = 0;
      bet_z0 = 0;
      bet_z1 = 0;
      bet_r = 0;
      bet_z = 0;
      gotovo = 0;
      sek = 0;
      minute = 0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (menu == 4) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 0;
      shet = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (fonarik == 0) { //фонарик
    PORTB &= ~(1 << 1);//пин фонаря
  } else if (fonarik == 1) {
    PORTB |= (1 << 1);//пин фонаря
  }
  if (podsvetka == 1) {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
  if (podsvetka == 0) {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    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сек
    }
    if (menu == 4) {
      zamer_beta();
    }
  }
  generator();//накачка по обратной связи с АЦП
  if (shet_s != shet) {
    signa ();//подача сигнала о частичке
  }
  if (!(PIND & (1 << PIND3))) { //нажатие ок
    _delay_ms(500);//антидребезг
    OK();
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1++;
      }
      if (n_menu == 1) {
        treviga_2++;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF++;
        if (scrin_GRAF > 10) {
          scrin_GRAF = 1;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe + 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls++;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time++;
      }
    }
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1--;
      }
      if (n_menu == 1) {
        treviga_2--;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF--;
        if (scrin_GRAF < 1) {
          scrin_GRAF = 10;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe - 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls--;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time--;
      }
    }
  }

    if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------
void OK () { //нажатие ОК
Serial.println("pressed OK");

  if (!(PIND & (1 << PIND3))) { //удержаиние OK
    val_ok++;
	Serial.println("holding OK  ");
	Serial.println(val_ok);	
    if (val_ok >= 7) {
      val_ok = 0;
      menu = 2;
    }
  }
  if (menu == 2) {
    sys_menu++;
    if (sys_menu > 5) {
      sys_menu = 0;
    }
  }
  if (menu == 1) {
    n_menu++;
    if (n_menu > 7) {
      n_menu = 0;
    }
  }
  if (menu == 0) {
    menu = 1;
  }
  if (menu == 3) {
    menu = 1;
  }
}
//--------------------------------------------------------------
void gif_nabor() {
  myGLCD.drawLine(0, 24, 84, 24); myGLCD.drawLine(0, 38, 84, 38);
  for (int i = 83 - zam_180p * 0.47; i < 84; i++) {
    myGLCD.drawLine(i, 24, i, 38);
  }
  g_fl = !g_fl;
  if (g_fl == 0) {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_1, 8, 8);
  } else {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_2, 8, 8);
  }
  if (zam_180p < 200) {
    gif_x = gif_x + 1;
    if (gif_x >= 83 - zam_180p * 0.47) {
      gif_x = 0;
    }
    myGLCD.print("ANALIZ", CENTER, 40);
  }

  if (zam_180p >= 200) {
    myGLCD.print("OBNOVLENIE", CENTER, 40);
  }
}
//--------------------------------------------------------------
void zamer_200s() {
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("%", 20, 0); myGLCD.printNumF(stat_percent, 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
      if (alarm_sound)  //сбрасываем сигнал тревоги первого уровня, если активен
    {
       res_first_alarm(); //сбрасываем сигнал тревоги 
    }
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  gif_nabor();
  battery();
  myGLCD.update();
  if (millis() - toch_milis >= 1000) {
    toch_milis = millis();
    for (int i = 0; i < 200; i++) { //сдвигаем
      mass_toch[i] = mass_toch[i + 1];
    }
    mass_toch[199] = shet;
    shet = 0;
    if (zam_180p < 200) { //первый набор массива
      zam_180p++;
      int fon_vr1 = 0;
      for (int i = 200 - zam_180p; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 * (40.0 / zam_180p);
    }
    if (zam_180p >= 200) { //набор массива
      int fon_vr1 = 0;
      for (int i = 0; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 / 5;
    }
    if (zam_180p <= 36) {
      stat_percent = stat_percent - 2.0;
    }
    if (zam_180p > 36 && zam_180p <= 72) {
      stat_percent = stat_percent - 0.3;
    }
    if (zam_180p > 72 && zam_180p <= 100) {
      stat_percent = stat_percent - 0.2;
    }
    if (zam_180p > 100 && zam_180p <= 200) {
      stat_percent = stat_percent - 0.1;
    }
    if (stat_percent < 5) {
      stat_percent = 5.0;
    }
  }
  if (!(PIND & (1 << PIND7))) { //нажатие <<<
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
    if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
      val_kl++;
      if (val_kl == 6) {
        val_kl = 0;
        fonarik = !fonarik;
      }
    }
  }
}
//--------------------------------------------------------------
void lcd_poisk() {//вывод на дисплей режима поиск
  if (shet < treviga_1 && fon < treviga_1) {//проверяем тревогу
    tr = 0;
  }
  if (shet > treviga_1 || fon > treviga_1) {//проверяем тревогу
    check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  if (tr == 1) { //опасно
    myGLCD.drawBitmap(0, 0, logo_tr, 24, 8);
  }
  myGLCD.print("%", 20, 0); myGLCD.printNumF(100 - (zam_36p * 2.0), 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  time_d ();
  myGLCD.setFont(TinyFont);
  myGLCD.printNumI(HOUR, 0, 26);
  if (HOUR >= 9) {
    myGLCD.print("h", 13, 26);
  }
  if (HOUR < 9) {
    myGLCD.print("h", 5, 26);
  }
  myGLCD.printNumI(MIN, 18, 26);
  if (MIN >= 9) {
    myGLCD.print("m", 26, 26);
  }
  if (MIN < 9) {
    myGLCD.print("m", 23, 26);
  }
  myGLCD.setFont(SmallFont);
  if (doz_v < 1000) {
    myGLCD.printNumF(doz_v, 1, 41, 24); myGLCD.print("uR", RIGHT, 24);
  }
  if (doz_v >= 1000) {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 24); myGLCD.print("mR", RIGHT, 24);
  }
  myGLCD.drawLine(0, 32, 83, 32);//верхняя
  battery();
  for (int i = 0; i < 82; i ++) { //печатаем график
    if (mass_p[i] > 0) {
      if (mass_p[i] <= 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - mass_p[i]);
      }
      if (mass_p[i] > 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - 15);
      }
    }
  }
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_menu() { //вывод на дисплей меню
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPASN.1", 0, 0); myGLCD.printNumI(treviga_1, CENTER, 0); myGLCD.print("uR/h", RIGHT, 0);
  myGLCD.print("OPASN.2", 0, 6); myGLCD.printNumI(treviga_2, CENTER, 6); myGLCD.print("uR/h", RIGHT, 6);
  myGLCD.print("PODSV.", 0, 12); myGLCD.printNumI(podsvetka, CENTER, 12);
  myGLCD.print("------", 0, 18); myGLCD.printNumI(son_OK, CENTER, 18); myGLCD.print("on/off", RIGHT, 18);//usr
  myGLCD.print("POISK.", 0, 24); myGLCD.printNumI(scrin_GRAF, CENTER, 24); myGLCD.print("SEK", RIGHT, 24);
  myGLCD.print("ZVUK", 0, 30); myGLCD.printNumI(buzz_ON, CENTER, 30);
  myGLCD.print("OUT", 0, 36);
  myGLCD.print("SAVE", 0, 42);
  myGLCD.print(">", 30, n_menu * 6);
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_sys() { //вывод на дисплей меню
  VCC_read();
  speed_nakachka ();//скорость накачки имлульсы/сек
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPORN", 0, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 55, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
  hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
  myGLCD.print("NAKAH", 0, 6); myGLCD.printNumI(puls, CENTER, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
  myGLCD.print("DOZA", 0, 12); myGLCD.print(">>", CENTER, 12); myGLCD.print("SBROS", RIGHT, 12);
  myGLCD.print("OUT", 0, 18);
  myGLCD.print("SAVE", 0, 24);
  myGLCD.print("BETA", 0, 30); myGLCD.printNumI(beta_time, CENTER, 30); myGLCD.print("MIN", RIGHT, 30);
  myGLCD.print(">", 30, sys_menu * 6);
  myGLCD.print("SPEED N", 0, 40); myGLCD.printNumI(speed_nak, CENTER, 40); myGLCD.print("imp/sek", RIGHT, 40);
  myGLCD.update();
}
//-------------------------------------------------------------
void zamer_beta() {// замер бета или продуктов
  if (gotovo == 0) {
    if (!(PIND & (1 << PIND3))) { //нажатие OK
      gotovo = 1;
      switch (bet_z) //проверяем, находимся ли в первом или втором замере
      {
        case 0: //если в первом замере
      bet_z0 = 0; //обнуляем текущие показания замера 1
      shet = 0; //обнуляем счёт
        case 1: //если во втором замере
      bet_z1 = 0; //обнуляем текущие показания замера 2
      shet = 0; //обнуляем счёт            
      }
    }
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
    {
       res_first_alarm(); //сбрасываем сигнал тревоги
    }
    myGLCD.clrScr();
    myGLCD.setFont(SmallFont);
    myGLCD.print("Zamer ", 20, 10); myGLCD.printNumI(bet_z, 55, 10);
    myGLCD.print("nagmi OK", CENTER, 20);
    myGLCD.update();
  }
  if (gotovo == 1) {
    timer_soft();
    byte otsup = 0;
    if (minute > 9) {
      otsup = 5;
    }
    myGLCD.clrScr();
    battery();
    myGLCD.setFont(TinyFont);
    myGLCD.printNumI(minute, LEFT, 0);
    if (toch == 0) {
      myGLCD.print(":", 5 + otsup, 0);
    } else {
      myGLCD.print(" ", 5 + otsup, 0);
    }
    myGLCD.printNumI(sek, 10 + otsup, 0); myGLCD.print("time", 23 + otsup, 0);
    myGLCD.drawLine(0, 8, 83, 8);
    myGLCD.setFont(SmallFont);
    myGLCD.drawLine(40, 8, 40, 28);
    myGLCD.print("Zamer0", LEFT, 10); myGLCD.print("Zamer1", RIGHT, 10);
    myGLCD.printNumI(bet_z0, LEFT, 20); myGLCD.printNumI(bet_z1, RIGHT, 20);
    myGLCD.drawLine(0, 28, 83, 28);
    if (bet_z < 2) {
      myGLCD.print("Idet zamer", CENTER, 30); myGLCD.printNumI(bet_z, RIGHT, 30);
      myGLCD.printNumI(bet_r, CENTER, 38);
    }
    if (bet_z == 2) {
      myGLCD.print("Rezultat", CENTER, 30);
      myGLCD.printNumI(bet_r, CENTER, 38); myGLCD.print("mkR/h", RIGHT, 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,70); //генерим писк 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,70); //генерим писк 2000Гц 70миллисекунд на 6й ноге		
      }
    }
    if (bet_z == 2) { //результат
      bet_r = bet_z1 - bet_z0;
      bet_r = bet_r / (1.5 * beta_time);
    }
  }
  if (!(PIND & (1 << PIND4))) { //нажатие >>>
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
  }
}
//-------------------------------------------------------------
void poisk_f() {//режим поиска
  if (poisk == 1) {
    if (millis() - gr_milis >= scrin_GRAF * 1000) { //счет для графика
      gr_milis = millis();
      val_ok = 0;//сброс удержания системного меню
Serial.println("null");
      shet_gr = shet - shet_n;
      if (shet_gr < 0) {
        shet_gr = 1;
      }
      mass_p[m] = shet_gr ;
      shet_n = shet;
      if (m < 82) {
        m++;
      }
      if (m == 82) {
        for (int i = 0; i < 83; i++) {
          mass_p[i] = mass_p[i + 1];
        }
        mass_p[82] = shet_gr;
      }
    }
    if (millis() - toch_milis >= 1000) {
      toch_milis = millis();
      for (int i = 0; i < 40; i++) { //сдвигаем
        mass_36[i] = mass_36[i + 1];
      }
      mass_36[40] = shet;
      if (zam_36p < 40) { //первый набор массива
        zam_36p++;
        fon = fon + shet;
      }
      if (zam_36p >= 40) { //набор массива
        int fon_vr1 = 0;
        for (int i = 0; i < 40; i++) {
          fon_vr1 = fon_vr1 + mass_36[i];
        }
        fon = fon_vr1;
      }
      shet = 0;
      doz_v = doz_v + fon / 100.0 / 40.0;
      time_doza = time_doza + 1;
      if (doz_v - doza_vr >= save_DOZ) { //а не пора ли сохранить дозу ?)
        eeprom_wrD ();
        doza_vr = doz_v;
      }
    }
  }
}
//-------------------------------------------------------------
void signa () { //индикация каждой частички звуком светом
  shet_s = shet;  
    if (alarm_sound) //если поднят флаг аварийного сигнала
  {
  #ifdef buzzer_active //если задефайнен активный бузер
    PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
  #else //пассивный
  tone (6, 1300); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
  #endif
    if ((millis() - alarm_milis) > first_alarm_duration) // проверяем, не истекло ли время подачи сигнала тревоги_
    {
    #ifdef buzzer_active   //если задефайнен активный бузер
    PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
    #else //пассивный бузер
    noTone (6); //выключаем писк на 6й ноге
    #endif 
    alarm_sound = 0; // сбрасываем флаг сигнала тревоги
    }   
    PORTB |= (1 << 5); //включаем светодиод
    delay(del_BUZZ);
    PORTB &= ~(1 << 5);//выключаем светодиод
  }
  else //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
  {
if ((buzz_ON == 1) && (shet_s > 0))  //включаем бузер
  #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    
  }
  //generator();//накачка по обратной связи с АЦП
}
//-------------------------------------------------------------
void Schet() { //прерывание от счетчика на пин 2
  shet++;
}
//-------------------------------------------------------------
void generator() {//накачка по обратной связи с АЦП
  hv_adc  = Read_HV();
  if (hv_adc < ADC) { //Значение АЦП при котором на выходе 400В
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//-------------------------------------------------------------
byte Read_HV () {
  ADCSRA = 0b11100111;
  ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
  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.drawBitmap(59, 0, logo_bat, 24, 8);
  myGLCD.setFont(TinyFont);
  myGLCD.printNumF(VCC, 2, 63, 2);
}
//-------------------------------------------------------------
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(SmallFont);
  myGLCD.print("Arduino+", CENTER, 32);
  myGLCD.print("Dosimetr v1.06", 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, son_OK);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, buzz_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(13, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("Save OK", CENTER, 24);
  myGLCD.update();
  _delay_ms(1000);
}
//-------------------------------------------------------------
void eeprom_wrD () { //запись настроек в память время накопления дозы
  byte hi = time_doza >> 8;
  byte low = time_doza;
  EEPROM.write(9, hi);
  EEPROM.write(10, low);
  hi = int(doz_v) >> 8;
  low = int(doz_v);
  EEPROM.write(11, hi);
  EEPROM.write(12, low);
}
//-------------------------------------------------------------
void eeprom_readD () { //чтание настроек из памяти время накопления дозы
  byte hi  = EEPROM.read(9);
  byte low  = EEPROM.read(10);
  time_doza = (hi << 8) | low;
  hi  = EEPROM.read(11);
  low  = EEPROM.read(12);
  doz_v = (hi << 8) | low;
}
//-------------------------------------------------------------
void eeprom_readS () { //чтание настроек из памяти
  if (EEPROM.read(0) == 222) {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    son_OK = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    buzz_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    beta_time = EEPROM.read(13);
  }
  _delay_ms(10);
}
//-------------------------------------------------------------
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() {
  HOUR = time_doza / 3600;
  MIN = (time_doza / 60) % 60;
}
//-------------------------------------------------------------
void timer_soft() {
  if (millis() - timer_mil >= 1000) {
    timer_mil = millis();
    sek++;
    toch = !toch;
    if (sek > 60) {
      sek = 0;
      minute++;
    }
  }
}


void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
  if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
    {
    alarm_sound = 1; // поднимаем флаг аварийного сигнала
    alarm_milis = millis(); // запоминаем время начала тревоги
    }  
}


void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
  {
    alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
  }


ortus пишет:

скачков не наблюдаю после выхода из системного меню... из меню - подскакивает

Ну дык всё верно, вызов функции счёта из пользовательского меню Вы отключили, из системного - нет.

Norsemen
Offline
Зарегистрирован: 08.07.2017

А зачем так много последовательно резисторов? Нельзя ли заменить меньшим количеством, но с тем же результирующим сопротивлением? И почему подается на HV в схеме с сайта "srukami.inf.ua"  126,6 Мом, а на этой странице 60 Мом  ?

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

Norsemen пишет:

А зачем так много последовательно резисторов? Нельзя ли заменить меньшим количеством, но с тем же результирующим сопротивлением?

Можно. Просто многие при сборке испытывают трудности с доставанием резисторов свыше 10МОм. Ну и желательно несколько резисторов, чтобы уменьшить вероятность утечки/пробоя по плате, и меньше скажется влияние материала платы и компаунда. Или слоты под резисторами в плате резать.

126,6МОм получилось, когда bodriy2014 выгреб из закромов все свои высокоомные резисторы))

Norsemen пишет:

И почему подается на HV в схеме с сайта "srukami.inf.ua"  126,6 Мом, а на этой странице 60 Мом  ?

В принципе делитель можно сделать в довольно таки широком диапазоне сопротивлений (в разумных пределах, пробовали 60-130МОм), пересчитав и задав соответствующие коэффициенты в скетче. Меньше сопротивление - чуть ниже экономичность, больше - чуть ниже стабильность и выше требования к чистоте и изоляции платы.

В выкладываемых  скетчах стараюсь сохранять коэффициенты для схемы с сайта srukami (когда не забываю изменить, у меня другие).

ortus
Offline
Зарегистрирован: 16.10.2017

null null null null pressed OK null pressed OK null pressed OK holding OK 1 pressed OK null pressed OK null null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK holding OK 2 null pressed OK holding OK 1 pressed OK null null

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

Пробуйте так:

/* ArDOs   v1.063.3_beta    без режима сна
***Дозиметр на Ардуино
***IDE Arduino 1.8.2
  ветка форума 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); //подключение дисплея
//LCD5110 myGLCD(12, 11, 10, A4, A5); //подключение дисплея
#define contrast 60 //контрастность дисплея
//#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой.
#define first_alarm_duration 7000 //длительность сигнала тревоги при превышении первого аварийного порога в миллисекундах
byte treviga_1 = 30; //первая ступень тревоги
byte treviga_2 = 60; //вторая ступень тревоги
byte del_BUZZ = 11;//длительность одиночного сигнала
//byte ton_BUZZ = 11; //тональность буззера
#define  ADC 163  //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255)
#define k_delitel 576 //коефициент дельтеля напряжения, зависит от вашего делителя.
byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса
byte scrin_GRAF = 1; //скорость построения графика в секундах
bool buzz_ON = 1;  //включить индикацию бузером (1)
bool podsvetka = 0; //подсветка
bool alarm_sound = 0; //флаг индикации превышения порога звуком
bool son_OK = 0; //разрешение или запрет сна
float opornoe = 1.10; //делить на opornoe/10
#define son_t 40 //время засыпания в секундах
#define save_DOZ 20 //как часто сохранять накопленную дозу например каждые 20мкР
byte beta_time = 5; //время замера бета излучения
//настройки //////////////конец
//служебные переменные
extern uint8_t SmallFont[], MediumNumbers[], TinyFont[];
extern uint8_t logo_bat[], logo_rag[], logo_tr[], gif_chast_1[], gif_chast_2[];
volatile int shet = 0;
unsigned long t_milis = 0, gr_milis = 0, lcd_milis = 0, toch_milis = 0, timer_mil = 0;
unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога
unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0;
int hv_adc, hv_400, shet_s = 0, fon = 0, shet_gr = 0, shet_n = 0;
int speed_nakT = 0, speed_nak = 0, time_sh_l = 0, MIN, HOUR, result;
int doza_vr = 0, val_dr_pr = 0, val_dr_OK = 0;
byte mass_p[84], mass_toch[201], m = 0, n_menu = 0, sys_menu = 0, mass_36[41];
byte val_kl = 0, val_ok = 0, menu = 0, zam_180p = 0, zam_36p = 0, gif_x = 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, stat_percent = 99.0;
bool tr = 0, poisk = 1, fonarik = 0, g_fl = 0, toch;
//-------------------------------------------------------------
void setup() {
  //Serial.begin(19200);
  ACSR |= 1 << ACD; //отключаем компаратор
  //ADCSRA &= ~(1 << ADEN);  // отключаем АЦП,
  pinMode(3, INPUT_PULLUP); //кнопка
  pinMode(4, INPUT_PULLUP); //кнопка
  pinMode(7, INPUT_PULLUP); //кнопка
  DDRB |= (0 << 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();
}
//-------------------------------------------------------------
void loop() {
  if (menu == 0) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      menu = 3;
      shet = 0; zam_180p = 0; fon = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 4;
      shet = 0;
      bet_z0 = 0;
      bet_z1 = 0;
      bet_r = 0;
      bet_z = 0;
      gotovo = 0;
      sek = 0;
      minute = 0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (menu == 4) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      menu = 0;
      shet = 0;
      stat_percent = 99.0;
      if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
        val_kl++;
        if (val_kl == 6) {
          val_kl = 0;
          fonarik = !fonarik;
        }
      }
    }
  }
  if (fonarik == 0) { //фонарик
    PORTB &= ~(1 << 1);//пин фонаря
  } else if (fonarik == 1) {
    PORTB |= (1 << 1);//пин фонаря
  }
  if (podsvetka == 1) {
    PORTC &= ~(1 << 2); //A2 дисплей Light
  }
  if (podsvetka == 0) {
    PORTC |= (1 << 2); //A2 дисплей Light
  }
  if (millis() - lcd_milis >= 300) { //скорость отрисоаки дисплея
    lcd_milis = millis();
    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сек
    }
    if (menu == 4) {
      zamer_beta();
    }
  }
  generator();//накачка по обратной связи с АЦП
  if (shet_s != shet) {
    signa ();//подача сигнала о частичке
  }
  if (!(PIND & (1 << PIND3))) { //нажатие ок
    _delay_ms(500);//антидребезг
    OK();
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1++;
      }
      if (n_menu == 1) {
        treviga_2++;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF++;
        if (scrin_GRAF > 10) {
          scrin_GRAF = 1;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND4))) { //нажатие >>>
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe + 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls++;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time++;
      }
    }
  }
  if (menu == 1) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (n_menu == 0) {
        treviga_1--;
      }
      if (n_menu == 1) {
        treviga_2--;
      }
      if (n_menu == 2) {
        podsvetka = !podsvetka;
      }
      if (n_menu == 3) {
        son_OK = !son_OK;
      }
      if (n_menu == 4) {
        scrin_GRAF--;
        if (scrin_GRAF < 1) {
          scrin_GRAF = 10;
        }
      }
      if (n_menu == 5) {
        buzz_ON = !buzz_ON;
      }
      if (n_menu == 6) {
        menu = 0;
      }
      if (n_menu == 7) {
        eeprom_wrS ();
        menu = 0;
      }
    }
  }
  if (menu == 2) {
    if (!(PIND & (1 << PIND7))) { //нажатие <<<
      _delay_ms(500);//антидребезг
      if (sys_menu == 0) {
        opornoe = opornoe - 0.01;
        if (opornoe < 0.98) {
          opornoe = 1.20;
        }
        if (opornoe > 1.20) {
          opornoe = 0.98;
        }
      }
      if (sys_menu == 1) {
        puls--;
        if (puls < 1) {
          puls = 200;
        }
        if (puls > 200) {
          puls = 1;
        }
      }
      if (sys_menu == 2) {
        time_doza = 0;//сброс накопленной дозы
        doz_v = 0;//сброс накопленной дозы
        eeprom_wrD ();
        myGLCD.clrScr();
        myGLCD.setFont(SmallFont);
        myGLCD.print("SBROS OK", CENTER, 24);
        myGLCD.update();
        _delay_ms(1000);
      }
      if (sys_menu == 3) {
        menu = 0;
      }
      if (sys_menu == 4) {
        eeprom_wrS ();
        menu = 0;
      }
      if (sys_menu == 5) {
        beta_time--;
      }
    }
  }

    if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен
  {
res_first_alarm(); //сбрасываем сигнал тревоги
  }
}
//-------------------------------------------------------------
void OK () { //нажатие ОК
  if (!(PIND & (1 << PIND3))) { //удержаиние OK
    val_ok++;
    if (val_ok >= 2) {
      val_ok = 0;
      menu = 2;
    }
  }
  if (menu == 2) {
    sys_menu++;
    if (sys_menu > 5) {
      sys_menu = 0;
    }
  }
  if (menu == 1) {
    n_menu++;
    if (n_menu > 7) {
      n_menu = 0;
    }
  }
  if (menu == 0) {
    menu = 1;
  }
  if (menu == 3) {
    menu = 1;
  }
}
//--------------------------------------------------------------
void gif_nabor() {
  myGLCD.drawLine(0, 24, 84, 24); myGLCD.drawLine(0, 38, 84, 38);
  for (int i = 83 - zam_180p * 0.47; i < 84; i++) {
    myGLCD.drawLine(i, 24, i, 38);
  }
  g_fl = !g_fl;
  if (g_fl == 0) {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_1, 8, 8);
  } else {
    myGLCD.drawBitmap(gif_x, 27, gif_chast_2, 8, 8);
  }
  if (zam_180p < 200) {
    gif_x = gif_x + 1;
    if (gif_x >= 83 - zam_180p * 0.47) {
      gif_x = 0;
    }
    myGLCD.print("ANALIZ", CENTER, 40);
  }

  if (zam_180p >= 200) {
    myGLCD.print("OBNOVLENIE", CENTER, 40);
  }
}
//--------------------------------------------------------------
void zamer_200s() {
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("%", 20, 0); myGLCD.printNumF(stat_percent, 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
      if (alarm_sound)  //сбрасываем сигнал тревоги первого уровня, если активен
    {
       res_first_alarm(); //сбрасываем сигнал тревоги 
    }
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  gif_nabor();
  battery();
  myGLCD.update();
  if (millis() - toch_milis >= 1000) {
    toch_milis = millis();
    for (int i = 0; i < 200; i++) { //сдвигаем
      mass_toch[i] = mass_toch[i + 1];
    }
    mass_toch[199] = shet;
    shet = 0;
    if (zam_180p < 200) { //первый набор массива
      zam_180p++;
      int fon_vr1 = 0;
      for (int i = 200 - zam_180p; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 * (40.0 / zam_180p);
    }
    if (zam_180p >= 200) { //набор массива
      int fon_vr1 = 0;
      for (int i = 0; i < 200; i++) {
        fon_vr1 = fon_vr1 + mass_toch[i];
      }
      fon = fon_vr1 / 5;
    }
    if (zam_180p <= 36) {
      stat_percent = stat_percent - 2.0;
    }
    if (zam_180p > 36 && zam_180p <= 72) {
      stat_percent = stat_percent - 0.3;
    }
    if (zam_180p > 72 && zam_180p <= 100) {
      stat_percent = stat_percent - 0.2;
    }
    if (zam_180p > 100 && zam_180p <= 200) {
      stat_percent = stat_percent - 0.1;
    }
    if (stat_percent < 5) {
      stat_percent = 5.0;
    }
  }
  if (!(PIND & (1 << PIND7))) { //нажатие <<<
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
    if (!(PIND & (1 << PIND7))) {//нажатие <<< фонарик
      val_kl++;
      if (val_kl == 6) {
        val_kl = 0;
        fonarik = !fonarik;
      }
    }
  }
}
//--------------------------------------------------------------
void lcd_poisk() {//вывод на дисплей режима поиск
  if (shet < treviga_1 && fon < treviga_1) {//проверяем тревогу
    tr = 0;
  }
  if (shet > treviga_1 || fon > treviga_1) {//проверяем тревогу
    check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
    tr = 1;
  }
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  if (tr == 1) { //опасно
    myGLCD.drawBitmap(0, 0, logo_tr, 24, 8);
  }
  myGLCD.print("%", 20, 0); myGLCD.printNumF(100 - (zam_36p * 2.0), 1, 26, 0);
  myGLCD.setFont(MediumNumbers);
  if (fon > 0) {
    if (fon >= 1000) {
      myGLCD.printNumI(fon, LEFT, 7);
    }
    if (fon < 1000) {
      myGLCD.printNumI(fon, CENTER, 7);
    }
  }
  myGLCD.setFont(SmallFont); myGLCD.print("uR/h", RIGHT, 12);
  time_d ();
  myGLCD.setFont(TinyFont);
  myGLCD.printNumI(HOUR, 0, 26);
  if (HOUR >= 9) {
    myGLCD.print("h", 13, 26);
  }
  if (HOUR < 9) {
    myGLCD.print("h", 5, 26);
  }
  myGLCD.printNumI(MIN, 18, 26);
  if (MIN >= 9) {
    myGLCD.print("m", 26, 26);
  }
  if (MIN < 9) {
    myGLCD.print("m", 23, 26);
  }
  myGLCD.setFont(SmallFont);
  if (doz_v < 1000) {
    myGLCD.printNumF(doz_v, 1, 41, 24); myGLCD.print("uR", RIGHT, 24);
  }
  if (doz_v >= 1000) {
    myGLCD.printNumF(doz_v / 1000.0, 2, 41, 24); myGLCD.print("mR", RIGHT, 24);
  }
  myGLCD.drawLine(0, 32, 83, 32);//верхняя
  battery();
  for (int i = 0; i < 82; i ++) { //печатаем график
    if (mass_p[i] > 0) {
      if (mass_p[i] <= 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - mass_p[i]);
      }
      if (mass_p[i] > 15) {
        myGLCD.drawLine(i + 1, 47, i + 1, 47 - 15);
      }
    }
  }
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_menu() { //вывод на дисплей меню
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPASN.1", 0, 0); myGLCD.printNumI(treviga_1, CENTER, 0); myGLCD.print("uR/h", RIGHT, 0);
  myGLCD.print("OPASN.2", 0, 6); myGLCD.printNumI(treviga_2, CENTER, 6); myGLCD.print("uR/h", RIGHT, 6);
  myGLCD.print("PODSV.", 0, 12); myGLCD.printNumI(podsvetka, CENTER, 12);
  myGLCD.print("------", 0, 18); myGLCD.printNumI(son_OK, CENTER, 18); myGLCD.print("on/off", RIGHT, 18);//usr
  myGLCD.print("POISK.", 0, 24); myGLCD.printNumI(scrin_GRAF, CENTER, 24); myGLCD.print("SEK", RIGHT, 24);
  myGLCD.print("ZVUK", 0, 30); myGLCD.printNumI(buzz_ON, CENTER, 30);
  myGLCD.print("OUT", 0, 36);
  myGLCD.print("SAVE", 0, 42);
  myGLCD.print(">", 30, n_menu * 6);
  myGLCD.update();
}
//-------------------------------------------------------------
void lcd_sys() { //вывод на дисплей меню
  VCC_read();
  speed_nakachka ();//скорость накачки имлульсы/сек
  myGLCD.clrScr();
  myGLCD.setFont(TinyFont);
  myGLCD.print("OPORN", 0, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 55, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0);
  hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом
  myGLCD.print("NAKAH", 0, 6); myGLCD.printNumI(puls, CENTER, 6); myGLCD.printNumI(hv_400, RIGHT, 6);
  myGLCD.print("DOZA", 0, 12); myGLCD.print(">>", CENTER, 12); myGLCD.print("SBROS", RIGHT, 12);
  myGLCD.print("OUT", 0, 18);
  myGLCD.print("SAVE", 0, 24);
  myGLCD.print("BETA", 0, 30); myGLCD.printNumI(beta_time, CENTER, 30); myGLCD.print("MIN", RIGHT, 30);
  myGLCD.print(">", 30, sys_menu * 6);
  myGLCD.print("SPEED N", 0, 40); myGLCD.printNumI(speed_nak, CENTER, 40); myGLCD.print("imp/sek", RIGHT, 40);
  myGLCD.update();
}
//-------------------------------------------------------------
void zamer_beta() {// замер бета или продуктов
  if (gotovo == 0) {
    if (!(PIND & (1 << PIND3))) { //нажатие OK
      gotovo = 1;
      switch (bet_z) //проверяем, находимся ли в первом или втором замере
      {
        case 0: //если в первом замере
      bet_z0 = 0; //обнуляем текущие показания замера 1
      shet = 0; //обнуляем счёт
        case 1: //если во втором замере
      bet_z1 = 0; //обнуляем текущие показания замера 2
      shet = 0; //обнуляем счёт            
      }
    }
    if (alarm_sound)  //если активен сигнал тревоги первого уровня
    {
       res_first_alarm(); //сбрасываем сигнал тревоги
    }
    myGLCD.clrScr();
    myGLCD.setFont(SmallFont);
    myGLCD.print("Zamer ", 20, 10); myGLCD.printNumI(bet_z, 55, 10);
    myGLCD.print("nagmi OK", CENTER, 20);
    myGLCD.update();
  }
  if (gotovo == 1) {
    timer_soft();
    byte otsup = 0;
    if (minute > 9) {
      otsup = 5;
    }
    myGLCD.clrScr();
    battery();
    myGLCD.setFont(TinyFont);
    myGLCD.printNumI(minute, LEFT, 0);
    if (toch == 0) {
      myGLCD.print(":", 5 + otsup, 0);
    } else {
      myGLCD.print(" ", 5 + otsup, 0);
    }
    myGLCD.printNumI(sek, 10 + otsup, 0); myGLCD.print("time", 23 + otsup, 0);
    myGLCD.drawLine(0, 8, 83, 8);
    myGLCD.setFont(SmallFont);
    myGLCD.drawLine(40, 8, 40, 28);
    myGLCD.print("Zamer0", LEFT, 10); myGLCD.print("Zamer1", RIGHT, 10);
    myGLCD.printNumI(bet_z0, LEFT, 20); myGLCD.printNumI(bet_z1, RIGHT, 20);
    myGLCD.drawLine(0, 28, 83, 28);
    if (bet_z < 2) {
      myGLCD.print("Idet zamer", CENTER, 30); myGLCD.printNumI(bet_z, RIGHT, 30);
      myGLCD.printNumI(bet_r, CENTER, 38);
    }
    if (bet_z == 2) {
      myGLCD.print("Rezultat", CENTER, 30);
      myGLCD.printNumI(bet_r, CENTER, 38); myGLCD.print("mkR/h", RIGHT, 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,70); //генерим писк 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,70); //генерим писк 2000Гц 70миллисекунд на 6й ноге		
      }
    }
    if (bet_z == 2) { //результат
      bet_r = bet_z1 - bet_z0;
      bet_r = bet_r / (1.5 * beta_time);
    }
  }
  if (!(PIND & (1 << PIND4))) { //нажатие >>>
    _delay_ms(500);//антидребезг
    menu = 0;
    shet = 0; fon = 0; zam_36p = 0;
    for (int i = 0; i < 18; i++) { //чистим
      mass_36[i] = 0;
    }
  }
}
//-------------------------------------------------------------
void poisk_f() {//режим поиска
  if (poisk == 1) {
    if (millis() - gr_milis >= scrin_GRAF * 1000) { //счет для графика
      gr_milis = millis();
      val_ok = 0;//сброс удержания системного меню
      shet_gr = shet - shet_n;
      if (shet_gr < 0) {
        shet_gr = 1;
      }
      mass_p[m] = shet_gr ;
      shet_n = shet;
      if (m < 82) {
        m++;
      }
      if (m == 82) {
        for (int i = 0; i < 83; i++) {
          mass_p[i] = mass_p[i + 1];
        }
        mass_p[82] = shet_gr;
      }
    }
    if (millis() - toch_milis >= 1000) {
      toch_milis = millis();
      for (int i = 0; i < 40; i++) { //сдвигаем
        mass_36[i] = mass_36[i + 1];
      }
      mass_36[40] = shet;
      if (zam_36p < 40) { //первый набор массива
        zam_36p++;
        fon = fon + shet;
      }
      if (zam_36p >= 40) { //набор массива
        int fon_vr1 = 0;
        for (int i = 0; i < 40; i++) {
          fon_vr1 = fon_vr1 + mass_36[i];
        }
        fon = fon_vr1;
      }
      shet = 0;
      doz_v = doz_v + fon / 100.0 / 40.0;
      time_doza = time_doza + 1;
      if (doz_v - doza_vr >= save_DOZ) { //а не пора ли сохранить дозу ?)
        eeprom_wrD ();
        doza_vr = doz_v;
      }
    }
  }
}
//-------------------------------------------------------------
void signa () { //индикация каждой частички звуком светом
  shet_s = shet;  
    if (alarm_sound) //если поднят флаг аварийного сигнала
  {
  #ifdef buzzer_active //если задефайнен активный бузер
    PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги
  #else //пассивный
  tone (6, 1300); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6
  #endif
    if ((millis() - alarm_milis) > first_alarm_duration) // проверяем, не истекло ли время подачи сигнала тревоги_
    {
    #ifdef buzzer_active   //если задефайнен активный бузер
    PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги
    #else //пассивный бузер
    noTone (6); //выключаем писк на 6й ноге
    #endif 
    alarm_sound = 0; // сбрасываем флаг сигнала тревоги
    }   
    PORTB |= (1 << 5); //включаем светодиод
    delay(del_BUZZ);
    PORTB &= ~(1 << 5);//выключаем светодиод
  }
  else //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы
  {
if ((buzz_ON == 1) && (shet_s > 0))  //включаем бузер
  #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    
  }
  //generator();//накачка по обратной связи с АЦП
}
//-------------------------------------------------------------
void Schet() { //прерывание от счетчика на пин 2
  shet++;
}
//-------------------------------------------------------------
void generator() {//накачка по обратной связи с АЦП
  hv_adc  = Read_HV();
  if (hv_adc < ADC) { //Значение АЦП при котором на выходе 400В
    int c = puls;
    PORTD |= (1 << 5); //пин накачки
    while (c > 0) {
      asm("nop");
      c--;
    }
    PORTD &= ~(1 << 5);//пин накачки
    speed_nakT++;
  }
}
//-------------------------------------------------------------
byte Read_HV () {
  ADCSRA = 0b11100111;
  ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6
  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.drawBitmap(59, 0, logo_bat, 24, 8);
  myGLCD.setFont(TinyFont);
  myGLCD.printNumF(VCC, 2, 63, 2);
}
//-------------------------------------------------------------
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(SmallFont);
  myGLCD.print("Arduino+", CENTER, 32);
  myGLCD.print("Dosimetr v1.06", 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, son_OK);
  EEPROM.write(4, scrin_GRAF);
  EEPROM.write(5, buzz_ON);
  EEPROM.write(6, puls);
  EEPROM.write(7, opornoe * 100);
  EEPROM.write(8, treviga_2);
  EEPROM.write(13, beta_time);
  myGLCD.clrScr();
  myGLCD.setFont(SmallFont);
  myGLCD.print("Save OK", CENTER, 24);
  myGLCD.update();
  _delay_ms(1000);
}
//-------------------------------------------------------------
void eeprom_wrD () { //запись настроек в память время накопления дозы
  byte hi = time_doza >> 8;
  byte low = time_doza;
  EEPROM.write(9, hi);
  EEPROM.write(10, low);
  hi = int(doz_v) >> 8;
  low = int(doz_v);
  EEPROM.write(11, hi);
  EEPROM.write(12, low);
}
//-------------------------------------------------------------
void eeprom_readD () { //чтание настроек из памяти время накопления дозы
  byte hi  = EEPROM.read(9);
  byte low  = EEPROM.read(10);
  time_doza = (hi << 8) | low;
  hi  = EEPROM.read(11);
  low  = EEPROM.read(12);
  doz_v = (hi << 8) | low;
}
//-------------------------------------------------------------
void eeprom_readS () { //чтание настроек из памяти
  if (EEPROM.read(0) == 222) {
    treviga_1 = EEPROM.read(1);
    podsvetka = EEPROM.read(2);
    son_OK = EEPROM.read(3);
    scrin_GRAF = EEPROM.read(4);
    buzz_ON = EEPROM.read(5);
    puls = EEPROM.read(6);
    opornoe = EEPROM.read(7) / 100.0;
    treviga_2 = EEPROM.read(8);
    beta_time = EEPROM.read(13);
  }
  _delay_ms(10);
}
//-------------------------------------------------------------
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() {
  HOUR = time_doza / 3600;
  MIN = (time_doza / 60) % 60;
}
//-------------------------------------------------------------
void timer_soft() {
  if (millis() - timer_mil >= 1000) {
    timer_mil = millis();
    sek++;
    toch = !toch;
    if (sek > 60) {
      sek = 0;
      minute++;
    }
  }
}


void check_alarm_signal()  // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1"
{
  if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен
    {
    alarm_sound = 1; // поднимаем флаг аварийного сигнала
    alarm_milis = millis(); // запоминаем время начала тревоги
    }  
}


void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута)
  {
    alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги
   #ifdef buzzer_active //если задефайнен активный бузер
   PORTD &= ~(1 << 6); // выключаем бузер
   #else //пассивный бузер
   noTone(6);   //выключаем генерацию сигнала на 6й ноге
   #endif
  }

Медленно как-то у Вас отрабатывает. Или накачка частая, или что-то ещё тормозит основной цикл...

ortus
Offline
Зарегистрирован: 16.10.2017

Стал выходить в системное! Спасибо Уважаемый Tekagi! Накачка стоит 2, скорость выдает 119-124 импульса накачки, что за глюк словил - не могу сказать(((( есть ли у Вас книги по программированию Ардуино?

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

Большинство знаний почерпнуто из местной обучалки, форума и гугла. Сам начинающий)

ortus пишет:

скорость выдает 119-124 импульса накачки,

Хорошие показатели, запас на регулирование есть. В чём задержка - не знаю. Я и с кодом то Бодрого нормально разобраться не могу, а отладка так и вовсе на грани догадок.

Medvedik
Medvedik аватар
Offline
Зарегистрирован: 09.07.2017

Могу подсказать где 0,1 , 0,5 и 1 ГОм купить можно)

Пару недель с Китая шли)

https://www.ebay.com.sg/itm/391917106515 Ух-ты даж 100 Гигаомник есть))

UPD: ток оне крупные... в половину СБМ-20

Norsemen
Offline
Зарегистрирован: 08.07.2017

а кстати маску паяльную обязательно использовать? на сайте сруками там есть на нее ссылка

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

Маска, лак "Пластик70", качественная эпоксидка или другое покрытие с высоким объёмным сопротивлением, устойчивое к влаге и не меняющее характеристики со временем. Основное внимание перед покрытием уделить тщательной мойке от флюса и прочей гадости и качественной просушке (рекомендации по процессу часто встречаются в сети в темах, посвящённых дозиметрам). Если дозиметр не будет эксплуатироваться в тяжёлых условиях можно ограничиться покрытием только высоковольтной части (со стороны компонентов и со стороны дорожек).

Medvedik
Medvedik аватар
Offline
Зарегистрирован: 09.07.2017

Можно и несколько слоёв лака Plastik 71 с послойной просушкой

Norsemen
Offline
Зарегистрирован: 08.07.2017

Если использовать готовую катушку, как написано на сайте 2 мГн, можно ли ее заменить 2,2 мГн? Не получается пока найти на 2.

Нет ли у кого чертежа печатной платы?

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

Norsemen пишет:

Если использовать готовую катушку, как написано на сайте 2 мГн, можно ли ее заменить 2,2 мГн? Не получается пока найти на 2.

Лучше возьмите гантельку  на 10, как советовал Medvedik, не придётся морочиться с умножителем. Тем более что с последними прошивками версия с умножителем может и не завестись.

Norsemen пишет:

Нет ли у кого чертежа печатной платы?

Есть на страничке автора, есть модифицированная авторская, плюс пользователи выкладывали в топике свои версии.

Norsemen
Offline
Зарегистрирован: 08.07.2017

т.е. гантелька подойдет от 2 до 10 мГн правильно я понял? я имел ввиду ее не перематывать, а только сверху намотать 4 витка толстым проводом. гантелька должна быть не smd как я понял. опыта мотать нет.

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

Если такая, как по ссылке Medvedik на 10мГн - то будет работать в обычной схеме с одним диодом, если на 2-4, то придётся собирать схему с умножителем.
Модифицированная печатка под схему без умножителя, остальные смотрите сами.
Кстати, в качестве повышающего трансформатора можно использовать трансформатор преобразователя фотовспышки со старого китайского плёночного фотоаппарата, работавшего от двух пальчиковых батареек ( "мыльницы" ). Омметром находим обмотку с наибольшим сопротивлением, это будет вторичка. Обмотка с наименьшим сопротивлением, намотанная более толстым проводом - первичка. Между собой обмотки звониться не должны. Эксперимент с подобным трансом дал около 140 имп/с накачки при потреблении на преобразователь менее миллиампера.

Sajsen
Offline
Зарегистрирован: 30.10.2017

У меня в запасниках обнаружился неисправный дозиметр ЭлатСим03. Решил полностью заменить ему начинку...

Печатная плата под ЛУТ в СпринтЛайаут6 https://yadi.sk/d/h5bjGNpK3Q9m2h

Скетч для ардуино https://yadi.sk/d/Huu1rNJr3Q9nFD

ПС: Использован процессор из АрдуиноУно, на плате установлен кварц на 16 мГц, скетч с авторской страницы немного подправленый. Схема авторская (переставлены кнопки для упрощения разводки(влево,вправо,меню) Один слой и традиционно много перемычек.)Выведен последовательный интерфейс (3пина - txd,rxd,gnd). СБМ-20 куплен, но пока не дошел. Синенькая платка в низу - зарядник для литиевого АКБ (с Алиэкспресса). Трансформатор- гантелька с китайской лампы+4 витка. Кнопки предполагались с длинными толкателями.

Norsemen
Offline
Зарегистрирован: 08.07.2017

Нашел только дросселя 1 мГн ,  15 мГн и 22 мГн. Других нет. Можно ли что-то с них сделать? Буззер пассивный на 3 вольта надо?

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

Бузер пассивный (если по авторской схеме). При желании можно переделать под активный 5В (для текущего скетча) с транзисторным усилителем.

Фото дросселей с размерами в студию) Малогабаритные гантельки?

Norsemen
Offline
Зарегистрирован: 08.07.2017

да, тот что на 1 размер 6*8   на 15 и 22 8*10

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

Пробуйте 5-6 витков на 15мГн. Потребление будет чуть выше, чем на малогабаритном. Или пробуйте перемотать маленький, смотав родную обмотку и намотав 600 витков тонким проводом (за габариты гантельки выходить нежелательно). Не забывайте про фазировку обмоток.