Контроль за тепловым насосом на Arduino UNO

pav2000
Offline
Зарегистрирован: 15.12.2014
Для отопления загородного дома я использую тепловой насос (подробнее можно почитать https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BF%D0%BB%D0%BE%D0%B2%D0%BE%D0%B9_%D0%BD%D0%B0%D1%81%D0%BE%D1%81).  Я его запустил осенью прошлого года и от отработал один сезон. При потреблении  2.5-2.8 кВт тепловой насос выдает 11-12 кВт тепла с помощью которого я грею дом используя теплые полы (для отопления радиаторы не использую).  Штатно тепловой насос не может рассчитать  свою эффективность, потребленную и выработанную энергия и т.д. По этому было решено сделать блок на микроконтроллере который будет выдавать "на гора"   качество работы насоса. 
Само устройство достаточно примитивно и состоит из нескольких узлов:
1. Теплосчетчик (две шутки - на грунтовый контур и теплые полы) имеет три датчика - датчик расхода (водосчетчик) и два датчика температуры (DS18B20)
2. Узел контроля потребления электроэнергии  использует три датчика:
- определение потребляемого тока (трансформатор тока)
- определение напряжения сети (через трансформатор)
- импульсный вход от электросчетчика  (1000 импульсов 1 кВт/час)  это дублирует первые два датчика.
3. Ардуино  УНО и монохромный графический дисплей (128х64) + кнопка (которая листает экраны).
4. Радио модуль nrf24 для передачи информации на удаленное устройство индикации
 
