Read с PCF8574 с использованием attachInterrupt

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Здравствуйте. 

Используя функцию attachInterrupt хочу считать данные с PCF8574

Функция void read() не работает если эти строки присутствуют

int x = pcf20.read8();
Serial.print("Read ");
Serial.println(x, HEX);

Может это только в протеусе так?

 

#include <PCF8574.h>
#include <Wire.h>
PCF8574 pcf20(0x20);

void setup() {
pcf20.begin();
Serial.begin(9600);
attachInterrupt(0, read,FALLING);
Serial.println("Start");
pcf20.write(4, LOW);
pcf20.write(5, LOW);
pcf20.write(6, LOW);
pcf20.write(7, LOW);
}

void loop() {
  ///
}

void read()
{
Serial.println("Read");
int x = pcf20.read8();
Serial.print("Read ");
Serial.println(x, HEX);
}

 

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

Честно, в лом смотреть как устроена pcf20.read8, но попробуйте после строки 21 вставить sei(); и отпишитесь заработало ли.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Заработало.

Этим sei(); остановили прерывания?

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

Разрешили прерывания.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Спасибо.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Подскажите, прерывания мешают выполнению основного цикла, как это исправить?

 

#include <iarduino_I2C_IO_Global.h>
int timer,timerPrev=0;
boolean status = false;

void setup() {
  Serial.begin(9600);
  Serial.println("Start");
  iarduino_I2C_IO_Global.begin();
  attachInterrupt(0, read,FALLING);
  
    pinMode(uint16_t(0), OUTPUT);//0 пин микросхемы PCF8574 с адресом 0x20
    pinMode(uint16_t(1), OUTPUT);//1 пин микросхемы PCF8574 с адресом 0x20
    pinMode(uint16_t(2), OUTPUT);
    pinMode(uint16_t(3), OUTPUT);
    
    pinMode(uint16_t(4), INPUT );
    pinMode(uint16_t(5), INPUT );
    pinMode(uint16_t(6), INPUT );
    pinMode(uint16_t(7), INPUT );

   digitalWrite(uint16_t(0), LOW);
   digitalWrite(uint16_t(1), LOW);
   digitalWrite(uint16_t(2), LOW);
   digitalWrite(uint16_t(3), LOW);
}


void loop(){
timer = millis(); 
if (timer-timerPrev>1000){
status=!status;
digitalWrite(uint16_t(0), status); 
timerPrev=timer;
}
}

void read()
{
sei();
Serial.println(digitalRead(uint16_t(4)));
}

 

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

Я не понимаю, что значит "прерывания мешают выполнению основного цикла"? Как именно мешают? С чего Вы взяли, что они мешают? 

И ещё, не стоит использовать Serial.println в обрботчике прерывания. для отладки там глянут ещё так-сяк, но серьёзно использовать не стоит. Уберите.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

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

digitalWrite(uint16_t(0), status); перестаёт "мигать" если срабатывает attachInterrupt(0, read,FALLING);

https://youtu.be/NDRSUBPvDOE

 

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

Это не связано с прерываниями. У Вас типы данных для времени неправильный Исправляйте. Не поможет, будем дальше смотреть.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Евгений, тип поменял,но что-то тут....на видео понятно будет.

https://youtu.be/c1wwi1T1i2Q

На выходе INT PCF8574 0 и пусто?

 

#include <iarduino_I2C_IO_Global.h>
unsigned long timer,timerPrev=0;
boolean status = false;

void setup() {
  Serial.begin(9600);
  Serial.println("Start");
  iarduino_I2C_IO_Global.begin();
  attachInterrupt(0, read,CHANGE);
  
    pinMode(uint16_t(0), OUTPUT);
    pinMode(uint16_t(1), OUTPUT);
    pinMode(uint16_t(2), OUTPUT);
    pinMode(uint16_t(3), OUTPUT);
    
    pinMode(uint16_t(4), INPUT );
    pinMode(uint16_t(5), INPUT );
    pinMode(uint16_t(6), INPUT );
    pinMode(uint16_t(7), INPUT );

   digitalWrite(uint16_t(0), LOW);
   digitalWrite(uint16_t(1), LOW);
   digitalWrite(uint16_t(2), LOW);
   digitalWrite(uint16_t(3), LOW);
}


void loop(){
timer = millis(); 
if (timer-timerPrev>1000){
status=!status;
digitalWrite(uint16_t(0), status); 
timerPrev=timer;
}
}

void read()
{
sei();
digitalWrite(uint16_t(1), digitalRead(uint16_t(4))); 
}

 

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Разобрался, с библиотекой <PCF8574.h> всё работает

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

Вас не смущает, что Вы в строках 32 и 40 пишете в пины 0 и 1, а на них же у Вас сидит Serial, который Вы инициализировали?

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

uint16_t(0) это 0 нога микросхемы PCF8274 с адресолм 0x20

 

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

