Вольтметр avr своими руками

Простой вольтметр на AVR на 50, 5 и 0.3В

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

Схема измерительного прибора

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

Схема измерительного прибора

Делитель напряжения R2, R3 позволяет измерять напряжения больше 5ти вольт. Для измерения малых напряжений входной сигнал пропускается через операционный усилитель DA2 с регулируемым коэффициентом усиления. Его коэффициент усиления задается резисторами R4, R5. Для измерения тока на входе прибора должен быть установлен шунт R1.
Основой схемы служит микроконтроллер Atmega8. После преобразования уровня сигнала он поступает на вход АЦП, встроенного в микроконтроллер. Микроконтроллер выводит полученное значение на трехразрядном сегментном индикаторе с общим анодом. Напряжение на аноды разрядов поступает через транзисторы. Резисторы в эмиттерах R9, R10, R11 задают яркость индикатора. Способ индикации — динамический.
Питание можно подавать напрямую от источника напряжения 5В, либо через стабилизатор. Обратите внимание, что минус питания и минус измерительного входа соединены друг с другом.

Печатная плата

Плата измерительного прибора

Плата односторонняя и содержит все элементы измерительного прибора. Резистор R1 (шунт амперметра) имеет несколько посадочных мест для корпусов разной мощности. Файл с платой, нарисованной в формате Sprint-Layout 5.0 можно скачать по ссылке.

Программа

При включении устройства в течении двух секунд на индикатор выводится приветствие «HI», после чего начинается работа прибора. В AVR-микроконтроллерах используется 10-ти разрядный АЦП. В нашем проекте мы используем только девять разрядов. Эта разрядность позволяет получить конечную приборную точность 1%. Для большей стабильности и плавности изменения показаний берется выборка из ста отсчетов и на дисплей выводится наибольший из них. Если входное напряжение превышает диапазон измеряемых значений на индикатор выводится сообщение: -0. Третий разряд не включается, если он не используется.
HEX-фал для каждой версии свой. Мы будем их прикладывать к каждой версии отдельно. Фьюз-биты всегда должны оставаться заводскими. Прошивка загружается через стандартный 6ти-пиновый разъем ISP-программирования.

Технические характеристики

  • напряжение питания, 5В либо 7-12В
  • потребляемый ток, не более 60мА
  • частота обновления индикатора, 56Гц
  • пределы измерения, 0.5В, 5В, 50В
  • входное сопротивление, не менее 10кОм
  • точность, не менее, 10%

Вольтметр на 50В

Для сборки вольтметра с пределом измерения 50В нужно установить все элементы, кроме R1, R4, R5, DA2. Если вы не планируете использовать нестабилизированное питание, то можно не устанавливать также конденсатор C1 и стабилизатор DA1.

Плата вольтметра на 50В

После сборки плата с лицевой стороны выглядит так:

Вольтметр на 50В. Лицевая сторона

…и с обратной стороны:

Вольтметр на 50В. Обратная сторона

Элементы схемы на предел 50В:

  1. C2 — танталовый конденсатор, 22мкФ, 16В T491C226K016AT, 1шт.
  2. C1,C3,C4 — конденсаторы на 0,1мкФ в корпусе 0805
  3. DA1 — стабилизатор L7805 в корпусе D2PAK, 1шт.
  4. DD1 — микроконтроллер Atmega8a-au, 1шт.
  5. J1 — чип-резистор 1206 с сопротивлением 0 Ом, 1шт. (перемычка)
  6. HL1 — сегментный индикатор BA56-12YWA, 1шт. (желательно устанавливать через колодку)
  7. R2 — подстроечный резистор CA6V на 2,5кОм, 1шт
  8. R3 — чип-резистор 0805 на 10кОм, 1шт.
  9. R6-R8, R12 — чип-резисторы 0805 на 1кОм, 4шт.
  10. R9-R11 — чип-резисторы 0805 на 56Ом, 3шт. (можно взять с меньшим сопротивлением для увеличения яркости)
  11. VT1-VT3 — транзисторы BC807-40, 3шт.
  12. Гребенка PLS-контактов

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


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