Так как это мое первое устройство и я не занимался радио любительством лет 20 пришлось взять УНО.  Использовал готовый бокс, куда запихнул все компоненты. Пришлось купить инструменты, осцилограф и т.д. Все было ранее утеряно -(((
Проблемы при реализации:
- Не надо верить что уно можно запитать от 12 вольт - это очень много стабилизатор при этом нагревается не хило. Пришлось ставить резистор для гашения лишнего напряжения теперь подается 8 вольт,
- Достаточно долго трахался  мучился с датчиками потока. Их характеристики не соответствовали то что было написано в даташите. В конце концов откалибровал и получил вменяемые результаты.
- радиомодуль тоже не сразу заработал но в конце концов и его победил, Обязательно надо вешать емкость по питанию модуля.
- ихмо уно можно использовать только первый раз, в дальнейшем только про мини.

В дальнейшем обеспечу связь по радиоканалу с выносным блоком stm32. (http://arduino.ru/forum/proekty/udalennyi-monitoring-za-datchikami-na-ma...). С помощью этого прибора опимизировал работу теплых полов.  Установил блок из двух реле. Одно задействовал в защите теплового насоса (контроль потоков через контура). Второе пока свободно.

Стандартную библиотеку emonLib сильно переработал, поэтом напрямую влючил в проект. В файле шрифтов использую только один шрифт, по этому все остальные можно выкинуть из исходников.

 

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

Собсвенно файлы проекта:

файл lcd12864.ino

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

//#define DEMO                               // Признак демонстрации
#define RADIO                              // Признак использования радио модуля
#define VERSION "Ver. leOS2 1.46 020615"   // Текущая верстия

// Конфигурация платы UNO (куда что подключается) --------------------------------
// Прерывания 
#define sensorInterrupt1    0                  // Первый датчик потока адрес прерывания
#define sensorInterrupt2    1                  // Второй датчик потока адрес прерывания
// ЦИФРОВЫЕ Ноги 
#define PIN_FLOW1           2                  // Первый датчик потока ножка на которую вешается датчик Холла
#define PIN_FLOW2           3                  // Второй датчик потока ножка на которую вешается датчик Холла
#define PIN_ST7920_SS1      4                  // ST7920 SS1
#define PIN_ENERGY_COUNT    5                  // Нога на которую заводится сигнал от электросчетчика (подсчет импульсов) используется аппаратный счетчик импульсов
#define PIN_ONE_WIRE_BUS    6                  // DS18b20 Нога на которой весят датчики температуры
#define PIN_ST7920_MOSI     7                  // ST7920 MOSI
#define PIN_ST7920_SCK      8                  // ST7920 SCK
// Беспроодный модуль NRF24L
#define PIN_SPI_CSN         9                  // NRF24L нога CSN выбор режима приема/передача
// Используем аппаратный SPI UNO
#define PIN_SPI_CE          10                 // NRF24L SPI сигнал SS1  – Slave-select 1 LCD
#define PIN_SPI_MOSI        11                 // NRF24L SPI сигнал MOSI – Master-out, Slave-in
#define PIN_SPI_MISO        12                 // NRF24L SPI сигнал MISO – Master-in, Slave out.
#define PIN_SPI_SCK         13                 // NRF24L SPI сигнал SCK  – Serial clock

// АНАЛОГОВЫЕ ноги
#define PIN_ANALOG_I        0                  // Нога на которую заводится ток от датчика (трансформатор тока)
#define PIN_ANALOG_V        1                  // Нога на которую заводится напряжение от датчика (220в)
#define PIN_KEY             16                 // Pin 16 = Analog in 2 Нога куда прицеплена кнопка 
#define PIN_LED_FLOW        17                 // Pin 17 = Analog in 3 Нога куда прицеплено реле потока (если замкнуто то поток есть) - светодиод и реле к ТП 1-2

#define READVCC_CALIBRATION_CONST 1103702L     // Калибровка встроенного АЦП (встроенный ИОН) по умолчанию 1126400 дальше измеряем питание и смотрим на дисплей 1103782L
#define NUM_SCREEN                5            // Число основных экранов
#define CALIBRATION_CONST_220     147.13       // Калибровка датчика напряжения 220 В 
#define CALIBRATION_CONST_220_I   10.03        // Калибровка датчика тока 220 A
#define EE_SAVED_ADDRESS          100          // Адрес записи данных eeprom
#define TIME_WRITE_EEPROM         60           // Период сохранения в eeprom МИНУТЫ!!!
#define eCONST                    1000         // Число импульсов на киловат/час электросчетчика

// Дополнительные библиотеки
#include <OneWire.h>           // OneWire библиотека
#include <leOS2.h>             // Шедуллер задач
#include "U8glib.h"            // Экран ЖКИ 128х64 по SPI
#include "rusFont.h"	       // Ресурс дополнительных фонтов
#include "BitMap.h"	       // Ресурс картинки для вывода на дисплей
#include "emonLib.h"           // Монитор электроэнергии
#include <avr/pgmspace.h>      // библиотека для использования  PROGMEM и F  - строковые константы в rom


 // Радио модуль NRF42l
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
    struct type_packet_NRF24               // Структура передаваемого пакета 32 байта - это максимум
    {
        int id=1;                          // Идентификатор устройства
        int tOut1=-5000,tIn1=-5000;        // Текущие температуры ТП в сотых градуса !!! место экономим
        int PowerFloor=0;                  // Мощность теплого пола  вт
        int tOut2=-5000,tIn2=-5000;        // Текущие температуры ГК в сотых градуса !!! место экономим
        int PowerLand=0;                   // Мощность теплого пола  вт
        int I,U,P;                         // Ток в сотых ампера, напряжение в сотых вольта, мощность в вт.
        char note[12] = "Arduino UNO";     // Примечание не более 11 байт + 0
    };

#ifdef  RADIO    // Радио модуль NRF24
    const unsigned int  Time_RF24_send=5000; // Длительность цикла посылки данных на сервер через радиомодуль (примерно- точность определяется стороживым таймером)
    type_packet_NRF24 packet;                 // пакет данных
    RF24 radio(PIN_SPI_CE,PIN_SPI_CSN);       // Создание структуры 
    const uint64_t pipes[2] = {0xF0F0F0F0E1LL,0xF0F0F0F0D2LL};
    bool send_packet_ok=false;                // признак удачной отправки последнего пакета 
#endif 

// ----------------------------------------------------------------------  
boolean indicator = true;                   // Индикатор потока на дисплее - переменная для его анимации.
int fStart = 0;                             // Какой текущий экран вывода 0-стартовый
volatile byte ScreenResetCount=0;           // Для корректной работы экрана сброса кнопка должна быть нажата а затем отжата
volatile byte count=0;                      // Счетчик времени для записи в eeprom в минутах

const int  TimeMeasurement=9715;            // Длительность цикла измерения мсек  !! неточно дискретность 16 мксек
const int  TimeInterview=150;               // Длительность цикла опроса кнопок мсек
const unsigned int  TimeOneMinutes=58270;   // Длительность минутного цикла 65000 (unsigned int) 59100
const int  TEMPERATURE_PRECISION =12;       // разрешение датчика темературы в битах 9-12 бит
const float calibrationFactor = 0.435;      // Калибровочный коэфициент датчика потока 2-0.439 3-431
const float heat_capacity=4.191;            // Теплоемкость теплоносителя (вода 4.191)
 
volatile unsigned long oldTime=0;           // переменная для расчета interval
volatile long interval;                     // реальный интервал измерения (чуть больше TimeMeasurement особенность leOS2)
volatile long ChartInterval;                // реальный интервал вывода графика (чуть больше TimeChart особенность leOS2)
volatile unsigned long ChartOldTime=0;      // переменная для расчета ChartInterval
char buf[15];                               // буфер для вывода чисел на экран
byte oldKey=0;                              // Предыдущее знаение клавиши 
byte flagKey=1;                             // Флаг нажатия клавиши

// Электросчетчик -----------------------------
volatile unsigned long eCount=0;             // Счетчик импульсов от электросчетчика
volatile float ePower=0;                     // Пиковая мощность за TimeMeasurement
volatile float eEnergy=0;                    // Потребленная энергия
byte pChart[60];                             // Данные графика потеблемой мощности (датчики ток и напряжение)
byte ChartCOP[60];                           // Данные графика COP
volatile float pPower=0;                     // Пиковая мощность за TimeMeasurement
volatile float pEnergy=0;                    // Потребленная энергия

// Первый канал Теплые полы -------------------------------
const float errOut1=0.05;                    // Ошибка первого датчика - вычитается из показаний 0.05
const float errIn1=0.07;                     // Ошибка второго датчика - вычитается из показаний 0.17
byte ThermOut1[8] = {0x28,0xFF,0x37,0x7F,0x4A,0x04,0x00,0xCF};  // ТП обратка адрес датчика DS18B20 28FF377F4A0400CF закругленный конец 
byte ThermIn1 [8] = {0x28,0xBC,0x6B,0x3D,0x06,0x00,0x00,0x01};  // ТП подача адрес датчика DS18B20 28BC6B3D06000001 прямой конец  синий кембрик
volatile unsigned int pulseCount1=0;         // Счетчик импульсов первого датчика
volatile float flowRate1=0.0;                // Поток литров в минуту измеряется раз в минуту
volatile float totalLitres1=0.0;             // Общий объем прошедшей житкости в литрах Пишется во флеш каждый час
volatile float totalPower1=0.0;              // Общий объем тепла
volatile unsigned int count1 = 0;            // Число импульсов от датчика полученное за интервал измерения
volatile float HZ1=0.0;                      // Частота           
volatile float P1=0.0;                       // Мощность за секунду ТП
volatile float tOut1=-50,tIn1=-50;           // текущие температуры,
byte Chart1[60];                             // Данные первого графика (ТП)

// Второй канал Геоконтур ---------------------------
const float errOut2=0.17;                    // Ошибка первого датчика - вычитается из показаний
const float errIn2=0.17;                     // Ошибка второго датчика - вычитается из показаний
//byte ThermOut2 [8]= {0x28,0x34,0x70,0x2b,0x06,0x00,0x00,0x77};  // ТП обратка адрес датчика DS18B20 28FF377F4A0400CF закругленный конец 
// byte ThermIn2 [8] = {0x28,0x63,0x87,0x2b,0x06,0x00,0x00,0x2b};  // ТП подача адрес датчика DS18B20 28BC6B3D06000001 прямой конец
byte ThermOut2 [8]= {0x28,0x63,0x87,0x2b,0x06,0x00,0x00,0x2b};  // ТП обратка адрес датчика DS18B20 метка синия 
byte ThermIn2 [8] = {0x28,0x34,0x70,0x2b,0x06,0x00,0x00,0x77};  // ТП подача адрес датчика DS18B20 метка красная
volatile unsigned int pulseCount2=0;         // Счетчик импульсов первого датчика
volatile float flowRate2=0.0;                // Поток литров в минуту измеряется раз в минуту
volatile float totalLitres2=0.0;             // Общий объем прошедшей житкости в литрах Пишется во флеш каждый час
volatile float totalPower2=0.0;              // Общий объем тепла
volatile unsigned int count2 = 0;            // Число импульсов от датчика полученное за интервал измерения
volatile float HZ2=0.0;                      // Частота           
volatile float P2=0.0;                       // Мощность за секунду 
volatile float tOut2=-50,tIn2=-50;           // текущие температуры
byte Chart2[60];                             // Данные второго графика (ГК)

// Структура для записи в EEPROM
struct type_Counts                            // Тип данных - счетчики
{
    float GlobalEnergyP;                          //  Потребленная энергия с момента старта ТН - не сбрасывается ДАТЧИКИ ТОК И НАПРЯЖЕНИЕ в КИЛОВАТАХ
    float GlobalEnergyG;                          //  Выработанная энергия с момента старта ТН - не сбрасывается ДАТЧИКИ ТОК И НАПРЯЖЕНИЕ в КИЛОВАТАХ
    float YearEnergyP;                            //  Потребленная энергия с начала сезона отопления ТН - сбрасывается в КИЛОВАТАХ
    float YearEnergyG;                            //  Выработанная энергия с начала сезона отопления ТН - сбрасывается в КИЛОВАТАХ
    unsigned long GlobalHour;                     //  Мото часы (секунды) общие с момента старта ТН - не сбрасывается В СЕКУНДАХ
    unsigned long YearHour;                       //  Мото часы (секунды) общие с начала сезона отопления ТН - сбрасывается В СЕКУНДАХ
    unsigned long GlobalCountE;                   //  Потребленная энергия с момента старта ТН - не сбрасывается ЭЛЕКТРОСЧЕТЧИК  В ИМПУЛЬСАХ
    unsigned long YearCountE;                     //  Потребленная энергия с начала сезона отопления ТН - сбрасывается ЭЛЕКТРОСЧЕТЧИК В ИМПУЛЬСАХ
    float GlobalEnergyGeo;                        //  Потребленная энергия из геоконтура с момента старта ТН - не сбрасывается в КИЛОВАТАХ
    float YearEnergyGeo;                          //  Потребленная энергия из геоконтура с момента старта ТН - сбрасывается в КИЛОВАТАХ
}; 
volatile type_Counts CountsSRAM;                   // Рабочая копия счетчиков в памяти
type_Counts CountsEEPROM EEMEM;                    // Копия счетчиков в eeprom - туда пишем

volatile float EnergyP=0,EnergyG=0,EnergyGeo=0;    // промежуточные переменные
volatile unsigned long CountE=0;

// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ БИБЛИОТЕК
//U8GLIB_ST7920_128X64_4X u8g(PIN_SPI_SS1);          // Используем аппартный SPI но память минус 370 байт (увеличенный буфер на 4)скорость увеличивается где то на 100%
U8GLIB_ST7920_128X64_4X u8g(PIN_ST7920_SCK, PIN_ST7920_MOSI, PIN_ST7920_SS1, U8G_PIN_NONE); // Программный SPI и 4х буффер для скорости

leOS2 myOS;                                        // многозадачность
OneWire ds(PIN_ONE_WIRE_BUS);                      // поддержка температурных датчиков
EnergyMonitor emon1;                               // Мониторинг электросети

void setup(void) {
  u8g.setFont(my5x7rus);                // Русский шрифт 5х7
  // Установка входов-выходов и подтягивание внутренними резисторами
  pinMode(PIN_LED_FLOW, OUTPUT);        // Индикация потока светодиод и реле
  digitalWrite(PIN_LED_FLOW, HIGH);  
  pinMode(PIN_FLOW1, INPUT);            //  Подключение датчика потока 1
  digitalWrite(PIN_FLOW1, HIGH);
  pinMode(PIN_FLOW2, INPUT);            //  Подключение датчика потока 2
  digitalWrite(PIN_FLOW2, HIGH);
  pinMode(PIN_KEY, INPUT);              //  Включена кнопка
  digitalWrite(PIN_KEY, HIGH);
  pinMode(PIN_ENERGY_COUNT, INPUT);     //  Электросчетчик
  digitalWrite(PIN_ENERGY_COUNT, HIGH); 
 
 #ifdef  RADIO    // Радио модуль NRF42l  определение управляющих ног
    pinMode( PIN_SPI_CSN, OUTPUT);          
    digitalWrite( PIN_SPI_CSN, HIGH);
    pinMode( PIN_SPI_CE, OUTPUT);           
    digitalWrite(PIN_SPI_CE, HIGH);
 #endif 

  // Установка начальных переменных
  interval=TimeMeasurement;
  ChartInterval=TimeOneMinutes;  
  attachInterrupt(sensorInterrupt1, pulseCounter1, CHANGE);  // Прерывания на ОБА ФРОНТА
  attachInterrupt(sensorInterrupt2, pulseCounter2, CHANGE);
  
  myOS.begin();
  myOS.addTask(measurement,myOS.convertMs(TimeMeasurement));
  myOS.addTask(OneMinutes,myOS.convertMs(TimeOneMinutes));
     
// Программирование 1 таймера на подсчет событий на PIN_ENERGY_COUNT (туда заводится электросчетчик)
  TCCR1A = 0;   // сброс Timer 1 
  TCCR1B = 0; 
  TCNT1  = 0;  
  // start Timer 1 External clock source on T1 pin (D5). Clock on rising edge.
  TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12);
  
  emon1.voltage(PIN_ANALOG_V, CALIBRATION_CONST_220,1.7);  // Инициализация датчика напряжения 220
  emon1.current(PIN_ANALOG_I, CALIBRATION_CONST_220_I);    // Инициализация датчика тока 220
  
  // проверка на запуск экрана сброса
 if ((digitalRead(PIN_KEY)==0)&&(digitalRead(PIN_KEY)==0)) fStart=-1; // Установка признака стартового экрана
  // Чтение счетчиков из флеша
  //  AllResetEeprom(); // обнуление всех счетчиков только один раз в момент пуска системы
  readEeprom();
 
  #ifdef  RADIO    // Радио модуль NRF24
      //---ИНИЦИАЛИЗАЦИЯ РАДИО МОДУЛЯ ------------------------------------- 
      radio.begin();
    // выбор скорости
      radio.setDataRate(RF24_250KBPS);
    //  radio.setDataRate(RF24_1MBPS);
    //  radio.setDataRate(RF24_2MBPS);
    radio.setPALevel(RF24_PA_MAX); // Максимальная мощность
    radio.setChannel(100);         //тут установка канала
    radio.setCRCLength(RF24_CRC_16);
    // radio.setAutoAck(false); // выключить аппаратное потверждение
    radio.setRetries(15,15);    // Задержка и число повторов
    radio.openWritingPipe(pipes[1]);   // Открываем канал передачи
    radio.openReadingPipe(1,pipes[0]); // Открываем канал приема  для получения подтверждения доставки пакета
    myOS.addTask(send_packet,myOS.convertMs(Time_RF24_send));  // Создание задачи по отправке пакетов
 #endif 
   }

// --------------------------------------------- LOOP ------------------------------------	 
void loop(void) {
  float t;
    // Старт преобразования датчиков время занимает до 0.7 секунды!!!!
    StartDS1820(ThermOut1);
    StartDS1820(ThermIn1);
    StartDS1820(ThermOut2);
    StartDS1820(ThermIn2);
    indicator=!indicator;   
 
    u8g.firstPage(); 
     do {
       // Общая часть для каждого экрана (для экономии длины кода) - заголовок экрана
       if (fStart>0)
        { 
          u8g.drawBox(0,0,128,9);  // Закрашиваем прямоугольник белым 
          u8g.setColorIndex(0);    // Черные чернила, Белый  фон
          u8g.setPrintPos(1, 7);
          u8g.print(int(fStart));
          u8g.drawLine(118, 0, 118, 8);  // Индикатор потока на экран и на реле
          if ((flowRate1>0)&&(flowRate2>0)) {digitalWrite(PIN_LED_FLOW, HIGH); 
            if (indicator==true) u8g.drawStr(121, 7,F("/")); else u8g.drawStr(121, 7,F("\\")); }// Светодиод и реле показывает что поток есть реле идет к ТН (1-2)
          else {digitalWrite(PIN_LED_FLOW, LOW); u8g.drawStr(121, 7,F("-"));}
          u8g.drawLine(98, 0, 98, 8);  // Индикатор потока на экран и на реле
          u8g.setPrintPos(100, 7);
          u8g.print(dtostrf(emon1.Vrms,3,0,buf)); // Вывод напряжения в строке состояния
            #ifdef  RADIO    // Радио модуль NRF42l ИНДИКАТОР ПЕРЕДАЧИ последнего пакета
                if (send_packet_ok==true)  u8g.drawXBMP(92, 1, 5, 7, antenna); else u8g.drawStr(92, 7,F("_"));
            #else
                u8g.drawStr(92, 7,F("-")); // радиомодуля нет выводим прочерк
            #endif 
           u8g.setPrintPos(8, 7);   // Далее сразу можно печатать заголовок
        }
       switch (fStart)
        {
        case -1:  ScreenReset(); break;  
        case  0:  ScreenStart(); break;
        case  1:  Screen1(); break;
        case  2:  Screen2(); break;
        case  3:  Screen3(); break;
        case  4:  Screen4(); break;
        case  5:  Screen5(); break;
        default:  Screen1();
        }
    
       } while( u8g.nextPage() );
       
       if (fStart==0) // Только один раз
         { delay(3000); myOS.addTask(scanKey,myOS.convertMs(TimeInterview)); } // Клавиатура активируется, начинается сканирование
        
       if (count>=TIME_WRITE_EEPROM) {writeEeprom();count=0;}  // Запись eeprom
       
        emon1.calcVI(40,2000);  // чтение датчиков тока и напряжения
   
        if (fStart>0 && myOS.getTaskStatus(scanKey)==0) myOS.restartTask(scanKey); //Борьба с зависаниями при переключении от кнопки - включение сканирования
        
        delay(350); 
        tOut1=VerificationTemp(tOut1,errOut1,ThermOut1);
        tIn1=VerificationTemp(tIn1,errIn1,ThermIn1);
        tOut2=VerificationTemp(tOut2,errOut2,ThermOut2);
        tIn2=VerificationTemp(tIn2,errIn2,ThermIn2);
  	}
     
   
float VerificationTemp(float newT,float errT, unsigned char *adrr)
{
 float t=getTempDS1820(adrr);
 if ((t>-15&&t<70&&abs(newT-t)<5)||(newT<-20)) t=t-errT;   // Иногда считывает глюки 
 return t;
} 
     
// Экран сброса настроек сезона --------------------------------------
void ScreenReset()
 {
  u8g.drawBox(0,0,128,9);  // Закрашиваем прямоугольник белым 
  u8g.setColorIndex(0);    // Черные чернила, Белый  фон
  u8g.drawStr(1, 7 , F("Сброс счетчиков сезона"));
  u8g.setColorIndex(1);
   
  u8g.drawStr(0, 16 , F("Выработка G кВт"));
  u8g.setPrintPos(84, 16);
  u8g.print(long(CountsSRAM.YearEnergyG));
    
  u8g.drawStr(0, 24 , F("Потреб. P кВт"));
  u8g.setPrintPos(84, 24);
  u8g.print(long(CountsSRAM.YearEnergyP));
   
  u8g.drawStr(0, 32 , F("Потреб. E кВт"));
  u8g.setPrintPos(84, 32);
  u8g.print(long(CountsSRAM.YearCountE/eCONST));  // импульсы в кВт
 
  u8g.drawStr(0, 40 , F("Наработка Часы"));
  u8g.setPrintPos(84, 40);
  u8g.print((unsigned int)(CountsSRAM.YearHour/60.0/60.0));
  
  u8g.drawLine(0, 46, 127, 46); 
  u8g.drawStr(0, 54 , F("СБРОС -  нажатие кнопки"));
  u8g.drawStr(0, 62 , F("ОТМЕНА - выключение"));
 
 // Опрос кнопки Сначало надо кнопку отпустить а потом нажимать
 if ((digitalRead(PIN_KEY)==1)&&(digitalRead(PIN_KEY)==1))  ScreenResetCount=1;   // кнопку отжали экран появился
 if ((digitalRead(PIN_KEY)==0)&&(digitalRead(PIN_KEY)==0)&&(ScreenResetCount==1)) // кнопку нажали и надо сбрасывать, простейшее подавление дребезка
 { fStart=1;  YearResetEeprom(); myOS.addTask(scanKey,myOS.convertMs(TimeInterview));}
 }   
// Стартовый экран --------------------------------------
void ScreenStart()
{
 u8g.setColorIndex(1);
 u8g.drawXBMP(0, 0, 56, 56, u8g_logo_bits); 
// u8g.drawXBMP(0, 0, 51, 51, aLogo); 
 u8g.drawStr(73, 8,  F("Контроль"));
 u8g.drawStr(70, 16, F("Теплового"));
 u8g.drawStr(78, 24, F("Насоса"));
 u8g.drawStr(66, 32, F("Arduino UNO"));
 #ifdef  RADIO    // Радио модуль NRF24
    u8g.drawStr(58, 41, F("Радио NRF24L"));
 #endif
 #ifdef  DEMO    // Демка
    u8g.drawStr(68, 52, F("-- DEMO --"));
 #endif
 u8g.drawStr(1, 63,F(VERSION));
}

// Отображение типа 1 ТЕПЛЫЙ ПОЛ-------------------------------------
void Screen1()
{
  byte i;
  u8g.print(F("Теплые Полы")); 
  u8g.setColorIndex(1);    // белые чернила, черный фон
  Screen12();
  u8g.setPrintPos(32, 16);
  u8g.print(dtostrf(flowRate1*60.0/1000.0,4, 3, buf));
  u8g.setPrintPos(95, 16);
  u8g.print(HZ1); 
  u8g.setPrintPos(8+14, 26); // Подача
  u8g.print(dtostrf(tOut1,4, 2, buf)); 
  u8g.setPrintPos(8+14, 26+9); // Обратка
  u8g.print(dtostrf(tIn1,4, 2, buf)); 
 
//  if (tOut1-tIn1<0) u8g.setPrintPos(8+13, 26+18); // Разность температур
//  else  u8g.setPrintPos(8+14+6, 26+9+9); 
   u8g.setPrintPos(8+14, 26+9+9);
  u8g.print(dtostrf(abs(tOut1-tIn1),4, 2, buf));  // Всегда больше нуля

  u8g.drawBox(64,19,64,9);  // Закрашиваем прямоугольник белым 
  u8g.setColorIndex(0);     // Черные чернила, Белый  фон
  u8g.drawStr(111, 26, F("кВт"));
  u8g.setPrintPos(86, 26);
  u8g.print(dtostrf(P1,4, 2, buf));
  if (tOut1>tIn1) u8g.drawStr(64, 26, F("Наг."));  // Показ режима работы теплового насоса
  else            u8g.drawStr(64, 26, F("Охл."));
  
  u8g.setColorIndex(1);    
  u8g.setPrintPos(12, 54);
  u8g.print(dtostrf(totalLitres1/60.0/1000.0,11, 2, buf)); 
  u8g.setPrintPos(12, 63);
  u8g.print(dtostrf(totalPower1,11, 2, buf)); 
  
  // График
  // for(i=0;i<60;i++) u8g.drawPixel(65+i,63-Chart1[i]);     // Точки
  for(i=0;i<60;i++) u8g.drawLine(65+i,64,65+i,64-Chart1[i]); // Линия 0 не выводится
}
// Общие процедуры для первого и второго экранов - экономим rom --------------------------------
void Screen12()
{
  u8g.drawStr(0, 16, F("Поток:         Част:"));
  u8g.drawXBMP(58, 10, 9, 7, cub);
  u8g.drawXBMP(120, 10, 8, 7, Hz);
  u8g.drawLine(0, 18, 127, 18); 
  u8g.drawXBMP(0, 20, 21, 25, T123); // Термометр и значки
  u8g.drawXBMP(8+45, 26-6, 9, 7, C0);
  u8g.drawXBMP(8+45, 26-6+9, 9, 7, C0);
  u8g.drawXBMP(8+45, 26-6+9+9, 9, 7, C0);
  u8g.drawLine(63, 18, 63, 63); 
  u8g.drawLine(0, 46, 63, 46);
  u8g.drawStr(0, 54, F("V:"));
  u8g.drawStr(0, 63, F("G:"));
} 

// Отображение типа 2 ГЕО КОНТУР-------------------------------------
void Screen2()
{
  byte i;
  u8g.print(F("Гео контур")); 
  u8g.setColorIndex(1);    // белые чернила, черный фон
  Screen12();
  u8g.setPrintPos(32, 16);
  u8g.print(dtostrf(flowRate2*60.0/1000.0,4, 3, buf));
  u8g.setPrintPos(95, 16);
  u8g.print(HZ2); 
  u8g.setPrintPos(8+14, 26); // Подача
  u8g.print(dtostrf(tOut2,4, 2, buf)); 
  
  u8g.setPrintPos(8+14, 26+9); // Обратка
  u8g.print(dtostrf(tIn2,4, 2, buf)); 
 
 // if (tOut2-tIn2<0) u8g.setPrintPos(8+13, 26+9+9); // Разность температур
//  else  u8g.setPrintPos(8+14+6, 26+9+9); 
  u8g.setPrintPos(8+14, 26+9+9);
  u8g.print(dtostrf(abs(tOut2-tIn2),4, 2, buf)); 
  
  u8g.drawBox(64,19,64,9);  // Закрашиваем прямоугольник белым 
  u8g.setColorIndex(0);     // Черные чернила, Белый  фон
  u8g.drawStr(111, 26, F("кВт"));
  u8g.setPrintPos(86, 26);
  u8g.print(dtostrf(P2,4, 2, buf));
  if (tOut2>tIn2) u8g.drawStr(64, 26, F("Наг."));  // Показ режима работы теплового насоса
  else            u8g.drawStr(64, 26, F("Охл."));
  
  
//  u8g.drawLine(63, 18, 63, 63); 
 
//  u8g.drawBox(64,19,63,9);  // Закрашиваем прямоугольник белым 
//  u8g.setColorIndex(0);     // Черные чернила, Белый  фон
//  u8g.drawStr(107, 26, F("кВт"));
//  u8g.setPrintPos(80, 26);
//  u8g.print(dtostrf(P2,4, 2, buf));
  u8g.setColorIndex(1);    
  
  u8g.setPrintPos(12, 54);
  u8g.print(dtostrf(totalLitres2/60.0/1000.0,11, 2, buf)); 
  u8g.setPrintPos(12, 63);
  u8g.print(dtostrf(totalPower2,11, 2, buf));
   // График
  // for(i=0;i<60;i++) u8g.drawPixel(65+i,63-Chart2[i]); 
  for(i=0;i<60;i++) u8g.drawLine(65+i,64,65+i,64-Chart2[i]); // 0 не выводится
   
}

// Отображение типа 3  Напряжение Ток-------------------------------------
void Screen3()
{
  int i;
  u8g.print(F("Напряжение&Ток"));
  u8g.setColorIndex(1);    // белые чернила, черный фон
  u8g.drawStr(0, 16, F("V rms:"));
  
  u8g.setPrintPos(31, 16);
  u8g.print(dtostrf(emon1.Vrms,4,1,buf));
  u8g.drawStr(0, 24, F("I rms:"));
  u8g.setPrintPos(31, 24);
  u8g.print(dtostrf(emon1.Irms,4,1,buf));
  u8g.drawStr(65, 16, F("Pow_f:"));
  u8g.setPrintPos(102, 16);
  u8g.print(dtostrf(emon1.powerFactor,3,2,buf));
  u8g.drawStr(0, 34, F("PW кВт:"));
  u8g.setPrintPos(39,34);
  u8g.print(dtostrf(abs(pPower),4, 2, buf));
  u8g.drawStr(75, 26, F("COP:"));
  u8g.setPrintPos(98, 26);
  if (pPower>0.500) u8g.print(dtostrf(P1/pPower,3,2,buf)); else u8g.print(dtostrf(0.0,3,2,buf));
  u8g.drawLine(63, 18, 63, 63); 
  u8g.drawLine(0, 26, 63, 26);
  u8g.drawLine(64, 18, 127, 18);
  
  //  for(i=0;i<=6;i++) u8g.drawPixel(62,64-i*4);  // Шкала мощность
  for(i=0;i<=5;i++)
  { u8g.drawPixel(64,64-i*7);   // Шкала СОР
    u8g.drawPixel(65,64-i*7);
  }
 
 for(i=0;i<60;i++) // График
    { 
     u8g.drawLine(i,64,i,64-pChart[i]);   
     u8g.drawLine(67+i,64,67+i,64-ChartCOP[i]); 
    }
}

// Отображение типа 4  Счетчики -------------------------------------
void Screen4()
{
  float temp;
  u8g.print(F("Счетчики")); 
  u8g.setColorIndex(1);    // белые чернила, черный фон
  
  u8g.drawLine(28, 9, 28, 63);
  u8g.drawLine(79, 9, 79, 63);
  u8g.drawLine(0, 43, 127, 43);
  u8g.drawStr(0, 16, F("        За сезон   Общий"));
  
  u8g.drawStr(0, 24, F("G кВт"));
  u8g.setPrintPos(31, 24);
  u8g.print(long(CountsSRAM.YearEnergyG));
  u8g.setPrintPos(82, 24);
  u8g.print(long(CountsSRAM.GlobalEnergyG));
  
  u8g.drawStr(0, 32, F("P кВт"));
  u8g.setPrintPos(31, 32);
  u8g.print(long(CountsSRAM.YearEnergyP));
  u8g.setPrintPos(82, 32);
  u8g.print(long(CountsSRAM.GlobalEnergyP));
  
  u8g.drawStr(0, 40, F("E кВт"));
  u8g.setPrintPos(31, 40);
  u8g.print(long(CountsSRAM.YearCountE/eCONST));  // импульсы в кВт
  u8g.setPrintPos(82, 40);
  u8g.print(long(CountsSRAM.GlobalCountE/eCONST)); // импульсы в кВт
  
  u8g.drawStr(0, 51, F("COP"));
  u8g.setPrintPos(30, 51);
  u8g.print(dtostrf((float)CountsSRAM.YearEnergyG/(float)CountsSRAM.YearEnergyP,4,2, buf));
  u8g.setPrintPos(81, 51);
  u8g.print(dtostrf((float)CountsSRAM.GlobalEnergyG/(float)CountsSRAM.GlobalEnergyP,4,2, buf));
  
  u8g.drawStr(30+22, 51, F(":"));
  u8g.drawStr(81+22, 51, F(":"));

  u8g.setPrintPos(30+26, 51);
  temp=(float)CountsSRAM.YearEnergyG/((float)CountsSRAM.YearCountE/(float)eCONST);
  if (temp<10.0) u8g.print(dtostrf(temp,4,2, buf));
      else u8g.print(F("-.-"));
  u8g.setPrintPos(81+26, 51);
  temp=(float)CountsSRAM.GlobalEnergyG/((float)CountsSRAM.GlobalCountE/(float)eCONST);
  if (temp<10.0) u8g.print(dtostrf(temp,4,2, buf));
      else u8g.print(F("-.-"));
  
  u8g.drawStr(0, 60, F("Часы"));
  u8g.setPrintPos(31, 60);
  u8g.print((unsigned int)(CountsSRAM.YearHour/60/60)); // Из секунд в часы
  u8g.setPrintPos(82, 60);
  u8g.print((unsigned int)(CountsSRAM.GlobalHour/60/60));
 }
 
// Отображение типа 5 Параметры  -------------------------------------
void Screen5()
{
  u8g.print(F("Параметры")); 
  u8g.setColorIndex(1);    // белые чернила, черный фон

  u8g.drawStr(0, 16, F("Питание UNO В"));
  u8g.setPrintPos(97, 16);
  u8g.print(dtostrf(emon1.readVcc()/1000.0,4, 3, buf));
    
  u8g.drawStr(0, 24, F("Температура чипа"));
  u8g.setPrintPos(97, 24);
  u8g.print(dtostrf(GetTemp(),4,2, buf));
  
  u8g.drawStr(0, 32, F("RAM free байт"));
  u8g.setPrintPos(97, 32);
  u8g.print(freeRam ()); 
  
  u8g.drawStr(0, 40, F("Таймера мс         :"));
  u8g.setPrintPos(65, 40);
  u8g.print(dtostrf(interval,5,0,buf));  
  u8g.setPrintPos(98, 40);
  u8g.print(dtostrf(ChartInterval,5,0,buf));  

  u8g.drawStr(0, 48, F("ТП err out/in"));
  u8g.setPrintPos(80, 48);
  u8g.print(dtostrf(errOut1,3, 2, buf));
  u8g.setPrintPos(108, 48);
  u8g.print(dtostrf(errIn1,3, 2, buf));
    
  u8g.drawStr(0, 56, F("Гео err out/in"));
  u8g.setPrintPos(80, 56);
  u8g.print(dtostrf(errOut2,3, 2, buf));
  u8g.setPrintPos(108, 56);
  u8g.print(dtostrf(errIn2,3, 2, buf));
  u8g.drawLine(103, 42, 103, 56); 
} 

// Прерывание подсчет импульсов от первого канала
void pulseCounter1() {   pulseCount1++; }
// Прерывание подсчет импульсов от второго канала
void pulseCounter2() {   pulseCount2++; }

// ОДНА СЕКУНДА Цикл измерения интервал задается -----------------------------------
void measurement()
{
 float intervalHour;           // интервал измерения в часах, используется для увеличения скорости
 cli();  // Запретить прерывания TimeMeasurement
 count1=pulseCount1;  pulseCount1 = 0;
 count2=pulseCount2;  pulseCount2 = 0;
 sei();  // разрешить прерывания
 
 interval=millis()-oldTime; // Точное определение интервала ----------------------------
 oldTime= interval+oldTime;  
 if (interval<=0) interval=TimeMeasurement; // Через 50 дней millis() сбросится по этому после этого первая итерация расчетная

 #ifdef  DEMO    // Демка
     count1=random(190,240); 
     count2=random(160,200);
     TCNT1= random(5,9);
     emon1.realPower=random(1900,2800);
 #endif

 intervalHour=((float)interval/1000.0)/3600.0;  // Предварительный расчет для оптимизации времени
 
 // Первый канал 
 HZ1=(float)(count1*1000.0)/interval/2; // делить на 2 - это т.к. прерывания работает на оба фронта импульса CHANGE
 flowRate1 = HZ1/calibrationFactor; // рассчитать поток в литрах за минуту
 totalLitres1 = totalLitres1 + flowRate1*(interval/1000.0); 
 P1=(flowRate1/60) // литры/килограммы в секунду
                   *heat_capacity*(abs(tOut1-tIn1)); 
 totalPower1 = totalPower1 + P1*intervalHour; 
 
 // Второй канал 
 HZ2=(float)(count2*1000.0)/interval/2; // делить на 2 - это т.к. прерывания работает на оба фронта импульса CHANGE
 flowRate2 = HZ2/calibrationFactor; // рассчитать поток в литрах за минуту
 totalLitres2 = totalLitres2 + flowRate2*(interval/1000.0); 
 P2=(flowRate2/60) // литры/килограммы в секунду
                   *heat_capacity*(abs(tOut2-tIn2)); 
 totalPower2 = totalPower2 + P2*intervalHour; 
 
 // Электросчетчик
 eCount=eCount+TCNT1;                                        // Общий счетчик
 ePower=(float)TCNT1*3600.0/(float)eCONST/(interval/1000.0); // Пиковый счетчик
 eEnergy=(float)eCount/(float)eCONST ;
 TCNT1 = 0;
 
 // Датчик напряжения и тока
 pPower=emon1.realPower/1000.0;         // Киловатты
 pEnergy=pEnergy+pPower*intervalHour;   // Потребленная энергия
 }

// Сканирование клавиш ------------------------------------------
void scanKey()
{
    byte key;  
    // cli();                                                         // Запретить прерывания TimeMeasurement
    key=digitalRead(PIN_KEY);                                         // Прочитать кнопку
    // sei();                                                         // разрешить прерывания
    if ((key==1)&&(oldKey==1)&&(flagKey==1)) {fStart++;flagKey=0;}    // Клавиша нажита
    if ((key==0)&&(oldKey==1))
        { flagKey=1;                           // Начало (по заднему фронту) ожидания нового нажатия 
         myOS.pauseTask(scanKey);              // Сканирование кнопки поставить на паузу, а то иногда висла задача
        }
    oldKey=key;
    if (fStart > NUM_SCREEN) fStart=1;
}

// РАЗ В МИНУТУ Подготовка массива точек для графиков и счетчиков ----------------------------------------
void OneMinutes()
{
 int i;
 float dP,dG,dGeo;
 unsigned long dE;
 
 count++;                                            // счетчик минут для записи eeprom
 
 ChartInterval=millis()-ChartOldTime;                // Точное определение интервала показа графика----------------------------
 ChartOldTime= ChartInterval+ChartOldTime;  
 if (ChartInterval<=0) ChartInterval=TimeMeasurement; // Через 50 дней millis() сбросится по этому после этого первая итерация расчетная
  // Сдвиг графиков и запись новых данных
  for(i=0;i<60;i++) 
     {  
      Chart1[i]=Chart1[i+1]; 
      Chart2[i]=Chart2[i+1];
      pChart[i]=pChart[i+1];
      ChartCOP[i]=ChartCOP[i+1];
     }
    Chart1[59]=P1*2.5;
    Chart2[59]=P2*2.5;
    pChart[59]=9*pPower; 
    if (pPower>0.500) ChartCOP[59]=(P1/(pPower))*7.0; else ChartCOP[59]=0;
     
 // Подготовка  накопительныч счетчиков для записи в eeprom ----------------------------------------------------
 // работают только если есть поток т.е. ТН работает!!!!! простой не учитывается СПОРНО надо думать
 
 //  Электричество
 dP=pEnergy-EnergyP;                  // Прирост 
 EnergyP=pEnergy;                     // запоминание для нового цикла
 CountsSRAM.GlobalEnergyP =CountsSRAM.GlobalEnergyP+dP;
 CountsSRAM.YearEnergyP   =CountsSRAM.YearEnergyP+dP;

 // Тепло ТП
 dG= totalPower1-EnergyG; // Прирост за час
 EnergyG=totalPower1;      // запоминание для нового цикла
 CountsSRAM.GlobalEnergyG =CountsSRAM.GlobalEnergyG+dG;
 CountsSRAM.YearEnergyG   =CountsSRAM.YearEnergyG+dG;
 
 // Тепло ГЕО контур
 dGeo= totalPower2-EnergyGeo; // Прирост за час
 EnergyGeo=totalPower2;      // запоминание для нового цикла
 CountsSRAM.GlobalEnergyGeo =CountsSRAM.GlobalEnergyGeo+dGeo;
 CountsSRAM.YearEnergyGeo   =CountsSRAM.YearEnergyGeo+dGeo;
 
 // Мото часы В секундах!!!!!!!!!!!!
 CountsSRAM.GlobalHour=CountsSRAM.GlobalHour+ChartInterval/1000; // в секундах
 CountsSRAM.YearHour=CountsSRAM.YearHour+ChartInterval/1000;     // в секундах
 
 // Электросчетчик
 dE=eCount-CountE;                   // Прирост электросчетчика
 CountE=eCount;                      // запоминание для нового цикла
 CountsSRAM.GlobalCountE =CountsSRAM.GlobalCountE+dE;
 CountsSRAM.YearCountE   =CountsSRAM.YearCountE+dE;
}

 // ---ПЕРЕДАЧА ДАННЫХ ЧЕРЕЗ РАДИОМОДУЛЬ -----------------------------
void send_packet()
{
#ifdef  RADIO    // Радио модуль NRF42l  
  packet.tOut1=100*tOut1;
  packet.tIn1=100*tIn1;
  packet.tOut2=100*tOut2;
  packet.tIn2=100*tIn2;
  packet.PowerFloor=P1*1000;
  packet.PowerLand=P2*1000;
  packet.I=emon1.Irms*100;
  packet.U=emon1.Vrms*100;
  packet.P=pPower*1000;
    myOS.pauseTask(send_packet);   // Остановить эту задачу а то при отсутствии связи идет сброс arduino
        radio.stopListening();     // Остановить приемник
    //    radio.flush_tx();          // Очистить буфер
        send_packet_ok = radio.write(&packet,sizeof(packet));
        radio.startListening();    // Включить приемник
    myOS.restartTask(send_packet); // Запустить задачу
  #endif  
 }  


// Старт преобразования одного датчика -----------------------------------------------
void StartDS1820(byte *addr)
{
   ds.reset();
   delay(10);
   ds.select(addr);
   delay(10);
   ds.write(0x44,0);
   delay(10);  
}
// Чтение температуры одного датчика -----------------------------------------------
float getTempDS1820(unsigned char *addr)
{
    byte i;
    byte type_s;
    byte present = 0;
    byte data[12];
    // Запрос уже послан ранее StartDS1820
    present = ds.reset();
    ds.select(addr);
    ds.write(0xBE); // Команда на чтение регистра температуры
    for ( i = 0; i < 9; i++) { data[i] = ds.read();}
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
     raw = raw << 3; // 9 bit resolution default
     if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;      // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  return (float)raw / 16.0;       
}

// Чтение внутреннего датчика температуры ---------------------------------------
double GetTemp(void)
{
  unsigned int wADC;
  double t;
  ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
  ADCSRA |= _BV(ADEN);  
  delay(20);           
  ADCSRA |= _BV(ADSC);  
  while (bit_is_set(ADCSRA,ADSC));
  wADC = ADCW;
  t = (wADC - 324.31 ) / 1.22;
  return (t); 
}
// Чтение свободной памяти --------------------------------------------------------------------
int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}
//----------------------------EEPROM FUNCTION--------------------------------------------------
void writeEeprom()
{ 
cli(); 
  eeprom_write_block((const void*)&CountsSRAM, (void*) &CountsEEPROM, sizeof(CountsSRAM)); 
sei();
}
// Полный сброс делается только один раз
void AllResetEeprom()
{
 CountsSRAM.GlobalEnergyP  =0;                       
 CountsSRAM.GlobalEnergyG  =0;                        
 CountsSRAM.YearEnergyP    =0;                          
 CountsSRAM.YearEnergyG    =0;                         
 CountsSRAM.GlobalHour     =0;                          
 CountsSRAM.YearHour       =0;  
 CountsSRAM.GlobalCountE   =0;                       
 CountsSRAM.YearCountE     =0;   
 CountsSRAM.GlobalEnergyGeo=0;
 CountsSRAM.YearEnergyGeo  =0;
 writeEeprom(); 
}
// Сброс только последнего сезона
void YearResetEeprom()
{
 CountsSRAM.YearEnergyP    =0;                          
 CountsSRAM.YearEnergyG    =0;                         
 CountsSRAM.YearHour       =0;  
 CountsSRAM.YearCountE     =0;   
 CountsSRAM.YearEnergyGeo  =0;
 writeEeprom(); 
}

//Чтение счетчиков из Eeprom 
void readEeprom()
{
cli(); 
   eeprom_read_block((void*)&CountsSRAM, (const void*) &CountsEEPROM, sizeof(CountsSRAM)); 
sei();
}

файл rusFont.h

// Русский шрифт 5х7 ------------------------------------------------------------
const u8g_fntpgm_uint8_t my5x7rus[2004] U8G_SECTION(".progmem.my5x7rus") = {
  0,6,6,0,255,7,1,147,3,35,32,255,255,6,255,7,
  255,0,0,0,4,0,0,1,7,7,2,0,255,128,128,128,
  128,128,0,128,3,3,3,4,0,3,160,160,160,5,7,7,
  6,0,255,80,80,248,80,248,80,80,5,7,7,6,0,255,
  32,120,160,112,40,240,32,5,7,7,6,0,255,192,200,16,
  32,64,152,24,5,7,7,6,0,255,96,144,160,64,168,144,
  104,2,3,3,3,0,3,192,64,128,3,7,7,4,0,255,
  32,64,128,128,128,64,32,3,7,7,4,0,255,128,64,32,
  32,32,64,128,5,5,5,6,0,0,80,32,248,32,80,5,
  5,5,6,0,0,32,32,248,32,32,2,3,3,3,0,255,
  192,64,128,5,1,1,6,0,2,248,2,2,2,3,0,255,
  192,192,5,5,5,6,0,0,8,16,32,64,128,5,7,7,
  6,0,255,112,136,152,168,200,136,112,3,7,7,4,0,255,
  64,192,64,64,64,64,224,5,7,7,6,0,255,112,136,8,
  16,32,64,248,5,7,7,6,0,255,248,16,32,16,8,136,
  112,5,7,7,6,0,255,16,48,80,144,248,16,16,5,7,
  7,6,0,255,248,128,240,8,8,136,112,5,7,7,6,0,
  255,48,64,128,240,136,136,112,5,7,7,6,0,255,248,8,
  16,32,64,64,64,5,7,7,6,0,255,112,136,136,112,136,
  136,112,5,7,7,6,0,255,112,136,136,120,8,16,96,2,
  5,5,3,0,0,192,192,0,192,192,2,6,6,3,0,0,
  192,192,0,192,64,128,4,7,7,5,0,255,16,32,64,128,
  64,32,16,5,3,3,6,0,1,248,0,248,4,7,7,5,
  0,255,128,64,32,16,32,64,128,5,7,7,6,0,255,112,
  136,8,16,32,0,32,5,7,7,6,0,255,112,136,8,104,
  168,168,112,5,7,7,6,0,255,112,136,136,136,248,136,136,
  5,7,7,6,0,255,240,136,136,240,136,136,240,5,7,7,
  6,0,255,112,136,128,128,128,136,112,5,7,7,6,0,255,
  224,144,136,136,136,144,224,5,7,7,6,0,255,248,128,128,
  240,128,128,248,5,7,7,6,0,255,248,128,128,224,128,128,
  128,5,7,7,6,0,255,112,136,128,128,152,136,112,5,7,
  7,6,0,255,136,136,136,248,136,136,136,3,7,7,4,0,
  255,224,64,64,64,64,64,224,5,7,7,6,0,255,56,16,
  16,16,16,144,96,5,7,7,6,0,255,136,144,160,192,160,
  144,136,5,7,7,6,0,255,128,128,128,128,128,128,248,5,
  7,7,6,0,255,136,216,168,136,136,136,136,5,7,7,6,
  0,255,136,136,200,168,152,136,136,5,7,7,6,0,255,112,
  136,136,136,136,136,112,5,7,7,6,0,255,240,136,136,240,
  128,128,128,5,7,7,6,0,255,112,136,136,136,168,144,104,
  5,7,7,6,0,255,240,136,136,240,160,144,136,5,7,7,
  6,0,255,120,128,128,112,8,8,240,5,7,7,6,0,255,
  248,32,32,32,32,32,32,5,7,7,6,0,255,136,136,136,
  136,136,136,112,5,7,7,6,0,255,136,136,136,136,136,80,
  32,5,7,7,6,0,255,136,136,136,168,168,216,136,5,7,
  7,6,0,255,136,136,80,32,80,136,136,5,7,7,6,0,
  255,136,136,80,32,32,32,32,5,7,7,6,0,255,248,8,
  16,32,64,128,248,3,7,7,4,0,255,224,128,128,128,128,
  128,224,5,5,5,6,0,0,128,64,32,16,8,3,7,7,
  4,0,255,224,32,32,32,32,32,224,5,3,3,6,0,3,
  32,80,136,5,1,1,6,0,255,248,3,3,3,4,0,3,
  128,64,32,5,5,5,6,0,255,112,8,120,136,120,5,7,
  7,6,0,255,128,128,176,200,136,136,240,5,5,5,6,0,
  255,112,128,128,136,112,5,7,7,6,0,255,8,8,104,152,
  136,136,120,5,5,5,6,0,255,112,136,248,128,112,5,7,
  7,6,0,255,48,72,64,224,64,64,64,5,5,5,6,0,
  255,120,136,120,8,48,5,7,7,6,0,255,128,128,176,200,
  136,136,136,3,7,7,4,0,255,64,0,192,64,64,64,224,
  4,7,7,5,0,255,16,0,48,16,16,144,96,4,7,7,
  5,0,255,128,128,144,160,192,160,144,3,7,7,4,0,255,
  192,64,64,64,64,64,224,5,5,5,6,0,255,208,168,168,
  136,136,5,5,5,6,0,255,176,200,136,136,136,5,5,5,
  6,0,255,112,136,136,136,112,5,5,5,6,0,255,240,136,
  240,128,128,5,5,5,6,0,255,104,152,120,8,8,5,5,
  5,6,0,255,176,200,128,128,128,5,5,5,6,0,255,112,
  128,112,8,240,5,7,7,6,0,255,64,64,224,64,64,72,
  48,5,5,5,6,0,255,136,136,136,152,104,5,5,5,6,
  0,255,136,136,136,80,32,5,5,5,6,0,255,136,136,168,
  168,80,5,5,5,6,0,255,136,80,32,80,136,5,5,5,
  6,0,255,136,136,120,8,112,5,5,5,6,0,255,248,16,
  32,64,248,3,7,7,4,0,255,32,64,64,128,64,64,32,
  1,7,7,2,0,255,128,128,128,128,128,128,128,3,7,7,
  4,0,255,128,64,64,32,64,64,128,5,5,5,6,0,0,
  32,16,248,16,32,5,5,5,6,0,0,32,64,248,64,32,
  5,5,5,6,0,255,240,136,240,128,128,5,5,5,6,0,
  255,112,128,128,136,112,5,5,5,6,0,255,248,32,32,32,
  32,5,5,5,6,0,255,136,136,120,8,112,5,5,5,6,
  0,255,32,112,168,168,112,5,5,5,6,0,255,136,80,32,
  80,136,5,5,5,6,0,255,136,136,136,136,248,5,5,5,
  6,0,255,136,136,120,8,8,5,5,5,6,0,255,168,168,
  168,168,248,5,5,5,6,0,255,168,168,168,168,248,5,5,
  5,6,0,255,192,64,112,72,112,5,5,5,6,0,255,136,
  136,232,152,232,4,5,5,5,0,255,128,128,224,144,224,5,
  5,5,6,0,255,112,136,56,136,112,5,5,5,6,0,255,
  144,168,232,168,144,5,5,5,6,0,255,120,136,120,40,72,
  5,7,7,6,0,255,112,136,136,136,248,136,136,5,7,7,
  6,0,255,248,136,128,240,136,136,240,5,7,7,6,0,255,
  240,136,136,240,136,136,240,5,7,7,6,0,255,248,136,128,
  128,128,128,128,5,7,7,6,0,255,120,40,40,40,72,136,
  248,5,7,7,6,0,255,248,128,128,240,128,128,248,5,7,
  7,6,0,255,168,168,168,112,168,168,168,5,7,7,6,0,
  255,240,8,8,112,8,8,240,5,7,7,6,0,255,136,136,
  152,168,200,136,136,5,7,7,6,0,255,80,32,136,152,168,
  200,136,5,7,7,6,0,255,136,144,160,192,160,144,136,5,
  7,7,6,0,255,120,40,40,40,40,168,72,5,7,7,6,
  0,255,136,216,168,168,136,136,136,5,7,7,6,0,255,136,
  136,136,248,136,136,136,5,7,7,6,0,255,112,136,136,136,
  136,136,112,5,7,7,6,0,255,248,136,136,136,136,136,136,
  5,7,7,6,0,255,240,136,136,240,128,128,128,5,7,7,
  6,0,255,112,136,128,128,128,136,112,5,7,7,6,0,255,
  248,32,32,32,32,32,32,5,7,7,6,0,255,136,136,136,
  80,32,64,128,5,7,7,6,0,255,32,112,168,168,168,112,
  32,5,7,7,6,0,255,136,136,80,32,80,136,136,5,7,
  7,6,0,255,136,136,136,136,136,136,248,5,7,7,6,0,
  255,136,136,136,120,8,8,8,5,7,7,6,0,255,168,168,
  168,168,168,168,248,5,7,7,6,0,255,168,168,168,168,168,
  168,248,5,7,7,6,0,255,192,64,64,112,72,72,112,5,
  7,7,6,0,255,136,136,136,200,168,168,200,4,7,7,5,
  0,255,128,128,128,224,144,144,224,5,7,7,6,0,255,112,
  136,8,56,8,136,112,5,7,7,6,0,255,144,168,168,232,
  168,168,144,5,7,7,6,0,255,120,136,136,120,40,72,136,
  5,5,5,6,0,255,112,8,120,136,120,5,7,7,6,0,
  255,24,96,128,240,136,136,112,4,5,5,5,0,255,224,144,
  224,144,224,5,5,5,6,0,255,248,136,128,128,128,5,5,
  5,6,0,255,120,40,72,136,248,5,5,5,6,0,255,112,
  136,248,128,112,5,5,5,6,0,255,168,168,112,168,168,5,
  5,5,6,0,255,240,8,48,8,240,5,5,5,6,0,255,
  136,152,168,200,136,5,7,7,6,0,255,80,32,136,136,152,
  168,200,4,5,5,5,0,255,144,160,192,160,144,5,5,5,
  6,0,255,120,40,40,168,72,5,5,5,6,0,255,136,216,
  168,136,136,5,5,5,6,0,255,136,136,248,136,136,5,5,
  5,6,0,255,112,136,136,136,112,5,5,5,6,0,255,248,
  136,136,136,136,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255};
// Русский шрифт 10х14 ------------------------------------------------------
const u8g_fntpgm_uint8_t my14x10rus[4157] U8G_SECTION(".progmem.my14x10") = {
  0,11,15,0,255,14,3,35,6,248,32,255,0,15,255,14,
  0,0,0,0,8,0,0,2,14,14,4,1,0,64,192,192,
  192,192,192,192,192,192,128,0,64,192,128,6,5,5,7,0,
  9,68,204,204,204,136,10,14,28,11,0,0,8,128,8,128,
  17,0,17,0,127,192,17,0,17,0,34,0,34,0,255,128,
  34,0,34,0,68,0,68,0,9,14,28,10,0,0,8,0,
  8,0,59,128,123,0,200,0,200,0,232,0,107,0,11,128,
  9,128,9,128,111,0,238,0,8,0,8,14,14,9,0,0,
  97,179,214,102,12,12,24,24,48,48,102,107,205,134,9,14,
  28,10,0,0,56,0,124,0,108,0,108,0,108,0,56,0,
  56,128,109,128,199,0,194,0,199,0,237,128,124,128,56,0,
  2,5,5,3,0,10,128,192,192,192,64,5,14,14,6,0,
  0,24,48,96,96,192,192,192,192,192,192,96,96,48,24,5,
  14,14,6,0,0,192,96,48,48,24,24,24,24,24,24,56,
  48,96,192,7,7,7,8,0,4,146,214,124,16,124,214,146,
  8,10,10,10,0,1,8,24,24,24,127,254,24,24,24,16,
  4,6,6,5,0,0,112,96,96,64,192,192,8,2,2,9,
  0,5,127,254,3,3,3,4,0,0,224,160,224,8,14,14,
  9,0,0,3,3,6,6,12,12,24,24,48,48,96,96,192,
  192,9,14,28,10,0,0,62,0,127,0,227,128,197,128,197,
  128,197,128,201,128,201,128,209,128,209,128,209,128,227,128,127,
  0,62,0,9,14,28,10,0,0,12,0,28,0,60,0,124,
  0,8,0,4,0,12,0,12,0,8,0,4,0,12,0,12,
  0,127,128,255,128,9,14,28,10,0,0,126,0,255,0,195,
  128,193,128,1,128,3,128,63,0,126,0,224,0,192,0,192,
  0,192,0,223,128,191,0,9,14,28,10,0,0,126,0,255,
  0,195,128,1,128,1,128,3,0,58,0,119,0,3,128,1,
  128,1,128,3,128,255,0,126,0,9,14,28,10,0,0,2,
  0,6,0,14,0,30,0,62,0,118,0,230,0,198,0,251,
  128,247,0,6,0,6,0,6,0,4,0,9,14,28,10,0,
  0,127,128,127,128,96,0,96,0,96,0,110,0,111,0,3,
  128,1,128,1,128,1,128,195,0,255,0,124,0,9,14,28,
  10,0,0,31,0,127,0,96,0,192,0,192,0,192,0,222,
  0,223,0,195,128,193,128,193,128,227,0,127,0,60,0,9,
  14,28,10,0,0,127,128,255,128,0,0,3,0,3,0,6,
  0,6,0,12,0,12,0,24,0,24,0,48,0,48,0,32,
  0,9,14,28,10,0,0,58,0,119,0,227,128,193,128,193,
  128,99,0,54,0,111,0,227,128,193,128,193,128,227,128,119,
  0,46,0,9,14,28,10,0,0,60,0,255,0,231,0,195,
  128,193,128,193,128,225,128,253,128,125,128,1,128,3,128,7,
  0,127,0,252,0,3,11,11,4,0,2,224,160,224,0,0,
  0,0,0,224,160,224,4,13,13,5,0,0,112,80,112,0,
  0,0,0,0,112,80,112,96,192,9,11,22,10,0,1,1,
  128,3,128,15,0,28,0,120,0,224,0,120,0,28,0,15,
  0,3,128,1,128,9,6,12,10,0,4,127,128,255,0,0,
  0,0,0,127,128,255,0,9,11,22,10,0,1,192,0,224,
  0,120,0,60,0,15,0,3,128,15,0,60,0,120,0,224,
  0,192,0,8,14,14,9,0,0,116,238,135,3,3,6,14,
  56,48,48,0,0,48,48,9,11,22,10,0,1,62,0,65,
  0,128,128,154,128,166,128,162,128,162,128,166,128,155,0,64,
  0,63,128,9,14,28,10,0,0,252,0,254,0,199,0,195,
  128,193,128,193,128,193,128,253,128,253,128,193,128,193,128,193,
  128,193,128,129,0,9,14,28,10,0,0,94,0,223,0,195,
  128,193,128,193,128,195,128,255,0,255,0,195,128,193,128,193,
  128,195,128,223,0,190,0,9,14,28,10,0,0,14,0,63,
  0,115,128,97,128,192,0,192,0,192,0,192,0,192,0,192,
  0,96,0,112,0,63,128,15,0,9,14,28,10,0,0,238,
  0,111,0,99,128,97,128,97,128,97,128,97,128,97,128,97,
  128,97,128,97,128,99,128,111,0,238,0,9,14,28,10,0,
  0,95,128,223,0,192,0,192,0,192,0,192,0,223,0,222,
  0,192,0,192,0,192,0,192,0,223,128,191,0,9,14,28,
  10,0,0,95,128,223,0,192,0,192,0,192,0,192,0,223,
  0,222,0,192,0,192,0,192,0,192,0,192,0,128,0,9,
  14,28,10,0,0,63,128,127,128,225,128,192,0,192,0,192,
  0,192,0,207,128,223,128,193,128,193,128,225,128,127,128,62,
  0,9,14,28,10,0,0,129,0,193,128,193,128,193,128,193,
  128,193,128,223,128,223,128,193,128,193,128,193,128,193,128,193,
  128,64,128,8,14,14,10,1,0,254,127,24,24,24,24,24,
  24,24,24,24,24,254,127,9,14,28,10,0,0,31,128,63,
  128,1,128,1,128,1,128,1,128,1,128,1,128,1,128,1,
  128,1,128,195,128,255,0,62,0,9,14,28,10,0,0,65,
  128,195,128,199,0,206,0,220,0,216,0,216,0,216,0,216,
  0,220,0,206,0,199,0,195,128,65,128,9,14,28,10,0,
  0,64,0,192,0,192,0,192,0,192,0,192,0,192,0,192,
  0,192,0,192,0,192,0,192,0,255,128,255,0,9,14,28,
  10,0,0,193,128,227,128,247,128,247,128,213,128,193,128,213,
  128,221,128,221,128,201,128,193,128,193,128,193,128,129,0,9,
  14,28,10,0,0,225,0,225,128,241,128,241,128,249,128,217,
  128,221,128,205,128,205,128,197,128,197,128,193,128,193,128,128,
  128,9,14,28,10,0,0,46,0,111,0,227,128,193,128,193,
  128,193,128,193,128,193,128,193,128,193,128,193,128,227,128,123,
  0,58,0,9,14,28,10,0,0,254,0,255,0,195,128,193,
  128,193,128,195,128,223,0,222,0,192,0,192,0,192,0,192,
  0,192,0,128,0,10,15,30,10,0,255,46,0,111,0,227,
  128,193,128,193,128,193,128,193,128,193,128,193,128,193,128,193,
  128,227,0,123,128,58,192,0,192,9,14,28,10,0,0,126,
  0,255,0,195,128,193,128,193,128,195,128,223,0,220,0,206,
  0,199,0,195,128,193,128,193,128,129,0,9,14,28,10,0,
  0,62,0,127,0,224,0,192,0,192,0,224,0,118,0,27,
  0,3,128,1,128,1,128,3,128,255,128,127,0,9,14,28,
  10,0,0,255,0,127,128,0,0,12,0,12,0,12,0,12,
  0,12,0,12,0,12,0,12,0,12,0,12,0,4,0,9,
  14,28,10,0,0,64,128,193,128,193,128,193,128,193,128,193,
  128,193,128,193,128,193,128,193,128,193,128,99,0,127,0,62,
  0,9,14,28,10,0,0,227,128,99,0,99,0,99,0,34,
  0,54,0,54,0,54,0,20,0,28,0,28,0,28,0,8,
  0,8,0,10,14,28,11,0,0,64,64,192,192,192,192,192,
  192,192,192,192,192,204,192,204,192,204,192,222,192,222,192,211,
  192,193,192,128,192,9,14,28,10,0,0,193,128,193,128,193,
  128,99,0,99,0,50,0,56,0,28,0,14,0,103,0,99,
  0,193,128,193,128,193,128,10,14,28,10,0,0,192,192,192,
  192,97,128,97,128,51,0,63,0,30,0,12,0,8,0,4,
  0,12,0,12,0,12,0,8,0,9,14,28,10,0,0,127,
  128,255,128,1,128,3,128,7,0,6,0,4,0,16,0,48,
  0,112,0,224,0,192,0,255,128,255,0,5,14,14,6,0,
  0,248,192,192,192,192,192,192,192,192,192,192,192,192,248,9,
  14,28,10,0,0,192,0,96,0,96,0,48,0,48,0,24,
  0,24,0,12,0,12,0,6,0,6,0,3,0,3,0,1,
  128,5,14,14,6,0,0,248,24,24,24,24,24,24,24,24,
  24,24,24,24,248,9,6,12,10,0,8,8,0,28,0,54,
  0,99,0,193,128,128,128,10,1,2,10,0,255,255,192,4,
  3,3,5,0,12,224,96,48,8,11,11,9,0,0,124,127,
  3,3,59,123,227,195,199,255,123,9,13,26,10,0,0,64,
  0,192,0,192,0,192,0,192,0,222,0,223,0,195,128,193,
  128,193,128,195,0,255,0,222,0,8,11,11,9,0,0,30,
  63,115,224,192,192,192,224,240,127,30,9,13,26,10,0,0,
  0,128,1,128,1,128,1,128,1,128,61,128,125,128,225,128,
  193,128,193,128,227,128,127,128,61,128,8,11,11,9,0,0,
  60,126,231,195,195,223,222,192,227,127,62,7,13,13,8,0,
  0,62,124,96,96,252,248,96,96,96,96,96,96,32,8,13,
  13,9,0,0,63,127,227,195,195,195,227,123,51,3,3,127,
  254,8,13,13,9,0,0,64,192,192,192,222,223,195,195,195,
  195,195,195,130,2,13,13,3,0,0,64,192,128,64,192,192,
  192,192,192,192,192,192,128,5,14,14,6,0,255,16,24,24,
  8,48,120,24,24,24,24,24,24,120,240,8,13,13,9,0,
  0,64,192,192,198,198,204,216,216,216,204,198,199,131,2,14,
  14,3,0,0,64,192,192,192,192,192,192,192,192,192,192,192,
  192,128,9,11,22,10,0,0,91,0,219,128,201,128,201,128,
  201,128,201,128,201,128,201,128,201,128,193,128,129,0,8,11,
  11,9,0,0,94,223,195,195,195,195,195,195,195,195,130,8,
  11,11,9,0,0,52,118,227,195,195,195,195,195,227,118,52,
  8,11,11,9,0,0,252,254,199,195,199,222,220,192,192,192,
  128,9,13,26,9,0,255,63,0,127,0,227,0,195,0,195,
  0,195,0,251,0,123,0,3,0,3,0,3,128,3,128,3,
  128,7,11,11,8,0,0,92,222,224,224,192,192,192,192,192,
  192,128,8,11,11,9,0,0,62,127,192,192,240,102,15,3,
  3,254,124,6,13,13,7,0,0,32,96,96,252,248,96,96,
  96,96,96,96,124,60,8,11,11,9,0,0,65,195,195,195,
  195,195,195,195,227,123,58,8,11,11,9,0,0,129,129,195,
  195,102,102,102,36,60,24,24,9,11,22,10,0,0,128,128,
  193,128,201,128,201,128,201,128,201,128,193,128,221,128,247,128,
  227,128,65,0,8,11,11,9,0,0,195,102,102,52,24,24,
  24,52,102,102,195,8,12,12,9,0,255,193,227,99,102,110,
  44,12,24,24,48,240,224,8,11,11,9,0,0,127,255,7,
  6,12,0,48,96,224,255,254,7,14,14,8,0,0,14,28,
  24,24,24,48,224,224,48,24,24,24,28,14,2,16,16,5,
  1,255,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
  192,192,8,14,14,9,0,0,224,112,24,24,24,12,7,7,
  12,24,24,24,112,224,10,5,10,11,0,4,48,192,120,192,
  204,192,199,128,195,0,5,13,13,6,0,1,248,136,136,136,
  136,136,136,136,136,136,136,136,248,8,11,11,9,0,0,252,
  254,199,195,199,222,220,192,192,192,128,8,11,11,9,0,0,
  30,63,115,224,192,192,192,224,240,127,30,8,11,11,9,0,
  0,127,254,24,24,24,24,24,24,24,24,16,8,12,12,9,
  0,255,193,227,99,102,110,44,12,24,24,48,240,224,8,12,
  12,9,0,255,126,255,219,219,219,219,90,24,24,24,24,16,
  8,11,11,9,0,0,195,102,102,52,24,24,24,52,102,102,
  195,8,12,12,9,0,255,132,198,198,198,198,198,198,198,198,
  254,255,3,8,11,11,9,0,0,65,195,195,195,231,127,63,
  3,3,3,2,8,11,11,9,0,0,130,195,195,211,219,219,
  219,219,219,203,255,8,12,12,9,0,255,130,195,195,211,219,
  219,219,219,218,200,255,3,8,11,11,9,0,0,192,224,96,
  96,108,110,103,99,103,126,124,8,11,11,9,0,0,130,195,
  195,195,219,221,207,199,207,253,251,8,11,11,9,0,0,64,
  192,192,192,220,222,199,195,199,254,252,8,11,11,9,0,0,
  124,254,198,3,27,59,3,3,6,254,120,9,11,22,10,0,
  0,71,0,207,128,205,128,205,128,221,128,221,128,205,128,205,
  128,205,128,207,128,135,0,8,11,11,9,0,0,63,127,227,
  195,227,123,59,51,51,115,226,9,14,28,10,0,0,252,0,
  254,0,199,0,195,128,193,128,193,128,193,128,253,128,253,128,
  193,128,193,128,193,128,193,128,129,0,9,14,28,10,0,0,
  223,128,223,0,192,0,192,0,192,0,192,0,222,0,223,0,
  195,128,193,128,193,128,195,128,255,0,254,0,9,14,28,10,
  0,0,94,0,223,0,195,128,193,128,193,128,195,128,255,0,
  255,0,195,128,193,128,193,128,195,128,223,0,190,0,9,14,
  28,10,0,0,223,0,223,128,192,0,192,0,192,0,192,0,
  192,0,192,0,192,0,192,0,192,0,192,0,192,0,128,0,
  9,14,28,10,0,0,11,0,27,0,59,0,115,0,99,0,
  99,0,99,0,99,0,99,0,99,0,123,0,251,128,193,128,
  193,128,9,14,28,10,0,0,95,128,223,0,192,0,192,0,
  192,0,192,0,223,0,222,0,192,0,192,0,192,0,192,0,
  223,128,191,0,10,14,28,11,0,0,64,64,192,192,196,192,
  204,192,204,192,109,128,109,128,109,128,109,128,204,192,204,192,
  204,192,200,192,128,128,9,14,28,10,0,0,122,0,251,0,
  131,128,1,128,1,128,3,0,58,0,123,0,3,128,1,128,
  1,128,131,128,251,0,120,0,9,14,28,10,0,0,67,128,
  195,128,199,128,199,128,199,128,205,128,205,128,205,128,217,128,
  217,128,217,128,209,128,209,128,193,0,9,14,28,10,0,0,
  91,128,219,128,215,128,199,128,199,128,205,128,205,128,205,128,
  217,128,217,128,217,128,209,128,209,128,193,0,9,14,28,10,
  0,0,65,128,195,128,199,0,206,0,220,0,216,0,216,0,
  216,0,216,0,220,0,206,0,199,0,195,128,65,128,9,14,
  28,10,0,0,220,0,222,0,199,0,195,128,193,128,193,128,
  193,128,193,128,193,128,193,128,193,128,193,128,193,128,193,128,
  9,14,28,10,0,0,193,128,227,128,247,128,247,128,213,128,
  193,128,213,128,221,128,221,128,201,128,193,128,193,128,193,128,
  129,0,9,14,28,10,0,0,129,0,193,128,193,128,193,128,
  193,128,193,128,223,128,223,128,193,128,193,128,193,128,193,128,
  193,128,64,128,9,14,28,10,0,0,46,0,111,0,227,128,
  193,128,193,128,193,128,193,128,193,128,193,128,193,128,193,128,
  227,128,123,0,58,0,9,14,28,10,0,0,223,128,223,128,
  193,128,193,128,193,128,193,128,193,128,193,128,193,128,193,128,
  193,128,193,128,193,128,129,0,9,14,28,10,0,0,254,0,
  255,0,195,128,193,128,193,128,195,128,223,0,222,0,192,0,
  192,0,192,0,192,0,192,0,128,0,9,14,28,10,0,0,
  14,0,63,0,115,128,97,128,192,0,192,0,192,0,192,0,
  192,0,192,0,96,0,112,0,63,128,15,0,9,14,28,10,
  0,0,255,0,127,128,0,0,12,0,12,0,12,0,12,0,
  12,0,12,0,12,0,12,0,12,0,12,0,4,0,9,14,
  28,10,0,0,129,0,193,128,193,128,193,128,193,128,125,128,
  61,128,1,128,1,128,1,128,193,128,225,128,127,0,62,0,
  10,14,28,11,0,0,63,0,127,128,237,192,204,192,204,192,
  237,192,109,128,45,0,12,0,12,0,12,0,12,0,12,0,
  4,0,9,14,28,10,0,0,193,128,193,128,193,128,99,0,
  99,0,50,0,56,0,28,0,14,0,103,0,99,0,193,128,
  193,128,193,128,10,15,30,10,0,255,130,0,195,0,195,0,
  195,0,195,0,195,0,195,0,195,0,195,0,195,0,195,0,
  195,0,223,0,223,128,1,192,9,14,28,10,0,0,129,0,
  193,128,193,128,193,128,193,128,193,128,225,128,125,128,61,128,
  1,128,1,128,1,128,1,128,0,128,10,14,28,11,0,0,
  128,128,192,192,192,192,192,192,200,192,204,192,204,192,204,192,
  204,192,204,192,196,192,192,64,223,128,95,192,11,15,30,11,
  0,255,128,128,192,192,192,192,192,192,200,192,204,192,204,192,
  204,192,204,192,204,192,196,192,192,64,223,128,95,192,0,224,
  9,14,28,10,0,0,224,0,224,0,96,0,96,0,96,0,
  96,0,110,0,111,0,99,128,97,128,97,128,99,128,127,0,
  62,0,10,14,28,11,0,0,128,128,192,192,192,192,192,192,
  192,192,192,192,220,192,222,192,199,64,195,64,195,64,199,64,
  254,192,124,192,9,14,28,10,0,0,128,0,192,0,192,0,
  192,0,192,0,192,0,222,0,223,0,195,128,193,128,193,128,
  195,128,255,0,254,0,9,14,28,10,0,0,62,0,127,0,
  227,128,193,128,193,128,1,128,29,128,29,128,1,128,1,128,
  193,128,227,128,127,0,62,0,10,14,28,11,0,0,71,0,
  207,128,221,192,216,192,216,192,216,192,248,192,248,192,216,192,
  216,192,216,192,221,192,207,128,135,0,9,14,28,10,0,0,
  63,128,127,128,225,128,193,128,193,128,225,128,125,128,61,128,
  29,128,57,128,113,128,225,128,193,128,129,0,8,11,11,9,
  0,0,124,127,3,3,59,123,227,195,199,255,123,8,11,11,
  9,0,0,7,31,56,112,102,207,195,195,231,126,60,8,11,
  11,9,0,0,92,222,198,198,220,222,195,195,199,222,188,8,
  11,11,9,0,0,254,255,192,192,192,192,192,192,192,192,128,
  10,11,22,11,0,0,31,128,31,128,25,128,49,128,49,128,
  49,128,1,128,127,192,255,192,192,192,192,192,8,11,11,9,
  0,0,60,126,231,195,195,223,222,192,227,127,62,9,11,22,
  10,0,0,64,128,201,128,201,128,107,0,54,0,54,0,107,
  0,201,128,201,128,201,128,129,0,8,11,11,9,0,0,116,
  246,195,7,126,62,6,3,7,254,124,8,11,11,9,0,0,
  65,195,195,199,207,223,219,211,195,195,130,8,11,11,9,0,
  0,89,219,211,199,207,223,219,211,195,195,130,8,11,11,9,
  0,0,71,207,204,220,216,216,216,220,206,199,67,8,11,11,
  9,0,0,27,59,115,227,195,195,195,195,195,195,195,9,11,
  22,10,0,0,65,0,227,128,247,128,247,128,213,128,213,128,
  213,128,213,128,193,128,193,128,129,0,8,11,11,9,0,0,
  65,195,195,251,251,195,195,195,195,195,130,8,11,11,9,0,
  0,52,118,227,195,195,195,195,195,227,118,52,8,11,11,9,
  0,0,95,223,195,195,195,195,195,195,195,195,130,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255};
  
  //  Только цифры Размер 32 -------------------------------------------------------
  const u8g_fntpgm_uint8_t digits32[1345] U8G_SECTION(".progmem.digits32") = {
  0,19,31,0,0,30,4,130,4,162,32,255,0,32,0,30,
  0,255,255,255,255,255,255,255,255,255,255,255,16,15,30,17,
  0,8,1,128,3,192,3,192,3,192,3,192,63,252,127,254,
  255,255,127,254,63,252,3,192,3,192,3,192,3,192,1,128,
  5,8,8,6,0,0,112,248,248,248,112,48,96,128,16,5,
  10,17,0,13,63,252,127,254,255,255,127,254,63,252,5,5,
  5,6,0,0,112,248,248,248,112,15,32,64,16,0,0,0,
  14,0,14,0,28,0,28,0,56,0,56,0,56,0,112,0,
  112,0,112,0,224,0,224,1,192,1,192,1,192,3,128,3,
  128,7,0,7,0,7,0,14,0,14,0,28,0,28,0,28,
  0,56,0,56,0,56,0,112,0,112,0,224,0,224,0,18,
  32,96,19,0,0,127,255,128,191,255,64,223,254,192,239,253,
  192,240,3,192,240,3,192,240,3,192,240,3,192,240,3,192,
  240,3,192,240,3,192,240,3,192,240,3,192,224,1,192,192,
  0,192,128,0,64,0,0,0,128,0,64,192,0,192,224,1,
  192,240,3,192,240,3,192,240,3,192,240,3,192,240,3,192,
  240,3,192,240,3,192,240,3,192,239,253,192,223,254,192,191,
  255,64,127,255,128,4,30,30,5,0,1,16,48,112,240,240,
  240,240,240,240,240,240,240,112,48,16,0,16,48,112,240,240,
  240,240,240,240,240,240,112,48,16,18,32,96,19,0,0,127,
  255,128,63,255,64,31,254,192,15,253,192,0,3,192,0,3,
  192,0,3,192,0,3,192,0,3,192,0,3,192,0,3,192,
  0,3,192,0,3,192,0,1,192,31,254,192,63,255,64,127,
  255,128,191,255,0,223,254,0,224,0,0,240,0,0,240,0,
  0,240,0,0,240,0,0,240,0,0,240,0,0,240,0,0,
  240,0,0,239,252,0,223,254,0,191,255,0,127,255,128,17,
  32,96,18,0,0,255,255,0,127,254,128,63,253,128,31,251,
  128,0,7,128,0,7,128,0,7,128,0,7,128,0,7,128,
  0,7,128,0,7,128,0,7,128,0,7,128,0,3,128,63,
  253,128,127,254,128,255,255,0,127,254,128,63,253,128,0,3,
  128,0,7,128,0,7,128,0,7,128,0,7,128,0,7,128,
  0,7,128,0,7,128,0,7,128,31,251,128,63,253,128,127,
  254,128,255,255,0,18,30,90,19,0,1,128,0,64,192,0,
  192,224,1,192,240,3,192,240,3,192,240,3,192,240,3,192,
  240,3,192,240,3,192,240,3,192,240,3,192,240,3,192,224,
  1,192,223,254,192,191,255,64,127,255,128,63,255,64,31,254,
  192,0,1,192,0,3,192,0,3,192,0,3,192,0,3,192,
  0,3,192,0,3,192,0,3,192,0,3,192,0,1,192,0,
  0,192,0,0,64,18,32,96,19,0,0,127,255,128,191,255,
  0,223,254,0,239,252,0,240,0,0,240,0,0,240,0,0,
  240,0,0,240,0,0,240,0,0,240,0,0,240,0,0,240,
  0,0,224,0,0,223,254,0,191,255,0,127,255,128,63,255,
  64,31,254,192,0,1,192,0,3,192,0,3,192,0,3,192,
  0,3,192,0,3,192,0,3,192,0,3,192,0,3,192,15,
  253,192,31,254,192,63,255,64,127,255,128,18,32,96,19,0,
  0,127,255,128,191,255,0,223,254,0,239,252,0,240,0,0,
  240,0,0,240,0,0,240,0,0,240,0,0,240,0,0,240,
  0,0,240,0,0,240,0,0,224,0,0,223,254,0,191,255,
  0,127,255,128,191,255,64,223,254,192,224,1,192,240,3,192,
  240,3,192,240,3,192,240,3,192,240,3,192,240,3,192,240,
  3,192,240,3,192,239,253,192,223,254,192,191,255,64,127,255,
  128,17,31,93,18,0,1,255,255,0,127,254,128,63,253,128,
  31,251,128,0,7,128,0,7,128,0,7,128,0,7,128,0,
  7,128,0,7,128,0,7,128,0,7,128,0,7,128,0,3,
  128,0,1,128,0,0,128,0,0,0,0,0,128,0,1,128,
  0,3,128,0,7,128,0,7,128,0,7,128,0,7,128,0,
  7,128,0,7,128,0,7,128,0,7,128,0,3,128,0,1,
  128,0,0,128,18,32,96,19,0,0,127,255,128,191,255,64,
  223,254,192,239,253,192,240,3,192,240,3,192,240,3,192,240,
  3,192,240,3,192,240,3,192,240,3,192,240,3,192,240,3,
  192,224,1,192,223,254,192,191,255,64,127,255,128,191,255,64,
  223,254,192,224,1,192,240,3,192,240,3,192,240,3,192,240,
  3,192,240,3,192,240,3,192,240,3,192,240,3,192,239,253,
  192,223,254,192,191,255,64,127,255,128,18,32,96,19,0,0,
  127,255,128,191,255,64,223,254,192,239,253,192,240,3,192,240,
  3,192,240,3,192,240,3,192,240,3,192,240,3,192,240,3,
  192,240,3,192,240,3,192,224,1,192,223,254,192,191,255,64,
  127,255,128,63,255,64,31,254,192,0,1,192,0,3,192,0,
  3,192,0,3,192,0,3,192,0,3,192,0,3,192,0,3,
  192,0,3,192,15,253,192,31,254,192,63,255,64,127,255,128,
  5,22,22,6,0,5,112,248,248,248,112,0,0,0,0,0,
  0,0,0,0,0,0,0,112,248,248,248,112,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255};
  
  
// FONT DS-DIGITAL NUMERIC ONLY 
const u8g_fntpgm_uint8_t u8g_font_DSDGNUM[527] U8G_FONT_SECTION("u8g_font_DSDGNUM") = {
  0,16,30,0,251,24,0,0,0,0,48,57,0,25,0,24,
  0,14,24,48,16,1,1,127,248,191,244,223,236,224,28,224,
  28,224,28,224,28,224,28,224,28,192,12,128,4,0,0,128,
  4,192,12,224,28,224,28,224,28,224,28,224,28,224,28,224,
  28,223,236,191,244,127,248,3,24,24,16,12,1,32,96,224,
  224,224,224,224,224,224,224,96,32,0,32,96,224,224,224,224,
  224,224,224,96,32,14,24,48,16,1,1,255,248,127,244,63,
  236,0,28,0,28,0,28,0,28,0,28,0,28,31,236,63,
  244,127,248,191,240,192,0,224,0,224,0,224,0,224,0,224,
  0,224,0,224,0,223,224,191,240,127,248,13,24,48,16,2,
  1,255,240,127,232,63,216,0,56,0,56,0,56,0,56,0,
  56,0,56,63,216,127,232,255,240,127,232,0,24,0,56,0,
  56,0,56,0,56,0,56,0,56,0,56,63,216,127,232,255,
  240,14,22,44,16,1,2,128,4,192,12,224,28,224,28,224,
  28,224,28,224,28,224,28,223,236,191,244,127,248,31,244,0,
  12,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,
  12,0,4,14,24,48,16,1,1,127,248,191,240,223,224,224,
  0,224,0,224,0,224,0,224,0,224,0,223,224,191,240,127,
  248,63,244,0,12,0,28,0,28,0,28,0,28,0,28,0,
  28,0,28,31,236,63,244,127,248,14,24,48,16,1,1,127,
  248,191,240,223,224,224,0,224,0,224,0,224,0,224,0,224,
  0,223,224,191,240,127,248,191,244,192,12,224,28,224,28,224,
  28,224,28,224,28,224,28,224,28,223,236,191,244,127,248,13,
  23,46,16,2,2,255,240,127,232,63,216,0,56,0,56,0,
  56,0,56,0,56,0,24,0,8,0,0,0,8,0,24,0,
  56,0,56,0,56,0,56,0,56,0,56,0,56,0,56,0,
  24,0,8,14,24,48,16,1,1,127,248,191,244,223,236,224,
  28,224,28,224,28,224,28,224,28,224,28,223,236,191,244,127,
  248,191,244,192,12,224,28,224,28,224,28,224,28,224,28,224,
  28,224,28,223,236,191,244,127,248,14,24,48,16,1,1,127,
  248,191,244,223,236,224,28,224,28,224,28,224,28,224,28,224,
  28,223,236,191,244,127,248,63,244,0,12,0,28,0,28,0,
  28,0,28,0,28,0,28,0,28,31,236,63,244,127,248};
 
/*
  Fontname: u8g_font_6x9_marlin_rus
  Copyright: Share and enjoy.
  Special chars: degree = \xС0
  Capital A Height: 6, '1' Height: 6
  Calculated Max Values w= 6 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 7 len= 9
  Font Bounding box     w= 6 h= 9 x= 0 y=-2
  Calculated Min Values           x= 0 y=-2 dx= 0 dy= 0
  Pure Font   ascent = 6 descent=-2
  X Font      ascent = 6 descent=-2
  Max Font    ascent = 7 descent=-2
*/

const u8g_fntpgm_uint8_t u8g_font_6x9[2234]  U8G_SECTION(".progmem.u8g_font_6x9") = {
   0,7,8,0,254,6,1,137,2,254,32,255,254,7,254,6,
  254,0,0,0,1,0,0,1,6,6,2,0,0,128,128,128,
  128,0,128,3,3,3,4,0,3,160,160,160,5,7,7,6,
  0,255,80,80,248,80,248,80,80,5,9,9,6,0,254,32,
  112,168,160,112,40,168,112,32,6,8,8,7,0,255,64,168,
  72,16,32,72,84,8,5,7,7,6,0,255,96,144,144,96,
  152,144,104,1,3,3,2,0,3,128,128,128,2,7,7,3,
  0,255,64,128,128,128,128,128,64,2,7,7,3,0,255,128,
  64,64,64,64,64,128,5,5,5,6,0,0,136,80,248,80,
  136,5,5,5,6,0,0,32,32,248,32,32,2,4,4,3,
  0,254,192,64,64,128,5,1,1,6,0,2,248,2,2,2,
  3,0,0,192,192,4,6,6,5,0,0,16,16,32,64,128,
  128,4,6,6,5,0,0,96,144,144,144,144,96,3,6,6,
  4,0,0,64,192,64,64,64,224,4,6,6,5,0,0,96,
  144,16,32,64,240,4,6,6,5,0,0,240,32,96,16,16,
  224,5,6,6,6,0,0,16,48,80,144,248,16,4,6,6,
  5,0,0,240,128,224,16,16,224,4,6,6,5,0,0,96,
  128,224,144,144,96,4,6,6,5,0,0,240,16,16,32,64,
  64,4,6,6,5,0,0,96,144,96,144,144,96,4,6,6,
  5,0,0,96,144,144,112,16,96,2,5,5,3,0,0,192,
  192,0,192,192,2,7,7,3,0,254,192,192,0,192,64,64,
  128,5,5,5,6,0,0,24,96,128,96,24,5,3,3,6,
  0,1,248,0,248,5,5,5,6,0,0,192,48,8,48,192,
  4,7,7,5,0,0,96,144,16,96,64,0,64,5,6,6,
  6,0,0,112,144,168,176,128,112,5,6,6,6,0,0,32,
  80,136,248,136,136,5,6,6,6,0,0,240,136,240,136,136,
  240,4,6,6,5,0,0,96,144,128,128,144,96,4,6,6,
  5,0,0,224,144,144,144,144,224,4,6,6,5,0,0,240,
  128,224,128,128,240,4,6,6,5,0,0,240,128,224,128,128,
  128,4,6,6,5,0,0,96,144,128,176,144,96,4,6,6,
  5,0,0,144,144,240,144,144,144,3,6,6,4,0,0,224,
  64,64,64,64,224,5,6,6,6,0,0,56,16,16,16,144,
  96,4,6,6,5,0,0,144,160,192,160,144,144,4,6,6,
  5,0,0,128,128,128,128,128,240,5,6,6,6,0,0,136,
  216,168,168,136,136,4,6,6,5,0,0,144,208,176,144,144,
  144,5,6,6,6,0,0,112,136,136,136,136,112,4,6,6,
  5,0,0,224,144,144,224,128,128,4,7,7,5,0,255,96,
  144,144,208,176,96,16,4,6,6,5,0,0,224,144,144,224,
  144,144,4,6,6,5,0,0,96,144,64,32,144,96,5,6,
  6,6,0,0,248,32,32,32,32,32,4,6,6,5,0,0,
  144,144,144,144,144,96,4,6,6,5,0,0,144,144,144,240,
  96,96,5,6,6,6,0,0,136,136,168,168,216,136,5,6,
  6,6,0,0,136,80,32,32,80,136,5,6,6,6,0,0,
  136,136,80,32,32,32,4,6,6,5,0,0,240,16,32,64,
  128,240,3,6,6,4,0,0,224,128,128,128,128,224,4,6,
  6,5,0,0,128,128,64,32,16,16,3,6,6,4,0,0,
  224,32,32,32,32,224,5,3,3,6,0,3,32,80,136,5,
  1,1,6,0,254,248,2,2,2,3,0,4,128,64,4,4,
  4,5,0,0,112,144,144,112,4,6,6,5,0,0,128,128,
  224,144,144,224,4,4,4,5,0,0,112,128,128,112,4,6,
  6,5,0,0,16,16,112,144,144,112,4,4,4,5,0,0,
  96,176,192,112,4,6,6,5,0,0,32,80,64,224,64,64,
  4,6,6,5,0,254,96,144,144,112,16,96,4,6,6,5,
  0,0,128,128,224,144,144,144,3,6,6,4,0,0,64,0,
  192,64,64,224,3,8,8,4,0,254,32,0,96,32,32,32,
  160,64,4,6,6,5,0,0,128,128,160,192,160,144,3,6,
  6,4,0,0,192,64,64,64,64,224,5,4,4,6,0,0,
  208,168,168,136,4,4,4,5,0,0,224,144,144,144,4,4,
  4,5,0,0,96,144,144,96,4,6,6,5,0,254,224,144,
  144,224,128,128,4,6,6,5,0,254,112,144,144,112,16,16,
  4,4,4,5,0,0,160,208,128,128,4,4,4,5,0,0,
  112,192,48,224,4,6,6,5,0,0,64,64,224,64,80,32,
  4,4,4,5,0,0,144,144,144,112,4,4,4,5,0,0,
  144,144,96,96,5,4,4,6,0,0,136,168,168,80,4,4,
  4,5,0,0,144,96,96,144,4,6,6,5,0,254,144,144,
  144,112,144,96,4,4,4,5,0,0,240,32,64,240,3,7,
  7,4,0,0,32,64,64,128,64,64,32,1,7,7,2,0,
  255,128,128,128,128,128,128,128,3,7,7,4,0,0,128,64,
  64,32,64,64,128,4,2,2,5,0,3,80,160,3,6,6,
  4,0,0,224,160,160,160,160,224,5,6,6,6,0,254,240,
  136,136,240,128,128,5,4,4,6,0,0,112,136,128,120,5,
  4,4,6,0,0,248,32,32,32,5,6,6,6,0,254,136,
  136,136,120,8,112,5,8,8,6,0,254,32,32,112,168,168,
  112,32,32,4,4,4,5,0,0,144,96,96,144,5,6,6,
  6,0,254,144,144,144,248,8,16,5,4,4,6,0,0,136,
  136,120,8,5,4,4,6,0,0,168,168,168,248,5,6,6,
  6,0,254,168,168,168,248,8,16,5,4,4,6,0,0,192,
  112,72,112,5,4,4,6,0,0,136,232,152,232,4,4,4,
  5,0,0,128,224,144,224,4,4,4,5,0,0,224,80,48,
  224,5,4,4,6,0,0,144,232,232,144,4,4,4,5,0,
  0,112,144,112,144,5,6,6,6,0,0,32,80,136,248,136,
  136,5,6,6,6,0,0,240,128,240,136,136,240,5,6,6,
  6,0,0,240,136,240,136,136,240,4,6,6,5,0,0,240,
  128,128,128,128,128,5,7,7,6,0,255,48,80,80,80,80,
  248,136,4,6,6,5,0,0,240,128,224,128,128,240,5,6,
  6,6,0,0,168,168,112,168,168,168,5,6,6,6,0,0,
  112,136,48,8,136,112,4,6,6,5,0,0,144,144,176,208,
  144,144,4,7,7,5,0,0,96,144,144,176,208,144,144,4,
  6,6,5,0,0,144,160,192,160,144,144,5,6,6,6,0,
  0,56,72,72,72,72,136,5,6,6,6,0,0,136,216,168,
  168,136,136,4,6,6,5,0,0,144,144,240,144,144,144,5,
  6,6,6,0,0,112,136,136,136,136,112,5,6,6,6,0,
  0,248,136,136,136,136,136,4,6,6,5,0,0,224,144,144,
  224,128,128,4,6,6,5,0,0,96,144,128,128,144,96,5,
  6,6,6,0,0,248,32,32,32,32,32,5,6,6,6,0,
  0,136,136,136,120,8,112,5,6,6,6,0,0,32,112,168,
  168,112,32,5,6,6,6,0,0,136,80,32,32,80,136,5,
  8,8,6,0,254,144,144,144,144,144,248,8,16,5,6,6,
  6,0,0,136,136,136,120,8,8,5,6,6,6,0,0,168,
  168,168,168,168,248,5,8,8,6,0,254,168,168,168,168,168,
  248,8,16,5,6,6,6,0,0,192,64,112,72,72,112,5,
  6,6,6,0,0,136,136,232,152,152,232,4,6,6,5,0,
  0,128,128,224,144,144,224,5,6,6,6,0,0,112,136,56,
  8,136,112,5,6,6,6,0,0,144,168,232,232,168,144,4,
  6,6,5,0,0,112,144,144,112,144,144,5,4,4,6,0,
  0,112,144,144,120,4,7,7,5,0,0,16,96,128,224,144,
  144,96,4,4,4,5,0,0,192,160,208,224,4,4,4,5,
  0,0,240,128,128,128,5,5,5,6,0,255,48,80,80,248,
  136,4,4,4,5,0,0,96,144,224,112,5,4,4,6,0,
  0,168,112,112,168,4,4,4,5,0,0,96,80,48,224,5,
  4,4,6,0,0,136,152,168,200,5,6,6,6,0,0,80,
  32,136,152,168,200,4,4,4,5,0,0,144,160,224,144,5,
  4,4,6,0,0,56,72,72,136,5,4,4,6,0,0,136,
  216,168,136,5,4,4,6,0,0,136,248,136,136,5,4,4,
  6,0,0,112,136,136,112,5,4,4,6,0,0,248,136,136,
  136,0,0,0,1,0,0,3,4,4,4,0,2,64,160,160,
  64,5,5,5,6,0,1,32,16,248,16,32,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0};


/*
  Fontname: u8g_font_6x10_marlin_rus
  Copyright: Share and enjoy.
  Special chars: degree = \xС0
  Capital A Height: 7, '1' Height: 7
  Calculated Max Values w= 6 h= 9 x= 1 y= 6 dx= 7 dy= 0 ascent= 8 len= 9
  Font Bounding box     w= 7 h= 9 x= 0 y=-2
  Calculated Min Values           x= 0 y=-2 dx= 0 dy= 0
  Pure Font   ascent = 7 descent=-2
  X Font      ascent = 7 descent=-2
  Max Font    ascent = 8 descent=-2
*/
const u8g_fntpgm_uint8_t u8g_font_6x10_marlin[2371] U8G_SECTION(".progmem.u8g_font_6x10_marlin") = {
 0,7,9,0,254,7,1,149,3,39,32,255,254,8,254,7,
  254,0,0,0,6,0,0,1,7,7,2,0,0,128,128,128,
  128,128,0,128,3,3,3,4,0,4,160,160,160,5,7,7,
  6,0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,
  32,112,160,112,40,112,32,5,7,7,6,0,0,72,168,80,
  32,80,168,144,5,7,7,6,0,0,64,160,160,64,168,144,
  104,1,3,3,2,0,4,128,128,128,3,7,7,4,0,0,
  32,64,128,128,128,64,32,3,7,7,4,0,0,128,64,32,
  32,32,64,128,5,5,5,6,0,1,136,80,248,80,136,5,
  5,5,6,0,1,32,32,248,32,32,2,3,3,4,0,255,
  64,64,128,5,1,1,6,0,3,248,1,2,2,4,1,0,
  128,128,5,7,7,6,0,0,8,8,16,32,64,128,128,5,
  7,7,6,0,0,32,80,136,136,136,80,32,5,7,7,6,
  0,0,32,96,160,32,32,32,248,5,7,7,6,0,0,112,
  136,8,48,64,128,248,5,7,7,6,0,0,248,8,16,48,
  8,136,112,5,7,7,6,0,0,16,48,80,144,248,16,16,
  5,7,7,6,0,0,248,128,176,200,8,136,112,5,7,7,
  6,0,0,48,64,128,176,200,136,112,5,7,7,6,0,0,
  248,8,16,16,32,64,64,5,7,7,6,0,0,112,136,136,
  112,136,136,112,5,7,7,6,0,0,112,136,152,104,8,16,
  96,1,5,5,4,1,0,128,128,0,128,128,2,6,6,4,
  0,255,64,64,0,64,64,128,4,7,7,5,0,0,16,32,
  64,128,64,32,16,5,3,3,6,0,2,248,0,248,4,7,
  7,5,0,0,128,64,32,16,32,64,128,5,7,7,6,0,
  0,112,136,16,32,32,0,32,5,7,7,6,0,0,112,136,
  152,168,176,128,112,5,7,7,6,0,0,32,80,136,136,248,
  136,136,5,7,7,6,0,0,240,72,72,112,72,72,240,5,
  7,7,6,0,0,112,136,128,128,128,136,112,5,7,7,6,
  0,0,240,72,72,72,72,72,240,5,7,7,6,0,0,248,
  128,128,240,128,128,248,5,7,7,6,0,0,248,128,128,240,
  128,128,128,5,7,7,6,0,0,112,136,128,128,152,136,112,
  5,7,7,6,0,0,136,136,136,248,136,136,136,3,7,7,
  4,0,0,224,64,64,64,64,64,224,5,7,7,6,0,0,
  56,16,16,16,16,144,96,5,7,7,6,0,0,136,144,160,
  192,160,144,136,5,7,7,6,0,0,128,128,128,128,128,128,
  248,5,7,7,6,0,0,136,136,216,168,136,136,136,5,7,
  7,6,0,0,136,136,200,168,152,136,136,5,7,7,6,0,
  0,112,136,136,136,136,136,112,5,7,7,6,0,0,240,136,
  136,240,128,128,128,5,8,8,6,0,255,112,136,136,136,136,
  168,112,8,5,7,7,6,0,0,240,136,136,240,160,144,136,
  5,7,7,6,0,0,112,136,128,112,8,136,112,5,7,7,
  6,0,0,248,32,32,32,32,32,32,5,7,7,6,0,0,
  136,136,136,136,136,136,112,5,7,7,6,0,0,136,136,136,
  80,80,80,32,5,7,7,6,0,0,136,136,136,168,168,216,
  136,5,7,7,6,0,0,136,136,80,32,80,136,136,5,7,
  7,6,0,0,136,136,80,32,32,32,32,5,7,7,6,0,
  0,248,8,16,32,64,128,248,3,7,7,4,0,0,224,128,
  128,128,128,128,224,5,7,7,6,0,0,128,128,64,32,16,
  8,8,3,7,7,4,0,0,224,32,32,32,32,32,224,5,
  3,3,6,0,4,32,80,136,5,1,1,6,0,255,248,2,
  2,2,3,0,6,128,64,5,5,5,6,0,0,112,8,120,
  136,120,5,7,7,6,0,0,128,128,176,200,136,200,176,5,
  5,5,6,0,0,112,136,128,136,112,5,7,7,6,0,0,
  8,8,104,152,136,152,104,5,5,5,6,0,0,112,136,248,
  128,112,5,7,7,6,0,0,48,72,64,240,64,64,64,5,
  7,7,6,0,254,120,136,136,120,8,136,112,5,7,7,6,
  0,0,128,128,176,200,136,136,136,3,7,7,4,0,0,64,
  0,192,64,64,64,224,4,9,9,5,0,254,16,0,48,16,
  16,16,144,144,96,5,7,7,6,0,0,128,128,136,144,224,
  144,136,3,7,7,4,0,0,192,64,64,64,64,64,224,5,
  5,5,6,0,0,208,168,168,168,136,5,5,5,6,0,0,
  176,200,136,136,136,5,5,5,6,0,0,112,136,136,136,112,
  5,7,7,6,0,254,176,200,136,200,176,128,128,5,7,7,
  6,0,254,104,152,136,152,104,8,8,5,5,5,6,0,0,
  176,200,128,128,128,5,5,5,6,0,0,112,128,112,8,240,
  5,7,7,6,0,0,64,64,240,64,64,72,48,5,5,5,
  6,0,0,136,136,136,152,104,5,5,5,6,0,0,136,136,
  80,80,32,5,5,5,6,0,0,136,136,168,168,80,5,5,
  5,6,0,0,136,80,32,80,136,5,7,7,6,0,254,136,
  136,152,104,8,136,112,5,5,5,6,0,0,248,16,32,64,
  248,4,7,7,5,0,0,48,64,32,192,32,64,48,1,7,
  7,2,0,0,128,128,128,128,128,128,128,4,7,7,5,0,
  0,192,32,64,48,64,32,192,5,3,3,6,0,4,72,168,
  144,4,7,7,5,0,0,240,144,144,144,144,144,240,5,7,
  7,6,0,254,176,200,136,200,176,128,128,5,5,5,6,0,
  0,112,136,128,136,112,5,5,5,6,0,0,248,32,32,32,
  32,5,7,7,6,0,254,136,136,136,120,8,136,112,5,9,
  9,6,0,254,32,32,112,168,168,168,112,32,32,5,5,5,
  6,0,0,136,80,32,80,136,5,7,7,6,0,254,144,144,
  144,144,248,8,8,5,5,5,6,0,0,136,136,120,8,8,
  5,5,5,6,0,0,168,168,168,168,248,5,7,7,6,0,
  254,168,168,168,168,248,8,8,5,5,5,6,0,0,192,64,
  112,72,112,6,5,5,7,0,0,132,132,228,148,228,4,5,
  5,5,0,0,128,128,224,144,224,5,5,5,6,0,0,112,
  136,56,136,112,5,5,5,6,0,0,144,168,232,168,144,5,
  5,5,6,0,0,120,136,120,136,136,5,7,7,6,0,0,
  32,80,136,136,248,136,136,5,7,7,6,0,0,240,128,128,
  240,136,136,240,5,7,7,6,0,0,240,136,136,240,136,136,
  240,5,7,7,6,0,0,248,128,128,128,128,128,128,5,8,
  8,6,0,255,24,40,40,72,72,72,248,136,5,7,7,6,
  0,0,248,128,128,240,128,128,248,5,7,7,6,0,0,168,
  168,168,112,168,168,168,5,7,7,6,0,0,112,136,8,48,
  8,136,112,5,7,7,6,0,0,136,136,152,168,200,136,136,
  5,8,8,6,0,0,80,32,136,152,168,200,136,136,5,7,
  7,6,0,0,136,144,160,192,160,144,136,5,7,7,6,0,
  0,56,72,72,72,72,72,136,5,7,7,6,0,0,136,136,
  216,168,136,136,136,5,7,7,6,0,0,136,136,136,248,136,
  136,136,5,7,7,6,0,0,112,136,136,136,136,136,112,5,
  7,7,6,0,0,248,136,136,136,136,136,136,5,7,7,6,
  0,0,240,136,136,240,128,128,128,5,7,7,6,0,0,112,
  136,128,128,128,136,112,5,7,7,6,0,0,248,32,32,32,
  32,32,32,5,7,7,6,0,0,136,136,136,80,32,64,128,
  5,7,7,6,0,0,32,112,168,168,168,112,32,5,7,7,
  6,0,0,136,136,80,32,80,136,136,5,9,9,6,0,254,
  144,144,144,144,144,144,248,8,8,5,7,7,6,0,0,136,
  136,136,120,8,8,8,5,7,7,6,0,0,168,168,168,168,
  168,168,248,5,9,9,6,0,254,168,168,168,168,168,168,248,
  8,8,5,7,7,6,0,0,192,64,64,112,72,72,112,5,
  7,7,6,0,0,136,136,136,232,152,152,232,4,7,7,5,
  0,0,128,128,128,224,144,144,224,5,7,7,6,0,0,112,
  136,8,56,8,136,112,5,7,7,6,0,0,144,168,168,232,
  168,168,144,5,7,7,6,0,0,120,136,136,120,40,72,136,
  5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,0,
  0,120,128,112,136,136,136,112,5,5,5,6,0,0,240,136,
  240,136,240,4,5,5,5,0,0,240,128,128,128,128,5,6,
  6,6,0,255,48,80,80,80,248,136,5,5,5,6,0,0,
  112,136,248,128,112,5,5,5,6,0,0,168,168,112,168,168,
  5,5,5,6,0,0,112,136,48,136,112,5,5,5,6,0,
  0,136,152,168,200,136,5,7,7,6,0,0,80,32,136,152,
  168,200,136,5,5,5,6,0,0,136,144,224,144,136,5,5,
  5,6,0,0,56,72,72,72,136,5,5,5,6,0,0,136,
  216,168,136,136,5,5,5,6,0,0,136,136,248,136,136,5,
  5,5,6,0,0,112,136,136,136,112,5,5,5,6,0,0,
  248,136,136,136,136,0,0,0,6,0,0,3,3,3,4,0,
  4,64,160,64,0,0,0,6,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
  0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,
  0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
  0,1,0,0,5,5,5,6,0,1,32,16,248,16,32,6,
  6,6,6,0,2,32,112,168,32,32,60,0,0,0,1,0,
  0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,
  1,0,0}; 

 

файл emonLib.ino

// --------------------------------------------------------------------------------------
// Вся теория и практика (и библиотека) изложена здесь:  http://openenergymonitor.org
// Переработанная библиотека emonLib. Выкинул все лишнее и добавил свое что было нужно. Затачивал под UNO
// Про измерение напряжения: http://openenergymonitor.org/emon/buildingblocks/measuring-voltage-with-...
// Только я использовал переменные резисторы для настройки уровня и смещения сигнала (10 ком).
// Про измерение тока читать здесь:  http://openenergymonitor.org/emon/buildingblocks/ct-sensors-interface
// Использовал датчик тока AC-1020 нагрузка 60 ом + резистор регулирования смещения 10 кОм
// Для увеличения точности измерения калибровал внутренний источник опорного напряжения
// --------------------------------------------------------------------------------------
#include "emonLib.h"
//--------------------------------------------------------------------------------------
// Sets the pins to be used for voltage and current sensors
//--------------------------------------------------------------------------------------
void EnergyMonitor::voltage(unsigned int _inPinV, double _VCAL, double _PHASECAL)
{
   inPinV = _inPinV;
   VCAL = _VCAL;
   PHASECAL = _PHASECAL;
   offsetV = ADC_COUNTS>>1;
}

void EnergyMonitor::current(unsigned int _inPinI, double _ICAL)
{
   inPinI = _inPinI;
   ICAL = _ICAL;
   offsetI = ADC_COUNTS>>1;
}

//--------------------------------------------------------------------------------------
// emon_calc procedure
// Calculates realPower,apparentPower,powerFactor,Vrms,Irms,kWh increment
// From a sample window of the mains AC voltage and current.
// The Sample window length is defined by the number of half wavelengths or crossings we choose to measure.
//--------------------------------------------------------------------------------------
void EnergyMonitor::calcVI(unsigned int crossings, unsigned int timeout)
{
  int SupplyVoltage = readVcc();
  unsigned int crossCount = 0;                             //Used to measure number of times threshold is crossed.
  unsigned int numberOfSamples = 0;                        //This is now incremented  

  //-------------------------------------------------------------------------------------------------------------------------
  // 1) Waits for the waveform to be close to 'zero' (mid-scale adc) part in sin curve.
  //-------------------------------------------------------------------------------------------------------------------------
  boolean st=false;                                  //an indicator to exit the while loop
  unsigned long start = millis();    //millis()-start makes sure it doesnt get stuck in the loop if there is an error.
  while(st==false)                                   //the while loop...
  {
     startV = analogRead(inPinV);                    //using the voltage waveform
     if ((startV < (ADC_COUNTS*0.55)) && (startV > (ADC_COUNTS*0.45))) st=true;  //check its within range
     if ((millis()-start)>timeout) st = true;
  }
  
  //-------------------------------------------------------------------------------------------------------------------------
  // 2) Main measurement loop
  //------------------------------------------------------------------------------------------------------------------------- 
  start = millis(); 

  while ((crossCount < crossings) && ((millis()-start)<timeout)) 
  {
    numberOfSamples++;                       //Count number of times looped.
    lastFilteredV = filteredV;               //Used for delay/phase compensation
    
    //-----------------------------------------------------------------------------
    // A) Read in raw voltage and current samples
    //-----------------------------------------------------------------------------
    sampleV = analogRead(inPinV);                 //Read in raw voltage signal
    sampleI = analogRead(inPinI);                 //Read in raw current signal

    //-----------------------------------------------------------------------------
    // B) Apply digital low pass filters to extract the 2.5 V or 1.65 V dc offset,
    //     then subtract this - signal is now centred on 0 counts.
    //-----------------------------------------------------------------------------
    offsetV = offsetV + ((sampleV-offsetV)/1024);
	filteredV = sampleV - offsetV;
    offsetI = offsetI + ((sampleI-offsetI)/1024);
	filteredI = sampleI - offsetI;
   
    //-----------------------------------------------------------------------------
    // C) Root-mean-square method voltage
    //-----------------------------------------------------------------------------  
    sqV= filteredV * filteredV;                 //1) square voltage values
    sumV += sqV;                                //2) sum
    
    //-----------------------------------------------------------------------------
    // D) Root-mean-square method current
    //-----------------------------------------------------------------------------   
    sqI = filteredI * filteredI;                //1) square current values
    sumI += sqI;                                //2) sum 
    
    //-----------------------------------------------------------------------------
    // E) Phase calibration
    //-----------------------------------------------------------------------------
    phaseShiftedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV); 
    
    //-----------------------------------------------------------------------------
    // F) Instantaneous power calc
    //-----------------------------------------------------------------------------   
    instP = phaseShiftedV * filteredI;          //Instantaneous Power
    sumP +=instP;                               //Sum  
    
    //-----------------------------------------------------------------------------
    // G) Find the number of times the voltage has crossed the initial voltage
    //    - every 2 crosses we will have sampled 1 wavelength 
    //    - so this method allows us to sample an integer number of half wavelengths which increases accuracy
    //-----------------------------------------------------------------------------       
    lastVCross = checkVCross;                     
    if (sampleV > startV) checkVCross = true; 
                     else checkVCross = false;
    if (numberOfSamples==1) lastVCross = checkVCross;                  
                     
    if (lastVCross != checkVCross) crossCount++;
  }
 
  //-------------------------------------------------------------------------------------------------------------------------
  // 3) Post loop calculations
  //------------------------------------------------------------------------------------------------------------------------- 
  //Calculation of the root of the mean of the voltage and current squared (rms)
  //Calibration coefficients applied. 
  
  double V_RATIO = VCAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
  Vrms = V_RATIO * sqrt(sumV / numberOfSamples); 
  
  double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
  Irms = I_RATIO * sqrt(sumI / numberOfSamples); 

  //Calculation power values
  realPower = V_RATIO * I_RATIO * sumP / numberOfSamples;
  apparentPower = Vrms * Irms;
  powerFactor=realPower / apparentPower;

  //Reset accumulators
  sumV = 0;
  sumI = 0;
  sumP = 0;
//--------------------------------------------------------------------------------------       
}

//--------------------------------------------------------------------------------------
double EnergyMonitor::calcIrms(unsigned int Number_of_Samples)
{
  
   #if defined emonTxV3
	int SupplyVoltage=3300;
   #else 
	int SupplyVoltage = readVcc();
   #endif

  
  for (unsigned int n = 0; n < Number_of_Samples; n++)
  {
    sampleI = analogRead(inPinI);

    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset, 
	//  then subtract this - signal is now centered on 0 counts.
    offsetI = (offsetI + (sampleI-offsetI)/1024);
	filteredI = sampleI - offsetI;

    // Root-mean-square method current
    // 1) square current values
    sqI = filteredI * filteredI;
    // 2) sum 
    sumI += sqI;
  }

  double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
  Irms = I_RATIO * sqrt(sumI / Number_of_Samples); 
  //Reset accumulators
  sumI = 0;
//--------------------------------------------------------------------------------------       
  return Irms;
}

long EnergyMonitor::readVcc() {
  long result;
   // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(1); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = READVCC_CALIBRATION_CONST  / result; // Back-calculate AVcc in mV
  return result;  
}


файл BitMap.h

#include "U8glib.h"
// КАРТИНКИ ДЛЯ ДИСПЛЕЯ 128х64 -----------------------------------------
const unsigned char u8g_logo_bits[] U8G_PROGMEM = { // Стартовое лого собака Боня размер 56х56
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0xE3,0x00,0x00,0xE0,0x00,0x00,0x00,0x61,0x03,0x00,0xBE,0x00,0x00,0x80,0xC1,0x06,
0xC0,0x01,0x01,0x00,0x80,0x88,0x0C,0xE0,0x41,0x01,0x00,0x80,0x88,0x09,0xA0,0x20,0x01,0x00,0x80,0x10,0x10,0xD0,0x31,0x02,0x00,0x80,0x38,0x20,
0x90,0x38,0x02,0x00,0x40,0x28,0x20,0x10,0x28,0x06,0x00,0x40,0x48,0x20,0x08,0x44,0x04,0x00,0x40,0xC8,0x20,0x48,0x46,0x04,0x00,0x40,0x84,0x21,
0x08,0x43,0x04,0x00,0x20,0xC4,0x1E,0x08,0xC3,0x08,0x00,0x20,0x44,0x02,0xC8,0x86,0x08,0xFE,0x23,0x46,0x03,0xF8,0x85,0xF8,0x03,0x3C,0x46,0x01,
0x00,0x8D,0x00,0x00,0x10,0x5C,0x01,0x00,0x89,0x01,0x00,0x00,0x70,0x01,0x00,0x9B,0x01,0x18,0x00,0xA0,0x01,0x00,0xD2,0x00,0x00,0x00,0x80,0x00,
0x00,0x76,0xE0,0x00,0x70,0x80,0x00,0x00,0x04,0x90,0x39,0x90,0x00,0x01,0x00,0x0C,0xF1,0x00,0x90,0x00,0x02,0x00,0x0C,0x00,0x38,0xE0,0x00,0x06,
0x00,0x02,0x00,0x00,0x00,0x00,0x04,0x00,0x83,0x00,0x00,0x00,0x00,0x0C,0x80,0x01,0x00,0x80,0x1F,0x80,0x08,0x80,0x08,0xC0,0xFF,0x7B,0x00,0x19,
0xC0,0x08,0xA0,0xD7,0x5F,0x78,0x10,0x60,0xA0,0xE0,0xD6,0x3F,0x50,0x10,0xB0,0xE0,0xC0,0xD6,0x3F,0x24,0x10,0xF0,0x00,0x80,0xFF,0x0F,0x20,0x1C,
0x40,0x00,0x00,0xFF,0x07,0x00,0x0C,0x40,0x00,0x00,0xFC,0x01,0x00,0x08,0xA0,0x01,0x0E,0x78,0x08,0x30,0x0A,0xE0,0x01,0x86,0x61,0x00,0x7C,0x0E,
0xA0,0x00,0x04,0x62,0x00,0x08,0x04,0x80,0x44,0x8C,0x21,0x06,0x08,0x04,0x80,0x87,0x18,0x20,0x00,0x8C,0x05,0x80,0x85,0x10,0x20,0x00,0x86,0x03,
0x00,0x06,0x24,0x22,0x00,0xA3,0x00,0x00,0x22,0xC2,0xFF,0xE0,0x60,0x00,0x00,0x3E,0x02,0x83,0x3F,0x10,0x00,0x00,0x2C,0x06,0x00,0x00,0x1E,0x00,
0x00,0x60,0x07,0x04,0x80,0x03,0x00,0x00,0xC0,0x34,0xFB,0x70,0x00,0x00,0x00,0x00,0xB8,0xFF,0x1E,0x00,0x00,0x00,0x00,0x60,0xF0,0x03,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 

const unsigned char cub[] U8G_PROGMEM = { // обозначение кубическикх метров  u8g.drawXBM(60, 40, 9, 7, cub)
0xc0,0x00,0x00,0x01,0x80,0x00,0x0e,0x01,0xd5,0x00,0x15,0x00,0x15,0x00 };

const unsigned char dT[] U8G_PROGMEM = { // дельта температур  u8g.drawXBM(x, x, 10, 7, dT)
0xe0,0x03,0x80,0x00,0x80,0x00,0x84,0x00,0x8a,0x00,0x91,0x00,0x9f,0x00 };

const unsigned char Hz[] U8G_PROGMEM = { // герцы  u8g.drawXBM(x, x, 8, 7, Hz)
0x0f,0x01,0x51,0x51,0x51,0xf1,0x80 };

const unsigned char T1[] U8G_PROGMEM = { // термометр 1  u8g.drawXBM(x, x, 9, 25, T1)
0x10,0x00,0x28,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x44,
 0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x54,0x00,0x54,0x00,0x54,0x00,
 0x54,0x00,0x54,0x00,0x92,0x00,0x39,0x01,0x7d,0x01,0x7d,0x01,0x39,0x01,0x92,
 0x00,0x44,0x00,0x38,0x00 };
 
const unsigned char T2[] U8G_PROGMEM = { // термометр 2  u8g.drawXBM(x, x, 9, 25, T2)
0x10,0x00,0x28,0x00,0x44,0x00,0x44,0x00,0x54,0x00,0x44,0x00,0x54,0x00,0x54,
 0x00,0x54,0x00,0x54,0x00,0x54,0x00,0x54,0x00,0x54,0x00,0x54,0x00,0x54,0x00,
 0x54,0x00,0x54,0x00,0x92,0x00,0x39,0x01,0x7d,0x01,0x7d,0x01,0x39,0x01,0x92,
 0x00,0x44,0x00,0x38,0x00 };
 
const unsigned char C0[] U8G_PROGMEM = { // Значек температуры  u8g.drawXBM(x, x, 9, 7, С0)
0x80,0x00,0x4E,0x01,0x91,0x00,0x01,0x00,0x01,0x00,0x11,0x00,0x0E,0x00};

const unsigned char T123[] U8G_PROGMEM = { // Термометр и три значка для темератур w 21 h 25
 0x10,0xc2,0x1f,0x28,0x06,0x10,0x44,0xce,0x1f,0x44,0x5e,0x00,0x54,0xce,0x1f,
 0x44,0x06,0x10,0x54,0xc2,0x1f,0x44,0x00,0x00,0x54,0x00,0x00,0x44,0xd0,0x1f,
 0x54,0x18,0x10,0x44,0xdc,0x1f,0x54,0x5e,0x00,0x54,0xdc,0x1f,0x54,0x18,0x10,
 0x54,0xd0,0x1f,0x54,0x00,0x00,0x92,0x00,0x00,0x39,0x01,0x1f,0x7d,0x01,0x04,
 0x7d,0x01,0x04,0x39,0x21,0x04,0x92,0x50,0x04,0x44,0x88,0x04,0x38,0xf8,0x04 };
 
const unsigned char aLogo[] U8G_PROGMEM = { // лого ардуино размер 51х51
 0x00,0x00,0xe0,0x3f,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0x01,0x00,0x00,0x00,
 0x80,0xff,0xff,0x0f,0x00,0x00,0x00,0xe0,0xff,0xff,0x3f,0x00,0x00,0x00,0xf8,
 0xff,0xff,0x7f,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x01,0x00,0x00,0xfe,0xff,
 0xff,0xff,0x03,0x00,0x00,0xff,0xff,0xff,0xff,0x07,0x00,0x80,0xff,0xff,0xff,
 0xff,0x0f,0x00,0xc0,0xff,0xff,0xff,0xff,0x1f,0x00,0xe0,0xff,0xff,0xff,0xff,
 0x3f,0x00,0xf0,0xff,0xff,0xff,0xff,0x3f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
 0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x00,
 0xfc,0xff,0xff,0xff,0xff,0xff,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0x01,0xfc,
 0x0f,0xf0,0x7f,0x80,0xff,0x01,0xfe,0x03,0xc0,0x1f,0x00,0xfe,0x03,0xfe,0x01,
 0x80,0x07,0x00,0xfc,0x03,0xfe,0xc0,0x07,0x07,0x3f,0xfc,0x03,0xfe,0xf0,0x0f,
 0x82,0x7f,0xf8,0x03,0x7f,0xf8,0x1f,0xc0,0xf3,0xf0,0x03,0x7f,0xf8,0x3f,0xe0,
 0xf3,0xf0,0x07,0x7f,0xfc,0x7f,0xf0,0xf3,0xf1,0x07,0x7f,0x0c,0xf8,0x78,0x80,
 0xf1,0x07,0x7f,0x0c,0xf8,0x78,0x80,0xf1,0x07,0x7f,0xfc,0x7f,0xf0,0xf3,0xf0,
 0x07,0x7f,0xf8,0x3f,0xe0,0xf3,0xf0,0x07,0xfe,0xf0,0x0f,0xc2,0x73,0xf8,0x03,
 0xfe,0xe0,0x07,0x87,0x3f,0xf8,0x03,0xfe,0xc1,0x03,0x0f,0x1e,0xfc,0x03,0xfe,
 0x03,0xc0,0x0f,0x00,0xfe,0x03,0xfe,0x0f,0xf0,0x3f,0x80,0xff,0x01,0xfc,0x3f,
 0xfc,0xff,0xf0,0xff,0x01,0xfc,0xff,0xff,0xff,0xff,0xff,0x01,0xf8,0xff,0xff,
 0xff,0xff,0xff,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x00,0xf0,0xff,0xff,0xff,
 0xff,0x7f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,0x00,0xe0,0xff,0xff,0xff,0xff,
 0x3f,0x00,0xc0,0xff,0xff,0xff,0xff,0x1f,0x00,0xc0,0xff,0xff,0xff,0xff,0x0f,
 0x00,0x80,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xfe,0xff,0xff,0xff,0x07,0x00,
 0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0xf8,0xff,0xff,0xff,0x00,0x00,0x00,
 0xf0,0xff,0xff,0x3f,0x00,0x00,0x00,0xc0,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,
 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0xfc,0xff,0x03,0x00,0x00 };
 
 const unsigned char antenna[] U8G_PROGMEM = { // Значек антенны 5х7
0xf5, 0xf5, 0xee, 0xe4, 0xe4,0xe4,0xe4, };  

файл emonLib.h

// --------------------------------------------------------------------------------------
// Вся теория и практика (и библиотека) изложена здесь:  http://openenergymonitor.org
// Переработанная библиотека emonLib. Выкинул все лишнее и добавил свое что было нужно. Затачивал под UNO
// Про измерение напряжения: http://openenergymonitor.org/emon/buildingblocks/measuring-voltage-with-...
// Только я использовал переменные резисторы для настройки уровня и смещения сигнала (10 ком).
// Про измерение тока читать здесь:  http://openenergymonitor.org/emon/buildingblocks/ct-sensors-interface
// Использовал датчик тока AC-1020 нагрузка 60 ом + резистор регулирования смещения 10 кОм
// Для увеличения точности измерения калибровал внутренний источник опорного напряжения
// --------------------------------------------------------------------------------------
// define theoretical vref calibration constant for use in readvcc()
// 1100mV*1024 ADC steps http://openenergymonitor.org/emon/node/1186
// override in your code with value for your specific AVR chip
// determined by procedure described under "Calibrating the internal reference voltage" at
// http://openenergymonitor.org/emon/buildingblocks/calibration

// to enable 12-bit ADC resolution on Arduino Due, 
// include the following line in main sketch inside setup() function:
//  analogReadResolution(ADC_BITS);
// otherwise will default to 10 bits, as in regular Arduino-based boards.
#ifndef EmonLib_h
#define EmonLib_h 
#define ADC_BITS    10     // разрядность АЦП
#define ADC_COUNTS  (1<<ADC_BITS)
class EnergyMonitor
{
  public:

    void voltage(unsigned int _inPinV, double _VCAL, double _PHASECAL);
    void current(unsigned int _inPinI, double _ICAL);
    void calcVI(unsigned int crossings, unsigned int timeout);
    double calcIrms(unsigned int NUMBER_OF_SAMPLES);
    long readVcc();
    //Useful value variables
    double realPower,
       apparentPower,
       powerFactor,
       Vrms,
       Irms;

  private:
    //Set Voltage and current input pins
    unsigned int inPinV;
    unsigned int inPinI;
    //Calibration coefficients
    //These need to be set in order to obtain accurate results
    double VCAL;
    double ICAL;
    double PHASECAL;

    //--------------------------------------------------------------------------------------
    // Variable declaration for emon_calc procedure
    //--------------------------------------------------------------------------------------
	int sampleV;  							 //sample_ holds the raw analog read value
	int sampleI;                     

	double lastFilteredV,filteredV;          //Filtered_ is the raw analog value minus the DC offset
	double filteredI;                  
	double offsetV;                          //Low-pass filter output
	double offsetI;                          //Low-pass filter output               

	double phaseShiftedV;                             //Holds the calibrated phase shifted voltage.
	double sqV,sumV,sqI,sumI,instP,sumP;              //sq = squared, sum = Sum, inst = instantaneous
	int startV;                                       //Instantaneous voltage at start of sample window.
	boolean lastVCross, checkVCross;                  //Used to measure number of times threshold is crossed.
};
#endif

Фото теплового насоа и блока.

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

Классно, вот бы еще видео вашей системы посмотреть!

pav2000
Offline
Зарегистрирован: 15.12.2014

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

А потом ничего интересного стоит и гудит в момент запуска компрессора свет мигает =))). Цифирки меняются, но тут надо понимать что и как что бы оценить качество работы насоса.

 

 

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

