File Coverage

blib/lib/Device/Chip/ADS1115.pm
Criterion Covered Total %
statement 65 65 100.0
branch 1 2 50.0
condition 2 6 33.3
subroutine 15 15 100.0
pod 5 6 83.3
total 88 94 93.6


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, 2017-2023 -- leonerd@leonerd.org.uk
5              
6 2     2   315092 use v5.26;
  2         16  
7 2     2   10 use warnings;
  2         6  
  2         63  
8 2     2   12 use Object::Pad 0.800;
  2         14  
  2         88  
9              
10             package Device::Chip::ADS1115 0.15;
11             class Device::Chip::ADS1115
12 2     2   1301 :isa(Device::Chip::Base::RegisteredI2C);
  2         7443  
  2         79  
13              
14             Device::Chip::Base::RegisteredI2C->VERSION( '0.10' );
15              
16 2     2   378 use Future::AsyncAwait 0.13; # list-context bugfix
  2         28  
  2         10  
17              
18 2     2   597 use Data::Bitfield 0.02 qw( bitfield boolfield enumfield );
  2         2333  
  2         173  
19              
20 2     2   16 use constant REG_DATA_SIZE => 16;
  2         5  
  2         191  
21              
22             =head1 NAME
23              
24             C - chip driver for F
25              
26             =head1 SYNOPSIS
27              
28             use Device::Chip::ADS1115;
29             use Future::AsyncAwait;
30              
31             my $chip = Device::Chip::ADS1115->new;
32             await $chip->mount( Device::Chip::Adapter::...->new );
33              
34             await $chip->change_config( MUX => "0" );
35             await $chip->trigger;
36              
37             printf "The voltage is %.2fV\n", await $chip->read_adc_voltage;
38              
39             =head1 DESCRIPTION
40              
41             This L subclass provides specific communications to a chip in
42             the F F family, such as the F, F
43             or F. Due to similarities in hardware, it also works for the
44             F family, consisting of F, F and F.
45              
46             The reader is presumed to be familiar with the general operation of this chip;
47             the documentation here will not attempt to explain or define chip-specific
48             concepts or features, only the use of this module to access them.
49              
50             =cut
51              
52             use constant {
53 2         3069 REG_RESULT => 0,
54             REG_CONFIG => 1,
55             # TODO: threshold config
56 2     2   15 };
  2         4  
57              
58             sub I2C_options
59             {
60             return (
61 1     1 0 455 addr => 0x48,
62             max_bitrate => 400E3,
63             );
64             }
65              
66             =head1 METHODS
67              
68             The following methods documented in an C expression return L
69             instances.
70              
71             =cut
72              
73             =head2 read_config
74              
75             $config = await $chip->read_config;
76              
77             Returns a C reference containing the chip's current configuration.
78              
79             OS => 0 | 1
80             MUX => "0" | "1" | "2" | "3" # single-ended
81             | "0-1" | "0-3" | "1-3" | "2-3" # bipolar
82             PGA => "6.144V" | "4.096V" | "2.048V" | "1.024V" | "0.512V" | "0.256V"
83             MODE => "CONT" | "SINGLE"
84             DR => 8 | 16 | 32 | 64 | 128 | 250 | 475 | 860
85              
86             COMP_MODE => "TRAD" | "WINDOW"
87             COMP_POL => "LOW" | "HIGH"
88             COMP_LAT => 0 | 1
89             COMP_QUE => 1 | 2 | 4 | "DIS"
90              
91             =cut
92              
93             bitfield { format => "integer" }, CONFIG =>
94             OS => boolfield(15),
95             MUX => enumfield(12, qw( 0-1 0-3 1-3 2-3 0 1 2 3 )),
96             PGA => enumfield( 9, qw( 6.144V 4.096V 2.048V 1.024V 0.512V 0.256V )),
97             MODE => enumfield( 8, qw( CONT SINGLE )),
98             DR => enumfield( 5, qw( 8 16 32 64 128 250 475 860 )),
99             COMP_MODE => enumfield(4, qw( TRAD WINDOW )),
100             COMP_POL => enumfield(3, qw( LOW HIGH )),
101             COMP_LAT => boolfield(2),
102             COMP_QUE => enumfield(0, qw( 1 2 4 DIS ));
103              
104             field $_config;
105             field $_fullscale_f;
106              
107 3         6 async method read_config ()
  3         5  
108 3         8 {
109 3         13 my $bytes = await $self->cached_read_reg( REG_CONFIG, 1 );
110              
111 3         10726 return $_config = { unpack_CONFIG( unpack "S>", $bytes ) };
112 3     3 1 372 }
113              
114             =head2 change_config
115              
116             await $chip->change_config( %changes );
117              
118             Changes the configuration. Any field names not mentioned will be preserved at
119             their existing values.
120              
121             =cut
122              
123 1         3 async method change_config ( %changes )
  1         4  
  1         2  
124 1         6 {
125 1   33     5 my $config = $_config // await $self->read_config;
126              
127 1         10 %$config = ( %$config, %changes );
128              
129 1 50       5 undef $_fullscale_f if exists $changes{PGA};
130              
131 1         9 await $self->cached_write_reg( REG_CONFIG, pack "S>", pack_CONFIG( %$config ) );
132 1     1 1 6723 }
133              
134             =head2 trigger
135              
136             await $chip->trigger;
137              
138             Set the C bit configuration bit, which will cause the chip to take a new
139             reading of the currently-selected input channel when in single-shot mode.
140              
141             =cut
142              
143 1         2 async method trigger ()
  1         3  
144 1         5 {
145 1         3 my $config = await $self->read_config;
146              
147             # Not "cached" as OS is a volatile bit
148 1         155 await $self->write_reg( REG_CONFIG, pack "S>", pack_CONFIG( %$config, OS => 1 ) );
149 1     1 1 5574 }
150              
151             =head2 read_adc
152              
153             $value = await $chip->read_adc;
154              
155             Reads the most recent reading from the result register on the chip. This
156             method should be called after a suitable delay after the L method
157             when in single-shot mode, or at any time when in continuous mode.
158              
159             The reading is returned directly from the chip as a plain 16-bit signed
160             integer. To convert this into voltage use the L method.
161              
162             =cut
163              
164 2         4 async method read_adc ()
  2         3  
165 2         8 {
166 2         8 my $bytes = await $self->read_reg( REG_RESULT, 1 );
167              
168 2         1666 return unpack "S>", $bytes;
169 2     2 1 1838 }
170              
171 1         3 async method _fullscale ()
  1         2  
172 1         2 {
173 1   33     5 return $_fullscale_f //= do {
174 1         4 my $config = await $self->read_config;
175 1         158 ( $config->{PGA} =~ m/(\d\.\d+)V/ )[0];
176             };
177 1     1   2 }
178              
179             =head2 read_adc_voltage
180              
181             $voltage = await $chip->read_adc_voltage;
182              
183             Reads the most recent reading as per L and converts it into a
184             voltage level by taking into account the current setting of the C
185             configuration option to scale it.
186              
187             =cut
188              
189 1         2 async method read_adc_voltage ()
  1         3  
190 1         5 {
191 1         5 my $f = Future->needs_all( $self->_fullscale, $self->read_adc );
192 1         1411 my ( $fullscale, $reading ) = await $f;
193              
194 1         184 return ( $reading * $fullscale ) / ( 1 << 15 );
195 1     1 1 4181 }
196              
197             =head1 AUTHOR
198              
199             Paul Evans
200              
201             =cut
202              
203             0x55AA;