avatar_Паяка

Универсальный модуль разрядной моргалки для Ардуино и не только

Автор Паяка, 17 Сен. 2018 в 15:11

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Паяка


Разрядный ток колеблется на единицы миллиампер в зависимости от количества светящих сегментов индикатора.

LM317T считает такой режим для себя нормальным, судя по тому, что не снижает ток. Но я всё же добавлю радиатору площади.
Видео
Режим секундомера, для калибровки отсчёта времени по эталонным часам, каковыми сегодня являются любые синхронизированные с точным временем Интернета.
Исходный код прошивки с комментариями
include 16f628a
pragma target clock 4_000_000
pragma target OSC      XT -- кварц 4 МГц
pragma target WDT      DISABLED
pragma target BROWNOUT ENABLED
pragma target LVP      DISABLED
pragma target CP       DISABLED
pragma target CPD      DISABLED
pragma target PWRTE    ENABLED
pragma target MCLR     INTERNAL

pragma EEDATA 0xB0, 0x04 -- 1200 мА по умолчанию
--pragma EEDATA 0x28, 0x05 -- 1320 мА прототип


-- разряды индикатора пронумерованы слева направо
alias digit1_on is   pin_A0 -- o вкл. 1 разряд
alias cmp_in    is   pin_A1 -- i
alias vrefout   is   pin_A2 -- i
alias dscg_on   is   pin_A3 -- o вкл. разрядный ток
alias digit2_on is   pin_A4 -- i вкл. 2 разряд
alias btn_plus  is   pin_A5 -- i кнопка плюс
alias clkout    is   pin_A6 -- i
alias clkin     is   pin_A7 -- i

alias btn_minus is   pin_A4 -- кнопка минус
var bit minus_dir at TRISA:4
alias dp_on     is   pin_B2 -- вкл. десятичная точка

const byte segments [20] = { -- кодировка сегментов
--  -A-
-- F   B
--  -G-
-- E   C
--  -D-
--FADECpGB -- согласно соединениям на плате
0b11111001, -- 0  ABCDEF
0b00001001, -- 1  BC
0b01110011, -- 2  ABDEG
0b01101011, -- 3  ABCDG
0b10001011, -- 4  BCFG
0b11101010, -- 5  ACDFG
0b11111010, -- 6  ACDEFG
0b01001001, -- 7  ABC
0b11111011, -- 8  ABCDEFG
0b11101011, -- 9  ABCDFG
0b01111010, -- 10 ACDEG
0b10011001, -- 11 BCFE
0b01110000, -- 12 ADE
0b01111000, -- 13 ACDE
0b00011010, -- 14 - n CEG
0b11010010, -- 15 - f AEFG
0b00000000, -- 16 - пусто
0b11010000, -- 17 - r AEF
0b00111011, -- 18 - d BCDEG
0b10101011  -- 19 - y BCDFG
--FADECpGB
}
const letter_o = 0
const letter_n = 14
const letter_f = 15
const space    = 16
const letter_r = 17
const letter_d = 18
const letter_y = 19

var volatile byte sec_100 = 0 -- сотни секунд
var volatile byte sec_10  = 0 -- десятки
var volatile byte sec_1   = 0 -- единицы
var volatile byte ah_1    = 0 -- единицы А*ч
var volatile byte ah_10   = 0 -- десятые доли
var volatile byte ah_100  = 0 -- сотые доли

var volatile byte ind1 --
var volatile byte ind2 --- вывод на индикатор
var volatile byte ind3 --
var volatile word current -- ток разряда в мА
var byte current_byte[2] at current
var volatile word current_old -- старая константа
var volatile word mas = 0 -- счётчик мА*с
var volatile byte scaler = 0 -- делитель 250Гц на 125
var volatile byte idle = 0    -- счётчик простоя
var volatile byte minus_count = 0 -- удержание кнопки
var volatile byte threshold = 0 -- Порог отключения


