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

PIC18F26k22 communication with INA219B

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
miskol



Joined: 01 Feb 2011
Posts: 16

View user's profile Send private message

PIC18F26k22 communication with INA219B
PostPosted: Thu Jan 28, 2016 11:32 am     Reply with quote

Hi,

i'm trying to communicate PIC18F26k22 with INA219B. I used supply 3.3V connected to Vshunt+ and Vshunt- connected to LED with series resistor 330ohm which goes to common GND.

Unfortunately it doesnt work, OLED shows reading of 255 for both VShunt and VBus value.

my OLED definitely works, i got it to show the input voltage correctly.

Below is my coding:
Code:

#include <main.h>
#include <mColed.c>
#include <float.h>

#USE SPI (MASTER, SPI1, ENABLE=PIN_B3, MODE=0, BITS=8, STREAM=SPI_1)
#use I2C (MASTER, I2C2, SLOW)

//float Rshunt = 0.001;
float adc = 0; float VBatt = 0;
char data1,data2;
unsigned int VSina = 0; unsigned int VBina = 0;

//INA219
BYTE INA219_CONFIGURATION = 0x00; // configuration register
BYTE INA219_SHUNT_VOLTAGE = 0x01; // shunt voltage register
BYTE INA219_BUS_VOLTAGE   = 0x02; // bus voltage register
BYTE INA219_POWER         = 0x03; // power register
BYTE INA219_CURRENT       = 0x04; // current register
BYTE INA219_CALIBRATION   = 0x05; // calibration register
BYTE INA219_I2C_ADDRESS   = 0x40; // I2C address

void ADCupdate(void);
void OLED_display(void);
void OLED_start(void);

void main()
{
   setup_adc_ports(sAN0, VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
   OLED_start(); //display OLED

   // INA219 initialize; bus 16V, shunt 320mV, 12-bit continuous Vshunt Vbus
   i2c_start();
   i2c_write(INA219_I2C_ADDRESS);  // I2C slave address 0x40
   i2c_write(INA219_CONFIGURATION);  // INA219 config reg
   i2c_write(0x19); // bus 16V, shunt 320mV, 12-bit continuous Vshunt Vbus
   i2c_write(0x9F); //
   i2c_stop();
   // LSB 1m A/bit
   i2c_start();
   i2c_write(INA219_I2C_ADDRESS); // I2C slave address 0x40
   i2c_write(INA219_CALIBRATION); // INA219 calibration reg
   i2c_write(0x10); // 1m A/bit, 20m W/bit
   i2c_write(0x00);
   i2c_stop();

   while(TRUE)
   {
      //TODO: User Code
      i2c_start();
      i2c_write(INA219_I2C_ADDRESS); // I2C slave address 0x40
      i2c_write(INA219_SHUNT_VOLTAGE); // command register to read VShunt
      i2c_stop(); delay_ms(1); // delay for ADC converts
      i2c_start();
      i2c_write(INA219_I2C_ADDRESS); // I2C slave address 0x40
      data1 = i2c_read(1); // read INA219 MSB with master Acknowledge
      data2 = i2c_read(1); // read INA219 LSB with master Acknowledge
      i2c_stop();
      VSina = make16(data1,data2); // combine MSB LSB, raw value for VShunt

      i2c_start();
      i2c_write(INA219_I2C_ADDRESS); // I2C slave address 0x40
      i2c_write(INA219_BUS_VOLTAGE); // command register to read VBus
      i2c_stop(); delay_ms(1); // delay for ADC converts
      i2c_start();
      i2c_write(INA219_I2C_ADDRESS); // I2C slave address 0x40
      data1 = i2c_read(1); // read INA219 MSB with master Acknowledge
      data2 = i2c_read(1);  // read INA219 LSB with master Acknowledge
      i2c_stop();
      VBina = make16(data1,data2); // combine MSB LSB, raw value for VBus
      //VBina = (VBina >> 3);
      OLED_display();
     }
}


void OLED_start(void) {
   OUTPUT_HIGH(RES); init_OLED(); //reset_display();
   show_bitmap(3); delay_ms(1000); // display image1
   OLED_init(); OLED_clear(); OLED_write(OLED);
}
void OLED_display(void) {
   char txt[100];
   ADCupdate(); OLED_clear();

   sprintf(txt,"%3.2f",VBatt); OLED_text(73,0,txt,2); // display Voltage input
   txt = "V"; OLED_text(117,0,txt,2);
   sprintf(txt,"%u",VBina); OLED_text(73,17,txt,2);  // display VBus
   sprintf(txt,"%u",VSina); OLED_text(73,34,txt,2);  // display VShunt
   OLED_write(OLED);
}
void ADCupdate(void) {
   set_adc_channel(0); delay_us(10); adc = read_adc(); VBatt = ((adc/65535)*3.3); VBatt = ((VBatt * 8.4) / 3.17); adc = 0; delay_us(10);
}



Please help, thank you.
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jan 28, 2016 12:02 pm     Reply with quote

3 comments

1) I don't see where you set the clock speed of the PIC.

