PCF8574

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Добрый день!

Приехали с китая вот такие микросхемки - PCF8574 (DIP-корпус).

Собрал для тестов: Ардуино Nano по I2C подключается к PCF8574. Все А0...А2 у PCF8574 посадил на GND и проверил подключение I2C-сканером, адрес получился 0x20. К пину P0 (вывод 4 микросхемы) подключил кнопку, второй вывод кнопки посадил на GND и резистор 18кОм (вторым концом резистор подключен к +5В). Для работы с PCF8574 использовал библиотеку https://github.com/xreef/PCF8574_library

Далее загрузил в ардуино код:

#include "PCF8574.h"               
PCF8574 pcf8574(0x20);           

void setup(){
  Serial.begin(9600);
// Проверка инициализация библиотеки pcf8574
  pcf8574.pinMode(P0, INPUT); 
  Serial.print("Init pcf8574...");
  if (pcf8574.begin()){
    Serial.println("OK");}
  else{
    Serial.println("ERROR");}
  delay(50);                                       
}

void loop() {
  byte val = pcf8574.digitalRead(P0);           
  if (val == LOW) {
    Serial.println("P0 LOW now!");
  }
  delay(5);                                        
}

Открываю монитор порта и там после "Init pcf8574... OK" постоянно сыпятся сообщения "P0 LOW now!" в не зависимости от того нажата кнопка или нет. Даже пробовал просто проводом подключенным к пину P0 подключаться к +5В и GND и никакой реакции (в мониторе порта так же сыпятся сообщения без остановки).

Никак не соображу - это микросхема такая дурная у меня (неисправная?) или я что-то делаю не так?

 

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

После строки №5 вставьте 

  pcf8574.begin();

Ой, простите!!!! Ссылку-то Вы указали, это я не заметил на этом сраном экране. Простите ради Бога.

С бегином-то заработало? У меня работает, а без него было как Вы описываете.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Евгений Петрович, как же так?

1. pcf8574.begin(); выполняется в строке #9

2. Библиотеку устанавливал через "Скетч->Подключить библиотеку->Управлять библиотеками (Ctrl+Shift+l)", в поиск вбивал "PCF8574", выбрал "PCF8574 library by Reef Версия 2.2.2"  (при нажатии на ссылку "More info" открывается вот этот адрес: https://github.com/xreef/PCF8574_library). Прошу прощения, если ввел в заблуждение.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

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

С бегином-то заработало? У меня работает, а без него было как Вы описываете.

Эксперимента ради вставил строчку с бегином в 5 строку (сдвинув все вниз на строчку) - как и ожидалось, ничего не поменялось.

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

За библиотеку я уже извинился.

BOOM пишет:

Евгений Петрович, как же так?

1. pcf8574.begin(); выполняется в строке #9

После pcf8574.pinMode(P0, INPUT); ?

Надо перед.

У меня работает. Если у Вас нет, то ... стесняю спросить за схему, но у меня P0 притянут к питанию резистором 10к. Попробуйте. 

P.S. Сейчас попробовал в протеусе. там тоже нормально работает.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

BOOM пишет:
1. pcf8574.begin(); выполняется в строке #9

То есть ПОСЛЕ pcf8574.pinMode() ???? А чо, красава! ;))) Так победим!

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Видимо в чем-то другом проблема. Вот смотрите, я вставил вот такой код в loop():

void loop() {
  byte val = pcf8574.digitalRead(P0);   
  Serial.print("LOW = ");
  Serial.print(LOW);
  Serial.print(" , val = ");
  Serial.println(val);
  if (val == LOW) {
    // Serial.println("P0 LOW now!");
  }
  delay(5);                                        
}

И вот что на выходе получается:

19:06:56.643 -> LOW = 0 , val = 1 // НЕ нажата кнопка
19:06:56.689 -> LOW = 0 , val = 1
19:06:56.689 -> LOW = 0 , val = 1
19:06:56.735 -> LOW = 0 , val = 1
19:06:56.735 -> LOW = 0 , val = 1
19:06:56.735 -> LOW = 0 , val = 0 // Нажата кнопка и удерживается
19:06:56.783 -> LOW = 0 , val = 0
19:06:56.783 -> LOW = 0 , val = 0
19:06:56.829 -> LOW = 0 , val = 0
19:06:56.829 -> LOW = 0 , val = 0
19:06:56.829 -> LOW = 0 , val = 0
19:06:56.876 -> LOW = 0 , val = 0

