ATtinyPowerMeter

4,994

118

22

Posted

Introduction: ATtinyPowerMeter

This instructables show how to make a simple power meter using 3 components: ATtiny85, INA219 and OLED module.

It can continuous measure the voltage(V), current(mA) and accumulated power usage(mWh). And also plot a simple graph to visualise the figures.

Step 1: Why?

While developing IoT device, power consumption does matter, especially if it cannot wired. A simple multi-meter is not enough for continuous monitoring the voltage and current at the same time. And also the accumulated power consumption (mWh) is very important for deciding how big a battery required in the IoT project.

So I use the components in hand to create this ATtinyPowerMeter.

Step 2: Preparation

The power meter should not drain too much power itself, it is the major criteria to choose the components:

MCU

ATtiny85 only draw less than 1 mA while running at 1 MHz and 8 KB program flash can well fit a power meter program.

Power Monitor Module

INA219 module is the only module I can found that can monitor voltage and current at the same time (leave comment to me if you known other modules). It draws around 1 mA power.

Display Module

SSD1306 OLED display module drain few mA for display, it is the major power consumption. It should be better if using mono LCD display, but I only have this I2C display module in hand, so I will use it this time.

Battery

According to the data sheet, the above 3 components can operate at 3 V to 5.5 V, 2 rechargeable AAA battery is not enough, 3 AAA battery is better, 1 Lipo battery also ok. But in this project I am testing a new type battery, Lithium iron phosphate (LiFePO4 or LFP) battery. It is the same as AAA battery in size, but can provide 3.2 V 600 mAh. It should be good enough for most electronic project but I am still testing it.

Others

A 380 hole breadboard, some breadboard wire, a breadboard friendly battery holder, a 3 pins screw terminal block and a switch. And also a ISP for programming the ATtiny85.

Step 3: Download Source Code

Download source from GitHub:

https://github.com/moononournation/ATtinyPowerMete...

If you are not familiar GitHub, simple press "Clone or download" button and then "Download ZIP".

Step 4: Program ATtiny85

Step 5: Circuit Design

Here is the connection summary:

Battery +ve -> switch -> ATtiny85 pin 8, INA219 module Vcc, OLED module Vcc
Battery -ve -> ATtiny85 pin 4, INA219 module GND, OLED module GND, screw terminal block middle pin
ATtiny85 pin 5 -> INA219 module SDA, OLED module SDA
ATtiny85 pin 7 -> INA219 module SCL, OLED module SCL
INA219 module Vin- -> screw terminal block left pin
INA219 module Vin+ -> screw terminal block right pin

Step 6: Testing

  1. Turn on the switch, you should see V and mA figure is 0.
  2. Connect testing power source +ve and -ve to screw terminal right pin and middle pin respectively, you should see V figure become the power source Voltage value and mA still 0
  3. Connect testing loading device +ve and -ve to screw terminal left pin and middle pin respectively, you should see mA figure become the loading device drawing current value

Step 7: Self Test

You want to know how much power draining this power meter itself? In my measurement it draws around 3 - 6 mA, just for your reference.

Step 8: Happing Measuring!

It is the time to design and testing your device power consumption now!

P.S. My source code configured measure maximum 16V and 800 mA, you may change the configuration at "INA219.h".

Share

Recommendations

  • Epilog Challenge 9

    Epilog Challenge 9
  • Paper Contest 2018

    Paper Contest 2018
  • Gluten Free Challenge

    Gluten Free Challenge
user

We have a be nice policy.
Please be positive and constructive.

Tips

Questions

18 Comments

How to change the maximum current limit. ( can you please specify)

you can change the maximum current limit by setting the Calibration Register (address = 05h).

Calibration value = 0.04096 / CURRENT_LSB / 0.1

CURRENT_LSB = maximum current limit / 2^15

You may refer to Data Sheet Page 12 Chapter 8.5.1 and Page 25 Figure 27 for more details.

If i need current limit of 3 amps?

CURRENT_LSB = 3 A / 2^15 ~= 0.0001 (100 uA)

Calibration value = 0.04096 / 100 / 0.1 = 4096 (0x1000)

i am get compilation error with tinywire library (any other libraries do i need to download)

Yes, you need to install TinyWireM at Library Manager. Sorry for missing it.

I have installed tinywire from Arduino ide itself

Arduino: 1.8.5 (Windows 10), Board: "Arduino/Genuino Uno"

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp: In function 'void USI_TWI_Master_Initialise()':

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:48:3: error: 'PORT_USI' was not declared in this scope

PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:48:19: error: 'PIN_USI_SDA' was not declared in this scope

PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:49:19: error: 'PIN_USI_SCL' was not declared in this scope

PORT_USI |= (1<<PIN_USI_SCL); // Enable pullup on SCL, to set high as released state.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:51:3: error: 'DDR_USI' was not declared in this scope

DDR_USI |= (1<<PIN_USI_SCL); // Enable SCL as output.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:54:3: error: 'USIDR' was not declared in this scope

USIDR = 0xFF; // Preload dataregister with "released level" data.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:55:3: error: 'USICR' was not declared in this scope

USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:55:19: error: 'USISIE' was not declared in this scope

USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:55:31: error: 'USIOIE' was not declared in this scope

USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:56:19: error: 'USIWM1' was not declared in this scope

(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:56:31: error: 'USIWM0' was not declared in this scope

(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:57:19: error: 'USICS1' was not declared in this scope

(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter clock source

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:57:31: error: 'USICS0' was not declared in this scope

(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter clock source

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:57:43: error: 'USICLK' was not declared in this scope

(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter clock source

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:58:19: error: 'USITC' was not declared in this scope

(0<<USITC);

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:59:3: error: 'USISR' was not declared in this scope

USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags,

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:59:19: error: 'USISIF' was not declared in this scope

USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags,

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:59:31: error: 'USIOIF' was not declared in this scope

USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags,

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:59:43: error: 'USIPF' was not declared in this scope

USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags,

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:59:54: error: 'USIDC' was not declared in this scope

USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags,

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:60:21: error: 'USICNT0' was not declared in this scope

(0x0<<USICNT0); // and reset counter.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp: In function 'unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char*, unsigned char)':

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:130:44: error: 'USISIF' was not declared in this scope

unsigned char const tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:130:56: error: 'USIOIF' was not declared in this scope

unsigned char const tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:130:68: error: 'USIPF' was not declared in this scope

unsigned char const tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:130:79: error: 'USIDC' was not declared in this scope

unsigned char const tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:131:40: error: 'USICNT0' was not declared in this scope

(0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:196:7: error: 'PORT_USI' was not declared in this scope

PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:196:24: error: 'PIN_USI_SCL' was not declared in this scope

PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:197:7: error: 'USIDR' was not declared in this scope

USIDR = *(msg++); // Setup data.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:201:7: error: 'DDR_USI' was not declared in this scope

DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:201:24: error: 'PIN_USI_SDA' was not declared in this scope

DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:234:7: error: 'DDR_USI' was not declared in this scope

DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:234:25: error: 'PIN_USI_SDA' was not declared in this scope

DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:240:9: error: 'USIDR' was not declared in this scope

USIDR = 0xFF; // Load NACK to confirm End Of Transmission.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:244:9: error: 'USIDR' was not declared in this scope

USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp: In function 'unsigned char USI_TWI_Master_Transfer(unsigned char)':

C:\Users\tejes\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:263:3: error: 'USISR' was not declared in this scope

USISR = temp; // Set USISR according to temp.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:265:16: error: 'USISIE' was not declared in this scope

temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:265:28: error: 'USIOIE' was not declared in this scope

temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:266:16: error: 'USIWM1' was not declared in this scope

(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:266:28: error: 'USIWM0' was not declared in this scope

(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:267:16: error: 'USICS1' was not declared in this scope

(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:267:28: error: 'USICS0' was not declared in this scope

(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:267:40: error: 'USICLK' was not declared in this scope

(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:268:16: error: 'USITC' was not declared in this scope

(1<<USITC); // Toggle Clock Port.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:272:5: error: 'USICR' was not declared in this scope

USICR = temp; // Generate positve SCL edge.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:273:14: error: 'PIN_USI' was not declared in this scope

while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:273:28: error: 'PIN_USI_SCL' was not declared in this scope

while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:276:25: error: 'USIOIF' was not declared in this scope

}while( !(USISR & (1<<USIOIF)) ); // Check for transfer complete.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:279:11: error: 'USIDR' was not declared in this scope

temp = USIDR; // Read out data.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:281:3: error: 'DDR_USI' was not declared in this scope

DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:281:18: error: 'PIN_USI_SDA' was not declared in this scope

DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp: In function 'unsigned char USI_TWI_Master_Start()':

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:291:3: error: 'PORT_USI' was not declared in this scope

PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:291:19: error: 'PIN_USI_SCL' was not declared in this scope

PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:296:20: error: 'PIN_USI_SDA' was not declared in this scope

PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:302:9: error: 'USISR' was not declared in this scope

if( !(USISR & (1<<USISIF)) )

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:302:21: error: 'USISIF' was not declared in this scope

if( !(USISR & (1<<USISIF)) )

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp: In function 'unsigned char USI_TWI_Master_Stop()':

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:316:3: error: 'PORT_USI' was not declared in this scope

PORT_USI &= ~(1<<PIN_USI_SDA); // Pull SDA low.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:316:20: error: 'PIN_USI_SDA' was not declared in this scope

PORT_USI &= ~(1<<PIN_USI_SDA); // Pull SDA low.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:317:19: error: 'PIN_USI_SCL' was not declared in this scope

PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:318:12: error: 'PIN_USI' was not declared in this scope

while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Wait for SCL to go high.

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:324:9: error: 'USISR' was not declared in this scope

if( !(USISR & (1<<USIPF)) )

^

C:\Users\Documents\Arduino\libraries\TinyWireM\USI_TWI_Master.cpp:324:21: error: 'USIPF' was not declared in this scope

if( !(USISR & (1<<USIPF)) )

^

exit status 1
Error compiling for board Arduino/Genuino Uno.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Thank you very much

Hi!

Just to thank you for publishing this project. It's exactly what i was looking for. I made it using a trinket 3.3V and the code is working out of the box. Great and useful project!