Reading from sensor with TWI

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

Hi guys,

I'am using ATmega644p and hih-6130-i2c sensor for reading temperature and realative humidity.

I want read all 4 bytes and then show values on LCD display. Data sending on the display is complete, but i cannot read 4 bytes from sensor.

 

I attach my code to read sensor data

 

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <util/twi.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "MLCDFN.h"//nacteni hlavickoveho souboru

#define POCET_BYTU 4
#define SLV_ADDRESS 0x27

#define TW_SEND_START TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
#define TW_SEND_STOP TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
#define TW_SEND_DATA TWCR = (1<<TWINT) | (1<<TWEN)
#define TW_RECEIVE_DATA TWCR = (1<<TWINT) | (1<<TWEN)
#define TW_WAIT while(!(TWCR & (1<<TWINT)))


char data[POCET_BYTU] = {};
char i2c_precti_pole(char adresa, char *pole, unsigned int pocet_bytu); 


			
int main()
{



	TWBR = 32;
	TWCR = (1<<TWEN);
	
	
  
    while(1) 
	{
		i2c_precti_pole(SLV_ADDRESS,data,POCET_BYTU);
		
		unsigned int HB,TB;
		
		HB = ((data[0] & 0x3F) << 8) | (data[1]);
		TB = ((data[2] << 8)| (data[3]);



	}
}

char i2c_precti_pole(char adresa, char *pole, unsigned int pocet_bytu)
{
	unsigned int i;

	adresa = adresa << 1;

	TW_SEND_START;

	TW_WAIT;

	if ((TW_STATUS) != TW_START){ return 1;}

	TWDR = adresa | 1;

	TW_SEND_DATA ;

	TW_WAIT;

	if ((TW_STATUS) != TW_MR_SLA_ACK){TW_SEND_STOP; return 2;}

	TW_RECEIVE_DATA | (1<<TWEA);

	i = 0;

	while(i < pocet_bytu){

		TW_WAIT; 

		switch(TW_STATUS){

			case TW_MR_DATA_ACK:

			pole[i] = TWDR;

		if (i < pocet_bytu-1){i++;}

		if (i >= (pocet_bytu-1)){TW_RECEIVE_DATA;}

		else {TW_RECEIVE_DATA | (1<<TWEA);}

			break;

			case TW_MR_DATA_NACK:

			pole[i] = TWDR;

			i++;

			break;

			default:

			TW_SEND_STOP;

			return 2;
		 }
		}

	TW_SEND_STOP;
	return 0;
}



 

data fetch from sensor

This topic has a solution.

New

Last Edited: Sat. Mar 16, 2019 - 11:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are far better off using a respected library for TWI than trying to write it from scratch (unless you goal here really is more about learning TWI than just making  hih-6130  work?).

 

Perhaps see:

 

manual: http://homepage.hispeed.ch/peter...

code: http://homepage.hispeed.ch/peter...

 

As his example shows, using TWI then becomes something like:

 

int main(void)
{
    unsigned char ret;
    i2c_init();                             // initialize I2C library
    // write 0x75 to EEPROM address 5 (Byte Write) 
    i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
    i2c_write(0x05);                        // write address = 5
    i2c_write(0x75);                        // write value 0x75 to EEPROM
    i2c_stop();                             // set stop conditon = release bus
    // read previously written value back from EEPROM address 5 
    i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
    i2c_write(0x05);                        // write address = 5
    i2c_rep_start(Dev24C02+I2C_READ);       // set device address and read mode
    ret = i2c_readNak();                    // read one byte from EEPROM
    i2c_stop();
    for(;;);
}

Actually this example breaks one of the fundamental rules of using an I2C library - almost everything you do returns a code to say whether it worked or not. Presumably for brevity, this example just calls the functions and ignores their return values - you shouldn't.

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

I dont know if this is relevant, but normally you should define the F_CPU before using a normal _delay_ms() or _delay_us() function:

 

this is what you are doing:

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <util/twi.h>
#include <util/delay.h> // <--------- here
#include <avr/interrupt.h>

some where up just do something like this:

 

#define F_CPU 5000000 // e.g. 5MHz

this is only valid if:

TW_WAIT; 

is a delay function.

 

Regards,
Moe

 

NOTE: "#define F_CPU" does not set the frequency for you, broadly speaking you are just telling the mcu which speed you are running. There are plenty of threads here in this forum about this topic.

 

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

I use configuration for definition speed.


 

New

Last Edited: Wed. Mar 13, 2019 - 04:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I try this lib.

So if i want 4 bytes from slave i need use three times function  i2c_readAck  and last byte with function  i2c_readNak .

This functions return last sent bytes in form TWDR.

main

{

        unsigned char data[4];

        int Rbytes = 0;

 

        while(1)

        {

        i2c_start_wait(HIH+I2C_READ);
        data[0] = i2c_readAck;

        if ( TWEA ==1)

           {

           Rbytes++;

           }

        if (Rbytes == 3)

           {

             data[4]=i2c_readNak;

           }

        }

        i2c_stop();

 

}

Can be bytes stored like this ?

New

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

AVR_Castieloo wrote:
    if ( TWEA ==1)

That almost certainly does not do what you think. There's a strong chance that the header file for this AVR says something like:

#define TWEA    6

So you test is effectively:

     if ( 6 ==1)

which can never be true. I assume what you meant to do here was read the TWCR register then check the state of the TWEA bit within it? Something like:

if (TWCR & (1 << TWEA)) {

perhaps?

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

Yeah its better.

 

With this i can control how many ACK was sent right ?

 

in this loop 

if (TWCR & (1 << TWEA)) {
 Rbytes++;
}

i can increment number of receive bytes to number 3.

if (Rbytes == 3)
{
data[4]= i2c_readNak;
}  
i2c_stop(); 

 

This loop end receiving bytes from slave.

unsigned int HB,TB;
		
HB = ((data[0] & 0x3F) << 8) | (data[1]);
TB = ((data[2] << 8)| (data[3]);

I want ask if i may this way parsing bits and get finall 14 bits resolution for value ?

New

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

Still doesnt work with library

 

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <util/twi.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <compat/twi.h>
#include <i2cmaster.h>
#include <math.h>


#include "MLCDFN.h"//nacteni hlavickoveho souboru

#define 	SCL_CLOCK 100000L
#define 	I2C_READ   1
#define 	HIH   0x27

int AckR = 0;


void i2c_init(void)
{
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
  
  TWSR = 0;                         /* no prescaler */
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */

}/* i2c_init */
void i2c_start_wait(unsigned char address)
{
    uint8_t   twst;


    while ( 1 )
    {
	    // send START condition
	    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    
    	// wait until transmission completed
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits.
    	twst = TW_STATUS & 0xF8;
    	if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
    
    	// send device address
    	TWDR = address;
    	TWCR = (1<<TWINT) | (1<<TWEN);
    
    	// wail until transmission completed
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits.
    	twst = TW_STATUS & 0xF8;
    	if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
    	{    	    
    	    /* device busy, send stop condition to terminate write operation */
	        TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	        
	        // wait until stop condition is executed and bus released
	        while(TWCR & (1<<TWSTO));
	        
    	    continue;
    	}
    	//if( twst != TW_MT_SLA_ACK) return 1;
    	break;
     }

}/* i2c_start_wait */

unsigned char i2c_readAck(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
	while(!(TWCR & (1<<TWINT)));    

    return TWDR;

}/* i2c_readAck */

unsigned char i2c_readNak(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN);
	while(!(TWCR & (1<<TWINT)));
	
    return TWDR;

}/* i2c_readNak */
void vypis1()
{
	     prikazMLCD(LCD_HOME);
		 printf_P(PSTR("Hej %d,Humidity"));
		 prikazMLCD(LCD_AT64);
		 printf_P(PSTR("mas ty hovado"));

}

void vypis2()
{
		 
	     prikazMLCD(LCD_CLEAR);
		 
}

void R4Bajts(int BytesR, int *adre)	
{
		if(AckR >= 1)// slave poslal ACK mužeme číst
		{
		 		int i;
				prikazMLCD(LCD_CLEAR)
				_delay_us(4100);
				for(i=0; i < BytesR ;i++)
				{
					while(!(TWCR & (1<<TWINT)));
					*adre = i2c_readAck;
					adre++;

					if (i==3)
					{
						*adre = i2c_readNak;
					}



				}
		}	
}		
int main()
{
	
	unsigned char ret[4];
	unsigned char TB;
	unsigned char HB;
	float Temperature;
	float Humidity;

	iniMLCD()

	i2c_init();
	
	//iniMLCD();
	
    
	

	DDRA &= ~(1 << PA2); //set as Input
    PORTA |= (1 << PA2); //pull up, logical 1 is on the port
	DDRA &= ~(1 << PA3); //set as Input
    PORTA |= (1 << PA3); //pull up, logical 1 is on the port


	
	


	
  
    while(1) 
	{
		
		i2c_start_wait(HIH+I2C_READ);

		R4Bajts(4, &ret[0]);

		HB = ((ret[0] & 0x3F) << 8) | (ret[1]);

		Humidity = (HB / 16383.0) * 100.0;
		

		// if(!(PINA & (1 << PA2)))
        {
           // vypis1();//tlacitko
        }
		 //if(!(PINA & (1 << PA3)))
        {
           // vypis2();//tlacitko
        }
		if (TWCR & (1 << TWEA)) //signalizace přijeti ACK
	    {
			AckR++;
		}
	
	}
}
Could someone please advise me, I'm clueless

New

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
unsigned char i2c_readAck(void)
{

 

					while(!(TWCR & (1<<TWINT)));
					*adre = i2c_readAck;

What VERY curious code. Why are you assigning the address of the i2c_readAck function through the adre pointer?? Surely you meant to INVOKE the function:

					*adre = i2c_readAck();

but if that is the case what is:

					while(!(TWCR & (1<<TWINT)));

doing there? The whole point of using a library is that you don't need to do anything local with the registers/bits. If you want to wait for this condition there should be a library function to do that.

 

Also you seem to have selectively copied just some of Fleury's library into your own program. That is not the way to use library code like this. All you had to do was add twimaster.c to the list of files in your project then you can call any of the functions in the library - this keeps things nice and modular (and means the library can easily be updated if there's ever a bugfix or improvement released).

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

I don't know how to use his library to counter ack a then generated nack on the last byte I want read. I don't know I can add all his function on my project like another. C. Thank you

New

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

Normally, as you may know, library contains a .c file and a .h file: you need both to use this library or you can simple add the *.c file and then add your header...call functions fro there in your main.c or whatever you call it

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

Thank you

New

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

I cant generated START .

unsigned char i2c_start(unsigned char address)
{
    uint8_t   twst;

	

	// send START condition
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);



	// wait until transmission completed
	while(!(TWCR & (1<<TWINT)));

	

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	
	
	if ( (twst != TW_START) && (twst != TW_REP_START)) return Chyba();

	

	// send device address
	TWDR = address;
	TWCR = (1<<TWINT) | (1<<TWEN);

	

	// wail until transmission completed and ACK/NACK has been received
	while(!(TWCR & (1<<TWINT)));

	

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return Chyba();

	return hodnota1();

}/* i2c_start */

I use his lib. and when i call start function i got set TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); 