а зачем питание снимать от БП через резистор?

pav2000
Offline
Зарегистрирован: 15.12.2014

Tomasina пишет:

а зачем питание снимать от БП через резистор?

А затем,  что при 12 вольтах на уно стабилизатор греется не хило. И мне проще было воткнуть резистор чем менять блок.

В следующих конструкциях это было учтено .

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

Сам тепловой насос заводской или самодельный?

Хочу попробовать на дачу сделать отопление на тепловом насосе.

yucan
Offline
Зарегистрирован: 20.04.2015

Почитал в википедиии:

Для установки теплового насоса необходимы первоначальные затраты: стоимость насоса и монтажа системы составляет $300-1200 на 1 кВт необходимой мощности отопления. Время окупаемости теплонасосов составляет 4-9 лет, при сроке службы по 15-20 лет до капитального ремонта.

задумался...

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

При потреблении  2.5-2.8 кВт тепловой насос выдает 11-12 кВт тепла 
как такое может быть ?

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

SU-27-16 пишет:

При потреблении  2.5-2.8 кВт тепловой насос выдает 11-12 кВт тепла 
как такое может быть ?

щаз объясню - внимательно:

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

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

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

SU-27-16 пишет:

там - да !!!!!!!

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

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

3-мя kW-ми вытянуть 12 kW - это уж слишком дорого будет , вот я про чё....
долгосрочно - дёшево , да....

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