Но почему-то если я меняю на это:

void loop() {
  byte val = pcf8574.digitalRead(P0);   
/*
  Serial.print("LOW = ");
  Serial.print(LOW);
  Serial.print(" , val = ");
  Serial.println(val);
*/
  if (val == LOW) {
     Serial.println("P0 LOW now!");
  }
  delay(5);                                        
}

То условие полностью игнорируется... %) Бред какой-то.... бррр....

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

wdrakula пишет:

BOOM пишет:
1. pcf8574.begin(); выполняется в строке #9

То есть ПОСЛЕ pcf8574.pinMode() ???? А чо, красава! ;))) Так победим!

Да, мне тоже это показалось бредом и я поменял (еще в начале экспериментов) местами begin() (поставив его в самый верх), но к моему сожалению в подобной "связке" я получал лишь:

Init pcf8574... ERROR

С чем это связано я не знаю.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Я не понимаю (действительно, серьезно, прям в самом деле) что происходит. Загружаю вот такой код:

void loop() {
  byte val = pcf8574.digitalRead(P0);   
/*
  Serial.print("LOW = ");
  Serial.print(LOW);
*/
  Serial.print(" , val = ");
  Serial.println(val);

  if (val == 0) {
     Serial.println("P0 LOW now!");
  }
  delay(5);                                        
}

И на выходе вот такое:

19:21:26.156 -> Init pcf8574...OK
19:21:26.205 ->  , val = 1
19:21:26.205 ->  , val = 0
19:21:26.205 -> P0 LOW now!
19:21:26.251 ->  , val = 0
19:21:26.251 -> P0 LOW now!
19:21:26.251 ->  , val = 1
19:21:26.298 ->  , val = 0
19:21:26.298 -> P0 LOW now!
19:21:26.344 ->  , val = 1
19:21:26.344 ->  , val = 1
19:21:26.344 ->  , val = 1
19:21:26.344 ->  , val = 1
19:21:26.344 ->  , val = 1
19:21:26.344 ->  , val = 1
19:21:26.391 ->  , val = 1

Пойду резистор по меньше 18кОм поищу...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Поставил на 5кОм резистор подтяжки к +5В, проверил мультиметром: на P0 +4.7В, когда нажимаю и удерживаю кнопку - 0В. Но код из заголовка темы ведёт себя так же - как будто игнорирует +5В подтяжку. (
Попробую микросхему поменять. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Поменял микросхему - ничего не изменилось. Жду советов более опытных товарищей.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Бред какой-то или особенность PCF8574P ??

Поменял логику работы - теперь я 5кОм притянул пин P0 к GND и кнопкой присоединяю его к +5В. Так изменился код:

void loop() {
  byte val = pcf8574.digitalRead(P0);   

  if (val == 1) {
     Serial.println("P0 HIGH now!");
  }
  delay(5);                                        
}

Все прекрасно работает. Но мне так не удобно, я привык всегда кнопкой к GND притягивать. Это особенность данной микросхемы (может быть именно моей микросхемы?) или все-таки брак? Покупал 5шт, а китаец прислал аж 10шт, невиданная щедрость....

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

BOOM пишет:

Видимо в чем-то другом проблема. Вот смотрите, я вставил вот такой код в loop():

void loop() {
  byte val = pcf8574.digitalRead(P0);   
  Serial.print("LOW = ");
  Serial.print(LOW);
  Serial.print(" , val = ");
  Serial.println(val);
  if (val == LOW) {
    // Serial.println("P0 LOW now!");
  }
  delay(5);                                        
}

И вот что на выходе получается:

19:06:56.643 -> LOW = 0 , val = 1 // НЕ нажата кнопка
19:06:56.689 -> LOW = 0 , val = 1
19:06:56.689 -> LOW = 0 , val = 1
19:06:56.735 -> LOW = 0 , val = 1
19:06:56.735 -> LOW = 0 , val = 1
19:06:56.735 -> LOW = 0 , val = 0 // Нажата кнопка и удерживается
19:06:56.783 -> LOW = 0 , val = 0
19:06:56.783 -> LOW = 0 , val = 0
19:06:56.829 -> LOW = 0 , val = 0
19:06:56.829 -> LOW = 0 , val = 0
19:06:56.829 -> LOW = 0 , val = 0
19:06:56.876 -> LOW = 0 , val = 0

Но почему-то если я меняю на это:

void loop() {
  byte val = pcf8574.digitalRead(P0);   
/*
  Serial.print("LOW = ");
  Serial.print(LOW);
  Serial.print(" , val = ");
  Serial.println(val);
*/
  if (val == LOW) {
     Serial.println("P0 LOW now!");
  }
  delay(5);                                        
}

То условие полностью игнорируется... %) Бред какой-то.... бррр....

