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

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

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

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


Вы здесь » Программирование ATMEL в BASCOM. » Кирпичи... » 8-битный i2c-декодер PCF8574 и код для управления 8 (до 64!) реле


8-битный i2c-декодер PCF8574 и код для управления 8 (до 64!) реле

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

1

Что делать, если нужно управлять множеством выходов, а кол-во свободных портов МК ограничено?
Или управляемое устройство находится в некотором отдалении от управляющего блока (единицы-десятки метров). Не тянуть же к нему многожильный пучок проводов!
На помощь приходит 8-разрядный i2c-декодер. У него есть 8 двунаправленных выводов, которые могут работать как на выход, так и на вход (с некоторыми ограничениями, и здесь эта функция не использована).
Достаточно подключить на шину этот декодер, как мы получим 8 дополнительных TTL-выходов.
Путем изменения уровней на адресных выводах PCF8574 можно адресовать до 8 чипов, получив, таким образом, в общей сумме 64 (!) выхода, управляемых всего по 2 проводам.

Ниже приведена библиотечка для управления блоком из 8 реле, подключенных через буферный каскад к PCF8574.

Код:
' Этот модуль работает с 8-разрядным декодером PCF8574 на шине i2c,
' подключенным к блоку из 8 реле.
' Каждый разряд в байте состояния/управления отвечает за свое реле.
'
' ВНИМАНИЕ: биты в байте состояния реле ИНВЕРТИРОВАНЫ, так что
' НИЗКИЙ уровень (0) означает, что реле ВКЛЮЧЕНО,
' ВЫСОКИЙ уровень (1) - что реле ВЫКЛЮЧЕНО.
' Во избежание ошибок используйте константы RELAY_ON|OFF.
'
' ОБРАТИТЕ ВНИМАНИЕ: реле нумеруются от 0 до 7

$nocompile

const RELAY_ON = 0
const RELAY_OFF = 1

const RELAY_W = &H40                                                            ' адрес записи в PCF8574 на шине i2c
const RELAY_R = &H41                                                            ' адрес чтения из в PCF8574 на шине i2c

dim RELAY_bTMP as byte
dim RELAY_bStateStored as byte                                                  ' для запоминания/восстановления состояния всех реле

declare function RELAY_GetRelay(byval relay_num as byte) as byte                ' прочитать состояние реле #0...7 (инвертировано! используйте RELAY_ON|OFF)
declare sub RELAY_SetRelay(byval relay_num as byte , byval state as byte)       ' установить состояние реле #0...7 (инвертировано! используйте RELAY_ON|OFF)
declare sub RELAY_ToggleRelay(byval relay_num as byte)                          ' переключить реле #0...7
declare sub RELAY_RelaysOFF()                                                   ' выключить все реле
declare function RELAY_GetState() as byte                                       ' прочитать состояние всех реле одним байтом
declare sub RELAY_SetState(byval relay_state as byte)                           ' установить состояние всех реле одним байтом
declare sub RELAY_Store()                                                       ' сохранить состояние всех реле
declare sub RELAY_Restotre()                                                    ' восстановить состояние всех реле

goto PCF8574_I2C_done                                                           ' требуется компилятору BASCOM при использовании оцпии "config submode = old"

macro RELAY_readI2C
   i2cstart
   i2cwbyte RELAY_R
   i2crbyte RELAY_bTMP , nack
   i2cstop
end macro

macro RELAY_writeI2C
   i2cstart
   i2cwbyte RELAY_W
   i2cwbyte RELAY_bTMP
   i2cstop
end macro

sub RELAY_RelaysOFF()                                                           ' выключить все реле
   i2cstart
   i2cwbyte RELAY_W
   i2cwbyte 255
   i2cstop
end sub