Вольтметр на 5В

На плату необходимо установить следующие элементы:

  1. C2 — танталовый конденсатор, 22мкФ, 16В T491C226K016AT, 1шт.
  2. C1,C3,C4 — конденсаторы на 0,1мкФ в корпусе 0805
  3. DA1 — стабилизатор L7805 в корпусе D2PAK, 1шт.
  4. DD1 — микроконтроллер Atmega8a-au, 1шт.
  5. J1 — чип-резистор 1206 с сопротивлением 0 Ом, 1шт. (перемычка)
  6. HL1 — сегментный индикатор BA56-12YWA, 1шт. (желательно устанавливать через колодку)
  7. R2 — подстроечный резистор CA6V на 25кОм, 1шт
  8. R3 — чип-резистор 0805 на 1кОм, 1шт.
  9. R6-R8, R12 — чип-резисторы 0805 на 1кОм, 4шт.
  10. R9-R11 — чип-резисторы 0805 на 56Ом, 3шт. (можно взять с меньшим сопротивлением для увеличения яркости)
  11. VT1-VT3 — транзисторы BC807-40, 3шт.
  12. Гребенка PLS-контактов

Фактически отличаются только сопротивления резисторов в делителе напряжения R2, R3.
Прошивку для версии вольтметра на 5В можно скачать здесь. Фьюз-биты оставляем без изменения. Отличие этой прошивки от предыдущей только в положении разрядной точки.
Видео работы вольтметра на 5В:

Вольтметр на 300мВ

Для работы с пределом измерения от 0 до 300мВ потребуется дополнительный каскад на микросхеме LM358N. Принципиальная схема при этом принимает следующий вид:

Схема вольтметра на 300мВ

Резисторы R4, R5 задают коэффициент усиления усилителя. R1 необходим для того, чтобы в отсутствии входного сигнала вольтметр показывал 0В.
Элементы платы:

  1. C2 — танталовый конденсатор, 22мкФ, 16В T491C226K016AT, 1шт.
  2. C1,C3,C4 — конденсаторы на 0,1мкФ в корпусе 0805
  3. DA1 — стабилизатор L7805 в корпусе D2PAK, 1шт.
  4. DA2 — операционный усилитель L358N в корпусе SO8, 1шт.
  5. DD1 — микроконтроллер Atmega8a-au, 1шт.
  6. J1 — чип-резистор 1206 с сопротивлением 0 Ом, 1шт. (перемычка)
  7. HL1 — сегментный индикатор BA56-12YWA, 1шт. (желательно устанавливать через колодку)
  8. R1 — чип-резистор 0805 на 10кОм, 1шт.
  9. R4 — чип-резистор 0805 на 1кОм, 1шт.
  10. R5 — подстроечный резистор CA6V на 25кОм, 1шт
  11. R6-R8, R12 — чип-резисторы 0805 на 1кОм, 4шт.
  12. R9-R11 — чип-резисторы 0805 на 56Ом, 3шт. (можно взять с меньшим сопротивлением для увеличения яркости)
  13. VT1-VT3 — транзисторы BC807-40, 3шт.
  14. Гребенка PLS-контактов

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

Предосторожности в работе и особенности эксплуатации

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

  1. Вольтметр рассчитан только для измерения постоянного напряжения
  2. У вольтметра нет встроенной защиты от смены полярности входного напряжения
  3. Измерения производятся относительно напряжения питания. Другими словами стабильность питающего напряжения определяет точность показаний вольметра.
  4. У вольтметра нет защиты по входу. Не стоит подавать на него напряжения больше предельного
  5. Вход вольметра не имеет гальванической развязки. Если вы питаете основную схему и предложенный вольтметр от одного и того же источника питания измерения можно производить только относительно общего провода. В случае, когда необходимо измерить разность потенциалов между двумя точками на которых есть напряжение, необходимо использовать для питания вольтметра отдельный источник питания с гальванической развязкой через трансформатор. И при этом обязательно подключать минус вольтметра к точке с меньшим напряжением!
  6. Если необходимо увеличить яркость индикатора, можно уменьшить сопротивление резисторов R9-R11. Однако не стоит ставить сопротивление меньше 20Ом
  7. Если вы планируете использовать вольтметр для индикации бортового напряжения в автомобиле вам потребует подключить только два провода: минус автомобиля к «GND» вольтметра, а плюсовой провод к выводам разъема «7-12V» и «+»
