gobot.io/x/gobot@v1.16.0/drivers/i2c/ads1x15_driver.go (about) 1 package i2c 2 3 import ( 4 "errors" 5 "math" 6 "strconv" 7 "time" 8 9 "fmt" 10 11 "gobot.io/x/gobot" 12 ) 13 14 const ( 15 16 // ADS1x15DefaultAddress is the default I2C address for the ADS1x15 components 17 ADS1x15DefaultAddress = 0x48 18 19 ads1x15PointerConversion = 0x00 20 ads1x15PointerConfig = 0x01 21 ads1x15PointerLowThreshold = 0x02 22 ads1x15PointerHighThreshold = 0x03 23 // Write: Set to start a single-conversion 24 ads1x15ConfigOsSingle = 0x8000 25 ads1x15ConfigMuxOffset = 12 26 ads1x15ConfigModeContinuous = 0x0000 27 //Single shoot mode 28 ads1x15ConfigModeSingle = 0x0100 29 30 ads1x15ConfigCompWindow = 0x0010 31 ads1x15ConfigCompAactiveHigh = 0x0008 32 ads1x15ConfigCompLatching = 0x0004 33 ads1x15ConfigCompQueDisable = 0x0003 34 ) 35 36 // ADS1x15Driver is the Gobot driver for the ADS1015/ADS1115 ADC 37 type ADS1x15Driver struct { 38 name string 39 connector Connector 40 connection Connection 41 gainConfig map[int]uint16 42 dataRates map[int]uint16 43 gainVoltage map[int]float64 44 converter func([]byte) float64 45 DefaultGain int 46 DefaultDataRate int 47 Config 48 } 49 50 // NewADS1015Driver creates a new driver for the ADS1015 (12-bit ADC) 51 // Largely inspired by: https://github.com/adafruit/Adafruit_Python_ADS1x15 52 func NewADS1015Driver(a Connector, options ...func(Config)) *ADS1x15Driver { 53 l := newADS1x15Driver(a, options...) 54 55 l.dataRates = map[int]uint16{ 56 128: 0x0000, 57 250: 0x0020, 58 490: 0x0040, 59 920: 0x0060, 60 1600: 0x0080, 61 2400: 0x00A0, 62 3300: 0x00C0, 63 } 64 if l.DefaultDataRate == 0 { 65 l.DefaultDataRate = 1600 66 } 67 68 l.converter = func(data []byte) (value float64) { 69 result := (int(data[0]) << 8) | int(data[1]) 70 71 if result&0x8000 != 0 { 72 result -= 1 << 16 73 } 74 75 return float64(result) / float64(1<<15) 76 } 77 78 return l 79 } 80 81 // NewADS1115Driver creates a new driver for the ADS1115 (16-bit ADC) 82 func NewADS1115Driver(a Connector, options ...func(Config)) *ADS1x15Driver { 83 l := newADS1x15Driver(a, options...) 84 85 l.dataRates = map[int]uint16{ 86 8: 0x0000, 87 16: 0x0020, 88 32: 0x0040, 89 64: 0x0060, 90 128: 0x0080, 91 250: 0x00A0, 92 475: 0x00C0, 93 860: 0x00E0, 94 } 95 96 if l.DefaultDataRate == 0 { 97 l.DefaultDataRate = 128 98 } 99 100 l.converter = func(data []byte) (value float64) { 101 result := (int(data[0]) << 8) | int(data[1]) 102 103 if result&0x8000 != 0 { 104 result -= 1 << 16 105 } 106 107 return float64(result) / float64(1<<15) 108 } 109 110 return l 111 } 112 113 func newADS1x15Driver(a Connector, options ...func(Config)) *ADS1x15Driver { 114 l := &ADS1x15Driver{ 115 name: gobot.DefaultName("ADS1x15"), 116 connector: a, 117 // Mapping of gain values to config register values. 118 gainConfig: map[int]uint16{ 119 2 / 3: 0x0000, 120 1: 0x0200, 121 2: 0x0400, 122 4: 0x0600, 123 8: 0x0800, 124 16: 0x0A00, 125 }, 126 gainVoltage: map[int]float64{ 127 2 / 3: 6.144, 128 1: 4.096, 129 2: 2.048, 130 4: 1.024, 131 8: 0.512, 132 16: 0.256, 133 }, 134 DefaultGain: 1, 135 136 Config: NewConfig(), 137 } 138 139 for _, option := range options { 140 option(l) 141 } 142 143 // TODO: add commands to API 144 return l 145 } 146 147 // Start initializes the sensor 148 func (d *ADS1x15Driver) Start() (err error) { 149 bus := d.GetBusOrDefault(d.connector.GetDefaultBus()) 150 address := d.GetAddressOrDefault(ADS1x15DefaultAddress) 151 152 if d.connection, err = d.connector.GetConnection(address, bus); err != nil { 153 return err 154 } 155 156 return 157 } 158 159 // Name returns the Name for the Driver 160 func (d *ADS1x15Driver) Name() string { return d.name } 161 162 // SetName sets the Name for the Driver 163 func (d *ADS1x15Driver) SetName(n string) { d.name = n } 164 165 // Connection returns the connection for the Driver 166 func (d *ADS1x15Driver) Connection() gobot.Connection { return d.connector.(gobot.Connection) } 167 168 // Halt returns true if devices is halted successfully 169 func (d *ADS1x15Driver) Halt() (err error) { return } 170 171 // WithADS1x15Gain option sets the ADS1x15Driver gain option. 172 // Valid gain settings are any of the ADS1x15RegConfigPga* values 173 func WithADS1x15Gain(val int) func(Config) { 174 return func(c Config) { 175 d, ok := c.(*ADS1x15Driver) 176 if ok { 177 d.DefaultGain = val 178 } else { 179 // TODO: return error for trying to set Gain for non-ADS1015Driver 180 return 181 } 182 } 183 } 184 185 // WithADS1x15DataRate option sets the ADS1x15Driver data rate option. 186 // Valid gain settings are any of the ADS1x15RegConfigPga* values 187 func WithADS1x15DataRate(val int) func(Config) { 188 return func(c Config) { 189 d, ok := c.(*ADS1x15Driver) 190 if ok { 191 d.DefaultDataRate = val 192 } else { 193 // TODO: return error for trying to set data rate for non-ADS1015Driver 194 return 195 } 196 } 197 } 198 199 // BestGainForVoltage returns the gain the most adapted to read up to the specified difference of potential. 200 func (d *ADS1x15Driver) BestGainForVoltage(voltage float64) (bestGain int, err error) { 201 var max float64 202 difference := math.MaxFloat64 203 currentBestGain := -1 204 205 for key, value := range d.gainVoltage { 206 max = math.Max(max, value) 207 newDiff := value - voltage 208 if newDiff >= 0 && newDiff < difference { 209 difference = newDiff 210 currentBestGain = key 211 } 212 } 213 214 if currentBestGain < 0 { 215 err = fmt.Errorf("The maximum voltage which can be read is %f", max) 216 return 217 } 218 219 bestGain = currentBestGain 220 return 221 } 222 223 // ReadDifferenceWithDefaults reads the difference in V between 2 inputs. It uses the default gain and data rate 224 // diff can be: 225 // * 0: Channel 0 - channel 1 226 // * 1: Channel 0 - channel 3 227 // * 2: Channel 1 - channel 3 228 // * 3: Channel 2 - channel 3 229 func (d *ADS1x15Driver) ReadDifferenceWithDefaults(diff int) (value float64, err error) { 230 return d.ReadDifference(diff, d.DefaultGain, d.DefaultDataRate) 231 } 232 233 // ReadDifference reads the difference in V between 2 inputs. 234 // diff can be: 235 // * 0: Channel 0 - channel 1 236 // * 1: Channel 0 - channel 3 237 // * 2: Channel 1 - channel 3 238 // * 3: Channel 2 - channel 3 239 func (d *ADS1x15Driver) ReadDifference(diff int, gain int, dataRate int) (value float64, err error) { 240 if err = d.checkChannel(diff); err != nil { 241 return 242 } 243 244 return d.rawRead(diff, gain, dataRate) 245 } 246 247 // ReadWithDefaults reads the voltage at the specified channel (between 0 and 3). 248 // Default values are used for the gain and data rate. The result is in V. 249 func (d *ADS1x15Driver) ReadWithDefaults(channel int) (value float64, err error) { 250 return d.Read(channel, d.DefaultGain, d.DefaultDataRate) 251 } 252 253 // Read reads the voltage at the specified channel (between 0 and 3). The result is in V. 254 func (d *ADS1x15Driver) Read(channel int, gain int, dataRate int) (value float64, err error) { 255 if err = d.checkChannel(channel); err != nil { 256 return 257 } 258 mux := channel + 0x04 259 260 return d.rawRead(mux, gain, dataRate) 261 } 262 263 // AnalogRead returns value from analog reading of specified pin 264 func (d *ADS1x15Driver) AnalogRead(pin string) (value int, err error) { 265 var useDifference = false 266 var channel int 267 var read float64 268 269 // First case: the ADC is used in difference mode 270 switch pin { 271 case "0-1": 272 useDifference = true 273 channel = 0 274 break 275 case "0-3": 276 useDifference = true 277 channel = 1 278 break 279 case "1-3": 280 useDifference = true 281 channel = 2 282 break 283 case "2-3": 284 useDifference = true 285 channel = 3 286 break 287 } 288 289 if useDifference { 290 read, err = d.ReadDifferenceWithDefaults(channel) 291 } else { 292 // Second case: read the voltage at a specific pin, compared to the ground 293 channel, err = strconv.Atoi(pin) 294 if err != nil { 295 return 296 } 297 298 read, err = d.ReadWithDefaults(channel) 299 } 300 301 if err == nil { 302 value = int(gobot.ToScale(gobot.FromScale(read, 0, d.gainVoltage[d.DefaultGain]), 0, 1023)) 303 } 304 305 return 306 } 307 308 func (d *ADS1x15Driver) rawRead(mux int, gain int, dataRate int) (value float64, err error) { 309 var config uint16 310 config = ads1x15ConfigOsSingle // Go out of power-down mode for conversion. 311 // Specify mux value. 312 config |= uint16((mux & 0x07) << ads1x15ConfigMuxOffset) 313 // Validate the passed in gain and then set it in the config. 314 315 gainConf, ok := d.gainConfig[gain] 316 317 if !ok { 318 err = errors.New("Gain must be one of: 2/3, 1, 2, 4, 8, 16") 319 return 320 } 321 config |= gainConf 322 // Set the mode (continuous or single shot). 323 config |= ads1x15ConfigModeSingle 324 // Get the default data rate if none is specified (default differs between 325 // ADS1015 and ADS1115). 326 dataRateConf, ok := d.dataRates[dataRate] 327 328 if !ok { 329 keys := []int{} 330 for k := range d.dataRates { 331 keys = append(keys, k) 332 } 333 334 err = fmt.Errorf("Invalid data rate. Accepted values: %d", keys) 335 return 336 } 337 // Set the data rate (this is controlled by the subclass as it differs 338 // between ADS1015 and ADS1115). 339 config |= dataRateConf 340 config |= ads1x15ConfigCompQueDisable // Disable comparator mode. 341 342 // Send the config value to start the ADC conversion. 343 // Explicitly break the 16-bit value down to a big endian pair of bytes. 344 if _, err = d.connection.Write([]byte{ads1x15PointerConfig, byte((config >> 8) & 0xFF), byte(config & 0xFF)}); err != nil { 345 return 346 } 347 348 // Wait for the ADC sample to finish based on the sample rate plus a 349 // small offset to be sure (0.1 millisecond). 350 time.Sleep(time.Duration(1000000/dataRate+100) * time.Microsecond) 351 352 // Retrieve the result. 353 if _, err = d.connection.Write([]byte{ads1x15PointerConversion}); err != nil { 354 return 355 } 356 357 data := make([]byte, 2) 358 _, err = d.connection.Read(data) 359 if err != nil { 360 return 361 } 362 363 voltageMultiplier, ok := d.gainVoltage[gain] 364 365 if !ok { 366 err = errors.New("Gain must be one of: 2/3, 1, 2, 4, 8, 16") 367 return 368 } 369 370 value = d.converter(data) * voltageMultiplier 371 372 return 373 } 374 375 func (d *ADS1x15Driver) checkChannel(channel int) (err error) { 376 if channel < 0 || channel > 3 { 377 err = errors.New("Invalid channel, must be between 0 and 3") 378 } 379 return 380 }