-
Notifications
You must be signed in to change notification settings - Fork 949
Added ina228 example #705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Louis31423142
wants to merge
1
commit into
raspberrypi:develop
Choose a base branch
from
Louis31423142:ina228
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+177
−0
Open
Added ina228 example #705
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
add_executable(ina228_i2c ina228_i2c.c) | ||
|
||
# pull in common dependencies and additional i2c hardware support | ||
target_link_libraries(ina228_i2c | ||
pico_stdlib | ||
hardware_i2c) | ||
|
||
# create map/bin/hex file etc. | ||
pico_add_extra_outputs(ina228_i2c) | ||
|
||
# add url via pico_set_program_url | ||
example_auto_set_url(ina228_i2c) | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
= Reading an INA228 power sensor via I2C | ||
|
||
This example code shows how to interface the Raspberry Pi Pico with the INA228 current/voltage/power/temperature/energy/charge sensor. The sensor features a 20-bit ADC and supports up to 85V DC, making it a great choice for high precision measurements. It is capable of high-side and low-side measurements (which can be configured by soldering the jumper on the back of the board), but this example focuses on low-side measurements. | ||
|
||
The sensor breakout board has an integrated 0.015 ohm, high precision shunt resistor, which is used for measuring voltage drop, which also gives current since the resistor value is known. This current, combined with the load voltage, allows load power and energy to be calculated. This example measures the power consumption of an LED. | ||
|
||
[TIP] | ||
====== | ||
The INA228 is highly configurable. Find the datasheet online (https://www.ti.com/lit/ds/symlink/ina228.pdf) to explore all of its capabilities beyond the simple example given here. | ||
====== | ||
|
||
== Wiring information | ||
|
||
[[ina228_i2c_wiring]] | ||
[pdfwidth=75%] | ||
.Wiring Diagram for INA228 sensor via I2C. | ||
image::ina228_i2c.png[] | ||
|
||
== List of Files | ||
|
||
CMakeLists.txt:: CMake file to incorporate the example into the examples build tree. | ||
ina228_i2c.c:: The example code. | ||
|
||
== Bill of Materials | ||
|
||
.A list of materials required for the example | ||
[[ina228_i2c-bom-table]] | ||
[cols=3] | ||
|=== | ||
| *Item* | *Quantity* | Details | ||
| Breadboard | 1 | generic part | ||
| Raspberry Pi Pico (any) | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico-2/ | ||
| INA228-based breakout board | 1 | https://www.adafruit.com/product/5832 | ||
| M/M Jumper wires | 8 | generic part | ||
| LED | 1 | generic part | ||
| 330 ohm resistor | 1 | generic part | ||
|=== |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
#include <stdio.h> | ||
#include "pico/stdlib.h" | ||
#include "hardware/i2c.h" | ||
#include <math.h> | ||
|
||
// LED GPIO | ||
#define EXT_LED_GPIO 2 | ||
|
||
// INA228 breakout board shunt resistance in Ohms | ||
#define R_SHUNT 0.015 | ||
|
||
// Max expected current through shunt resistor in Amps | ||
#define MAX_EXPECTED_CURRENT 0.1 | ||
#define I2C_ADDR 0x40 | ||
|
||
// Macros for converting arrays of bytes to decimal integer | ||
#define COALESCE_2_BYTES(a2) ((a2[0] << 8) | a2[1]) | ||
#define COALESCE_3_BYTES(a3) ((a3[0] << 16) | (a3[1] << 8) | a3[2]) | ||
#define COALESCE_RESERVED_3_BYTES(a3) ((a3[0] << 12) | (a3[1] << 4) | (a3[2] >> 4)) | ||
#define COALESCE_5_BYTES(a5) (((uint64_t)a5[0] << 32) | (a5[1] << 24) | (a5[2] << 16) | (a5[3] << 8) | a5[4]) | ||
|
||
// ina228 registers (see datasheet) | ||
uint8_t VSHUNT_REG = 0x04; | ||
uint8_t VBUS_REG = 0x05; | ||
uint8_t DIETEMP_REG = 0x06; | ||
uint8_t CURRENT_REG = 0x07; | ||
uint8_t POWER_REG = 0x08; | ||
uint8_t ENERGY_REG = 0x09; | ||
uint8_t CHARGE_REG = 0x0A; | ||
|
||
uint8_t ADC_CONFIG_REG = 0x01; | ||
uint8_t SHUNT_CAL_REG = 0x02; | ||
|
||
// conversion factors (see datasheet) | ||
// note: VSHUNT_FACTOR assumes ADCRANGE = 0 | ||
const double VSHUNT_FACTOR = 312.5 * 1e-9; | ||
const double VBUS_FACTOR = 195.3125 * 1e-6; | ||
const double DIETEMP_FACTOR = 7.8125 * 1e-3; | ||
const double CURRENT_FACTOR = MAX_EXPECTED_CURRENT / (1<<19); | ||
const double POWER_FACTOR = 3.2 * CURRENT_FACTOR ; | ||
const double ENERGY_FACTOR = 16 * 3.2 * CURRENT_FACTOR; | ||
const double CHARGE_FACTOR = CURRENT_FACTOR; | ||
|
||
const uint16_t SHUNT_CAL = 13107.2 * 1e6 * CURRENT_FACTOR * R_SHUNT; | ||
|
||
float vshunt, vbus, dietemp, current, power, energy, charge; | ||
|
||
static void ina228_init() { | ||
// Write to shunt register | ||
uint8_t shunt_msb = (SHUNT_CAL >> 8) & 0xFF; | ||
uint8_t shunt_lsb = SHUNT_CAL & 0xFF; | ||
uint8_t shunt_buf[3] = {SHUNT_CAL_REG, shunt_msb, shunt_lsb}; | ||
i2c_write_blocking(i2c_default, I2C_ADDR, shunt_buf, 3, false); | ||
|
||
// Write to ADC config register (need to enable continuous mode to access accumulation variables energy and charge) | ||
uint8_t adc_msb = 0xF0; | ||
uint8_t adc_lsb = 0x00; | ||
uint8_t adc_buf[3] = {ADC_CONFIG_REG, adc_msb, adc_lsb}; | ||
i2c_write_blocking(i2c_default, I2C_ADDR, adc_buf, 3, false); | ||
} | ||
|
||
static void ina228_read(float *vshunt, float *vbus, float *dietemp, float *current, float *power, float *energy, float *charge) { | ||
// Buffers for writing register measurements to | ||
// Some registers are 2 bytes, some are 3 bytes, the accumulation registers are 5 bytes | ||
uint8_t buffer_2[2]; | ||
uint8_t buffer_3[3]; | ||
uint8_t buffer_5[5]; | ||
|
||
// For the vshunt, vbus and current registers the 4 least significant bits are reserved and always read zero, so use variant of coalesce macro to extract value | ||
i2c_write_blocking(i2c_default, I2C_ADDR, &VSHUNT_REG, 1, true); | ||
i2c_read_blocking(i2c_default, I2C_ADDR, buffer_3, 3, false); | ||
*vshunt = COALESCE_RESERVED_3_BYTES(buffer_3) * VSHUNT_FACTOR; | ||
|
||
i2c_write_blocking(i2c_default, I2C_ADDR, &VBUS_REG, 1, true); | ||
i2c_read_blocking(i2c_default, I2C_ADDR, buffer_3, 3, false); | ||
*vbus = COALESCE_RESERVED_3_BYTES(buffer_3) * VBUS_FACTOR; | ||
|
||
i2c_write_blocking(i2c_default, I2C_ADDR, &DIETEMP_REG, 1, true); | ||
i2c_read_blocking(i2c_default, I2C_ADDR, buffer_2, 2, false); | ||
*dietemp = COALESCE_2_BYTES(buffer_2) * DIETEMP_FACTOR; | ||
|
||
i2c_write_blocking(i2c_default, I2C_ADDR, &CURRENT_REG, 1, true); | ||
i2c_read_blocking(i2c_default, I2C_ADDR, buffer_3, 3, false); | ||
*current = COALESCE_RESERVED_3_BYTES(buffer_3) * CURRENT_FACTOR; | ||
|
||
i2c_write_blocking(i2c_default, I2C_ADDR, &POWER_REG, 1, true); | ||
i2c_read_blocking(i2c_default, I2C_ADDR, buffer_3, 3, false); | ||
*power = COALESCE_3_BYTES(buffer_3) * POWER_FACTOR; | ||
|
||
i2c_write_blocking(i2c_default, I2C_ADDR, &ENERGY_REG, 1, true); | ||
i2c_read_blocking(i2c_default, I2C_ADDR, buffer_5, 5, false); | ||
*energy = COALESCE_5_BYTES(buffer_5) * ENERGY_FACTOR; | ||
|
||
i2c_write_blocking(i2c_default, I2C_ADDR, &CHARGE_REG, 1, true); | ||
i2c_read_blocking(i2c_default, I2C_ADDR, buffer_5, 5, false); | ||
*charge = COALESCE_5_BYTES(buffer_5) * CHARGE_FACTOR; | ||
} | ||
|
||
int main() | ||
{ | ||
stdio_init_all(); | ||
|
||
// Initialise external LED and turn it on (so we can measure some current) | ||
gpio_init(EXT_LED_GPIO); | ||
gpio_set_dir(EXT_LED_GPIO, GPIO_OUT); | ||
gpio_put(EXT_LED_GPIO, true); | ||
|
||
// I2C initialisation | ||
i2c_init(i2c_default, 400*1000); | ||
|
||
// GPIO initialisation | ||
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); | ||
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); | ||
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); | ||
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); | ||
|
||
// Initialise ina228 | ||
ina228_init(); | ||
|
||
while (true) { | ||
ina228_read(&vshunt, &vbus, &dietemp, ¤t, &power, &energy, &charge); | ||
printf("INA228 Measurements:\nVSHUNT: %f V\nVBUS: %f V\nDIETEMP: %f °C\nCURRENT: %f A\nPOWER: %f W\nENERGY: %f J\nCHARGE: %f C\n-----------------\n", vshunt, vbus, dietemp, current, power, energy, charge); | ||
sleep_ms(1000); | ||
} | ||
} |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably makes sense to update this URL too. https://www.raspberrypi.com/products/raspberry-pi-pico/
Although thinking about it, I wonder if something like this works, or if it's too wordy?
WDYT @peterharperuk ?