Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » ! Санькины ПЛЮШКИ ! » ЖКИ из электросчетчиков с последовательной записью (аналог TIC55M)


ЖКИ из электросчетчиков с последовательной записью (аналог TIC55M)

Сообщений 1 страница 22 из 22

1

Стали у нас менять в домах электросчетчики по истечению межповерочного интервала.
Вообще-то их можно поверять, но предпочитают просто менять на новые, а старые выбрасывают.
Не могла пройти мимо и подобрала несколько штук.
Вскрытие показало, что внутри счетчика (СЭБ - 2А) стоит ЖКИ, у которого рабочими являются всего 5 ног, остальные по углам -- крепежные и никуда не подключены.
До этого мне уже попадались ЖКИ счетчиков со встроенным контроллером, причем I2C (счетчики НЕВА).
Однако небольшой реверс-инжинириг схемы включения показал, что здесь какой-то другой интерфейс. На самом дислпее какие-либо обозначения отсуствовали.
У него было 5 ног и 8 разраядов, точка в каждом разряде, а также галочка V под каждым разрядом для указания на какую-нибудь надпись - обозначение функции прибора.
После некоторого гугления и реверс-инжиниринга стало понятно, что мой дисплей очень похож на типовой TIC55M с чипом MT1001.
Копание в даташитах и метод тыка позволили запустить дисплей.

https://upforme.ru/uploads/0000/25/b8/2070/t129069.jpg

Для тех, кто совсем не встречался ЖКИ типа TIC, краткий экскурс. Два вывода -- это Vcc и GND. Остальные три имеют следующее назначение: DATA -- сюда мы выставляем передаваемые данные; CLK -- такт. При подаче "1" данные с вывода DATA записываются в сдвиговый регистр. LOAD -- при подаче сюда "1" данные из регистра переписываются в регистр индикации и начинают отображаться на экране. Каждый записанный бит соответствует одному сегменту индикатора. В моем случае для одного знакоместа следовало передать 9 бит: 7 для сегментов, один управлял десятичной точкой, и еще один -- галочкой под разрядом. Всего, стало быть, необходимо передать 8 разрядов * 9 бит = 72 бита (здесь отличие от TIC55, которому, согласно datasheet, следует передавать 80 бит несмотря на то, что сегментов у него всего 72).

В итоге я сделала простую демо-программку, которая управляет ЖКИ. Чтобы не было совсем скучно и дисплей показывал какие-нибудь данные, я прицепила термометр DS18B20. Кстати, я написала корректный код для считывания DS18B20 в виде числа с плавающей точкой, который реализует максимальную точность датчика и корректно считает отрицательные температуры -- потому что в интернете полно неправильных примеров, которые только вводят в заблуждение.

Ловите  :love:

Код:

' -----------------------------------------------------------
' Пример работы с ЖКИ с последовательной загрузкой данных
' в регистр сдвига. аналог TIC55M. 5 выводов, 8 знакомест и галочки под
' каждым знакоместом. в отличие от оригинального TIC55, в этот
' ЖКИ надо задвигать всего 72 бита, а не 80, как в TIC55.
' Назначение выводов: (1- Vcc, 2 - GND, 3- LOAD) ... (4 - DATA, 5 - CLK)
' Vcc 3V3...5V. Сигнальные выводы следует притянуть к GND через 10K,
' сигналы подавать через ~5K, хотя работает и так. Это может быть важно, если вы 
' планируете реализовать прибор с питанием от батарейки, и МК будет уходить
' в режим сна -- индикатору не нравятся "болтающиеся в воздухе" выводы.
'
' Written by Cirno_9 (t.me/Cirno9)
' -----------------------------------------------------------

$regfile = "m328pdef.dat"
$crystal = 16000000
$hwstack = 64
$swstack = 64
$framesize = 64

config submode = new

LCD_LOAD alias PORTD.5                                      ' pin used to load data from shift-regiter content to display
LCD_DATA alias PORTD.6                                      ' serial data pin
LCD_DCLK alias PORTD.7                                      ' clock of data ("1" stores data from data pin to register)
config LCD_LOAD = output
config LCD_DATA = output
config LCD_DCLK = output