and TWIN FLAG too (!(TWCR & (1<<TWINT)));

 

but in this line // check value of TWI Status Register. Mask prescaler bits. twst = TW_STATUS & 0xF8; if ( (twst != TW_START) && (twst != TW_REP_START)) return Chyba();

if got error, i check value in TWSR on display and i this moment is 0010000, last 3 bits i dont care but still this is in Hex 2 and TW_START is 8.

 

I try HIH sensor on Labview and its still work so i dont know why doesnt work.

 

I have connect PC0 like SCL and PC1 like SDA i use externall Pull-up resistor 4.7K.

 

I try use function start_wait but in here is the same problem.

 

Does anybody know where is problem ? 

New

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

First off.  A confession.   My eyes glaze over when I see students attempting to write / adapt any I2C library.    I have not read through this thread.

 

I Googled HIH6130 and got this SparkFun Breakout board

It has links to the datasheet and Arduino code.

It also has links to excellent App Notes from Honeywell.

 

I suggest that you use Fleury's TWI library.   Just convert the Wire.h statements into the corresponding C code e.g.

 

Arduino function:

      ...
      Wire.begin();
      ...

byte fetch_humidity_temperature(unsigned int *p_H_dat, unsigned int *p_T_dat)
{
      byte address, Hum_H, Hum_L, Temp_H, Temp_L, _status;
      unsigned int H_dat, T_dat;
      address = 0x27;;
      Wire.beginTransmission(address); 
      Wire.endTransmission();
      delay(100);
      
      Wire.requestFrom((int)address, (int) 4);
      Hum_H = Wire.receive();
      Hum_L = Wire.receive();
      Temp_H = Wire.receive();
      Temp_L = Wire.receive();
      Wire.endTransmission();
      
      _status = (Hum_H >> 6) & 0x03;
      Hum_H = Hum_H & 0x3f;
      H_dat = (((unsigned int)Hum_H) << 8) | Hum_L;
      T_dat = (((unsigned int)Temp_H) << 8) | Temp_L;
      T_dat = T_dat / 4;
      *p_H_dat = H_dat;
      *p_T_dat = T_dat;
      return(_status);
}

