File Coverage

blib/lib/Device/Chip/INA219.pm
Criterion Covered Total %
statement 67 67 100.0
branch 2 4 50.0
condition 1 2 50.0
subroutine 15 15 100.0
pod 4 5 80.0
total 89 93 95.7


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2014-2023 -- leonerd@leonerd.org.uk
5              
6 3     3   512639 use v5.26;
  3         23  
7 3     3   15 use warnings;
  3         3  
  3         81  
8 3     3   536 use Object::Pad 0.800;
  3         8966  
  3         140  
9              
10             package Device::Chip::INA219 0.10;
11             class Device::Chip::INA219
12 3     3   1548 :isa(Device::Chip::Base::RegisteredI2C 0.10);
  3         24563  
  3         118  
13              
14 3     3   570 use constant REG_DATA_SIZE => 16;
  3         5  
  3         148  
15              
16 3     3   16 use utf8;
  3         6  
  3         12  
17              
18 3     3   66 use Carp;
  3         6  
  3         141  
19 3     3   16 use Future::AsyncAwait;
  3         6  
  3         11  
20              
21 3     3   1381 use Data::Bitfield qw( bitfield boolfield enumfield );
  3         5623  
  3         724  
22              
23             =encoding UTF-8
24              
25             =head1 NAME
26              
27             C - chip driver for an F
28              
29             =head1 SYNOPSIS
30              
31             use Device::Chip::INA219;
32             use Future::AsyncAwait;
33              
34             my $chip = Device::Chip::INA219->new;
35             await $chip->mount( Device::Chip::Adapter::...->new );
36              
37             printf "Current bus voltage is %d mV, shunt voltage is %d uV\n",
38             await $chip->read_bus_voltage, await $chip->read_shunt_voltage;
39              
40             =head1 DESCRIPTION
41              
42             This L subclass provides specific communication to a
43             F F attached to a computer via an I²C adapter.
44              
45             The reader is presumed to be familiar with the general operation of this chip;
46             the documentation here will not attempt to explain or define chip-specific
47             concepts or features, only the use of this module to access them.
48              
49             =cut
50              
51             =head1 MOUNT PARAMETERS
52              
53             =head2 addr
54              
55             The I²C address of the device. Can be specified in decimal, octal or hex with
56             leading C<0> or C<0x> prefixes.
57              
58             =cut
59              
60 2         4 method I2C_options ( %params )
  2         3  
  2         4  
61 2     2 0 749 {
62 2   50     12 my $addr = delete $params{addr} // 0x40;
63 2 50       10 $addr = oct $addr if $addr =~ m/^0/;
64              
65             return (
66 2         13 addr => $addr,
67             max_bitrate => 100E3,
68             );
69             }
70              
71             =head1 METHODS
72              
73             The following methods documented in an C expression return L
74             instances.
75              
76             =cut
77              
78             use constant {
79 3         3529 REG_CONFIG => 0x00, # R/W
80             REG_VSHUNT => 0x01, # R
81             REG_VBUS => 0x02, # R
82             REG_POWER => 0x03, # R
83             REG_CURRENT => 0x04, # R
84             REG_CALIB => 0x05, # R/W
85 3     3   21 };
  3         5  
86              
87             my @ADCs = qw( 9b 10b 11b 12b . . . . 1 2 4 8 16 32 64 128 );
88              
89             # We'll use integer encoding and pack/unpack it ourselves because the BADC
90             # field spans a byte boundary the wrong way
91             bitfield { format => "integer" }, CONFIG =>
92             RST => boolfield(15),
93             BRNG => enumfield(13, qw( 16V 32V )),
94             PG => enumfield(11, qw( 40mV 80mV 160mV 320mV )),
95             BADC => enumfield( 7, @ADCs),
96             SADC => enumfield( 3, @ADCs),
97             MODE_CONT => boolfield(2),
98             MODE_BUS => boolfield(1),
99             MODE_SHUNT => boolfield(0);
100              
101             =head2 read_config
102              
103             $config = await $chip->read_config;
104              
105             Reads and returns the current chip configuration as a C reference.
106              
107             RST => BOOL
108             BRNG => "16V" | "32V"
109             PG => "40mV" | "80mV" | "160mV" | "320mV"
110             BADC => "9b" | "10b" | "11b" | "12b" | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128
111             SADC => as above
112             MODE_CONT => BOOL
113             MODE_BUS => BOOL
114             MODE_SHUNT => BOOL
115              
116             =cut
117              
118             field $_config;
119              
120 1         1 async method read_config ()
  1         1  
121 1         3 {
122 1         8 my $bytes = await $self->cached_read_reg( REG_CONFIG, 1 );
123              
124 1         8900 return $_config = { unpack_CONFIG( unpack "S>", $bytes ) };
125 1     1 1 287 }
126              
127             =head2 change_config
128              
129             await $chip->change_config( %config );
130              
131             Changes the configuration. Any field names not mentioned will be preserved.
132              
133             =cut
134              
135 1         2 async method change_config ( %changes )
  1         2  
  1         2  
136 1         4 {
137 1 50       4 defined $_config or await $self->read_config;
138              
139 1         2 my %config = ( %{ $_config }, %changes );
  1         6  
140              
141 1         4 undef $_config; # invalidate the cache
142              
143 1         5 await $self->write_reg( REG_CONFIG, pack "S>", pack_CONFIG( %config ) );
144 1     1 1 5073 }
145              
146             =head2 read_shunt_voltage
147              
148             $uv = await $chip->read_shunt_voltage;
149              
150             Returns the current shunt voltage reading scaled integer in microvolts.
151              
152             =cut
153              
154 1         1 async method read_shunt_voltage ()
  1         2  
155 1         3 {
156 1         7 my $vraw = unpack "s>", await $self->read_reg( REG_VSHUNT, 1 );
157              
158             # Each $vraw graduation is 10uV
159 1         7941 return $vraw * 10;
160 1     1 1 266 }
161              
162             =head2 read_bus_voltage
163              
164             $mv = await $chip->read_bus_voltage;
165              
166             ( $mv, $ovf, $cnvr ) = await $chip->read_bus_voltage;
167              
168             Returns the current bus voltage reading, as a scaled integer in milivolts.
169              
170             The returned L also yields the OVF and CNVR flags.
171              
172             =cut
173              
174 1         2 async method read_bus_voltage ()
  1         2  
175 1         4 {
176 1         4 my $value = unpack "s>", await $self->read_reg( REG_VBUS, 1 );
177              
178 1         1243 my $ovf = ( $value & 1<<0 );
179 1         2 my $cnvr = ( $value & 1<<1 );
180 1         3 my $vraw = $value >> 3;
181              
182             # Each $vraw graduation is 4mV
183 1         5 return $vraw * 4, $cnvr, $ovf;;
184 1     1 1 3907 }
185              
186             =head1 AUTHOR
187              
188             Paul Evans
189              
190             =cut
191              
192             0x55AA;