var volatile byte flags = 0 -- флаги конечного автомата
var bit digit1_next   at flags:0 -- Передача индикации
var bit digit2_next   at flags:1 -- следующему разряду
var bit dp_1          at flags:2 -- Позиция десятичной
var bit dp_2          at flags:3 -- точки
var bit second        at flags:4 -- Прошла секунда
var bit minus_pressed at flags:5 -- Нажата кнопка "-"
var bit plus_pressed  at flags:6 -- Нажата кнопка "+"
var bit clock         at flags:7 -- Режим секундомера

var volatile byte flags1 = 0
var bit dscg_enable   at flags1:0 -- Разрешение разряда
var bit calibr_mode   at flags1:1 -- Режим калибровки
var bit minus_detect  at flags1:2 -- Антидребезг "-"
var bit plus_detect   at flags1:3 -- Антидребезг "+"
var bit even          at flags1:4 -- Делитель 2Гц на 2
var bit minus_hold    at flags1:5 -- Минус удерживался
var bit threshold_set at flags1:6 -- Переключение порогов


alias cmp_out is CMCON_C2OUT

procedure interrupt is
pragma interrupt
if PIR1_TMR2IF then -- динамическая индикация
  PIR1_TMR2IF = off
  if !(dscg_enable|clock|calibr_mode|threshold_set)then
   ind1 = letter_o  -- Если не выбран ни разряд,
   if cmp_out then  -- ни секундомер, ни калибровка,
    ind2 = letter_f -- ни переключение порогов,
    ind3 = letter_f -- показываем состояние компаратора
   else
    ind2 = letter_n
    ind3 = space
   end if
   dp_1 = off
   dp_2 = off
  end if
  if digit1_next then    -- включаем 1 разряд
   digit1_next = off
   digit2_next = on
   portb = segments[ind1]
   dp_on = dp_1
   digit1_on = on
   digit2_on = off
  elsif digit2_next then -- включаем 2 разряд
   digit1_next = off
   digit2_next = off
   portb = segments[ind2]
   dp_on = dp_2
   minus_dir = 1
   digit2_on = on
   digit1_on = off
  else                   -- включаем 3 разряд
   if !btn_minus then
    minus_detect = on
   else
    if (minus_count > 3) then
     minus_hold = on
    end if
    minus_count = 0
   end if
   digit1_next = on
   digit2_next = off
   portb = segments[ind3]
   dp_on = !(dp_2|dp_1)
   digit1_on = off
   minus_dir = 0
   digit2_on = off
  end if
end if
if !btn_plus then
  plus_detect = on
end if
scaler = scaler + 1
if (scaler >= 125) then -- прошло 1/2 секунды
  scaler = 0
  if plus_detect then
   plus_detect = off
   plus_pressed = on
  end if
  if minus_detect then
   minus_detect = off
   minus_pressed = on
   minus_count = minus_count + 1
  end if
  even = !even
  if !even then --прошла секунда
   second = on
  end if
end if
end procedure

TRISB    =   0b00000000
TRISA    =   0b11110110
PORTB    =   0b00000000
PORTA    =   0b00000000
CMCON    =   0b00000101 -- 1 независимый компаратор
const vrcon_105  = 0b11100111
const vrcon_12   = 0b11101000 -- 1,6(6)В при 5В Vdd
const vrcon_1125 = 0b11000010
VRCON    =   vrcon_105
-- Частота кварца 4 МГц, команд 1 МГц.
-- Тактировать конечный автомат удобно частотой 250 Гц.
-- Это оптимально и для динамической индикации,
-- и для подсчёта времени.
-- Для этого настроим предделитель TMR2 на 16,
-- получим 62500 Гц. Период 250, получим 250 Гц.
-- По прерыванию с TMR2 будем обновлять индикатор
-- и прибавлять счётчики антидребезга и секунд

PIE1     =   0b00000010 -- только от TIMER2
PIR1     =   0b00000000 -- регистр флагов прерываний
T2CON    =   0b00000110 -- предделитель 16, постделитель 1
PR2      =   250
INTCON   =   0b11000000

procedure ah_indicate is
if (ah_1 < 14) then    -- 0.00 - 13.99
  ind1 = ah_1
  ind2 = ah_10
  ind3 = ah_100
  dp_1 = on
  dp_2 = off