2) what are the pullup resistors for the I2C bus ?

3)I've never seen
setup_adc(ADC_CLOCK_INTERNAL_TAD_MUL_0);
used for any ADC except while in sleep mode.

from the datasheet....When the device frequency is greater than 1 MHz, the FRC clock source is only recommended if the
conversion will be performed during Sleep.

and I assume you're using a device frequency > 1MHz.

Jay
miskol



Joined: 01 Feb 2011
Posts: 16

View user's profile Send private message

PostPosted: Thu Jan 28, 2016 12:08 pm     Reply with quote

temtronic wrote:
3 comments

1) I don't see where you set the clock sped of the PIC.

2) what are the pullup resistors for the I2C bus ?

3)I've never seen
setup_adc(ADC_CLOCK_INTERNAL_TAD_MUL_0);
used for any ADC except while in sleep mode

from the datasheet....When the device frequency is greater than 1 MHz, the FRC clock source is only recommended if the
conversion will be performed during Sleep.

and I assume you're using a device fequncy > 1MHz.

Jay


Hi, TQ for your help.

1) PIC clock speed is 64MHz.
2) pull-up resistors are 2.49K ohm.
3) noted with thanks.
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Thu Jan 28, 2016 12:43 pm     Reply with quote

Classic problem.

Texas list I2C addresses as the 7bit address.

The seven bit address is the top seven bits of the byte sent by the PIC (and every other controller), followed by the direction bit.

So to turn the Texas address into an address for use on the bus, you have to multiply it by 2.

Assuming you have A0 and A1 grounded, the chips write address is 0x80...
It's _read_ address is 0x81.

You are also not sending the read bit (trying to use the same address both for read and write)....


Last edited by Ttelmah on Thu Jan 28, 2016 12:47 pm; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jan 28, 2016 12:45 pm     Reply with quote

re 2) pullups. Might be too high, I use 1K2R though check with peripheral datasheet to see what they recommend.


re I2C
copy the I2C scanner program from the code library, it's at the top. Use it to confirm the PIC sees the peripheral.


Jay
miskol



Joined: 01 Feb 2011
Posts: 16

View user's profile Send private message

PostPosted: Thu Jan 28, 2016 1:47 pm     Reply with quote

Ttelmah wrote:
Classic problem.

Texas list I2C addresses as the 7bit address.

The seven bit address is the top seven bits of the byte sent by the PIC (and every other controller), followed by the direction bit.

So to turn the Texas address into an address for use on the bus, you have to multiply it by 2.

Assuming you have A0 and A1 grounded, the chips write address is 0x80...
It's _read_ address is 0x81.

You are also not sending the read bit (trying to use the same address both for read and write)....


TQ very much, finally i'm getting something now Very Happy
miskol



