Четырехразрядный семисегментный индикатор на 74HC595

andryn
Offline
Зарегистрирован: 08.06.2018

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

Схема: 

Не очень "красивое" соединение между HC595 и индикатором обусловлено наличием микросхем в DIP корпусе желанием сделать одностороннюю плату с минимумом перемычек.

Плата получилась такая:

Код оформил в виде библиотеки:

Файл SevenSegmentDigitsDisplay.h

 

/*
   Описание библиотеки для работы с индикатором с общим катодом и двумя сдвиговыми регистрами 74НС595
*/
#ifndef SevenSegmentDigitsDisplay_H
#define SevenSegmentDigitsDisplay_H

#include <Arduino.h>

#define INDICATOR_DIGITS 4   //Количество разрядов индикатора
#define INDICATOR_SYMBOLS 16 //Количество описанных символов, включая минус, точку и тп

class SevenSegmentDigitsDisplay
{
   public:
      // Инициализация дисплея. Задаются пины для clock, latch, data
      SevenSegmentDigitsDisplay(int clock_pin, int latch_pin, int data_pin);
      
      // Функция для перерисовки дисплея
      // Должна вызываться регулярно в loop
      void indicateValue();
   
      // Функция для расчета значениий по разрядам.
      // Вызывается только при изменении отображаемого значения. Точность по умолчанию 0.
      void calculateValue(float val);
      void calculateValue(float val, byte prec);
   
      // Функция для для установки конкретного символа в разряд. Разряд от 0 до INDICATOR_DIGITS. Символ от 0 до INDICATOR_SYMBOLS из symbols[INDICATOR_SYMBOLS].
      // Установленное значение будет затерто при вызове calculateValue
      void setDiditValue(byte digit, byte symbol);
   
   private:
      int _clock; // SHCP отвечает за ШИМ. Когда 1 из данных забирается бит, 0 пропускается. Синхронизация потока. На 74HC595 пин 11
      int _latch; // STCP  отвечает за защелкивание. Когда биты переданы, посылаем сигнал, что окончили передачу. На 74HC595 пин 12
      int _data;  // DS отвечает за поток битов(данные). На 74HC595 пин 14
      byte _currentDigit; //Текущий отображаемый разряд индикатора
      byte _countDigitInication; //Количество показов подряд одного разряда. Нужно, чтобы частота выключения была много меньше частоты свечения.
      byte values[INDICATOR_DIGITS+1]; //Массив для значений индикатора по разрядам + 1 значение, соотв. разряду с точкой
   
};

#endif /* SevenSegmentDigitsDisplay_H */

Файл SevenSegmentDigitsDisplay.cpp 

/*
   Описание библиотеки для работы с индикатором с общим катодом и двумя сдвиговыми регистрами 74НС595
*/
#include "SevenSegmentDigitsDisplay.h"

#if defined(SevenSegmentDigitsDisplay_H)

const byte digits[INDICATOR_DIGITS] = {  //Массив значений для разрядов. Подключение q3->1, q2->2, q1->3, q4->4. Разряд зажигается низким уровнем.
   //3214 // Выводы 3,2,1,4 74HC595 на разряды 1,2,3,4 индикатора. Если будет 8-разрядный индикатор, то нужно добатить еще 4 значения
   B11110111,
   B10111111,
   B11011111,
   B11101111
}; //Пины для управления разрядами индикатора. 0 - низкий уровень подать на катод.

const byte symbols[INDICATOR_SYMBOLS] = { //Массив значений для различных символов, подключение q0->G, q1->C, q2->DP,..,q7->B, индикатор с общим катодом
  //GC.DEAFB  //Подключение выводов 74HC595 к индикатору
   B01011111, //0
   B01000001, //1
   B10011101, //2
   B11010101, //3
   B11000011, //4
   B11010110, //5
   B11011110, //6
   B01000101, //7
   B11011111, //8
   B11010111, //9 
   B00000000, //  (пусто)
   B00100000, //. (точка) 
   B10000000, //- (минус) 
   B10011110, //E 
   B10001000, //r 
   B11001011  //H 
};

SevenSegmentDigitsDisplay::SevenSegmentDigitsDisplay(int clock_pin, int latch_pin, int data_pin) {
   _clock = clock_pin;
   _latch = latch_pin;
   _data = data_pin;
   pinMode(_clock, OUTPUT);
   pinMode(_latch, OUTPUT);
   pinMode(_data, OUTPUT);
   _currentDigit = 0;
   _countDigitInication = 0;
}

// Функция для расчета значениий по разрядам.
// Вызывается только при изменении отображаемого значения. Точность по умолчанию 0.
void SevenSegmentDigitsDisplay::calculateValue(float val){
   //Точность по умолчанию равна 0
   calculateValue(val, 0);

}

void SevenSegmentDigitsDisplay::calculateValue(float val, byte prec){
   byte i = INDICATOR_DIGITS;
   //Зачистить все значения
   while (i--) {
      values[i] = 10;
   }
   
   long intval = (long)(val * pow(10, prec));
   if (intval >= 0) {
      i = INDICATOR_DIGITS;
   }
   else {
      i = INDICATOR_DIGITS - 1; //Если число отрицательное, то 1 разряд занимает минус
   }
   
   //Проверим влезает точность и число в разряды индикатора 
   if (prec >= i || intval > (long)pow(10, i)) {
      values[2] = 13;
      values[1] = 14;
      values[0] = 14;
      return;
   }
   
   values[INDICATOR_DIGITS] = prec; //Поставить точку в нужном месте
   
   //Если все влезло, распределим число по разрядам
   byte prevval = 10; //Значение предыдущего старшего разряда, чтобы убрать ведущие нули
   i = INDICATOR_DIGITS;
   while (i--) {
      values[i] = intval / pow(10, i);
      intval = intval - values[i] * pow(10, i);
      //Уберем ведущие нули
      if (prevval == 10 && values[i] == 0) {
         values[i] = 10;
      }
      prevval = values[i];
   }
}

// Функция для перерисовки дисплея
// Должна вызываться регулярно в loop
void SevenSegmentDigitsDisplay::indicateValue(){
   if (!_countDigitInication) {
      //
      _countDigitInication++;
      return;
   }
   byte symbol = symbols[values[_currentDigit]]; //Выбрать символ для отображения из таблицы символов
   if (values[INDICATOR_DIGITS] && values[INDICATOR_DIGITS] == _currentDigit) { //Нужно поставить точку в текущем разряде
      symbol |= symbols[11];
   }
   //Погасить все разряды
   digitalWrite(_latch, LOW);
   shiftOut(_data, _clock, LSBFIRST, B00000000); // Символы
   shiftOut(_data, _clock, LSBFIRST, B11111111); //Разряды
   digitalWrite(_latch, HIGH);

   //Для начала записи в 74HC595 нужно подать 0 на STCP (открыть)
   digitalWrite(_latch, LOW);
   // С данными выпускаем поток битов на DS  синхроннированные с SHCP
   // Показать нужный символ
   shiftOut(_data, _clock, LSBFIRST, symbol);
   // Зажечь нужный разряд
   shiftOut(_data, _clock, LSBFIRST, digits[_currentDigit]);
   // Когда последний бит передали, закрываем
   digitalWrite(_latch, HIGH);
   
   // Перейти к следующему разряду
   _currentDigit++;
   _currentDigit = _currentDigit % INDICATOR_DIGITS;   
}

// Функция для для установки конкретного символа в разряд. Разряд от 0 до INDICATOR_DIGITS. Символ от 0 до INDICATOR_SYMBOLS из symbols[INDICATOR_SYMBOLS].
// Это значение будет затерто при вызове calculateValue
void SevenSegmentDigitsDisplay::setDiditValue(byte digit, byte symbol){
   if (digit < INDICATOR_DIGITS) {
      values[digit] = symbol;
   }
}

#endif

Файл для теста DigitsIndicator.ino 

#include "SevenSegmentDigitsDisplay.h"

volatile float dfreq;
unsigned long tm;

SevenSegmentDigitsDisplay disp(2, 3, 4);

void setup() {
  // put your setup code here, to run once:
   Serial.begin(115200);        // connect to the serial port
   Serial.println("Test begin");
   
   dfreq = 123.0;
   disp.calculateValue(dfreq, 1); //Заполнить значение для индикатора
   tm = millis();
}

