Shop OBEX P1 Docs P2 Docs Learn Events
PCF8591 input reads — Parallax Forums

PCF8591 input reads

Chicago MikeChicago Mike Posts: 88
edited 2008-01-23 22:17 in Propeller 1
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)   




-

Comments

  • deSilvadeSilva Posts: 2,967
    edited 2008-01-18 19:13
    (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 MikeChicago Mike Posts: 88
    edited 2008-01-20 14:55
    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!
  • deSilvadeSilva Posts: 2,967
    edited 2008-01-21 02:35
    EXT should be connected to Vss, not floating.
    If that does not work, you should check the ACKs, they should all be 0....
  • deSilvadeSilva Posts: 2,967
    edited 2008-01-23 22:17
    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
    
     +&#9472; &#61582;&#61576;&#61582;&#61576; &#9472;&#9488;
        A     O
      + O + - O - C D
     &#9484;&#9524;&#9472;&#9524;&#9472;&#9524;&#9472;&#9524;&#9472;&#9524;&#9472;&#9524;&#9472;&#9524;&#9472;&#9524;&#9488;
     &#9474;(8591)         &#9474;
     &#9474;               &#9474;
     &#9492;&#9516;&#9472;&#9516;&#9472;&#9516;&#9472;&#9516;&#9472;&#9516;&#9472;&#9516;&#9472;&#9516;&#9472;&#9516;&#9496; 
      &#61600; &#61600; &#61600; &#61600; - - - -
      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[noparse][[/noparse]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[noparse][[/noparse]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[noparse][[/noparse]SCL]~~
       outa[noparse][[/noparse]SDA]~  
      'The former two instructions need be done only once, if all is o.k.
    
       outa[noparse][[/noparse]SCL]~~   
       dira[noparse][[/noparse]SDA]~    ' Pulse SDA; HIGH by pullup (default)
       dira[noparse][[/noparse]SDA]~~   ' Enable = LOW
       outa[noparse][[/noparse]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[noparse][[/noparse]SDA] := by
        outa[noparse][[/noparse]SCL]~~                ' Transfer on rising edge
        by >>= 1
        outa[noparse][[/noparse]SCL]~ 
     
    ' Returns "acknowledge bit": 0 = ACK, 1 = NAK.
      dira[noparse][[/noparse]SDA]~            ' release SDA
      outa[noparse][[/noparse]SCL]~~           ' puls-in ACK
      status := ina[noparse][[/noparse]SDA]
      outa[noparse][[/noparse]SCL]~            ' keep CLK low
    
      
    PUB release
    ' Assert stop condition.
    ' SDA transits from LOW to HIGH whilst SCL is HIGH
      dira[noparse][[/noparse]SDA]~~           ' LOW
      outa[noparse][[/noparse]SCL]~~
      dira[noparse][[/noparse]SDA]~            ' release SDA (HIGH)
    
       
    PUB rcv : val
    ' Get a byte
      REPEAT 8
        outa[noparse][[/noparse]SCL]~~        ' Request bit
        val <<= 1
        val |= ina[noparse][[/noparse]SDA]
        outa[noparse][[/noparse]SCL]~         ' Keep CLK low
    
    
    PUB rcvack : val          ' new v002
    ' Get a byte... and more
      REPEAT 8
        outa[noparse][[/noparse]SCL]~~        ' Request bit
        val <<= 1
        val |= ina[noparse][[/noparse]SDA]
        outa[noparse][[/noparse]SCL]~         ' Keep CLK low
    
    ' Send ackbit
      dira[noparse][[/noparse]SDA]~~         ' set LOW
      outa[noparse][[/noparse]SCL]~~         ' Pulse SCL
      outa[noparse][[/noparse]SCL]~          ' keep CLK low 
      dira[noparse][[/noparse]SDA]~          ' release SDA  
    
    
    PUB nak                 ' mod v002
    ' Send ackbit
      dira[noparse][[/noparse]SDA]~            ' HIGH (korr!)
      outa[noparse][[/noparse]SCL]~~           ' Pulse SCL
      outa[noparse][[/noparse]SCL]~            ' keep CLK low
    
     
    PUB ack                'mod v002
    ' Send ackbit
      dira[noparse][[/noparse]SDA]~~         ' set LOW
      outa[noparse][[/noparse]SCL]~~         ' Pulse SCL
      outa[noparse][[/noparse]SCL]~          ' keep CLK low 
      dira[noparse][[/noparse]SDA]~          ' release SDA
    

    Post Edited (deSilva) : 1/23/2008 10:26:04 PM GMT
Sign In or Register to comment.