SU-27-16 пишет:

3-мя kW-ми вытянуть 12 kW - это уж слишком дорого будет , вот я про чё....
долгосрочно - дёшево , да....

тебе человек предоставил рабочий прототип - что тебе ещё нужно?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

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

SU-27-16 пишет:

там - да !!!!!!!

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

посчитал.... с 12-го этажа - очень дорого
:)-

toc
Offline
Зарегистрирован: 09.02.2013

SU-27-16 пишет:

При потреблении  2.5-2.8 кВт тепловой насос выдает 11-12 кВт тепла 
как такое может быть ?

я понимаю так:

Этот насос по устройтву похож на кондиционер или холодильник.
Он охлаждает мокрую землю (на глубине где грунтовые воды), имеющую высокую теплоёмкость и нагревает воздух в доме. Высасывает тепло из земли.
Нагревает дом как 12 кВт нагреватель.
А из розетки потребляет 3 кВт электроэнергии.

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

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

в Елизово от Елизово можно обогреть весь Сахалин...
не греют - бешенные бабки... бабло....

toc
Offline
Зарегистрирован: 09.02.2013

Рядом с морем проще из моря тепло выкачивать, мне кажется. Не знаю рядом ли.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Он охлаждает мокрую землю (на глубине где грунтовые воды) или льда немеренно
тут согласен !!!!!!!!!!!
но не в Рязани , а на Аляске.....

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

