Solved: Help with Fleury's i2cmaster for Attiny841 and HIH9000 sensor

Go To Last Post
22 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since the ATtiny841's hardware TWI is can only be a slave, I am using Fleury's i2cmaster to communicate to the humidicon sensor, the slave. The code builds fine in AtmelStudio 7, but does not really do anything. I am using fleury's sample code. I have a few issues that I am not sure of and would like some help with resolving.

 

1. Not sure what to replace 0xA2 in "#define Dev24C02  0xA2"

2. I did not change the delay, not sure how to go about doing that

3. I set SDA and SCL to an unused pin for simple i/o, but did not set a direction. However, oscilloscope shows correct waveforms. (probably not this one then)

4. I may have soldered the HIH9131 soic incorrectly onto the DIP adapter for my breadboard. Damaged HIH9000 chip? (did not follow installation instructions)

 

Thanks

 

Edit:

I put breakpoints in Fleury's example code, but the program never stops at any of them. I am programming with JTAGIC3 (ISP) on debugWIRE.

 

Last Edited: Thu. Apr 6, 2017 - 12:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lambox wrote:
Not sure what to replace 0xA2 in "#define Dev24C02 0xA2"

You need to replace with I2C address of the HIH9131 (for the HIH6130/6131 Series, the default is 0x27, I do not know if this address applies to the HIH9131)

(Of course you should also change the "Dev24C02" to reflect the actual device used throughout the code...)

David (aka frog_jr)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You use the i2c_Master.S for bit-banging on a non-TWI chip. You might need to adjust the delay timing.
.
The main test code will link with the appropriate bit-bang or TWI version.
.
Note that you will have to splash out on REAL-LIFE external pull-up resistors.
And read the device datasheet to find the 8-bit Slave address.. e.g. 0x4E
.
David.

Last Edited: Wed. Mar 29, 2017 - 03:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have correctly soldered a new HIH9131 onto an adapter.

 

frog_jr wrote:

lambox wrote:
Not sure what to replace 0xA2 in "#define Dev24C02 0xA2"

You need to replace with I2C address of the HIH9131 (for the HIH6130/6131 Series, the default is 0x27, I do not know if this address applies to the HIH9131)

(Of course you should also change the "Dev24C02" to reflect the actual device used throughout the code...)

 

I have changed the line to "#define hih9131  0x27" according to what you said since the datasheet for the HIH9000 has nothing about the i2c address. I have also replaced Dev24C02 with hih9131 in the test code.

 

david.prentice wrote:
You use the i2c_Master.S for bit-banging on a non-TWI chip. You might need to adjust the delay timing. . The main test code will link with the appropriate bit-bang or TWI version. . Note that you will have to splash out on REAL-LIFE external pull-up resistors. And read the device datasheet to find the 8-bit Slave address.. e.g. 0x4E . David.

 

I have 4.7k pull-up resistors on the SDA and SCL line as instructed in the manual. Regarding the delay timing, according to fleury, "Adjust the  CPU clock frequency F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementation." However, I am using the software implementation. It seems like the .S file accommodates multiple frequency ranges in the current version, as well.

 

Code: https://pastebin.com/mwxtsb42

Side note: I am using PB2 for SCL and PA7 for SDA, so I have changed the define lines in the .S file to:

#define SDA             7           // SDA Port A, Pin 7 (PA7)   
#define SCL             2           // SCL Port B, Pin 2 (PB2)
#define SDA_PORT        PORTA       // SDA Port A
#define SCL_PORT        PORTB       // SCL Port B 

 

After stepping through with debugWIRE, it seems like it calls i2c_start_wait(hih9131+I2C_WRITE); the first time and waits forever. Thus, nothing happens. What could be wrong here? Could it be the delay?

 

 

Last Edited: Wed. Mar 29, 2017 - 03:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to look at the end of that spec sheet to find that there is a technical document called "I2C Communication with the Honeywell HumidIconTM Digital Humidity/Temperature Sensors" That should have the address details you need.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am not an I2C guru, so is there a reason you did not start the access to the I2C device with:

