Go Down

Topic: Problemas de comunicacion PCF8574 IO Expander (Read 512 times) previous topic - next topic

snalgur

Apr 30, 2020, 03:55 pm Last Edit: May 09, 2020, 12:54 am by snalgur
Buenas! Ando buscando algún consejo o ayuda .
Vengo trabajando en un proyecto donde estoy usando un ARDUINO MKR Wifi 1010 y una placa expansora IO PCF8574.


La Idea es controlar las 8 salidas donde voy a conectar 8 relays.
Estos Relay son controlados a través de IOT de ARDUINO.


He probado de todo... y no logro redondear la operación y que funcione.


--> Los problemas Sin usar alguna librería.

No podía mandar los ocho bits (xxxxxxxx).
Es decir no encontré la forma de por ejemplo formar la secuencia: 00001111
para enviarla el modulo PCF8574.
Probé mil maneras, no hubo forma de que me funcione.
Uno de los tantos códigos que probé fue :   (RESUMEN DE LA SECCION QUE IMPORTA)
Code: [Select]

#include <Wire.h>
bool UNO=0;

bool OCHO=0;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Serial.println("Comienzo");
  delay(5000);
}

void loop()
{
  // Escribir dato en canal 'channel'
  delay(2000);
  Wire.beginTransmission(0x38);
  Wire.write(UNO+DOS*10+TRES*100....+OCHO*10000000);
  Wire.endTransmission();
 }



NADA...

Entonces pase a alguna solución con librerías.
La que pude cargar  y que compilara, fue la siguiente:
https://github.com/davetcc/IoAbstraction

El ejemplo funciona , pero cuando cargo el programa completo no me funciona...
dejo el código para ver si alguno me ayuda a encontrar el problema
Hay una sección que es la comunicación con un ARDUINO UNO (aviso para evitar la confusión)

Code: [Select]

#include "Wire.h"
#include "thingProperties.h"
#include <IoAbstraction.h>
#include <IoAbstractionWire.h>
IoAbstractionRef ioExpander = ioFrom8574(0x38); //Adress PCF8574

uint8_t UNO=0;
uint8_t CUATRO=0;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you'll get.
     The default is 0 (only errors).
     Maximum is 4
  */
  setDebugMessageLevel(4);
  ArduinoCloud.printDebugInfo();

  //Conexion I2C Maestro
  Wire.begin(); // join i2c bus (address optional for master)
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(5000);
  Serial.println("I am I2C Master");
  ioDevicePinMode(ioExpander, 0, OUTPUT);
  ioDevicePinMode(ioExpander, 1, OUTPUT);
  ioDevicePinMode(ioExpander, 2, OUTPUT);
  ioDevicePinMode(ioExpander, 3, OUTPUT);
  ioDevicePinMode(ioExpander, 4, OUTPUT);
  ioDevicePinMode(ioExpander, 5, OUTPUT);
  ioDevicePinMode(ioExpander, 6, OUTPUT);
  ioDevicePinMode(ioExpander, 7, OUTPUT);
  ioDeviceDigitalWriteS(ioExpander, 0, 1);
  ioDeviceDigitalWriteS(ioExpander, 1, 1);
  ioDeviceDigitalWriteS(ioExpander, 2, 1);
  ioDeviceDigitalWriteS(ioExpander, 3, 1);
  ioDeviceDigitalWriteS(ioExpander, 4, 1);
  ioDeviceDigitalWriteS(ioExpander, 5, 1);
  ioDeviceDigitalWriteS(ioExpander, 6, 1);
  ioDeviceDigitalWriteS(ioExpander, 7, 1);
}

void loop() {
  ArduinoCloud.update();
  // Your code here
  delay(5000);
  Serial.println("----------------");
  Wire.requestFrom(10, 3); /* request & read data of size 3 from slave */
  /* read data received from slave */
  while (1 < Wire.available()) {
    int TempHeladera = (Wire.read() - 30);
    Serial.print("Recibido por I2C: ");
    Serial.println(TempHeladera);
  }
  //Expansor PCF8574

 
}

void onONOFFHeladeraChange() {
  // Do something
  Wire.beginTransmission(10); // transmit to device #10
  Wire.write(2); //Indicamos que es un comando
  Wire.write(ONOFFHeladera);
  Serial.println("Envio por I2C");
  Serial.print("Estado ON/OFF de la Heladera: ");
  Serial.println(ONOFFHeladera);
  Wire.endTransmission(); // stop transmitting
}

void onTempHeladeraChange() {
  // Do something
}

