Ich habe ein I2C-Gerät, von dem ich weiß, dass die Adresse 0x70 ist (geprüft, wenn es mit i2cdetect -y 1 an Raspberry Pi angeschlossen ist). Mein Problem ist, dass die Bytes, die ich mir ansehen möchte, in WiringPi aufgerufen werden müssen. Der Ausgabe-String ist sieben Byte lang und WiringPi schaut auf die Geräteadresse und dann auf die Byte-Adresse, die ich lesen möchte.Würde die Adressierung wie folgt aussehen:
Device Adr.= 0x70: First Byte Adr.= 0x01 ----oder---- First Byte Adr.=0x71
Benötigt die Adresse eine 'neue' Adressidentifikation (beginnend bei 1) oder wird die Adressnummer an die Geräteadresse 'angehängt' (ja, ich verwende das locker)?
Neue Informationen: Ich habe diese Dokumentation gefunden, nachdem ich sie gründlicher durchsucht hatte: Upgrade Guide und Short Communication Guide
Es scheint, dass aus dem Upgrade-Blatt die interne Adresse des Slaves für das Adressbyte 0xE0 für das Schreiben lautet . Das Befehlsbyte, das ich verwenden möchte, ist der Befehl (#3.5): 0b000001100 (was ich in Hex annehme: 0x0C ). Es scheint dann, dass das Adressbyte zum Lesen 0xE1 ist . Wie würde ich von diesem Punkt an aus den Datenbytes lesen, da ihre Register nicht explizit angezeigt werden (siehe Upgrade Guide)?
Hier ist mein aktueller Code in 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;
}
Bitte sehen Sie sich den folgenden C-Quellcode an, der den Standard-Linux-I²C-Treiber verwendet. Der Schlüssel liegt im Verständnis der Parametervorbereitung von ioctl(). Der komplette I²C-Transfer wird vom Kernel-Treiber automatisch abgewickelt.
#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;
}
struct i2c_msg i2c_msgs[2];
Fehlermeldung, die besagt, dass der Array-Typ einen unvollständigen Elementtyp hat. Und zweitens, meintest du etwas anderes als I2C_M_RD
wie etwas von hier#include <sys/ioctl.h>
und #include <linux/i2c.h>
zur Liste der Einschließungen hinzu. Leider enthält die explizite erforderliche Änderung mit jeder API-Version../i2ctest2
(benannt mit gcc -o) ergibt sich aSegmentation Fault
gdb ./i2ctest2
, dann run
an der gdb-Eingabeaufforderung.i2c_transfer.msgs =i2c_msgs;
, könnte das das Problem sein?[Gelöst] Dieses Modul ist ein nützliches Werkzeug, sobald Sie gelernt haben, wie man damit arbeitet. Nachdem ich Gordon (von wiringPi) eine E-Mail geschickt hatte, wurde darauf hingewiesen, dass ich versuchte, zu tief zu schauen. Raspberry Pi kümmerte sich um das, worüber ich mir Sorgen machte. In dem Wissen, dass es einige Versuche und Irrtümer bedurfte, um Adressen und Befehle korrekt zu erhalten, aber mein folgender Code scheint zu funktionieren, bevor die Kalibrierung und das Testen der CO2-Empfindlichkeit abgeschlossen sind (Hinweis: Der 'cout'-Ausgang, der den Datenpuffer ausliest, ist ausgeschaltet. Aber das ist es nicht zu jetzt wichtig):
#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;
}
Dieser Code wurde verifiziert und löst mein Problem.
Janka
Brandon Williams
crj11
Brandon Williams
Janka
Nick Alexejew
crj11
Brandon Williams
Janka
Brandon Williams
crj11
SamGibson
Nick Alexejew
Brandon Williams