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

     1  package i2c
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  	"testing"
     7  
     8  	"gobot.io/x/gobot/v2"
     9  	"gobot.io/x/gobot/v2/gobottest"
    10  )
    11  
    12  // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver
    13  // and tests all implementations, so no further tests needed here for gobot.Driver interface
    14  var _ gobot.Driver = (*ADXL345Driver)(nil)
    15  
    16  func initTestADXL345WithStubbedAdaptor() (*ADXL345Driver, *i2cTestAdaptor) {
    17  	a := newI2cTestAdaptor()
    18  	d := NewADXL345Driver(a)
    19  	return d, a
    20  }
    21  
    22  func TestNewADXL345Driver(t *testing.T) {
    23  	var di interface{} = NewADXL345Driver(newI2cTestAdaptor())
    24  	d, ok := di.(*ADXL345Driver)
    25  	if !ok {
    26  		t.Errorf("NewADXL345Driver() should have returned a *ADXL345Driver")
    27  	}
    28  	gobottest.Refute(t, d.Driver, nil)
    29  	gobottest.Assert(t, strings.HasPrefix(d.Name(), "ADXL345"), true)
    30  	gobottest.Assert(t, d.defaultAddress, 0x53)
    31  	gobottest.Assert(t, d.powerCtl.measure, uint8(1))
    32  	gobottest.Assert(t, d.dataFormat.fullScaleRange, ADXL345FsRangeConfig(0x00))
    33  	gobottest.Assert(t, d.bwRate.rate, ADXL345RateConfig(0x0A))
    34  	gobottest.Assert(t, d.bwRate.lowPower, true)
    35  }
    36  
    37  func TestADXL345Options(t *testing.T) {
    38  	// This is a general test, that options are applied in constructor by using the common WithBus() option and
    39  	// least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)".
    40  	d := NewADXL345Driver(newI2cTestAdaptor(), WithBus(2), WithADXL345LowPowerMode(false))
    41  	gobottest.Assert(t, d.GetBusOrDefault(1), 2)
    42  	gobottest.Assert(t, d.bwRate.lowPower, false)
    43  }
    44  
    45  func TestADXL345WithADXL345DataOutputRate(t *testing.T) {
    46  	// arrange
    47  	d, a := initTestADXL345WithStubbedAdaptor()
    48  	a.written = []byte{} // reset writes of former test
    49  	const (
    50  		setVal = ADXL345RateConfig(0x0E) // 1.6kHz
    51  	)
    52  	// act
    53  	WithADXL345DataOutputRate(setVal)(d)
    54  	// assert
    55  	gobottest.Assert(t, d.bwRate.rate, setVal)
    56  	gobottest.Assert(t, len(a.written), 0)
    57  }
    58  
    59  func TestADXL345WithADXL345FullScaleRange(t *testing.T) {
    60  	// arrange
    61  	d, a := initTestADXL345WithStubbedAdaptor()
    62  	a.written = []byte{} // reset writes of former test
    63  	const (
    64  		setVal = ADXL345FsRangeConfig(0x02) // +-8 g
    65  	)
    66  	// act
    67  	WithADXL345FullScaleRange(setVal)(d)
    68  	// assert
    69  	gobottest.Assert(t, d.dataFormat.fullScaleRange, setVal)
    70  	gobottest.Assert(t, len(a.written), 0)
    71  }
    72  
    73  func TestADXL345UseLowPower(t *testing.T) {
    74  	// sequence to set low power:
    75  	// * set value in data rate structure
    76  	// * write the data rate register (0x2C)
    77  	d, a := initTestADXL345WithStubbedAdaptor()
    78  	d.Start()
    79  	a.written = []byte{} // reset writes of former test
    80  	setVal := !d.bwRate.lowPower
    81  	const (
    82  		wantReg = uint8(0x2C)
    83  		wantVal = uint8(0x0A) // only 100 Hz left over
    84  	)
    85  	// act
    86  	err := d.UseLowPower(setVal)
    87  	// assert
    88  	gobottest.Assert(t, err, nil)
    89  	gobottest.Assert(t, d.bwRate.lowPower, setVal)
    90  	gobottest.Assert(t, len(a.written), 2)
    91  	gobottest.Assert(t, a.written[0], wantReg)
    92  	gobottest.Assert(t, a.written[1], wantVal)
    93  }
    94  
    95  func TestADXL345SetRate(t *testing.T) {
    96  	// sequence to set rate:
    97  	// * set value in data rate structure
    98  	// * write the data rate register (0x2C)
    99  	d, a := initTestADXL345WithStubbedAdaptor()
   100  	d.Start()
   101  	a.written = []byte{} // reset writes of former test
   102  	const (
   103  		setVal  = ADXL345RateConfig(0x0F) // 3.2kHz
   104  		wantReg = uint8(0x2C)
   105  		wantVal = uint8(0x1F) // also low power bit
   106  	)
   107  	// act
   108  	err := d.SetRate(setVal)
   109  	// assert
   110  	gobottest.Assert(t, err, nil)
   111  	gobottest.Assert(t, d.bwRate.rate, setVal)
   112  	gobottest.Assert(t, len(a.written), 2)
   113  	gobottest.Assert(t, a.written[0], wantReg)
   114  	gobottest.Assert(t, a.written[1], wantVal)
   115  }
   116  
   117  func TestADXL345SetRange(t *testing.T) {
   118  	// sequence to set range:
   119  	// * set value in data format structure
   120  	// * write the data format register (0x31)
   121  	d, a := initTestADXL345WithStubbedAdaptor()
   122  	d.Start()
   123  	a.written = []byte{} // reset writes of former test
   124  	const (
   125  		setVal  = ADXL345FsRangeConfig(0x03) // +/- 16 g
   126  		wantReg = uint8(0x31)
   127  		wantVal = uint8(0x03)
   128  	)
   129  	// act
   130  	err := d.SetRange(setVal)
   131  	// assert
   132  	gobottest.Assert(t, err, nil)
   133  	gobottest.Assert(t, d.dataFormat.fullScaleRange, setVal)
   134  	gobottest.Assert(t, len(a.written), 2)
   135  	gobottest.Assert(t, a.written[0], wantReg)
   136  	gobottest.Assert(t, a.written[1], wantVal)
   137  }
   138  
   139  func TestADXL345RawXYZ(t *testing.T) {
   140  	// sequence to read:
   141  	// * prepare read, see test of initialize()
   142  	// * read data output registers (0x32, 3 x 16 bit, LSByte first)
   143  	// * apply two's complement converter
   144  	//
   145  	// arrange
   146  	var tests = map[string]struct {
   147  		inputX []uint8
   148  		inputY []uint8
   149  		inputZ []uint8
   150  		wantX  int16
   151  		wantY  int16
   152  		wantZ  int16
   153  	}{
   154  		"+FS_0_-FS": {
   155  			inputX: []uint8{0xFF, 0x07},
   156  			inputY: []uint8{0x00, 0x00},
   157  			inputZ: []uint8{0x00, 0xF8},
   158  			wantX:  (1<<11 - 1),
   159  			wantY:  0,
   160  			wantZ:  -(1 << 11),
   161  		},
   162  		"-4096_-1_+1": {
   163  			inputX: []uint8{0x00, 0xF0},
   164  			inputY: []uint8{0xFF, 0xFF},
   165  			inputZ: []uint8{0x01, 0x00},
   166  			wantX:  -4096,
   167  			wantY:  -1,
   168  			wantZ:  1,
   169  		},
   170  	}
   171  	d, a := initTestADXL345WithStubbedAdaptor()
   172  	d.Start()
   173  	for name, tc := range tests {
   174  		t.Run(name, func(t *testing.T) {
   175  			a.written = []byte{} // reset writes of former test and start
   176  			// arrange reads
   177  			returnRead := append(append(tc.inputX, tc.inputY...), tc.inputZ...)
   178  			numCallsRead := 0
   179  			a.i2cReadImpl = func(b []byte) (int, error) {
   180  				numCallsRead++
   181  				copy(b, returnRead)
   182  				return len(b), nil
   183  			}
   184  			// act
   185  			gotX, gotY, gotZ, err := d.RawXYZ()
   186  			// assert
   187  			gobottest.Assert(t, err, nil)
   188  			gobottest.Assert(t, gotX, tc.wantX)
   189  			gobottest.Assert(t, gotY, tc.wantY)
   190  			gobottest.Assert(t, gotZ, tc.wantZ)
   191  			gobottest.Assert(t, numCallsRead, 1)
   192  			gobottest.Assert(t, len(a.written), 1)
   193  			gobottest.Assert(t, a.written[0], uint8(0x32))
   194  		})
   195  	}
   196  }
   197  
   198  func TestADXL345RawXYZError(t *testing.T) {
   199  	// arrange
   200  	d, a := initTestADXL345WithStubbedAdaptor()
   201  	d.Start()
   202  	a.i2cReadImpl = func(b []byte) (int, error) {
   203  		return 0, errors.New("read error")
   204  	}
   205  	// act
   206  	_, _, _, err := d.RawXYZ()
   207  	// assert
   208  	gobottest.Assert(t, err, errors.New("read error"))
   209  }
   210  
   211  func TestADXL345XYZ(t *testing.T) {
   212  	// arrange
   213  	var tests = map[string]struct {
   214  		inputX []uint8
   215  		inputY []uint8
   216  		inputZ []uint8
   217  		wantX  float64
   218  		wantY  float64
   219  		wantZ  float64
   220  	}{
   221  		"null_value": {
   222  			inputX: []uint8{0, 0},
   223  			inputY: []uint8{0, 0},
   224  			inputZ: []uint8{0, 0},
   225  			wantX:  0,
   226  			wantY:  0,
   227  			wantZ:  0,
   228  		},
   229  		"some_value": {
   230  			inputX: []uint8{218, 0},
   231  			inputY: []uint8{251, 255},
   232  			inputZ: []uint8{100, 0},
   233  			wantX:  0.8515625,
   234  			wantY:  -0.01953125,
   235  			wantZ:  0.390625,
   236  		},
   237  	}
   238  	for name, tc := range tests {
   239  		t.Run(name, func(t *testing.T) {
   240  			// arrange
   241  			d, a := initTestADXL345WithStubbedAdaptor()
   242  			d.Start()
   243  			a.written = []byte{} // reset writes of former test and start
   244  			// arrange reads
   245  			returnRead := append(append(tc.inputX, tc.inputY...), tc.inputZ...)
   246  			numCallsRead := 0
   247  			a.i2cReadImpl = func(b []byte) (int, error) {
   248  				numCallsRead++
   249  				copy(b, returnRead)
   250  				return len(b), nil
   251  			}
   252  			// act
   253  			x, y, z, _ := d.XYZ()
   254  			// assert
   255  			gobottest.Assert(t, x, tc.wantX)
   256  			gobottest.Assert(t, y, tc.wantY)
   257  			gobottest.Assert(t, z, tc.wantZ)
   258  		})
   259  	}
   260  }
   261  
   262  func TestADXL345XYZError(t *testing.T) {
   263  	// arrange
   264  	d, a := initTestADXL345WithStubbedAdaptor()
   265  	d.Start()
   266  	a.i2cReadImpl = func(b []byte) (int, error) {
   267  		return 0, errors.New("read error")
   268  	}
   269  	// act
   270  	_, _, _, err := d.XYZ()
   271  	// assert
   272  	gobottest.Assert(t, err, errors.New("read error"))
   273  }
   274  
   275  func TestADXL345_initialize(t *testing.T) {
   276  	// sequence to prepare read in initialize():
   277  	// * prepare rate register content (data output rate, low power mode)
   278  	// * prepare power control register content (wake up, sleep, measure, auto sleep, link)
   279  	// * prepare data format register (fullScaleRange, justify, fullRes, intInvert, spi, selfTest)
   280  	// * write 3 registers
   281  	// arrange
   282  	d, a := initTestADXL345WithStubbedAdaptor()
   283  	a.written = []byte{} // reset writes of former test
   284  	const (
   285  		wantRateReg      = uint8(0x2C)
   286  		wantRateRegVal   = uint8(0x1A) // 100HZ and low power
   287  		wantPwrReg       = uint8(0x2D)
   288  		wantPwrRegVal    = uint8(0x08) // measurement on
   289  		wantFormatReg    = uint8(0x31)
   290  		wantFormatRegVal = uint8(0x00) // FS to +/-2 g
   291  	)
   292  	// act, assert - initialize() must be called on Start()
   293  	err := d.Start()
   294  	// assert
   295  	gobottest.Assert(t, err, nil)
   296  	gobottest.Assert(t, len(a.written), 6)
   297  	gobottest.Assert(t, a.written[0], wantRateReg)
   298  	gobottest.Assert(t, a.written[1], wantRateRegVal)
   299  	gobottest.Assert(t, a.written[2], wantPwrReg)
   300  	gobottest.Assert(t, a.written[3], wantPwrRegVal)
   301  	gobottest.Assert(t, a.written[4], wantFormatReg)
   302  	gobottest.Assert(t, a.written[5], wantFormatRegVal)
   303  }
   304  
   305  func TestADXL345_shutdown(t *testing.T) {
   306  	// sequence to prepare read in shutdown():
   307  	// * reset the measurement bit in structure
   308  	// * write the power control register (0x2D)
   309  	d, a := initTestADXL345WithStubbedAdaptor()
   310  	d.Start()
   311  	a.written = []byte{} // reset writes of former test
   312  	const (
   313  		wantReg = uint8(0x2D)
   314  		wantVal = uint8(0x00)
   315  	)
   316  	// act, assert - shutdown() must be called on Halt()
   317  	err := d.Halt()
   318  	// assert
   319  	gobottest.Assert(t, err, nil)
   320  	gobottest.Assert(t, len(a.written), 2)
   321  	gobottest.Assert(t, a.written[0], wantReg)
   322  	gobottest.Assert(t, a.written[1], wantVal)
   323  }