Fleury version:

#include "i2cmaster.h"

     ...
     i2c_init();
     ...

// byte is an Arduino name for uint8_t
uint8_t fetch_humidity_temperature(unsigned int *p_H_dat, unsigned int *p_T_dat)
{
      uint8_t address, Hum_H, Hum_L, Temp_H, Temp_L, _status;
      unsigned int H_dat, T_dat;
      address = 0x27 << 1;    //Fleury uses 8-bit addresses
      _status = i2c_start(address | I2C_WRITE); //always check start
      if (_status != 0) return 0xFF; //report failure
      i2c_stop();
      delay(100);
      
      i2c_start(address | I2C_READ);
      Hum_H = i2c_readAck();
      Hum_L = i2c_readAck();
      Temp_H = i2c_readAck();
      Temp_L = i2c_readNak(); //always NAK the last read
      i2c_stop();
      
      _status = (Hum_H >> 6) & 0x03;
      Hum_H = Hum_H & 0x3f;
      H_dat = (((unsigned int)Hum_H) << 8) | Hum_L;
      T_dat = (((unsigned int)Temp_H) << 8) | Temp_L;
      T_dat = T_dat / 4;
      *p_H_dat = H_dat;
      *p_T_dat = T_dat;
      return(_status);   //good returns are 0, 1, 2, 3. 
}