toc пишет:
Рядом с морем проще из моря тепло выкачивать, мне кажется. Не знаю рядом ли.

аха , прямо из Гольфстрима :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

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

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

SU-27-16 пишет:

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

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

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

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

SU-27-16 пишет:

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

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

так и дом разрушить можно :)-

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

SU-27-16 пишет:

Чем просить и унижаться , лучше спиздить газ и молчать !

А если нету газа? Есть только электричество.

К тому же у меня на даче грунтовые воды на глубине 2-3 метра.

inspiritus
Offline
Зарегистрирован: 17.12.2012

Автор молодец.

тепловой насос - тема.

Самое сложное в тн это прокладка в земле контура отбора тепла. Иногда в глубокие канавы кладут, иногда в вертикальные шурфы. Согласен ли с эитм автор?

Интересно , как сделал автор внешний контур и какой теплоноситель там применен ( рассол?)  ?

Какой компрессор применен (производитель, фазность)  ?

Какой хладагент?

Какой трв ( электронный?) ?

Как устроены теплообменники ( кожухотрубные или плстинчатые)?

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

inspiritus пишет:

Самое сложное в тн это прокладка в земле контура отбора тепла. 

Я хочу поробовать сделать 2 скважины и перекачивать с одной в другую через теплообменник.

Смотрел вчера на ебее вот такой теплообменник: http://www.ebay.com/itm/B3-12-60-Stainless-Steel-Plate-Heat-Exchanger-up-to-105-KW-Solar-Poel-Heater-NEW-/131639133044?hash=item1ea64dc374:g:114AAOSwBLlU2pMq

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