LCD_LOAD = 0
LCD_DATA = 0
LCD_DCLK = 0

config 1wire = PortD.4                                      ' uses by DS18B20 sensor

dim wserial(8) as word                                      ' uses by tic55 procedures
declare sub tic55_display(byval ss as string)               ' show string to display
declare sub tic55_set_checkmark(byval pos as byte)          ' set chekmark sign "v" in specified position
declare sub _tic55_send_data()                              ' internal use sub
declare function ds18b20_read() as single                   ' get temperature from DS18B20

dim thermo as single
dim ss as string * 8

do
   thermo = ds18b20_read()
   ss = fusing(thermo , "0.0") + "*C"
   tic55_display ss
loop

end

' -----------------------------------------------------------
'     TIC55M
' -----------------------------------------------------------

sub tic55_set_checkmark(byval pos as byte)
   ' display chekmark "v" in the specified position.
   ' pos = 0...8, pos = 0 clears all chekmarks.
   if pos = 0 then
      for pos = 1 to 8
         wserial(pos).7 = 0
      next
   else
      wserial(pos) = wserial(pos) or &b0000_0000_1000_0000
   end if
   _tic55_send_data
end sub

' -----------------------------------------------------------

sub tic55_display(byval ss as string)
   ' shows string to display.
   ' string can contains any digits, some symbols...
   ' (letter C, sing * means "degreee sign", sign "-")...
   ' and the "dot" symbol.
   ' you can add all other aplhabet simbols and
   ' special characters by yourself if you need.
local i as byte , j as byte , bchar as byte
   ss = ucase(ss)                                           ' remove this line if you'll need to display a small letters
   j = 1
   for i = 1 to len(ss)
      bchar = asc(ss , i)
      select case bchar
         case 42                                            ' degree sign
            wserial(j) = &b0000_0000_0011_1100
         case 45                                            ' minus sign
            wserial(j) = &b0000_0000_0000_0100
         case 46                                            ' dot sign
            decr j
            wserial(j) = wserial(j) or &b0000_0001_0000_0000
         case 48 to 57                                      ' digits
            bchar = bchar - 48
            wserial(j) = lookup(bchar , digits)
         case 67                                            ' "C" letter
            wserial(j) = &b0000_0000_0001_1011
         case else                                          ' space
            wserial(j) = &b0000_0000_0000_0000
      end select
      incr j
      if j = 9 then exit for
   next
   ' fill unused positions by space
   while j < 9
      wserial(j) = &b0000_0000_0000_0000                    ' space
      incr j
   wend
   _tic55_send_data
end sub

' -----------------------------------------------------------

sub _tic55_send_data()                                      ' send data to the display  (72 bits must be sent)
local i as byte , j as byte
   for j = 8 to 1 step -1                                   ' symbols
      for i = 8 to 0 step -1                                ' bits for each symbol
        LCD_DATA = wserial(j).i                             ' set bit to DATA line
        LCD_DCLK = 1                                        ' }
        waitus 10                                           ' } (just use "nop" for slow microcotrollers less or eq 4 MHz)
        LCD_DCLK = 0                                        ' } clock to store data bit to display register
      next
   next
   LCD_LOAD = 1                                             ' }
   waitus 10                                                ' } (just use "nop" for slow microcotrollers less or eq 4 MHz)
   LCD_LOAD = 0                                             ' } show register data on the display
end sub

' -----------------------------------------------------------
'     DS18B20
' -----------------------------------------------------------

function ds18b20_read() as single
local lsb as byte , msb as byte , nvalue as integer , fvalue as single , sign as byte
   1wreset
   1wwrite &HCC                                             ' command: call DS18B20 indirect (single sensor inline)
   1wwrite &H44                                             ' command: start themperature measuring
   waitus 780
   1wreset
   1wwrite &HCC                                             ' command: call DS18B20 indirect (single sensor inline)
   1wwrite &HBE                                             ' command: read DS18B20 data
   lsb = 1wread()
   msb = 1wread()
   sign = msb.7                                             ' bits 7...3 of msb means temperature less 0
   if sign = 1 then
      msb = 0xFF - msb                                      ' }
      lsb = 0xFF - lsb                                      ' } convert if value less 0
      incr lsb                                              ' an 1 must be to added to lsb
   else
      msb = msb and &b0000_0111                             ' clear bits 7...3 if temperature over or eq 0
   end if
   nvalue = makeint(lsb , msb)
   if sign = 1 then nvalue = -nvalue
   fvalue = nvalue
   fvalue = fvalue / 16
   ds18b20_read = fvalue