ret = i2c_start(hih9131+I2C_WRITE);       // set device address and write mode

to determine device availability?

David (aka frog_jr)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can find no reference to I2C Slave address in the HIH9000 document.   So I suggest that you scan the bus to find out for yourself.

 

I am always amazed by I2C datasheets that obfuscate this important information.

 

You simply loop through all possible addresses with i2c_start(ads) and see which return OK.   e.g. for (int ads = 2; ads < 256; ads += 2) ...

NEVER use i2c_start_wait() unless you have verified the address.   The Fleury example uses it to poll while the EEPROM is busy during a Page Write.

 

David.
 

Last Edited: Wed. Mar 29, 2017 - 04:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The document I referenced says:

 

2.1 Sensor Address

Each sensor is referenced on the bus by a seven bit slave address. The default address is 0x27. Other available addresses are: I2C Slave addresses from 0x00 to 0x7F. Please contact Honeywell Customer Service with questions regarding custom Slave addresses. 

Seems pretty clear to me.

 

The way I2C "addresses" are often written, that has to be left-shifted by 1 bit and the read/write bit has to be inserted into the LSB location.

 

Jim 

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Wed. Mar 29, 2017 - 05:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had not thought through it till Jim mentioned it, so (to be explicit) I believe you need:

ret = i2c_start((hih9131 << 1 ) + I2C_WRITE);

since the address is (thought to be) 0x27.

 

Edit: Or make the define:

#define hih9131 (0x27 << 1)

 

David (aka frog_jr)

Last Edited: Wed. Mar 29, 2017 - 05:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I gave 0x4E as an example in #3. Apparently, this address did not ACK.
Seriously, get the correct address and document whether you want to use 7-bit style or 8-bit style.
Fleury uses 8-bit style. So does the TWI peripheral.
.
Many other libraries use 7-bit style.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The document I referenced shows the address graphically as a 7-bit address occupying the high 7 bits of the 8-bit address byte. So, you MUST shift it and insert the read/write bit. Simpler is to convert it to 8-bit form 0x27<<1 = 0x4E

 

But, what you do depends on whether or not your TWI routine does the shifting internally or expects an 8-bit address. This is something YOU have to figure out.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, you don't. The Fleury docs tell you.
Your earlier post implies that Honeywell will supply custom chips with custom addresses. So even more reason to run the 3-line loop that tells you exactly which address is in the "custom" chip.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Second sentence in the quote says "0x27".

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

 

I found your doc after a bit of a struggle https://sensing.honeywell.com/i2c-comms-humidicon-tn-009061-2-en-final-07jun12.pdf

and sure enough,  it says:

2.1 Sensor Address
Each sensor is referenced on the bus by a seven bit slave
address. The default address is 0x27. Other available
addresses are: I2C Slave addresses from 0x00 to 0x7F. Please
contact Honeywell Customer Service with questions regarding
custom Slave addresses.

I am fairly gobsmacked.   That is a very large range of addresses.    It might mean that the devices are often customised.

 

The OP might find the tech note useful.  It shows you how to read the Status bits.

 

David.

Last Edited: Wed. Mar 29, 2017 - 08:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
I am fairly gobsmacked. That is a very large range of addresses. It might mean that the devices are often customised.
david.prentice wrote:
So even more reason to run the 3-line loop that tells you exactly which address is in the "custom" chip. .

I'm not an inveterate I2C user.  But indeed, in a new/unknown app, a "sniffer" routine to test the bus by calling out and seeing who answers is a great sanity check, IMO.  Not a bad thing to keep in the app, if practical, to be able to detect connection later on in the field or problem unit or similar.  IMO/IME.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Fleury uses 8-bit style. So does the TWI peripheral. . Many other libraries use 7-bit style. .

 

See: https://www.avrfreaks.net/comment...

 

And follow the link to: https://www.avrfreaks.net/comment...

 