Untested.  I just edited in the Browser.

 

Personally,   I would always start with the Arduino code.   Verify that your hardware is working.    Become familiar with the example sketches.

Then you can write the equivalent C program with Fleury.    Remember to test return value from i2c_start()

Compare the C behaviour with the Arduino behaviour that you now know well.

 

David.

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

Thank you David.

 

I study Arduino code and i understood how to process data and i uses similar way i C with Fleury.

 

But still when i test i2c_start i get failed to access device. I look in TWSR and there was 00100000.

 

I think is HW problem but i dont know where. I have 5V from board to power supply SCA A SCL, both lines have 4.7K resistor. I check connection with multimetr and everything is good.

 

Sensor is okay to.

 

I am in a pickle 

 

btw. if i disconnect sensor i get same status in TWSR 


 

 

New

Last Edited: Sat. Mar 16, 2019 - 12:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have no idea what your 00100000 means.

 

The code that I posted was Untested.

 

If the function returns 0xFF you have not got the correct Slave Address.

Have you not checked the code on an Arduino?

Have you scanned for I2C addresses on the Arduino?

0x27 can be changed in software.

 

I have not looked at your code or schematic.    Most I2C backpacks for 16x2 displays use 0x27.   You can change hardware solder-bridges to select a different address for the LCD.

 