Так, понятно. Или поставьте задержку больше (500, например), или читайте принудительно. Вы библиотеку-то смотрели? Она не так проста.

Замените строку №2 на

byte val = pcf8574.digitalRead(P0, true);

и будет счастье

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

BOOM пишет:

Все прекрасно работает. Но мне так не удобно, я привык всегда кнопкой к GND притягивать. Это особенность данной микросхемы (может быть именно моей микросхемы?) или все-таки брак? Покупал 5шт, а китаец прислал аж 10шт, невиданная щедрость....

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

Я Вам уже написал как победить.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

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

Замените строку №2 на

byte val = pcf8574.digitalRead(P0, true);

и будет счастье

Евгений Петрович, благодарю Вас сердечно! Заработало! :)

Честно говоря, библиотеку (ее код) не смотрел.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Можете порекомендовать какую-нибудь более легковесную библиотеку для PCF8574? Честно говоря используемая сейчас и мудреная (как выяснилось) и "тяжеловата". Вышеприведенный код уже занимает 4558 байт. :(

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

Не, не могу. Посмотрите по названию, их много. Я только сегодня ещё две скачивал :-)

sadman41
Offline
Зарегистрирован: 19.10.2016

Так там же чистейший I2C - токмо читай из него и налива...
Инит только замысловатый был какой-то. Вроде.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Чтобы прочитать 0 с порта, надо сначала операцией записи послать в него 1. 

inspiritus
Offline
Зарегистрирован: 17.12.2012

А подвесить порт внешним резистором на плюс не поможет?

sadman41
Offline
Зарегистрирован: 19.10.2016

Вот у меня такая функция завалялась:

int16_t readPCF8574(uint8_t _address) {
  int16_t rc = -1;
  uint8_t len;
  Wire.beginTransmission(_address);
  Wire.write(0xFF); // Activate input mode
  if (0x00 != Wire.endTransmission()) {
    goto finish;
  }
  len = Wire.requestFrom(_address, (uint8_t) 0x01);
  if (0x01 != len) {
    goto finish;
  }
  rc = (Wire.read() & 0xFF);
finish:
  return rc;
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

inspiritus пишет:

А подвесить порт внешним резистором на плюс не поможет?

Нет, там надо именно внутренний бит в единицу взвести, тогда м/с понимает, что это вход.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

inspiritus пишет:

А подвесить порт внешним резистором на плюс не поможет?

Именно так и было сделано. В начале 18кОм, потом уменьшил до 5кОм. Пока Евгений Петрович не подсказал как нужно - ничего не помогало.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Вторая часть "балета" - это (как уже все поняли) использование PCF8574P в качестве "выходного пина". В описании к микросхеме имеется ограничение на ток (при установке HIGH) всего в 100мкА (оно же 0,1мА). Собственно, а как управлять, например, РЕЛЕ?

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

Имеются в наличии для экспериментов следующие полупроводники:

2N7000, различные NPN и PNP транзисторы (в основной массе 2N3904 и 2N3906), а так же мосфеты вида IRF740, IRF840 и т.п.

Ток срабатывания РЕЛЕ от 60мА до 100мА, экспериментировать буду вечером.

sadman41
Offline
Зарегистрирован: 19.10.2016

А как управляют РЕЛЕ китайцы на своих модулях? Так и управлять.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Почитай, узнаешь многа интерресного

inspiritus
Offline
Зарегистрирован: 17.12.2012

Или pcf.pinmode(x, INPUT_PULLUP) ?

Сопутствующая тема, в ,например нане, при наличии внешней подтяжки наверно тоже лучше инитить с пуллапом?
 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

inspiritus пишет:
в нане, при наличии внешней подтяжки наверно тоже лучше инитить с пуллапом?

В нане пофиг, а этот регистр понимает, что нога входная, только когда во вход 1 прописана.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

DetSimen пишет:

Почитай, узнаешь многа интерресного

Собственно, с прочтения данной статьи вопросы и появились. Не читал бы и не знал про ограничения в 100мкА. Но к GND подтягивается полноценно, поэтому думаю схему нужно использовать с подтяжкой к GND. Пока в голове только использование PNP-транзисторов "крутится"....

inspiritus пишет:

Или pcf.pinmode(x, INPUT_PULLUP) ?

Не работает это, пробовал. Работает только как Евгений Петрович написал.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

sadman41 пишет:

А как управляют РЕЛЕ китайцы на своих модулях? Так и управлять.

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

inspiritus
Offline
Зарегистрирован: 17.12.2012

Вот и я так думаю, однако столкнулся с непонятным глюком: пуллапнутая нога наны при касании отверткой «звенит» и не видит импулься с ок. npn выхода датчика расхода жидкости.. При этом соседняя ведет себя нормально с аналогичным датчиком. Ноги соответственно 2и3 , на них активированы прерывания FALLING.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Так у AVR подтяжка-то слабая, килоом 50-100 с большим разбросом, так, на кнопку в макетке хватит, но для серьёзного ОК надо ставить внешний резистор.  Ну а из-за разброса, на одной ноге может работать, а на соседней будет звенеть.  Я всегда для отвецтвенных цепей внешнюю подтяжку ставлю, килоом на 5-10. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

inspiritus пишет:

пуллапнутая нога наны при касании отверткой «звенит»

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

inspiritus
Offline
Зарегистрирован: 17.12.2012

Ага, вот и я поставил 4.7 кОм и задышало. Непонятно только почему один вход фонил, а второй нет...

видимо как раз разброс.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Итак, продолжаем:

#include "PCF8574.h"               
PCF8574 pcf8574(0x20);           

void setup(){
  Serial.begin(9600);
  pcf8574.pinMode(P0, OUTPUT); 

// Проверка инициализация библиотеки pcf8574
  Serial.print("Init pcf8574...");
  if (pcf8574.begin()){
    Serial.println("OK");
  } else{
    Serial.println("ERROR");
  }
  delay(50);                                       

}

void loop() {
  pcf8574.digitalWrite(P0, HIGH);   
  Serial.println("HIGH");
/*
  if (val == 0) {
     Serial.println("P0 HIGH now!");
  }
*/
  delay(1000);                                        
  pcf8574.digitalWrite(P0, LOW);   
  Serial.println("LOW");
  delay(1000);                                        
}

Светодиод через 120 Ом подтянут к +5В, коммутирую катод на GND. Светодиод моргает.

Нужно с транзистором замутить...

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

BOOM пишет:
Светодиод моргает.
А он точно не "мигающий"?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Если по типу работы светодиода - то подал питание и он «горит» (излучает свет), а уж моргающий он там или мигающий - не знаю ))) Изменяя время задержки - изменяется время свечения/бездействия (или как сказать то?). 

SLKH
Offline
Зарегистрирован: 17.08.2015

BOOM пишет:

Светодиод через 120 Ом подтянут к +5В, коммутирую катод на GND. Светодиод моргает.

Нужно с транзистором замутить...

Так уж нужно ли для светодиода? лучше резистор увеличить. у 8574 нормальный ток LOW 25 миллиампер.

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

BOOM пишет:

Если по типу работы светодиода - то подал питание и он «горит» (излучает свет), а уж моргающий он там или мигающий - не знаю ))) Изменяя время задержки - изменяется время свечения/бездействия (или как сказать то?). 