Ну, Вам виднее.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

https://lesson.iarduino.ru/page/rasshiritel-na-8-vhodov-vyhodov-trema-mo...

  • №_ВЫВОДА_МОДУЛЯ - число, типа uint16_t.
  • №_ВЫВОДА_ARDUINO - число, типа uint8_t.
sadman41
Offline
Зарегистрирован: 19.10.2016

Прочитайте статью внимательней, в последнем фрагменте коде явно какая-то ерунда написана.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

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

Ну, Вам виднее.

Женя. Это правда. Та библиотека перегружает стандартные digitalRead() и digitalWrite().

Для меня - плохо, но кому-то понравится. Я вообще перегрузки не люблю... Это "не честный С" ;) ;) ;)

#ifndef __IARDUINO_I2C_IO_GLOBAL_H__
#define __IARDUINO_I2C_IO_GLOBAL_H__

#include   <iarduino_I2C_IO.h>
			iarduino_I2C_IO										iarduino_I2C_IO_Global;
	void	pinMode				(uint16_t i, uint8_t j)	{		iarduino_I2C_IO_Global.pinMode		(i,j);}
	bool	digitalRead			(uint16_t i)			{return	iarduino_I2C_IO_Global.digitalRead	(i  );}
	void	digitalWrite		(uint16_t i, uint8_t j)	{		iarduino_I2C_IO_Global.digitalWrite	(i,j);}
#endif

 

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

<PCF8574.h> мне понравилась больше

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

<PCF8574.h> мне понравилась больше

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

wdrakula пишет:

Женя. Это правда. Та библиотека перегружает стандартные digitalRead() и digitalWrite().

Так я и не спорил. Я не знаю той библиотеки, потому и сказал, что ТС виднее.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Ещё вопрос, нужно ли подтянуть INT пин микросхемы PCF к +5?

Если не притянут к +5, то на выходе INT Proteus кажет вопросительный знак, почему?

Если притянуть к +5 через 10кОм, то кажет 1.

При этом Ардуино считывает прерывания. Вот видео что происходит:

https://youtu.be/FqQTqywV4G8

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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

Поэтому в шпроте и чередуется 0 с высокоимпедансным состоянием (подключено в никуда)

Сделано это для возможности объединения практически неограниченного количества таких мс на одно прерывание, методом монтажного И

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Спасибо

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

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

https://www.youtube.com/watch?v=QnmePPzPFYc   (со 2 минуты)

Там такой код:

#include <Wire.h>
#define adres 0x20
#define adres1 0x21

void setup() {
Wire.begin();
Wire.beginTransmission(adres);
Wire.write(0b00000001);
Wire.write(0b00000000);
Wire.endTransmission();
}

void loop() {

}

Для чего отсылать два байта? (с одним байтом всё работает)

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

Потому что видео про 8575, а не про 8574. У первой в два раза больше I/O портов.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Вот это невнимательность.....Спасибочки. (надо закупаться 8575, количество адресов такое же, а портов в два раза больше)

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
#include <Wire.h>
#define adres 0x20
#define adres1 0x21

void setup() {
Serial.begin(9600);
Wire.begin();
Serial.println("Start");
}

void loop() {
Wire.requestFrom(adres1,7);  
if (Wire.available()){
Wire.beginTransmission(adres);
Wire.write(Wire.read());
Wire.endTransmission();
}

}

Я верно считываю с одной микросхемы и записываю в другую? 7 байт нужно считывать?

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

Больше ног - легче запутаться в них. Да и разводить сложнее. 

Еще есть мнение, что MCP23017 получше на выход работает.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Почему 6 , а не 7? Ножек же по 8 (16)

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

Больше ног - легче запутаться в них. Да и разводить сложнее. 

Еще есть мнение, что MCP23017 получше на выход работает.

Стоят дешевле. Надо попробовать.

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

Irinka пишет:

Почему 6 , а не 7? Ножек же по 8 (16)

Потомушто нечего по ютубу учиться программированию. Прокомментировать действия видеоблоггера я не могу. 

И зачем вам с одной PCF писать в другую 7 байт?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Одна ардуина будет собирать данные от 80-100 кнопок и передавать на расстояние (либо по радиоканалу, либо RS-485) другой ардуино, которая будет выводить светодиодами состояние кнопок.

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

И что, все эти кнопки у вас на одной PCF-ке? Вы понимаете, что с 8574, например, можно только один байт читать? Если у Вас семь раз спросить Ваше имя, то Вы назовете семь разных?

bwn
Offline
Зарегистрирован: 25.08.2014

Irinka пишет:

Вот это невнимательность.....Спасибочки. (надо закупаться 8575, количество адресов такое же, а портов в два раза больше)