How have you added the Fleury C and H files to your project?

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
_status = i2c_start(address | I2C_WRITE); //always check start

Its return 0xFF but thats mean that i2c_start(0x27+one bit 1 like Read) dont work because its fail in :

 

if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

This save in _status 1 and get 0xFF.

 

      //address = 0x27 << 1;    //Fleury uses 8-bit addresses
      _status = i2c_start(ADDRESS + I2C_READ); //always check start
      if (_status != 0) return 0xFF; //report failure
      i2c_stop();
      _delay_us(100);

I dont have Arduino. i Just look on his way to get data from I2C slave.

 

Most I2C backpacks for 16x2 displays use 0x27.   You can change hardware solder-bridges to select a different address for the LCD.

 

I really dont understand this information. I use standart driver for LCD i use 4 bit comunication, RS and E bits.

 

c. file i add on my project like existing file.

 

 

 

#include <i2cmaster.h>

 

i copy him to 

New

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

Go on.   Fleury uses 8-bit addresses.  

      address = 0x27 << 1;    //Fleury uses 8-bit addresses

I2C is straightforward if you use the return values.

There is no point in going any further until you get an ACK from i2c_start().

The 7-bit address 0x27 means 8-bit 0x4E for Write, 0x4F for Read.

 

Personally,  I would copy "i2cmaster.h" to the project directory and change <i2cmaster.h> to "i2cmaster.h"

I do not like altering the "system" files

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
i2c_start(ADDRESS + I2C_READ);

 He use same way:

 

i2c_start_wait(Dev24C02+I2C_READ);     

I try display value, but ist hard when your comunication failed in second step:

 

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;

	if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

Never i got in TWST =TW_START or TW_REP_START(0x08 0x10)

 

At the same time HW respond an set TWIN FLAG, i see that in TWCR.

 


I dont know why i cant get STATUS .

New

Last Edited: Sat. Mar 16, 2019 - 04:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Seriously.    Wire.h uses 7-bit e.g. 0x27.   i2cmaster.h uses 8-bit e.g. 0x4E/0x4F

 

I presume that you have a Breakout board similar to SparkFun.

You can simply connect it to the Arduino for testing.

 

Never use i2c_start_wait() unless you have previously had a successful i2c_start() that verifies the device is present.

It is useful for polling a 24Cxxx EEPROM while it is doing a Page Write.

 

It is fatal if you have the wrong address.

 

If i2c_start(0x4E) fails it means one or more:

missing Slave device

wrong Slave address

missing pullups

swapped SDA, SCL wiring

 

Don't be proud.   Check your wiring.    We have all swapped wires by mistake.

Chinese jumper wires often break internally.

 

David.

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

David 

I'm starting to lose more and more in this new information.

 

This is my main c. file and lib i have 

#include <avr/io.h> // for buttons
#include <avr/pgmspace.h> // for save in program memmory putchar
#include <stdio.h> // main lib
#include <util/twi.h> // lib for TWI
#include <util/delay.h> // delay
#include <avr/interrupt.h> // interrupt
#include <inttypes.h> // need for binary output
#include <compat/twi.h> // its Fluery ?
#include "i2cmaster.h" // function fluery
#include <math.h> // +-*..


#include "MLCDFN.h"//My h. file for display LCD

#define 	I2C_READ   1
#define 	NIN 0x27  

So if i wanna use  i2cmaster.h i must set on address  0x4E  to read and this address ser in TWDR and sent ?

 

This may be problem. i use i2cmaster.h and in twi_start get parametr (NIN + I2C_READ) 0x27+1.

 

Never use i2c_start_wait()

 

I use this last night.. but after one hour dissapotting i use i2c_start but whith wrong address (NIN + I2C_READ)?

 

I am not proud, just feel helpless. I dont know so many things in this problematic and if i learn something its show thousand another things i dont know :)

 