function RELAY_GetRelay(relay_num as byte) as byte                              ' прочитать состояние реле #0...7 (инвертировано! используйте RELAY_ON|OFF)
   ' прочитать текущее состояние всех реле
   RELAY_readI2C
   ' смотря по состоянию заданного реле из байта состояния
   if RELAY_bTMP.relay_num = RELAY_ON then
      RELAY_GetRelay = RELAY_ON
   else
      RELAY_GetRelay = RELAY_OFF
   end if
end function

sub RELAY_SetRelay(relay_num as byte , state as byte)                           ' установить состояние реле #0...7 (инвертировано! используйте RELAY_ON|OFF)
   ' прочитать текущее состояние всех реле
   RELAY_readI2C
   ' сбросить бит заданного реле
   RELAY_bTMP.relay_num = state.0
   ' записать обратно
   RELAY_writeI2C
end sub

sub RELAY_ToggleRelay(relay_num as byte)                                        ' переключить реле #0...7
   ' прочитать текущее состояние всех реле
   RELAY_readI2C
   ' инвертировать бит заданного реле
   RELAY_bTMP.relay_num = not RELAY_bTMP.relay_num
   ' записать обратно
   RELAY_writeI2C
end sub

function RELAY_GetState() as byte                                               ' прочитать состояние всех реле одним байтом
   ' прочитать текущее состояние всех реле
   RELAY_readI2C
   RELAY_GetState = RELAY_bTMP
end function

sub RELAY_SetState(relay_state as byte)                                         ' установить состояние всех реле одним байтом
   i2cstart
   i2cwbyte RELAY_W
   i2cwbyte relay_state
   i2cstop
end sub

sub RELAY_Store()                                                               ' сохранить состояние всех реле
   RELAY_bStateStored = RELAY_GetState()
end sub

sub RELAY_Restotre()                                                            ' восстановить состояние всех реле
   RELAY_SetState RELAY_bStateStored
end sub

PCF8574_I2C_done:                                                               ' требуется компилятору BASCOM при использовании оцпии "config submode = old"

+4

2

Есть еще 1-Wire, но это уже совсем другая история... ;)

0

3

А  вот за это спасибо!
без суперциклов и операциооных систем надеюсь работать будет?

0

4

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

А  вот за это спасибо!
без суперциклов и операциооных систем надеюсь работать будет?


Конечно. Это простая библиотечка для работы с аппаратным ресурсом. Готовые модули на основе PCF8574 продаются на Али, и обычно снабжены самим чипом, гребенкой пинов и переключателем или перемычками для выбора адреса на шине i2c. Выпускаются также "проходные" модули, у которых контакты шины i2c и питания выведены в торцы платы: с одной стороны "папа", а с другой - "мама", что позволяет стыковать модули "паравозиком" один за другим, получая 8 х %число_модулей% выходов типа GPIO.
На картинке это модуль синего цвета http://sh.uploads.ru/t/8ioKx.jpg

0

5

К недостатку  PCF8574 я бы отнёс квази-двунаправленный выход - это надо помнить. Допустим, поляризованное реле с одной обмоткой к нему не подключить.
Пришлось применять 74HC595.

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

Есть еще 1-Wire, но это уже совсем другая история...

Хорошо зарекомендовало себя  управление 74HC595 по одному проводу, но это тоже уже другая история.

0

6

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

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

Ну кто же вешает реле на обычную логику без ключа. Надо хотя бы для ленивых, через ULN...даже китайцы через оптрон делают или так же.

0

7

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

Хорошо зарекомендовало себя  управление 74HC595 по одному проводу, но это тоже уже другая история.

Расскажите свою историю, будет интересно. Особенно мне :)

0

8

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

Хорошо зарекомендовало себя  управление 74HC595 по одному проводу, но это тоже уже другая история.

Основной недостаток 74НС595 - безадресная последовательная передача данных в каскаде.
Те же PCFxxxx или 1-Wire расширители позволяют индивидуальное обращение, что ставит их на "другую полку"... ;)
Впрочем, тут диспут не об этом. Выбор за конструктором схемы...

0

9

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

