CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

iAQ-Core from Hell - SOLVED
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

iAQ-Core from Hell - SOLVED
PostPosted: Wed Apr 26, 2017 8:11 am     Reply with quote

Hi All,

Has ANYONE used this sensor before?
https://ams.com/eng/content/download/686523/1787697/file/iAQ-core_Datasheet_EN_v1.pdf
I have a working driver and the sensor seems to be working properly but only after fighting with the ACKs and NACKs, I finally got it working by looking at the wave form on the Scope and flipping bits until i got 9 distinct byte transfers....
after visually/manually doing so the Chip stopped reporting wrong data, wrong flags, or simply just dropping all comms...seems stable.

This working solution i have seems to be stable only getting a "Busy" (real) flag from time to time which i expected as I'm reading the chip 8 times to produce 1 value.... I'm reading continuously every 1.5 seconds as the data sheet says 1s max rate.

My problem is that the ACK and NACKs that i have on my code are different from what the Data sheet says... but if I follow the datasheet exactly, it fails... Whats up with that?

I'm willing to share compare notes/code with anyone who has this chip...

I have a MLX90614 on the same I2C Bus...(no issues here) with the driver i posted a while back.

G.
_________________
CCS PCM 5.078 & CCS PCH 5.093


Last edited by Gabriel on Thu May 04, 2017 8:30 am; edited 1 time in total
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Wed Apr 26, 2017 8:44 am     Reply with quote

Don't question your working code - data sheets are frequently wrong. I'm not entirely surprised given how the data sheet is laid out and written.

Have you mentioned this to the manufacturer?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 26, 2017 9:05 am     Reply with quote

The chip has a 5 minute warm-up time. I looked at Arduino code on the
net for this chip, and it's not doing anything special. There is a warning
in the data sheet to never set the Write bit. If you want help, post your
code.
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Wed Apr 26, 2017 9:05 am     Reply with quote

The behaviour looks completely standard....
I think part of the problem is to understand that they are sometimes referring to the ACK bit, not the level, and (of course), that and 'ACK' is a low bit in I2C, where a NACK is a high bit. So the timing diagrams show 'ACK' in several places where the chip is returning a 'NACK'. This is because the diagram is just labeling the bit, not telling you what it's level will be...
Code:

#define CHIP_ADDR 0xB5
#define READ_OK 0
#define COLD 0x10
#define BUSY 0x1
#define ERROR 0x80
#define NOT_FOUND 0xA0

struct {
   unsigned int16 pred;
   unsigned int8 status;
   unsigned int32 resistance;
   unsigned int16 Tvoc;
} iAQ;

int8 load_IAQ(void)
{
    int8 * data_ptr;
    int8 ctr;
    const int8 offset[] = {1, 0, 2, 6, 5, 4, 3, 8, 7};
    int1 ack;

    data_ptr=&iAQ;
    //point to 9 byte structure for data
    //note that the chip sends MSB first. I've used a const array
    //to correct the byte order.
    i2c_start();
    ack=i2c_write(CHIP_ADDR);
    if (ack!=0)
    {
        i2c_stop();
        return NOT_FOUND; //chip not found error
    }
    //chip has acknowledged
    for (ctr=0;ctr<8;ctr++)
    {
        *(data_ptr+offset[ctr])=read_i2c();
    } //read 8 bytes with an acknowledge
    *(data_ptr+offset[8])=read_i2c(1); //no acknowledge on last byte
    i2c_stop();
    //now if status is not OK signal error
    return iAQ.status;
}


This should give you the structure iAQ filled with the data from the chip.

Have modified this so it returns the status with an added value (NOT_FOUND), for if the chip is not acknowledging.

So you can now just call this, and test the return for the status.


Last edited by Ttelmah on Wed Apr 26, 2017 1:32 pm; edited 1 time in total
avro698



Joined: 11 Nov 2006
Posts: 9
Location: South Wales, UK.

View user's profile Send private message

PostPosted: Wed Apr 26, 2017 9:24 am     Reply with quote

Hi Gabriel,

Yes, I've used it. You don't mention which version you are using, -P or -C. I used -C