end function

' -----------------------------------------------------------
'     TIC55M DIGITS CODE
' -----------------------------------------------------------

digits:
'  A
' F B
'  G
' E C
'  D
'              ._vCBA_FGED                                  ' bit order
data &b0000_0000_0111_1011%                                 ' 0
data &b0000_0000_0110_0000%                                 ' 1
data &b0000_0000_0011_0111%                                 ' 2
data &b0000_0000_0111_0101%                                 ' 3
data &b0000_0000_0110_1100%                                 ' 4
data &b0000_0000_0101_1101%                                 ' 5
data &b0000_0000_0101_1111%                                 ' 6
data &b0000_0000_0111_0000%                                 ' 7
data &b0000_0000_0111_1111%                                 ' 8
data &b0000_0000_0111_1111%                                 ' 9

+5

2

Спасибо! Возьму на заметку,давно лежит такой дисплей

0

3

Уж очень он похож на Ht1621
https://radiokot.ru/forum/viewtopic.php?f=2&t=89010

Не пробовали отправлять на дисплей с помощью Shiftout ?
https://avrhelp.mcselec.com/index.html?shift.htm

0

4

Cirno_9 написал(а):

Кстати, я написала корректный код для считывания DS18B20 в виде числа с плавающей точкой, который реализует максимальную точность датчика и корректно считает отрицательные температуры -- потому что в интернете полно неправильных примеров, которые только вводят в заблуждение.

Так-же на много проще, и прожорливого деления нет.

'------------------------  Настраиваем шину 1Ware  -----------------------------
  Config 1wire = Portb.0       ' Ножка МК для подключения датчика Ds18b20
'-----------------------  Используемые переменные  -----------------------------
  Dim Temp_ds18b20 As Integer       'Температура*16 в HEX формате
  Dim Data_ds18b20(2) As Byte At Temp_ds18b20 Overlay       'массив данных от DS18B20
  Dim Температура As Single

'===============================================================================
  Опрос_ds18b20:
'-------------------------------------------------------------------------------

    1wreset       ' Сброс линии 1Ware
    1wwrite &HCC       ' Обращение к датчику
    1wwrite &HBE       ' Команда чтения ОЗУ датчика
    Data_ds18b20(1) = 1wread(2)       ' Принимаем данные
    Температура = Temp_ds18b20       ' Забираем сырое значение температуры
    Shift Температура , Right , 4       ' Получаем готовую температуру с знаком

'===============================================================================
  Запуск_измер_датчиков_ds18b20:
'-------------------------------------------------------------------------------
   1wreset       ' Сброс линии 1Ware
   1wwrite &HCC       ' Обращение к датчику
   1wwrite &H44       ' Запуск измерения датчика
'-------------------------------------------------------------------------------
  Return
'===============================================================================

+1

5

sasha_1973 написал(а):

Так-же на много проще, и прожорливого деления нет.

Еще проще:

Код:
function ds18b20_readA() as single
local value as integer , fvalue as single
   1wreset
   1wwrite 0xCC                                             '// command: call DS18B20 indirect (single sensor inline)
   1wwrite 0x44                                             '// command: start themperature measuring
   waitms 1                                                 '// minimal delay = 780 us
   1wreset                                                  
   1wwrite 0xCC                                             '// command: call DS18B20 indirect (single sensor inline)
   1wwrite 0xBE                                             '// command: start themperature measuring
   value = 1wread(2)
   fvalue = value
   shift fvalue , right , 4 , signed
   ds18b20_readA = fvalue
end function

0

6

ТаваГищи! непонашенски это! Ни проверки CRC, ни проверки состояния линии до опроса ))