pchela5 написал(а): Ну кто же вешает реле на обычную логику без ключа. Надо хотя бы для ленивых, через ULN...даже китайцы через оптрон делают или так же.


Конечно, напрямую к выходам PCF8574 подключать реле не следует. Даже если они совсем маломощные, параллельно обмотке необходимо поставить диод в обратном включении для защиты от токов самоиндукции, которые возникают при отпускании реле. В полностью самодельных схемах можно применить сборку типа ULN, или поставить в конструкцию один из готовых модулей - они выпускаются на 1, 2, 4 и 8 реле с опторазвязкой и транзисторными ключами; это, помимо прочего, позволяет питать обмотки реле от второго, обычно нестабилизированного источника питания, что позволяет не нагружать основной источник или батарею в случае батарейного питания. Типовые реле на 5 В жрут довольно приличный ток, 50...100 мА на обмотку, так что при 8 включенных реле требуется довольно мощный источник.

0

10

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

Ну кто же вешает реле на обычную логику без ключа

Ну вот смотрите - я сделал осциллограф-пробник в корпусе пейджера Моторола Адвизор, для этого мне понадобилась всего одна  74HC595 - 3 выхода на мультиплексор, 1 выход на оптрон и 2 по 2 выхода включил параллельно. По паспорту максимальный ток с выхода - 25 мА. Поляризованное реле на 3 вольта кушает в импульсе около 30 мА, для пущей безопасности поставил с выходов 74HC595 последовательно еще сборку из 4 резисторов для удобства монтажа на 10 Ом. Перебрасывание реле из одной позиции в другую 0,2 секунды, потом питание с реле снимается. Для перестраховки поставил параллельно обмотке двунаправленный стабилитрон на 3,6 вольта - от лития все работает. Кстати, когда был непропай одного вывода - реле на срабатывало - сказывалось большое внутреннее сопротивления ключа, потом все заработало. Но это решение только для таких видов реле на 3 вольта: IM41GR или G6KU-2F-Y-DC3V. В остальных случаях надо или сборки ставить или одиночные ключи.

Основой послужила следующая статья: https:// drive2.ru/b/469158314110878789/

Листинг подпрограммы (здесь 74hc595_scale_index , 74hc595_index - массив и индекс значений состояния аттенюатора, 74hc595 - байт посылки, Input_rele - нулевой бит на открытый/закрытый вход осциллографа):
Send_to_74hc595:

   74hc595 = Lookup(74hc595_scale_index , 74hc595_index)
   74hc595 = 74hc595 Or Input_rele

' 0 bit - on/off input
' 1,2 bit - reley 1
' 3,4 bit - reley 2
' 5 bit - address A1 74HC4051
' 6 bit - address A0 74HC4051
' 7 bit - address A2 74HC4051

   For J_count = 0 To 7                                     ' кратковременно устанавливаем релюшку в нужное положение

      If 74hc595.j_count = 1 Then
         74hc595_sw = 1
         Waitus 20
         74hc595_sw = 0
         Waitus 2
         74hc595_sw = 1
      Else
         74hc595_sw = 1
         Waitus 2
         74hc595_sw = 0
         Waitus 30
         74hc595_sw = 1
      End If
      Waitus 2

   Next J_count

   Waitus 250
   74hc595_sw = 0
   Waitms 200

   74hc595 = 74hc595 And &B11100001                         ' снимаем питание с релюшки

   For J_count = 0 To 7

      If 74hc595.j_count = 1 Then
         74hc595_sw = 1
         Waitus 20
         74hc595_sw = 0
         Waitus 2
         74hc595_sw = 1
      Else
         74hc595_sw = 1
         Waitus 2
         74hc595_sw = 0
         Waitus 30
         74hc595_sw = 1
      End If
      Waitus 2

   Next J_count

   Waitus 250
   74hc595_sw = 0
   Waitms 200

Отредактировано pchela5 (2019-10-08 15:03:18)

+1

11

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