elsif (ah_1 < 99) then -- 14.0 - 99.9
  ind1 = ah_1 / 10
  ind2 = ah_1 % 10
  ind3 = ah_10
  dp_1 = off
  dp_2 = on
else                   -- 100 - 255
  ind1 = ah_1 / 100
  ind2 = (ah_1 % 100) / 10
  ind3 = ah_1 % 10
  dp_1 = off
  dp_2 = off
end if
end procedure

procedure dscg_count is
-- 1 А*ч = 3600 А*с (кулон)
-- 0.01 А*ч = 36 А*с = 36000 мА*с
mas = mas + current
if (mas >= 36000) then
  mas = mas - 36000
  ah_100 = ah_100 + 1
  if (ah_100 > 9) then
   ah_100 = 0
   ah_10 = ah_10 + 1
   if (ah_10 > 9) then
    ah_10 = 0
    ah_1 = ah_1 + 1
   end if
  end if
end if
end procedure

procedure clock_count is
sec_1 = sec_1 + 1
if (sec_1 > 9) then
  sec_1 = 0
  sec_10 = sec_10 + 1
  if (sec_10 > 9) then
   sec_10 = 0
   sec_100 = sec_100 + 1
   if (sec_100 > 13) then
    sec_100 = 0
   end if
  end if
end if
ind1 = sec_100
ind2 = sec_10
ind3 = sec_1
dp_1 = off
dp_2 = off
end procedure

procedure main_cycle is
forever loop
  if cmp_out then -- если напряжение ниже порога,
   dscg_on = off   -- отключаем ток
  end if
  if second then -- если прошла секунда
   second = off
   if dscg_enable then
    if dscg_on then -- если ток идёт,
     dscg_count -- подсчитываем ёмкость
    end if
    ah_indicate -- индицируем ёмкость
   elsif clock then
    clock_count -- считаем секунды
   end if
  end if
  if plus_pressed then -- вкл/выкл разряд
   plus_pressed = off
   threshold_set = off
   clock = off
   dscg_enable = !dscg_enable
   if dscg_enable then
    dscg_on = !cmp_out
   else
    dscg_on = off
   end if
  end if
  if minus_pressed then
   dscg_enable = off
   dscg_on = off
   if minus_hold  then -- длинное нажатие
    minus_pressed = off
    minus_hold = off  -- переводит в режим
    threshold_set = off  -- секундомера
    sec_100 = 0
    sec_10 = 0
    sec_1 = 0
    clock = on
   elsif (minus_count == 0) then -- короткое нажатие переключает пороги
    minus_pressed = off
    threshold_set = on
    dp_1 = off
    dp_2 = on
    if threshold > 1 then -- с верхнего на нижний
     VRCON = vrcon_105
     threshold = 0
     ind1 = 1
     ind2 = 0
     ind3 = 5
    elsif threshold > 0 then -- со среднего на верхний
     VRCON = vrcon_12
     threshold = 2
     ind1 = 1
     ind2 = 2
     ind3 = 0
    else                      -- с нижнего на средний
     VRCON = vrcon_1125
     threshold = 1
     ind1 = 1
     ind2 = 12
     ind3 = 5
    end if
   end if
  end if
end loop
end procedure

procedure ma_indicate is
-- индикация калибровки миллиампер
  ind1 = current / 100
  ind2 = (current % 100) / 10
  ind3 = current % 10
  dp_1 = off
  dp_2 = off
end procedure

procedure calibrate is
calibr_mode = on
current_old = current
ma_indicate
while !btn_plus loop
end loop -- ждём отпускания кнопки +
plus_pressed = off
second = off
while !second loop
end loop
second = off
while !second loop
end loop
second = off
while !(plus_pressed|minus_pressed) loop
end loop -- ждём нажатия любой кнопки
plus_pressed = off
minus_pressed = off
while (idle < 11) loop
  if second then -- если прошла секунда
   second = off
   idle = idle + 1
  end if
  if plus_pressed then
   plus_pressed = off
   idle = 0
   if (current < 1398) then
    current = current + 1
   else
    current = 400
   end if
   ma_indicate
  end if
  if minus_pressed then
   minus_pressed = off
   idle = 0
   if (current > 401) then
    current = current - 1
   else
    current = 1399
   end if
   ma_indicate
  end if
