gobot.io/x/gobot/v2@v2.1.0/drivers/i2c/mpl115a2_driver.go (about)

     1  package i2c
     2  
     3  import (
     4  	"gobot.io/x/gobot/v2"
     5  
     6  	"bytes"
     7  	"encoding/binary"
     8  	"time"
     9  )
    10  
    11  const mpl115a2DefaultAddress = 0x60
    12  
    13  const (
    14  	mpl115A2Reg_PressureMSB = 0x00 // first ADC register
    15  	mpl115A2Reg_PressureLSB = 0x01
    16  	mpl115A2Reg_TempMSB     = 0x02
    17  	mpl115A2Reg_TempLSB     = 0x03
    18  
    19  	mpl115A2Reg_A0_MSB  = 0x04 // first coefficient register
    20  	mpl115A2Reg_A0_LSB  = 0x05
    21  	mpl115A2Reg_B1_MSB  = 0x06
    22  	mpl115A2Reg_B1_LSB  = 0x07
    23  	mpl115A2Reg_B2_MSB  = 0x08
    24  	mpl115A2Reg_B2_LSB  = 0x09
    25  	mpl115A2Reg_C12_MSB = 0x0A
    26  	mpl115A2Reg_C12_LSB = 0x0B
    27  
    28  	mpl115A2Reg_StartConversion = 0x12
    29  )
    30  
    31  // MPL115A2Driver is a Gobot Driver for the MPL115A2 I2C digital pressure/temperature sensor.
    32  // datasheet:
    33  // https://www.nxp.com/docs/en/data-sheet/MPL115A2.pdf
    34  //
    35  // reference implementations:
    36  // * https://github.com/adafruit/Adafruit_MPL115A2
    37  type MPL115A2Driver struct {
    38  	*Driver
    39  	gobot.Eventer
    40  	a0  float32
    41  	b1  float32
    42  	b2  float32
    43  	c12 float32
    44  }
    45  
    46  // NewMPL115A2Driver creates a new Gobot Driver for an MPL115A2
    47  // I2C Pressure/Temperature sensor.
    48  //
    49  // Params:
    50  //
    51  //	c Connector - the Adaptor to use with this Driver
    52  //
    53  // Optional params:
    54  //
    55  //	i2c.WithBus(int):	bus to use with this driver
    56  //	i2c.WithAddress(int):	address to use with this driver
    57  func NewMPL115A2Driver(c Connector, options ...func(Config)) *MPL115A2Driver {
    58  	d := &MPL115A2Driver{
    59  		Driver:  NewDriver(c, "MPL115A2", mpl115a2DefaultAddress),
    60  		Eventer: gobot.NewEventer(),
    61  	}
    62  	d.afterStart = d.initialization
    63  
    64  	for _, option := range options {
    65  		option(d)
    66  	}
    67  
    68  	// TODO: add commands to API
    69  	d.AddEvent(Error)
    70  
    71  	return d
    72  }
    73  
    74  // Pressure fetches the latest data from the MPL115A2, and returns the pressure in kPa
    75  func (d *MPL115A2Driver) Pressure() (p float32, err error) {
    76  	d.mutex.Lock()
    77  	defer d.mutex.Unlock()
    78  
    79  	p, _, err = d.getData()
    80  	return
    81  }
    82  
    83  // Temperature fetches the latest data from the MPL115A2, and returns the temperature in °C
    84  func (d *MPL115A2Driver) Temperature() (t float32, err error) {
    85  	d.mutex.Lock()
    86  	defer d.mutex.Unlock()
    87  
    88  	_, t, err = d.getData()
    89  	return
    90  }
    91  
    92  func (d *MPL115A2Driver) initialization() (err error) {
    93  	data := make([]byte, 8)
    94  	if err = d.connection.ReadBlockData(mpl115A2Reg_A0_MSB, data); err != nil {
    95  		return
    96  	}
    97  
    98  	var coA0 int16
    99  	var coB1 int16
   100  	var coB2 int16
   101  	var coC12 int16
   102  
   103  	buf := bytes.NewBuffer(data)
   104  	binary.Read(buf, binary.BigEndian, &coA0)
   105  	binary.Read(buf, binary.BigEndian, &coB1)
   106  	binary.Read(buf, binary.BigEndian, &coB2)
   107  	binary.Read(buf, binary.BigEndian, &coC12)
   108  
   109  	coC12 = coC12 >> 2
   110  
   111  	d.a0 = float32(coA0) / 8.0
   112  	d.b1 = float32(coB1) / 8192.0
   113  	d.b2 = float32(coB2) / 16384.0
   114  	d.c12 = float32(coC12) / 4194304.0
   115  
   116  	return
   117  }
   118  
   119  // getData fetches the latest data from the MPL115A2
   120  func (d *MPL115A2Driver) getData() (p, t float32, err error) {
   121  	var temperature uint16
   122  	var pressure uint16
   123  	var pressureComp float32
   124  
   125  	if err = d.connection.WriteByteData(mpl115A2Reg_StartConversion, 0); err != nil {
   126  		return
   127  	}
   128  	time.Sleep(5 * time.Millisecond)
   129  
   130  	data := []byte{0, 0, 0, 0}
   131  	if err = d.connection.ReadBlockData(mpl115A2Reg_PressureMSB, data); err != nil {
   132  		return
   133  	}
   134  
   135  	buf := bytes.NewBuffer(data)
   136  	binary.Read(buf, binary.BigEndian, &pressure)
   137  	binary.Read(buf, binary.BigEndian, &temperature)
   138  
   139  	temperature = temperature >> 6
   140  	pressure = pressure >> 6
   141  
   142  	pressureComp = d.a0 + (d.b1+d.c12*float32(temperature))*float32(pressure) + d.b2*float32(temperature)
   143  	p = (65.0/1023.0)*pressureComp + 50.0
   144  	t = ((float32(temperature) - 498.0) / -5.35) + 25.0
   145  
   146  	return
   147  }