0

7

Александр Д. написал(а):

ТаваГищи! непонашенски это! Ни проверки CRC, ни проверки состояния линии до опроса ))

Так научите ж нас, как правильно! И притом, желательно, как можно компактнее и ... изящнее, я б сказала.
И да, чтобы можно было добавить несколько датчиков (насколько я понимаю, приходится хранить в ОЗУ или ЭСПЗУ 8-байтные серийники датчиков. Или можно обойтись одним 8-байтным буфером? (Стандартный подход: первый серийник возвращает 1wsearchfirst(), затем 1wsearchnext() пока err != 1 или по счету до 1wirecount(), а уж потом сброс, команда старта замера, пауза, и вычитывание через последовательность  1wreset -> 1wwrite &H55 -> 1wverify idN(1) -> 1wwrite &HBE -> value = 1wread(2). А нельзя ли сразу получать в буфер серийник от 1wsearchfirst() или 1wsearchnext(), и тут же его использовать в указанной последовательности - чтобы не хранить где-то серийнки всех датчиков?

А и кстати, что и как там надо проверять в линии?

0

8

Подходы зависят от её величества Задачи

Если вам показометр на подоконник - 2 байта приняли и ладно.
Если управление ростом неких бактерий и дрожжей (два чана с нагревателями по 60 Квт каждый), то уже надо посерьезнее.
А если это управление котлом - там вообще дублирование, да еще разного типа датчиками!

Можно воспользоваться услугами Баском: Err
Я делаю так: Если линия в нуле - явно проблема, сразу в обработчик ошибок.
Всегда принимаю все байты и считаю CRC.

После того, как из-за моей ошибки (и недогляда технолога) сервисникам пришлось покататься по всей России-матушке и при любой погоде менять около сотни плат (прошить не могли - уровня мозгов не хватало) - вот тогда я стал бдеть и перебдевать где только можно :)

Красота важна в музее, а мне бы понадёжнее...

ps
серийники в "ширпотребе" не храню
А вот если что-то понадежнее (умный дом и всякие сигнализации) - обязательно!

Отредактировано Александр Д. (2024-03-19 15:25:29)

+1

9

Cirno_9 написал(а):

мой дисплей очень похож на типовой TIC55M с чипом MT1001.

а не HT1613 это или что-то близкое?

Я очень их любил по юности, модель KO4B2, он же TXD-006
https://www.eham.ru/articles/optoelektronika/2306-применение-7-сегментных-жки-–-модулей

0

10

Александр Д. написал(а):

а не HT1613 это или что-то близкое?

Судя по описанию в ссылке - что-то весьма похожее!
Просто там к индикатору подключается внешний сдвиговый регистр - а тут он встроен прямо в стекляшку!

0

11

Cirno_9 написал(а):

Еще проще:

Этот код вообще работать не будет :disappointed:

0

12

kip написал(а):

Cirno_9 написал(а):

    Еще проще:

Этот код вообще работать не будет :disappointed:

я тоже так думаю, но не проверял и утверждать не стал.
Хотя да, как вдруг определится факт отрицательной температуры?

0

13

Александр Д. написал(а):

Хотя да, как вдруг определится факт отрицательной температуры?

Если речь про

Код:
shift fvalue , right , 4 , signed

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

Код:
x.w = %0000000010100010 ; +10.125
Debug x>>4              ; 10
x =   %1111111001101111 ; -25.0625
Debug x>>4              ; -26

Правда вычисления производятся с целочисленной 2-ух байтовой переменной.
Как баском выполняет аналогичные действия для single, не знаю, но могу предположить что сдвиг заменяется делением, в данном случае на 16.

0

14

Пётр написал(а):

Если речь про

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

Правда вычисления производятся с целочисленной 2-ух байтовой переменной.
Как баском выполняет аналогичные действия для single, не знаю, но могу предположить что сдвиг заменяется делением, в данном случае на 16.

Проверял - только деление. Шифт не спасёт.
Но там есть ещё одна мааааленькая ошибка

(не верно прочитан даташит)
waitms 1                                                 '// minimal delay = 780 us

Отредактировано kip (2024-03-20 20:36:36)

0

15

kip написал(а):

Этот код вообще работать не будет

Но, что замечетально - работает.
Да и что ему, собственно, помешает?

+1

16

kip написал(а):

Но там есть ещё одна мааааленькая ошибка

(не верно прочитан даташит)
waitms 1                                                 '// minimal delay = 780 us

Вот только беда в том, что ошибка - в датащах (!). И эту ошибку тащат в любой код, вместе с громоздким способом преобразования считанных данных.
Ну сами посудите, там написано, что минимальное время преобразования - 780 мс. Это что ж получается за датчик - тугодум такой! Почти целую секунду преобразует 12 бит?
В реальности мкс, конечно же. И задержка 1 мс - с запасом, более чем (АЦП с частотой 1 кГц - нормально для датчика, ок).

А можно и вообще не ждать. Если внимательно почитать датащи, то там сказано, что на время преобразования датчик притягивает линию данных к НИЗКОМУ, а как только оно закончится - отпускает. Поскольку линия должна быть подтянута к питанию, на ней устанавливается ВЫСОКИЙ. Так что нам достаточно это проверять, или вовсе повесить на прерывание и заниматься другими делами. Правда, этот способ не будет работать (или работает через пень-колоду) при фантомном питании. Лучше к нему без особой нужды и вовсе не прибегать.

Так-то.

+2

17

Cirno_9 написал(а):

Это что ж получается за датчик - тугодум такой! Почти целую секунду преобразует 12 бит?
В реальности мкс, конечно же.

Минимальное время 780 миллисекунд. Обычно округляют до секунды.
За 780 микросекунд он ничего измерить не успеет!

Cirno_9 написал(а):

на время преобразования датчик притягивает линию данных к НИЗКОМУ, а как только оно закончится - отпускает.

Вот, проведите эксперимент и убедитесь что время вовсе не 780 микросекунд, а почти секунда.

https://upforme.ru/uploads/0000/25/b8/385/691921.png

Отредактировано Пётр (2024-03-21 16:37:56)

0

18

Пётр написал(а):

Вот, проведите эксперимент и убедитесь что время вовсе не 780 микросекунд, а почти секунда.

Провела. Да, на 12 битах 580 мс вышло в среднем.
Тогда, если датчик опрашивается периодически (а слишком часто нет смысла), нужно выдавать запрос на конвертацию в конце процедуры, а не в начале. А в следующий раз читать уже измеренный результат.

Получаем такой код:

Код:
function ds18b20_readB() as single
local value as integer , fvalue as single
   1wreset                                                  
   1wwrite 0xCC                                             '// command: direct call of DS18B20 (single sensor inline)
   1wwrite 0xBE                                             '// command: get themperature measuring
   value = 1wread(2)
   fvalue = value
   shift fvalue , right , 4 , signed
   1wreset
   1wwrite 0xCC                                             '// command: direct call of DS18B20 (single sensor inline)
   1wwrite 0x44                                             '// command: start themperature measuring
   ds18b20_readB = fvalue
end function

Вызывать его нужно не чаще, чем раз в 780 мс. Первый результат он даст неправильный (скорее всего, 85°, что означает "преобразование не выполнено")

+1

19

Cirno_9 написал(а):

выдавать запрос на конвертацию в конце процедуры, а не в начале. А в следующий раз читать уже измеренный результат

примерно так и делаю.
Или при инициализации сразу шлю "холостой" опрос, а потом читаю достоверный.

+1

20

Пётр написал(а):

Минимальное время 780 миллисекунд.

Я вообще использую bitwait и не заморачиваюсь с временным интервалом. В этом есть свои минусы, но пока сбоев не было.

+1

21

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

+1

22

полностью согласен

kip написал(а):

Единственное неудобство только при включении, показывает фигню.

я вначале делаю "холостой" опрос и всё хорошо (выше про это писал)

+1


Вы здесь » Программирование ATMEL в BASCOM. » ! Санькины ПЛЮШКИ ! » ЖКИ из электросчетчиков с последовательной записью (аналог TIC55M)