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

     1  package i2c
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"gobot.io/x/gobot/v2"
     8  	"gobot.io/x/gobot/v2/gobottest"
     9  )
    10  
    11  // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver
    12  // and tests all implementations, so no further tests needed here for gobot.Driver interface
    13  var _ gobot.Driver = (*HMC5883LDriver)(nil)
    14  
    15  func initTestHMC5883LWithStubbedAdaptor() (*HMC5883LDriver, *i2cTestAdaptor) {
    16  	a := newI2cTestAdaptor()
    17  	return NewHMC5883LDriver(a), a
    18  }
    19  
    20  func TestNewHMC5883LDriver(t *testing.T) {
    21  	var di interface{} = NewHMC5883LDriver(newI2cTestAdaptor())
    22  	d, ok := di.(*HMC5883LDriver)
    23  	if !ok {
    24  		t.Errorf("NewHMC5883LDriver() should have returned a *HMC5883LDriver")
    25  	}
    26  	gobottest.Refute(t, d.Driver, nil)
    27  	gobottest.Assert(t, strings.HasPrefix(d.name, "HMC5883L"), true)
    28  	gobottest.Assert(t, d.defaultAddress, 0x1E)
    29  	gobottest.Assert(t, d.samplesAvg, uint8(8))
    30  	gobottest.Assert(t, d.outputRate, uint32(15000))
    31  	gobottest.Assert(t, d.applyBias, int8(0))
    32  	gobottest.Assert(t, d.measurementMode, 0)
    33  	gobottest.Assert(t, d.gain, 390.0)
    34  }
    35  
    36  func TestHMC5883LOptions(t *testing.T) {
    37  	// This is a general test, that options are applied in constructor by using the common WithBus() option and
    38  	// least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)".
    39  	d := NewHMC5883LDriver(newI2cTestAdaptor(), WithBus(2), WithHMC5883LSamplesAveraged(4))
    40  	gobottest.Assert(t, d.GetBusOrDefault(1), 2)
    41  	gobottest.Assert(t, d.samplesAvg, uint8(4))
    42  }
    43  
    44  func TestHMC5883LWithHMC5883LDataOutputRate(t *testing.T) {
    45  	d := NewHMC5883LDriver(newI2cTestAdaptor())
    46  	WithHMC5883LDataOutputRate(7500)(d)
    47  	gobottest.Assert(t, d.outputRate, uint32(7500))
    48  }
    49  
    50  func TestHMC5883LWithHMC5883LApplyBias(t *testing.T) {
    51  	d := NewHMC5883LDriver(newI2cTestAdaptor())
    52  	WithHMC5883LApplyBias(-1)(d)
    53  	gobottest.Assert(t, d.applyBias, int8(-1))
    54  }
    55  
    56  func TestHMC5883LWithHMC5883LGain(t *testing.T) {
    57  	d := NewHMC5883LDriver(newI2cTestAdaptor())
    58  	WithHMC5883LGain(230)(d)
    59  	gobottest.Assert(t, d.gain, 230.0)
    60  }
    61  
    62  func TestHMC5883LRead(t *testing.T) {
    63  	// arrange
    64  	var tests = map[string]struct {
    65  		inputX []uint8
    66  		inputY []uint8
    67  		inputZ []uint8
    68  		gain   float64
    69  		wantX  float64
    70  		wantY  float64
    71  		wantZ  float64
    72  	}{
    73  		"+FS_0_-FS_resolution_0.73mG": {
    74  			inputX: []uint8{0x07, 0xFF},
    75  			inputY: []uint8{0x00, 0x00},
    76  			inputZ: []uint8{0xF8, 0x00},
    77  			gain:   1370,
    78  			wantX:  2047.0 / 1370,
    79  			wantY:  0,
    80  			wantZ:  -2048.0 / 1370,
    81  		},
    82  		"+1_-4096_-1_resolution_0.73mG": {
    83  			inputX: []uint8{0x00, 0x01},
    84  			inputY: []uint8{0xF0, 0x00},
    85  			inputZ: []uint8{0xFF, 0xFF},
    86  			gain:   1370,
    87  			wantX:  1.0 / 1370,
    88  			wantY:  -4096.0 / 1370,
    89  			wantZ:  -1.0 / 1370,
    90  		},
    91  		"+FS_0_-FS_resolution_4.35mG": {
    92  			inputX: []uint8{0x07, 0xFF},
    93  			inputY: []uint8{0x00, 0x00},
    94  			inputZ: []uint8{0xF8, 0x00},
    95  			gain:   230,
    96  			wantX:  2047.0 / 230,
    97  			wantY:  0,
    98  			wantZ:  -2048.0 / 230,
    99  		},
   100  		"-1_+1_-4096_resolution_4.35mG": {
   101  			inputX: []uint8{0xFF, 0xFF},
   102  			inputY: []uint8{0x00, 0x01},
   103  			inputZ: []uint8{0xF0, 0x00},
   104  			gain:   230,
   105  			wantX:  -1.0 / 230,
   106  			wantY:  1.0 / 230,
   107  			wantZ:  -4096.0 / 230,
   108  		},
   109  	}
   110  	a := newI2cTestAdaptor()
   111  	for name, tc := range tests {
   112  		t.Run(name, func(t *testing.T) {
   113  			d := NewHMC5883LDriver(a, WithHMC5883LGain(int(tc.gain)))
   114  			d.Start()
   115  			// arrange reads
   116  			returnRead := append(append(tc.inputX, tc.inputZ...), tc.inputY...)
   117  			a.i2cReadImpl = func(b []byte) (int, error) {
   118  				copy(b, returnRead)
   119  				return len(b), nil
   120  			}
   121  			// act
   122  			gotX, gotY, gotZ, err := d.Read()
   123  			// assert
   124  			gobottest.Assert(t, err, nil)
   125  			gobottest.Assert(t, gotX, tc.wantX)
   126  			gobottest.Assert(t, gotY, tc.wantY)
   127  			gobottest.Assert(t, gotZ, tc.wantZ)
   128  		})
   129  	}
   130  }
   131  
   132  func TestHMC5883L_readRawData(t *testing.T) {
   133  	// sequence to read:
   134  	// * prepare read, see test of Start()
   135  	// * read data output registers (3 x 16 bit, MSByte first)
   136  	// * apply two's complement converter
   137  	//
   138  	// arrange
   139  	var tests = map[string]struct {
   140  		inputX []uint8
   141  		inputY []uint8
   142  		inputZ []uint8
   143  		wantX  int16
   144  		wantY  int16
   145  		wantZ  int16
   146  	}{
   147  		"+FS_0_-FS": {
   148  			inputX: []uint8{0x07, 0xFF},
   149  			inputY: []uint8{0x00, 0x00},
   150  			inputZ: []uint8{0xF8, 0x00},
   151  			wantX:  (1<<11 - 1),
   152  			wantY:  0,
   153  			wantZ:  -(1 << 11),
   154  		},
   155  		"-4096_-1_+1": {
   156  			inputX: []uint8{0xF0, 0x00},
   157  			inputY: []uint8{0xFF, 0xFF},
   158  			inputZ: []uint8{0x00, 0x01},
   159  			wantX:  -4096,
   160  			wantY:  -1,
   161  			wantZ:  1,
   162  		},
   163  	}
   164  	d, a := initTestHMC5883LWithStubbedAdaptor()
   165  	d.Start()
   166  	for name, tc := range tests {
   167  		t.Run(name, func(t *testing.T) {
   168  			a.written = []byte{} // reset writes of former test and start
   169  			// arrange reads
   170  			returnRead := append(append(tc.inputX, tc.inputZ...), tc.inputY...)
   171  			numCallsRead := 0
   172  			a.i2cReadImpl = func(b []byte) (int, error) {
   173  				numCallsRead++
   174  				copy(b, returnRead)
   175  				return len(b), nil
   176  			}
   177  			// act
   178  			gotX, gotY, gotZ, err := d.readRawData()
   179  			// assert
   180  			gobottest.Assert(t, err, nil)
   181  			gobottest.Assert(t, gotX, tc.wantX)
   182  			gobottest.Assert(t, gotY, tc.wantY)
   183  			gobottest.Assert(t, gotZ, tc.wantZ)
   184  			gobottest.Assert(t, numCallsRead, 1)
   185  			gobottest.Assert(t, len(a.written), 1)
   186  			gobottest.Assert(t, a.written[0], uint8(hmc5883lAxisX))
   187  		})
   188  	}
   189  }
   190  
   191  func TestHMC5883L_initialize(t *testing.T) {
   192  	// sequence to prepare read in Start():
   193  	// * prepare config register A content (samples averaged, data output rate, measurement mode)
   194  	// * prepare config register B content (gain)
   195  	// * prepare mode register (continuous/single/idle)
   196  	// * write registers A, B, mode
   197  	// arrange
   198  	d, a := initTestHMC5883LWithStubbedAdaptor()
   199  	a.written = []byte{} // reset writes of former test
   200  	wantRegA := uint8(0x70)
   201  	wantRegB := uint8(0xA0)
   202  	wantRegM := uint8(0x00)
   203  	// act, assert - initialize() must be called on Start()
   204  	err := d.Start()
   205  	// assert
   206  	gobottest.Assert(t, err, nil)
   207  	gobottest.Assert(t, len(a.written), 6)
   208  	gobottest.Assert(t, a.written[0], uint8(hmc5883lRegA))
   209  	gobottest.Assert(t, a.written[1], wantRegA)
   210  	gobottest.Assert(t, a.written[2], uint8(hmc5883lRegB))
   211  	gobottest.Assert(t, a.written[3], wantRegB)
   212  	gobottest.Assert(t, a.written[4], uint8(hmc5883lRegMode))
   213  	gobottest.Assert(t, a.written[5], wantRegM)
   214  }