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 }