void loop() {
  // put your main code here, to run repeatedly:
   disp.indicateValue();
   
   if (millis()-tm > 200) {
      tm = millis();
      dfreq = dfreq + 0.1;
      Serial.println(dfreq);
      disp.calculateValue(dfreq, 1);
      
      //disp.setDiditValue(3,15);
   }

}

Библиотека работает с положительными и отрицательными числами. Так же позволяет устанавливать спец. символы, типа H, E и т.п. 

Если кому-то нужно, могу выложить проект в KiCad для модификации под другой индикатор или под два четырехразрядных индикатора.

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

 

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

andryn пишет:
Принимаю здоровую критику по улучшению платы и кода

7 резисторов (или 8 с точкой) на сегментах были бы лучше чем 4 общих. Хотя, дело вкуса, пожалуй. С моей стороны - сие значимо т. к. я даже th резисторы ставлю с той же стороны платы, как smd.

andryn
Offline
Зарегистрирован: 08.06.2018

Voodoo Doll пишет:

7 резисторов (или 8 с точкой) на сегментах были бы лучше чем 4 общих. Хотя, дело вкуса, пожалуй. С моей стороны - сие значимо т. к. я даже th резисторы ставлю с той же стороны платы, как smd.

Согласен, зря экономил :) . Уже заметил, что 1 получается ярче, чем 8. Наверно переделаю.

Еще по программе обнаружил, что зря сначала гашу все разряды. Это лишнее, только занимает время.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Voodoo Doll пишет:

7 резисторов (или 8 с точкой) на сегментах были бы лучше чем 4 общих. Хотя, дело вкуса, пожалуй. 

Да, нет, не дело вкуса - это грубая схемотехническая ошибка.

andryn
Offline
Зарегистрирован: 08.06.2018

ЕвгенийП пишет:

Да, нет, не дело вкуса - это грубая схемотехническая ошибка.

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andryn пишет:

Грубая - это когда все сгорело, 

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

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

andryn
Offline
Зарегистрирован: 08.06.2018

ЕвгенийП пишет:

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

В даташите максимальный прямой ток через 1 сегмент = 25мА. 5В/220Ом = 23мА, поэтому ничего не сгорит. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

Теперь по поводу Вашего расчёта

andryn пишет:

5В/220Ом = 23мА, поэтому ничего не сгорит. 

Вы не учли падение напряжения на светодиоде. Допустим - 2В. Значит ток у Вас не 23мА, а всего лишь 14мА. Причём не через сегмнент, а через общий вывод. Т.е. это на 8 светодиодов (если будет цифра 8 с точкой). Не маловато? По 1,75 на брата?

Кстати, если будете увеличивать ток, то не забывайте, что у 595 ограничение 70мА на корпус, т.е. если Вы захотите сделать, скажем хоть по 10мА на светодиод, то Ваш верхний 595-ый будет работать с перегрузкой (при "8 с точкой" - все 80мА). Так что там тоже считайте внимательно.

andryn
Offline
Зарегистрирован: 08.06.2018

ЕвгенийП пишет:

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

Я вроде же написал, что "Согласен, зря экономил".

Спасибо за комментарий.

 

andryn
Offline
Зарегистрирован: 08.06.2018

Переделал на 8 резисторов. Пришлость изменить пару соединений между индикатором и 74HC595.

Соответственно немного изменилась библиотека.

Схема:

Плата:

Код SevenSegmentDigitsDisplay.cpp

/*
   Описание библиотеки для работы с индикатором с общим катодом и двумя сдвиговыми регистрами 74НС595
*/
#include "SevenSegmentDigitsDisplay.h"

#if defined(SevenSegmentDigitsDisplay_H)

const byte digits[INDICATOR_DIGITS] = {  //Массив значений для разрядов. Подключение q3->1, q2->2, q1->3, q4->4. Разряд зажигается низким уровнем.
   //3214 // Выводы 3,2,1,4 74HC595 на разряды 1,2,3,4 индикатора. Если будет 8-разрядный индикатор, то нужно добатить еще 4 значения
   B11110111,
   B10111111,
   B11011111,
   B11101111
}; //Пины для управления разрядами индикатора. 0 - низкий уровень подать на катод.