З.Ы. и еще мощность теплообменника удивила, 105 кВт...

pav2000
Offline
Зарегистрирован: 15.12.2014

Как автор темы постараюсь ответить на все вопросы.

1. Насос производства Казахстан (вот это поворот -))). Фирма sundue. Хозяин энтузиаст и фанат этого дела. Занимается этим уже лет 10. У него большое отлаженное производство с хорошим качеством. Как не странно Россия отстает в этом вопросе от Казахстана Украины и Прибалтики. Я по всем техническим вопросам общался с производителем лично, и онмнесильно помог. Производитель не против иодернизаций его изделий. Для меня это ценно.

2. Тепловой насос называется насосом по тому что он не вырабатывает тепло а перекачивает от более хододного тела к более горячему. По этому потратив 2.8 кв можно перекачать 12 кв тепла.

3. Геоконтур 5 скважин по 40 метров, в них без обсадной трубы запихнуты 2 32 мм пнд трубы в виде U. Все это соединено параллельно.

Если делать горизонтальный контур то выйдет дешевле. Но его надо делать на пустом участке и большего размера.

Да геоконтур это самый затратный момент. У меня вышло около 250 тыс на него.

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

Полюс стратегический запас образовался -)))

Решение стандартное для самодельщиков.

5. Компресор копланд. Использую однофазный. Но это моя ошибка. В дальнейшем перейду на три фазы. Всегда надо использовать трехфазные компрессоры с частотниками. Эффективность вырастает на 5 - 10 %. У однофазного 3 квт компрессора есть проблемы с пуском. Я их решил но это стоило денег.

6. Хладогент я не знаю какой.

7. Трв я не знаю кажись электронный.

8. Теплообменники паяные пластинчатые.

9. Мне тепловой насос обошелся около 500 тыс за все. Если брать под ключ на фирме будет около 1 млн. (С худшим качеством монтажа). Подключение газа в МО сейчас 500- 900 тыс. Соизмеримо с насосом.

Сейчас соотношение цены отопления электричество газ 5 к 1 у меня получилось 1 к 4. Можно выжать 1 к 4.5

В долгосрочной перспективе будет как в европе т.е 1 к 2 газ электричество. Газ будет дорожать для внутреннего потребления или газпром разорится.

Но дом должен быть хорошо утеплен. Иначе геоконтур будет большой и дорогой.

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

Сейчас жду изменения законодательства и тогда можно ставить солнечные батареи -))

 

 

 

inspiritus
Offline
Зарегистрирован: 17.12.2012

Скважины сами бурили, чем, каким диаметром?

А если применять медные трубы 3/4 - 1/2  и плети в четыре трубы( двойное U , вверх / вниз коленом)  не получилось бы сэкономить на скважинах ?

пластинчатый теплообменник главное не заморозить... 

pav2000
Offline
Зарегистрирован: 15.12.2014

Тима пишет:

inspiritus пишет:

Самое сложное в тн это прокладка в земле контура отбора тепла. 

Я хочу поробовать сделать 2 скважины и перекачивать с одной в другую через теплообменник.

Смотрел вчера на ебее вот такой теплообменник: http://www.ebay.com/itm/B3-12-60-Stainless-Steel-Plate-Heat-Exchanger-up-to-105-KW-Solar-Poel-Heater-NEW-/131639133044?hash=item1ea64dc374:g:114AAOSwBLlU2pMq

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

З.Ы. и еще мощность теплообменника удивила, 105 кВт...

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

1. Возможность скважин отдавать и принимать требуемый объем воды. На 10 кв это 2-3 куба в час. Не факт что скважина примет такой объем. Либо вода далеко тогда см п.2

2. Если вода далеко (более 10 метров) то потребуется мощный насос. Это киловаты. И эту мощность надо учитывать при рассчете эффективности системы.  СОР упадет и сильно.

3. Вода не абсолютно чистая и по этому теплообменники будут забиваться. Надо ставить фильтры а это приведет к росту мощности насоса. 

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

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

pav2000
Offline
Зарегистрирован: 15.12.2014

inspiritus пишет:

Скважины сами бурили, чем, каким диаметром?

А если применять медные трубы 3/4 - 1/2  и плети в четыре трубы( двойное U , вверх / вниз коленом)  не получилось бы сэкономить на скважинах ?

пластинчатый теплообменник главное не заморозить... 

Бурила бригада прялкой самодельной с промывкой. Диаметр около 150 мм (какой там ближайший стандартный).

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

Можно укладывать пнд в четыре трубы (двойной контур) при этом теплосъем увеличится на 5 10 %. Но главное будет резервирование контуров . Если я бы сейчас делал бы то сделал резервирование, доп расходы только пнд труба и рассол это около 40 тыс.

Сейчас появляются системы прямого испарения дх. Там нет одного теплообменника и в землю закапывается медь (маленький диаметр) с фреоном. Рабочие температуры при этом уходят в сильный минус(на это и рассчитано). Медь от корозии чем то покрывается или вообще используется аллюминий в оболочке. Все это уменьшает земляные работы. Но пока нет длительного опыта эксплуатации таких систем.

Цена не сильно уменьшается. Самыми дешовыми являются системы с горизонтальным контуром, или воздушные ТН.

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

На просторах нэта прочитал, что к нержавейке можно приварить медь аргоном. Это хорошо. 

Следующий вопрос: Как расчитать мощность теплообменников? У той, что по ссылке с ебея написано, поток 4 куба в час. Достаточно ли этого?

Компрессор на 3 фазы(до 2.2 квт) вроде можно запитать от однофазной сети через частотник.

pav2000
Offline
Зарегистрирован: 15.12.2014

Тима пишет:

На просторах нэта прочитал, что к нержавейке можно приварить медь аргоном. Это хорошо. 

Следующий вопрос: Как расчитать мощность теплообменников? У той, что по ссылке с ебея написано, поток 4 куба в час. Достаточно ли этого?

Компрессор на 3 фазы(до 2.2 квт) вроде можно запитать от однофазной сети через частотник.

Проще найти теплообменник нужный чем эксперементировить со сваркой. Соединение должно быть пластичным и не хрупким.

Мощность подсчитать просто

1. Требуемая мощность  считается на основе теплопотерь дома (есть определенные правила) У меня теплопотери 5 квт с учетом вентиляции около 6 квт. Для -26 градусов.

2. Снимаемая мощность с теплообменника = теплоемкость носителя х разность температур х объем   только надо не запутатся в единицах измерения. Разницу определяем при расчете холодильной машины и ее рабочих точек.

Про частотники я знаю, и буду использовать. В дальнейшем. Сейчас подключаю три фазы 15 квт к участку.

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

Теплоемкость носителя - это для воды или фреона?

pav2000
Offline
Зарегистрирован: 15.12.2014

Считается что для любой части теплообменника(мощности будут равны). Если считается для воды то теплоемкость  воды (у антифриза он кстати поменьше будет  на 10-30%)

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

А не могли бы Вы выложить фото узлов самого теплового насоса?

pav2000
Offline
Зарегистрирован: 15.12.2014

Тима пишет:

А не могли бы Вы выложить фото узлов самого теплового насоса?

Там все достаточно стандартно. К сожалению фоток узлов у меня нет. Даю ссылку на мою тему по поводу теплового насоса на специальном форуме. Дед марос на форуме это представитель моего производителя.

https://www.forumhouse.ru/threads/187858/page-16

Начинать надо с подбора компрессора по специализированним программам.

Прибалты продают комплекты для самосборки, достаточно дешево.

bwn
Offline
Зарегистрирован: 25.08.2014

pav2000, Пока у России есть Газпром, или у Газпрома Россия (тут дискуссионный вопрос) изменения законодательства в энергетической сфере, ждать не приходится((((. Газпрому это не надо.)))).

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

bwn пишет:

pav2000, Пока у России есть Газпром, или у Газпрома Россия (тут дискуссионный вопрос) изменения законодательства в энергетической сфере, ждать не приходится((((. Газпрому это не надо.)))).

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

bwn
Offline
Зарегистрирован: 25.08.2014

