I2C Direccionamiento después de que se conoce la dirección del dispositivo

0

Tengo un dispositivo I2C que sé que la dirección es 0x70 (se detectó cuando se conectó a Raspberry Pi usando i2cdetect -y 1). Mi problema es que los bytes que quiero ver deben llamarse en WiringPi. La cadena de salida tiene una longitud de siete bytes y WiringPi mira la dirección del dispositivo y luego la dirección del byte que quiero leer. Dicho esto, el direccionamiento sería:

Device Addr. = 0x70:    Primer byte Addr. = 0x01 ----o----    Primer byte Addr. = 0x71

¿La dirección necesita una "nueva" identificación de dirección (comenzando desde 1) o el número de la dirección se "anexa" (sí, lo uso a la ligera) a la dirección del dispositivo?

Nueva información: Encontré esta documentación después de tamizar más profundo: Guía de actualización y Guía de comunicación corta

Parece que en la hoja de actualización, la dirección interna del esclavo para el byte de dirección es 0xE0 para escribir . El byte de comando que quiero usar es el comando (# 3.5): 0b000001100 (que asumo en hexadecimal: 0x0C ). Entonces parece que el byte de dirección para leer es 0xE1 . A partir de este punto, ¿cómo leería de los bytes de datos ya que sus registros no se muestran explícitamente (consulte la Guía de actualización)?

Aquí está mi código actual en WiringPi (C ++):

#include <iostream>
#include <errno.h>
#include <wiringPiI2C.h>

using namespace std;

#define SLAVE_ADDR 0x70
#define DEV_ADDR_W 0XE0
#define DEV_ADDR_R 0XE1
#define DEV_COMMAND 0X0C //GET STATUS


int main(){
    int fd,writeRes,comm_res,readRes;
    fd=wiringPiI2CSetup(SLAVE_ADDR);
    cout<<"Initial Result: "<<fd<<endl;

    for(int i=0;i<1;i++){
        writeRes=wiringPiI2CWriteReg8(fd,DEV_ADDR_W,0);
        cout<<"Write to Address(write): "<<writeRes<<endl;
        comm_res=wiringPiI2CWriteReg8(fd,DEV_COMMAND,0);
        cout<<"Slave Command Acknowledge: "<<comm_res<<endl;
        readRes=wiringPiI2CWriteReg8(fd,DEV_ADDR_R,0);
        cout<<"Write to Recieve Data: "<<readRes<<endl;
        int readD_1=wiringPiI2CReadReg8(fd,0x0D);
        cout<<"Data 1, VOC= "<<readD_1<<endl;
    }

    return 0;
}
pregunta Brandon Williams

2 respuestas

0

[Resuelto] Este módulo es una herramienta útil una vez que aprendes a trabajar con él. Después de enviar un correo electrónico a Gordon (de wiringPi), se señaló que estaba tratando de mirar demasiado profundo. Raspberry Pi se encargó de lo que me preocupaba. Sabiendo que se necesitaron algunas pruebas y errores para que las direcciones y los comandos fueran correctos, pero mi siguiente código parece funcionar antes de cerrar la calibración y probar la sensibilidad al CO2 (nota: la salida de 'cout' que lee el búfer de datos está desactivada. Pero eso no es demasiado importante en este momento):

#include <iostream>
#include <unistd.h>
#include <cstdint>
#include <wiringPiI2C.h>
#include <cerrno>

using namespace std;

const uint8_t dev_id = 0x70;
const uint8_t dev_addr = 0b000001100;
const uint8_t dev_comm = 0x0C;
const uint8_t dev_data = 0x00;

uint8_t getCRC(uint8_t bytes_to_send[6]){
    uint8_t byte_sum = 0x00;
    uint8_t crc;
    for(int i=0; i<6 ; i++){
        byte_sum += bytes_to_send[i];
    }
    crc = byte_sum;
    crc += (byte_sum/(0x0100));
    crc = 0xFF - crc;
    return crc;
}

int main(){
    int fd;
    int write_res;
    uint8_t sensor_data[8];
    int read_res;
    uint8_t crc;
    uint8_t out_buff[6]{dev_addr, dev_comm, dev_data, dev_data, 
        dev_data, dev_data};
    crc = getCRC(out_buff);
    cout<<"CRC: "<<(int)crc<<endl;
    uint8_t out_buff_full[7]{dev_addr, dev_comm, dev_data, dev_data, 
        dev_data, dev_data, 0xFF /*crc*/};
    if((fd=wiringPiI2CSetup(0x70)) < 0){
        cout<<"Error Occured in setting up Dev_ID: 0x70"<<endl;
        return 0;
    }
    else{
        cout<<"FD= "<<fd<<endl;
        cout<<"-------------Before Writing, Check Sensor Array---------------"<<endl;
        read_res = read(fd, sensor_data, 8);
        cout<<"1: "<<(int)sensor_data[0]<<endl;
        cout<<"2: "<<(int)sensor_data[1]<<endl;
        cout<<"3: "<<(int)sensor_data[2]<<endl;
        cout<<"4: "<<(int)sensor_data[3]<<endl;
        cout<<"5: "<<(int)sensor_data[4]<<endl;
        cout<<"6: "<<(int)sensor_data[5]<<endl;
        cout<<"7: "<<(int)sensor_data[6]<<endl;
        cout<<"8: "<<(int)sensor_data[7]<<endl;
        cout<<"-------------End Test Before Write---------------"<<endl;
        if((write_res = write(fd, out_buff_full, 7)) != 7){
            cout<<"There could be an issue writing to the file."<<endl;
            cout<<"Write returned: "<<write_res<<endl;
            return 0;
        }
        else{
            sleep(5);
            if((read_res = read(fd, sensor_data, 8)) != 8){
                cout<<"There could be an issue reading from the file."<<endl;
                cout<<"Read returned: "<<read_res<<endl;
                return 0;
            }
            else{
                cout<<"Returned Data {Address}: "<<(int)sensor_data[0]<<endl;
                cout<<"Returned Data {VOC}: "<<(int)sensor_data[1]<<endl;
                cout<<"Returned Data {CO2}: "<<(int)sensor_data[2]<<endl;
                cout<<"Returned Data {Raw Sensor Value[MSB]}: "<<(int)sensor_data[3]<<endl;
                cout<<"Returned Data {Raw Sensor Value}: "<<(int)sensor_data[4]<<endl;
                cout<<"Returned Data {Raw Sensor Value[LSB]}: "<<(int)sensor_data[5]<<endl;
                cout<<"Returned Data {Error Byte}: "<<(int)sensor_data[6]<<endl;
                cout<<"Returned Data {CRC}: "<<(int)sensor_data[7]<<endl;
            }
        close(fd);
        }
    }
    return 0;
}

Se verificó que este código funciona y resuelve mi problema.

Lección: Raspberry Pi es una computadora completa (incluso para protocolos de comunicación) y no puedes ir demasiado lejos por el agujero del conejo, te perderás.

Espero que esto ayude a cualquiera que pueda necesitar eso.     
respondido por el Brandon Williams
0

Consulte el siguiente código fuente de C, usando el controlador estándar de Linux I²C. La clave es entender la preparación del parámetro ioctl (). La transferencia completa de I²C es manejada automáticamente por el controlador del kernel.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>

int main(int argc, char* argv[]) {
    struct i2c_msg i2c_msgs[2];
    struct i2c_rdwr_ioctl_data i2c_transfer;
    uint8_t rdata[6];
    int fd;

    /* Open I2C device. */
    fd = open("/dev/i2c-1", O_RDWR);
    if (fd < 0) {
        perror("i2c device open");
        return 2;
    }

    /* Select and read CO2 register. */
    i2c_msgs[0].addr   = 0x70;
    i2c_msgs[0].flags  = 0;
    i2c_msgs[0].len    = 1;
    i2c_msgs[0].buf    = "\x08";

    i2c_msgs[1].addr   = 0x70;
    i2c_msgs[1].flags  = I2C_M_RD;
    i2c_msgs[1].len    = 6;
    i2c_msgs[1].buf    = (char*)&rdata;

    i2c_transfer.msgs  = i2c_msgs;
    i2c_transfer.nmsgs = 2;

    if (ioctl(fd, I2C_RDWR, &i2c_transfer) < 0) {
        perror("i2c CO2 read");
        return 2;
    };

    /* Print result. */
    printf("%02x %02x %02x %02x %02x %02x\n", rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5]);

    /* Finish. */
    close(fd);
    return 0;
}
    
respondido por el Janka

Lea otras preguntas en las etiquetas