-
-
Notifications
You must be signed in to change notification settings - Fork 106
/
Adxl345.cs
131 lines (112 loc) · 4.02 KB
/
Adxl345.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Buffers.Binary;
using System.Device.Model;
using System.Device.Spi;
using System.Numerics;
namespace Iot.Device.Adxl345
{
/// <summary>
/// SPI Accelerometer ADX1345.
/// </summary>
[Interface("SPI Accelerometer ADX1345")]
public class Adxl345 : IDisposable
{
private const int Resolution = 1024; // All g ranges resolution
private readonly byte _gravityRangeByte;
private readonly int _range;
private SpiDevice _sensor;
#region SpiSetting
/// <summary>
/// ADX1345 SPI Clock Frequency.
/// </summary>
public const int SpiClockFrequency = 5000000;
/// <summary>
/// ADX1345 SPI Mode.
/// </summary>
public const SpiMode SpiMode = System.Device.Spi.SpiMode.Mode3;
#endregion
/// <summary>
/// Read Acceleration from ADXL345.
/// </summary>
[Telemetry]
public Vector3 Acceleration => ReadAcceleration();
/// <summary>
/// Initializes a new instance of the <see cref="Adxl345" /> class. SPI Accelerometer ADX1345.
/// </summary>
/// <param name="sensor">The communications channel to a device on a SPI bus.</param>
/// <param name="gravityRange">Gravity Measurement Range.</param>
public Adxl345(SpiDevice sensor, GravityRange gravityRange)
{
_sensor = sensor ?? throw new ArgumentNullException(nameof(sensor));
_range = ConvertGravityRangeToInt(gravityRange);
_gravityRangeByte = (byte)gravityRange;
Initialize();
}
private static int ConvertGravityRangeToInt(GravityRange gravityRange)
{
switch (gravityRange)
{
case GravityRange.Range02:
return 4;
case GravityRange.Range04:
return 8;
case GravityRange.Range08:
return 16;
case GravityRange.Range16:
return 32;
default:
return 0;
}
}
/// <summary>
/// Initialize ADXL345.
/// </summary>
private void Initialize()
{
SpanByte dataFormat = new byte[]
{
(byte)Register.ADLX_DATA_FORMAT, _gravityRangeByte
};
SpanByte powerControl = new byte[]
{
(byte)Register.ADLX_POWER_CTL, 0x08
};
_sensor.Write(dataFormat);
_sensor.Write(powerControl);
}
/// <summary>
/// Read data from ADXL345.
/// </summary>
/// <returns>Acceleration as Vector3.</returns>
private Vector3 ReadAcceleration()
{
int units = Resolution / _range;
SpanByte readBuf = new byte[6 + 1];
SpanByte regAddrBuf = new byte[1 + 6];
regAddrBuf[0] = (byte)(Register.ADLX_X0 | Register.ADLX_SPI_RW_BIT | Register.ADLX_SPI_MB_BIT);
_sensor.TransferFullDuplex(regAddrBuf, readBuf);
SpanByte readData = readBuf.Slice(1);
short accelerationX = BinaryPrimitives.ReadInt16LittleEndian(readData.Slice(0, 2));
short accelerationY = BinaryPrimitives.ReadInt16LittleEndian(readData.Slice(2, 2));
short accelerationZ = BinaryPrimitives.ReadInt16LittleEndian(readData.Slice(4, 2));
Vector3 accel = new Vector3
{
X = (float)accelerationX / units, Y = (float)accelerationY / units, Z = (float)accelerationZ / units
};
return accel;
}
/// <summary>
/// <inheritdoc/>
/// </summary>
public void Dispose()
{
if (_sensor != null && _sensor is object)
{
_sensor.Dispose();
_sensor = null;
}
}
}
}