#I2CAddressConfusion

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for all the help. I have been working on this on and off for the past week and have gotten it to work, for the most part. However, the data from the sensor gets stale after two cycles. I am following the instructions in "I2C Communication with the Honeywell HumidIconTM Digital Humidity/Temperature Sensorsfor Humidity and Temperature Data Fetch.

 

The first iteration of the loop: humH = 0x7F, humL = 0xFF, tempH = 0xFF, tempL = 0xFD

The second (assuming correct) iteration of the loop: humH = 0x1b, humL = 0xab, tempH = 0x60, tempL = 0x88

The third iteration of the loop: humH = 0x57, etc. (5 --> 0101, status bits: 01 --> Stale Data)

(Stale Data: When the status bits read “01”, “Stale” data is indicated. This means that the data in the output buffer of the sensor has already been fetched by the master, and has not yet been updated with the new data from the current measurement cycle. This can happen when the master polls the data quicker than the sensor can update the output buffer.)

 

Updated code: https://pastebin.com/hFCh68ak

 

I am assuming these lines should be changed somehow, but I am not sure how.

 

    humH = i2c_readAck();                    // read one byte from EEPROM
    humL = i2c_readAck();
    tempH = i2c_readAck();
    tempL = i2c_readNak();

 

Last Edited: Wed. Apr 5, 2017 - 02:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please tidy up your code.   e.g. use BIT_NAMEs.  post your USART code (e.g. to use stdio routines)

 

Then I will offer some constructive advice.  

 

Your project should work just fine.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tidied up code: https://pastebin.com/X0uQL1pj

i2cmaster.S 

 

I moved the measurement request lines back into the loop (since it should be done every time a measurement needs to  be made), but now all the values are like the first iteration. 7F, FF, FF, FD

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void THSense(void) {
    i2c_start_wait(hih9131w);               // measurement request
    i2c_stop();                             // set stop condition = release bus
    i2c_start_wait(hih9131r);               // set device address and read mode
    humH = i2c_readAck();                   // read one byte from EEPRO M
    humL = i2c_readAck();
    tempH = i2c_readAck();
    tempL = i2c_readNak();
    i2c_stop();
    hum = (humH << 8) + humL;
    temp = (tempH << 8) + tempL;
    hum = (hum << 2);
    hum = (hum >> 2);
    temp = (temp >> 2);
    humN = (hum/16382.0) * 100;
    tempN = ((temp/16382.0) * 165) - 40;

}

I would just:

void THSense(void) 
{
    i2c_start_wait(hih9131r);               // set device address and read mode
    humH = i2c_readAck();                   // read one byte from EEPRO M
    humL = i2c_readAck();
    tempH = i2c_readAck();
    tempL = i2c_readNak();
    i2c_stop();
    hum = (humH << 8) + humL;               // 16-bit value
    temp = (tempH << 8) + tempL;            // 16-bit value
    hum &= 0x3FFF;                          // top 2 bits are status
    status = humH >> 6;
    humN = (hum/16382.0) * 100;
    tempN = ((temp/16382.0) * 165) - 40;
}

Note that there is little point in calling this repeatedly.   You might just as well call once a second or once a minute.   Otherwise the status will whinge.

Alternatively,  you could poll the first byte.  Read the status,  throw away if not valid.

 

This is all very well.  But surely you would need a USART or LCD to report the values.  

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It works now. I had to insert delays after each Measurement request and data fetch.

 

while loop:

   Measurement Request

   1 second delay

   Data Fetch

   4 second delay

 

In terms of seeing the values, I am using debugWIRE and watching the values, but I will be sending data over USART to another system for display. This current system acts as a remote sensor.

Thanks for all the help!

Last Edited: Wed. Apr 5, 2017 - 03:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah-ha.   I see that you need the Measurement Request to start a conversion.

 

The data sheet / tech note tells you how long a conversion takes.

So you would split into two discrete transactions.

 

Or you read 4 bytes and immediately start a fresh request in a single transaction.

Throw away the first result.   Call the single transaction on a regular basis.

 

I would have produced output on a USART.    Only use debugWIRE if I had a problem.

 

David.