К недостатку  PCF8574 я бы отнёс квази-двунаправленный выход

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

http://sg.uploads.ru/URQwy.png

http://sg.uploads.ru/qAtCk.png

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

Отредактировано sla174 (2019-10-08 17:42:59)

0

12

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

pchela5 написал(а): Если использовать "Модуль управления LCD1602 по I2C", к примеру, управление подсветкой
неприятно промаргивает при включении.


Давно уже пользуюсь только такими дисплеями, да и все старые, которые были, переделала на i2c добавкой этого модуля.
Никакого промаргивания не замечала. Вот то, что иногда они нормально не инициализируются, это бывает. Так и не нашла способа это надежно побороть.
Использую примерно такой код:

Код:
$lib "LCD_I2C_Backlight.lib"
i2cinit
waitms 50
initlcd
dim _lcd_e as byte
dim backlight as byte
const backlight_on = &H08
const backlight_off = &H00
const Pcf8574_lcd = &H4E
const Pcf_d4 = 4
const Pcf_d5 = 5
const Pcf_d6 = 6
const Pcf_d7 = 7
const Pcf_rs = 0
const Pcf_rw = 1
const Pcf_e1 = 2
const Pcf_e2 = 9                                                             ' 9 or more if not used
waitms 50
_lcd_e = 128
waitms 50
backlight = backlight_on
waitms 50
home
cursor off , noblink
deflcdchar  <somechar>
cls

0

13

Промаргивание, это когда при включении подсветки она включается ярко, но через мгновение притухает.
Это из за того, что верхний ключ PCF подключает базу транзистора к  + питания на короткое время, а потом он отключается и остается внутренняя подтяжка PCF 0,1 mA и резистор R8.

http://s8.uploads.ru/Sm7PW.png

Код

$lib "lcd_HD44780_pcf8574.lib"

------LCD--------
Dim _backlight As Byte : _backlight = 0
Dim _lcd_e As Byte : _lcd_e = 192
Dim Pcf8574_lcd As Byte

Const Pcf_rs = 0
Const Pcf_bl = 3
Const Pcf_e2 = 2
Const Pcf_e1 = 1
Const Pcf_d4 = 4
Const Pcf_d5 = 5
Const Pcf_d6 = 6
Const Pcf_d7 = 7

Const Lcd_addr = &H4E
Pcf8574_lcd = Lcd_addr

Config Lcd = 16 * 4

'------   Конфигурация шины I2c   ----

Config Scl = Portc.2
Config Sda = Portc.3
Config I2cdelay = 30
I2cinit

Waitms 100

Lcdinit

У меня библиотека другая, брал где то здесь, на форуме.
Тоже не инициализируется нормально иногда, думаю, из за ардуиновского загрузчика,
но без него не пробовал.

+1

14

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

Промаргивание, это когда при включении подсветки она включается ярко, но через мгновение притухает.
Это из за того, что верхний ключ PCF подключает базу транзистора к  + питания на короткое время, а потом он отключается и остается внутренняя подтяжка PCF 0,1 mA и резистор R8.
...
У меня библиотека другая, брал где то здесь, на форуме.
Тоже не инициализируется нормально иногда, думаю, из за ардуиновского загрузчика,
но без него не пробовал.


Тогда конечно, 0.1 мА это очень мало, при h21 транзистора порядка 100 он сможет выдать не более 10 мА, тогда как подсветка (особенно старая, "зеленая") жрет 100-150 мА.
В этом случае для управления подстветкой можно использовать сборку или готовый транзистор дарлингтона, либо ключевой мосфет.

А библиотека, скорее всего, та же самая, просто другое имя файла.

0

15

В своё время делал так, работало прекрасно.
http://s5.uploads.ru/t/9Ofx5.jpg

+2


Вы здесь » Программирование ATMEL в BASCOM. » Кирпичи... » 8-битный i2c-декодер PCF8574 и код для управления 8 (до 64!) реле