end loop
if (current_old != current) then
  INTCON_GIE = 0
  EEADR = 0
  EEDATA = current_byte[0]
  EECON1_WREN = 1
  EECON2 = 0x55
  EECON2 = 0xAA
  EECON1_WR = 1
  while EECON1_WR loop
  end loop
  EEADR = 1
  EEDATA = current_byte[1]
  EECON2 = 0x55
  EECON2 = 0xAA
  EECON1_WR = 1
  while EECON1_WR loop
  end loop
  EECON1_WREN = 0
  INTCON_GIE = 1
end if
ind1 = letter_r -- вывод "rdy"
ind2 = letter_d
ind3 = letter_y
dp_1 = off
dp_2 = off
forever loop
end loop
end procedure

EEADR = 0  --   загрузим калибровочную константу
EECON1_RD = 1
current_byte[0] = EEDATA
EEADR = 1
EECON1_RD = 1
current_byte[1] = EEDATA

if btn_plus then -- если при включении не нажат +
main_cycle
else -- если нажат, запускаем в режиме калибровки
calibrate
end if
Итоговая схема

В архивах HEX и JAL V.2 исходник прошивки, эта схема картинкой и проект KiCAD с исходниками принципиальной схемы и печатной платы. Вторая версия с переключением порогов завершения разряда коротким нажатием кнопки "-".

Теперь короткое нажатие нижней кнопки "-" переключает пороги 10.5-11.25-12В, длинное переводит в режим секундомера. Верхняя кнопка "+" включает и отключает разряд. Когда разряд отключен, Off на индикаторе означает, что напряжение на клеммах ниже текущего порога, On - выше. Это поможет калибровать порог многооборотным подстроечным резистором. Калибровка одна на все пороги, т.е. надо откалибровать по любому одному из них.

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

Формула для расчёта калибровочной константы такова. Фактический средний ток в мА умножить на время по эталонным часам и делить на время по функции секундомера. Например, средний ток 1315 мА, 1406 эталонных секунд, секундомер прибора насчитал 1400. Тогда константа равна 1315*1406/1400=1321.
GT TF1 60V 20Ah Chilwee DZF

Vova_n

[user]Паяка[/user], Ваш в клад в теме СА дорогого стоит  :exactly:
У меня к вам предложение чуть чуть ещё потратить время и ввести хотя бы смену порогов КТЦ с фиксированными значениями 10,5/11,5/12в.
Это сделает модуль более универсальным.

S_Kov

Цитата: Паяка от 24 Фев. 2019 в 00:37В архиве HEX и JAL V.2 исходник прошивки
Мне особенно понравилась индикация Ач в диапазоне от 10 до 13. Даже не сразу понял.
Раньше такого не видел! "Голь на выдумки хитра!" ;))

Паяка

[user]Vova_n[/user], спасибо! Сегодня постараюсь заняться. Можно будет менять опору компаратора отключения с кнопок.

[user]S_Kov[/user], :-) идея давняя, изначально заключалась в том, чтобы индицировать до 1024 на 3-разрядном индикаторе, высвечивая 10 старшим разрядом сверху вниз. Затем подумалось, что 11 совсем просто, а 12 и 13 тоже можно стилизовать. Можно пойти и дальше, но тогда придётся уже запоминать, какая цифра как отображается.
GT TF1 60V 20Ah Chilwee DZF

S_Kov

Цитата: Паяка от 24 Фев. 2019 в 14:02идея давняя, изначально заключалась в том, чтобы индицировать до 1024 на 3-разрядном индикаторе, высвечивая 10 старшим разрядом сверху вниз. Затем подумалось, что 11 совсем просто, а 12 и 13 тоже можно стилизовать. Можно пойти и дальше, но тогда придётся уже запоминать, какая цифра как отображается.
На трех цифрах индикатора уже можно делать бегущую строку и не заморачиваться с разрядностью отображаемых цифр

Паяка

#239
[user]S_Kov[/user], верно. Но легче воспринимать, когда индикация статична.