I will check my board again.

 

Thank you David.

New

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

Copy i2cmaster.h and twimaster.c into your project directory.

Edit twimaster.c to use quotes instead of wedges in the include i2cmaster.h statement.

 

Your program needs:

#include <avr/io.h> // for buttons
#include <avr/pgmspace.h> // for save in program memmory putchar
#include <stdio.h> // main lib
//#include <util/twi.h> // lib for TWI //Fleury knows this
#include <util/delay.h> // delay
#include <avr/interrupt.h> // interrupt
#include <inttypes.h> // need for binary output
//#include <compat/twi.h> // its Fluery ? //Fleury knows this
#include "i2cmaster.h" // function fluery
#include <math.h> // +-*..


#include "MLCDFN.h"//My h. file for display LCD

//#define 	I2C_READ   1  //Fleury knows this
#define 	NIN 0x27  

Please do not attempt to access TWI by yourself.

Just use the Fleury functions that are in "i2cmaster.h"

 

AVR_Castieloo wrote:
So if i wanna use i2cmaster.h i must set on address 0x4E to read and this address ser in TWDR and sent ?

No.  0x4E is Write.   0x4F is Read.

      address = 0x27 << 1;    //Fleury uses 8-bit addresses
      _status = i2c_start(address | I2C_WRITE); //always check start

I have already set the correct base in "address" i.e. 0x4E.

 

David.

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

Thank you for everything David.

May i ask you something about debbuging ? 

When i debug i call function i2c_start i set start condition in to TWSR, you can see START and ENEABLE bit is 1. TWINT flag set HW after every TWI operation is done. Theoretical after HW set TWINT flag i get status code in TWSR right ? I am running simulator so may i somehow get in next statement ?

New

Last Edited: Sat. Mar 16, 2019 - 08:09 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My advice is almost always:  Treat a proven library as a Black Box.

 

Obey the rules for the data to send into the Black Box.

Assume that the data that comes out is 100% correct.

 

After all.   You obeyed the input rules.   The Black Box has behaved 100% correctly.    (We did say that the library was Good)

 

When debugging in AS7 you can just set a Breakpoint where you want to stop.    I would never step into the Library code.

 

Ok.   GCC debugging is a bit crap.   Sometimes you seem to go round in circles before you actually get to the Breakpoint.

One trick is to insert some pointless statement for the Breakpoint.   e.g.

      i2c_start(address | I2C_READ);
      asm("nop");   //pointless statement that is handy to Break on.
      Hum_H = i2c_readAck();
      asm("nop"); //pointless statement that is handy to Break on.
      Hum_L = i2c_readAck();
      asm("nop"); //pointless statement that is handy to Break on.
      Temp_H = i2c_readAck();
      asm("nop"); //pointless statement that is handy to Break on.
      Temp_L = i2c_readNak(); //always NAK the last read
      asm("nop"); //pointless statement that is handy to Break on.
      i2c_stop();
      asm("nop"); //pointless statement that is handy to Break on.

Untested.    I would just break on the return statement.    Single-stepping is seldom worthwhile.    Choose a sensible Breakpoint and Run to it.

 

When you are thoroughly confident about how to use a library,  you can study the library source code.   Understand how it works.    Why functions have a particular set of input rules and output behaviour.

 

Only then should you even dream of writing your own version.

 

Yes,   you can improve on Shakespeare.    Possible but unusual.     Likewise with Mathematical methods or computer language functions.

It is very important that you know how to use a method or function.    Even better if you understand how it works.

 

Think of Maths at school.   You learned several techniques.    I doubt if you invented anything new or better.  

 

David.

 

p.s.   A Black Box still needs testing.   Send unusual or edge values as input (that obey the rules).    Do you get the expected output?

This is known as a "Test Suite".   Devise suitable tests.    Run your program through the Test Suite at every iteration in its development.

Last Edited: Sat. Mar 16, 2019 - 08:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for everything you learn me :) My app works.

 

After so many changes in code i forgot call i2c_init :)

New