const byte symbols[INDICATOR_SYMBOLS] = { //Массив значений для различных символов, подключение q0->G, q1->C, q2->E,..,q7->B, индикатор с общим катодом
  //GCED.AFB  //Подключение выводов 74HC595 к индикатору
   B01110111, //0
   B01000001, //1
   B10110101, //2
   B11010101, //3
   B11000011, //4
   B11010110, //5
   B11110110, //6
   B01000101, //7
   B11110111, //8
   B11010111, //9 
   B00000000, //  (пусто) [10]
   B00001000, //. (точка) [11]
   B10000000, //- (минус) [12]
   B10110110, //E         [13]
   B10100000, //r         [14]
   B11100011  //H         [15]
};

SevenSegmentDigitsDisplay::SevenSegmentDigitsDisplay(int clock_pin, int latch_pin, int data_pin) {
   _clock = clock_pin;
   _latch = latch_pin;
   _data = data_pin;
   pinMode(_clock, OUTPUT);
   pinMode(_latch, OUTPUT);
   pinMode(_data, OUTPUT);
   _currentDigit = 0;
   _countDigitInication = 0;
}

// Функция для расчета значениий по разрядам.
// Вызывается только при изменении отображаемого значения. Точность по умолчанию 0.
void SevenSegmentDigitsDisplay::calculateValue(float val){
   //Точность по умолчанию равна 0
   calculateValue(val, 0);

}

void SevenSegmentDigitsDisplay::calculateValue(float val, byte prec){
   byte i = INDICATOR_DIGITS;
   //Зачистить все значения
   while (i--) {
      values[i] = 10;
   }
   
   long intval = (long)(val * pow(10, prec));
   if (intval >= 0) {
      i = INDICATOR_DIGITS;
   }
   else {
      i = INDICATOR_DIGITS - 1; //Если число отрицательное, то старший разряд занимает минус
      values[3] = 12;   //Поставить минус в старший разряд
      intval = -intval; //Сделать число положительным
   }
   
   //Проверим влезает точность и число в разряды индикатора 
   if (prec >= i || intval > (long)pow(10, i)) {
      values[3] = 10; //Пусто
      values[2] = 13; //E
      values[1] = 14; //r
      values[0] = 14; //r
      values[INDICATOR_DIGITS] = 0;
      return;
   }
   
   values[INDICATOR_DIGITS] = prec; //Поставить точку в нужном месте
   
   //Если все влезло, распределим число по разрядам
   byte prevval = 10; //Значение предыдущего старшего разряда, чтобы убрать ведущие нули
   
   while (i--) {
      values[i] = intval / pow(10, i);
      intval = intval - values[i] * pow(10, i);
      //Уберем ведущие нули
      if (prevval == 10 && values[i] == 0) {
         values[i] = 10;
      }
      prevval = values[i];
   }
}

// Функция для перерисовки дисплея
// Должна вызываться регулярно в loop
void SevenSegmentDigitsDisplay::indicateValue(){
   if (_countDigitInication++ != 32) {
      return;
   }
   _countDigitInication = 0;
   byte symbol = symbols[values[_currentDigit]]; //Выбрать символ для отображения из таблицы символов
   if (values[INDICATOR_DIGITS] && values[INDICATOR_DIGITS] == _currentDigit) { //Нужно поставить точку в текущем разряде
      symbol |= symbols[11];
   }
   
   //Для начала записи в 74HC595 нужно подать 0 на STCP (открыть)
   digitalWrite(_latch, LOW);
   // С данными выпускаем поток битов на DS  синхроннированные с SHCP
   // Показать нужный символ
   shiftOut(_data, _clock, LSBFIRST, symbol);
   // Зажечь нужный разряд
   shiftOut(_data, _clock, LSBFIRST, digits[_currentDigit]);
   // Когда последний бит передали, закрываем
   digitalWrite(_latch, HIGH);
   
   // Перейти к следующему разряду
   _currentDigit++;
   _currentDigit = _currentDigit % INDICATOR_DIGITS;   
}

// Функция для для установки конкретного символа в разряд. Разряд от 0 до INDICATOR_DIGITS. Символ от 0 до INDICATOR_SYMBOLS из symbols[INDICATOR_SYMBOLS].
// Это значение будет затерто при вызове calculateValue
void SevenSegmentDigitsDisplay::setDiditValue(byte digit, byte symbol){
   if (digit < INDICATOR_DIGITS) {
      values[digit] = symbol;
   }
}

