Shop OBEX P1 Docs P2 Docs Learn Events
Issue with PCF8591 A/D I2C converter - anyone used this? — Parallax Forums

Issue with PCF8591 A/D I2C converter - anyone used this?

CarlosFandangoCarlosFandango Posts: 67
edited 2008-10-27 18:20 in Propeller 1
Hi All,

I'm using a PCF8591 4 channel A-D converter in a current project, with Mike Green's Basic_I2C_Driver object. But there is an issue that I don't totally understand, so if anyone has used this I'd like some advice. Depending on how it's set, the device may transmit either a single channel's data, or all 4 channels at once. I'm reading it in single channel mode, and would like to think that a single read would suffice to obtain the latest conversion value. But currently, it seems, I can only get reliable data by reading the device twice in succession... page 10 of the data sheet (attached) does specify that "the first byte transmitted in a read cycle contains the conversion result code of the previous read cycle". I've tried reading various numbers of bytes from the device but as I say it's only reliable if read twice, so I believe that what I'm seeing is actually the result code which just happens to be the data from the channel that I requested during the PREVIOUS read.

This is my current code, at least the relevant bits:

In Basic_I2C_Driver, I have a modded function that reads two bytes from a device:

PUB readlocation2(SCL,device_address,register) | value
' Read two successive bytes from device at address
' Control byte is 'register'
start(SCL)
write(SCL,device_address | 0)
write(SCL,register)
start(SCL)
write(SCL,device_address | 1)
value := read(SCL,ACK) & 255
value := value << 8
value += read(SCL,NAK) & 255
stop(SCL)
return value

And in my object my read has to be specified thus:

PRI ReadADC(channel) | r
{{

ReadADC(channel) channel is 0..3
Reads the specified a to d channel in single-ended mode
For some reason unknown to me it's necessary to read the required channel twice...?
Surely, this is an error but I haven't been able to make it work any other way.
Warrants further investigation, as it makes everything slower (albeit reliable!)

}}

i2c.readlocation2(20,%10010000,channel) ' First read discarded
r := i2c.readlocation2(20,%10010000,channel) ' Second read is 'genuine' one
' Shift right 8 bits to get the proper value (1st byte is code of last conversion)
r := r >> 8
return r

Anyone...?!

-CF

Comments

  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2008-10-26 19:02
    CF,
    I looked at the data sheet for the ADC and the data outputs lags the conversion by one sample. I didn't spend a great deal of time looking at it but take a look at the bottom page 8 of the attachment.
    Jim-

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Signature space for rent, only $1.
    Send cash and signature to CannibalRobotics.
  • CarlosFandangoCarlosFandango Posts: 67
    edited 2008-10-26 19:38
    Hi Jim - thanks for that data sheet, it's 5 years newer than mine!

    However, this is what I'm doing (I think...). That's what the ReadLocation2() routine does, or what it's supposedly doing - specifically reading two bytes from the bus, with the intention of getting "Value of data byte 1"... it's weird. I don't know what's happening here at all. It seems strange to me that it would be necessary to read twice going by what's in the data sheet - how could that be right? The sheet seems to imply that the conversion task takes at least as long as it takes to read 1 byte, so the 'previous value' is just put in there [noparse][[/noparse]I suppose] because it might be useful, and it fills in the time that the chip needs to do its job.

    Hmmm... if I could get it to work properly I could save some significant cycle time...!
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2008-10-26 19:57
    In the AD conversion description it says:

    An A/D conversion cycle is always started after sending a valid read mode address to a PCF8591 device. The A/D
    conversion cycle is triggered at the trailing edge of the acknowledge clock pulse and is executed while
    transmitting the result of the previous conversion (see Fig.9).
    The first byte transmitted in a read cycle contains the conversion result code of the previous read cycle.

    I think your stuck with at least two read cycles. What I've done with A to D's is just start a cog that free runs constantly sampling all of the channels and loading them into an array. That way your other modules never have to wait for the data, it just grabs the last data. That's the beauty of having all of these cogs. I guess it depends on what your acceptable update rate is.
    If you want I can send you my code for this but you'll have to wait until tomorrow as it's on my PC in the lab at the shop.
    Jim

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Signature space for rent, only $1.
    Send cash and signature to CannibalRobotics.
  • CarlosFandangoCarlosFandango Posts: 67
    edited 2008-10-27 08:28
    Jim-

    Yep, I think you're right. Another cog would do the trick, although I probably don't need this as the I2C code runs in its own anyway - I just need to modify the message passing system a bit more and have the it free-run for this channel (it already does this as it happens, for a set of buttons attached to one of the other analogue lines). In fact come to think of it now, the best way would be for it to request all 4 channels at once, that would be faster for sure - even if it does still have to do two reads.

    I don't think I need any code right now as it seems simple enough - however, if you do post it up, I will of course be happy to steal the best bits!

    -CF
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2008-10-27 14:34
    Here it is.
    I think this is actually on the object sharring side too.
    Enjoy.


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Signature space for rent, only $1.
    Send cash and signature to CannibalRobotics.
  • CarlosFandangoCarlosFandango Posts: 67
    edited 2008-10-27 18:20
    Thank you Jim!
Sign In or Register to comment.