Бывают такие "подал питание, а он мигает". А бывают даже и разными цветами мигает. Вот я и спросил, не мигающий ли у Вас.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Нет, обычный светодиод (я же код вставил - обычная моргалка с задержкой в 1сек). Вчера до экспериментов с транзисторами дело не дошло - отвлекли. 

Мне нужно реле включать с током до 100мА (а лучше с запасом по току). 

Pyotr
Offline
Зарегистрирован: 12.03.2014

BOOM пишет:

Нужно с транзистором замутить...

База на пин 8574, Э на землю, К на реле. Внешняя подтяжка пина 8574 к +5В 1-3 кОм. LOW - реле выключено, HIGH-включено. С мосфетом даже без внешней подтяжки можно обойтись.

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

И прощай микруха

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Pyotr пишет:

BOOM пишет:

Нужно с транзистором замутить...

База на пин 8574, Э на землю, К на реле. Внешняя подтяжка пина 8574 к +5В 1-3 кОм. LOW - реле выключено, HIGH-включено. С мосфетом даже без внешней подтяжки можно обойтись.

Благодарю! Вечером опробую. Транзистор типа 2N3904 подойдет? Если использовать мосфет - IRF510 (их много у меня) пойдет? Правда китайский, емкость затвора порядка 2400пФ....

Pyotr
Offline
Зарегистрирован: 12.03.2014

Alexey_Rem пишет:

И прощай микруха

Что, микруху жалко? ВООМ их много купил)))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Alexey_Rem пишет:

И прощай микруха

Почему, если внешнюю подтяжку к +5В использовать? Объясните, пожалуйста...

Pyotr
Offline
Зарегистрирован: 12.03.2014

BOOM пишет:

Pyotr пишет:

BOOM пишет:

Нужно с транзистором замутить...

База на пин 8574, Э на землю, К на реле. Внешняя подтяжка пина 8574 к +5В 1-3 кОм. LOW - реле выключено, HIGH-включено. С мосфетом даже без внешней подтяжки можно обойтись.

Благодарю! Вечером опробую. Транзистор типа 2N3904 подойдет? Если использовать мосфет - IRF510 (их много у меня) пойдет? Правда китайский, емкость затвора порядка 2400пФ....

Подойдет любой npn с усилением больше 50 и соответствующим током К и напряжением. Да и мосфет пойдет, если больше никакого нет. Только лучше между затвором и пином 8574 резистор поставить 100-300 Ом.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну усилит он 100 микроамперную единичку до 5 мА, и што?  Какая релюха сработает от этого?  BOOM, возьми Р-MOSFET типа NDP6020P (он логический) и коммутируй нагрузку нулём, шыбчее будет. Тока помни, что включение выхода будет инвертировано. 

P.S. А про IRF510 забудь как страшный сон, он от 4Вольт тока-тока приоткрываться начинает, лучше тогда уж IRL540

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

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

Pyotr
Offline
Зарегистрирован: 12.03.2014

Парни, у меня рабочий день в 4:00 начинается. К обеду могу ченить и так говорить...

Вытекающий ток у 8574 100 мкА. Поэтому для нрн нужна верхняя подтяжка. Я об этом выше написал. 1 кОм даст ток базы 4.3 мА. Мосфет, хоть и медленно, но откроется и таким током. (емкость затвора зарядится). При 5 В на затворе думаю у любого мосфета сопротивление канала будет меньше 10 Ом. Этого достаточно, чтоб реле сработало.

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Alexey_Rem пишет:

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

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

Что-то поменялось с того (хоть и давнего) времени?

nik182
Offline
Зарегистрирован: 04.05.2015

Ничего не поменялось. Это ты не дочитал. Есть такой ток базы, после увеличения которого коллекторный ток не увеличивается. Он максимально возможный. Называется ток насыщения. В этом режиме нагрев транзистора минимальный. Параметр из справочника. Лучший режим для управления нагрузкой вкл - выкл. Резистор в цепи базы надо выбирать так, чтобы ток коллекторный был близок к насыщению.