#endif

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andryn пишет:

Переделал на 8 резисторов.

Ну, я же Вам писал

ЕвгенийП пишет:
считайте внимательно.

Давайте посчитаем, что Вы сделали:

Резисторы у Вас по 510 ом. Хорошо. Падение напряжения на светодиоде считаем 2В (хотя, если он красный, то там даже меньше - 1,8В). Таким образом ток через светодиод (5-2) / 510 = 5,88мА. Если мы включаем все 8  сегментов (цифра "8" с точкой), то ток через общий провод разряда получается 5,88 * 8 = 47мА. Значит, через пины 1-4 нижнего по схеме сдвигового регистра может идти до 47 мА. Пока правильно?

Теперь открываем даташит на сдвиговый регистр и читаем "absolute maximum ratings" ... "Continuous output current, IO (VO = 0 to VCC)  -  ±35 mA".

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

andryn
Offline
Зарегистрирован: 08.06.2018

ЕвгенийП пишет:

Т.е. Вы на треть превышаете ток, заявленный как абсолютный максимум

Согласен. В военное время необходимо использовать резисторы не менее 1K, но для гражданского применения сойдет и 510, т.к. светятся они не долго и по очереди.

Схема для военного применения:

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Мне почему-то кажется, что вы не очень-то рады замечаниям, хотя сами о них просили. Если чё, так Вы скажите, у меня есть чем заняться, кроме как помогать Вам.

Для военного времени Ваша схема не очень подходит. 3 мА на светодиод - яркость-то слабенькая, при ярком свете (от ядерной вспышки, например) ни хрена не видно будет.

У Вас же у нижнего регистра четыре выхода пропадают, кто Вам мешает запараллелить по два вместе? ну, если боитесь, то через маленький резистор типа 1 Ом? Если Вы так сделаете, то можно ещё и увеличить яркость, используя резисторы не 510 Ом, а 390 Ом - вполне достаточно. Ток восьми светодиодов будет 8*3/390 - 62мА - всё укладывается.

Это как раз то, о чём я Вам говорил - "считайте внимательнее". Удачи!

andryn
Offline
Зарегистрирован: 08.06.2018

ЕвгенийП пишет:

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

Почему не рад? Очень даже рад. Очень здравые замечания.

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

Будет вариант "для долговременного постоянного использования в светлое время суток в странах с тропическим климатом".

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

Если автор ещё не спит.

В библиотеку можно было бы и обработку переменной вставить.

Индикатор четырёхразрядный показывает первые четыре числа с плавающей запятой и гашением незначащих нолей допустим в течение 1,5 сек. А следующие 1,5 сек показывает знак числа и показатель степени.

Алгоритм примерно такой:

Если Х>999 999 999 пишем Err

Если Х < -999 999 999 пишем -Err

Если Х < 0.000 000 001 пишем 0,0,0,0,

Если Х > 9999  то Х/1000 и показатель степени d = d+3

Повторяем, если надо.

Если Х < 0.0001 то Х= Х*1000 и показатель степени d = d -3

Если Х<999  то Х =Х*10 и число разряда десяток ставим с запятой.

С сотнями также.

Всё. 

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

Я такой алгоритм сотворил. Учебным быдлокодом. Вот библиотеку сотворить нет опыта.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Муж_Долговой пишет:

Если автор ещё не спит.

Гляньте на дату последнего сообщения в теме :)

andryn
Offline
Зарегистрирован: 08.06.2018

Муж_Долговой пишет:

Если автор ещё не спит.

....

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

Я такой алгоритм сотворил. Учебным быдлокодом. Вот библиотеку сотворить нет опыта.

Ну почему же спит... Уже проснулся :)