void onSettempHeladeraChange() {
  // Do something
  Wire.beginTransmission(10); // transmit to device #8
  Wire.write(1); //Indicamos que es DATO
  int settempaux = SettempHeladera + 50;
  Wire.write(settempaux);
  Serial.println("Envio por I2C");
  Serial.print("Set de Temp de la Heladera: ");
  Serial.println(SettempHeladera);
  Wire.endTransmission(); // stop transmitting
}

void onInteriorChange() {
  // Do something
  if (interior == true) {
    ioDeviceDigitalWriteS(ioExpander, 0, 1);
    UNO=1;
    Serial.println("Encendido de interior");
  }
  if (interior == false) {
    ioDeviceDigitalWriteS(ioExpander, 0, 0);
    UNO=0;
    Serial.println("Apagado de interior");
  }
}

void onLuzdetopeChange() {
  // Do something
  if (luzdetope == true) {
    ioDeviceDigitalWriteS(ioExpander, 3, 1);
    CUATRO=1;
    Serial.println("Encendido de Luz de tope");
  }
  if (luzdetope == false) {
    ioDeviceDigitalWriteS(ioExpander, 3, 0);
    CUATRO=0;
    Serial.println("Apagado de Luz de tope");
  }
}



Pido Disculpas si es muy enroscado todo, cualquier cosa trato de explicarlo de manera diferente lo que no se entienda..

Gracias

surbyte

Modeador
Bueno venías muy bien con toda la presentación del problema hasta que colocaste la imagen y no la hiciste visible. Por favor, edita tu post y mirá al final de las normas como se hace para corregir esta leve falta en tu posteo incial.



Si, con el tutorial de Luis llamas no lo resuelves, es porque estas mirando otro canal.

Asegúrate de estar en la dirección I2C adecuada a tu PCF8574, usa el scanner I2C para asegurarte.

snalgur

Listo! Corregido! :)

La librería que mencionas, ya la probé y nada... no pude sacar nada en limpio.
La dirección también la corrobore y nada.



altarion10

#3
Jul 07, 2020, 10:43 am Last Edit: Jul 07, 2020, 10:49 am by altarion10
Hola! yo tambien tuve algun que otro problema enviando las ordenes mediante bytes binarios. Al final decidí enviar la informacion mediante un número decimal. No se si será la opción más idónea, pero a mi me funciona. Te dejo el código que he utilizado por si quieres echarle un ojo:



Code: [Select]


////////////////////////////////////////////////////////////////////////////////////////////////////


void escribir_i2c (byte dato){

  Wire.beginTransmission(0x20);
  Wire.write(dato);
  Wire.endTransmission();

}//escribir i2c

/////////////////////////////////////////////////////////////////////////////////////////////////////////

byte BIN_DEC(){

byte b = 0;

for(int x=2;x<7;x++){
  b+= ( electrovalvula[x] << x);
}
b+= (bomba << 7);

return (~(b));

  Serial.print("I2C: "); Serial.println(~b);  
     
}//bin_dec

//////////////////////////////////////////////////////////////////////////////////////////

void regar(unsigned long tiempo_riego, unsigned long tiempo_comprobar){

 switch(modo){
   
   case 0://desactivado
     apagar_todo();    
   break; //modo desactivado, no riega

   case 1://automatico
     for(i=0;i<8;i++){
       abrir_valvulas(i);
       cerrar_valvulas(i, tiempo_riego);
       comprobar(i, tiempo_comprobar);
     }
   break;

   case 2: //manual
     control_manual();
   break;

   case 3: //programador
     control_programador();
   break;  
 
 }//switch

 //una vez he controlado lo que quiero encender o apagar, en los distintos modos de funcionamiento, acctivo las válvulas.
 // y la bomba la encendere dentro de la funcion del control de la bomba.

 escribir_i2c(BIN_DEC());
   
}//regar



La funcion regar engloba otras funciones de mi programa, pero al final de ella es donde mando la informacion al pcf8574, recogiendo el dato convertido a decimal que me devuelve BIN_DEC().

Puedes observar que el bucle for empieza con i=2, esto es simplemente porque los reles a activar empiezan a partir del tercero, ya que tuve que cortar el modulo de reles para que entraran en la caja. Pero la funcionalidad del codigo es la misma.
Tambien tengo que invertir el dato a enviar, ya que los reles se activan con un false.

Un saludo, espero que te haya podido ayudar

tauro0221

Hi,
Aqui yo veo este problema. La palabra que envias es the 8 bits. Aqui esta tu instruccion "  Wire.write(UNO+DOS*10+TRES*100....+OCHO*10000000)" porque este numero tan grande para una palabra de 8 bits. Trata de por ejemplo wire.write(0xFF). Esto hace que todos los bits de output =1.Tratalo para ver si te trabaja.

Go Up