Читайте также:  Как сделать тонкий галстук своими руками

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

Источник

Схема

Логика программы

Структура проекта

Драйвер семисегментного индикатора

//куда подключены сегменты
#define PORT_IND PORTB
#define DDR_IND DDRB

#define SEG_A 0
#define SEG_B 1
#define SEG_C 2
#define SEG_D 3
#define SEG_E 4
#define SEG_F 5
#define SEG_G 6
#define SEG_DP 7

//куда подключены упр. выводы
#define PORT_TR PORTD
#define DDR_TR DDRD

#define NUM1 0
#define NUM2 1
#define NUM3 2
#define NUM4 3

void IND_Init( void );
void IND_Output( unsigned int value, unsigned char comma);
void IND_Update( void );

Прототипы функций находятся в заголовочном файле, а их реализации в сишном.

Функция инициализации

//количество разрядов индикатора
#define AMOUNT_NUM 4

//буфер семисегментного индикатора
unsigned char buf[AMOUNT_NUM];

void IND_Init( void )
<
PORT_IND = 0xff;
DDR_IND = 0xff;

PORT_TR |= (1 for ( unsigned char i = 0; i //массив для преобразования десятичных чисел в коды индикатора
unsigned char number[] =
<
(1 //0
(0 //1
(1 //2
(1 //3
(0 //4
(1 //5
(1 //6
(1 //7
(1 //8
(1 //9
>;

void IND_Output( unsigned int value, unsigned char comma)
<
unsigned char tmp;
for ( unsigned char i = 0; i if (comma //макросы для настройки драйвера индикатора под другую схему
#define LightOutAll() PORT_TR &=

((1 #define BurnDigit(port, digit) port |= (1 #define ValueBuf() buf[count]

void IND_Update( void )
<
static unsigned char count = 0;

//гасим все разряды
PORT_IND = 0;
LightOutAll();

//зажигаем соответствующий разряд
if (count == 0) BurnDigit(PORT_TR, NUM1);
else if (count == 1) BurnDigit(PORT_TR, NUM2);
else if (count == 2) BurnDigit(PORT_TR, NUM3);
else BurnDigit(PORT_TR, NUM4);

//выводим код цифры в порт
PORT_IND = ValueBuf();

count++;
if (count == AMOUNT_NUM) count = 0;
>

(1 #define ValueBuf() buf[count]

индикатор с общим катодом подключенный к микроконтроллеру с помощью транзисторов
#define LightOutAll() PORT_TR &=

((1 #define BurnDigit(port, digit) port |= (1 #define ValueBuf() buf[count]

индикатор с общим анодом подключенный напрямую к микроконтроллеру
#define LightOutAll() PORT_TR &=

((1 #define BurnDigit(port, digit) port |= (1 #define ValueBuf()

индикатор с общим анодом подключенный к микроконтроллеру с помощью транзисторов
#define LightOutAll() PORT_TR |= (1 #define BurnDigit(port, digit) port &=

(1 #define ValueBuf()

Полный текст драйвера светодиодного семисегментного индикатора

Как вычисляется напряжение

Uadc = Uin*R14/(R14 + R15) = 30В*82 /(82 + 910) = 2,48 В

Чтобы вычислить напряжение на входе вольтметра нужно результат преобразования АЦП пересчитать в напряжение и домножить на коэффициент

(R14 + R15)/R14 = 992/82

Напряжение на входе АЦП — Uadc вычисляется по формуле:

Uadc = value * 2,56/(2^n – 1),

где n – разрядность АЦП, value – цифровое значение напряжения

Отсюда напряжение на входе вольтметра будет равно:

Uin = (value * 2,56 * 992)/(82 * 1023) = (value * 30,96)/1023

Чтобы не связываться с типом float и при этом иметь возможность вычислять напряжение с точностью до 2-ух знаков после запятой, числитель этой формулы я домножил на 100

Uin = (value * 3096)/1023

Тест вольтметра

Результаты вы можете видеть в таблице. Первая колонка – это напряжение выставляемое на источнике питания, вторая — показания мультиметра Fluke, а третья – цифровой вольтметр на ATmega8.

Источник

Вольтметр/амперметр для лабораторного БП


В ходе размышлений над проектом лабораторного блока питания решил я немного поизучать возможности AVR в качестве измерителя напряжения и тока. Как известно, контроллеры серии ATMega имеют 10-разрядный АЦП, который можно использовать для измерения.

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

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

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

Итак, что же мы имеем?


Примечание к схеме: на каждый вывод порта B нужно привесить резистор, у меня 680 Ом.

Прибор собран на контроллере ATMega8 в корпусе TQFP-32, это дает нам 2 дополнительных входа АЦП. Обвеса минимум, буквально один блокировочный конденсатор по питанию. Тактирование — внутренняя RC-цепочка на 8 Мгц.

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

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

Вторая задача, которую пришлось решать — источник опорного напряжения. AVR позволяет использовать 3 источника — напряжение питания, встроенный ИОН 2,56В или внешний AREF. Напряжение питания показалось мне недостаточно стабильным, а встроенный ИОН — маловатым, для измерения 30В будет слишком большой коэффициент деления. К тому же была информация о недостаточной точности этого источника.

Читайте также:  Вертикальный зажим своими руками

Для упрощения расчетов я решил сделать простой ИОН на 5.12В на TL431.

Точное значение опорного напряжения устанавливается многооборотным подстроечником R2, делитель для измерения напряжения тоже дополнен подстроечником R6, потому что точных резисторов необходимого номинала у меня нет. Если у вас есть, вы можете пересчитать под другие номиналы. К тому же, в результате борьбы за точность я изменил максимальное входное напряжение до 32В, так что подстроить оказалось легче, чем перепаивать.

Теперь перейдем к программированию. Здесь есть две задачи: перейти от отсчетов АЦП к вольтам и повысить точность измерения.

После нескольких вариантов пересчета я остановился на следующем.
Задаемся максимальным выходным значением 30.0В, десятичную запятую выкидываем, получается 300. Записываем степени двойки до максимального значащего разряда нашего АЦП и смотрим, какие степени в сумме составляют наше число: 256+32+8+4==300. Теперь, чтобы получить весь диапазон, нужно сделать: value=(ADC>>1)+(ADC>>4)+(ADC>>6)+(ADC>>7);
Удобно для этого пользоваться каким-нибудь табличным редактором, у меня, например, OpenOffice Calc:

Вот тут-то и вылазят все ошибки точности и округления.

Для повышения точности хорошо бы применить программные методы, например оверсемплинг, потому что 10 бит недостаточно даже для одной цифры после запятой в диапазоне 0-30В.
Для того, чтобы поднять разрядность на N бит, нужно сделать 4^N измерений и затем сумму этих измерений поделить на 2^N, то есть сдвинуть вправо N раз.
По-хорошему, нужно добавить еще шум, но я пока решил обойтись без этого.
Код:

Ну и напоследок, несколько фото:
Напряжение, больше 10В:

Напряжение, меньше 10В:

Ток:

Снизу:

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

PS: кстати, в исходнике есть функция BCDSlow. Она, по-идее, должна быть BCDfast, но на малых значениях проигрывает обычному вычитанию. Я ее переводил с пиковского ассемблера, там она получается быстрая, по сути, все делается сдвигами и сложениями и в циклах получается не больше 9 итераций на каждый десятичный разряд, но на С что-то не заладилось. Можете глянуть на предмет оптимизации.

Комментарии ( 43 )

Прибор собран на контроллере ATMega8 в корпусе TQFP-32, это дает нам 2 дополнительных входа АЦП.

Для того, чтобы поднять разрядность на N бит, нужно сделать 4^N измерений и затем сумму этих измерений поделить на 2^N

А смысл? Все равно ADC0-ADC5 не задействованы.

потому что 10 бит недостаточно даже для одной цифры после запятой в диапазоне 0-30В.

octave:1> 30/1024
ans = 0.029297

около 3 сотых вольта на один разряд ацп.

Пересчет можно и через умножение сделать, про быстродействие же речи не идет? Да и аппаратное умножение есть.

Сильно дрожит младший разряд, не остановишь

AVR121: Enhancing ADC resolution by
oversampling

For each additional bit of resolution, n, the signal must be oversampled four times.

Thescale factor, sf, given by Equation 3-2, is the factor, which the sum of 4n samples should be divided by, to scale the result properly. n is the desired number of extra bit.
Equation 3-2: sf = 2^n

На каждый дополнительный разряд АЦП надо сделать 4^n лишних семплов. После суммирования оверсемплов результат надо побитно сдвинуть вправо n раз (разделить на 2^n).

10 Гц, хотя бы RC первого порядка, тогда и посмотреть, быть может и оверсэмплинг с дизерингом (тьфу ты, мерзопакость какая) не понадобятся.

обновлять показания чаще нескольких раз в секунду.

Ведь измерения проводятся только для индикации? Тогда нет смысла обновлять показания чаще нескольких раз в секунду.

‘* Filename: Вольтметр, 2х диапазонный ампертметр *
‘* Revision: 5.1 *
‘* Controller: ATMEGA8 *
‘* Compiler: BASCOM-AVR 2.0.6.1 *
‘* Author: MACTEPOK *
‘*******************************************************************************
$regfile = «m8def.dat» ‘определяем контроллер
$crystal = 8000000 ‘внутренний генератор
‘$sim
$lib «mcsbyte.lbx» ‘подключаем библиотеку функций

Config Pinc.0 = Input: Portc.0 = 1 ‘кнопка Выбор
Config Pinc.1 = Input: Portc.1 = 1 ‘кнопка Вверх
Config Pinc.2 = Input: Portc.2 = 1 ‘кнопка Вниз

Config Portd = Output: Config Portb = Output ‘порты на выход к которым подключен индикатор

Load1 Alias Portb.3 ‘нагрузка №1
Load2 Alias Portb.4 ‘нагрузка №2
Vibor Alias Pinc.0 ‘кнопка Выбор
Up Alias Pinc.1 ‘кнопка Вверх
Down Alias Pinc.2 ‘кнопка Вниз

Config Adc = Single, Prescaler = Auto, Reference = Avcc ‘настраиваем АЦП
Dim W As Byte, Y As Byte, X As Byte, I As Byte, Z As Byte, Chislo(6) As Integer, Channel_1 As Integer, On1 As Word, Off1 As Word, Channel_2 As Integer, On2 As Word, Off2 As Word, Channel_3 As Integer, Sostoyanie As Byte, Sostoyanie_2 As Byte, Copy_print As Integer, Copy_print_sec As Integer, Copy_var As Integer, _print As Integer, _print_sec As Integer, Pokazaniya As Integer, View_menu As Byte, Booton_flag As Bit, Booton_flag_2 As Bit, Count As Word, Error_flag As Bit
Dim On2_l As Word, On2_h As Word, Off2_l As Word, Off2_h As Word, Diapazon As Byte
Dim Razryad_1 As Byte, Razryad_2 As Byte, Temp_najatiya As Byte, Indicator As Byte
Dim Menu_punkt As Byte ‘пункт меню
Dim Set_flag As Bit ‘флаг режима настройки уставок
Dim Podskaz_flag As Bit, Podskaz_flag_sec As Bit ‘флаги режима отображения подсказок на соответствующих каналах
Dim Default As Eram Byte At &H14 ‘переменная EEPROM для записи начальных уставок для первого включения прибора

‘A Alias Portd.5: B Alias Portd.7: C Alias Portd.3: D Alias Portd.1 ‘порты, к которым подключены сегменты индикатора
‘E Alias Portd.0: F Alias Portd.6: G Alias Portd.4: H Alias Portd.2 ‘
‘Dig1 Alias Portb.0: Dig2 Alias Portb.1: Dig3 Alias Portb.2 ‘ порты, к которым подключены общие аноды 1го индикатора
‘Dig1_sec Alias Portb.5: Dig2_sec Alias Portb.6: Dig3_sec Alias Portb.7 ‘ порты, к которым подключены общие аноды 2го индикатора

A Alias Portd.2: B Alias Portd.6: C Alias Portb.7: D Alias Portb.2 ‘порты, к которым подключены сегменты индикатора
E Alias Portd.0: F Alias Portb.6: G Alias Portd.7: H Alias Portb.5 ‘
Dig1 Alias Portd.3: Dig2 Alias Portd.4: Dig3 Alias Portd.1 ‘ порты, к которым подключены общие аноды 1го индикатора
Dig1_sec Alias Portd.5: Dig2_sec Alias Portb.0: Dig3_sec Alias Portb.1 ‘ порты, к которым подключены общие аноды 2го индикатора

For X = 1 To 6 ‘ присваиваем всем цифрам пустоту, чтоб в момент включения не высвечивались нули
Chislo(x) = 11
Next
‘*********** ___ Переключение типа индикаторов (ОК/ОА) ___ *********************
Readeeprom Indicator, 30
If Vibor = 0 Then ‘ Удерживая кнопку УСТ, подаем питание.
For X = 1 To 200
If X = 150 Then ‘ При длительном нажатии
Set Booton_flag
Toggle Indicator.3 ‘ Переключаем младший (четвертый) бит переменной. Номер бита выбрал произвольно
Writeeeprom Indicator, 30
If Indicator = &B00000000 Then ‘ Если переключили на ОА, зажжем все сегменты идикатора для подтверждения
Reset A: Reset B: Reset C: Reset D: Reset E: Reset F: Reset G: Reset H
Set Dig1: Set Dig2: Set Dig3: Set Dig1_sec: Set Dig2_sec: Set Dig3_sec
End If
If Indicator = &B00001000 Then ‘ Если переключили на ОK, зажжем все сегменты идикатора для подтверждения
Set A: Set B: Set C: Set D: Set E: Set F: Set G: Set H
Reset Dig1: Reset Dig2: Reset Dig3: Reset Dig1_sec: Reset Dig2_sec: Reset Dig3_sec
End If
Waitms 1500
Exit For
End If
If Vibor = 1 Then Exit For
Waitms 10
Next
End If
‘*******************************************************************************
If Default = 255 Then ‘при первом запуске, когда Default=255
Off1 = 120 ‘присваиваем начальный уставки
On1 = 110
‘ Off2 = 60
‘ On2 = 50
On2_l = 800
On2_h = 99
Off2_l = 600
Off2_h = 99
Indicator = &B00000000 ‘ для ОА. Indicator = &B00001000 для ОК
Razryad_1 = &B10111011
Razryad_2 = &B11101110
Writeeeprom On1, 0 ‘ Записываем в EEPROM уставку ON1
Writeeeprom Off1, 5 ‘ Записываем в EEPROM уставку OFF1
‘ Writeeeprom On2, 10 ‘ Записываем в EEPROM уставку ON2
‘ Writeeeprom Off2, 14 ‘ Записываем в EEPROM уставку OFF2
Writeeeprom On2_l, 22
Writeeeprom On2_h, 24
Writeeeprom Off2_l, 26
Writeeeprom Off2_h, 28
Writeeeprom Razryad_1, 16
Writeeeprom Razryad_2, 17
Writeeeprom Indicator, 30
Default = 100 ‘ присваиваем значение 100(произвольное, отличное от 255) и больше этот кусок кода выполняться не будет
End If
Readeeprom On1, 0 ‘ Считываем из EEPROM уставку ON1
Readeeprom Off1, 5 ‘ Считываем из EEPROM уставку OFF1
‘ Readeeprom On2, 10 ‘ Считываем из EEPROM уставку ON2
‘ Readeeprom Off2, 14 ‘ Считываем из EEPROM уставку OFF2
Readeeprom On2_l, 22
Readeeprom On2_h, 24
Readeeprom Off2_l, 26
Readeeprom Off2_h, 28
Readeeprom Razryad_1, 16
Readeeprom Razryad_2, 17

Читайте также:  Дистанционное управление для лодочного мотора своими руками

Config Timer0 = Timer, Prescale = 8: On Timer0 Pulse ‘ конфигурируем таймер 0 и назначаем подпрограмму которая выполняется при переполнении таймера
Config Timer1 = Timer, Prescale = 1: On Timer1 Bootons ‘ конфигурируем таймер 1 и назначаем подпрограмму которая выполняется при переполнении таймера
Enable Interrupts: Enable Timer0: Enable Timer1 ‘ разрешаем прерывания, таймер 0, таймер 1
Start Timer0: Start Timer1
Start Adc ‘ начало преобразования

If On2_l > 999 Then On2 = On2_h Else On2 = On2_l
If Off2_l > 999 Then Off2 = Off2_h Else Off2 = Off2_l

Do
If X > 40 Then ‘ увеличили период опроса АЦП, чтобы значения не прыгали
Stop Timer0: Stop Timer1 ‘ на время преобразования останавливаем таймеры
Channel_1 = Getadc(5) ‘ Вольтметр 0..500 В ‘опрос АЦП (диапазон от 0 до 1023) (1 канал)
‘ Channel_1 = 1023 — Channel_1 ‘инвертирование раскомментировать===========
Channel_1 = Channel_1 / 2.046 ‘пересчет тут любая формула для требуемого диапазона или необходимой характеристики
If Channel_1 > 500 Then Channel_1 = 500 ‘верхний предел показаний

Channel_2 = Getadc(4) ‘ Ток 1,00… 9,99 А ‘опрос АЦП (2 канал)
‘ Channel_2 = Channel_2 ‘пересчет тут любая формула для требуемого диапазона или необходимой характеристики
If Channel_2 > 999 Then Channel_2 = 999 ‘верхний предел показаний
‘ Razryad_2 = &B01110111
Diapazon = 2
If Channel_2 999 Then Channel_2 = 999
‘ Razryad_2 = &B11101110
Diapazon = 1
End If
X = 0 ‘
End If
Start Timer0: Start Timer1
If On1 = Off1 Then Sostoyanie = 0 ‘если значение первого канала АЦП выше уставки OFF1, то выключаем нагрузку №1
Else ‘если уставка ON1 > OFF1 то режим охладителя
If Channel_1 >= On1 Then Sostoyanie = 1 ‘если значение первого канала АЦП выше уставки ON1, то включаем нагрузку №1
If Channel_1 0

через 5 сек)
If Count > 7000 Then ‘задается время автоматического выхода из меню
Count = 0 ‘сброс счетчика
View_menu = 0 ‘ выход из меню в основной режим
End If
‘ H = 1 ‘ выключаем точку на индикаторе
Stop Timer0 ‘останавливаем таймер 0
Select Case View_menu ‘в зависимости от пункта меню, записываем в переменные расчета следующие данные
Case 0:
_print = Channel_1 ‘ основной режим. 1й индикатор показывает значение АЦП 1го канала
_print_sec = Channel_2 ‘ основной режим. 2й индикатор показывает значение АЦП 2го канала
If Diapazon = 2 Then Razryad_2 = &B01110111 Else Razryad_2 = &B11101110

Case 1:
_print = On1 ‘ 1й индикатор показывает значение уставки ON1
_print_sec = Channel_2 ‘ 2й индикатор показывает значение АЦП 2го канала
Case 2:
_print = Off1 ‘ 1й индикатор показывает значение уставки OFF1
_print_sec = Channel_2 ‘ 2й индикатор показывает значение АЦП 2го канала
Case 3:
_print = Channel_1 ‘ 1й индикатор показывает значение АЦП 1го канала
If On2_l = 1000 Then Razryad_2 = &B01110111 Else Razryad_2 = &B11101110
_print_sec = On2 ‘ 2й индикатор показывает значение уставки ON2
Case 4:
_print = Channel_1 ‘ 1й индикатор показывает значение АЦП 1го канала
If Off2_l = 1000 Then Razryad_2 = &B01110111 Else Razryad_2 = &B11101110
_print_sec = Off2 ‘ 2й индикатор показывает значение уставки OFF2

If Podskaz_flag = 0 Then ‘если не выводим на 1й индикатор подсказки, то работаем с числами
Copy_print = _print ‘
Copy_var = Copy_print ‘
For I = 3 To 1 Step -1 ‘ цикл в котором разбивается переменная на 3 числа
Chislo(i) = Copy_print Mod 10 ‘ заносим в масив последнюю цифру от числа Copy_print(123 mod 10 = 3)
Copy_print = Copy_print / 10 ‘ отсекаем последнюю цифру от числа Copy_print (123/10=12)
Next ‘ убираем незначимые нули
If Copy_var 6 Then W = 1 ‘ выбираем какую цифру сейчас включать
Y = 0
Gosub Look: A = Z ‘ переходим к подпрограмме Look, которая определяет нужно ли сейчас загорется сегменту А
Gosub Look: B = Z
Gosub Look: C = Z
Gosub Look: D = Z
Gosub Look: E = Z
Gosub Look: F = Z
Gosub Look: G = Z

Select Case W ‘ включаем цифру(разряд) которую выбрали (w). Подаем плюс на общий провод конкретной цифры (разряда)
Case 1:
If Indicator = 0 Then
Set Dig3
If Podskaz_flag = 0 Then H = Razryad_1.3 Else H = 1
Else
Reset Dig3
If Podskaz_flag = 0 Then
H = Razryad_1.3
Toggle H
Else
H = 0
End If
End If
Case 2:
If Indicator = 0 Then
Set Dig2
If Podskaz_flag = 0 Then H = Razryad_1.2 Else H = 1
Else
Reset Dig2
If Podskaz_flag = 0 Then
H = Razryad_1.2
Toggle H
Else
H = 0
End If
End If
Case 3:
If Indicator = 0 Then
Set Dig1
If Podskaz_flag = 0 Then H = Razryad_1.1 Else H = 1
Else
Reset Dig1
If Podskaz_flag = 0 Then
H = Razryad_1.1
Toggle H
Else
H = 0
End If
End If
Case 4:
If Indicator = 0 Then
Set Dig3_sec
If Podskaz_flag_sec = 0 Then H = Razryad_2.3 Else H = 1
Else
Reset Dig3_sec
If Podskaz_flag = 0 Then
H = Razryad_2.3
Toggle H
Else
H = 0
End If
End If
Case 5:
If Indicator = 0 Then
Set Dig2_sec
If Podskaz_flag_sec = 0 Then H = Razryad_2.2 Else H = 1
Else
Reset Dig2_sec
If Podskaz_flag = 0 Then
H = Razryad_2.2
Toggle H
Else
H = 0
End If
End If
Case 6:
If Indicator = 0 Then
Set Dig1_sec
If Podskaz_flag_sec = 0 Then H = Razryad_2.1 Else H = 1
Else
Reset Dig1_sec
If Podskaz_flag = 0 Then
H = Razryad_2.1
Toggle H
Else
H = 0
End If
End If
End Select

Start Timer0
Return

Look: ‘ подпрограмма которая определяет нужно ли сейчас гореть сегменту, который вызвал эту подпрограмму
Z = Chislo(w) * 7: Z = Y + Z ‘ определяем порядковый номер числа из таблици DATA. W — это цифра которую будем выводить 1..2..3, Y это номер сегмента (A=0 B=1 C=2. G=7)
If Indicator = 0 Then
Z = Lookup(z, Cifri_oa) ‘ выбираем из таблици включить или выключить нужный сегмент -OA
Else
Z = Lookup(z, Cifri_ok) ‘-OK
End If
Incr Y ‘Y это номер сегмента (A=0 B=1 C=2. ). Chislo(w) * 7 — переход на начало нужной строки Data.Z = Y + Z — по очереди перебираем сегменты в строке.
Return

Источник

Оцените статью