简体   繁体   中英

Raspberry Pi and I2C in c++ with wiringPi for PCF8591

I'm trying to understand I2C bus for controlling a PCF8591 D/A Converter with the wiringPi C library on my Raspberry Pi B+.

I wrote a test code (in c++) which work fine, but I don't know if I'm doing it the right way. The program reads and display the 4 analog input values each 0.5 seconds, and set the output accordingly to the average value of the 4 inputs pins.

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

using namespace std;

int readInput(int fd, int reg)
{
    wiringPiI2CReadReg8(fd, reg);
    return wiringPiI2CReadReg8(fd, reg);
}

int main()
{
    wiringPiSetupGpio();
    int dacModule = wiringPiI2CSetup(0x48);
    if (dacModule < 0)
    {
        cout << "I2C Setup Error" << endl;
        return 0;
    }

    int i;
    int A[4]        = {0,       0,      0,      0};
    int A_Reg[4]    = {0x40,    0x41,   0x42,   0x43};

    while (1)
    {
        for (i=0;i<4;i++) A[i] = readInput(dacModule, A_Reg[i]);

        wiringPiI2CWriteReg8(dacModule, 0x40, (A[0]+A[1]+A[2]+A[3])/4);

        cout << endl;
        for (i=0;i<4;i++) cout << i << " : " << A[i] << endl;
        delay(500);
    }
    return 0;
}

My questions are :

  • I noticed I need to call the wiringPiI2CReadReg8 function twice in order to read the correct input value, why ? (If I don't do so, the function return the previous input value).
  • I read there is a special module of the wiringPi library specially made for the PCF8591 ( This one ), is there any performance differences between the two approach (special lib vs generic I2C lib) ?

Thanks a lot for your help / feedbacks.

To answer your first question: yes, that's normal. If you look to the datasheet (which you can find here ), you will see in figure 8 on page 8 that a read action is triggering a new conversion but will output the result of the previous conversion. So, you indeed need to read out 2 bytes if you want to know the current conversion by "forcing" two consecutive read actions one after the other. It's also again mentioned on the next page, second paragraph.

As for your second question, I have no experience yet with that library. But the source code is freely available, so you could check and compare your code/method with what you find in there.

I wrote the following code for PCF8591 using a C language. This cord work fine.

#include <wiringPi.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

/*
cc -o test1 test1.c -lwiringPi
*/

int main (void)
{
  int fd;
  int i;
  int a2dChannel = 0; // analog channel
  int a2dVal;
  float a2dVol;
  float Vref = 3.3;

  if ((fd = wiringPiI2CSetup(0x48)) < 0) {
    printf("wiringPiI2CSetup failed:\n");
  }

  for(i=0;i<20;i++) {
    wiringPiI2CWrite(fd,0x40 | a2dChannel);
    a2dVal = wiringPiI2CRead(fd); // Previously byte
    a2dVal = wiringPiI2CRead(fd);
    a2dVol = a2dVal * Vref / 255;
    printf("a2dVal=%d\n",a2dVal);
    printf("a2dVol=%f[V]\n",a2dVol);
    sleep(1);
  }
}

And you can use analogRead().

#include <wiringPi.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pcf8591.h>

#define PINBASE 100

/*
cc -o test2 test2.c -lwiringPi
*/

int main (void)
{
  int i;
  int a2dChannel = 0; // analog channel
  int a2dVal;
  float a2dVol;
  float Vref = 3.3;

  if (pcf8591Setup(PINBASE, 0x48) < 0)
  {
    printf("pcf8591Setup failed:\n");
  }

  for(i=0;i<20;i++) {
    a2dVal = analogRead(PINBASE + a2dChannel);
    a2dVol = a2dVal * Vref / 255;
    printf("a2dVal=%d\n",a2dVal);
    printf("a2dVol=%f[V]\n",a2dVol);
    sleep(1);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM