PDA

View Full Version : PCF8591 input reads



Chicago Mike
01-18-2008, 11:20 PM
I have a few questions about reading from a PCF8591. I'm read over the datasheet several times and there are some this that I just don't get.
Below is a small bit of code I'm using to attempt to read Input 3.




PUB ReadAD(SCL, devSel) | ackbit,data1,data2

Start(SCL)
ackbit := (ackbit << 1) | Write(SCL, (devSel&!(|<0)))
ackbit := (ackbit << 1) | Write(SCL, %00000011)
Start(SCL)
ackbit := (ackbit << 1) | Write(SCL, (devSel|1))
data1:=Read(SCL,ACK)
data2:=Read(SCL,NAK)
Stop(SCL)
return data2




I seem to always get a 128. (When I have the input pin at 3.3 volts, which is what the PCF is running at, which should result in data2 reading 255).

My questions are:
- Obviously, this type of selective read isn't working? Any tips?
- The datasheet and the nuts and volts article I read refer to having to ditch the first read value because its the 'last' value. I'm doing this with the data1 variable in this case. Is this really needed in a selective read like this?
- I don't understand the auto increment. I'm not using it here, but if I used it, would I just perform 5 reads. (The first one being junked because of the above, and then I would read the 4 inputs?
- DO I need to re issue the control byte on every read like the above, or after executing it once, can I continuously perform the following to get constant updates



Start(SCL)
ackbit := (ackbit << 1) | Write(SCL, (devSel|1))
data1:=Read(SCL,ACK)
data2:=Read(SCL,NAK)
Stop(SCL)




-

deSilva
01-19-2008, 02:13 AM
(1) I think you should terminate the configuration by a STOP, it will be best to also provide a third (zero) byte as D/A value.
(2) After that you can read ad infinitum; you either get the values from one channel or cycling through the 4.
(3) I think there is too much ado about this "first" value... It is just the last value sampled, as the sampling process will only start with the read command and takes some time, so it MIGHT be unclear from what channel and from what time this value comes...

(4) I am not sure with what channel each new read starts in auto-incrementing mode.. I THINK it will will go on with the last channel, so it might be a good practice to repeat the configuration setting before each sequence of reads...

Chicago Mike
01-20-2008, 09:55 PM
I added the stop bit and added a blank data byte as discussed and it seems I'm getting the same result. Its really strange I seem to get a $80 or 128 reading MOST of the time, but occasionally I get an accurate reading. Its just takes 30 seconds, but then it will pop back up to 128 on and off. Even if I tie it to ground from the start. 128 is the magic value. I'm starting to wonder if this is my circuit. I did try to different PCF 8591 in the event I fried one. No different.

Heres the current code running in a loop:



UB ReadAD(SCL, devSel) | ackbit,data1,data2

Start(SCL)
ackbit := (ackbit << 1) | Write(SCL, (devSel&!(|<0)))
ackbit := (ackbit << 1) | Write(SCL, %00000011)
ackbit := (ackbit << 1) | Write(SCL, %00000000)
Stop(SCL)

Start(SCL)
ackbit := (ackbit << 1) | Write(SCL, (devSel|1))
data1:=Read(SCL,NAK)
Stop(SCL)
return data1




My circuit
PIN = Tied to
--------------------
(1-3)AIN1-AIN2 = Vss
(4)AIN3 = (Sampling input, for testing I've tied this to 3.3 volts)
(5-7)A0-A2 = Vss
(8)Vss = Vss
(9-10)SDA-SCL = I2c bus
(11)OSC = Floating
(12)EXT = Floating
(13)AGND = Vss
(14)VRef = 3.3V(Vdd)
(15)AOut = Floating
(16)Vdd = 3.3v

Very, very strange, I'm stumped. This is such a basic component.

Thanks!

deSilva
01-21-2008, 09:35 AM
EXT should be connected to Vss, not floating.
If that does not work, you should check the ACKs, they should all be 0....

deSilva
01-24-2008, 05:17 AM
Mike - most likely you solved your issue..

If not here is code that is checked with my "smallI2Cdriver":


'' MPE_I2C_002
'' Minimal I2C driver 2008-01 by deSilva



' ----- The following section is a test routine
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000

DEVICE = $90
LEDPIN = 25

PUB checkOut | i , x , status
{
This checks my minimal I2C driver, using a PCF8591 DAC/4-Channel ADC

+─  ─┐
A O
+ O + - O - C D
┌┴─┴─┴─┴─┴─┴─┴─┴┐
│(8591) │
│ │
└┬─┬─┬─┬─┬─┬─┬─┬┘
    - - - -
0 1 2 3


At pin OO a 1.5 kHz signal should be measured (conversion clock)
AO will output DAC
}


REPEAT
engage
i:=snd(DEVICE)
i := (i<<1) + snd($00) ' read from Port 0
' $04 : cycle through all ports
release
REPEAT
engage
i:= (i<<1) + snd(DEVICE+1)
DIRA[LEDPIN]:= (i<>0)
x := rcv
{ or read multiple values...
ACK
x := rcv
}
release



' An alternative: Generate a Ramp-Up

REPEAT
engage
i:=snd(DEVICE)
i := (i<<1) + snd($40)
DIRA[LEDPIN]:= (i<>0)
REPEAT x from 0 to 255
snd(x)
release




' ===========Here starts deSilva's small I2C driver (V.002)
CON
SCL = 28
SDA = 29

PUB engage
' Pulls SDA to LOW whilst CLK is HIGH

dira[SCL]~~
outa[SDA]~
'The former two instructions need be done only once, if all is o.k.

outa[SCL]~~
dira[SDA]~ ' Pulse SDA; HIGH by pullup (default)
dira[SDA]~~ ' Enable = LOW
outa[SCL]~ ' Keep SCL LOW


PUB snd(by) : status | i
' Send a byte (and get status: 0: ACK 1: NAK)

by := (!by) >< 8 ' Reverse bits and invert pattern
REPEAT 8
dira[SDA] := by
outa[SCL]~~ ' Transfer on rising edge
by >>= 1
outa[SCL]~

' Returns "acknowledge bit": 0 = ACK, 1 = NAK.
dira[SDA]~ ' release SDA
outa[SCL]~~ ' puls-in ACK
status := ina[SDA]
outa[SCL]~ ' keep CLK low


PUB release
' Assert stop condition.
' SDA transits from LOW to HIGH whilst SCL is HIGH
dira[SDA]~~ ' LOW
outa[SCL]~~
dira[SDA]~ ' release SDA (HIGH)


PUB rcv : val
' Get a byte
REPEAT 8
outa[SCL]~~ ' Request bit
val <<= 1
val |= ina[SDA]
outa[SCL]~ ' Keep CLK low


PUB rcvack : val ' new v002
' Get a byte... and more
REPEAT 8
outa[SCL]~~ ' Request bit
val <<= 1
val |= ina[SDA]
outa[SCL]~ ' Keep CLK low

' Send ackbit
dira[SDA]~~ ' set LOW
outa[SCL]~~ ' Pulse SCL
outa[SCL]~ ' keep CLK low
dira[SDA]~ ' release SDA


PUB nak ' mod v002
' Send ackbit
dira[SDA]~ ' HIGH (korr!)
outa[SCL]~~ ' Pulse SCL
outa[SCL]~ ' keep CLK low


PUB ack 'mod v002
' Send ackbit
dira[SDA]~~ ' set LOW
outa[SCL]~~ ' Pulse SCL
outa[SCL]~ ' keep CLK low
dira[SDA]~ ' release SDA

Post Edited (deSilva) : 1/23/2008 10:26:04 PM GMT