Версия 1.05: doz_v = doz_v + fon / 100.0 / 36.0; , счёт был 36 секунд.
Версия 1.062 doz_v = doz_v + fon / 100.0 / 40.0; , счёт использован 40секунд.
Учитывая, что вызов ведётся раз в секунду, логично предположить, что текущий уровень фона должен делиться на 3600, т.е. верхнее выражение верное. Видимо, при переходе к 40 секундам по ошибке было изменено и это значение. Но всё равно буду переделывать на другой алгоритм подсчёта.
Так 36 или 40? Поменял согласно этому посту на 36. Еще заметил что в режиме поиск диод моргает хаотично с бкззером, где искать косяк? В индикации кроме частоты буззера и времени в 5мкс ничего не менял?
В режиме разностного замера вспышки соответствуют щелчкам буззера, в поиске нет.
alexadresat пишет:
надпись Внимание! остается, так и должно быть?
Нет, это косяк, сам вчера с этим бодался час в своём скетче.
Это не из-за таймера, я вообщем спросил из-за чего может быть такое? Раньше не помню было так же или нет. Вчера, позавчера очень много изменений делал, но индикацию не трогал.
alexadresat пишет:
OfficialGalkin - а может надпись Внимание! лучше сделать моргающей?
Если бузер активный - должно работать строго одновременно, при пассивном точно не скажу, tone работает с аппаратным таймером, насколько я знаю, может на него что-то влияет.
А такое будет интересно, где дозиметр показывает на экране гистограмму распределения Пуассона в реальном времени?
Сверху три цифры (просто для отладки) - минимальное, среднее арифметическое, максимальное значение CPS. В консоль выводится дисперсия, статистическая ошибка ну и всё такое. На экране реальные данные от датчика СБТ-9 и СПДшного стрелочного индикатора.
В железе это пока ужас, но не думаю, что буду изобретать что-то новое, тут уже всё придумано давно.
Разве что как отдельная прошивка для энтузиастов, с теми же параметрами в еепром (железо уже настроено). Памяти уже не хватает. Практической пользы особо не вижу, хоть и интересно. А вообще я за любое развитие проекта :)
З.Ы. Не держите дома СПД, ещё и в неупакованом виде. Редкая кака, сам светосостав сыпется и его пыль разносится по комнате. А попадание такой пылинки куда не надо чревато... В качестве домашнего КИ лучше использовать урановое стекло. Или, в крайнем случае, пакет калийных удобрений.
Зачем? Дозиметр по определению должен быть небольшим, для постоянного ношения. И с микропотреблением, чего никогда не достигнуть с большим экраном (если это не е-инк). На больший камень переводить тоже смысла не вижу, и в текущем немыслимый простор для оптимизации, раньше делали на восьмой меге и тиньках, причём не уступающие в функционале. Даже АрДос на атмега8 существует, в теме выложен.
Кабы современные погромисты учились, вместо того, чтобы переходить на бОльшие системные требования, глядишь, и не пришлось бы каждые два года плашку памяти в комп докидывать, и телефон менять...
Поэксперементировал я с MC34063, и с кольцами и с гантелькой...потом вообще работать перестало, похоже что МС-ка не выдержала, даёт какие то всплески и молчит.
Нашёл гантельку, диаметр шляпы - 1см. Откопал из запасов неплохие релюшки на 10А от Omron...т.к я их нигде не используию и они достались мне бесплатно из принтеров, то решено было раскурочить и смотать оттуда провод. Провод кстати оч тонкий, наверное 0,063, замерить нечем, в сравнении есть только 0,2мм. Гантельку за ноги зажал в патрон дрели и намотал на глаз "сколько то там". Наверное пол-гантели в толщину. Подпаялся, замерил - 34,5 mH. Замотал пару слоёв лентой фум. Сверху первичка проводом 0,2мм - 50 витков. Лента фум сверху.
У меня есть генератор шим с Али до 150 кГц с регулировкой скважности, ослик DSO203. Через полевик (STP65NF06) подключил генератор к гантельке. На выходе у гантельки Диод FR-607 и плёнка Suntan 1000V 10nF. Запитал всё это через литий с защитой и через мультиметр с замером тока.
Результаты были интересные. Сначала я думал, что нормально юзать гантельку под частотой 20-50кГц, при это добиться 400 Вольт оказалось возможно скважностью 50-60%, потребление было около 40мА (т.е это потребление только гантельки, диода, кондёра и транзистора без затвора (ЗЫ:затвор питается соответственно от генератора, который в свою очередь работал от USB)). Я полазил в верхних частотах 60+кГц, там дела обстаяли ещё хуже, околонулевые напряжения на выходе.
Тут я попёр в нижний диапозон...и тут началось главное! Чем ниже я опускался, тем меньше потреблялся ток и понижался % скважности. Лучше всего гантелька с моей намоткой работала как раз на частоте ШИМ ардуино 400-600 Гц, при этом скважность была 1%, а потребление тока было в районе 1,7 мА (и это при 4В)! Это конечно не рекордные 1мА, но разница с тем что я делал раньше ощутима.
Позже попробую тоже самое с кольцом. Если будет тоже самое, то буду думали либо о переходе на Ардуину в качестве ШИМ контроллера, либо буду заставлять работать 34063 на частотах меньше килогерца (хотя по даташиту это не возможно).
PS: а вообще за последние пару лет я построил более десятка ИИП, мощностью конечно больше 100 ватт, но на разных топологиях. Считал всегда на проге Старичка. Но вот это реально первая импульсная маленькая схема, с которой такие проблемы. К тому же гантельку не посчитать, а результаты кольца не верные. Хочется и ток пониже и напряжение без просадок...и на контроллере низковольтнои и ничего не выходит. От части Joiner прав, чтоб использовать внешний специализированный контроллер ИИП, а не ардуину, ведь в нормальных полноценных устройствах не отдают контроль таким устройствам. Как минимум ардуина может зависнуть, и если на маленьком маломощном устройстве это "ничего страшного", то на 10 амперном полумосте это может закончиться пожаром, а TL494 и ей подобные не страдают от этого. К тому же скорость реакции контроллера ИИП по фидбэку или по усилителю ошибки во много раз быстрее реакции любого контроллера. В нашей теме то понятно, накачка медленная и хватит тупого кода по типу "if V>400 else PWM STep -1".
Поэксперементировал я с MC34063, и с кольцами и с гантелькой....
Позже попробую тоже самое с кольцом. Если будет тоже самое, то буду думали либо о переходе на Ардуину в качестве ШИМ контроллера, либо буду заставлять работать 34063 на частотах меньше килогерца (хотя по даташиту это не возможно).
Буржуины в каком-то своем высоковольтном преобразователе на MC34063, при помощи дополнительных деталек, добиваются очень короткого импульса. Я по аналогии спаял схему, у меня получился импульс 400 наносекунд. И еще они рекомендуют настроить микросхемку на частоту не более 10 килогерц. Моя схема работает на частоте 6 килогерц. Ключ еще не подключал. Експерименты продолжу. И интересно было бы услышать резуьтаты Ваших опытов.
Померил кольцо. Такая же история, на низких частотах, порядка 1-1,5кГц самый высокий КПД - минимум скважности и тока при максимуме напряжения. Ток у кольца оказался где то на 1мА больше чем у гантельки. Подключил всё это к МС-ке, Ст поставил на 22 нФ, это где то 1,5 кГц. Выдаёт максимум 220 вольт. Менял и полярность подключения - не помогает. Есть ощущение, что их не подружить. С обычным генератором я получил больше 1000 В с подключеным осликом через 90 Мом и напрямую подключеным мультиметром на 10Мом. И это при скважности меньше 10%
На днях попробую банальное тупое управление через ардуину, только не через стандартный PWM, а через сторонний PWM.h, там можно скважность до 16bit делать и частоту любую до 2МГц.
Dark-Dante, там же, где я и говорил. В строке 881 костыль, чуть выше условие его активации на последней минуте (хотя достаточно было последней секунды). Это не найденное решение, а маскировка бага.
Dark-Dante, там же, где я и говорил. В строке 881 костыль, чуть выше условие его активации на последней минуте (хотя достаточно было последней секунды). Это не найденное решение, а маскировка бага.
Понял. У меня бага нет, так как строку я эту выбросил сразу.
Привет я уже давно смотрю твои видео и повторяю твой дозиметр.И я хочу согласиться со сталкерами ведь дисплей легко разбить.У меня давно завалялись модули от ардуино и я нашел ардуино нано и цифровой дисплей с китая (TM1637) можешь дополнить самую первую схему с ардуино из этих двух компонентов? Я буду очень благодарен.И вот тебе лайфхак, с алиэкспрес можно заказать коробку для самоделок по твоему размеру просто введи в поиск "Пластиковый корпус для DIY". Надеюсь что из этого что то получится.
Всем привет. Смотрю изменеий фура пронеслась на крайних страница. Будут ли какие то правки в платы (схему) и что с прошивками и их описанием и изменениями?
Так же вопрос, можно ли подцепиться к ардуинке esp8266 к примеру и передавать онлайн данные на сайт какого нибудь народного контроля?
Глобально ничего не менялось, разве что супрессор в схему добавился.
Можно сделать вывод в юарт, а там хоть есп, хоть другой девайс. Но для мониторинга функционал избыточен, проще сделать преобразователь на блокинге, ограничитель 400В для стабилизации и считать самой еспшкой, не задействуя ардуину.
Тоже хочу собрать прибор для отправки данных на radmon, но не могу придумать, что делать с питанием и защитой от сырости. Литий и мороз не дружат, да и где-то читал, что сбм-20 с морозами тоже не очень. Если кто видел хорошие схемки, или может помочь, буду рад.
P.s. в теме наткнулся на пост, где Вы (tekagi) говорите про планы по проверке тлеющего, можете рассказать на словах хотябы, как это работает?
Питание лучше внешнее, сетевое. Тогда и нагреватель с термостабилизацией поставить можно. Про нестабильную работу СБМ при отрицательныx температрах тоже упоминания встречал. Ну и корпус обязательно герметичный, чтобы конденсата не было. Качественная электрическая распредкоробка в помощь, там и уплотнитель по периметру, и сальники зажимные поставить можно. Только не брать белые и полупрозрачные, они уф боятся и за пару лет рассыпаются.
По контролю задумка простая - к катодному резистору подвесить резистор и накопительный конденсатор, и на ацп. Если импульсов с формирователя нет, а на конденсаторе присутствует напряжение - идёт тлеющий разряд. Где-то схожая реализация попадалась. Можно, конечно, детектировать косвенно, по увеличению скорости накачки, но тогда придётся строить зависимости от фона и напряжения питания, не думаю, что такой вариант даст стабильный результат.
Я вот хочу свою плату развести. Хотелось бы на 16mhz что бы чип работал, но тогда надо что бы было питание 5 вольт. А это надо повышайку делать. При 3.8 вольтах уже 8 mhz частоту надо делать. Иначе могут быть глюки как мне сказал один человек. У меня ардуино нано на 2.9 даже работает на 16mhz, но он говорит что просто повезло и что многие будут глючить.
А с повышайкой будет лишняя потеря. И как отслеживать тогда напряжение на акб через ардуино?
Хотелось бы на 16mhz что бы чип работал, но тогда надо что бы было питание 5 вольт. А это надо повышайку делать. При 3.8 вольтах уже 8 mhz частоту надо делать. Иначе могут быть глюки
При повторении Ардоса тоже задавался этим вопросом. Глючить будет один камень из ста, хотя даташит говорит об обратном, но около 30 конструкций на 328й работающие от лития на 16, а то и 20-22 мГц говорят о том что разработчики просто перестраховались, так что не создавайте себе проблем на ровном месте, работает- не трогайте.
Такой же step-up, как и в АрДосе. Только дроссель не двухобмоточный и транзистор высоковольтный биполярный, что на кпд скажется не лучшим образом. И делитель на два мега есть будет, как не в себя.
Минимальный порог сигналки и будет от 100.
сейчас он от 10 лишь для того, что бы можно было проверять мне ее. Ибо источника радиации пока что нету что бы повышать фон.
Тобишь только допилить код сигналки и все?
Раньше больше 3000 не наберал...
Колокольчик за графиком как-то не смотрится.
/* ArDOs v1.08.2 ***Дозиметр на Ардуино ***IDE Arduino 1.8.8 ветка форума arduino.ru/forum/proekty/delaem-dozimetr сайт srukami.inf.ua/ardos.html */ #include <util/delay.h> //уже есть #include <EEPROM.h>//уже есть #include <LCD5110_Graph.h>//нужно установить //настройки /////////////начало LCD5110 myGLCD(A1, A0, 12, 10, 11); //подключение дисплея #define contrast 70 //контрастность дисплея //#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой. //#define UNO_DIP // если используется ArduinoUNO или плата на голой атмеге328 в корпусе DIP - раскомментируйте данную строчку. Это переключит чтение напряжения с делителя с ноги A6 на ногу A5. byte treviga_1 = 30; //первая ступень тревоги byte treviga_2 = 0; //вторая ступень тревоги byte del_BUZZ = 2;//длительность одиночного сигнала #define ADC_value 225 //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255). Для значений делителя с сайта srukami 163. alexadresat 185. (Тестовая версия tekagi 67) #define k_delitel 420 //коефициент делителя напряжения, зависит от вашего делителя. Для значений делителя с сайта srukami k_delitel 576. alexadresat 500 (Тестовая версия tekagi 1395) byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса byte scrin_GRAF = 1; //скорость построения графика в секундах bool podsvetka = 0; //подсветка uint8_t graph_type = 1; //тип графика bool alarm_sound = 0; //флаг индикации превышения порога звуком float opornoe = 1.10; //делить на opornoe/10 #define save_DOZ 1 //как часто сохранять накопленную дозу например каждые 20мкР #define geiger_counter_seconds 40 // число секунд для замера, соответствующее характеристикам счётчика. Для СБМ-20 равно 40. byte beta_time = 5; //время замера бета излучения uint8_t batproc = 0; // 1- отображать проценты. 0 - не отображать float batusb = 4.30; // настройка напряжения, выше которого будет отображаться значек USB float batmax = 4.15; //Настройка максимального значения напряжения акб для отображения. Обычно 4.20 вольта float batnapruga = 3.20; //Настройка минимального значения напряжения акб для отображения. Зависит от работоспособности вашей схемы. Обычно 3.20 вольта by OfficialGalkin //настройки //////////////конец //служебные переменные extern uint8_t SmallFontRus[], MediumNumbers[], TinyFontRus[]; volatile uint8_t timer_seconds = 0; // для отсчёта секундных интервалов в прерывании uint8_t beta_seconds = 0; uint8_t count_and_dose_seconds = 0; #define maxString 21 // для работы функции преобразования кодировки utf8us char target[maxString + 1] = ""; // для работы функции преобразования кодировки utf8us extern uint8_t logo_bat[], logo_bat_line[], logo_bat_usb[], logo_rag[], logo_tr[], beta_prev_1[], beta_prev_2[], beta_fon[], em_logo[], fon_poisk[], mkr[], mr[]; volatile int shet = 0; volatile bool overflow_alarm = 0; int8_t ind_ON = 1; //0 - индикация выключена, 1 - включён бузер, 2 - светодиод, 3 - и бузер, и светодиод uint8_t first_alarm_type = 1; //1-3, 1 - только бузер, 2 - только вибро, 3 - и бузер, и вибро byte periodical_alarm_variable = 0; // переменная для периодически повторяющейся тревожной сигнализации uint8_t tr2 = 0; // сигналка 2 сработала unsigned long gr_milis = 0, lcd_milis = 0; unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0; uint16_t hv_adc, hv_400, shet_n = 0, shet_s = 0; uint16_t fon = 0, fon_254 = 0; int speed_nakT = 0, speed_nak = 0, result; byte MIN, DAY, HOUR, MONTH; //для учёта времени дозы uint16_t doza_vr = 0, fon_vr254 = 0, fon_vr_poisk = 0; byte mass_p[84]; // массив для графика byte m = 0, n_menu = 0, sys_menu = 0, sys_menu_1 = 0, sys_menu_2 = 0; byte mass_poisk[255]; // основной рабочий массив byte val_kl = 0, val_ok = 0, menu = 0, zam_poisk_counter = 0; byte sek = 0, minute = 0, bet_z = 0, gotovo = 0; int bet_z0 = 0, bet_z1 = 0, bet_r = 0; float VCC = 0.0, doz_v = 0.0; bool tr = 0, poisk = 1, fonarik = 0, toch, blink_data=1; uint8_t GRAPH_max = 5; // максимальное значение за период отображения графика uint8_t GRAPH_count = 0; // счётчик для поиска максимального значения для графика #define key_pressed_left 1 #define key_pressed_right 2 #define key_pressed_ok 3 #define key_holded_left 4 #define key_holded_right 5 #define key_holded_ok 6 #define keys_not_pressed 0 uint8_t key_data = 0; //------------------------------------------------------------- void setup() { //----------------------------------------------------------- // настраиваем таймер на секундный интервал TCCR1A=(1<<WGM11); //режим14 FAST PWM TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256 if (F_CPU == 16000000UL) { ICR1=62499; // (16000000MHz /div256) -1 = 1 раз в секунду } else if (F_CPU == 8000000UL) { ICR1=31249; // (8000000MHz /div256) -1 = 1 раз в секунду } TIMSK1=(1<<TOIE1); //разрешить прерывание //----------------------------------------------------------- // Serial.begin(115200); ACSR |= 1 << ACD; //отключаем компаратор //ADCSRA &= ~(1 << ADEN); // отключаем АЦП, pinMode(3, INPUT_PULLUP); //кнопка pinMode(4, INPUT_PULLUP); //кнопка pinMode(7, INPUT_PULLUP); //кнопка DDRB |= (1 << 0); PORTB &= ~(1 << 0); //пин вибры 8 DDRC |= (0 << 4); PORTC &= ~(1 << 4); //пин пустой А4 DDRC |= (0 << 5); PORTC &= ~(1 << 5); //пин пустой А5 DDRB |= (1 << 1);//пин фонаря DDRC |= (1 << 3);//A3 дисплей GND DDRC |= (1 << 2);//A2 дисплей Light PORTC &= ~(1 << 3); //A3 дисплей GND PORTC |= (1 << 2); //A2 дисплей Light eeprom_readS (); eeprom_readD (); lcd_init(); attachInterrupt(0, Schet, FALLING);//прерываниям пин 2 DDRB |= (1 << 5); //пины на выход DDRD |= (1 << 5); DDRD |= (1 << 6); DDRD |= (1 << 6);//пин бузера nakachka(); clear_poisk_variables(); } //------------------------------------------------------------- void loop() { key_data = get_key(); // вызываем функцию определения нажатия кнопок, присваивая возвращаемое ней значение переменной, которую далее будем использовать в коде if (menu == 0) { if (key_data == key_pressed_left) //нажатие <<< { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду clear_poisk_variables(); } if (key_data == key_holded_left) //удержание <<< фонарик { fonarik = !fonarik; key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (key_data == key_holded_right) // удержание <<< подсветка { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 4; shet = 0; bet_z0 = 0; bet_z1 = 0; bet_r = 0; bet_z = 0; gotovo = 0; sek = 0; minute = 0; } } if (menu == 3) { if (key_data == key_pressed_left) //нажатие <<< { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; shet = 0; fon = 0; zam_poisk_counter = 0; for (int i = 0; i < 18; i++) { mass_poisk[i] = 0; }//чистим } } if (menu == 4) { if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; clear_poisk_variables(); } } if (fonarik == 0) //фонарик { PORTB &= ~(1 << 1);//пин фонаря } else if (fonarik == 1) { PORTB |= (1 << 1);//пин фонаря } if (podsvetka == 1) { PORTC &= ~(1 << 2); //A2 дисплей Light } else if (podsvetka == 0) { PORTC |= (1 << 2); //A2 дисплей Light } if (millis() - lcd_milis >= 300) //скорость отрисовки дисплея { lcd_milis = millis(); blink_data = !blink_data; if (menu == 0) { lcd_poisk(); //вывод на дисплей режима поиск poisk_f(); //вызов функции счёта и набора массива } if (menu == 1) { lcd_menu(); //вывод на дисплей меню poisk_f(); //вызов функции счёта и набора массива } if (menu == 2) { lcd_sys(); //вывод на дисплей системного меню poisk_f(); //вызов функции счёта и набора массива } if (menu == 3) { // zamer_200s(); //вывод на дисплей замер 180сек menu = 0; } if (menu == 4) { zamer_beta(); } } //------------------------------------------------------------------------------------------------------------- /* Костыль. Разностный замер и длительный замер вызываются с частотой отрисовки дисплея, поэтому сложно поймать нажатия кнопок внутри функций zamer_200s() и zamer_beta(). Возможно в будущем придётся разделить эти функции на обработку данных (вызывать с частотой loop'а) и вывод на дисплей (вызывать с частотой обновления дисплея) */ if (menu == 4) { if ((key_data == key_pressed_ok) && (gotovo == 0)) //нажатие OK { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду gotovo = 1; switch (bet_z) //проверяем, находимся ли в первом или втором замере { case 0: //если в первом замере bet_z0 = 0; //обнуляем текущие показания замера 1 shet = 0; //обнуляем счёт case 1: //если во втором замере bet_z1 = 0; //обнуляем текущие показания замера 2 shet = 0; //обнуляем счёт } } } //-------------------------------------------------------------------------------------------------------------- generator();//накачка по обратной связи с АЦП if (shet_s != shet) { signa ();//подача сигнала о частичке } if (key_data == key_pressed_ok) { //нажатие ок if (menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду sys_menu++; if (sys_menu > 7) { sys_menu = 0; } } if (menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду n_menu++; if (n_menu > 7) { n_menu = 0; } } if (menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 1; } } if (menu == 0) // в меню по удержанию кнопки "ок" входим только из режима "поиск" { if (key_data == key_holded_ok) //удержание OK { menu = 2; key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } } if (menu == 1) { if (key_data == key_pressed_right) //нажатие >>> { if (n_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_1 = treviga_1 + 10; if (treviga_1<10) {treviga_1 = 10;} if (treviga_1>100) {treviga_1 = 10;} } if (n_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_2++; treviga_2 = constrain (treviga_2, 0, 6); } if (n_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (n_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду graph_type++; if (graph_type>1) {graph_type = 0;} } if (n_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду scrin_GRAF++; if (scrin_GRAF > 10) { scrin_GRAF = 1; } } if (n_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду ind_ON++; ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4 } if (n_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (n_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 2) { if (key_data == key_pressed_right) //нажатие >>> { if (sys_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду opornoe = opornoe + 0.01; if (opornoe < 0.98) { opornoe = 1.20; } if (opornoe > 1.20) { opornoe = 0.98; } } if (sys_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду puls++; if (puls < 1) { puls = 30; } else if (puls > 30) { puls = 1; } } if (sys_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду time_doza = 0;//сброс накопленной дозы doz_v = 0;//сброс накопленной дозы eeprom_wrD (); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16); myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24); myGLCD.update(); _delay_ms(1000); } if (sys_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (sys_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду batproc++; if (batproc > 2) {batproc = 0;} } if (sys_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду beta_time++; if (beta_time > 99) {beta_time = 1;} } if (sys_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (sys_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 1) { if (key_data == key_pressed_left) //нажатие <<< { if (n_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_1 = treviga_1 - 10; if (treviga_1<10) {treviga_1 = 100;} if (treviga_1>100) {treviga_1 = 100;} } if (n_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_2--; treviga_2 = constrain (treviga_2, 0, 6); } if (n_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (n_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду graph_type--; if (graph_type > 1) {graph_type = 1;} } if (n_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду scrin_GRAF--; if (scrin_GRAF < 1) { scrin_GRAF = 10; } } if (n_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду ind_ON--; ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4 } if (n_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (n_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 2) { if (sys_menu == 7) { sys_menu_1 = 40; sys_menu_2 = 6; } else { sys_menu_1 = 0; sys_menu_2 = 0; } if (key_data == key_pressed_left) //нажатие <<< { if (sys_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду opornoe = opornoe - 0.01; if (opornoe < 0.98) { opornoe = 1.20; } else if (opornoe > 1.20) { opornoe = 0.98; } } if (sys_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду puls--; if (puls < 1) { puls = 30; } else if (puls > 30) { puls = 1; } } if (sys_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду time_doza = 0;//сброс накопленной дозы doz_v = 0;//сброс накопленной дозы eeprom_wrD (); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16); myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24); myGLCD.update(); _delay_ms(1000); } if (sys_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (sys_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду batproc--; if (batproc > 2) {batproc = 2;} } if (sys_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду beta_time--; if (beta_time > 99) {beta_time = 99;} if (beta_time < 1) {beta_time = 99;} } if (sys_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (sys_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } //------------------------------------------------------------------------------------------------------------------ if (alarm_sound && (millis() - lcd_milis >= 300)) //если поднят флаг аварийного сигнала (плюс попользуемся интервалом обновления экрана) { periodical_alarm_variable++; if (periodical_alarm_variable >= 4) {periodical_alarm_variable = 1;} // держим переменную в пределах PORTB |= (1 << 0); //включаем вибру if (periodical_alarm_variable > 1 ) { PORTB &= ~(1 << 0); // выключаем вибру } if (periodical_alarm_variable < 3) // периодичный звук тревоги { #ifdef buzzer_active //если задефайнен активный бузер PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги #else //пассивный tone (6, 500); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6 #endif } else { #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги #else //пассивный бузер noTone (6); //выключаем писк на 6й ноге #endif } if ((millis() - alarm_milis) > 3000) // проверяем, не истекло ли время подачи сигнала тревоги { PORTB &= ~(1 << 0); // выключаем вибру periodical_alarm_variable = 0; // обнуляем переменную #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги #else //пассивный бузер noTone (6); //выключаем писк на 6й ноге #endif alarm_sound = 0; // сбрасываем флаг сигнала тревоги } } //------------------------------------------------------------------------------------------------------------------ if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен { res_first_alarm(); //сбрасываем сигнал тревоги } } //------------------------------------------------------------------------------------------------------- void lcd_poisk() {//вывод на дисплей режима поиск if (fon_254 < treviga_1) //проверяем тревогу { tr = 0; } if (fon_254 > treviga_1) //проверяем тревогу { check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1" tr = 1; } switch (treviga_2) //проверяем, какое значение выбрано { case 0: tr = 0;tr2 = 0; break; case 1: if (shet > 10 || fon > 10) {tr2 = 1;} else {tr2 = 0;} break; case 2: if (shet > 300 || fon > 300) {tr2 = 1;} else {tr2 = 0;} break; case 3: if (shet > 500 || fon > 500) {tr2 = 1;} else {tr2 = 0;} break; case 4: if (shet > 1000 || fon > 1000) {tr2 = 1;} else {tr2 = 0;} break; case 5: if (shet > 5000 || fon > 5000) {tr2 = 1;} else {tr2 = 0;} break; case 6: if (shet > 10000 || fon > 10000) {tr2 = 1;} else {tr2 = 0;} break; } myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, fon_poisk, 84, 48); myGLCD.setFont(SmallFontRus); if (tr == 1) //опасно { myGLCD.drawBitmap(2, 26, logo_tr, 24, 8); } myGLCD.drawLine(1, 21, zam_poisk_counter * 0.1 + 1, 21); myGLCD.drawLine(1, 22, zam_poisk_counter * 0.1 + 1.4, 22); myGLCD.drawLine(1, 23, zam_poisk_counter * 0.1 + 0.6, 23); if (fon_254 > 0) { myGLCD.setFont(TinyFontRus); if (fon_254 >= 0 && fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);}; if (fon_254 >= 10 && fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);}; if (fon_254 >= 100 && fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);}; if (fon_254 >= 1000 && fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);}; if (fon_254 >= 10000 && fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);}; if (fon_254 >= 100000 && fon_254 <= 999999) {myGLCD.printNumI(fon_254, 2, 8);}; } if (overflow_alarm && !blink_data) {myGLCD.drawBitmap(27, 7, em_logo, 37, 17);overflow_alarm = 0;} else if ((zam_poisk_counter >= geiger_counter_seconds) || blink_data) { myGLCD.setFont(MediumNumbers); if (fon >= 0 && fon <= 9) {myGLCD.printNumI(fon, 52, 7);}; if (fon >= 10 && fon <= 99) {myGLCD.printNumI(fon, 40, 7);}; if (fon >= 100 && fon <= 999) {myGLCD.printNumI(fon, 28, 7);}; if (fon >= 1000 && fon <= 9999) {myGLCD.printNumI(fon / 1000, 52, 7);}; if (fon >= 10000 && fon <= 99999) {myGLCD.printNumI(fon / 1000, 40, 7);}; if (fon >= 100000 && fon <= 999999) {myGLCD.printNumI(fon / 1000, 28, 7);}; } if (fon < 1000) {myGLCD.drawBitmap(66, 8, mkr, 16, 15);} else {myGLCD.drawBitmap(66, 8, mr, 16, 15);} time_d (); myGLCD.setFont(TinyFontRus); ind_doze_time(); //вывод времени накопления дозы на дисплей myGLCD.setFont(SmallFontRus); if (doz_v < 1000) { if (doz_v < 100) { myGLCD.printNumF(doz_v, 1, 41, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41); } else { myGLCD.printNumF(doz_v, 1, 34, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41); } } if (doz_v >= 1000) { myGLCD.printNumF(doz_v / 1000.0, 2, 41, 41); myGLCD.print(utf8rus("мР"), RIGHT, 41); } battery(); if (graph_type == 0) { for (uint8_t i = 0; i < 84; i ++) //печатаем график { uint8_t max_pixel = map(mass_p[i], 0, GRAPH_max, 0, 15); myGLCD.drawLine(i + 0, 39, i + 0, 39 - max_pixel); } } else if (graph_type == 1) { for (int i = 0; i < 84; i ++) //печатаем график { if (mass_p[i] > 0) { if (mass_p[i] <= 15) { myGLCD.drawLine(i + 0, 39, i + 0, 39 - mass_p[i]); } if (mass_p[i] > 15) { myGLCD.drawLine(i + 0, 39, i + 0, 39 - 15); } } } } //------------------------------------------ Синалка 2 сработала ------------------------------------------------ if (tr2 == 1) { overflow_alarm = 1; #ifdef buzzer_active //если задефайнен активный бузер { PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер } #else //пассивный бузер { if (blink_data){tone (6,1000,1000);} else {tone (6,3000,1000);} } #endif } //------------------------------------------------------------------------------------------------------ myGLCD.update(); } //------------------------------------------------------------------------------------------------------- void lcd_menu() //вывод на дисплей меню { myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ПОРОГ 1"), 5, 0); myGLCD.printNumI(treviga_1, 52, 0); myGLCD.print("\xBC\xBD\xBE\xBF", RIGHT, 0); myGLCD.print(utf8rus("СИГНАЛКА"), 5, 6); //пункт меню выбора индикации частиц switch (treviga_2) { case 0: myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 6); //сигналка выключена. Сигнализация Порог 1 тоже отключется. break; case 1: myGLCD.print(utf8rus("test 10 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 100 мкр/ч break; case 2: myGLCD.print(utf8rus("300 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 300 мкр/ч break; case 3: myGLCD.print(utf8rus("500 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 500 мкр/ч break; case 4: myGLCD.print(utf8rus("1 \xBC\xBE\xBF"), RIGHT, 6); // 1000 мкр/ч break; case 5: myGLCD.print(utf8rus("5 \xBC\xBE\xBF"), RIGHT, 6); // 5000 мкр/ч break; case 6: myGLCD.print(utf8rus("10 \xBC\xBE\xBF"), RIGHT, 6); // 10000 мкр/ч break; default: myGLCD.print("err", RIGHT, 6); // если значение не равно 1,2,3,4,5,6 или 0 - выводим ошибку } myGLCD.print(utf8rus("ПОДСВЕТКА"), 5, 12); if (podsvetka) { myGLCD.print(utf8rus("ВКЛ."), RIGHT, 12); } else { myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 12); } myGLCD.print(utf8rus("ТИП ГРАФИКА"), 5, 18); if (graph_type) {myGLCD.print(utf8rus("НОВЫЙ"), RIGHT, 18);} else { myGLCD.print(utf8rus("СТАРЫЙ"), RIGHT, 18);} // myGLCD.print(utf8rus("ОБН. ГРАФИКА"), 5, 24); myGLCD.printNumI(scrin_GRAF, 60, 24); myGLCD.print(utf8rus("СЕК."), RIGHT, 24);// myGLCD.print(utf8rus("ИНДИКАЦИЯ"), 5, 30); //пункт меню выбора индикации частиц switch (ind_ON) { case 0: myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 30); //индикация выключена break; case 1: myGLCD.print(utf8rus("ЗВУК"), RIGHT, 30); //индикация звуком break; case 2: myGLCD.print(utf8rus("СВЕТ"), RIGHT, 30); //индикация светом break; case 3: myGLCD.print(utf8rus("ЗВУК+СВЕТ"), RIGHT, 30); //индикация звуком и светом break; case 4: myGLCD.print(utf8rus("ВИБРО"), RIGHT, 30); //индикация вибрацией break; default: myGLCD.print("err", RIGHT, 30); // если значение не равно 1,2,3 или 0 - выводим ошибку } myGLCD.print(utf8rus("ВЫХОД"), 5, 36); myGLCD.print(utf8rus("СОХРАНИТЬ"), 5, 42); myGLCD.print(">", 0, n_menu * 6); myGLCD.update(); } //---------------------------------------------------------------------------------------------------------------------- void lcd_sys() //вывод на дисплей меню { VCC_read(); speed_nakachka ();//скорость накачки имлульсы/сек myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ОПОРН."), 5, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 53, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0); hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом myGLCD.print(utf8rus("НАКАЧКА"), 5, 6); myGLCD.printNumI(puls, 55, 6); myGLCD.printNumI(hv_400, RIGHT, 6); myGLCD.print(utf8rus("СБРОС ДОЗЫ"), 5, 12); myGLCD.print(utf8rus("----"), 5, 18); if (batproc == 0) { myGLCD.print(utf8rus("БАТ. "), 5, 24);myGLCD.print(utf8rus("БЕЗ ИНДИКАЦИИ"), RIGHT, 24); } if (batproc == 1) { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("ПРОЦЕНТАМИ"), RIGHT, 24); } if (batproc == 2) { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("НАПРЯЖЕНИЕМ"), RIGHT, 24); } myGLCD.print(utf8rus("БЕТА"), 5, 30); myGLCD.printNumI(beta_time, 50, 30); myGLCD.print(utf8rus("МИНУТ"), RIGHT, 30); myGLCD.print(utf8rus("ВЫХОД"), 5, 36); myGLCD.print(utf8rus("СОХРАНИТЬ"), RIGHT, 36); myGLCD.print(">",sys_menu_1 + 0, sys_menu * 6 - sys_menu_2); myGLCD.print(utf8rus("СКОРОСТЬ"), 5, 43); myGLCD.printNumI(speed_nak, 40, 43); myGLCD.print(utf8rus("ИМП/СЕК"), RIGHT, 43); myGLCD.update(); } //--------------------------------------------------------------------------------------------------------------------- void zamer_beta() {// замер бета или продуктов if (gotovo == 0) { if (alarm_sound) //если активен сигнал тревоги первого уровня { res_first_alarm(); //сбрасываем сигнал тревоги } myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); if (bet_z == 0) { myGLCD.drawBitmap(0, 0, beta_prev_1, 84, 48); } else if (bet_z == 1) { myGLCD.drawBitmap(0, 0, beta_prev_2, 84, 48); } myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("НАЖМИТЕ OK"), CENTER, 36); myGLCD.update(); } if (gotovo == 1) { if (timer_seconds != beta_seconds) { beta_seconds = timer_seconds; sek++; toch = !toch; if (sek >= 60) { sek = 0; minute++; } } byte otsup = 0; if (minute > 9) { otsup = 5; } byte otsupp = 0; if (beta_time > 9) { if (beta_time > 99) { otsupp = 10; } else { otsupp = 5; } } myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, beta_fon, 84, 48); battery(); if (bet_z < 2) //таймер выводим только пока идёт первый или второй замер { myGLCD.setFont(TinyFontRus); myGLCD.printNumI(minute, LEFT, 0); if (toch == 0) { myGLCD.print(":", 5 + otsup, 0); } else { myGLCD.print(" ", 5 + otsup, 0); } if (sek < 10){myGLCD.printNumI(0, 10 + otsup, 0);myGLCD.printNumI(sek, 10 + otsup + 4, 0);} else {myGLCD.printNumI(sek, 10 + otsup, 0);} myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ИЗ"), 21 + otsup, 0); myGLCD.printNumI(beta_time, 32 + otsup, 0); myGLCD.print("\xBC", 37 + otsup + otsupp, 0); } else { myGLCD.setFont(TinyFontRus);myGLCD.print(utf8rus("РЕЗУЛЬТАТ..."), 0, 0); } myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z0, 2, 17); myGLCD.printNumI(bet_z1, 44, 17); if (bet_z < 2) { myGLCD.print(utf8rus("Идёт замер"), 5, 33); myGLCD.printNumI(bet_z, 72, 33); } if (bet_z == 2) { myGLCD.printNumI(bet_r, CENTER, 29); myGLCD.print(utf8rus("мкР/ч"), CENTER, 38); } myGLCD.update(); if (bet_z == 0) //первый замер { bet_z0 = bet_z0 + shet; shet = 0; if (minute >= beta_time) { bet_z = 1; sek = 0; minute = 0; gotovo = 0; tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге } } if (bet_z == 1) //второй замер { bet_z1 = bet_z1 + shet; shet = 0; if (minute >= beta_time) { bet_z = 2; sek = 0; minute = 0; tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге } } if (bet_z == 2) //результат { bet_r = bet_z1 - bet_z0; // bet_r = bet_r / (1.5 * beta_time); bet_r = bet_r / ((60.0/(float)geiger_counter_seconds) * (float)beta_time); if (bet_r < 0) {bet_r = 0;} // если результат отрицательный - выводим 0. Можно оставить вывод отрицательного результата, закомментировав данную строчку. } } if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; clear_poisk_variables(); } } //------------------------------------------------------------------------------------------------------------- void poisk_f() //режим поиска { int16_t shet_gr = 0; if (poisk == 1) { if (timer_seconds != count_and_dose_seconds) { count_and_dose_seconds = timer_seconds; for (int i = 0; i < 254; i++) //сдвигаем { mass_poisk[i] = mass_poisk[i + 1]; } mass_poisk[254] = shet; if ((zam_poisk_counter < 254) && (zam_poisk_counter < geiger_counter_seconds)) //первый набор массива { fon_vr_poisk = fon_vr_poisk + shet; zam_poisk_counter++; fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); // fon_254 = fon; fon_254 = 0; } else if ((zam_poisk_counter < 254) && (zam_poisk_counter == geiger_counter_seconds)) // { zam_poisk_counter++; fon_vr_poisk = fon_vr_poisk + shet; fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); fon_254 = fon; fon_vr254 = fon_vr_poisk; } else if ((zam_poisk_counter < 254) && (zam_poisk_counter > geiger_counter_seconds)) // { fon_vr_poisk = 0; fon_vr254 = 0; for (int i = zam_poisk_counter; i > 0; i--) { fon_vr254 = fon_vr254 + mass_poisk[254-i]; } for (int j = 254 - geiger_counter_seconds; j < 255; j++) { fon_vr_poisk = fon_vr_poisk + mass_poisk[j]; } fon = fon_vr_poisk; // fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); fon_254 = (float)fon_vr254*((float)geiger_counter_seconds/(float)zam_poisk_counter); fon_vr254 = 0; zam_poisk_counter++; } else if (zam_poisk_counter >= 254) //набор массива { fon_vr_poisk = 0; fon_vr254 = 0; byte geiger_counter_seconds_reverse = 254 - geiger_counter_seconds; for (int i = 254; i > 0; i--) { fon_vr254 = fon_vr254 + mass_poisk[i]; if (i > geiger_counter_seconds_reverse) { fon_vr_poisk = fon_vr_poisk + mass_poisk[i]; } } fon = fon_vr_poisk; fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/254.0); } shet = 0; doz_v = doz_v + fon / 100.0 / 36.0; time_doza = time_doza + 1; if (doz_v - doza_vr >= save_DOZ) //а не пора ли сохранить дозу ? { eeprom_wrD (); doza_vr = doz_v; } //Serial.print(" zam_poisk_counter="); //Serial.println(zam_poisk_counter); } if (millis() - gr_milis >= scrin_GRAF * 1000) //счет для графика { gr_milis = millis(); if (graph_type == 0) { val_ok = 0;//сброс удержания системного меню for (uint8_t s = 254; s >= (255 - scrin_GRAF); s--) { shet_gr = shet_gr + mass_poisk[s]; } shet_gr = shet_gr / scrin_GRAF; for (int i = 0; i < 83; i++) // сдвигаем массив графика { mass_p[i] = mass_p[i + 1]; } mass_p[82] = byte(shet_gr); if (GRAPH_count > 82) { GRAPH_max = 5; GRAPH_count = 0; } for (int i = 0; i < 82; i++) { if (mass_p[i] > GRAPH_max) { GRAPH_max = mass_p[i]; GRAPH_count = 0; } } GRAPH_count++; } if (graph_type == 1) { val_ok = 0;//сброс удержания системного меню shet_gr = shet - shet_n; if (shet_gr < 0) { shet_gr = 1; } shet_n = shet; for (int i = 0; i < 83; i++) { mass_p[i] = mass_p[i + 1]; } mass_p[82] = byte(shet_gr); } } } } //---------------------------------------------------------------------------------------------------------------- void clear_poisk_variables () { shet = 0; fon = 0; fon_254 = 0; zam_poisk_counter = 0; GRAPH_max = 5; GRAPH_count = 0; fon_vr254 = 0; fon_vr_poisk = 0; for (uint8_t i = 0; i < 84; i++) { mass_p[i] = 0; } // чистим массив графика for (uint8_t i = 0; i < 254; i++) { mass_poisk[i] = 0; } // чистим массив поиска } void signa () //индикация каждой частички звуком светом { shet_s = shet; if (!alarm_sound && tr2 == 0) //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы { if (!shet_s) {return;} //если залетели в функцию signa() при обнулении переменной shet_s - просто возвращаемся в точку вызова. Детальнее здесь: arduino.ru/forum/proekty/delaem-dozimetr?page=16#comment-318736 switch (ind_ON) //проверяем, какой тип индикации выбран { case 0: //индикация выключена break; case 1: //индикация звуком #ifdef buzzer_active //если задефайнен активный бузер { PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер } #else //пассивный бузер { tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге } #endif break; case 2: //индикация светом PORTB |= (1 << 5); //включаем светодиод delay(del_BUZZ); //длительность одиночного сигнала PORTB &= ~(1 << 5); //выключаем светодиод break; case 3: //индикация звуком и светом #ifdef buzzer_active //если задефайнен активный бузер { PORTB |= (1 << 5); //включаем светодиод PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер PORTB &= ~(1 << 5); //выключаем светодиод } #else //пассивный бузер { PORTB |= (1 << 5); //включаем светодиод tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге delay(del_BUZZ);//длительность одиночного сигнала PORTB &= ~(1 << 5);//выключаем светодиод } #endif break; case 4: // индикация вибрацией PORTB |= (1 << 0); //включаем вибру delay(del_BUZZ); //длительность одиночного сигнала PORTB &= ~(1 << 0); // выключаем вибру } } else // если активен сигнал тревоги, то только мигаем светодиодом (независимо от того, включён или нет светодиод в меню) { PORTB |= (1 << 5); //включаем светодиод delay(del_BUZZ); PORTB &= ~(1 << 5);//выключаем светодиод } } //------------------------------------------------------------------------------------------------- void Schet() //прерывание от счетчика на пин 2 { shet++; if (shet>250) {overflow_alarm = 1;} // детект приближения к переполнению переменной } //------------------------------------------------------------------------------------------------- void generator() //накачка по обратной связи с АЦП { hv_adc = Read_HV(); if (hv_adc < ADC_value) //Значение АЦП при котором на выходе 400В { int c = puls; PORTD |= (1 << 5); //пин накачки while (c > 0) { asm("nop"); c--; } PORTD &= ~(1 << 5);//пин накачки speed_nakT++; } } //-------------------------------------------------------------------------------------------------- byte Read_HV () { ADCSRA = 0b11100111; #ifdef UNO_DIP //если при компилляции выбрана плата ArduinoUNO ADMUX = 0b11100101;//выбор внутреннего опорного 1,1В и А5 #else // если используется промини, нано или голый камень в tqfp ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6 #endif for (int i = 0; i < 10; i++) { while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; } result = 0; for (int i = 0; i < 10; i++) { while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; result += ADCH; } result /= 10; return result; } //---------------------------------------------------------------------------------------------------- void battery() //батарейка { if (bat_mill - millis() > 2000) { bat_mill = millis(); VCC_read(); } myGLCD.setFont(TinyFontRus); byte batprocent = 99; batprocent = ((VCC - batnapruga) * 100 / (batmax - batnapruga)); byte batline = 9; //Задаем длину линии батареи batline = 0.1 * ((VCC - batnapruga) * 100 / (batmax - batnapruga)); //Зависимость длинны в пикселях от процента заряда if (batproc == 1 && VCC < batusb && batprocent < 100) {myGLCD.printNumF(batprocent, 0, 58, 0);myGLCD.print("%", 66, 0);} // процент заряда if (batproc == 2) {myGLCD.printNumF(VCC, 2, 54, 0);} // процент заряда if (batprocent > 5 && (VCC - batnapruga) > 0.01) //Проверяем процентный заряд акб 0.05 - 5% { if (VCC > batusb) { myGLCD.drawBitmap(71, 0, logo_bat_usb, 13, 5); } else { myGLCD.drawBitmap(71, 0, logo_bat, 13, 5); if (batprocent >= 100) {batline = 9;}; myGLCD.drawBitmap(82 - batline, 1, logo_bat_line, batline + 1, 3); } } else //Если заряд меньше 5% мигаем пустой батарейкой { toch = !toch; if (toch == 0) { myGLCD.drawBitmap(71, 0, logo_bat, 13, 5); } else { myGLCD.drawBitmap(71, 0, logo_bat, 0, 0); } } } //---------------------------------------------------------------------------------------------------- void VCC_read() // Чтение напряжения батареи { ADCSRA = 0b11100111; ADMUX = 0b01101110;//Выбор внешнего опорного+BG _delay_ms(5); while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; byte resu = ADCH; //ADCSRA &= ~(1 << ADEN); // отключаем АЦП, VCC = (opornoe * 255.0) / resu; } //---------------------------------------------------------------------------------------------------- void lcd_init() { myGLCD.InitLCD(); myGLCD.setContrast(contrast); myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, logo_rag, 84, 48); //myGLCD.setFont(SmallFontRus); // myGLCD.print(utf8rus("Ардуино+"), CENTER, 32); // myGLCD.print(utf8rus("Дозиметр v1.07"), CENTER, 40); myGLCD.update(); _delay_ms(1000); } //---------------------------------------------------------------------------------------------------- void eeprom_wrS () //запись настроек в память { EEPROM.write(0, 222); EEPROM.write(1, treviga_1); EEPROM.write(2, podsvetka); EEPROM.write(3, graph_type); EEPROM.write(4, scrin_GRAF); EEPROM.write(5, ind_ON); EEPROM.write(6, puls); EEPROM.write(7, opornoe * 100); EEPROM.write(8, treviga_2); EEPROM.write(100, batproc); EEPROM.write(17, beta_time); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("Сохранено"), CENTER, 20); myGLCD.update(); _delay_ms(1000); } //----------------------------------------------------------------------------------------------------- void eeprom_wrD () //запись настроек в память время накопления дозы { EEPROM.put(9, time_doza); EEPROM.put(13, doz_v); } //----------------------------------------------------------------------------------------------------- void eeprom_readD () //чтение настроек из памяти время накопления дозы { EEPROM.get(9, time_doza); EEPROM.get(13, doz_v); } //----------------------------------------------------------------------------------------------------- void eeprom_readS () //чтение настроек из памяти { if (EEPROM.read(0) == 222) { treviga_1 = EEPROM.read(1); podsvetka = EEPROM.read(2); graph_type = EEPROM.read(3); scrin_GRAF = EEPROM.read(4); ind_ON = EEPROM.read(5); puls = EEPROM.read(6); opornoe = EEPROM.read(7) / 100.0; treviga_2 = EEPROM.read(8); batproc = EEPROM.read(100); beta_time = EEPROM.read(17); } _delay_ms(11); } //------------------------------------------------------------------------------------------------------ void nakachka() //первая накачка { byte n = 0; while (n < 30) { PORTD |= (1 << 5);//дергаем пин int c = puls; while (c > 0) { asm("nop"); c--; } PORTD &= ~(1 << 5);//дергаем пин n++; _delay_us(100); } } //------------------------------------------------------------------------------------------------------ void speed_nakachka () //скорость накачки имлульсы/сек { if (millis() - spNAK_milis >= 1000) { spNAK_milis = millis(); speed_nak = speed_nakT; speed_nakT = 0; } } //------------------------------------------------------------------------------------------------------ void time_d() { MONTH = time_doza / 2592000; DAY = (time_doza / 86400) % 30 ; HOUR = (time_doza / 3600) % 24 ; MIN = (time_doza / 60) % 60; } //------------------------------------------------------------------------------------------------------ void check_alarm_signal() // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1" { if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен { alarm_sound = 1; // поднимаем флаг аварийного сигнала alarm_milis = millis(); // запоминаем время начала тревоги } } //------------------------------------------------------------------------------------------------------ void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута) { alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги PORTB &= ~(1 << 0); // выключаем вибру periodical_alarm_variable = 0; // обнуляем переменную #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем бузер #else //пассивный бузер noTone(6); //выключаем генерацию сигнала на 6й ноге #endif } //------------------------------------------------------------------------------------------------------ void ind_doze_time() //вывод времени накопления дозы на дисплей { myGLCD.setFont(TinyFontRus); if (MONTH) // если есть месяцы { myGLCD.printNumI(MONTH, 0, 43); if(MONTH>99) { myGLCD.print("M", 13, 43); } else if (MONTH>9) { myGLCD.print("M", 9, 43); } else { myGLCD.print("M", 5, 43); } myGLCD.printNumI(DAY, 18, 43); if (DAY > 9) { myGLCD.print("\xBB", 26, 43); } else { myGLCD.print("\xBB", 23, 43); } } else if (DAY) // если нет месяцев, но есть дни { myGLCD.printNumI(DAY, 0, 43); if (DAY > 9) { myGLCD.print("\xBB", 9, 43); } else { myGLCD.print("\xBB", 5, 43); } myGLCD.printNumI(HOUR, 18, 43); if (HOUR > 9) { myGLCD.print("\xBA", 26, 43); } else { myGLCD.print("\xBA", 23, 43); } } else // если нет дней { myGLCD.printNumI(HOUR, 0, 43); if (HOUR > 9) { myGLCD.print("\xBA", 9, 43); } else { myGLCD.print("\xBA", 5, 43); } myGLCD.printNumI(MIN, 18, 43); if (MIN > 9) { myGLCD.print("\xBC", 26, 43); } else { myGLCD.print("\xBC", 23, 43); } } } //-------------------------------------------------------------------------------------------------------- byte get_key() // Функция определения нажатия и удержания кнопок { // версия 1 - для кратковременного нажатия значение возвращается при отпускании кнопки, для длительного - пока кнопка остаётся нажатой, с заданным интервалом uint8_t trigger_push_hold_counter = 10; // задержка триггера кратковременного/длительного нажатия (проходов функции, умноженных на задержку "milliseconds_between_increment") uint8_t milliseconds_between_increment = 50; // интервал в миллисекундах между инкрементом счётчика нажатой кнопки static uint8_t val_kp, val_kl, val_ok; static uint32_t key_delay_millis; static uint32_t key_delay_after_hold_millis; if ((millis() - key_delay_millis) > milliseconds_between_increment) //обрабатываем нажатия инкрементом переменной только если после предыдущей обработки прошло не менее "milliseconds_between_increment" миллисекунд { if (!(PIND & (1 << PIND4))) //нажатие >>> { val_kp++; // инкрементируем счётчик if (val_kp > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_kp = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_right; // возвращаем значение } } if (!(PIND & (1 << PIND7))) //нажатие <<< { val_kl++; // инкрементируем счётчик if (val_kl > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_kl = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_left; // возвращаем значение } } if (!(PIND & (1 << PIND3))) //нажатие OK { val_ok++; // инкрементируем счётчик if (val_ok > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_ok = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_ok; // возвращаем значение } } key_delay_millis = millis(); // запоминаем время } if (val_ok > 0) //если клавиша OK перед этим была нажата { if ((PIND & (1 << PIND3)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_ok = 0; // сбрасываем счётчик return key_pressed_ok; // возвращаем значение } } if (val_kp > 0) //если клавиша >>> перед этим была нажата { if ((PIND & (1 << PIND4)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_kp = 0; // сбрасываем счётчик return key_pressed_right; // возвращаем значение } } if (val_kl > 0) //если клавиша <<< перед этим была нажата { if ((PIND & (1 << PIND7)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_kl = 0; // сбрасываем счётчик return key_pressed_left; // возвращаем значение } } if (PIND & (1 << PIND4)) {val_kp = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") if (PIND & (1 << PIND7)) {val_kl = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") if (PIND & (1 << PIND3)) {val_ok = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") return 0; // если ни одна из кнопок не была нажата - возвращаем 0 } //------------------------------------------------------------------------------------------------------------------------------ char *utf8rus(char *source) // функция преобразования utf8 для вывода кириллицы (by arduinec) { int i,j,k; unsigned char n; char m[2] = { '0', '\0' }; strcpy(target, ""); k = strlen(source); i = j = 0; while (i < k) { n = source[i]; i++; if (n >= 0xC0) { switch (n) { case 0xD0: { n = source[i]; i++; if (n == 0x81) { n = 0xA8; break; } if (n >= 0x90 && n <= 0xBF) n = n + 0x30; break; } case 0xD1: { n = source[i]; i++; if (n == 0x91) { n = 0xB8; break; } if (n >= 0x80 && n <= 0x8F) n = n + 0x70; break; } } } m[0] = n; strcat(target, m); j++; if (j >= maxString) break; } return target; } ISR (TIMER1_OVF_vect) // прерывание по таймеру, генерируемое каждую секунду { timer_seconds++ ; //инкремент переменной каждую секунду if (timer_seconds > 59){timer_seconds = 0;} } // ________________ конец скетча, дальше можно не копировать _____________________Чуть подправил сигналку 2. Выкинул одну глобальную переменную.
Колокольчик за графиком как-то не смотрится.
А колокольчик больше некуда деть. Хотел наверх, но там всего 5 пикселей свободно.
Дык надо было просто надпись "алярма" туда выводить, а колокольчик выкинуть.
Это косяк или что?
10 мкР/ч -> и сразу 300 мкР/ч -> потом 500 мкР/ч -> 1 мР/ч -> 5 мР/ч -> 10 мР/ч
В место 10 должно быть 100.
Там написано Test 10.
Если нужно как конечная версия, то вот.
100 мкр > 250 мкр > 500 мкр > 1 мР > 5мР > 10мР
Вместо колокольчика, надпись - ВНИМАНИЕ!
/* ArDOs v1.08.2 ***Дозиметр на Ардуино ***IDE Arduino 1.8.8 ветка форума arduino.ru/forum/proekty/delaem-dozimetr сайт srukami.inf.ua/ardos.html */ #include <util/delay.h> //уже есть #include <EEPROM.h>//уже есть #include <LCD5110_Graph.h>//нужно установить //настройки /////////////начало LCD5110 myGLCD(A1, A0, 12, 10, 11); //подключение дисплея #define contrast 70 //контрастность дисплея //#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой. //#define UNO_DIP // если используется ArduinoUNO или плата на голой атмеге328 в корпусе DIP - раскомментируйте данную строчку. Это переключит чтение напряжения с делителя с ноги A6 на ногу A5. byte treviga_1 = 30; //первая ступень тревоги byte treviga_2 = 0; //вторая ступень тревоги byte del_BUZZ = 2;//длительность одиночного сигнала #define ADC_value 225 //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255). Для значений делителя с сайта srukami 163. alexadresat 185. (Тестовая версия tekagi 67) #define k_delitel 420 //коефициент делителя напряжения, зависит от вашего делителя. Для значений делителя с сайта srukami k_delitel 576. alexadresat 500 (Тестовая версия tekagi 1395) byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса byte scrin_GRAF = 1; //скорость построения графика в секундах bool podsvetka = 0; //подсветка uint8_t graph_type = 1; //тип графика bool alarm_sound = 0; //флаг индикации превышения порога звуком float opornoe = 1.10; //делить на opornoe/10 #define save_DOZ 1 //как часто сохранять накопленную дозу например каждые 20мкР #define geiger_counter_seconds 40 // число секунд для замера, соответствующее характеристикам счётчика. Для СБМ-20 равно 40. byte beta_time = 5; //время замера бета излучения uint8_t batproc = 0; // 1- отображать проценты. 0 - не отображать float batusb = 4.30; // настройка напряжения, выше которого будет отображаться значек USB float batmax = 4.15; //Настройка максимального значения напряжения акб для отображения. Обычно 4.20 вольта float batnapruga = 3.20; //Настройка минимального значения напряжения акб для отображения. Зависит от работоспособности вашей схемы. Обычно 3.20 вольта by OfficialGalkin //настройки //////////////конец //служебные переменные extern uint8_t SmallFontRus[], MediumNumbers[], TinyFontRus[]; volatile uint8_t timer_seconds = 0; // для отсчёта секундных интервалов в прерывании uint8_t beta_seconds = 0; uint8_t count_and_dose_seconds = 0; #define maxString 21 // для работы функции преобразования кодировки utf8us char target[maxString + 1] = ""; // для работы функции преобразования кодировки utf8us extern uint8_t logo_bat[], logo_bat_line[], logo_bat_usb[], logo_rag[], logo_tr[], beta_prev_1[], beta_prev_2[], beta_fon[], em_logo[], fon_poisk[], mkr[], mr[]; volatile int shet = 0; volatile bool overflow_alarm = 0; int8_t ind_ON = 1; //0 - индикация выключена, 1 - включён бузер, 2 - светодиод, 3 - и бузер, и светодиод uint8_t first_alarm_type = 1; //1-3, 1 - только бузер, 2 - только вибро, 3 - и бузер, и вибро byte periodical_alarm_variable = 0; // переменная для периодически повторяющейся тревожной сигнализации uint8_t tr2 = 0; // сигналка 2 сработала unsigned long gr_milis = 0, lcd_milis = 0; unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0; uint16_t hv_adc, hv_400, shet_n = 0, shet_s = 0; uint16_t fon = 0, fon_254 = 0; int speed_nakT = 0, speed_nak = 0, result; byte MIN, DAY, HOUR, MONTH; //для учёта времени дозы uint16_t doza_vr = 0, fon_vr254 = 0, fon_vr_poisk = 0; byte mass_p[84]; // массив для графика byte m = 0, n_menu = 0, sys_menu = 0, sys_menu_1 = 0, sys_menu_2 = 0; byte mass_poisk[255]; // основной рабочий массив byte val_kl = 0, val_ok = 0, menu = 0, zam_poisk_counter = 0; byte sek = 0, minute = 0, bet_z = 0, gotovo = 0; int bet_z0 = 0, bet_z1 = 0, bet_r = 0; float VCC = 0.0, doz_v = 0.0; bool tr = 0, poisk = 1, fonarik = 0, toch, blink_data=1; uint8_t GRAPH_max = 5; // максимальное значение за период отображения графика uint8_t GRAPH_count = 0; // счётчик для поиска максимального значения для графика #define key_pressed_left 1 #define key_pressed_right 2 #define key_pressed_ok 3 #define key_holded_left 4 #define key_holded_right 5 #define key_holded_ok 6 #define keys_not_pressed 0 uint8_t key_data = 0; //------------------------------------------------------------- void setup() { //----------------------------------------------------------- // настраиваем таймер на секундный интервал TCCR1A=(1<<WGM11); //режим14 FAST PWM TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256 if (F_CPU == 16000000UL) { ICR1=62499; // (16000000MHz /div256) -1 = 1 раз в секунду } else if (F_CPU == 8000000UL) { ICR1=31249; // (8000000MHz /div256) -1 = 1 раз в секунду } TIMSK1=(1<<TOIE1); //разрешить прерывание //----------------------------------------------------------- // Serial.begin(115200); ACSR |= 1 << ACD; //отключаем компаратор //ADCSRA &= ~(1 << ADEN); // отключаем АЦП, pinMode(3, INPUT_PULLUP); //кнопка pinMode(4, INPUT_PULLUP); //кнопка pinMode(7, INPUT_PULLUP); //кнопка DDRB |= (1 << 0); PORTB &= ~(1 << 0); //пин вибры 8 DDRC |= (0 << 4); PORTC &= ~(1 << 4); //пин пустой А4 DDRC |= (0 << 5); PORTC &= ~(1 << 5); //пин пустой А5 DDRB |= (1 << 1);//пин фонаря DDRC |= (1 << 3);//A3 дисплей GND DDRC |= (1 << 2);//A2 дисплей Light PORTC &= ~(1 << 3); //A3 дисплей GND PORTC |= (1 << 2); //A2 дисплей Light eeprom_readS (); eeprom_readD (); lcd_init(); attachInterrupt(0, Schet, FALLING);//прерываниям пин 2 DDRB |= (1 << 5); //пины на выход DDRD |= (1 << 5); DDRD |= (1 << 6); DDRD |= (1 << 6);//пин бузера nakachka(); clear_poisk_variables(); } //------------------------------------------------------------- void loop() { key_data = get_key(); // вызываем функцию определения нажатия кнопок, присваивая возвращаемое ней значение переменной, которую далее будем использовать в коде if (menu == 0) { if (key_data == key_pressed_left) //нажатие <<< { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду clear_poisk_variables(); } if (key_data == key_holded_left) //удержание <<< фонарик { fonarik = !fonarik; key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (key_data == key_holded_right) // удержание <<< подсветка { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 4; shet = 0; bet_z0 = 0; bet_z1 = 0; bet_r = 0; bet_z = 0; gotovo = 0; sek = 0; minute = 0; } } if (menu == 3) { if (key_data == key_pressed_left) //нажатие <<< { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; shet = 0; fon = 0; zam_poisk_counter = 0; for (int i = 0; i < 18; i++) { mass_poisk[i] = 0; }//чистим } } if (menu == 4) { if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; clear_poisk_variables(); } } if (fonarik == 0) //фонарик { PORTB &= ~(1 << 1);//пин фонаря } else if (fonarik == 1) { PORTB |= (1 << 1);//пин фонаря } if (podsvetka == 1) { PORTC &= ~(1 << 2); //A2 дисплей Light } else if (podsvetka == 0) { PORTC |= (1 << 2); //A2 дисплей Light } if (millis() - lcd_milis >= 300) //скорость отрисовки дисплея { lcd_milis = millis(); blink_data = !blink_data; if (menu == 0) { lcd_poisk(); //вывод на дисплей режима поиск poisk_f(); //вызов функции счёта и набора массива } if (menu == 1) { lcd_menu(); //вывод на дисплей меню poisk_f(); //вызов функции счёта и набора массива } if (menu == 2) { lcd_sys(); //вывод на дисплей системного меню poisk_f(); //вызов функции счёта и набора массива } if (menu == 3) { // zamer_200s(); //вывод на дисплей замер 180сек menu = 0; } if (menu == 4) { zamer_beta(); } } //------------------------------------------------------------------------------------------------------------- /* Костыль. Разностный замер и длительный замер вызываются с частотой отрисовки дисплея, поэтому сложно поймать нажатия кнопок внутри функций zamer_200s() и zamer_beta(). Возможно в будущем придётся разделить эти функции на обработку данных (вызывать с частотой loop'а) и вывод на дисплей (вызывать с частотой обновления дисплея) */ if (menu == 4) { if ((key_data == key_pressed_ok) && (gotovo == 0)) //нажатие OK { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду gotovo = 1; switch (bet_z) //проверяем, находимся ли в первом или втором замере { case 0: //если в первом замере bet_z0 = 0; //обнуляем текущие показания замера 1 shet = 0; //обнуляем счёт case 1: //если во втором замере bet_z1 = 0; //обнуляем текущие показания замера 2 shet = 0; //обнуляем счёт } } } //-------------------------------------------------------------------------------------------------------------- generator();//накачка по обратной связи с АЦП if (shet_s != shet) { signa ();//подача сигнала о частичке } if (key_data == key_pressed_ok) { //нажатие ок if (menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду sys_menu++; if (sys_menu > 7) { sys_menu = 0; } } if (menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду n_menu++; if (n_menu > 7) { n_menu = 0; } } if (menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 1; } } if (menu == 0) // в меню по удержанию кнопки "ок" входим только из режима "поиск" { if (key_data == key_holded_ok) //удержание OK { menu = 2; key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } } if (menu == 1) { if (key_data == key_pressed_right) //нажатие >>> { if (n_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_1 = treviga_1 + 10; if (treviga_1<10) {treviga_1 = 10;} if (treviga_1>100) {treviga_1 = 10;} } if (n_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_2++; treviga_2 = constrain (treviga_2, 0, 6); } if (n_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (n_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду graph_type++; if (graph_type>1) {graph_type = 0;} } if (n_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду scrin_GRAF++; if (scrin_GRAF > 10) { scrin_GRAF = 1; } } if (n_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду ind_ON++; ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4 } if (n_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (n_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 2) { if (key_data == key_pressed_right) //нажатие >>> { if (sys_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду opornoe = opornoe + 0.01; if (opornoe < 0.98) { opornoe = 1.20; } if (opornoe > 1.20) { opornoe = 0.98; } } if (sys_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду puls++; if (puls < 1) { puls = 30; } else if (puls > 30) { puls = 1; } } if (sys_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду time_doza = 0;//сброс накопленной дозы doz_v = 0;//сброс накопленной дозы eeprom_wrD (); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16); myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24); myGLCD.update(); _delay_ms(1000); } if (sys_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (sys_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду batproc++; if (batproc > 2) {batproc = 0;} } if (sys_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду beta_time++; if (beta_time > 99) {beta_time = 1;} } if (sys_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (sys_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 1) { if (key_data == key_pressed_left) //нажатие <<< { if (n_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_1 = treviga_1 - 10; if (treviga_1<10) {treviga_1 = 100;} if (treviga_1>100) {treviga_1 = 100;} } if (n_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_2--; treviga_2 = constrain (treviga_2, 0, 6); } if (n_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (n_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду graph_type--; if (graph_type > 1) {graph_type = 1;} } if (n_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду scrin_GRAF--; if (scrin_GRAF < 1) { scrin_GRAF = 10; } } if (n_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду ind_ON--; ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4 } if (n_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (n_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 2) { if (sys_menu == 7) { sys_menu_1 = 40; sys_menu_2 = 6; } else { sys_menu_1 = 0; sys_menu_2 = 0; } if (key_data == key_pressed_left) //нажатие <<< { if (sys_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду opornoe = opornoe - 0.01; if (opornoe < 0.98) { opornoe = 1.20; } else if (opornoe > 1.20) { opornoe = 0.98; } } if (sys_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду puls--; if (puls < 1) { puls = 30; } else if (puls > 30) { puls = 1; } } if (sys_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду time_doza = 0;//сброс накопленной дозы doz_v = 0;//сброс накопленной дозы eeprom_wrD (); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16); myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24); myGLCD.update(); _delay_ms(1000); } if (sys_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (sys_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду batproc--; if (batproc > 2) {batproc = 2;} } if (sys_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду beta_time--; if (beta_time > 99) {beta_time = 99;} if (beta_time < 1) {beta_time = 99;} } if (sys_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (sys_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } //------------------------------------------------------------------------------------------------------------------ if (alarm_sound && (millis() - lcd_milis >= 300)) //если поднят флаг аварийного сигнала (плюс попользуемся интервалом обновления экрана) { periodical_alarm_variable++; if (periodical_alarm_variable >= 4) {periodical_alarm_variable = 1;} // держим переменную в пределах PORTB |= (1 << 0); //включаем вибру if (periodical_alarm_variable > 1 ) { PORTB &= ~(1 << 0); // выключаем вибру } if (periodical_alarm_variable < 3) // периодичный звук тревоги { #ifdef buzzer_active //если задефайнен активный бузер PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги #else //пассивный tone (6, 500); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6 #endif } else { #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги #else //пассивный бузер noTone (6); //выключаем писк на 6й ноге #endif } if ((millis() - alarm_milis) > 3000) // проверяем, не истекло ли время подачи сигнала тревоги { PORTB &= ~(1 << 0); // выключаем вибру periodical_alarm_variable = 0; // обнуляем переменную #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги #else //пассивный бузер noTone (6); //выключаем писк на 6й ноге #endif alarm_sound = 0; // сбрасываем флаг сигнала тревоги } } //------------------------------------------------------------------------------------------------------------------ if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен { res_first_alarm(); //сбрасываем сигнал тревоги } } //------------------------------------------------------------------------------------------------------- void lcd_poisk() {//вывод на дисплей режима поиск if (fon_254 < treviga_1) //проверяем тревогу { tr = 0; } if (fon_254 > treviga_1) //проверяем тревогу { check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1" tr = 1; } switch (treviga_2) //проверяем, какое значение выбрано { case 0: tr = 0;tr2 = 0; break; case 1: if (shet > 100 || fon > 100) {tr2 = 1;} else {tr2 = 0;} break; case 2: if (shet > 250 || fon > 250) {tr2 = 1;} else {tr2 = 0;} break; case 3: if (shet > 500 || fon > 500) {tr2 = 1;} else {tr2 = 0;} break; case 4: if (shet > 1000 || fon > 1000) {tr2 = 1;} else {tr2 = 0;} break; case 5: if (shet > 5000 || fon > 5000) {tr2 = 1;} else {tr2 = 0;} break; case 6: if (shet > 10000 || fon > 10000) {tr2 = 1;} else {tr2 = 0;} break; } myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, fon_poisk, 84, 48); myGLCD.setFont(SmallFontRus); myGLCD.drawLine(1, 21, zam_poisk_counter * 0.1 + 1, 21); myGLCD.drawLine(1, 22, zam_poisk_counter * 0.1 + 1.4, 22); myGLCD.drawLine(1, 23, zam_poisk_counter * 0.1 + 0.6, 23); if (fon_254 > 0) { myGLCD.setFont(TinyFontRus); if (tr == 1) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);} if (fon_254 >= 0 && fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);}; if (fon_254 >= 10 && fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);}; if (fon_254 >= 100 && fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);}; if (fon_254 >= 1000 && fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);}; if (fon_254 >= 10000 && fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);}; if (fon_254 >= 100000 && fon_254 <= 999999) {myGLCD.printNumI(fon_254, 2, 8);}; } if (overflow_alarm && !blink_data) {myGLCD.drawBitmap(27, 7, em_logo, 37, 17);overflow_alarm = 0;} else if ((zam_poisk_counter >= geiger_counter_seconds) || blink_data) { myGLCD.setFont(MediumNumbers); if (fon >= 0 && fon <= 9) {myGLCD.printNumI(fon, 52, 7);}; if (fon >= 10 && fon <= 99) {myGLCD.printNumI(fon, 40, 7);}; if (fon >= 100 && fon <= 999) {myGLCD.printNumI(fon, 28, 7);}; if (fon >= 1000 && fon <= 9999) {myGLCD.printNumI(fon / 1000, 52, 7);}; if (fon >= 10000 && fon <= 99999) {myGLCD.printNumI(fon / 1000, 40, 7);}; if (fon >= 100000 && fon <= 999999) {myGLCD.printNumI(fon / 1000, 28, 7);}; } if (fon < 1000) {myGLCD.drawBitmap(66, 8, mkr, 16, 15);} else {myGLCD.drawBitmap(66, 8, mr, 16, 15);} time_d (); myGLCD.setFont(TinyFontRus); ind_doze_time(); //вывод времени накопления дозы на дисплей myGLCD.setFont(SmallFontRus); if (doz_v < 1000) { if (doz_v < 100) { myGLCD.printNumF(doz_v, 1, 41, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41); } else { myGLCD.printNumF(doz_v, 1, 34, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41); } } if (doz_v >= 1000) { myGLCD.printNumF(doz_v / 1000.0, 2, 41, 41); myGLCD.print(utf8rus("мР"), RIGHT, 41); } battery(); if (graph_type == 0) { for (uint8_t i = 0; i < 84; i ++) //печатаем график { uint8_t max_pixel = map(mass_p[i], 0, GRAPH_max, 0, 15); myGLCD.drawLine(i + 0, 39, i + 0, 39 - max_pixel); } } else if (graph_type == 1) { for (int i = 0; i < 84; i ++) //печатаем график { if (mass_p[i] > 0) { if (mass_p[i] <= 15) { myGLCD.drawLine(i + 0, 39, i + 0, 39 - mass_p[i]); } if (mass_p[i] > 15) { myGLCD.drawLine(i + 0, 39, i + 0, 39 - 15); } } } } //------------------------------------------ Синалка 2 сработала ------------------------------------------------ if (tr2 == 1) { overflow_alarm = 1; #ifdef buzzer_active //если задефайнен активный бузер { PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер } #else //пассивный бузер { if (blink_data){tone (6,1000,1000);} else {tone (6,3000,1000);} } #endif } //------------------------------------------------------------------------------------------------------ myGLCD.update(); } //------------------------------------------------------------------------------------------------------- void lcd_menu() //вывод на дисплей меню { myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ПОРОГ 1"), 5, 0); myGLCD.printNumI(treviga_1, 52, 0); myGLCD.print("\xBC\xBD\xBE\xBF", RIGHT, 0); myGLCD.print(utf8rus("СИГНАЛКА"), 5, 6); //пункт меню выбора индикации частиц switch (treviga_2) { case 0: myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 6); //сигналка выключена. Сигнализация Порог 1 тоже отключется. break; case 1: myGLCD.print(utf8rus("100 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 100 мкр/ч break; case 2: myGLCD.print(utf8rus("250 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 250 мкр/ч break; case 3: myGLCD.print(utf8rus("500 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 500 мкр/ч break; case 4: myGLCD.print(utf8rus("1 \xBC\xBE\xBF"), RIGHT, 6); // 1000 мкр/ч break; case 5: myGLCD.print(utf8rus("5 \xBC\xBE\xBF"), RIGHT, 6); // 5000 мкр/ч break; case 6: myGLCD.print(utf8rus("10 \xBC\xBE\xBF"), RIGHT, 6); // 10000 мкр/ч break; default: myGLCD.print("err", RIGHT, 6); // если значение не равно 1,2,3,4,5,6 или 0 - выводим ошибку } myGLCD.print(utf8rus("ПОДСВЕТКА"), 5, 12); if (podsvetka) { myGLCD.print(utf8rus("ВКЛ."), RIGHT, 12); } else { myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 12); } myGLCD.print(utf8rus("ТИП ГРАФИКА"), 5, 18); if (graph_type) {myGLCD.print(utf8rus("НОВЫЙ"), RIGHT, 18);} else { myGLCD.print(utf8rus("СТАРЫЙ"), RIGHT, 18);} // myGLCD.print(utf8rus("ОБН. ГРАФИКА"), 5, 24); myGLCD.printNumI(scrin_GRAF, 60, 24); myGLCD.print(utf8rus("СЕК."), RIGHT, 24);// myGLCD.print(utf8rus("ИНДИКАЦИЯ"), 5, 30); //пункт меню выбора индикации частиц switch (ind_ON) { case 0: myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 30); //индикация выключена break; case 1: myGLCD.print(utf8rus("ЗВУК"), RIGHT, 30); //индикация звуком break; case 2: myGLCD.print(utf8rus("СВЕТ"), RIGHT, 30); //индикация светом break; case 3: myGLCD.print(utf8rus("ЗВУК+СВЕТ"), RIGHT, 30); //индикация звуком и светом break; case 4: myGLCD.print(utf8rus("ВИБРО"), RIGHT, 30); //индикация вибрацией break; default: myGLCD.print("err", RIGHT, 30); // если значение не равно 1,2,3 или 0 - выводим ошибку } myGLCD.print(utf8rus("ВЫХОД"), 5, 36); myGLCD.print(utf8rus("СОХРАНИТЬ"), 5, 42); myGLCD.print(">", 0, n_menu * 6); myGLCD.update(); } //---------------------------------------------------------------------------------------------------------------------- void lcd_sys() //вывод на дисплей меню { VCC_read(); speed_nakachka ();//скорость накачки имлульсы/сек myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ОПОРН."), 5, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 53, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0); hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом myGLCD.print(utf8rus("НАКАЧКА"), 5, 6); myGLCD.printNumI(puls, 55, 6); myGLCD.printNumI(hv_400, RIGHT, 6); myGLCD.print(utf8rus("СБРОС ДОЗЫ"), 5, 12); myGLCD.print(utf8rus("----"), 5, 18); if (batproc == 0) { myGLCD.print(utf8rus("БАТ. "), 5, 24);myGLCD.print(utf8rus("БЕЗ ИНДИКАЦИИ"), RIGHT, 24); } if (batproc == 1) { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("ПРОЦЕНТАМИ"), RIGHT, 24); } if (batproc == 2) { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("НАПРЯЖЕНИЕМ"), RIGHT, 24); } myGLCD.print(utf8rus("БЕТА"), 5, 30); myGLCD.printNumI(beta_time, 50, 30); myGLCD.print(utf8rus("МИНУТ"), RIGHT, 30); myGLCD.print(utf8rus("ВЫХОД"), 5, 36); myGLCD.print(utf8rus("СОХРАНИТЬ"), RIGHT, 36); myGLCD.print(">",sys_menu_1 + 0, sys_menu * 6 - sys_menu_2); myGLCD.print(utf8rus("СКОРОСТЬ"), 5, 43); myGLCD.printNumI(speed_nak, 40, 43); myGLCD.print(utf8rus("ИМП/СЕК"), RIGHT, 43); myGLCD.update(); } //--------------------------------------------------------------------------------------------------------------------- void zamer_beta() {// замер бета или продуктов if (gotovo == 0) { if (alarm_sound) //если активен сигнал тревоги первого уровня { res_first_alarm(); //сбрасываем сигнал тревоги } myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); if (bet_z == 0) { myGLCD.drawBitmap(0, 0, beta_prev_1, 84, 48); } else if (bet_z == 1) { myGLCD.drawBitmap(0, 0, beta_prev_2, 84, 48); } myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("НАЖМИТЕ OK"), CENTER, 36); myGLCD.update(); } if (gotovo == 1) { if (timer_seconds != beta_seconds) { beta_seconds = timer_seconds; sek++; toch = !toch; if (sek >= 60) { sek = 0; minute++; } } byte otsup = 0; if (minute > 9) { otsup = 5; } byte otsupp = 0; if (beta_time > 9) { if (beta_time > 99) { otsupp = 10; } else { otsupp = 5; } } myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, beta_fon, 84, 48); battery(); if (bet_z < 2) //таймер выводим только пока идёт первый или второй замер { myGLCD.setFont(TinyFontRus); myGLCD.printNumI(minute, LEFT, 0); if (toch == 0) { myGLCD.print(":", 5 + otsup, 0); } else { myGLCD.print(" ", 5 + otsup, 0); } if (sek < 10){myGLCD.printNumI(0, 10 + otsup, 0);myGLCD.printNumI(sek, 10 + otsup + 4, 0);} else {myGLCD.printNumI(sek, 10 + otsup, 0);} myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ИЗ"), 21 + otsup, 0); myGLCD.printNumI(beta_time, 32 + otsup, 0); myGLCD.print("\xBC", 37 + otsup + otsupp, 0); } else { myGLCD.setFont(TinyFontRus);myGLCD.print(utf8rus("РЕЗУЛЬТАТ..."), 0, 0); } myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z0, 2, 17); myGLCD.printNumI(bet_z1, 44, 17); if (bet_z < 2) { myGLCD.print(utf8rus("Идёт замер"), 5, 33); myGLCD.printNumI(bet_z, 72, 33); } if (bet_z == 2) { myGLCD.printNumI(bet_r, CENTER, 29); myGLCD.print(utf8rus("мкР/ч"), CENTER, 38); } myGLCD.update(); if (bet_z == 0) //первый замер { bet_z0 = bet_z0 + shet; shet = 0; if (minute >= beta_time) { bet_z = 1; sek = 0; minute = 0; gotovo = 0; tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге } } if (bet_z == 1) //второй замер { bet_z1 = bet_z1 + shet; shet = 0; if (minute >= beta_time) { bet_z = 2; sek = 0; minute = 0; tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге } } if (bet_z == 2) //результат { bet_r = bet_z1 - bet_z0; // bet_r = bet_r / (1.5 * beta_time); bet_r = bet_r / ((60.0/(float)geiger_counter_seconds) * (float)beta_time); if (bet_r < 0) {bet_r = 0;} // если результат отрицательный - выводим 0. Можно оставить вывод отрицательного результата, закомментировав данную строчку. } } if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; clear_poisk_variables(); } } //------------------------------------------------------------------------------------------------------------- void poisk_f() //режим поиска { int16_t shet_gr = 0; if (poisk == 1) { if (timer_seconds != count_and_dose_seconds) { count_and_dose_seconds = timer_seconds; for (int i = 0; i < 254; i++) //сдвигаем { mass_poisk[i] = mass_poisk[i + 1]; } mass_poisk[254] = shet; if ((zam_poisk_counter < 254) && (zam_poisk_counter < geiger_counter_seconds)) //первый набор массива { fon_vr_poisk = fon_vr_poisk + shet; zam_poisk_counter++; fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); // fon_254 = fon; fon_254 = 0; } else if ((zam_poisk_counter < 254) && (zam_poisk_counter == geiger_counter_seconds)) // { zam_poisk_counter++; fon_vr_poisk = fon_vr_poisk + shet; fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); fon_254 = fon; fon_vr254 = fon_vr_poisk; } else if ((zam_poisk_counter < 254) && (zam_poisk_counter > geiger_counter_seconds)) // { fon_vr_poisk = 0; fon_vr254 = 0; for (int i = zam_poisk_counter; i > 0; i--) { fon_vr254 = fon_vr254 + mass_poisk[254-i]; } for (int j = 254 - geiger_counter_seconds; j < 255; j++) { fon_vr_poisk = fon_vr_poisk + mass_poisk[j]; } fon = fon_vr_poisk; // fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); fon_254 = (float)fon_vr254*((float)geiger_counter_seconds/(float)zam_poisk_counter); fon_vr254 = 0; zam_poisk_counter++; } else if (zam_poisk_counter >= 254) //набор массива { fon_vr_poisk = 0; fon_vr254 = 0; byte geiger_counter_seconds_reverse = 254 - geiger_counter_seconds; for (int i = 254; i > 0; i--) { fon_vr254 = fon_vr254 + mass_poisk[i]; if (i > geiger_counter_seconds_reverse) { fon_vr_poisk = fon_vr_poisk + mass_poisk[i]; } } fon = fon_vr_poisk; fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/254.0); } shet = 0; doz_v = doz_v + fon / 100.0 / 36.0; time_doza = time_doza + 1; if (doz_v - doza_vr >= save_DOZ) //а не пора ли сохранить дозу ? { eeprom_wrD (); doza_vr = doz_v; } //Serial.print(" zam_poisk_counter="); //Serial.println(zam_poisk_counter); } if (millis() - gr_milis >= scrin_GRAF * 1000) //счет для графика { gr_milis = millis(); if (graph_type == 0) { val_ok = 0;//сброс удержания системного меню for (uint8_t s = 254; s >= (255 - scrin_GRAF); s--) { shet_gr = shet_gr + mass_poisk[s]; } shet_gr = shet_gr / scrin_GRAF; for (int i = 0; i < 83; i++) // сдвигаем массив графика { mass_p[i] = mass_p[i + 1]; } mass_p[82] = byte(shet_gr); if (GRAPH_count > 82) { GRAPH_max = 5; GRAPH_count = 0; } for (int i = 0; i < 82; i++) { if (mass_p[i] > GRAPH_max) { GRAPH_max = mass_p[i]; GRAPH_count = 0; } } GRAPH_count++; } if (graph_type == 1) { val_ok = 0;//сброс удержания системного меню shet_gr = shet - shet_n; if (shet_gr < 0) { shet_gr = 1; } shet_n = shet; for (int i = 0; i < 83; i++) { mass_p[i] = mass_p[i + 1]; } mass_p[82] = byte(shet_gr); } } } } //---------------------------------------------------------------------------------------------------------------- void clear_poisk_variables () { shet = 0; fon = 0; fon_254 = 0; zam_poisk_counter = 0; GRAPH_max = 5; GRAPH_count = 0; fon_vr254 = 0; fon_vr_poisk = 0; for (uint8_t i = 0; i < 84; i++) { mass_p[i] = 0; } // чистим массив графика for (uint8_t i = 0; i < 254; i++) { mass_poisk[i] = 0; } // чистим массив поиска } void signa () //индикация каждой частички звуком светом { shet_s = shet; if (!alarm_sound && tr2 == 0) //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы { if (!shet_s) {return;} //если залетели в функцию signa() при обнулении переменной shet_s - просто возвращаемся в точку вызова. Детальнее здесь: arduino.ru/forum/proekty/delaem-dozimetr?page=16#comment-318736 switch (ind_ON) //проверяем, какой тип индикации выбран { case 0: //индикация выключена break; case 1: //индикация звуком #ifdef buzzer_active //если задефайнен активный бузер { PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер } #else //пассивный бузер { tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге } #endif break; case 2: //индикация светом PORTB |= (1 << 5); //включаем светодиод delay(del_BUZZ); //длительность одиночного сигнала PORTB &= ~(1 << 5); //выключаем светодиод break; case 3: //индикация звуком и светом #ifdef buzzer_active //если задефайнен активный бузер { PORTB |= (1 << 5); //включаем светодиод PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер PORTB &= ~(1 << 5); //выключаем светодиод } #else //пассивный бузер { PORTB |= (1 << 5); //включаем светодиод tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге delay(del_BUZZ);//длительность одиночного сигнала PORTB &= ~(1 << 5);//выключаем светодиод } #endif break; case 4: // индикация вибрацией PORTB |= (1 << 0); //включаем вибру delay(del_BUZZ); //длительность одиночного сигнала PORTB &= ~(1 << 0); // выключаем вибру } } else // если активен сигнал тревоги, то только мигаем светодиодом (независимо от того, включён или нет светодиод в меню) { PORTB |= (1 << 5); //включаем светодиод delay(del_BUZZ); PORTB &= ~(1 << 5);//выключаем светодиод } } //------------------------------------------------------------------------------------------------- void Schet() //прерывание от счетчика на пин 2 { shet++; if (shet>250) {overflow_alarm = 1;} // детект приближения к переполнению переменной } //------------------------------------------------------------------------------------------------- void generator() //накачка по обратной связи с АЦП { hv_adc = Read_HV(); if (hv_adc < ADC_value) //Значение АЦП при котором на выходе 400В { int c = puls; PORTD |= (1 << 5); //пин накачки while (c > 0) { asm("nop"); c--; } PORTD &= ~(1 << 5);//пин накачки speed_nakT++; } } //-------------------------------------------------------------------------------------------------- byte Read_HV () { ADCSRA = 0b11100111; #ifdef UNO_DIP //если при компилляции выбрана плата ArduinoUNO ADMUX = 0b11100101;//выбор внутреннего опорного 1,1В и А5 #else // если используется промини, нано или голый камень в tqfp ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6 #endif for (int i = 0; i < 10; i++) { while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; } result = 0; for (int i = 0; i < 10; i++) { while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; result += ADCH; } result /= 10; return result; } //---------------------------------------------------------------------------------------------------- void battery() //батарейка { if (bat_mill - millis() > 2000) { bat_mill = millis(); VCC_read(); } myGLCD.setFont(TinyFontRus); byte batprocent = 99; batprocent = ((VCC - batnapruga) * 100 / (batmax - batnapruga)); byte batline = 9; //Задаем длину линии батареи batline = 0.1 * ((VCC - batnapruga) * 100 / (batmax - batnapruga)); //Зависимость длинны в пикселях от процента заряда if (batproc == 1 && VCC < batusb && batprocent < 100) {myGLCD.printNumF(batprocent, 0, 58, 0);myGLCD.print("%", 66, 0);} // процент заряда if (batproc == 2) {myGLCD.printNumF(VCC, 2, 54, 0);} // процент заряда if (batprocent > 5 && (VCC - batnapruga) > 0.01) //Проверяем процентный заряд акб 0.05 - 5% { if (VCC > batusb) { myGLCD.drawBitmap(71, 0, logo_bat_usb, 13, 5); } else { myGLCD.drawBitmap(71, 0, logo_bat, 13, 5); if (batprocent >= 100) {batline = 9;}; myGLCD.drawBitmap(82 - batline, 1, logo_bat_line, batline + 1, 3); } } else //Если заряд меньше 5% мигаем пустой батарейкой { toch = !toch; if (toch == 0) { myGLCD.drawBitmap(71, 0, logo_bat, 13, 5); } else { myGLCD.drawBitmap(71, 0, logo_bat, 0, 0); } } } //---------------------------------------------------------------------------------------------------- void VCC_read() // Чтение напряжения батареи { ADCSRA = 0b11100111; ADMUX = 0b01101110;//Выбор внешнего опорного+BG _delay_ms(5); while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; byte resu = ADCH; //ADCSRA &= ~(1 << ADEN); // отключаем АЦП, VCC = (opornoe * 255.0) / resu; } //---------------------------------------------------------------------------------------------------- void lcd_init() { myGLCD.InitLCD(); myGLCD.setContrast(contrast); myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, logo_rag, 84, 48); //myGLCD.setFont(SmallFontRus); // myGLCD.print(utf8rus("Ардуино+"), CENTER, 32); // myGLCD.print(utf8rus("Дозиметр v1.07"), CENTER, 40); myGLCD.update(); _delay_ms(1000); } //---------------------------------------------------------------------------------------------------- void eeprom_wrS () //запись настроек в память { EEPROM.write(0, 222); EEPROM.write(1, treviga_1); EEPROM.write(2, podsvetka); EEPROM.write(3, graph_type); EEPROM.write(4, scrin_GRAF); EEPROM.write(5, ind_ON); EEPROM.write(6, puls); EEPROM.write(7, opornoe * 100); EEPROM.write(8, treviga_2); EEPROM.write(100, batproc); EEPROM.write(17, beta_time); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("Сохранено"), CENTER, 20); myGLCD.update(); _delay_ms(1000); } //----------------------------------------------------------------------------------------------------- void eeprom_wrD () //запись настроек в память время накопления дозы { EEPROM.put(9, time_doza); EEPROM.put(13, doz_v); } //----------------------------------------------------------------------------------------------------- void eeprom_readD () //чтение настроек из памяти время накопления дозы { EEPROM.get(9, time_doza); EEPROM.get(13, doz_v); } //----------------------------------------------------------------------------------------------------- void eeprom_readS () //чтение настроек из памяти { if (EEPROM.read(0) == 222) { treviga_1 = EEPROM.read(1); podsvetka = EEPROM.read(2); graph_type = EEPROM.read(3); scrin_GRAF = EEPROM.read(4); ind_ON = EEPROM.read(5); puls = EEPROM.read(6); opornoe = EEPROM.read(7) / 100.0; treviga_2 = EEPROM.read(8); batproc = EEPROM.read(100); beta_time = EEPROM.read(17); } _delay_ms(11); } //------------------------------------------------------------------------------------------------------ void nakachka() //первая накачка { byte n = 0; while (n < 30) { PORTD |= (1 << 5);//дергаем пин int c = puls; while (c > 0) { asm("nop"); c--; } PORTD &= ~(1 << 5);//дергаем пин n++; _delay_us(100); } } //------------------------------------------------------------------------------------------------------ void speed_nakachka () //скорость накачки имлульсы/сек { if (millis() - spNAK_milis >= 1000) { spNAK_milis = millis(); speed_nak = speed_nakT; speed_nakT = 0; } } //------------------------------------------------------------------------------------------------------ void time_d() { MONTH = time_doza / 2592000; DAY = (time_doza / 86400) % 30 ; HOUR = (time_doza / 3600) % 24 ; MIN = (time_doza / 60) % 60; } //------------------------------------------------------------------------------------------------------ void check_alarm_signal() // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1" { if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен { alarm_sound = 1; // поднимаем флаг аварийного сигнала alarm_milis = millis(); // запоминаем время начала тревоги } } //------------------------------------------------------------------------------------------------------ void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута) { alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги PORTB &= ~(1 << 0); // выключаем вибру periodical_alarm_variable = 0; // обнуляем переменную #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем бузер #else //пассивный бузер noTone(6); //выключаем генерацию сигнала на 6й ноге #endif } //------------------------------------------------------------------------------------------------------ void ind_doze_time() //вывод времени накопления дозы на дисплей { myGLCD.setFont(TinyFontRus); if (MONTH) // если есть месяцы { myGLCD.printNumI(MONTH, 0, 43); if(MONTH>99) { myGLCD.print("M", 13, 43); } else if (MONTH>9) { myGLCD.print("M", 9, 43); } else { myGLCD.print("M", 5, 43); } myGLCD.printNumI(DAY, 18, 43); if (DAY > 9) { myGLCD.print("\xBB", 26, 43); } else { myGLCD.print("\xBB", 23, 43); } } else if (DAY) // если нет месяцев, но есть дни { myGLCD.printNumI(DAY, 0, 43); if (DAY > 9) { myGLCD.print("\xBB", 9, 43); } else { myGLCD.print("\xBB", 5, 43); } myGLCD.printNumI(HOUR, 18, 43); if (HOUR > 9) { myGLCD.print("\xBA", 26, 43); } else { myGLCD.print("\xBA", 23, 43); } } else // если нет дней { myGLCD.printNumI(HOUR, 0, 43); if (HOUR > 9) { myGLCD.print("\xBA", 9, 43); } else { myGLCD.print("\xBA", 5, 43); } myGLCD.printNumI(MIN, 18, 43); if (MIN > 9) { myGLCD.print("\xBC", 26, 43); } else { myGLCD.print("\xBC", 23, 43); } } } //-------------------------------------------------------------------------------------------------------- byte get_key() // Функция определения нажатия и удержания кнопок { // версия 1 - для кратковременного нажатия значение возвращается при отпускании кнопки, для длительного - пока кнопка остаётся нажатой, с заданным интервалом uint8_t trigger_push_hold_counter = 10; // задержка триггера кратковременного/длительного нажатия (проходов функции, умноженных на задержку "milliseconds_between_increment") uint8_t milliseconds_between_increment = 50; // интервал в миллисекундах между инкрементом счётчика нажатой кнопки static uint8_t val_kp, val_kl, val_ok; static uint32_t key_delay_millis; static uint32_t key_delay_after_hold_millis; if ((millis() - key_delay_millis) > milliseconds_between_increment) //обрабатываем нажатия инкрементом переменной только если после предыдущей обработки прошло не менее "milliseconds_between_increment" миллисекунд { if (!(PIND & (1 << PIND4))) //нажатие >>> { val_kp++; // инкрементируем счётчик if (val_kp > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_kp = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_right; // возвращаем значение } } if (!(PIND & (1 << PIND7))) //нажатие <<< { val_kl++; // инкрементируем счётчик if (val_kl > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_kl = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_left; // возвращаем значение } } if (!(PIND & (1 << PIND3))) //нажатие OK { val_ok++; // инкрементируем счётчик if (val_ok > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_ok = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_ok; // возвращаем значение } } key_delay_millis = millis(); // запоминаем время } if (val_ok > 0) //если клавиша OK перед этим была нажата { if ((PIND & (1 << PIND3)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_ok = 0; // сбрасываем счётчик return key_pressed_ok; // возвращаем значение } } if (val_kp > 0) //если клавиша >>> перед этим была нажата { if ((PIND & (1 << PIND4)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_kp = 0; // сбрасываем счётчик return key_pressed_right; // возвращаем значение } } if (val_kl > 0) //если клавиша <<< перед этим была нажата { if ((PIND & (1 << PIND7)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_kl = 0; // сбрасываем счётчик return key_pressed_left; // возвращаем значение } } if (PIND & (1 << PIND4)) {val_kp = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") if (PIND & (1 << PIND7)) {val_kl = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") if (PIND & (1 << PIND3)) {val_ok = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") return 0; // если ни одна из кнопок не была нажата - возвращаем 0 } //------------------------------------------------------------------------------------------------------------------------------ char *utf8rus(char *source) // функция преобразования utf8 для вывода кириллицы (by arduinec) { int i,j,k; unsigned char n; char m[2] = { '0', '\0' }; strcpy(target, ""); k = strlen(source); i = j = 0; while (i < k) { n = source[i]; i++; if (n >= 0xC0) { switch (n) { case 0xD0: { n = source[i]; i++; if (n == 0x81) { n = 0xA8; break; } if (n >= 0x90 && n <= 0xBF) n = n + 0x30; break; } case 0xD1: { n = source[i]; i++; if (n == 0x91) { n = 0xB8; break; } if (n >= 0x80 && n <= 0x8F) n = n + 0x70; break; } } } m[0] = n; strcat(target, m); j++; if (j >= maxString) break; } return target; } ISR (TIMER1_OVF_vect) // прерывание по таймеру, генерируемое каждую секунду { timer_seconds++ ; //инкремент переменной каждую секунду if (timer_seconds > 59){timer_seconds = 0;} } // ________________ конец скетча, дальше можно не копировать _____________________OfficialGalkin - Ну вот так получше.
Похоже общими усилиями нашли ещё один косяк.
Версия 1.05: doz_v = doz_v + fon / 100.0 / 36.0; , счёт был 36 секунд.
Версия 1.062 doz_v = doz_v + fon / 100.0 / 40.0; , счёт использован 40секунд.
Учитывая, что вызов ведётся раз в секунду, логично предположить, что текущий уровень фона должен делиться на 3600, т.е. верхнее выражение верное. Видимо, при переходе к 40 секундам по ошибке было изменено и это значение. Но всё равно буду переделывать на другой алгоритм подсчёта.
Так 36 или 40? Поменял согласно этому посту на 36. Еще заметил что в режиме поиск диод моргает хаотично с бкззером, где искать косяк? В индикации кроме частоты буззера и времени в 5мкс ничего не менял?
В режиме разностного замера вспышки соответствуют щелчкам буззера, в поиске нет.
надпись Внимание! остается, так и должно быть?
Нет, это косяк, сам вчера с этим бодался час в своём скетче.
Dark-Dante - Все работает как надо, я разобрался. Пока во втором показометре доза превышает лилит до тех пор надпись Внимание! на экране.
OfficialGalkin - а может надпись Внимание! лучше сделать моргающей?
36. Там было ошибочно выставлено 40, видимо приняли за время счёта.
На столе помигивает 1.08.2 с добавленым обратным отсчётом при бета-замере, баг не наблюдаю. Бузер активный.
Это не из-за таймера, я вообщем спросил из-за чего может быть такое? Раньше не помню было так же или нет. Вчера, позавчера очень много изменений делал, но индикацию не трогал.
OfficialGalkin - а может надпись Внимание! лучше сделать моргающей?
Добавьте blink_data в 634 строку.
Если бузер активный - должно работать строго одновременно, при пассивном точно не скажу, tone работает с аппаратным таймером, насколько я знаю, может на него что-то влияет.
switch (ind_ON) //проверяем, какой тип индикации выбран { case 0: //индикация выключена break; case 1: //индикация звуком #ifdef buzzer_active //если задефайнен активный бузер { PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер } #else //пассивный бузер { tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге } #endif break; case 2: //индикация светом PORTB |= (1 << 5); //включаем светодиод delay(del_BUZZ); //длительность одиночного сигнала PORTB &= ~(1 << 5); //выключаем светодиод break; case 3: //индикация звуком и светом #ifdef buzzer_active //если задефайнен активный бузер { PORTB |= (1 << 5); //включаем светодиод PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер PORTB &= ~(1 << 5); //выключаем светодиод } #else //пассивный бузер { PORTB |= (1 << 5); //включаем светодиод tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге delay(del_BUZZ);//длительность одиночного сигнала PORTB &= ~(1 << 5);//выключаем светодиод } #endif break; case 4: // индикация вибрацией PORTB |= (1 << 0); //включаем вибру delay(del_BUZZ); //длительность одиночного сигнала PORTB &= ~(1 << 0); // выключаем вибру }Dark-Dante - если можно напиши целиком строчку 634, как должно быть.
Dark-Dante,
if ((tr == 1) && blink_data) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);}Так можно прилепить мигание к любому выводимому на экран АрДоса элементу, период около 0,3с.
OfficialGalkin, обратите внимание на последовательность операторов if (...) else if (...). Всяко лучше такого:
if (tr == 1) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);} if (fon_254 >= 0 && fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);} if (fon_254 >= 10 && fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);} if (fon_254 >= 100 && fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);} if (fon_254 >= 1000 && fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);} if (fon_254 >= 10000 && fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);} if (fon_254 >= 100000 && fon_254 <= 999999) {myGLCD.printNumI(fon_254, 2, 8);}tekagi - Благодарю!
Так?
myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, fon_poisk, 84, 48); myGLCD.setFont(SmallFontRus); myGLCD.drawLine(1, 21, zam_poisk_counter * 0.1 + 1, 21); myGLCD.drawLine(1, 22, zam_poisk_counter * 0.1 + 1.4, 22); myGLCD.drawLine(1, 23, zam_poisk_counter * 0.1 + 0.6, 23); if (fon_254 > 0) { myGLCD.setFont(TinyFontRus); if ((tr == 1) && blink_data) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);} if (fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);} else if (fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);} else if (fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);} else if (fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);} else if (fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);} else {myGLCD.printNumI(fon_254, 2, 8);}; } if (overflow_alarm && !blink_data) {myGLCD.drawBitmap(27, 7, em_logo, 37, 17);overflow_alarm = 0;} else if ((zam_poisk_counter >= geiger_counter_seconds) || blink_data) { myGLCD.setFont(MediumNumbers); if (fon <= 9){myGLCD.printNumI(fon, 52, 7);} else if (fon <= 99){myGLCD.printNumI(fon, 40, 7);} else if (fon <= 999){myGLCD.printNumI(fon, 28, 7);} else if (fon <= 9999){myGLCD.printNumI(fon / 1000, 52, 7);} else if (fon <= 99999){myGLCD.printNumI(fon / 1000, 40, 7);} else{myGLCD.printNumI(fon / 1000, 28, 7);} }Последние условия я бы всё же оставил else if. Особенно учитывая, что оно поверх фоновых нулей пишется. И зачем точки с запятой после фигурных скобок?
Ну так оно все равно выполняется, если все верхние не выполнились. Как и написано в вики.
А такое будет интересно, где дозиметр показывает на экране гистограмму распределения Пуассона в реальном времени?
Сверху три цифры (просто для отладки) - минимальное, среднее арифметическое, максимальное значение CPS. В консоль выводится дисперсия, статистическая ошибка ну и всё такое. На экране реальные данные от датчика СБТ-9 и СПДшного стрелочного индикатора.
В железе это пока ужас, но не думаю, что буду изобретать что-то новое, тут уже всё придумано давно.
Разве что как отдельная прошивка для энтузиастов, с теми же параметрами в еепром (железо уже настроено). Памяти уже не хватает. Практической пользы особо не вижу, хоть и интересно. А вообще я за любое развитие проекта :)
З.Ы. Не держите дома СПД, ещё и в неупакованом виде. Редкая кака, сам светосостав сыпется и его пыль разносится по комнате. А попадание такой пылинки куда не надо чревато... В качестве домашнего КИ лучше использовать урановое стекло. Или, в крайнем случае, пакет калийных удобрений.
У меня была мысль перевести проект на atmega2560. Собрать дозиметр с экраном побольше.
большой экран уже круто
Зачем? Дозиметр по определению должен быть небольшим, для постоянного ношения. И с микропотреблением, чего никогда не достигнуть с большим экраном (если это не е-инк). На больший камень переводить тоже смысла не вижу, и в текущем немыслимый простор для оптимизации, раньше делали на восьмой меге и тиньках, причём не уступающие в функционале. Даже АрДос на атмега8 существует, в теме выложен.
Кабы современные погромисты учились, вместо того, чтобы переходить на бОльшие системные требования, глядишь, и не пришлось бы каждые два года плашку памяти в комп докидывать, и телефон менять...
Экран всего по 10 пикселей больше. Такой-же монохромный. Тоже подключение. И стоит также. HX1230
Это из-за того что колокольчик не влез?))
Передела бету (визуально)
Выкинуто 2 глобальные переменные.
Обратный таймер от tekagi
В обратном таймере убран баг с -1 - й минутой
Код
/* ArDOs v1.08.2 ***Дозиметр на Ардуино ***IDE Arduino 1.8.8 ветка форума arduino.ru/forum/proekty/delaem-dozimetr сайт srukami.inf.ua/ardos.html */ #include <util/delay.h> //уже есть #include <EEPROM.h>//уже есть #include <LCD5110_Graph.h>//нужно установить //настройки /////////////начало LCD5110 myGLCD(A1, A0, 12, 10, 11); //подключение дисплея #define contrast 70 //контрастность дисплея //#define buzzer_active //если используется активный бузер (со встроенным генератором), управляемый транзистором с выхода 6, то раскомментировать эту строчку, если пассивный (с усилителем или без) - оставить закомментированой. //#define UNO_DIP // если используется ArduinoUNO или плата на голой атмеге328 в корпусе DIP - раскомментируйте данную строчку. Это переключит чтение напряжения с делителя с ноги A6 на ногу A5. byte treviga_1 = 30; //первая ступень тревоги byte treviga_2 = 0; //вторая ступень тревоги byte del_BUZZ = 2;//длительность одиночного сигнала #define ADC_value 225 //значение АЦП при котором 400В с учетом вашего делителя напряжения (0..255). Для значений делителя с сайта srukami 163. alexadresat 185. (Тестовая версия tekagi 67) #define k_delitel 420 //коефициент делителя напряжения, зависит от вашего делителя. Для значений делителя с сайта srukami k_delitel 576. alexadresat 500 (Тестовая версия tekagi 1395) byte puls = 2; //тонкая настройка длинны импульса высоковольтного транса byte scrin_GRAF = 1; //скорость построения графика в секундах bool podsvetka = 0; //подсветка uint8_t graph_type = 1; //тип графика bool alarm_sound = 0; //флаг индикации превышения порога звуком float opornoe = 1.10; //делить на opornoe/10 #define save_DOZ 1 //как часто сохранять накопленную дозу например каждые 20мкР #define geiger_counter_seconds 40 // число секунд для замера, соответствующее характеристикам счётчика. Для СБМ-20 равно 40. byte beta_time = 5; //время замера бета излучения uint8_t batproc = 0; // 1- отображать проценты. 0 - не отображать float batusb = 4.30; // настройка напряжения, выше которого будет отображаться значек USB float batmax = 4.15; //Настройка максимального значения напряжения акб для отображения. Обычно 4.20 вольта float batnapruga = 3.20; //Настройка минимального значения напряжения акб для отображения. Зависит от работоспособности вашей схемы. Обычно 3.20 вольта by OfficialGalkin //настройки //////////////конец //служебные переменные extern uint8_t SmallFontRus[], MediumNumbers[], TinyFontRus[]; volatile uint8_t timer_seconds = 0; // для отсчёта секундных интервалов в прерывании uint8_t beta_seconds = 0; uint8_t count_and_dose_seconds = 0; #define maxString 21 // для работы функции преобразования кодировки utf8us char target[maxString + 1] = ""; // для работы функции преобразования кодировки utf8us extern uint8_t logo_bat[], logo_bat_line[], logo_bat_usb[], logo_rag[], logo_tr[], beta_prev_1[], beta_prev_2[], beta_fon[], bs[], em_logo[], fon_poisk[], mkr[], mr[]; volatile int shet = 0; volatile bool overflow_alarm = 0; int8_t ind_ON = 1; //0 - индикация выключена, 1 - включён бузер, 2 - светодиод, 3 - и бузер, и светодиод uint8_t first_alarm_type = 1; //1-3, 1 - только бузер, 2 - только вибро, 3 - и бузер, и вибро byte periodical_alarm_variable = 0; // переменная для периодически повторяющейся тревожной сигнализации uint8_t tr2 = 0; // сигналка 2 сработала unsigned long gr_milis = 0, lcd_milis = 0; unsigned long alarm_milis = 0; //для отсчёта длительности сигнала тревоги по превышению порога unsigned long spNAK_milis = 0, time_doza = 0, bat_mill = 0; uint16_t hv_adc, hv_400, shet_n = 0, shet_s = 0; uint16_t fon = 0, fon_254 = 0; int speed_nakT = 0, speed_nak = 0, result; byte MIN, DAY, HOUR, MONTH; //для учёта времени дозы uint16_t doza_vr = 0, fon_vr254 = 0, fon_vr_poisk = 0; byte mass_p[84]; // массив для графика byte m = 0, n_menu = 0, sys_menu = 0, sys_menu_1 = 0, sys_menu_2 = 0; byte mass_poisk[255]; // основной рабочий массив byte val_kl = 0, val_ok = 0, menu = 0, zam_poisk_counter = 0; byte sek = 0, minute = 0, bet_z = 0, gotovo = 0; int bet_z0 = 0, bet_z1 = 0, bet_r = 0; float VCC = 0.0, doz_v = 0.0; bool tr = 0, poisk = 1, fonarik = 0, toch, blink_data=1; uint8_t GRAPH_max = 5; // максимальное значение за период отображения графика uint8_t GRAPH_count = 0; // счётчик для поиска максимального значения для графика #define key_pressed_left 1 #define key_pressed_right 2 #define key_pressed_ok 3 #define key_holded_left 4 #define key_holded_right 5 #define key_holded_ok 6 #define keys_not_pressed 0 uint8_t key_data = 0; //------------------------------------------------------------- void setup() { //----------------------------------------------------------- // настраиваем таймер на секундный интервал TCCR1A=(1<<WGM11); //режим14 FAST PWM TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256 if (F_CPU == 16000000UL) { ICR1=62499; // (16000000MHz /div256) -1 = 1 раз в секунду } else if (F_CPU == 8000000UL) { ICR1=31249; // (8000000MHz /div256) -1 = 1 раз в секунду } TIMSK1=(1<<TOIE1); //разрешить прерывание //----------------------------------------------------------- // Serial.begin(115200); ACSR |= 1 << ACD; //отключаем компаратор //ADCSRA &= ~(1 << ADEN); // отключаем АЦП, pinMode(3, INPUT_PULLUP); //кнопка pinMode(4, INPUT_PULLUP); //кнопка pinMode(7, INPUT_PULLUP); //кнопка DDRB |= (1 << 0); PORTB &= ~(1 << 0); //пин вибры 8 DDRC |= (0 << 4); PORTC &= ~(1 << 4); //пин пустой А4 DDRC |= (0 << 5); PORTC &= ~(1 << 5); //пин пустой А5 DDRB |= (1 << 1);//пин фонаря DDRC |= (1 << 3);//A3 дисплей GND DDRC |= (1 << 2);//A2 дисплей Light PORTC &= ~(1 << 3); //A3 дисплей GND PORTC |= (1 << 2); //A2 дисплей Light eeprom_readS (); eeprom_readD (); lcd_init(); attachInterrupt(0, Schet, FALLING);//прерываниям пин 2 DDRB |= (1 << 5); //пины на выход DDRD |= (1 << 5); DDRD |= (1 << 6); DDRD |= (1 << 6);//пин бузера nakachka(); clear_poisk_variables(); } //------------------------------------------------------------- void loop() { key_data = get_key(); // вызываем функцию определения нажатия кнопок, присваивая возвращаемое ней значение переменной, которую далее будем использовать в коде if (menu == 0) { if (key_data == key_pressed_left) //нажатие <<< { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду clear_poisk_variables(); } if (key_data == key_holded_left) //удержание <<< фонарик { fonarik = !fonarik; key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (key_data == key_holded_right) // удержание <<< подсветка { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 4; shet = 0; bet_z0 = 0; bet_z1 = 0; bet_r = 0; bet_z = 0; gotovo = 0; sek = 0; minute = 0; } } if (menu == 3) { if (key_data == key_pressed_left) //нажатие <<< { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; shet = 0; fon = 0; zam_poisk_counter = 0; for (int i = 0; i < 18; i++) { mass_poisk[i] = 0; }//чистим } } if (menu == 4) { if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; clear_poisk_variables(); } } if (fonarik == 0) //фонарик { PORTB &= ~(1 << 1);//пин фонаря } else if (fonarik == 1) { PORTB |= (1 << 1);//пин фонаря } if (podsvetka == 1) { PORTC &= ~(1 << 2); //A2 дисплей Light } else if (podsvetka == 0) { PORTC |= (1 << 2); //A2 дисплей Light } if (millis() - lcd_milis >= 300) //скорость отрисовки дисплея { lcd_milis = millis(); blink_data = !blink_data; if (menu == 0) { lcd_poisk(); //вывод на дисплей режима поиск poisk_f(); //вызов функции счёта и набора массива } if (menu == 1) { lcd_menu(); //вывод на дисплей меню poisk_f(); //вызов функции счёта и набора массива } if (menu == 2) { lcd_sys(); //вывод на дисплей системного меню poisk_f(); //вызов функции счёта и набора массива } if (menu == 3) { // zamer_200s(); //вывод на дисплей замер 180сек menu = 0; } if (menu == 4) { zamer_beta(); } } //------------------------------------------------------------------------------------------------------------- /* Костыль. Разностный замер и длительный замер вызываются с частотой отрисовки дисплея, поэтому сложно поймать нажатия кнопок внутри функций zamer_200s() и zamer_beta(). Возможно в будущем придётся разделить эти функции на обработку данных (вызывать с частотой loop'а) и вывод на дисплей (вызывать с частотой обновления дисплея) */ if (menu == 4) { if ((key_data == key_pressed_ok) && (gotovo == 0)) //нажатие OK { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду gotovo = 1; switch (bet_z) //проверяем, находимся ли в первом или втором замере { case 0: //если в первом замере bet_z0 = 0; //обнуляем текущие показания замера 1 shet = 0; //обнуляем счёт case 1: //если во втором замере bet_z1 = 0; //обнуляем текущие показания замера 2 shet = 0; //обнуляем счёт } } } //-------------------------------------------------------------------------------------------------------------- generator();//накачка по обратной связи с АЦП if (shet_s != shet) { signa ();//подача сигнала о частичке } if (key_data == key_pressed_ok) { //нажатие ок if (menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду sys_menu++; if (sys_menu > 7) { sys_menu = 0; } } if (menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду n_menu++; if (n_menu > 7) { n_menu = 0; } } if (menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 1; } } if (menu == 0) // в меню по удержанию кнопки "ок" входим только из режима "поиск" { if (key_data == key_holded_ok) //удержание OK { menu = 2; key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } } if (menu == 1) { if (key_data == key_pressed_right) //нажатие >>> { if (n_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_1 = treviga_1 + 10; if (treviga_1<10) {treviga_1 = 10;} if (treviga_1>100) {treviga_1 = 10;} } if (n_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_2++; treviga_2 = constrain (treviga_2, 0, 6); } if (n_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (n_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду graph_type++; if (graph_type>1) {graph_type = 0;} } if (n_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду scrin_GRAF++; if (scrin_GRAF > 10) { scrin_GRAF = 1; } } if (n_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду ind_ON++; ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4 } if (n_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (n_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 2) { if (key_data == key_pressed_right) //нажатие >>> { if (sys_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду opornoe = opornoe + 0.01; if (opornoe < 0.98) { opornoe = 1.20; } if (opornoe > 1.20) { opornoe = 0.98; } } if (sys_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду puls++; if (puls < 1) { puls = 30; } else if (puls > 30) { puls = 1; } } if (sys_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду time_doza = 0;//сброс накопленной дозы doz_v = 0;//сброс накопленной дозы eeprom_wrD (); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16); myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24); myGLCD.update(); _delay_ms(1000); } if (sys_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (sys_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду batproc++; if (batproc > 2) {batproc = 0;} } if (sys_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду beta_time++; if (beta_time > 99) {beta_time = 1;} } if (sys_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (sys_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 1) { if (key_data == key_pressed_left) //нажатие <<< { if (n_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_1 = treviga_1 - 10; if (treviga_1<10) {treviga_1 = 100;} if (treviga_1>100) {treviga_1 = 100;} } if (n_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду treviga_2--; treviga_2 = constrain (treviga_2, 0, 6); } if (n_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду podsvetka = !podsvetka; } if (n_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду graph_type--; if (graph_type > 1) {graph_type = 1;} } if (n_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду scrin_GRAF--; if (scrin_GRAF < 1) { scrin_GRAF = 10; } } if (n_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду ind_ON--; ind_ON = constrain (ind_ON, 0, 4); //держим значение в диапазоне 0...4 } if (n_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (n_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } if (menu == 2) { if (sys_menu == 7) { sys_menu_1 = 40; sys_menu_2 = 6; } else { sys_menu_1 = 0; sys_menu_2 = 0; } if (key_data == key_pressed_left) //нажатие <<< { if (sys_menu == 0) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду opornoe = opornoe - 0.01; if (opornoe < 0.98) { opornoe = 1.20; } else if (opornoe > 1.20) { opornoe = 0.98; } } if (sys_menu == 1) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду puls--; if (puls < 1) { puls = 30; } else if (puls > 30) { puls = 1; } } if (sys_menu == 2) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду time_doza = 0;//сброс накопленной дозы doz_v = 0;//сброс накопленной дозы eeprom_wrD (); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("ДОЗА И ВРЕМЯ"), CENTER, 16); myGLCD.print(utf8rus("ОБНУЛЕНЫ"), CENTER, 24); myGLCD.update(); _delay_ms(1000); } if (sys_menu == 3) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду } if (sys_menu == 4) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду batproc--; if (batproc > 2) {batproc = 2;} } if (sys_menu == 5) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду beta_time--; if (beta_time > 99) {beta_time = 99;} if (beta_time < 1) {beta_time = 99;} } if (sys_menu == 6) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; } if (sys_menu == 7) { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду eeprom_wrS (); menu = 0; } } } //------------------------------------------------------------------------------------------------------------------ if (alarm_sound && (millis() - lcd_milis >= 300)) //если поднят флаг аварийного сигнала (плюс попользуемся интервалом обновления экрана) { periodical_alarm_variable++; if (periodical_alarm_variable >= 4) {periodical_alarm_variable = 1;} // держим переменную в пределах PORTB |= (1 << 0); //включаем вибру if (periodical_alarm_variable > 1 ) { PORTB &= ~(1 << 0); // выключаем вибру } if (periodical_alarm_variable < 3) // периодичный звук тревоги { #ifdef buzzer_active //если задефайнен активный бузер PORTD |= (1 << 6); // включаем непрерывный сигнал тревоги #else //пассивный tone (6, 500); //генерим писк с частотой 1300Гц (значение можно изменить на своё) на пине 6 #endif } else { #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги #else //пассивный бузер noTone (6); //выключаем писк на 6й ноге #endif } if ((millis() - alarm_milis) > 3000) // проверяем, не истекло ли время подачи сигнала тревоги { PORTB &= ~(1 << 0); // выключаем вибру periodical_alarm_variable = 0; // обнуляем переменную #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем непрерывный сигнал тревоги #else //пассивный бузер noTone (6); //выключаем писк на 6й ноге #endif alarm_sound = 0; // сбрасываем флаг сигнала тревоги } } //------------------------------------------------------------------------------------------------------------------ if (!tr && alarm_sound) // если фон ниже порога тревоги, но сигнал тревоги ещё не выключен { res_first_alarm(); //сбрасываем сигнал тревоги } } //------------------------------------------------------------------------------------------------------- void lcd_poisk() {//вывод на дисплей режима поиск if (fon_254 < treviga_1) //проверяем тревогу { tr = 0; } if (fon_254 > treviga_1) //проверяем тревогу { check_alarm_signal(); // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1" tr = 1; } switch (treviga_2) //проверяем, какое значение выбрано { case 0: tr = 0;tr2 = 0; break; case 1: if (shet > 100 || fon > 100) {tr2 = 1;} else {tr2 = 0;} break; case 2: if (shet > 250 || fon > 250) {tr2 = 1;} else {tr2 = 0;} break; case 3: if (shet > 500 || fon > 500) {tr2 = 1;} else {tr2 = 0;} break; case 4: if (shet > 1000 || fon > 1000) {tr2 = 1;} else {tr2 = 0;} break; case 5: if (shet > 5000 || fon > 5000) {tr2 = 1;} else {tr2 = 0;} break; case 6: if (shet > 10000 || fon > 10000) {tr2 = 1;} else {tr2 = 0;} break; } myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, fon_poisk, 84, 48); myGLCD.setFont(SmallFontRus); myGLCD.drawLine(1, 21, zam_poisk_counter * 0.1 + 1, 21); myGLCD.drawLine(1, 22, zam_poisk_counter * 0.1 + 1.4, 22); myGLCD.drawLine(1, 23, zam_poisk_counter * 0.1 + 0.6, 23); if (fon_254 > 0) { myGLCD.setFont(TinyFontRus); if ((tr == 1) && blink_data) {myGLCD.print(utf8rus("ВНИМАНИЕ!"), 0, 0);} if (fon_254 <= 9) {myGLCD.printNumI(fon_254, 22, 8);} else if (fon_254 <= 99) {myGLCD.printNumI(fon_254, 18, 8);} else if (fon_254 <= 999) {myGLCD.printNumI(fon_254, 14, 8);} else if (fon_254 <= 9999) {myGLCD.printNumI(fon_254, 10, 8);} else if (fon_254 <= 99999) {myGLCD.printNumI(fon_254, 6, 8);} else {myGLCD.printNumI(fon_254, 2, 8);}; } if (overflow_alarm && !blink_data) {myGLCD.drawBitmap(27, 7, em_logo, 37, 17);overflow_alarm = 0;} else if ((zam_poisk_counter >= geiger_counter_seconds) || blink_data) { myGLCD.setFont(MediumNumbers); if (fon <= 9){myGLCD.printNumI(fon, 52, 7);} else if (fon <= 99){myGLCD.printNumI(fon, 40, 7);} else if (fon <= 999){myGLCD.printNumI(fon, 28, 7);} else if (fon <= 9999){myGLCD.printNumI(fon / 1000, 52, 7);} else if (fon <= 99999){myGLCD.printNumI(fon / 1000, 40, 7);} else{myGLCD.printNumI(fon / 1000, 28, 7);} } if (fon < 1000) {myGLCD.drawBitmap(66, 8, mkr, 16, 15);} else {myGLCD.drawBitmap(66, 8, mr, 16, 15);} time_d (); myGLCD.setFont(TinyFontRus); ind_doze_time(); //вывод времени накопления дозы на дисплей myGLCD.setFont(SmallFontRus); if (doz_v < 1000) { if (doz_v < 100) { myGLCD.printNumF(doz_v, 1, 41, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41); } else { myGLCD.printNumF(doz_v, 1, 34, 41); myGLCD.print(utf8rus("мкР"), RIGHT, 41); } } if (doz_v >= 1000) { myGLCD.printNumF(doz_v / 1000.0, 2, 41, 41); myGLCD.print(utf8rus("мР"), RIGHT, 41); } battery(); if (graph_type == 0) { for (uint8_t i = 0; i < 84; i ++) //печатаем график { uint8_t max_pixel = map(mass_p[i], 0, GRAPH_max, 0, 15); myGLCD.drawLine(i + 0, 39, i + 0, 39 - max_pixel); } } else if (graph_type == 1) { for (int i = 0; i < 84; i ++) //печатаем график { if (mass_p[i] > 0) { if (mass_p[i] <= 15) { myGLCD.drawLine(i + 0, 39, i + 0, 39 - mass_p[i]); } if (mass_p[i] > 15) { myGLCD.drawLine(i + 0, 39, i + 0, 39 - 15); } } } } //------------------------------------------ Синалка 2 сработала ------------------------------------------------ if (tr2 == 1) { overflow_alarm = 1; #ifdef buzzer_active //если задефайнен активный бузер { PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер } #else //пассивный бузер { if (blink_data){tone (6,1000,1000);} else {tone (6,3000,1000);} } #endif } //------------------------------------------------------------------------------------------------------ myGLCD.update(); } //------------------------------------------------------------------------------------------------------- void lcd_menu() //вывод на дисплей меню { myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ПОРОГ 1"), 5, 0); myGLCD.printNumI(treviga_1, 52, 0); myGLCD.print("\xBC\xBD\xBE\xBF", RIGHT, 0); myGLCD.print(utf8rus("СИГНАЛКА"), 5, 6); //пункт меню выбора индикации частиц switch (treviga_2) { case 0: myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 6); //сигналка выключена. Сигнализация Порог 1 тоже отключется. break; case 1: myGLCD.print(utf8rus("100 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 100 мкр/ч break; case 2: myGLCD.print(utf8rus("250 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 250 мкр/ч break; case 3: myGLCD.print(utf8rus("500 \xBC\xBD\xBE\xBF"), RIGHT, 6); // 500 мкр/ч break; case 4: myGLCD.print(utf8rus("1 \xBC\xBE\xBF"), RIGHT, 6); // 1000 мкр/ч break; case 5: myGLCD.print(utf8rus("5 \xBC\xBE\xBF"), RIGHT, 6); // 5000 мкр/ч break; case 6: myGLCD.print(utf8rus("10 \xBC\xBE\xBF"), RIGHT, 6); // 10000 мкр/ч break; default: myGLCD.print("err", RIGHT, 6); // если значение не равно 1,2,3,4,5,6 или 0 - выводим ошибку } myGLCD.print(utf8rus("ПОДСВЕТКА"), 5, 12); if (podsvetka) { myGLCD.print(utf8rus("ВКЛ."), RIGHT, 12); } else { myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 12); } myGLCD.print(utf8rus("ТИП ГРАФИКА"), 5, 18); if (graph_type) {myGLCD.print(utf8rus("НОВЫЙ"), RIGHT, 18);} else { myGLCD.print(utf8rus("СТАРЫЙ"), RIGHT, 18);} // myGLCD.print(utf8rus("ОБН. ГРАФИКА"), 5, 24); myGLCD.printNumI(scrin_GRAF, 60, 24); myGLCD.print(utf8rus("СЕК."), RIGHT, 24);// myGLCD.print(utf8rus("ИНДИКАЦИЯ"), 5, 30); //пункт меню выбора индикации частиц switch (ind_ON) { case 0: myGLCD.print(utf8rus("ВЫКЛ."), RIGHT, 30); //индикация выключена break; case 1: myGLCD.print(utf8rus("ЗВУК"), RIGHT, 30); //индикация звуком break; case 2: myGLCD.print(utf8rus("СВЕТ"), RIGHT, 30); //индикация светом break; case 3: myGLCD.print(utf8rus("ЗВУК+СВЕТ"), RIGHT, 30); //индикация звуком и светом break; case 4: myGLCD.print(utf8rus("ВИБРО"), RIGHT, 30); //индикация вибрацией break; default: myGLCD.print("err", RIGHT, 30); // если значение не равно 1,2,3 или 0 - выводим ошибку } myGLCD.print(utf8rus("ВЫХОД"), 5, 36); myGLCD.print(utf8rus("СОХРАНИТЬ"), 5, 42); myGLCD.print(">", 0, n_menu * 6); myGLCD.update(); } //---------------------------------------------------------------------------------------------------------------------- void lcd_sys() //вывод на дисплей меню { VCC_read(); speed_nakachka ();//скорость накачки имлульсы/сек myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ОПОРН."), 5, 0); myGLCD.printNumF(opornoe, 2, CENTER, 0); myGLCD.print("VCC", 53, 0); myGLCD.printNumF(VCC, 2, RIGHT, 0); hv_400 = hv_adc * opornoe * k_delitel / 255; //считем высокео перед выводом myGLCD.print(utf8rus("НАКАЧКА"), 5, 6); myGLCD.printNumI(puls, 55, 6); myGLCD.printNumI(hv_400, RIGHT, 6); myGLCD.print(utf8rus("СБРОС ДОЗЫ"), 5, 12); myGLCD.print(utf8rus("----"), 5, 18); if (batproc == 0) { myGLCD.print(utf8rus("БАТ. "), 5, 24);myGLCD.print(utf8rus("БЕЗ ИНДИКАЦИИ"), RIGHT, 24); } if (batproc == 1) { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("ПРОЦЕНТАМИ"), RIGHT, 24); } if (batproc == 2) { myGLCD.print(utf8rus("ИНДИК. "), 5, 24);myGLCD.print(utf8rus("НАПРЯЖЕНИЕМ"), RIGHT, 24); } myGLCD.print(utf8rus("БЕТА"), 5, 30); myGLCD.printNumI(beta_time, 50, 30); myGLCD.print(utf8rus("МИНУТ"), RIGHT, 30); myGLCD.print(utf8rus("ВЫХОД"), 5, 36); myGLCD.print(utf8rus("СОХРАНИТЬ"), RIGHT, 36); myGLCD.print(">",sys_menu_1 + 0, sys_menu * 6 - sys_menu_2); myGLCD.print(utf8rus("СКОРОСТЬ"), 5, 43); myGLCD.printNumI(speed_nak, 40, 43); myGLCD.print(utf8rus("ИМП/СЕК"), RIGHT, 43); myGLCD.update(); } //--------------------------------------------------------------------------------------------------------------------- void zamer_beta() {// замер бета или продуктов if (gotovo == 0) { if (alarm_sound) //если активен сигнал тревоги первого уровня { res_first_alarm(); //сбрасываем сигнал тревоги } myGLCD.clrScr(); myGLCD.setFont(TinyFontRus); if (bet_z == 0) { myGLCD.drawBitmap(0, 0, beta_prev_1, 84, 48); } else if (bet_z == 1) { myGLCD.drawBitmap(0, 0, beta_prev_2, 84, 48); } myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("НАЖМИТЕ OK"), CENTER, 36); myGLCD.update(); } if (gotovo == 1) { if (timer_seconds != beta_seconds) { beta_seconds = timer_seconds; sek++; toch = !toch; if (sek >= 60) { sek = 0; minute++; } } myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, beta_fon, 84, 48); battery(); if (bet_z < 2) //таймер выводим только пока идёт первый или второй замер { myGLCD.setFont(SmallFontRus); if (toch == 0) { myGLCD.drawBitmap(41, 33, bs, 0, 0); } else { myGLCD.drawBitmap(41, 33, bs, 3, 9); } myGLCD.setFont(MediumNumbers); if ((beta_time - minute -1) >= 0) { if ((beta_time - minute -1) <= 9) { myGLCD.print("0", 12, 29); myGLCD.printNumI((beta_time - minute -1), 24, 29); } else { myGLCD.printNumI((beta_time - minute -1), 12, 29); } } else { myGLCD.print("0", 12, 29);myGLCD.print("0", 24, 29); } byte sektemp = 0; if (sek == 0) { sektemp = 60; } else { sektemp = sek; } if (((60 - sek) <= 9) || (sektemp == 60)) { myGLCD.print("0", 49, 29); myGLCD.printNumI((60 - sektemp), 61, 29); } else { myGLCD.printNumI((60 - sektemp), 49, 29); } } //myGLCD.setFont(MediumNumbers); //myGLCD.printNumI(0, 10 + otsup, 0); //myGLCD.printNumI(sek, 10 + otsup + 4, 0); if (bet_z < 2) {myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ИДЕТ ЗАМЕР"), 0, 0); myGLCD.printNumI(bet_z, 44, 0);} if (bet_z == 0 && blink_data) { myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z0, 2, 19); } if (bet_z == 1) { myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z0, 2, 19); if (blink_data) {myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z1, 44, 19);} } if (bet_z == 2) { myGLCD.setFont(SmallFontRus); myGLCD.printNumI(bet_z0, 2, 19); myGLCD.printNumI(bet_z1, 44, 19); myGLCD.setFont(MediumNumbers);myGLCD.printNumI(bet_r, CENTER, 29); myGLCD.setFont(TinyFontRus); myGLCD.print(utf8rus("ИТОГО"), 0, 0); myGLCD.print(utf8rus("\xBC\xBD\xBE\xBF"), 26, 0); } myGLCD.update(); if (bet_z == 0) //первый замер { bet_z0 = bet_z0 + shet; shet = 0; if (minute >= beta_time) { bet_z = 1; sek = 0; minute = 0; gotovo = 0; tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге } } if (bet_z == 1) //второй замер { bet_z1 = bet_z1 + shet; shet = 0; if (minute >= beta_time) { bet_z = 2; sek = 0; minute = 0; tone (6,2000,550); //генерим писк 2000Гц 70миллисекунд на 6й ноге } } if (bet_z == 2) //результат { bet_r = bet_z1 - bet_z0; // bet_r = bet_r / (1.5 * beta_time); bet_r = bet_r / ((60.0/(float)geiger_counter_seconds) * (float)beta_time); if (bet_r < 0) {bet_r = 0;} // если результат отрицательный - выводим 0. Можно оставить вывод отрицательного результата, закомментировав данную строчку. } } if (key_data == key_pressed_right) //нажатие >>> { key_data = 0; // обнуляем переменную функции кнопок для предотвращения ложных срабатываний далее по коду menu = 0; clear_poisk_variables(); } } //------------------------------------------------------------------------------------------------------------- void poisk_f() //режим поиска { int16_t shet_gr = 0; if (poisk == 1) { if (timer_seconds != count_and_dose_seconds) { count_and_dose_seconds = timer_seconds; for (int i = 0; i < 254; i++) //сдвигаем { mass_poisk[i] = mass_poisk[i + 1]; } mass_poisk[254] = shet; if ((zam_poisk_counter < 254) && (zam_poisk_counter < geiger_counter_seconds)) //первый набор массива { fon_vr_poisk = fon_vr_poisk + shet; zam_poisk_counter++; fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); // fon_254 = fon; fon_254 = 0; } else if ((zam_poisk_counter < 254) && (zam_poisk_counter == geiger_counter_seconds)) // { zam_poisk_counter++; fon_vr_poisk = fon_vr_poisk + shet; fon = fon_vr_poisk*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); fon_254 = fon; fon_vr254 = fon_vr_poisk; } else if ((zam_poisk_counter < 254) && (zam_poisk_counter > geiger_counter_seconds)) // { fon_vr_poisk = 0; fon_vr254 = 0; for (int i = zam_poisk_counter; i > 0; i--) { fon_vr254 = fon_vr254 + mass_poisk[254-i]; } for (int j = 254 - geiger_counter_seconds; j < 255; j++) { fon_vr_poisk = fon_vr_poisk + mass_poisk[j]; } fon = fon_vr_poisk; // fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/(float(zam_poisk_counter))); fon_254 = (float)fon_vr254*((float)geiger_counter_seconds/(float)zam_poisk_counter); fon_vr254 = 0; zam_poisk_counter++; } else if (zam_poisk_counter >= 254) //набор массива { fon_vr_poisk = 0; fon_vr254 = 0; byte geiger_counter_seconds_reverse = 254 - geiger_counter_seconds; for (int i = 254; i > 0; i--) { fon_vr254 = fon_vr254 + mass_poisk[i]; if (i > geiger_counter_seconds_reverse) { fon_vr_poisk = fon_vr_poisk + mass_poisk[i]; } } fon = fon_vr_poisk; fon_254 = (float(fon_vr254))*((float(geiger_counter_seconds))/254.0); } shet = 0; doz_v = doz_v + fon / 100.0 / 36.0; time_doza = time_doza + 1; if (doz_v - doza_vr >= save_DOZ) //а не пора ли сохранить дозу ? { eeprom_wrD (); doza_vr = doz_v; } //Serial.print(" zam_poisk_counter="); //Serial.println(zam_poisk_counter); } if (millis() - gr_milis >= scrin_GRAF * 1000) //счет для графика { gr_milis = millis(); if (graph_type == 0) { val_ok = 0;//сброс удержания системного меню for (uint8_t s = 254; s >= (255 - scrin_GRAF); s--) { shet_gr = shet_gr + mass_poisk[s]; } shet_gr = shet_gr / scrin_GRAF; for (int i = 0; i < 83; i++) // сдвигаем массив графика { mass_p[i] = mass_p[i + 1]; } mass_p[82] = byte(shet_gr); if (GRAPH_count > 82) { GRAPH_max = 5; GRAPH_count = 0; } for (int i = 0; i < 82; i++) { if (mass_p[i] > GRAPH_max) { GRAPH_max = mass_p[i]; GRAPH_count = 0; } } GRAPH_count++; } if (graph_type == 1) { val_ok = 0;//сброс удержания системного меню shet_gr = shet - shet_n; if (shet_gr < 0) { shet_gr = 1; } shet_n = shet; for (int i = 0; i < 83; i++) { mass_p[i] = mass_p[i + 1]; } mass_p[82] = byte(shet_gr); } } } } //---------------------------------------------------------------------------------------------------------------- void clear_poisk_variables () { shet = 0; fon = 0; fon_254 = 0; zam_poisk_counter = 0; GRAPH_max = 5; GRAPH_count = 0; fon_vr254 = 0; fon_vr_poisk = 0; for (uint8_t i = 0; i < 84; i++) { mass_p[i] = 0; } // чистим массив графика for (uint8_t i = 0; i < 254; i++) { mass_poisk[i] = 0; } // чистим массив поиска } void signa () //индикация каждой частички звуком светом { shet_s = shet; if (!alarm_sound && tr2 == 0) //если флаг сигнала тревоги не поднят, генерим одиночные сигналы, озвучивающие пойманные частицы { if (!shet_s) {return;} //если залетели в функцию signa() при обнулении переменной shet_s - просто возвращаемся в точку вызова. Детальнее здесь: arduino.ru/forum/proekty/delaem-dozimetr?page=16#comment-318736 switch (ind_ON) //проверяем, какой тип индикации выбран { case 0: //индикация выключена break; case 1: //индикация звуком #ifdef buzzer_active //если задефайнен активный бузер { PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер } #else //пассивный бузер { tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге } #endif break; case 2: //индикация светом PORTB |= (1 << 5); //включаем светодиод delay(del_BUZZ); //длительность одиночного сигнала PORTB &= ~(1 << 5); //выключаем светодиод break; case 3: //индикация звуком и светом #ifdef buzzer_active //если задефайнен активный бузер { PORTB |= (1 << 5); //включаем светодиод PORTD |= (1 << 6); //включаем бузер delay(del_BUZZ); //длительность одиночного сигнала PORTD &= ~(1 << 6); //выключаем бузер PORTB &= ~(1 << 5); //выключаем светодиод } #else //пассивный бузер { PORTB |= (1 << 5); //включаем светодиод tone (6,1000,30); //генерим писк 1000Гц 30миллисекунд на 6й ноге delay(del_BUZZ);//длительность одиночного сигнала PORTB &= ~(1 << 5);//выключаем светодиод } #endif break; case 4: // индикация вибрацией PORTB |= (1 << 0); //включаем вибру delay(del_BUZZ); //длительность одиночного сигнала PORTB &= ~(1 << 0); // выключаем вибру } } else // если активен сигнал тревоги, то только мигаем светодиодом (независимо от того, включён или нет светодиод в меню) { PORTB |= (1 << 5); //включаем светодиод delay(del_BUZZ); PORTB &= ~(1 << 5);//выключаем светодиод } } //------------------------------------------------------------------------------------------------- void Schet() //прерывание от счетчика на пин 2 { shet++; if (shet>250) {overflow_alarm = 1;} // детект приближения к переполнению переменной } //------------------------------------------------------------------------------------------------- void generator() //накачка по обратной связи с АЦП { hv_adc = Read_HV(); if (hv_adc < ADC_value) //Значение АЦП при котором на выходе 400В { int c = puls; PORTD |= (1 << 5); //пин накачки while (c > 0) { asm("nop"); c--; } PORTD &= ~(1 << 5);//пин накачки speed_nakT++; } } //-------------------------------------------------------------------------------------------------- byte Read_HV () { ADCSRA = 0b11100111; #ifdef UNO_DIP //если при компилляции выбрана плата ArduinoUNO ADMUX = 0b11100101;//выбор внутреннего опорного 1,1В и А5 #else // если используется промини, нано или голый камень в tqfp ADMUX = 0b11100110;//выбор внутреннего опорного 1,1В и А6 #endif for (int i = 0; i < 10; i++) { while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; } result = 0; for (int i = 0; i < 10; i++) { while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; result += ADCH; } result /= 10; return result; } //---------------------------------------------------------------------------------------------------- void battery() //батарейка { if (bat_mill - millis() > 2000) { bat_mill = millis(); VCC_read(); } myGLCD.setFont(TinyFontRus); byte batprocent = 99; batprocent = ((VCC - batnapruga) * 100 / (batmax - batnapruga)); byte batline = 9; //Задаем длину линии батареи batline = 0.1 * ((VCC - batnapruga) * 100 / (batmax - batnapruga)); //Зависимость длинны в пикселях от процента заряда if (batproc == 1 && VCC < batusb && batprocent < 100) {myGLCD.printNumF(batprocent, 0, 58, 0);myGLCD.print("%", 66, 0);} // процент заряда if (batproc == 2) {myGLCD.printNumF(VCC, 2, 54, 0);} // процент заряда if (batprocent > 5 && (VCC - batnapruga) > 0.01) //Проверяем процентный заряд акб 0.05 - 5% { if (VCC > batusb) { myGLCD.drawBitmap(71, 0, logo_bat_usb, 13, 5); } else { myGLCD.drawBitmap(71, 0, logo_bat, 13, 5); if (batprocent >= 100) {batline = 9;}; myGLCD.drawBitmap(82 - batline, 1, logo_bat_line, batline + 1, 3); } } else //Если заряд меньше 5% мигаем пустой батарейкой { toch = !toch; if (toch == 0) { myGLCD.drawBitmap(71, 0, logo_bat, 13, 5); } else { myGLCD.drawBitmap(71, 0, logo_bat, 0, 0); } } } //---------------------------------------------------------------------------------------------------- void VCC_read() // Чтение напряжения батареи { ADCSRA = 0b11100111; ADMUX = 0b01101110;//Выбор внешнего опорного+BG _delay_ms(5); while ((ADCSRA & 0x10) == 0); ADCSRA |= 0x10; byte resu = ADCH; //ADCSRA &= ~(1 << ADEN); // отключаем АЦП, VCC = (opornoe * 255.0) / resu; } //---------------------------------------------------------------------------------------------------- void lcd_init() { myGLCD.InitLCD(); myGLCD.setContrast(contrast); myGLCD.clrScr(); myGLCD.drawBitmap(0, 0, logo_rag, 84, 48); //myGLCD.setFont(SmallFontRus); // myGLCD.print(utf8rus("Ардуино+"), CENTER, 32); // myGLCD.print(utf8rus("Дозиметр v1.07"), CENTER, 40); myGLCD.update(); _delay_ms(1000); } //---------------------------------------------------------------------------------------------------- void eeprom_wrS () //запись настроек в память { EEPROM.write(0, 222); EEPROM.write(1, treviga_1); EEPROM.write(2, podsvetka); EEPROM.write(3, graph_type); EEPROM.write(4, scrin_GRAF); EEPROM.write(5, ind_ON); EEPROM.write(6, puls); EEPROM.write(7, opornoe * 100); EEPROM.write(8, treviga_2); EEPROM.write(100, batproc); EEPROM.write(17, beta_time); myGLCD.clrScr(); myGLCD.setFont(SmallFontRus); myGLCD.print(utf8rus("Сохранено"), CENTER, 20); myGLCD.update(); _delay_ms(1000); } //----------------------------------------------------------------------------------------------------- void eeprom_wrD () //запись настроек в память время накопления дозы { EEPROM.put(9, time_doza); EEPROM.put(13, doz_v); } //----------------------------------------------------------------------------------------------------- void eeprom_readD () //чтение настроек из памяти время накопления дозы { EEPROM.get(9, time_doza); EEPROM.get(13, doz_v); } //----------------------------------------------------------------------------------------------------- void eeprom_readS () //чтение настроек из памяти { if (EEPROM.read(0) == 222) { treviga_1 = EEPROM.read(1); podsvetka = EEPROM.read(2); graph_type = EEPROM.read(3); scrin_GRAF = EEPROM.read(4); ind_ON = EEPROM.read(5); puls = EEPROM.read(6); opornoe = EEPROM.read(7) / 100.0; treviga_2 = EEPROM.read(8); batproc = EEPROM.read(100); beta_time = EEPROM.read(17); } _delay_ms(11); } //------------------------------------------------------------------------------------------------------ void nakachka() //первая накачка { byte n = 0; while (n < 30) { PORTD |= (1 << 5);//дергаем пин int c = puls; while (c > 0) { asm("nop"); c--; } PORTD &= ~(1 << 5);//дергаем пин n++; _delay_us(100); } } //------------------------------------------------------------------------------------------------------ void speed_nakachka () //скорость накачки имлульсы/сек { if (millis() - spNAK_milis >= 1000) { spNAK_milis = millis(); speed_nak = speed_nakT; speed_nakT = 0; } } //------------------------------------------------------------------------------------------------------ void time_d() { MONTH = time_doza / 2592000; DAY = (time_doza / 86400) % 30 ; HOUR = (time_doza / 3600) % 24 ; MIN = (time_doza / 60) % 60; } //------------------------------------------------------------------------------------------------------ void check_alarm_signal() // устанавливаем сигнал непрерывной тревоги, если "tr" переключился в "1" { if (!tr) // если счёт превысил аварийный порог, но флаг "tr" ещё не установлен { alarm_sound = 1; // поднимаем флаг аварийного сигнала alarm_milis = millis(); // запоминаем время начала тревоги } } //------------------------------------------------------------------------------------------------------ void res_first_alarm() //подпрограмма выключения тревоги (ручного или по истечении таймаута) { alarm_sound = 0; // сбрасываем флаг звукового сигнала тревоги PORTB &= ~(1 << 0); // выключаем вибру periodical_alarm_variable = 0; // обнуляем переменную #ifdef buzzer_active //если задефайнен активный бузер PORTD &= ~(1 << 6); // выключаем бузер #else //пассивный бузер noTone(6); //выключаем генерацию сигнала на 6й ноге #endif } //------------------------------------------------------------------------------------------------------ void ind_doze_time() //вывод времени накопления дозы на дисплей { myGLCD.setFont(TinyFontRus); if (MONTH) // если есть месяцы { myGLCD.printNumI(MONTH, 0, 43); if(MONTH>99) { myGLCD.print("M", 13, 43); } else if (MONTH>9) { myGLCD.print("M", 9, 43); } else { myGLCD.print("M", 5, 43); } myGLCD.printNumI(DAY, 18, 43); if (DAY > 9) { myGLCD.print("\xBB", 26, 43); } else { myGLCD.print("\xBB", 23, 43); } } else if (DAY) // если нет месяцев, но есть дни { myGLCD.printNumI(DAY, 0, 43); if (DAY > 9) { myGLCD.print("\xBB", 9, 43); } else { myGLCD.print("\xBB", 5, 43); } myGLCD.printNumI(HOUR, 18, 43); if (HOUR > 9) { myGLCD.print("\xBA", 26, 43); } else { myGLCD.print("\xBA", 23, 43); } } else // если нет дней { myGLCD.printNumI(HOUR, 0, 43); if (HOUR > 9) { myGLCD.print("\xBA", 9, 43); } else { myGLCD.print("\xBA", 5, 43); } myGLCD.printNumI(MIN, 18, 43); if (MIN > 9) { myGLCD.print("\xBC", 26, 43); } else { myGLCD.print("\xBC", 23, 43); } } } //-------------------------------------------------------------------------------------------------------- byte get_key() // Функция определения нажатия и удержания кнопок { // версия 1 - для кратковременного нажатия значение возвращается при отпускании кнопки, для длительного - пока кнопка остаётся нажатой, с заданным интервалом uint8_t trigger_push_hold_counter = 10; // задержка триггера кратковременного/длительного нажатия (проходов функции, умноженных на задержку "milliseconds_between_increment") uint8_t milliseconds_between_increment = 50; // интервал в миллисекундах между инкрементом счётчика нажатой кнопки static uint8_t val_kp, val_kl, val_ok; static uint32_t key_delay_millis; static uint32_t key_delay_after_hold_millis; if ((millis() - key_delay_millis) > milliseconds_between_increment) //обрабатываем нажатия инкрементом переменной только если после предыдущей обработки прошло не менее "milliseconds_between_increment" миллисекунд { if (!(PIND & (1 << PIND4))) //нажатие >>> { val_kp++; // инкрементируем счётчик if (val_kp > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_kp = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_right; // возвращаем значение } } if (!(PIND & (1 << PIND7))) //нажатие <<< { val_kl++; // инкрементируем счётчик if (val_kl > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_kl = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_left; // возвращаем значение } } if (!(PIND & (1 << PIND3))) //нажатие OK { val_ok++; // инкрементируем счётчик if (val_ok > trigger_push_hold_counter) // если значение счётчика больше порога детектирования удержания клавиши { val_ok = 0; // сбрасываем счётчик key_delay_after_hold_millis = millis(); // запоминаем время return key_holded_ok; // возвращаем значение } } key_delay_millis = millis(); // запоминаем время } if (val_ok > 0) //если клавиша OK перед этим была нажата { if ((PIND & (1 << PIND3)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_ok = 0; // сбрасываем счётчик return key_pressed_ok; // возвращаем значение } } if (val_kp > 0) //если клавиша >>> перед этим была нажата { if ((PIND & (1 << PIND4)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_kp = 0; // сбрасываем счётчик return key_pressed_right; // возвращаем значение } } if (val_kl > 0) //если клавиша <<< перед этим была нажата { if ((PIND & (1 << PIND7)) && ((millis() - key_delay_after_hold_millis) > (trigger_push_hold_counter * milliseconds_between_increment))) // если клавиша на данный момент отпущена и с момента последнего удержания любой клавиши прошёл интервал больше, чем один интервал удержания клавиши { val_kl = 0; // сбрасываем счётчик return key_pressed_left; // возвращаем значение } } if (PIND & (1 << PIND4)) {val_kp = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") if (PIND & (1 << PIND7)) {val_kl = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") if (PIND & (1 << PIND3)) {val_ok = 0;} // если добрались до этой точки и кнопка не нажата - обнуляем счётчик (защита от появления "pressed" после "holded") return 0; // если ни одна из кнопок не была нажата - возвращаем 0 } //------------------------------------------------------------------------------------------------------------------------------ char *utf8rus(char *source) // функция преобразования utf8 для вывода кириллицы (by arduinec) { int i,j,k; unsigned char n; char m[2] = { '0', '\0' }; strcpy(target, ""); k = strlen(source); i = j = 0; while (i < k) { n = source[i]; i++; if (n >= 0xC0) { switch (n) { case 0xD0: { n = source[i]; i++; if (n == 0x81) { n = 0xA8; break; } if (n >= 0x90 && n <= 0xBF) n = n + 0x30; break; } case 0xD1: { n = source[i]; i++; if (n == 0x91) { n = 0xB8; break; } if (n >= 0x80 && n <= 0x8F) n = n + 0x70; break; } } } m[0] = n; strcat(target, m); j++; if (j >= maxString) break; } return target; } ISR (TIMER1_OVF_vect) // прерывание по таймеру, генерируемое каждую секунду { timer_seconds++ ; //инкремент переменной каждую секунду if (timer_seconds > 59){timer_seconds = 0;} } // ________________ конец скетча, дальше можно не копировать _____________________Графика
// файл gif.c // должен находиться в папке со скетчем #include <avr/pgmspace.h> #ifndef fontdatatype #define fontdatatype const uint8_t #endif const unsigned char PROGMEM logo_bat[] = {0xe,0x1f,0x11,0x11, 0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11, 0x1f}; const unsigned char PROGMEM logo_bat_line[] = {0x7,0x7,0x7,0x7, 0x7,0x7,0x7,0x7, 0x7,0x7}; const unsigned char PROGMEM logo_bat_usb[] = {0xf,0x10,0x10,0xf, 0x0,0x17,0x15,0x1d, 0x0,0x1f,0x15,0x15, 0xa }; const unsigned char PROGMEM logo_tr[] = { 0x0C, 0x12, 0x21, 0x0C, 0x00, 0x10, 0x28, 0x26, 0x61, 0x61, 0x26, 0x28, 0x10, 0x00, 0x0C, 0x21, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char PROGMEM fon_poisk[] = {0xc0,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0xc0,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0xc0, 0xff,0x0,0x10,0x10, 0x10,0x0,0x10,0x10, 0x10,0x0,0xd0,0x50, 0x90,0x0,0x90,0x10, 0x10,0x0,0x10,0x10, 0x10,0x0,0x10,0x10, 0x10,0x0,0xff,0x0, 0x0,0x7e,0x3d,0x3, 0x3,0x3,0x3,0x3, 0x3,0x3d,0x7e,0x0, 0x0,0x7e,0x3d,0x3, 0x3,0x3,0x3,0x3, 0x3,0x3d,0x7e,0x0, 0x0,0x7e,0x3d,0x3, 0x3,0x3,0x3,0x3, 0x3,0x3d,0x7e,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xff, 0xff,0x10,0x17,0x13, 0x17,0x10,0x17,0x12, 0x15,0x10,0x17,0x11, 0x14,0x13,0x10,0x13, 0x12,0x17,0x10,0x17, 0x13,0x17,0x10,0x17, 0x15,0x10,0xff,0x0, 0x0,0x3f,0x5e,0x60, 0x60,0x60,0x60,0x60, 0x60,0x5e,0x3f,0x0, 0x0,0x3f,0x5e,0x60, 0x60,0x60,0x60,0x60, 0x60,0x5e,0x3f,0x0, 0x0,0x3f,0x5e,0x60, 0x60,0x60,0x60,0x60, 0x60,0x5e,0x3f,0x0, 0x0,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x0,0xff, 0xff,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0xff, 0xff,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0xff, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; const unsigned char PROGMEM mkr[] = {0x7c,0x8,0x10,0x8, 0x7c,0x0,0x7c,0x10, 0x10,0x28,0x44,0x0, 0x7f,0x9,0x9,0x6, 0x1,0x1d,0x21,0x21, 0x7d,0x1,0x79,0x15, 0x15,0x79,0x1,0x39, 0x45,0x45,0x45,0x1}; const unsigned char PROGMEM mr[] = {0x0,0x0,0x7c,0x8, 0x10,0x8,0x7c,0x0, 0x0,0x7f,0x9,0x9, 0x6,0x0,0x0,0x0, 0x1,0x1d,0x21,0x21, 0x7d,0x1,0x79,0x15, 0x15,0x79,0x1,0x39, 0x45,0x45,0x45,0x1}; const unsigned char PROGMEM em_logo[] = {0x0,0x0,0x0,0x20, 0x30,0x38,0x98,0xd8, 0xf8,0xf0,0xf0,0xee, 0xce,0x8e,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe0, 0xc0,0x80,0x0,0x0, 0x0,0x0,0x18,0x18, 0x18,0x1c,0xf,0x87, 0xc7,0xef,0x7d,0x38, 0x10,0x1,0x3,0x3, 0x3,0x3,0x0,0x0, 0x7,0x7,0x7,0x7, 0x7,0x7,0x7,0x7, 0x7,0x7,0x7,0x7, 0x3f,0x1f,0xf,0x7, 0x2,0x0,0x0,0x0, 0x0,0x0,0x0,0x1, 0x1,0x1,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0}; const unsigned char PROGMEM logo_rag[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x78, 0x78, 0x78, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF8, 0x98, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0x9F, 0x81, 0x81, 0x81, 0x9F, 0xFF, 0xFF, 0xFC, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1E, 0x0F, 0x0F, 0x0F, 0x06, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFC, 0xFF, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x36, 0x78, 0x78, 0x78, 0x36, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF, 0xFC, 0x00, 0xFC, 0xFE, 0xFF, 0xEF, 0xC7, 0xC7, 0x8F, 0x0F, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFC, 0xFF, 0xFF, 0xFF, 0x1F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x7E, 0x7F, 0x3F, 0x3F, 0x0F, 0x07, 0x00, 0x01, 0x0F, 0x1E, 0x38, 0x70, 0x60, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0x60, 0x70, 0x38, 0x1F, 0x07, 0x01, 0x00, 0x79, 0xF9, 0xF1, 0xF3, 0xF7, 0xFF, 0xFF, 0x7F, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00, 0x7C, 0x24, 0x24, 0x24, 0x18, 0x00, 0x60, 0x3C, 0x24, 0x3C, 0x60, 0x00, 0x0C, 0x50, 0x50, 0x50, 0x3C, 0x00, 0x7C, 0x20, 0x10, 0x08, 0x7C, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3E, 0x23, 0x3F, 0x60, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x28, 0x44, 0x54, 0x54, 0x28, 0x00, 0x7C, 0x20, 0x10, 0x08, 0x7C, 0x00, 0x7C, 0x08, 0x10, 0x08, 0x7C, 0x00, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x04, 0x04, 0x7C, 0x04, 0x04, 0x00, 0x7C, 0x24, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x36, 0x49, 0x49, 0x49, 0x36}; // заставка БЕТА режима первая const unsigned char PROGMEM beta_prev_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x05, 0x02, 0x00, 0x1F, 0x15, 0x11, 0x00, 0x1B, 0x1F, 0x1B, 0x00, 0x1F, 0x0C, 0x1F, 0x00, 0x1F, 0x07, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x05, 0x02, 0x00, 0x1E, 0x05, 0x1E, 0x00, 0x11, 0x15, 0x0A, 0x00, 0x1F, 0x04, 0x1F, 0x00, 0x0E, 0x11, 0x0E, 0x00, 0x0E, 0x11, 0x0A, 0x00, 0x01, 0x1F, 0x01, 0x00, 0x1F, 0x04, 0x1F, 0x00, 0x0E, 0x11, 0x0E, 0x00, 0x1F, 0x01, 0x01, 0x00, 0x0E, 0x11, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x15, 0x0A, 0x00, 0x1E, 0x05, 0x1E, 0x00, 0x1F, 0x07, 0x1F, 0x00, 0x1F, 0x15, 0x11, 0x00, 0x1F, 0x05, 0x02, 0x00, 0x1E, 0x05, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x71, 0x41, 0xF1, 0x01, 0xE1, 0x11, 0xA1, 0x01, 0x11, 0xF1, 0x11, 0x01, 0xE1, 0x51, 0xE1, 0x01, 0xF1, 0x41, 0xF1, 0x01, 0xE1, 0x11, 0xE1, 0x01, 0xF1, 0x51, 0xA1, 0x01, 0xF1, 0xC1, 0xF1, 0x01, 0x11, 0xF1, 0x11, 0x01, 0xF1, 0x51, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0xF1, 0x11, 0xF1, 0x01, 0xF1, 0x51, 0x21, 0x01, 0xF1, 0xC1, 0xF1, 0x01, 0xF1, 0x51, 0x91, 0x01, 0xE1, 0x11, 0xE1, 0x01, 0xF1, 0x51, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x40, 0xF1, 0x01, 0xE0, 0x50, 0xE0, 0x01, 0x00, 0x00, 0xF0, 0x11, 0xF0, 0x00, 0x71, 0x40, 0xF1, 0x00, 0xE1, 0x10, 0xA1, 0x00, 0x10, 0xF1, 0x10, 0x00, 0x71, 0x41, 0xF0, 0x00, 0xF1, 0xE0, 0x11, 0xE0, 0x00, 0x01, 0x00, 0xF0, 0x41, 0x91, 0x01, 0xF0, 0xE0, 0x10, 0xE0, 0x00, 0xF1, 0x50, 0xA1, 0x00, 0xF1, 0x50, 0x10, 0x00, 0x11, 0xF0, 0x11, 0x00, 0x71, 0x41, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0xC0, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xF0, 0x81, 0x80, 0x80, 0xF0, 0x01, 0xC0, 0x21, 0x10, 0x21, 0xC1, 0x00, 0x70, 0x80, 0xE1, 0x80, 0x70, 0x00, 0xF1, 0x20, 0xC0, 0x21, 0xF1, 0x00, 0xF0, 0x01, 0x80, 0x61, 0xF0, 0x00, 0x10, 0x10, 0xF1, 0x10, 0x11, 0x00, 0xF1, 0x90, 0x91, 0x90, 0x10, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0xE0, 0x10, 0x11, 0x10, 0xE0, 0x01, 0xF1, 0x80, 0x40, 0x20, 0x10, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x01, 0x01, 0x01, 0x07, 0x00, 0x07, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // заставка БЕТА режима вторая const unsigned char PROGMEM beta_prev_2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x15, 0x0A, 0x00, 0x1E, 0x05, 0x1E, 0x00, 0x1F, 0x07, 0x1F, 0x00, 0x1F, 0x15, 0x11, 0x00, 0x1F, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x0E, 0x00, 0x1F, 0x15, 0x1D, 0x00, 0x1F, 0x05, 0x02, 0x00, 0x1E, 0x05, 0x1E, 0x00, 0x11, 0x15, 0x0A, 0x00, 0x1F, 0x10, 0x1F, 0x30, 0x1E, 0x05, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, 0x51, 0xA1, 0x01, 0xE1, 0x51, 0xE1, 0x01, 0xF1, 0x11, 0xF1, 0x01, 0xE1, 0x11, 0xE1, 0x01, 0xE1, 0x11, 0xF1, 0x01, 0xF1, 0x41, 0xF1, 0x01, 0xF1, 0xC1, 0xF1, 0x01, 0x11, 0xF1, 0x11, 0x01, 0xF1, 0x51, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0xF1, 0x41, 0x91, 0x01, 0xF1, 0xE1, 0x11, 0xE1, 0x01, 0xF1, 0x51, 0xA1, 0x01, 0xF1, 0x51, 0x11, 0x01, 0x11, 0xF1, 0x11, 0x01, 0x71, 0x41, 0xF1, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xF0, 0xC0, 0xF0, 0x00, 0x10, 0x50, 0xA0, 0x00, 0xF1, 0x71, 0xF0, 0x00, 0xF1, 0x50, 0x11, 0x00, 0xF1, 0x50, 0x21, 0x00, 0xA0, 0x51, 0xF0, 0x00, 0xF1, 0x50, 0x11, 0x00, 0xF1, 0x70, 0xF1, 0x00, 0xF1, 0x40, 0x81, 0xF0, 0x00, 0xF1, 0x70, 0xF0, 0x01, 0x01, 0x01, 0x00, 0xF0, 0x50, 0xA0, 0x00, 0xF1, 0x50, 0x11, 0x00, 0xF1, 0xC0, 0xF1, 0x00, 0xF0, 0x51, 0x11, 0x00, 0xE0, 0x11, 0xA1, 0x01, 0x10, 0xF0, 0x11, 0x00, 0xF0, 0x51, 0xA1, 0x00, 0xE0, 0x10, 0xE0, 0x00, 0xF0, 0x70, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x71, 0x41, 0xF0, 0x00, 0xE1, 0x10, 0xA1, 0x00, 0x11, 0xF1, 0x11, 0x00, 0xE1, 0x50, 0xE0, 0x00, 0xF1, 0x40, 0xF1, 0x00, 0xE1, 0x11, 0xE1, 0x00, 0xF1, 0x50, 0xA1, 0x00, 0xF1, 0xC1, 0xF0, 0x01, 0x10, 0xF1, 0x10, 0x01, 0xF0, 0x50, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0xF1, 0x11, 0xF1, 0x00, 0xF1, 0x51, 0x23, 0x00, 0xF1, 0xC1, 0xF1, 0x00, 0xF0, 0x51, 0xD0, 0x00, 0xE0, 0x11, 0xE0, 0x00, 0xF1, 0x51, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF1, 0xC0, 0xF1, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF0, 0x80, 0x81, 0x80, 0xF0, 0x01, 0xC0, 0x21, 0x10, 0x21, 0xC0, 0x01, 0x70, 0x80, 0xE1, 0x80, 0x70, 0x01, 0xF1, 0x20, 0xC0, 0x21, 0xF0, 0x01, 0xF0, 0x00, 0x81, 0x60, 0xF0, 0x01, 0x11, 0x11, 0xF0, 0x10, 0x10, 0x00, 0xF0, 0x91, 0x90, 0x91, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xE0, 0x11, 0x11, 0x11, 0xE0, 0x00, 0xF1, 0x80, 0x40, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x01, 0x01, 0x01, 0x07, 0x00, 0x07, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char PROGMEM beta_fon[] = {0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xc0,0xc0,0xc0,0xc0, 0xff,0xff,0xc1,0xae, 0xb6,0xba,0xc1,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xdd,0xb6,0xb6,0xa2, 0xc9,0xff,0xdf,0xab, 0xab,0xab,0x87,0xff, 0x83,0xf7,0xef,0xf7, 0x83,0xff,0xc7,0xab, 0xab,0xab,0xe7,0xff, 0x83,0xdb,0xdb,0xdb, 0xe7,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xbd, 0x80,0xbf,0xff,0xff, 0xff,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0xff,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0xff, 0xff,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x1f,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0xff, 0xff,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xff, 0xff,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0x80, 0x80,0x80,0x80,0xff}; const unsigned char PROGMEM bs[] = {0xc7,0xc7,0xc7,0x1, 0x1,0x1}; //---------------------------------------------------------------------- // Секция шрифтов // Font size : 6x8 pixels fontdatatype SmallFontRus[] PROGMEM={ 0x06,0x08,0x20,0x5F, 0x00,0x00,0x00,0x00,0x00,0x00, // <space> 0x00,0x00,0x00,0x2F,0x00,0x00, // ! 0x00,0x00,0x07,0x00,0x07,0x00, // " 0x00,0x14,0x7F,0x14,0x7F,0x14, // # 0x00,0x24,0x2A,0x7F,0x2A,0x12, // $ 0x00,0x23,0x13,0x08,0x64,0x62, // % 0x00,0x36,0x49,0x55,0x22,0x50, // & 0x00,0x00,0x05,0x03,0x00,0x00, // ' 0x00,0x00,0x1C,0x22,0x41,0x00, // ( 0x00,0x00,0x41,0x22,0x1C,0x00, // ) 0x00,0x14,0x08,0x3E,0x08,0x14, // * 0x00,0x08,0x08,0x3E,0x08,0x08, // + 0x00,0x00,0x00,0xA0,0x60,0x00, // , 0x00,0x08,0x08,0x08,0x08,0x08, // - 0x00,0x00,0x60,0x60,0x00,0x00, // . 0x00,0x20,0x10,0x08,0x04,0x02, // / 0x00,0x3E,0x51,0x49,0x45,0x3E, // 0 0x00,0x00,0x42,0x7F,0x40,0x00, // 1 0x00,0x42,0x61,0x51,0x49,0x46, // 2 0x00,0x21,0x41,0x45,0x4B,0x31, // 3 0x00,0x18,0x14,0x12,0x7F,0x10, // 4 0x00,0x27,0x45,0x45,0x45,0x39, // 5 0x00,0x3C,0x4A,0x49,0x49,0x30, // 6 0x00,0x01,0x71,0x09,0x05,0x03, // 7 0x00,0x36,0x49,0x49,0x49,0x36, // 8 0x00,0x06,0x49,0x49,0x29,0x1E, // 9 0x00,0x00,0x36,0x36,0x00,0x00, // : 0x00,0x00,0x56,0x36,0x00,0x00, // ; 0x00,0x08,0x14,0x22,0x41,0x00, // < 0x00,0x14,0x14,0x14,0x14,0x14, // = 0x00,0x00,0x41,0x22,0x14,0x08, // > 0x00,0x02,0x01,0x51,0x09,0x06, // ? 0x00,0x32,0x49,0x59,0x51,0x3E, // @ 0x00,0x7C,0x12,0x11,0x12,0x7C, // A 0x00,0x7F,0x49,0x49,0x49,0x36, // B 0x00,0x3E,0x41,0x41,0x41,0x22, // C 0x00,0x7F,0x41,0x41,0x22,0x1C, // D 0x00,0x7F,0x49,0x49,0x49,0x41, // E 0x00,0x7F,0x09,0x09,0x09,0x01, // F 0x00,0x3E,0x41,0x49,0x49,0x7A, // G 0x00,0x7F,0x08,0x08,0x08,0x7F, // H 0x00,0x00,0x41,0x7F,0x41,0x00, // I 0x00,0x20,0x40,0x41,0x3F,0x01, // J 0x00,0x7F,0x08,0x14,0x22,0x41, // K 0x00,0x7F,0x40,0x40,0x40,0x40, // L 0x00,0x7F,0x02,0x0C,0x02,0x7F, // M 0x00,0x7F,0x04,0x08,0x10,0x7F, // N 0x00,0x3E,0x41,0x41,0x41,0x3E, // O 0x00,0x7F,0x09,0x09,0x09,0x06, // P 0x00,0x3E,0x41,0x51,0x21,0x5E, // Q 0x00,0x7F,0x09,0x19,0x29,0x46, // R 0x00,0x46,0x49,0x49,0x49,0x31, // S 0x00,0x01,0x01,0x7F,0x01,0x01, // T 0x00,0x3F,0x40,0x40,0x40,0x3F, // U 0x00,0x1F,0x20,0x40,0x20,0x1F, // V 0x00,0x3F,0x40,0x38,0x40,0x3F, // W 0x00,0x63,0x14,0x08,0x14,0x63, // X 0x00,0x07,0x08,0x70,0x08,0x07, // Y 0x00,0x61,0x51,0x49,0x45,0x43, // Z 0x00,0x00,0x7F,0x41,0x41,0x00, // [ 0xAA,0x55,0xAA,0x55,0xAA,0x55, // <backslash> 0x00,0x00,0x41,0x41,0x7F,0x00, // ] 0x00,0x04,0x02,0x01,0x02,0x04, // ^ 0x00,0x40,0x40,0x40,0x40,0x40, // _ 0x00,0x00,0x03,0x05,0x00,0x00, // ` 0x00,0x7C,0x12,0x11,0x12,0x7C, // a 0x00,0x7F,0x49,0x49,0x49,0x36, // b 0x00,0x7F,0x49,0x49,0x49,0x36, // c 0x00,0x7F,0x01,0x01,0x01,0x01, // d 0x00,0x60,0x3E,0x23,0x3F,0x60, // e 0x00,0x7F,0x49,0x49,0x49,0x41, // f 0x00,0x77,0x08,0x3E,0x08,0x77, // g 0x00,0x22,0x49,0x49,0x5D,0x36, // h 0x00,0x00,0x44,0x7D,0x40,0x00, // i 0x00,0x40,0x80,0x84,0x7D,0x00, // j 0x00,0x7F,0x10,0x28,0x44,0x00, // k 0x00,0x00,0x41,0x7F,0x40,0x00, // l 0x00,0x7C,0x04,0x18,0x04,0x78, // m 0x00,0x7C,0x08,0x04,0x04,0x78, // n 0x00,0x38,0x44,0x44,0x44,0x38, // o 0x00,0xFC,0x24,0x24,0x24,0x18, // p 0x00,0x18,0x24,0x24,0x18,0xFC, // q 0x00,0x7C,0x08,0x04,0x04,0x08, // r 0x00,0x48,0x54,0x54,0x54,0x20, // s 0x00,0x04,0x3F,0x44,0x40,0x20, // t 0x00,0x3C,0x40,0x40,0x20,0x7C, // u 0x00,0x1C,0x20,0x40,0x20,0x1C, // v 0x00,0x3C,0x40,0x30,0x40,0x3C, // w 0x00,0x44,0x28,0x10,0x28,0x44, // x 0x00,0x1C,0xA0,0xA0,0xA0,0x7C, // y 0x00,0x44,0x64,0x54,0x4C,0x44, // z 0x00,0x00,0x10,0x7C,0x82,0x00, // { 0x00,0x00,0x00,0xFF,0x00,0x00, // | 0x00,0x00,0x82,0x7C,0x10,0x00, // } 0x00,0x00,0x06,0x09,0x09,0x06, // ~ //----------------------------------- 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x7E,0x4B,0x4A,0x4B,0x42, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x20, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x38,0x55,0x54,0x55,0x58, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x03,0x05,0x00,0x00, // 0x00,0x7C,0x12,0x11,0x12,0x7C, // 0x00,0x7F,0x49,0x49,0x49,0x30, // 0x00,0x7F,0x49,0x49,0x49,0x36, // 0x00,0x7F,0x01,0x01,0x01,0x01, // 0x00,0x60,0x3E,0x23,0x3F,0x60, // 0x00,0x7F,0x49,0x49,0x49,0x41, // 0x00,0x77,0x08,0x3E,0x08,0x77, // 0x00,0x22,0x49,0x49,0x5D,0x36, // 0x00,0x7F,0x30,0x08,0x06,0x7F, // 0x00,0x7F,0x30,0x19,0x0C,0x7F, // 0x00,0x7F,0x08,0x08,0x14,0x63, // 0x00,0x40,0x7E,0x01,0x01,0x7F, // 0x00,0x7F,0x02,0x0C,0x02,0x7F, // 0x00,0x7F,0x08,0x08,0x08,0x7F, // 0x00,0x3E,0x41,0x41,0x41,0x3E, // 0x00,0x7F,0x01,0x01,0x01,0x7F, // 0x00,0x7F,0x09,0x09,0x09,0x06, // 0x00,0x3E,0x41,0x41,0x41,0x22, // 0x00,0x01,0x01,0x7F,0x01,0x01, // 0x00,0x07,0x48,0x48,0x48,0x3F, // 0x00,0x0E,0x11,0x7F,0x11,0x0E, // 0x00,0x63,0x14,0x08,0x14,0x63, // 0x00,0x3F,0x20,0x20,0x3F,0x60, // 0x00,0x07,0x08,0x08,0x08,0x7F, // 0x00,0x7F,0x40,0x7E,0x40,0x7F, // 0x00,0x3F,0x20,0x3F,0x20,0x7F, // 0x40,0x01,0x7F,0x48,0x48,0x30, // 0x00,0x7F,0x48,0x30,0x00,0x7F, // 0x00,0x7F,0x48,0x48,0x30,0x00, // 0x41,0x49,0x49,0x49,0x3E,0x00, // 0x00,0x7F,0x08,0x3E,0x41,0x3E, 0x00,0x46,0x29,0x19,0x09,0x7F, //----------------------------------- //0x00,0x00,0x00,0x00,0x00,0x00, //0x00,0x7C,0x10,0x7C,0x44,0x7C, 0x00,0x20,0x54,0x54,0x54,0x78, // 0x00,0x3C,0x4A,0x4A,0x4A,0x30, // 0x00,0x7C,0x54,0x54,0x54,0x28, // 0x00,0x7C,0x04,0x04,0x04,0x00, // 0x00,0x60,0x3C,0x24,0x3C,0x60, // 0x00,0x38,0x54,0x54,0x54,0x18, // 0x00,0x6C,0x10,0x7C,0x10,0x6C, // 0x00,0x28,0x44,0x54,0x54,0x28, // 0x00,0x7C,0x20,0x10,0x08,0x7C, // 0x00,0x7C,0x20,0x12,0x08,0x7C, // 0x00,0x7C,0x10,0x10,0x28,0x44, // 0x00,0x40,0x7C,0x04,0x04,0x7C, // 0x00,0x7C,0x08,0x10,0x08,0x7C, // 0x00,0x7C,0x10,0x10,0x10,0x7C, // 0x00,0x38,0x44,0x44,0x44,0x38, // 0x00,0x7C,0x04,0x04,0x04,0x7C, // 0x00,0x7C,0x24,0x24,0x24,0x18, // 0x00,0x38,0x44,0x44,0x44,0x28, // 0x00,0x04,0x04,0x7C,0x04,0x04, // 0x00,0x0C,0x50,0x50,0x50,0x3C, // 0x00,0x18,0x24,0x7C,0x24,0x18, // 0x00,0x44,0x28,0x10,0x28,0x44, // 0x00,0x3C,0x20,0x20,0x3C,0x60, // 0x00,0x1C,0x20,0x20,0x7C,0x00, // 0x00,0x7C,0x40,0x78,0x40,0x7C, // 0x00,0x3C,0x20,0x3C,0x20,0x7C, // 0x40,0x04,0x7C,0x50,0x50,0x20, // 0x00,0x7C,0x50,0x70,0x00,0x7C, // 0x00,0x7C,0x50,0x50,0x20,0x00, // 0x44,0x54,0x54,0x54,0x38,0x00, // 0x00,0x7C,0x10,0x7C,0x44,0x7C, 0x00,0x48,0x54,0x34,0x14,0x7C, }; /* fontdatatype rus_4x6[] PROGMEM = { 0x04, 0x08, 0xC0, 0x20, 0x00, 0x3c, 0x12, 0x3c, // Code for char А 0x00, 0x3E, 0x2A, 0x12, // Code for char Б 0x00, 0x3E, 0x2A, 0x14, // Code for char В 0x00, 0x3E, 0x02, 0x02, // Code for char Г 0x00, 0x30, 0x1E, 0x30, // Code for char Д 0x00, 0x3E, 0x2A, 0x22, // Code for char Е 0x00, 0x36, 0x3E, 0x36, // Code for char Ж 0x00, 0x22, 0x2A, 0x14, // Code for char З 0x00, 0x3E, 0x18, 0x3E, // Code for char И 0x00, 0x3E, 0x19, 0x3E, // Code for char Й 0x00, 0x3E, 0x08, 0x22, // Code for char К 0x00, 0x3C, 0x02, 0x3E, // Code for char Л 0x00, 0x3E, 0x0E, 0x3E, // Code for char М 0x00, 0x3E, 0x08, 0x3E, // Code for char Н 0x00, 0x1C, 0x22, 0x1C, // Code for char О 0x00, 0x3E, 0x02, 0x3E, // Code for char П 0x00, 0x3E, 0x0A, 0x04, // Code for char Р 0x00, 0x1C, 0x22, 0x14, // Code for char С 0x00, 0x02, 0x3E, 0x02, // Code for char Т 0x00, 0x06, 0x28, 0x1E, // Code for char У 0x00, 0x1C, 0x3E, 0x1C, // Code for char Ф 0x00, 0x36, 0x08, 0x36, // Code for char Х 0x00, 0x1E, 0x10, 0x2E, // Code for char Ц 0x00, 0x0E, 0x08, 0x3E, // Code for char Ч 0x00, 0x3E, 0x38, 0x3E, // Code for char Ш 0x00, 0x1E, 0x1C, 0x3E, // Code for char Щ 0x00, 0x3E, 0x28, 0x10, // Code for char Ъ 0x3E, 0x30, 0x00, 0x3E, // Code for char Ы 0x00, 0x3E, 0x28, 0x10, // Code for char Ь 0x00, 0x14, 0x2A, 0x1C, // Code for char Э 0x3E, 0x08, 0x3E, 0x3E, // Code for char Ю 0x00, 0x34, 0x0A, 0x3E, // Code for char Я }; */ fontdatatype TinyFontRus[] PROGMEM = { 0x04, 0x06, 0x20, 0x5f, 0x00, 0x00, 0x00, 0x03, 0xa0, 0x00, 0xc0, 0x0c, 0x00, 0xf9, 0x4f, 0x80, 0x6b, 0xeb, 0x00, 0x98, 0x8c, 0x80, 0x52, 0xa5, 0x80, 0x03, 0x00, 0x00, // Space, !"#$%&' 0x01, 0xc8, 0x80, 0x89, 0xc0, 0x00, 0x50, 0x85, 0x00, 0x21, 0xc2, 0x00, 0x08, 0x40, 0x00, 0x20, 0x82, 0x00, 0x00, 0x20, 0x00, 0x18, 0x8c, 0x00, // ()*+,-./ 0xfa, 0x2f, 0x80, 0x4b, 0xe0, 0x80, 0x5a, 0x66, 0x80, 0x8a, 0xa5, 0x00, 0xe0, 0x8f, 0x80, 0xea, 0xab, 0x00, 0x72, 0xa9, 0x00, 0x9a, 0x8c, 0x00, // 01234567 0xfa, 0xaf, 0x80, 0x4a, 0xa7, 0x00, 0x01, 0x40, 0x00, 0x09, 0x40, 0x00, 0x21, 0x48, 0x80, 0x51, 0x45, 0x00, 0x89, 0x42, 0x00, 0x42, 0x66, 0x00, // 89:;<=>? 0x72, 0xa6, 0x80, 0x7a, 0x87, 0x80, 0xfa, 0xa5, 0x00, 0x72, 0x25, 0x00, 0xfa, 0x27, 0x00, 0xfa, 0xa8, 0x80, 0xfa, 0x88, 0x00, 0x72, 0x2b, 0x00, // @ABCDEFG 0xf8, 0x8f, 0x80, 0x8b, 0xe8, 0x80, 0x8b, 0xe8, 0x00, 0xf8, 0x8d, 0x80, 0xf8, 0x20, 0x80, 0xf9, 0x0f, 0x80, 0xf9, 0xcf, 0x80, 0x72, 0x27, 0x00, // HIJKLMNO 0xfa, 0x84, 0x00, 0x72, 0x27, 0x40, 0xfa, 0x85, 0x80, 0x4a, 0xa9, 0x00, 0x83, 0xe8, 0x00, 0xf0, 0x2f, 0x00, 0xe0, 0x6e, 0x00, 0xf0, 0xef, 0x00, // PQRSTUVW 0xd8, 0x8d, 0x80, 0xc0, 0xec, 0x00, 0x9a, 0xac, 0x80, 0x03, 0xe8, 0x80, 0xc0, 0x81, 0x80, 0x8b, 0xe0, 0x00, 0x42, 0x04, 0x00, 0x08, 0x20, 0x80, // XYZ[\]^_ 0x02, 0x04, 0x00, 0x31, 0x23, 0x80, 0xf9, 0x23, 0x00, 0x31, 0x24, 0x80, 0x31, 0x2f, 0x80, 0x31, 0x62, 0x80, 0x23, 0xea, 0x00, 0x25, 0x53, 0x80, // `abcdefg 0xf9, 0x03, 0x80, 0x02, 0xe0, 0x00, 0x06, 0xe0, 0x00, 0xf8, 0x42, 0x80, 0x03, 0xe0, 0x00, 0x79, 0x87, 0x80, 0x39, 0x03, 0x80, 0x31, 0x23, 0x00, // hijklmno 0x7d, 0x23, 0x00, 0x31, 0x27, 0xc0, 0x78, 0x84, 0x00, 0x29, 0x40, 0x00, 0x43, 0xe4, 0x00, 0x70, 0x27, 0x00, 0x60, 0x66, 0x00, 0x70, 0x67, 0x00, // pqrstuvw 0x48, 0xc4, 0x80, 0x74, 0x57, 0x80, 0x59, 0xe6, 0x80, 0x23, 0xe8, 0x80, 0x03, 0x60, 0x00, 0x8b, 0xe2, 0x00, 0x61, 0x0c, 0x00, // zyx{|}~ 0x00, 0x00, 0x1E, // Index: 95 (0x005F) Character: 0x007F ('') 0x01, 0x07, 0x96, // Index: 96 (0x0060) Character: 0x0080 ('?') 0x00, 0x07, 0x90, // Index: 97 (0x0061) Character: 0x0081 ('?') 0x00, 0x30, 0x00, // Index: 98 (0x0062) Character: 0x0082 ('?') 0x00, 0x00, 0x00, // Index: 99 (0x0063) Character: 0x0083 ('?') 0x0C, 0x00, 0x00, // Index: 100 (0x0064) Character: 0x0084 ('?') 0x00, 0x00, 0x00, // Index: 101 (0x0065) Character: 0x0085 ('?') 0x00, 0x00, 0x00, // Index: 102 (0x0066) Character: 0x0086 ('?') 0x00, 0x00, 0x00, // Index: 103 (0x0067) Character: 0x0087 ('?') 0x00, 0x00, 0x00, // Index: 104 (0x0068) Character: 0x0088 ('?') 0x00, 0x00, 0x00, // Index: 105 (0x0069) Character: 0x0089 ('?') 0x00, 0x00, 0x00, // Index: 106 (0x006A) Character: 0x008A ('?') 0x00, 0x01, 0x0A, // Index: 107 (0x006B) Character: 0x008B ('?') 0x00, 0x00, 0x00, // Index: 108 (0x006C) Character: 0x008C ('?') 0x01, 0xE3, 0x12, // Index: 109 (0x006D) Character: 0x008D ('?') 0x01, 0x07, 0x96, // Index: 110 (0x006E) Character: 0x008E ('?') 0x01, 0xE0, 0xDE, // Index: 111 (0x006F) Character: 0x008F ('?') 0x01, 0xE1, 0x80, // Index: 112 (0x0070) Character: 0x0090 ('?') 0x01, 0x00, 0x00, // Index: 113 (0x0071) Character: 0x0091 ('?') 0x01, 0x00, 0x00, // Index: 114 (0x0072) Character: 0x0092 ('?') 0x40, 0x00, 0x00, // Index: 115 (0x0073) Character: 0x0093 ('?') 0x00, 0x00, 0x00, // Index: 116 (0x0074) Character: 0x0094 ('?') 0x00, 0x00, 0x00, // Index: 117 (0x0075) Character: 0x0095 ('?') 0x00, 0x00, 0x00, // Index: 118 (0x0076) Character: 0x0096 ('?') 0x00, 0x00, 0x00, // Index: 119 (0x0077) Character: 0x0097 ('?') 0x00, 0x00, 0x00, // Index: 120 (0x0078) Character: 0x0098 ('') 0x00, 0x00, 0x00, // Index: 121 (0x0079) Character: 0x0099 ('?') 0x00, 0x00, 0x00, // Index: 122 (0x007A) Character: 0x009A ('?') 0x00, 0x02, 0x84, // Index: 123 (0x007B) Character: 0x009B ('?') 0x00, 0x00, 0x00, // Index: 124 (0x007C) Character: 0x009C ('?') 0x00, 0x00, 0x00, // Index: 125 (0x007D) Character: 0x009D ('?') 0x00, 0x00, 0x00, // Index: 126 (0x007E) Character: 0x009E ('?') 0x00, 0x00, 0x00, // Index: 127 (0x007F) Character: 0x009F ('?') 0x00, 0x00, 0x00, // Index: 128 (0x0080) Character: 0x00A0 (' ') 0x00, 0x00, 0x00, // Index: 129 (0x0081) Character: 0x00A1 ('?') 0x00, 0x00, 0x00, // Index: 130 (0x0082) Character: 0x00A2 ('?') 0x00, 0x00, 0x9C, // Index: 131 (0x0083) Character: 0x00A3 ('?') 0x00, 0x00, 0x00, // Index: 132 (0x0084) Character: 0x00A4 ('¤') 0x00, 0x00, 0x00, // Index: 133 (0x0085) Character: 0x00A5 ('?') 0x00, 0x00, 0x00, // Index: 134 (0x0086) Character: 0x00A6 ('¦') 0x00, 0x00, 0x00, // 0xA7 0x03, 0xFF, 0xFF, // 0xA8 ||| 0x00, 0x0F, 0xFF, // 0xA9 || 0x00, 0x00, 0x3F, // 0xAA | 0x82, 0x08, 0x20, // 0xAB 1- 0xC3, 0x0C, 0x30, // 0xAC 2- 0xE3, 0x8E, 0x38, // 0xAD 3- 0xF3, 0xCF, 0x3C, // 0xAE 4- 0xFB, 0xEF, 0xBE, // 0xAF 5- 0x3C, 0xF3, 0xCF, // 0xB0 5_ 0x3C, 0xF3, 0xCF, // 0xB1 4_ 0x1C, 0x71, 0xC7, // 0xB2 3_ 0x0C, 0x30, 0xC3, // 0xB3 2_ 0x04, 0x10, 0x41, // 0xB4 1_ 0xFF, 0xFF, 0xFF, // 0xB5 |||| 0xFF, 0xFF, 0xC0, // 0xB6 ||| 0xFF, 0xF0, 0x00, // 0xB7 || 0xFC, 0x00, 0x00, // 0xB8 | 0x38, 0xA2, 0x80, // 0xB9 с 0x30, 0x43, 0x80, // 0xBA ч 0x18, 0xC1, 0x80, // 0xBB д 0x38, 0xC3, 0x80, // 0xBC м 0x38, 0x42, 0x80, // 0xBD к 0xFA, 0x84, 0x8C, // 0xBE Р/ 0x40, 0xC1, 0x0E, // 0xBF /ч 0x7A, 0x87, 0x80, // А 0xFA, 0xAB, 0x80, // Б 0xFA, 0xA5, 0x00, // В 0xFA, 0x08, 0x00, // Г 0x1B, 0xC1, 0x80, // Д 0xFA, 0xA8, 0x80, // Е 0xDB, 0xED, 0x80, // Ж 0x8A, 0xA5, 0x00, // З 0xF8, 0xCF, 0x80, // И 0x7A, 0xC7, 0x80, // Й 0xF8, 0x89, 0x80, // К 0x7A, 0x0F, 0x80, // Л 0xFB, 0x8F, 0x80, // М 0xF8, 0x8F, 0x80, // Н 0x72, 0x27, 0x00, // О 0xFA, 0x0F, 0x80, // П 0xFA, 0x84, 0x00, // Р 0x72, 0x28, 0x80, // С 0x83, 0xE8, 0x00, // Т 0xE8, 0xAF, 0x00, // У 0x73, 0xE7, 0x00, // Ф 0x89, 0xC8, 0x80, // Х 0xF8, 0x2F, 0x83, // Ц 0xE0, 0x8F, 0x80, // Ч 0xF8, 0xEF, 0x80, // Ш 0xF8, 0xEF, 0xC0, // Щ 0x83, 0xE2, 0x84, // Ъ 0xF8, 0xA1, 0x3E, // Ы 0xF8, 0xA1, 0x00, // Ь 0x8A, 0xA7, 0x00, // Э 0xF9, 0xC8, 0x9C, // Ю 0x5A, 0x8F, 0x80, // Я };Поэксперементировал я с MC34063, и с кольцами и с гантелькой...потом вообще работать перестало, похоже что МС-ка не выдержала, даёт какие то всплески и молчит.
Нашёл гантельку, диаметр шляпы - 1см. Откопал из запасов неплохие релюшки на 10А от Omron...т.к я их нигде не используию и они достались мне бесплатно из принтеров, то решено было раскурочить и смотать оттуда провод. Провод кстати оч тонкий, наверное 0,063, замерить нечем, в сравнении есть только 0,2мм. Гантельку за ноги зажал в патрон дрели и намотал на глаз "сколько то там". Наверное пол-гантели в толщину. Подпаялся, замерил - 34,5 mH. Замотал пару слоёв лентой фум. Сверху первичка проводом 0,2мм - 50 витков. Лента фум сверху.
У меня есть генератор шим с Али до 150 кГц с регулировкой скважности, ослик DSO203. Через полевик (STP65NF06) подключил генератор к гантельке. На выходе у гантельки Диод FR-607 и плёнка Suntan 1000V 10nF. Запитал всё это через литий с защитой и через мультиметр с замером тока.
Результаты были интересные. Сначала я думал, что нормально юзать гантельку под частотой 20-50кГц, при это добиться 400 Вольт оказалось возможно скважностью 50-60%, потребление было около 40мА (т.е это потребление только гантельки, диода, кондёра и транзистора без затвора (ЗЫ:затвор питается соответственно от генератора, который в свою очередь работал от USB)). Я полазил в верхних частотах 60+кГц, там дела обстаяли ещё хуже, околонулевые напряжения на выходе.
Тут я попёр в нижний диапозон...и тут началось главное! Чем ниже я опускался, тем меньше потреблялся ток и понижался % скважности. Лучше всего гантелька с моей намоткой работала как раз на частоте ШИМ ардуино 400-600 Гц, при этом скважность была 1%, а потребление тока было в районе 1,7 мА (и это при 4В)! Это конечно не рекордные 1мА, но разница с тем что я делал раньше ощутима.
Позже попробую тоже самое с кольцом. Если будет тоже самое, то буду думали либо о переходе на Ардуину в качестве ШИМ контроллера, либо буду заставлять работать 34063 на частотах меньше килогерца (хотя по даташиту это не возможно).
PS: а вообще за последние пару лет я построил более десятка ИИП, мощностью конечно больше 100 ватт, но на разных топологиях. Считал всегда на проге Старичка. Но вот это реально первая импульсная маленькая схема, с которой такие проблемы. К тому же гантельку не посчитать, а результаты кольца не верные. Хочется и ток пониже и напряжение без просадок...и на контроллере низковольтнои и ничего не выходит. От части Joiner прав, чтоб использовать внешний специализированный контроллер ИИП, а не ардуину, ведь в нормальных полноценных устройствах не отдают контроль таким устройствам. Как минимум ардуина может зависнуть, и если на маленьком маломощном устройстве это "ничего страшного", то на 10 амперном полумосте это может закончиться пожаром, а TL494 и ей подобные не страдают от этого. К тому же скорость реакции контроллера ИИП по фидбэку или по усилителю ошибки во много раз быстрее реакции любого контроллера. В нашей теме то понятно, накачка медленная и хватит тупого кода по типу "if V>400 else PWM STep -1".
Поэксперементировал я с MC34063, и с кольцами и с гантелькой....
Позже попробую тоже самое с кольцом. Если будет тоже самое, то буду думали либо о переходе на Ардуину в качестве ШИМ контроллера, либо буду заставлять работать 34063 на частотах меньше килогерца (хотя по даташиту это не возможно).
OfficialGalkin, а где баг по таймеру был? На вскидку код таймера тот же.
Частотозадающий конденсатор какой ёмкости?
Померил кольцо. Такая же история, на низких частотах, порядка 1-1,5кГц самый высокий КПД - минимум скважности и тока при максимуме напряжения. Ток у кольца оказался где то на 1мА больше чем у гантельки. Подключил всё это к МС-ке, Ст поставил на 22 нФ, это где то 1,5 кГц. Выдаёт максимум 220 вольт. Менял и полярность подключения - не помогает. Есть ощущение, что их не подружить. С обычным генератором я получил больше 1000 В с подключеным осликом через 90 Мом и напрямую подключеным мультиметром на 10Мом. И это при скважности меньше 10%
На днях попробую банальное тупое управление через ардуину, только не через стандартный PWM, а через сторонний PWM.h, там можно скважность до 16bit делать и частоту любую до 2МГц.
Dark-Dante, там же, где я и говорил. В строке 881 костыль, чуть выше условие его активации на последней минуте (хотя достаточно было последней секунды). Это не найденное решение, а маскировка бага.
понимаю но маленький экран не всегда удобно если он будет чуть больше бдет норм плюс можно выводить больше информацыи
Ну больший экран разве что для красоты. Для более красивого оформления. А информации и так достаточно, все что нужно выведено.
Понял. У меня бага нет, так как строку я эту выбросил сразу.
Привет я уже давно смотрю твои видео и повторяю твой дозиметр.И я хочу согласиться со сталкерами ведь дисплей легко разбить.У меня давно завалялись модули от ардуино и я нашел ардуино нано и цифровой дисплей с китая (TM1637) можешь дополнить самую первую схему с ардуино из этих двух компонентов? Я буду очень благодарен.И вот тебе лайфхак, с алиэкспрес можно заказать коробку для самоделок по твоему размеру просто введи в поиск "Пластиковый корпус для DIY". Надеюсь что из этого что то получится.
Ага, уже пошел пилить под все дисплеи и счётчики с али))
OficialGalkin, а в чём вы картинки рисуете для файла гиф.ц?
Всем привет. Смотрю изменеий фура пронеслась на крайних страница. Будут ли какие то правки в платы (схему) и что с прошивками и их описанием и изменениями?
Так же вопрос, можно ли подцепиться к ардуинке esp8266 к примеру и передавать онлайн данные на сайт какого нибудь народного контроля?
Глобально ничего не менялось, разве что супрессор в схему добавился.
Можно сделать вывод в юарт, а там хоть есп, хоть другой девайс. Но для мониторинга функционал избыточен, проще сделать преобразователь на блокинге, ограничитель 400В для стабилизации и считать самой еспшкой, не задействуя ардуину.
Тоже хочу собрать прибор для отправки данных на radmon, но не могу придумать, что делать с питанием и защитой от сырости. Литий и мороз не дружат, да и где-то читал, что сбм-20 с морозами тоже не очень. Если кто видел хорошие схемки, или может помочь, буду рад.
P.s. в теме наткнулся на пост, где Вы (tekagi) говорите про планы по проверке тлеющего, можете рассказать на словах хотябы, как это работает?
Питание лучше внешнее, сетевое. Тогда и нагреватель с термостабилизацией поставить можно. Про нестабильную работу СБМ при отрицательныx температрах тоже упоминания встречал. Ну и корпус обязательно герметичный, чтобы конденсата не было. Качественная электрическая распредкоробка в помощь, там и уплотнитель по периметру, и сальники зажимные поставить можно. Только не брать белые и полупрозрачные, они уф боятся и за пару лет рассыпаются.
По контролю задумка простая - к катодному резистору подвесить резистор и накопительный конденсатор, и на ацп. Если импульсов с формирователя нет, а на конденсаторе присутствует напряжение - идёт тлеющий разряд. Где-то схожая реализация попадалась. Можно, конечно, детектировать косвенно, по увеличению скорости накачки, но тогда придётся строить зависимости от фона и напряжения питания, не думаю, что такой вариант даст стабильный результат.
Я вот хочу свою плату развести. Хотелось бы на 16mhz что бы чип работал, но тогда надо что бы было питание 5 вольт. А это надо повышайку делать. При 3.8 вольтах уже 8 mhz частоту надо делать. Иначе могут быть глюки как мне сказал один человек. У меня ардуино нано на 2.9 даже работает на 16mhz, но он говорит что просто повезло и что многие будут глючить.
А с повышайкой будет лишняя потеря. И как отслеживать тогда напряжение на акб через ардуино?
OfficialGalkin, в какой программе графику рисуете для файла гиф.ц?
В Paint стандартном либо Paint . NET
Сохраняю в бмп и конвертирую онлайн.
http://pavelk.ru/konverter-kartinok-dlya-lcd-oled-128x64-displeya
OfficialGalkin, кто мешает использовать на 8 МГц?
Хотелось бы на 16mhz что бы чип работал, но тогда надо что бы было питание 5 вольт. А это надо повышайку делать. При 3.8 вольтах уже 8 mhz частоту надо делать. Иначе могут быть глюки
При повторении Ардоса тоже задавался этим вопросом. Глючить будет один камень из ста, хотя даташит говорит об обратном, но около 30 конструкций на 328й работающие от лития на 16, а то и 20-22 мГц говорят о том что разработчики просто перестраховались, так что не создавайте себе проблем на ровном месте, работает- не трогайте.
Гуру, расскажите, как в этой схеме работает повышайка
Чем данная схема хуже/лучше той, что используется в ардосе?
Такой же step-up, как и в АрДосе. Только дроссель не двухобмоточный и транзистор высоковольтный биполярный, что на кпд скажется не лучшим образом. И делитель на два мега есть будет, как не в себя.
http://electrik.info/main/praktika/1112-dcdc-preobrazovateli.html