[user]Vova_n[/user], готово и проверено.  :-)

Почти час непрерывной работы, полёт нормальный. С усиленным радиатором, при 12.8 В, 15.5 Вт температура подложки LM317T, измеренная через термопасту, 62 градуса Цельсия. В помещении 21 градус.

Токозадающий резистор солидно греется. 4Вт номинальной мощности - не излишек, а в самый раз. На фото температура радиатора, замерена в штатном резьбовом отверстии.

Светодиод погас, свидетельствуя о касании выбранного порога 10.5В и завершении разряда. Ёмкость старой DZM-12-12, (не той, у которой на днях было КЗ, её ставлю на разряд сейчас), получилась 4.06 А*ч.

Возобновить разряд можно вручную, нажав кнопку "+". При этом значение слитой ёмкости сохраняется до отключения питания.
GT TF1 60V 20Ah Chilwee DZF

Ribbentrop


Паяка

[user]Ribbentrop[/user], счётчик с порогом отключения по прекрасной цене! :wow: Нагрузка ему нужна внешняя, её можно собрать на той же LM317T или двух транзисторах.
GT TF1 60V 20Ah Chilwee DZF

Паяка

Финальный действующий вариант управляющей части аналоговой разрядной моргалки на одной LM324.
GT TF1 60V 20Ah Chilwee DZF

Паяка

Более продвинутой версии можно добавить функцию прекращения разряда при начале резкого спада напряжения, с запоминанием и отображением этого уровня. Очень пригодится для восстановления, когда разряды по ГОСТ до 10.5В сводят прогресс на нет или вовсе обращают вспять, а более высокий предустановленный уровень может оказаться неинформативным.
GT TF1 60V 20Ah Chilwee DZF

tj™

ЗУС7/ЗУС5/ЗУС4/Вымпел/BL1204/Бережок7/Бережок40

Паяка

[user]tj™[/user], пока тиражировать разрядные устройства не планирую. Когда доделаю продвинутое, можно будет подумать. Пишите пожелания, какие функции нужны, какой диапазон токов.
GT TF1 60V 20Ah Chilwee DZF

Паяка

#246
На Али внезапно нашёлся очень умный показометр по имени BY62.


Модуль умеет двусторонне общаться с ПК или ПЛК по последовательному интерфейсу, в т.ч. принимать команды и настройки и передавать информацию для лога, а также коммутировать разрядную нагрузку. Только пока непонятна логика высокого и низкого уровня напряжений: гистерезис или отсечка.

Эту игрушку однозначно надо осваивать! :wow: Получаем и контроллер разрядной нагрузки, и управляемый датчик для логгера с цифровым управлением, и возможность непосредственного наблюдения на экране и оперативной перенастройки с кнопки.
Ссылка на Али
GT TF1 60V 20Ah Chilwee DZF

S_Kov

Цитата: Паяка от 20 Март 2019 в 20:46На Али внезапно нашёлся очень умный показометр по имени BY62.
А что там за многоногий таракан? Не видно?

Паяка

[user]S_Kov[/user], неразборчиво. Если фото через фильтр прогнать? Только я этого не умею.

Если эту платформу ещё и программировать научиться, получится готовый форумный ПЛК! А если по SPI и SD-карту подключить, то и с логгером!  :eureka:
GT TF1 60V 20Ah Chilwee DZF

SapienzSPB

Цитата: Паяка от 20 Март 2019 в 21:55А если по SPI и SD-карту подключить, то и с логгером!
Если надо и протокол обмена данными с компьютером нешифрованый - могу добавить его поддержку в мою программу-логер.

Яков93

Цитата: S_Kov от 20 Март 2019 в 21:42
А что там за многоногий таракан? Не видно?

Хотя судя по всему у меня модель не совсем такая, вроде разводка разная.

serggio

Цитата: Паяка от 20 Март 2019 в 20:46На Али внезапно нашёлся очень умный показометр по имени BY62.
Очередная китайская поделка с кучей «сюрпризов».
Вы не с того конца к нагрузкам зашли, вам нужно было делать ее самостоятельно, либо брать готовые достойные варианты, а не показометры к своей схеме прикручивать