Поаккуратней с 8575, которые мне на Али попадались, тянут только вниз, нету верхнего плеча.
P/S Да и корпус гнусненький.((((

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Понимаю.

#include <Wire.h>
#define adres 0x20
#define adres1 0x21
#define adres2 0x22
#define adres3 0x23
void setup() {
Serial.begin(9600);
Wire.begin();
/*Wire.beginTransmission(adres2);
Wire.beginTransmission(0b11111111);
Wire.beginTransmission(0b11111111);
Wire.write(Wire.read());*/
Serial.println("Start");
}

void loop() {
Wire.requestFrom(adres1,7);  
if (Wire.available()){
Wire.beginTransmission(adres);
Wire.write(Wire.read());
Wire.endTransmission();
}

Wire.requestFrom(adres2,7);  
if (Wire.available()){
Wire.beginTransmission(adres3);
Wire.write(Wire.read());
Wire.endTransmission();



}
}


Соответственно в цикле считывать буду.

 

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

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

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
#include <Wire.h>

byte Input[]={0x21,0x22}; 
byte Output[]={0x20,0x23};
 
unsigned long Times;





void setup() {
Serial.begin(9600);
Wire.begin();
Serial.println("Start");
}

void loop() {
 
if (millis()-Times>=500){
Times=millis();
Serial.println("Status");  

for (byte i=0; i<=2; i++){
Wire.requestFrom(Input[i],7);
  
if (Wire.available()){
Wire.beginTransmission(Output[i]);
Wire.write(Wire.read());
Wire.endTransmission();
}

}




}
}

как-то так

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

bwn пишет:

Irinka пишет:

Вот это невнимательность.....Спасибочки. (надо закупаться 8575, количество адресов такое же, а портов в два раза больше)

Поаккуратней с 8575, которые мне на Али попадались, тянут только вниз, нету верхнего плеча.
P/S Да и корпус гнусненький.((((

А мне что низ, что верх, разницы никакой.

 

sadman41 пишет:

Больше ног - легче запутаться в них. Да и разводить сложнее. 

Еще есть мнение, что MCP23017 получше на выход работает.

Полностью доверюсь мнению sadman41 и буду использовать их.

 

bwn
Offline
Зарегистрирован: 25.08.2014

Irinka пишет:

А мне что низ, что верх, разницы никакой.

Типа, на всякий случай.))) У меня транзисторы npn должны были открывать, всю плату переделывать пришлось.)))

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

Последний раз спрошу - зачем 7 байт читаете с однобайтовой PCF-ки?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

Последний раз спрошу - зачем 7 байт читаете с однобайтовой PCF-ки?

Wire.requestFrom(Input[i],1);

Всё всё всё...Поняла))))

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

В MCP23017 уже записываем 2 байта?

#include <Wire.h>


void setup() {

Wire.begin();
Wire.beginTransmission(0x20);
Wire.write("0b11111111");
Wire.write("0b11111111");
Wire.endTransmission();
}

void loop() {

}




 

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

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

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

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

Ну да, так и буду, при реализации передачи, скорее всего через RS-485

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Что-то неправильно я сделала

#include <Wire.h>


void setup() {

Wire.begin();
Wire.beginTransmission(0x20);
Wire.write("0b11111111");
Wire.write("0b11111111");
Wire.endTransmission();
}

void loop() {

}



 

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

Irinka пишет:

Что-то неправильно я сделала

Интуиция вас не подводит. А вот пальцы подводят - засылают в МС строки вместо байт.

В 23017 все через использование конретных регистров производится. Если автоинкремент не включен.

Инициализация первых восьми I/O как INPUT - в регистр 0x00 пишем 0xFF.
Инициализация вторых восьми - в регистр 0x01 пишем 0xFF.
Читаем первые восемь ног - с регистра 0x12, вторые - с регистра 0x13
 
Давно в руки ее не брал, подзабыл уж.
 
Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
#include<Wire.h>



void setup(){
Wire.begin();
//Порт А-все выходы
Wire.beginTransmission(0x20);
Wire.write(0x00);
Wire.write(0x00);
Wire.endTransmission();
//Порт B-все выходы
Wire.beginTransmission(0x20);
Wire.write(0x01);
Wire.write(0x00);
Wire.endTransmission();


//Порт А-все 1
Wire.beginTransmission(0x20);
Wire.write(0x12);
Wire.write(0xFF);
Wire.endTransmission();

//Порт B-все 1
Wire.beginTransmission(0x20);
Wire.write(0x13);
Wire.write(0xFF);
Wire.endTransmission();

}





void loop(){




}

Запись получилась. Чтение на день оставлю. Спасибо. Доброй ночи.

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

100 кнопок, это не клавиатура, случаем?

Если да, то проще обычную PS/2 подключить. 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Нее. Не она)

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

теперь всю ночь не спать буду, варочаца, думать, кудыж в Ардуине 100 кнопок надо. 

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

На ёлке лампочки зажигать.