Joined: 01 Feb 2011
Posts: 16

View user's profile Send private message

PostPosted: Thu Jan 28, 2016 1:49 pm     Reply with quote

temtronic wrote:
re 2) pullups. Might be too high, I use 1K2R though check with peripheral datasheet to see what they recommend.


re I2C
copy the I2C scanner program from the code library, it's at the top. Use it to confirm the PIC sees the peripheral.


Jay



TQ, i've used the scanner program, edited it to display on my OLED and yes it shows 80 for the address and number of i2c chips found is 1. very nice very useful code Very Happy

earlier i used 4.7K ohm resistors, figured it could be too high then i changed to 2.49K ohm and now i changed it to nearest that i have which is 1K ohm.
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Fri Jan 29, 2016 4:54 am     Reply with quote

Just to add on the bus resistors, it's a case of 'current/time'. Some values will be different for a 3.3v bus than a 5v bus.

On the I2C bus, you have the current that the pull down drivers can generate. This is required to be a minimum of 3mA at 0.4v. So straight away without considering anything else, the _minimum_ resistor that can be used 'generically', is 1150R at 5v (normally quoted as 1.2KR), and 725R at 3.3v (750R normally quoted). Note how much smaller the 3.3v value is.
Separately, you then have how fast the resistor can pull the bus back 'up' when the drivers switch off. The rise time on I2C, is the time taken for the rail to go from 0.3*Vdd to 0.7*Vdd (again in the spec), and this depends on the resistor, and the bus capacitance. The rise time is specified to be 1uS maximum for standard mode, and 0.3uSec maximum for fast mode. V(t) is calculated as Vdd * (1-e^(-t/RC)), so:

V(T1) = 0.3 * 3.3
Then solving:
3.3 * (1-e^(-t/RC))
for T1, gives:

0.99 = 3.3 * (1-e^(t1/RC)

0.3 = 1-e^(t1/RC)

-0.7 = -e^(t1/RC)

ln(0.7) = t1/RC

t1 = 0.35667*RC

Now the neat thing is if you study this, that the voltage terms cancel throughout, so you get the same result for all different supply voltages. Try 5v and you get the same answer. Then do the same for the 0.7*Vcc (T2) term, and you get:

t2 = 1.20397*RC

Now since we want the time 'between' these (T2-T1), this solves as:

Trise = (1.20397-0.35667)*RC

0.8473*RC - you'll find this in most I2C data sheets.

Then if you are using a bus with 400pF maximum capacitance, you can calculate 'Rmax' for 'standard mode' as:

1/R = 0.8473 * 400pF * 1/1E-6

Gives R=2950R

Do the same for 'fast mode', and you have R = 885R

The first interesting thing about this is that a 5V master can't actually then drive a fast mode bus with 400R capacitance. Since Rmin is greater than the resistance actually required. The quoted maximum bus capacitance for fast mode at 5v, using standard drivers is actually just under 300pF. However many devices actually generate more than the 3mA current, so higher capacitance busses can often be driven OK, but it is a warning that some devices may then have problems. You can also see that using (for instance) 4K7R, will only be OK at this speed up to about 75pF capacitance. Always make a rough estimate of your likely 'worst case' capacitance and choose resistors that will have a little margin at this.

Separately there is 'high speed' mode, but on this active pull up's (rise time accelerators) become required, since otherwise the allowable bus capacitance would just be so low.

This all becomes really important when using a lot of devices on long busses.
In your case, if the bus is short and only has the one device, your bus capacitance, is most likely only a few 10's of pF. 2K49R, will be fine even on fast mode, up to 142pF on the bus.
zamzam23



Joined: 25 Aug 2010
Posts: 47

View user's profile Send private message

the working code
PostPosted: Thu Mar 16, 2017 10:17 pm     Reply with quote

hi,
Can you share the last working code for ina219 ? I need read voltage and current with this module.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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