Схема, плата, код библиотеки в этом сообщении: 

 
Попробуйте исправить под свою задумку. Добавьте функцию SevenSegmentDigitsDisplay::calculateAnyValue, которая будет заполнять values нужными значениями.
Для того, чтобы реализовать показ степени через 1,5 секунды придется править SevenSegmentDigitsDisplay::indicateValue() в вводить какие-нибудь флаги.
Выкладывайте сюда, что получится. Совместно допилим.
 
 
Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018
[code]
// Двухдиапазонный Омметр. 
   const int dataPin = 2;     //14Пин подключен к DS входу 74HC595
   const int latchPin = 3;     //12Пин "защелки" первого регистра подключен к ST_CP входу первого регистра отвечающего за сегменты 
   const int clockPin = 4;    //11Пин подключен к SH_CP входу 74HC595
 const int relePin = 11;//Пин на реле
 const int battonPin = 12; // Пин на кнопку
 const int sensorPin = 15;   //Аналоговая переменная
 int  t=0, s=0, d=0, e=0,  z=0, g=10, j=10,f=1;   //объявляем переменные для подготовки числа
 const float omm = 100000;
 const float hande = 100;
 float v;
     const int sex = 1500; 
    unsigned long loopTime; 
byte SegDisplay; // переменная для вывода символов на индикаторе
byte RazrDisplay; // переменная для включения разрядов
//      Соответственно { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , _,  P, U,   S,  H,  - , E,  r,  d,  C}
   const byte digits[]={192,249,164,176,153,146,130,248,128,144,255,140,193,146,137,191,134,175,161,198,
                        64, 121,36, 48, 25, 18, 2,  120, 0, 16,}; //массив цифр, генерирующий из сегментов цифры с запятой.
         const byte digitRpins[]={1,2,4,8};//массив цифр, указывающий разряд
   void setup() { DDRD = 28; //Обозначаем пины от сдвиговых регистров как выходы
                 DDRB = 8;}
         // Serial.begin(9600); }        
   void loop() {
        g = 10, z = 0, j = 10, t = 0, s = 0, d = 0, e = 0; // Обнуление регистра порта D
        int value = analogRead(sensorPin);  // читаем аналоговый пин A1
        int rele = digitalRead (battonPin);
               digitalWrite (relePin, rele);
    //  Раскомментить после наладки
        /*   if (rele == HIGH) { 
              v = value * hande / (1023 - value);} 
          else {
             v = value * omm / (1023 - value);} */
            // v = 3568459; // тестовое число. После наладки закомментить или совсем удалить
            // v = - 0.00123456; //второе тестовое 
             v = - 0.0123456;   // третье тестовое
             
   if (v < 0){
     g = 15; // знак числа "-"
     v = - v; }
        if (v > 9999999 | v <= 0.01){
         t=g, s=16, d=17, e=17; }  // Принт "_Err"
   else {
     if (v >= 10000){
     v = v / 1000 ;
     z = z + 3;   }    // Показатель степени
         if (v < 10)  {
            v = v * 1000 ;
            z = z - 3;  }
    if (v >= 100 && v < 1000)  {
      v = v * 10 ;
      d = 20; }   // "," десяток
           if (v >= 10 && v < 100){
             v = v * 100 ;
             s = 20;   // "," сотен
             d = 0;  }
    if (z <0 ){
      j = 15;   //Знак степени 
      z = z * (-1); } 
             t = v / 1000; 
             e = v - t * 1000; 
         int sp = e / 100;  // Вспомогательная переменная
             e = e - sp * 100; 
         int dp = e / 10;    // Вспомогательная переменная
          e = e - dp * 10;
             s = s + sp;
             d = d + dp;
          unsigned long   currentTime = millis ();
       if (currentTime >= (loopTime + sex)) {
          f = - f;
          loopTime = currentTime;}
       if (f > 0 && z != 0) {
             t = g;//знак числа
              s = 18; //знак "d"
               d = j; // знак степени
                 e = z;} // степень
   }
       Indicate(0, t);
          Indicate(1, s);    
             Indicate(2, d);
                 Indicate(3, e);}
   
      void Indicate(int y,int x){
          SegDisplay=digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
          RazrDisplay=digitRpins[y];  // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
       digitalWrite(latchPin, LOW);  // устанавливаем синхронизацию "защелки" на LOW
        shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда)
        shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay);  // Записываем информацию для первого регистра (Номер символа)
       digitalWrite(latchPin, HIGH);}  //"защелкиваем" регистр, тем самым устанавливая значения на выходах
       // Только я не умею библиотеки сочинять. Да и нельзя такое увековечивать. Это же не код. Ужастик.
[/code]