Насчет налога за кордоном на солн.батареи не знаю, знаю про кредиты на их установку и покупку излишков эл.энергии. у установивших. В итоге окупаемость в районе 5-10лет. Это у дойчев. А у нас да, солнечная в загоне, ветровая и био там же.
А самое интересное, где у частных домов муниципальная канализация?????))))).
Смотрим старый мультик "Чипполино": "Это безобразие, когды мы ввели налог на воздух, вы стали меньше дышать"(((((.

 

 

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

Вот про налог на солнечную энергию: https://www.youtube.com/watch?v=vrO6Em7YPpA

вот про налог на дождь: https://www.youtube.com/watch?v=d6Zc7gJbuTM

pav2000
Offline
Зарегистрирован: 15.12.2014

bwn пишет:

Насчет налога за кордоном на солн.батареи не знаю, знаю про кредиты на их установку и покупку излишков эл.энергии. у установивших. В итоге окупаемость в районе 5-10лет. Это у дойчев. А у нас да, солнечная в загоне, ветровая и био там же.
А самое интересное, где у частных домов муниципальная канализация?????))))).
Смотрим старый мультик "Чипполино": "Это безобразие, когды мы ввели налог на воздух, вы стали меньше дышать"(((((.

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

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

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Grid Tie inverter поможет вам не связываясь с продажей энергии выработанную отсылать в розетку.
Поэтому ваш счётчик будет считать  только разницу
между потреблённой нагрузкой  и выработанной солнцем( или другим источником)

Тима
Тима аватар
Offline
Зарегистрирован: 11.04.2013

trembo пишет:

Grid Tie inverter поможет вам не связываясь с продажей энергии выработанную отсылать в розетку.
Поэтому ваш счётчик будет считать  только разницу
между потреблённой нагрузкой  и выработанной солнцем( или другим источником)

Как быть когда разница отрицательная, т.е. потребляется 10 вт, а при этом системой вырабатывается 100 вт? Некоторым счетчикам по барабану прием или отдача, он считает походящий через него ток и он посчитает 90 вт при потреблении 10 вт. А потом докажи электросети что эти 90 вт ты отдал с веть, а не наоборот.

Есть счетчики, которые считают и прием и передачу отдельно. Вот тут да, нужен закон для населения. Для предприятий он есть, но "государство" не хочет конкурентов и всячески вставляет палки в колеса, чтоб не допустить использование любых электростанций, способных работать в сети и отдавать в нее электричество. Сам сталкивался с этой проблемой.

pav2000
Offline
Зарегистрирован: 15.12.2014

Изменен код передачи информации в головной блок (http://arduino.ru/forum/proekty/udalennyi-monitoring-za-datchikami-na-ma...)

Мелкие изменения кода.

Поменялся только файл lcd12864.ino

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

//#define DEMO                               // Признак демонстрации
#define RADIO                              // Признак использования радио модуля
#define VERSION "Ver. leOS2 1.47 181115"   // Текущая верстия
#define NRF24_CHANEL  100                       // Номер канала nrf24

// Конфигурация платы UNO (куда что подключается) --------------------------------
// Прерывания 
#define sensorInterrupt1    0                  // Первый датчик потока адрес прерывания
#define sensorInterrupt2    1                  // Второй датчик потока адрес прерывания
// ЦИФРОВЫЕ Ноги 
#define PIN_FLOW1           2                  // Первый датчик потока ножка на которую вешается датчик Холла
#define PIN_FLOW2           3                  // Второй датчик потока ножка на которую вешается датчик Холла
#define PIN_ST7920_SS1      4                  // ST7920 SS1
#define PIN_ENERGY_COUNT    5                  // Нога на которую заводится сигнал от электросчетчика (подсчет импульсов) используется аппаратный счетчик импульсов
#define PIN_ONE_WIRE_BUS    6                  // DS18b20 Нога на которой весят датчики температуры
#define PIN_ST7920_MOSI     7                  // ST7920 MOSI
#define PIN_ST7920_SCK      8                  // ST7920 SCK
// Беспроодный модуль NRF24L
#define PIN_SPI_CSN         9                  // NRF24L нога CSN выбор режима приема/передача
// Используем аппаратный SPI UNO
#define PIN_SPI_CE          10                 // NRF24L SPI сигнал SS1  – Slave-select 1 LCD
#define PIN_SPI_MOSI        11                 // NRF24L SPI сигнал MOSI – Master-out, Slave-in
#define PIN_SPI_MISO        12                 // NRF24L SPI сигнал MISO – Master-in, Slave out.
#define PIN_SPI_SCK         13                 // NRF24L SPI сигнал SCK  – Serial clock

// АНАЛОГОВЫЕ ноги
#define PIN_ANALOG_I        0                  // Нога на которую заводится ток от датчика (трансформатор тока)
#define PIN_ANALOG_V        1                  // Нога на которую заводится напряжение от датчика (220в)
#define PIN_KEY             16                 // Pin 16 = Analog in 2 Нога куда прицеплена кнопка 
#define PIN_LED_FLOW        17                 // Pin 17 = Analog in 3 Нога куда прицеплено реле потока (если замкнуто то поток есть) - светодиод и реле к ТП 1-2

#define READVCC_CALIBRATION_CONST 1103702L     // Калибровка встроенного АЦП (встроенный ИОН) по умолчанию 1126400 дальше измеряем питание и смотрим на дисплей 1103782L
#define NUM_SCREEN                5            // Число основных экранов
#define CALIBRATION_CONST_220     147.13       // Калибровка датчика напряжения 220 В 
#define CALIBRATION_CONST_220_I   10.03        // Калибровка датчика тока 220 A
#define EE_SAVED_ADDRESS          100          // Адрес записи данных eeprom
#define TIME_WRITE_EEPROM         60           // Период сохранения в eeprom МИНУТЫ!!!
#define eCONST                    1000         // Число импульсов на киловат/час электросчетчика

// Дополнительные библиотеки
#include <OneWire.h>           // OneWire библиотека
#include <leOS2.h>             // Шедуллер задач
#include "U8glib.h"            // Экран ЖКИ 128х64 по SPI
#include "rusFont.h"	       // Ресурс дополнительных фонтов
#include "BitMap.h"	       // Ресурс картинки для вывода на дисплей
#include "emonLib.h"           // Монитор электроэнергии
#include <avr/pgmspace.h>      // библиотека для использования  PROGMEM и F  - строковые константы в rom


 // Радио модуль NRF42l
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
    struct type_packet_NRF24               // Версия 2.0!! адаптация для stm32 Структура передаваемого пакета 32 байта - 32 максимум
    {
        byte id=0x00;                          // Идентификатор типа устройства - старшие 4 бита, вторые (младшие) 4 бита серийный номер устройства
        byte error;                            // Ошибка теплового насоса
        int16_t tOut1=-5000,tIn1=-5000;        // Текущие температуры ТП в сотых градуса !!! место экономим
        int16_t PowerFloor=0;                  // Мощность теплого пола  вт
        int16_t tOut2=-5000,tIn2=-5000;        // Текущие температуры ГК в сотых градуса !!! место экономим
        int16_t PowerLand=0;                   // Мощность геоконтура  вт
        int16_t I,U,P;                         // Ток в сотых ампера, напряжение в сотых вольта, мощность в вт.
//        uint8_t   count=0;                      // циклический счетчик отправленных пакетов нужен что бы на приемнике проверять качество связи
        char note[12] = "Heat pump";           // Примечание не более 11 байт + 0 байт Русские буквы в два раза меньше т.к. UTF-8
    };

#ifdef  RADIO    // Радио модуль NRF24
    const unsigned int  Time_RF24_send=5000;  // Длительность цикла посылки данных на сервер через радиомодуль (примерно- точность определяется стороживым таймером)
    type_packet_NRF24 packet;                 // пакет данных
    RF24 radio(PIN_SPI_CE,PIN_SPI_CSN);       // Создание структуры 
    const uint64_t pipes[2] = {0xF0F0F0F0E1LL,0xF0F0F0F0D2LL};
    bool send_packet_ok=false;                // признак удачной отправки последнего пакета 
    unsigned long tt=0;                       // Время пришедшее от головного блока если 0 то вроемя не приходило ничего не выводим
#endif 

// ----------------------------------------------------------------------  
boolean indicator = true;                   // Индикатор потока на дисплее - переменная для его анимации.
int fStart = 0;                             // Какой текущий экран вывода 0-стартовый
volatile byte ScreenResetCount=0;           // Для корректной работы экрана сброса кнопка должна быть нажата а затем отжата
volatile byte count=0;                      // Счетчик времени для записи в eeprom в минутах

const int  TimeMeasurement=9715;            // Длительность цикла измерения мсек  !! неточно дискретность 16 мксек
const int  TimeInterview=150;               // Длительность цикла опроса кнопок мсек
const unsigned int  TimeOneMinutes=58270;   // Длительность минутного цикла 65000 (unsigned int) 59100
const int  TEMPERATURE_PRECISION =12;       // разрешение датчика темературы в битах 9-12 бит
const float calibrationFactor = 0.435;      // Калибровочный коэфициент датчика потока 2-0.439 3-431
const float heat_capacity=4.191;            // Теплоемкость теплоносителя (вода 4.191)
 
volatile unsigned long oldTime=0;           // переменная для расчета interval
volatile long interval;                     // реальный интервал измерения (чуть больше TimeMeasurement особенность leOS2)
volatile long ChartInterval;                // реальный интервал вывода графика (чуть больше TimeChart особенность leOS2)
volatile unsigned long ChartOldTime=0;      // переменная для расчета ChartInterval
char buf[15];                               // буфер для вывода чисел на экран
byte oldKey=0;                              // Предыдущее знаение клавиши 
byte flagKey=1;                             // Флаг нажатия клавиши

// Электросчетчик -----------------------------
volatile unsigned long eCount=0;             // Счетчик импульсов от электросчетчика
volatile float ePower=0;                     // Пиковая мощность за TimeMeasurement
volatile float eEnergy=0;                    // Потребленная энергия
byte pChart[60];                             // Данные графика потеблемой мощности (датчики ток и напряжение)
byte ChartCOP[60];                           // Данные графика COP
volatile float pPower=0;                     // Пиковая мощность за TimeMeasurement
volatile float pEnergy=0;                    // Потребленная энергия

// Первый канал Теплые полы -------------------------------
const float errOut1=-0.10;                    // Ошибка первого датчика - вычитается из показаний 0.05
const float errIn1=-0.15;                     // Ошибка второго датчика - вычитается из показаний 0.07
byte ThermOut1[8] = {0x28,0xFF,0x37,0x7F,0x4A,0x04,0x00,0xCF};  // ТП обратка адрес датчика DS18B20 28FF377F4A0400CF закругленный конец 
byte ThermIn1 [8] = {0x28,0xBC,0x6B,0x3D,0x06,0x00,0x00,0x01};  // ТП подача адрес датчика DS18B20 28BC6B3D06000001 прямой конец  синий кембрик
volatile unsigned int pulseCount1=0;         // Счетчик импульсов первого датчика
volatile float flowRate1=0.0;                // Поток литров в минуту измеряется раз в минуту
volatile float totalLitres1=0.0;             // Общий объем прошедшей житкости в литрах Пишется во флеш каждый час
volatile float totalPower1=0.0;              // Общий объем тепла
volatile unsigned int count1 = 0;            // Число импульсов от датчика полученное за интервал измерения
volatile float HZ1=0.0;                      // Частота           
volatile float P1=0.0;                       // Мощность за секунду ТП
volatile float tOut1=-50,tIn1=-50;           // текущие температуры,
byte Chart1[60];                             // Данные первого графика (ТП)

// Второй канал Геоконтур ---------------------------
const float errOut2=-0.11;                    // Ошибка первого датчика - вычитается из показаний
const float errIn2=-0.05;                     // Ошибка второго датчика - вычитается из показаний
byte ThermOut2 [8]= {0x28,0x63,0x87,0x2b,0x06,0x00,0x00,0x2b};  // ТП обратка адрес датчика DS18B20 метка синия 
byte ThermIn2 [8] = {0x28,0x34,0x70,0x2b,0x06,0x00,0x00,0x77};  // ТП подача адрес датчика DS18B20 метка красная
volatile unsigned int pulseCount2=0;         // Счетчик импульсов первого датчика
volatile float flowRate2=0.0;                // Поток литров в минуту измеряется раз в минуту
volatile float totalLitres2=0.0;             // Общий объем прошедшей житкости в литрах Пишется во флеш каждый час
volatile float totalPower2=0.0;              // Общий объем тепла
volatile unsigned int count2 = 0;            // Число импульсов от датчика полученное за интервал измерения
volatile float HZ2=0.0;                      // Частота           
volatile float P2=0.0;                       // Мощность за секунду 
volatile float tOut2=-50,tIn2=-50;           // текущие температуры
byte Chart2[60];                             // Данные второго графика (ГК)

// Структура для записи в EEPROM
struct type_Counts                            // Тип данных - счетчики
{
    float GlobalEnergyP;                          //  Потребленная энергия с момента старта ТН - не сбрасывается ДАТЧИКИ ТОК И НАПРЯЖЕНИЕ в КИЛОВАТАХ
    float GlobalEnergyG;                          //  Выработанная энергия с момента старта ТН - не сбрасывается ДАТЧИКИ ТОК И НАПРЯЖЕНИЕ в КИЛОВАТАХ
    float YearEnergyP;                            //  Потребленная энергия с начала сезона отопления ТН - сбрасывается в КИЛОВАТАХ
    float YearEnergyG;                            //  Выработанная энергия с начала сезона отопления ТН - сбрасывается в КИЛОВАТАХ
    unsigned long GlobalHour;                     //  Мото часы (секунды) общие с момента старта ТН - не сбрасывается В СЕКУНДАХ
    unsigned long YearHour;                       //  Мото часы (секунды) общие с начала сезона отопления ТН - сбрасывается В СЕКУНДАХ
    unsigned long GlobalCountE;                   //  Потребленная энергия с момента старта ТН - не сбрасывается ЭЛЕКТРОСЧЕТЧИК  В ИМПУЛЬСАХ
    unsigned long YearCountE;                     //  Потребленная энергия с начала сезона отопления ТН - сбрасывается ЭЛЕКТРОСЧЕТЧИК В ИМПУЛЬСАХ
    float GlobalEnergyGeo;                        //  Потребленная энергия из геоконтура с момента старта ТН - не сбрасывается в КИЛОВАТАХ
    float YearEnergyGeo;                          //  Потребленная энергия из геоконтура с момента старта ТН - сбрасывается в КИЛОВАТАХ
}; 
volatile type_Counts CountsSRAM;                   // Рабочая копия счетчиков в памяти
type_Counts CountsEEPROM EEMEM;                    // Копия счетчиков в eeprom - туда пишем

volatile float EnergyP=0,EnergyG=0,EnergyGeo=0;    // промежуточные переменные
volatile unsigned long CountE=0;

// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ БИБЛИОТЕК
//U8GLIB_ST7920_128X64_4X u8g(PIN_SPI_SS1);          // Используем аппартный SPI но память минус 370 байт (увеличенный буфер на 4)скорость увеличивается где то на 100%
U8GLIB_ST7920_128X64_4X u8g(PIN_ST7920_SCK, PIN_ST7920_MOSI, PIN_ST7920_SS1, U8G_PIN_NONE); // Программный SPI и 4х буффер для скорости

leOS2 myOS;                                        // многозадачность
OneWire ds(PIN_ONE_WIRE_BUS);                      // поддержка температурных датчиков
EnergyMonitor emon1;                               // Мониторинг электросети

void setup(void) {
  u8g.setFont(my5x7rus);                // Русский шрифт 5х7
  // Установка входов-выходов и подтягивание внутренними резисторами
  pinMode(PIN_LED_FLOW, OUTPUT);        // Индикация потока светодиод и реле
  digitalWrite(PIN_LED_FLOW, HIGH);  
  pinMode(PIN_FLOW1, INPUT);            //  Подключение датчика потока 1
  digitalWrite(PIN_FLOW1, HIGH);
  pinMode(PIN_FLOW2, INPUT);            //  Подключение датчика потока 2
  digitalWrite(PIN_FLOW2, HIGH);
  pinMode(PIN_KEY, INPUT);              //  Включена кнопка
  digitalWrite(PIN_KEY, HIGH);
  pinMode(PIN_ENERGY_COUNT, INPUT);     //  Электросчетчик
  digitalWrite(PIN_ENERGY_COUNT, HIGH); 
 
 #ifdef  RADIO    // Радио модуль NRF42l  определение управляющих ног
    pinMode( PIN_SPI_CSN, OUTPUT);          
    digitalWrite( PIN_SPI_CSN, HIGH);
    pinMode( PIN_SPI_CE, OUTPUT);           
    digitalWrite(PIN_SPI_CE, HIGH);
 #endif 

  // Установка начальных переменных
  interval=TimeMeasurement;
  ChartInterval=TimeOneMinutes;  
  attachInterrupt(sensorInterrupt1, pulseCounter1, CHANGE);  // Прерывания на ОБА ФРОНТА
  attachInterrupt(sensorInterrupt2, pulseCounter2, CHANGE);
  
  myOS.begin();
  myOS.addTask(measurement,myOS.convertMs(TimeMeasurement));
  myOS.addTask(OneMinutes,myOS.convertMs(TimeOneMinutes));
     
// Программирование 1 таймера на подсчет событий на PIN_ENERGY_COUNT (туда заводится электросчетчик)
  TCCR1A = 0;   // сброс Timer 1 
  TCCR1B = 0; 
  TCNT1  = 0;  
  // start Timer 1 External clock source on T1 pin (D5). Clock on rising edge.
  TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12);
  
  emon1.voltage(PIN_ANALOG_V, CALIBRATION_CONST_220,1.7);  // Инициализация датчика напряжения 220
  emon1.current(PIN_ANALOG_I, CALIBRATION_CONST_220_I);    // Инициализация датчика тока 220
  
  // проверка на запуск экрана сброса
 if ((digitalRead(PIN_KEY)==0)&&(digitalRead(PIN_KEY)==0)) fStart=-1; // Установка признака стартового экрана
  // Чтение счетчиков из флеша
  //  AllResetEeprom(); // обнуление всех счетчиков только один раз в момент пуска системы
  readEeprom();
 
  #ifdef  RADIO    // Радио модуль NRF24
      //---ИНИЦИАЛИЗАЦИЯ РАДИО МОДУЛЯ ------------------------------------- 
  /*    
      radio.begin();
    // выбор скорости
      radio.setDataRate(RF24_250KBPS);
    //  radio.setDataRate(RF24_1MBPS);
    //  radio.setDataRate(RF24_2MBPS);
    radio.setPALevel(RF24_PA_MAX); // Максимальная мощность
    radio.setChannel(100);         //тут установка канала
    radio.setCRCLength(RF24_CRC_16);
    // radio.setAutoAck(false); // выключить аппаратное потверждение
    radio.setRetries(15,15);    // Задержка и число повторов
    radio.openWritingPipe(pipes[1]);   // Открываем канал передачи
    radio.openReadingPipe(1,pipes[0]); // Открываем канал приема  для получения подтверждения доставки пакета
  */
   radio.begin();
   radio.setDataRate(RF24_250KBPS);         //  выбор скорости RF24_250KBPS RF24_1MBPS RF24_2MBPS
   radio.setPALevel(RF24_PA_MAX);           // выходная мощность передатчика
   radio.setChannel(NRF24_CHANEL);          //тут установка канала
   radio.setCRCLength(RF24_CRC_16);         // использовать контрольную сумму в 16 бит
   radio.setAutoAck(true);                  // выключить аппаратное потверждение
// radio.enableDynamicPayloads();           // разрешить Dynamic Payloads
   radio.enableAckPayload();                // Разрешить ответ приемника AckPayload
   radio.setRetries(50,10);                 // Количество пауза и количество повторов 
  // Рекомендуют первые 2-4 байта адреса устанавливать в E7 или 18 он проще детектируется чипом
  radio.openWritingPipe(0xE7E7E7E7E1LL);    // передатчик 
  radio.openReadingPipe(1,0xE7E7E7E7D2LL);  // приемник
  radio.startListening();
    myOS.addTask(send_packet,myOS.convertMs(Time_RF24_send));  // Создание задачи по отправке пакетов
 #endif 
   }

// --------------------------------------------- LOOP ------------------------------------	 
void loop(void) {
  float t;
    // Старт преобразования датчиков время занимает до 0.7 секунды!!!!
    StartDS1820(ThermOut1);
    StartDS1820(ThermIn1);
    StartDS1820(ThermOut2);
    StartDS1820(ThermIn2);
    indicator=!indicator;   
 
    u8g.firstPage(); 
     do {
       // Общая часть для каждого экрана (для экономии длины кода) - заголовок экрана
       if (fStart>0)
        { 
          u8g.drawBox(0,0,128,9);  // Закрашиваем прямоугольник белым 
          u8g.setColorIndex(0);    // Черные чернила, Белый  фон
          u8g.setPrintPos(1, 7);
          u8g.print(int(fStart));
          u8g.drawLine(118, 0, 118, 8);  // Индикатор потока на экран и на реле
          if ((flowRate1>0)&&(flowRate2>0)) {digitalWrite(PIN_LED_FLOW, HIGH); 
            if (indicator==true) u8g.drawStr(121, 7,F("/")); else u8g.drawStr(121, 7,F("\\")); }// Светодиод и реле показывает что поток есть реле идет к ТН (1-2)
          else {digitalWrite(PIN_LED_FLOW, LOW); u8g.drawStr(121, 7,F("-"));}
          u8g.drawLine(98, 0, 98, 8);  // Индикатор потока на экран и на реле
          u8g.setPrintPos(100, 7);
          u8g.print(dtostrf(emon1.Vrms,3,0,buf)); // Вывод напряжения в строке состояния
            #ifdef  RADIO    // Радио модуль NRF42l ИНДИКАТОР ПЕРЕДАЧИ последнего пакета
                if (send_packet_ok==true)  u8g.drawXBMP(92, 1, 5, 7, antenna); else u8g.drawStr(92, 7,F("_"));
            #else
                u8g.drawStr(92, 7,F("-")); // радиомодуля нет выводим прочерк
            #endif 
           u8g.setPrintPos(8, 7);   // Далее сразу можно печатать заголовок
        }
       switch (fStart)
        {
        case -1:  ScreenReset(); break;  
        case  0:  ScreenStart(); break;
        case  1:  Screen1(); break;
        case  2:  Screen2(); break;
        case  3:  Screen3(); break;
        case  4:  Screen4(); break;
        case  5:  Screen5(); break;
        default:  Screen1();
        }
    
       } while( u8g.nextPage() );
       
       if (fStart==0) // Только один раз
         { delay(3000); myOS.addTask(scanKey,myOS.convertMs(TimeInterview)); } // Клавиатура активируется, начинается сканирование
        
       if (count>=TIME_WRITE_EEPROM) {writeEeprom();count=0;}  // Запись eeprom
       
        emon1.calcVI(40,2000);  // чтение датчиков тока и напряжения
   
        if (fStart>0 && myOS.getTaskStatus(scanKey)==0) myOS.restartTask(scanKey); //Борьба с зависаниями при переключении от кнопки - включение сканирования
        
        delay(350); 
        tOut1=VerificationTemp(tOut1,errOut1,ThermOut1);
        tIn1=VerificationTemp(tIn1,errIn1,ThermIn1);
        tOut2=VerificationTemp(tOut2,errOut2,ThermOut2);
        tIn2=VerificationTemp(tIn2,errIn2,ThermIn2);
  	}
     
   
float VerificationTemp(float newT,float errT, unsigned char *adrr)
{
 float t=getTempDS1820(adrr);
 if ((t>-15&&t<70&&abs(newT-t)<5)||(newT<-20)) t=t-errT;   // Иногда считывает глюки 
 return t;
} 
     
// Экран сброса настроек сезона --------------------------------------
void ScreenReset()
 {
  u8g.drawBox(0,0,128,9);  // Закрашиваем прямоугольник белым 
  u8g.setColorIndex(0);    // Черные чернила, Белый  фон
  u8g.drawStr(1, 7 , F("Сброс счетчиков сезона"));
  u8g.setColorIndex(1);
   
  u8g.drawStr(0, 16 , F("Выработка G кВт"));
  u8g.setPrintPos(84, 16);
  u8g.print(long(CountsSRAM.YearEnergyG));
    
  u8g.drawStr(0, 24 , F("Потреб. P кВт"));
  u8g.setPrintPos(84, 24);
  u8g.print(long(CountsSRAM.YearEnergyP));
   
  u8g.drawStr(0, 32 , F("Потреб. E кВт"));
  u8g.setPrintPos(84, 32);
  u8g.print(long(CountsSRAM.YearCountE/eCONST));  // импульсы в кВт
 
  u8g.drawStr(0, 40 , F("Наработка Часы"));
  u8g.setPrintPos(84, 40);
  u8g.print((unsigned int)(CountsSRAM.YearHour/60.0/60.0));
  
  u8g.drawLine(0, 46, 127, 46); 
  u8g.drawStr(0, 54 , F("СБРОС -  нажатие кнопки"));
  u8g.drawStr(0, 62 , F("ОТМЕНА - выключение"));
 
 // Опрос кнопки Сначало надо кнопку отпустить а потом нажимать
 if ((digitalRead(PIN_KEY)==1)&&(digitalRead(PIN_KEY)==1))  ScreenResetCount=1;   // кнопку отжали экран появился
 if ((digitalRead(PIN_KEY)==0)&&(digitalRead(PIN_KEY)==0)&&(ScreenResetCount==1)) // кнопку нажали и надо сбрасывать, простейшее подавление дребезка
 { fStart=1;  YearResetEeprom(); myOS.addTask(scanKey,myOS.convertMs(TimeInterview));}
 }   
// Стартовый экран --------------------------------------
void ScreenStart()
{
 u8g.setColorIndex(1);
 u8g.drawXBMP(0, 0, 56, 56, u8g_logo_bits); 
// u8g.drawXBMP(0, 0, 51, 51, aLogo); 
 u8g.drawStr(73, 8,  F("Контроль"));
 u8g.drawStr(70, 16, F("Теплового"));
 u8g.drawStr(78, 24, F("Насоса"));
 u8g.drawStr(66, 32, F("Arduino UNO"));
 #ifdef  RADIO    // Радио модуль NRF24
    u8g.drawStr(58, 41, F("Радио NRF24L"));
 #endif
 #ifdef  DEMO    // Демка
    u8g.drawStr(68, 52, F("-- DEMO --"));
 #endif
 u8g.drawStr(1, 63,F(VERSION));
}

// Отображение типа 1 ТЕПЛЫЙ ПОЛ-------------------------------------
void Screen1()
{
  byte i;
  u8g.print(F("Теплые Полы")); 
  u8g.setColorIndex(1);    // белые чернила, черный фон
  Screen12();
  u8g.setPrintPos(32, 16);
  u8g.print(dtostrf(flowRate1*60.0/1000.0,4, 3, buf));
  u8g.setPrintPos(95, 16);
  u8g.print(HZ1); 
  u8g.setPrintPos(8+14, 26); // Подача
  u8g.print(dtostrf(tOut1,4, 2, buf)); 
  u8g.setPrintPos(8+14, 26+9); // Обратка
  u8g.print(dtostrf(tIn1,4, 2, buf)); 
 
//  if (tOut1-tIn1<0) u8g.setPrintPos(8+13, 26+18); // Разность температур
//  else  u8g.setPrintPos(8+14+6, 26+9+9); 
   u8g.setPrintPos(8+14, 26+9+9);
  u8g.print(dtostrf((tOut1-tIn1),4, 2, buf));  // Всегда больше нуля

  u8g.drawBox(64,19,64,9);  // Закрашиваем прямоугольник белым 
  u8g.setColorIndex(0);     // Черные чернила, Белый  фон
  u8g.drawStr(111, 26, F("кВт"));
  u8g.setPrintPos(86, 26);
  u8g.print(dtostrf(P1,4, 2, buf));
  if (tOut1>tIn1) u8g.drawStr(64, 26, F("Наг."));  // Показ режима работы теплового насоса
  else            u8g.drawStr(64, 26, F("Охл."));
  
  u8g.setColorIndex(1);    
  u8g.setPrintPos(12, 54);
  u8g.print(dtostrf(totalLitres1/60.0/1000.0,11, 2, buf)); 
  u8g.setPrintPos(12, 63);
  u8g.print(dtostrf(totalPower1,11, 2, buf)); 
  
  // График
  // for(i=0;i<60;i++) u8g.drawPixel(65+i,63-Chart1[i]);     // Точки
  for(i=0;i<60;i++) u8g.drawLine(65+i,64,65+i,64-Chart1[i]); // Линия 0 не выводится
}
// Общие процедуры для первого и второго экранов - экономим rom --------------------------------
void Screen12()
{
  u8g.drawStr(0, 16, F("Поток:         Част:"));
  u8g.drawXBMP(58, 10, 9, 7, cub);
  u8g.drawXBMP(120, 10, 8, 7, Hz);
  u8g.drawLine(0, 18, 127, 18); 
  u8g.drawXBMP(0, 20, 21, 25, T123); // Термометр и значки
  u8g.drawXBMP(8+45, 26-6, 9, 7, C0);
  u8g.drawXBMP(8+45, 26-6+9, 9, 7, C0);
  u8g.drawXBMP(8+45, 26-6+9+9, 9, 7, C0);
  u8g.drawLine(63, 18, 63, 63); 
  u8g.drawLine(0, 46, 63, 46);
  u8g.drawStr(0, 54, F("V:"));
  u8g.drawStr(0, 63, F("G:"));
} 

// Отображение типа 2 ГЕО КОНТУР-------------------------------------
void Screen2()
{
  byte i;
  u8g.print(F("Гео контур")); 
  u8g.setColorIndex(1);    // белые чернила, черный фон
  Screen12();
  u8g.setPrintPos(32, 16);
  u8g.print(dtostrf(flowRate2*60.0/1000.0,4, 3, buf));
  u8g.setPrintPos(95, 16);
  u8g.print(HZ2); 
  u8g.setPrintPos(8+14, 26); // Подача
  u8g.print(dtostrf(tOut2,4, 2, buf)); 
  
  u8g.setPrintPos(8+14, 26+9); // Обратка
  u8g.print(dtostrf(tIn2,4, 2, buf)); 
 
 // if (tOut2-tIn2<0) u8g.setPrintPos(8+13, 26+9+9); // Разность температур
//  else  u8g.setPrintPos(8+14+6, 26+9+9); 
  u8g.setPrintPos(8+14, 26+9+9);
  u8g.print(dtostrf((tOut2-tIn2),4, 2, buf)); 
  
  u8g.drawBox(64,19,64,9);  // Закрашиваем прямоугольник белым 
  u8g.setColorIndex(0);     // Черные чернила, Белый  фон
  u8g.drawStr(111, 26, F("кВт"));
  u8g.setPrintPos(86, 26);
  u8g.print(dtostrf(P2,4, 2, buf));
  if (tOut2>tIn2) u8g.drawStr(64, 26, F("Наг."));  // Показ режима работы теплового насоса
  else            u8g.drawStr(64, 26, F("Охл."));
  
  
//  u8g.drawLine(63, 18, 63, 63); 
 
//  u8g.drawBox(64,19,63,9);  // Закрашиваем прямоугольник белым 
//  u8g.setColorIndex(0);     // Черные чернила, Белый  фон
//  u8g.drawStr(107, 26, F("кВт"));
//  u8g.setPrintPos(80, 26);
//  u8g.print(dtostrf(P2,4, 2, buf));
  u8g.setColorIndex(1);    
  
  u8g.setPrintPos(12, 54);
  u8g.print(dtostrf(totalLitres2/60.0/1000.0,11, 2, buf)); 
  u8g.setPrintPos(12, 63);
  u8g.print(dtostrf(totalPower2,11, 2, buf));
   // График
  // for(i=0;i<60;i++) u8g.drawPixel(65+i,63-Chart2[i]); 
  for(i=0;i<60;i++) u8g.drawLine(65+i,64,65+i,64-Chart2[i]); // 0 не выводится
   
}

// Отображение типа 3  Напряжение Ток-------------------------------------
void Screen3()
{
  int i;
  u8g.print(F("Напряжение&Ток"));
  u8g.setColorIndex(1);    // белые чернила, черный фон
  u8g.drawStr(0, 16, F("V rms:"));
  
  u8g.setPrintPos(31, 16);
  u8g.print(dtostrf(emon1.Vrms,4,1,buf));
  u8g.drawStr(0, 24, F("I rms:"));
  u8g.setPrintPos(31, 24);
  u8g.print(dtostrf(emon1.Irms,4,1,buf));
  u8g.drawStr(65, 16, F("Pow_f:"));
  u8g.setPrintPos(102, 16);
  u8g.print(dtostrf(emon1.powerFactor,3,2,buf));
  u8g.drawStr(0, 34, F("PW кВт:"));
  u8g.setPrintPos(39,34);
  u8g.print(dtostrf(abs(pPower),4, 2, buf));
  u8g.drawStr(75, 26, F("COP:"));
  u8g.setPrintPos(98, 26);
  if (pPower>0.500) u8g.print(dtostrf(P1/pPower,3,2,buf)); else u8g.print(dtostrf(0.0,3,2,buf));
  u8g.drawLine(63, 18, 63, 63); 
  u8g.drawLine(0, 26, 63, 26);
  u8g.drawLine(64, 18, 127, 18);
  
  //  for(i=0;i<=6;i++) u8g.drawPixel(62,64-i*4);  // Шкала мощность
  for(i=0;i<=5;i++)
  { u8g.drawPixel(64,64-i*7);   // Шкала СОР
    u8g.drawPixel(65,64-i*7);
  }
 
 for(i=0;i<60;i++) // График
    { 
     u8g.drawLine(i,64,i,64-pChart[i]);   
     u8g.drawLine(67+i,64,67+i,64-ChartCOP[i]); 
    }
}

// Отображение типа 4  Счетчики -------------------------------------
void Screen4()
{
  float temp;
  u8g.print(F("Счетчики")); 
  u8g.setColorIndex(1);    // белые чернила, черный фон
  
  u8g.drawLine(28, 9, 28, 63);
  u8g.drawLine(79, 9, 79, 63);
  u8g.drawLine(0, 43, 127, 43);
  u8g.drawStr(0, 16, F("        За сезон   Общий"));
  
  u8g.drawStr(0, 24, F("G кВт"));
  u8g.setPrintPos(31, 24);
  u8g.print(long(CountsSRAM.YearEnergyG));
  u8g.setPrintPos(82, 24);
  u8g.print(long(CountsSRAM.GlobalEnergyG));
  
  u8g.drawStr(0, 32, F("P кВт"));
  u8g.setPrintPos(31, 32);
  u8g.print(long(CountsSRAM.YearEnergyP));
  u8g.setPrintPos(82, 32);
  u8g.print(long(CountsSRAM.GlobalEnergyP));
  
  u8g.drawStr(0, 40, F("E кВт"));
  u8g.setPrintPos(31, 40);
  u8g.print(long(CountsSRAM.YearCountE/eCONST));  // импульсы в кВт
  u8g.setPrintPos(82, 40);
  u8g.print(long(CountsSRAM.GlobalCountE/eCONST)); // импульсы в кВт
  
  u8g.drawStr(0, 51, F("COP"));
  u8g.setPrintPos(30, 51);
  u8g.print(dtostrf((float)CountsSRAM.YearEnergyG/(float)CountsSRAM.YearEnergyP,4,2, buf));
  u8g.setPrintPos(81, 51);
  u8g.print(dtostrf((float)CountsSRAM.GlobalEnergyG/(float)CountsSRAM.GlobalEnergyP,4,2, buf));
  
  u8g.drawStr(30+22, 51, F(":"));
  u8g.drawStr(81+22, 51, F(":"));

  u8g.setPrintPos(30+26, 51);
  temp=(float)CountsSRAM.YearEnergyG/((float)CountsSRAM.YearCountE/(float)eCONST);
  if (temp<10.0) u8g.print(dtostrf(temp,4,2, buf));
      else u8g.print(F("-.-"));
  u8g.setPrintPos(81+26, 51);
  temp=(float)CountsSRAM.GlobalEnergyG/((float)CountsSRAM.GlobalCountE/(float)eCONST);
  if (temp<10.0) u8g.print(dtostrf(temp,4,2, buf));
      else u8g.print(F("-.-"));
  
  u8g.drawStr(0, 60, F("Часы"));
  u8g.setPrintPos(31, 60);
  u8g.print((unsigned int)(CountsSRAM.YearHour/60/60)); // Из секунд в часы
  u8g.setPrintPos(82, 60);
  u8g.print((unsigned int)(CountsSRAM.GlobalHour/60/60));
 }
 
// Отображение типа 5 Параметры  -------------------------------------
void Screen5()
{
  u8g.print(F("Параметры")); 
  u8g.setColorIndex(1);    // белые чернила, черный фон

  u8g.drawStr(0, 16, F("Питание UNO В"));
  u8g.setPrintPos(97, 16);
  u8g.print(dtostrf(emon1.readVcc()/1000.0,4, 3, buf));
    
  u8g.drawStr(0, 24, F("Температура чипа"));
  u8g.setPrintPos(97, 24);
  u8g.print(dtostrf(GetTemp(),4,2, buf));
  
  u8g.drawStr(0, 32, F("RAM free байт"));
  u8g.setPrintPos(97, 32);
  u8g.print(freeRam ()); 
  
  u8g.drawStr(0, 40, F("Таймера мс         :"));
  u8g.setPrintPos(65, 40);
  u8g.print(dtostrf(interval,5,0,buf));  
  u8g.setPrintPos(98, 40);
  u8g.print(dtostrf(ChartInterval,5,0,buf));  

  u8g.drawStr(0, 48, F("ТП err out/in"));
  u8g.setPrintPos(80, 48);
  u8g.print(dtostrf(errOut1,3, 2, buf));
  u8g.setPrintPos(108, 48);
  u8g.print(dtostrf(errIn1,3, 2, buf));
    
  u8g.drawStr(0, 56, F("Гео err out/in"));
  u8g.setPrintPos(80, 56);
  u8g.print(dtostrf(errOut2,3, 2, buf));
  u8g.setPrintPos(108, 56);
  u8g.print(dtostrf(errIn2,3, 2, buf));
  
  u8g.drawLine(103, 42, 103, 56); 
} 

// Прерывание подсчет импульсов от первого канала
void pulseCounter1() {   pulseCount1++; }
// Прерывание подсчет импульсов от второго канала
void pulseCounter2() {   pulseCount2++; }

// ОДНА СЕКУНДА Цикл измерения интервал задается -----------------------------------
void measurement()
{
 float intervalHour;           // интервал измерения в часах, используется для увеличения скорости
 cli();  // Запретить прерывания TimeMeasurement
 count1=pulseCount1;  pulseCount1 = 0;
 count2=pulseCount2;  pulseCount2 = 0;
 sei();  // разрешить прерывания
 
 interval=millis()-oldTime; // Точное определение интервала ----------------------------
 oldTime= interval+oldTime;  
 if (interval<=0) interval=TimeMeasurement; // Через 50 дней millis() сбросится по этому после этого первая итерация расчетная

 #ifdef  DEMO    // Демка
     count1=random(190,240); 
     count2=random(160,200);
     TCNT1= random(5,9);
     emon1.realPower=random(1900,2800);
 #endif

 intervalHour=((float)interval/1000.0)/3600.0;  // Предварительный расчет для оптимизации времени
 
 // Первый канал 
 HZ1=(float)(count1*1000.0)/interval/2; // делить на 2 - это т.к. прерывания работает на оба фронта импульса CHANGE
 flowRate1 = HZ1/calibrationFactor; // рассчитать поток в литрах за минуту
 totalLitres1 = totalLitres1 + flowRate1*(interval/1000.0); 
 P1=(flowRate1/60) // литры/килограммы в секунду
                   *heat_capacity*(abs(tOut1-tIn1)); 
 totalPower1 = totalPower1 + P1*intervalHour; 
 
 // Второй канал 
 HZ2=(float)(count2*1000.0)/interval/2; // делить на 2 - это т.к. прерывания работает на оба фронта импульса CHANGE
 flowRate2 = HZ2/calibrationFactor; // рассчитать поток в литрах за минуту
 totalLitres2 = totalLitres2 + flowRate2*(interval/1000.0); 
 P2=(flowRate2/60) // литры/килограммы в секунду
                   *heat_capacity*(abs(tOut2-tIn2)); 
 totalPower2 = totalPower2 + P2*intervalHour; 
 
 // Электросчетчик
 eCount=eCount+TCNT1;                                        // Общий счетчик
 ePower=(float)TCNT1*3600.0/(float)eCONST/(interval/1000.0); // Пиковый счетчик
 eEnergy=(float)eCount/(float)eCONST ;
 TCNT1 = 0;
 
 // Датчик напряжения и тока
 pPower=emon1.realPower/1000.0;         // Киловатты
 pEnergy=pEnergy+pPower*intervalHour;   // Потребленная энергия
 }

// Сканирование клавиш ------------------------------------------
void scanKey()
{
    byte key;  
    // cli();                                                         // Запретить прерывания TimeMeasurement
    key=digitalRead(PIN_KEY);                                         // Прочитать кнопку
    // sei();                                                         // разрешить прерывания
    if ((key==1)&&(oldKey==1)&&(flagKey==1)) {fStart++;flagKey=0;}    // Клавиша нажита
    if ((key==0)&&(oldKey==1))
        { flagKey=1;                           // Начало (по заднему фронту) ожидания нового нажатия 
         myOS.pauseTask(scanKey);              // Сканирование кнопки поставить на паузу, а то иногда висла задача
        }
    oldKey=key;
    if (fStart > NUM_SCREEN) fStart=1;
}

// РАЗ В МИНУТУ Подготовка массива точек для графиков и счетчиков ----------------------------------------
void OneMinutes()
{
 int i;
 float dP,dG,dGeo;
 unsigned long dE;
 
 count++;                                            // счетчик минут для записи eeprom
 
 ChartInterval=millis()-ChartOldTime;                // Точное определение интервала показа графика----------------------------
 ChartOldTime= ChartInterval+ChartOldTime;  
 if (ChartInterval<=0) ChartInterval=TimeMeasurement; // Через 50 дней millis() сбросится по этому после этого первая итерация расчетная
  // Сдвиг графиков и запись новых данных
  for(i=0;i<60;i++) 
     {  
      Chart1[i]=Chart1[i+1]; 
      Chart2[i]=Chart2[i+1];
      pChart[i]=pChart[i+1];
      ChartCOP[i]=ChartCOP[i+1];
     }
    Chart1[59]=P1*2.5;
    Chart2[59]=P2*2.5;
    pChart[59]=9*pPower; 
    if (pPower>0.500) ChartCOP[59]=(P1/(pPower))*7.0; else ChartCOP[59]=0;
     
 // Подготовка  накопительныч счетчиков для записи в eeprom ----------------------------------------------------
 // работают только если есть поток т.е. ТН работает!!!!! простой не учитывается СПОРНО надо думать
 
 //  Электричество
 dP=pEnergy-EnergyP;                  // Прирост 
 EnergyP=pEnergy;                     // запоминание для нового цикла
 CountsSRAM.GlobalEnergyP =CountsSRAM.GlobalEnergyP+dP;
 CountsSRAM.YearEnergyP   =CountsSRAM.YearEnergyP+dP;

 // Тепло ТП
 dG= totalPower1-EnergyG;  // Прирост за час
 EnergyG=totalPower1;      // запоминание для нового цикла
 CountsSRAM.GlobalEnergyG =CountsSRAM.GlobalEnergyG+dG;
 CountsSRAM.YearEnergyG   =CountsSRAM.YearEnergyG+dG;
 
 // Тепло ГЕО контур
 dGeo= totalPower2-EnergyGeo; // Прирост за час
 EnergyGeo=totalPower2;      // запоминание для нового цикла
 CountsSRAM.GlobalEnergyGeo =CountsSRAM.GlobalEnergyGeo+dGeo;
 CountsSRAM.YearEnergyGeo   =CountsSRAM.YearEnergyGeo+dGeo;
 
 // Мото часы В секундах!!!!!!!!!!!!
 CountsSRAM.GlobalHour=CountsSRAM.GlobalHour+ChartInterval/1000; // в секундах
 CountsSRAM.YearHour=CountsSRAM.YearHour+ChartInterval/1000;     // в секундах
 
 // Электросчетчик
 dE=eCount-CountE;                   // Прирост электросчетчика
 CountE=eCount;                      // запоминание для нового цикла
 CountsSRAM.GlobalCountE =CountsSRAM.GlobalCountE+dE;
 CountsSRAM.YearCountE   =CountsSRAM.YearCountE+dE;
}

 // ---ПЕРЕДАЧА ДАННЫХ ЧЕРЕЗ РАДИОМОДУЛЬ -----------------------------
void send_packet()
{
#ifdef  RADIO    // Радио модуль NRF42l  
  packet.tOut1=100*tOut1;
  packet.tIn1=100*tIn1;
  packet.tOut2=100*tOut2;
  packet.tIn2=100*tIn2;
  packet.PowerFloor=P1*1000;
  packet.PowerLand=P2*1000;
  packet.I=emon1.Irms*100;
  packet.U=emon1.Vrms*100;
  packet.P=pPower*1000;
    myOS.pauseTask(send_packet);   // Остановить эту задачу а то при отсутствии связи идет сброс arduino
    
 /*   
        radio.stopListening();     // Остановить приемник
    //    radio.flush_tx();          // Очистить буфер
        send_packet_ok = radio.write(&packet,sizeof(packet));
        radio.startListening();    // Включить приемник
   */
        radio.powerUp();
        radio.stopListening();     // Остановить приемник
        delay(2);
        cli();
          radio.writeBlocking(&packet,sizeof(packet),200);  // Writes 1 payload to the buffers
          send_packet_ok=radio.txStandBy();
          if ( radio.isAckPayloadAvailable() )   // Ждем получения -- основной блок передает текущее время
          radio.read(&tt,sizeof(tt));            //... и имеем переменную tt с временем от приемника.
        sei(); 
        radio.startListening();    // Включить приемни 
    myOS.restartTask(send_packet); // Запустить задачу
  #endif  
 }  


// Старт преобразования одного датчика -----------------------------------------------
void StartDS1820(byte *addr)
{
   ds.reset();
   delay(10);
   ds.select(addr);
   delay(10);
   ds.write(0x44,0);
   delay(10);  
}
// Чтение температуры одного датчика -----------------------------------------------
float getTempDS1820(unsigned char *addr)
{
    byte i;
    byte type_s;
    byte present = 0;
    byte data[12];
    // Запрос уже послан ранее StartDS1820
    present = ds.reset();
    ds.select(addr);
    ds.write(0xBE); // Команда на чтение регистра температуры
    for ( i = 0; i < 9; i++) { data[i] = ds.read();}
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
     raw = raw << 3; // 9 bit resolution default
     if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;      // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  return (float)raw / 16.0;       
}

// Чтение внутреннего датчика температуры ---------------------------------------
double GetTemp(void)
{
  unsigned int wADC;
  double t;
  ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
  ADCSRA |= _BV(ADEN);  
  delay(20);           
  ADCSRA |= _BV(ADSC);  
  while (bit_is_set(ADCSRA,ADSC));
  wADC = ADCW;
  t = (wADC - 324.31 ) / 1.22;
  return (t); 
}
// Чтение свободной памяти --------------------------------------------------------------------
int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}
//----------------------------EEPROM FUNCTION--------------------------------------------------
void writeEeprom()
{ 
cli(); 
  eeprom_write_block((const void*)&CountsSRAM, (void*) &CountsEEPROM, sizeof(CountsSRAM)); 
sei();
}
// Полный сброс делается только один раз
void AllResetEeprom()
{
 CountsSRAM.GlobalEnergyP  =0;                       
 CountsSRAM.GlobalEnergyG  =0;                        
 CountsSRAM.YearEnergyP    =0;                          
 CountsSRAM.YearEnergyG    =0;                         
 CountsSRAM.GlobalHour     =0;                          
 CountsSRAM.YearHour       =0;  
 CountsSRAM.GlobalCountE   =0;                       
 CountsSRAM.YearCountE     =0;   
 CountsSRAM.GlobalEnergyGeo=0;
 CountsSRAM.YearEnergyGeo  =0;
 writeEeprom(); 
}
// Сброс только последнего сезона
void YearResetEeprom()
{
 CountsSRAM.YearEnergyP    =0;                          
 CountsSRAM.YearEnergyG    =0;                         
 CountsSRAM.YearHour       =0;  
 CountsSRAM.YearCountE     =0;   
 CountsSRAM.YearEnergyGeo  =0;
 writeEeprom(); 
}

//Чтение счетчиков из Eeprom 
void readEeprom()
{
cli(); 
   eeprom_read_block((void*)&CountsSRAM, (const void*) &CountsEEPROM, sizeof(CountsSRAM)); 
sei();
}


Фотки информационных экранов. Тепловой насос работает и греет дом -)) В доме +22 за бортом -4

 

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Тима пишет:

Как быть когда разница отрицательная, т.е. потребляется 10 вт, а при этом системой вырабатывается 100 вт? Некоторым счетчикам по барабану прием или отдача, он считает походящий через него ток и он посчитает 90 вт при потреблении 10 вт. А потом докажи электросети что эти 90 вт ты отдал с веть, а не наоборот.

Есть счетчики, которые считают и прием и передачу отдельно. Вот тут да, нужен закон для населения. Для предприятий он есть, но "государство" не хочет конкурентов и всячески вставляет палки в колеса, чтоб не допустить использование любых электростанций, способных работать в сети и отдавать в нее электричество. Сам сталкивался с этой проблемой.

По барабану быть не может. Он не просто считает ток.

Счётчик считает АКТИВНУЮ энергию.  Её мощьность равна   U x I x cosF.
    При нашей почти активной нагрузке cosF болтается около "1"
    При нашей генерации cosF около " - 1 ".  Минус, Карл
   Счётчик- это мотор переменного тока .
   К тому-же способный крутится в обратную сторону.
   Если в нём нет блокировки обратного вращения то вы будете его "отматывать" своей энергией.
   Если есть- он будет стоять пока вы не станете потреблять больше чем вырабатываете.

pav2000
Offline
Зарегистрирован: 15.12.2014

"Счётчик- это мотор переменного тока ."  Это механический счетчик  который сейчас вытесняются электронными.

"К тому-же способный крутится в обратную сторону."  Механический счетчик БЕЗ храпового механизма.

Да такие сетчики бывают в природе (у меня был такой у него 4 разряда было - за год можно легко через ноль перегнать) НО уже лет 30 не выпускаются.

И никакой электрик его не введет в эксплуатацию. Сейчас такие счетчики стоят в "глухих деревнях" но у них разрешенная мощность обычно 3 кВт. Т.е вариант чисто теоритический. И любые хотелки с электриками начинаются с их требования заменить счетчик.

Счетчики способные ШТАТНО мотать в обе стороны существуют но их кране мало (кажется называются либо двухвходовые или ходовые ). А атестованные ростестом вообще еденицы.

Будет закон будут и сразу появятся нужные счетчики.

А пока я использую тепловой насос с  средним СОР 4.4-4.6  т.е  у меня электрическое отопление но при этом тариф /4.5 .

Надеюсь опимизировать до 5 -))

 

pav2000
Offline
Зарегистрирован: 15.12.2014

Выложил проект на Гитхаб  https://github.com/pav2000/ControlHP.git

Михаил-893
Offline
Зарегистрирован: 13.01.2021

Добрейшего всем!
Интересное устройство, буду повторять.
Прошу прощения за совсем нубский вопрос.
А зачем тут и на гитхабе два файла ino? С основным понятно, а вот emonLib.ino для чего?