As previously mentioned, you must wait for 5 minutes until 'real' data is available. Easiest way is to just read the whole 9 bytes from the device as follows: (doesn't show what I do with the data Wink )

i2c_start();
i2c_write(device_address);
i2c_read(1);
i2c_read(1);
i2c_read(1);
i2c_read(1);
i2c_read(1);
i2c_read(1);
i2c_read(1);
i2c_read(1);
i2c_read(0);
i2c_stop();

I dump the data straight into a structure (not shown) and just reference that.

avro698
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Wed Apr 26, 2017 3:19 pm     Reply with quote

Hi All,

Thank you for your support:

Code:
#define iAQ_Core_Read_Bit 0x01            // Read/Write direction bit - ONLY READ on this chip
#define iAQ_Core_ACK 0x00               // ACK for I2C transaction
#define iAQ_Core_NACK 0x01               // NACK for I2C transaction


Code:
   i2c_start();                     // Send Start Bit
   if (i2c_write(Command)==iAQ_Core_ACK)   // Send "Write" Command to the Device Address
   { 
      Raw_Data[0]=i2c_read(iAQ_Core_NACK);      // Prediction Byte0
      Raw_Data[1]=i2c_read(iAQ_Core_NACK);      // Prediction Byte1

      Raw_Data[2]=i2c_read(iAQ_Core_NACK);      // Status Byte

      Raw_Data[3]=i2c_read(iAQ_Core_NACK);   // Get first 8 data bytes without sending ACK
      Raw_Data[4]=i2c_read(iAQ_Core_NACK);   // Get first 8 data bytes without sending ACK
      Raw_Data[5]=i2c_read(iAQ_Core_NACK);   // Get first 8 data bytes without sending ACK
      Raw_Data[6]=i2c_read(iAQ_Core_NACK);   // Get first 8 data bytes without sending ACK

      Raw_Data[7]=i2c_read(iAQ_Core_NACK);   // Get first 8 data bytes without sending ACK
      Raw_Data[8]=i2c_read(iAQ_Core_ACK);      // Needs ACK on last byte only - Wierd.   
      i2c_stop();                        // Hammer Time


This is my final working "Read" sequence after much simplification and manual correction brutforcing ACKs and NACKS....

Ive had no further issues since but im hoping someone can shed some light on what the hell is up with this NACK ACK confusion..

I am aware of the warm up time and i have a status check function that redirects code and prints to screen different messages depending on the status byte value.

I am also aware of the Write bit restriction and have implemented a safety check to avoid setting it by mistake.

I have the "C" version for Continuous reads...

PLEASE NOTE: The comments might not match the actual working instructions.. i got this working this morning.


G.
_________________
CCS PCM 5.078 & CCS PCH 5.093
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Wed Apr 26, 2017 3:29 pm     Reply with quote

Under each wave form on the data sheet it explicitly says if there is an ACK/NACK.

Also the level of the ACK/NACK is shown by the wave form on the datasheet... at least im assuming the levels are correct.

Its particularly the requirement for ACK/NACK on the 4 resistance Byte that has me confused.

G.
_________________
CCS PCM 5.078 & CCS PCH 5.093
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 26, 2017 3:59 pm     Reply with quote

Your confusion is caused by CCS defining ACK and NACK differently for
i2c_read() and i2c_write(). See the manual:
Quote:

i2c_read( )

Syntax:
data = i2c_read();
data = i2c_read(ack);

Parameters:
ack -Optional, defaults to 1.
0 indicates do not ack.
1 indicates to ack.


Quote:
i2c_write( )

Returns:
This function returns the ACK Bit.
0 means ACK, 1 means NO ACK


In your code, you defined ACK/NACK in terms of how i2c_write() uses it.
But that's inappropriate for i2c_read(). For your read routine, you
should have several ACK's followed by a NACK at the end, at least in
terms of the parameter names. If you use 1's and 0's from the manual's
definition of the i2c_read() parameter, you would avoid the naming conflict.
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Thu May 04, 2017 8:31 am     Reply with quote

Thanks PCM... i did not know the ACK was diferent from read to write.

Sorry for the delay in response.. I went on holydays!
_________________
CCS PCM 5.078 & CCS PCH 5.093
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Sat May 06, 2017 10:04 am     Reply with quote

Hi Gabriel,

I, too, have been experimenting with the IAQ module, and it's mostly working fine. I have noted that every other read of the status byte is decimal 160. This occurs both during the warm-up and valid states. Everything else seems as expected except this result! Have you see this?
_________________
John

If it's worth doing, it's worth doing in real hardware!
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Sat May 06, 2017 10:59 am     Reply with quote

Though you now have it working, this is worrying.
Quote from data sheet:
Quote:

If the status is ERROR constantly (or very frequently) this
indicates that the module is reading non-realistic values, and
the sensor element is probably defective.


However it'd be worth seeing if reducing the frequency of your access has any change on this.
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Sat May 06, 2017 6:45 pm     Reply with quote

Hi,

I saw that in the datasheet, but I don't think that explains what I'm seeing. According to the documentation, the actual ERROR status is a return of 0x01. I'm not seeing that. If it's correct, the code I'm seeing doesn't seem to be documented in the docs. The actual data that is being returned by the module seems perfectly fine after the warm-up period, and access frequency does not seem to affect this issue. I've send an email to the manufacturer to see what they think!
_________________
John

If it's worth doing, it's worth doing in real hardware!
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Sun May 07, 2017 12:49 am     Reply with quote

No. ERROR is 0x80. 160 in decimal....
Code:

0x00: OK (data valid)
0x10: RUNIN (module in warm up phase)
0x01: BUSY (re-read multi byte data!)
0x80: ERROR (if constant: replace sensor)
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Sun May 07, 2017 5:59 am     Reply with quote

Hi Ttelmah,

Yes, you are correct, the ERROR code is 0x80, not 0x01 - my recollection was faulty when I wrote that. But, that is 128 decimal, not 160 decimal, so still undocumented. The return I'm getting 160 decimal is 0xA0. Weird!
_________________
John

If it's worth doing, it's worth doing in real hardware!
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Sun May 07, 2017 10:30 am     Reply with quote

0xA0 is RUNIN | ERROR. I don't believe it's a separate, unique, code - just those two being asserted simultaneously.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group