diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Datasheet/Mma7660fc.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Datasheet/Mma7660fc.pdf new file mode 100644 index 0000000000..0d6947bae6 Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Datasheet/Mma7660fc.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Addresses.cs new file mode 100644 index 0000000000..b1a035ee4b --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Addresses.cs @@ -0,0 +1,20 @@ +namespace Meadow.Foundation.Sensors.Motion +{ + public partial class Mma7660fc + { + /// + /// Valid addresses for the sensor. + /// + public enum Addresses : byte + { + /// + /// Bus address 0x4C + /// + Address_0x4c = 0x4C, + /// + /// Bus address 0x4C + /// + Default = Address_0x4c + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Enums.cs new file mode 100644 index 0000000000..f82a1f9068 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Enums.cs @@ -0,0 +1,121 @@ +namespace Meadow.Foundation.Sensors.Motion +{ + public partial class Mma7660fc + { + /// + /// Sensor power mode + /// + public enum SensorPowerMode : byte + { + /// + /// Device is in standby mode + /// + Standby = 0, + /// + /// Device is active + /// + Active = 1, + } + + /// + /// Represents the number samples per second + /// + public enum SampleRate : byte + { + /// + /// 120 samples per second + /// + _120 = 0, + /// + /// 64 sample per second + /// + _64 = 1, + /// + /// 32 samples per second + /// + _32 =2, + /// + /// 16 samples per second + /// + _16 = 3, + /// + /// 8 samples per second + /// + _8 = 4, + /// + /// 4 samples per second + /// + _4 = 5, + /// + /// 2 samples per second + /// + _2 = 6, + /// + /// 1 samples per second + /// + _1 = 7, + } + + /// + /// Direction/orientation of the device + /// UP/DOWN/LEFT/RIGHT + /// + public enum DirectionType : byte + { + /// + /// Direction unknown + /// + Unknown = 0, + /// + /// Device oriented up + /// + Up = 0b00011000, + /// + /// Device oriented down + /// + Down = 0b00010100, + /// + /// Device oriented right + /// + Right = 0b00001000, + /// + /// Device oriented left + /// + Left = 0b00000100, + } + + /// + /// Is device face down or face up + /// + public enum OrientationType : byte + { + /// + /// Orientation unknown + /// + Unknown = 0, + /// + /// Device is face up (on back) + /// + Back = 0b00000010, + /// + /// Device is face down (on front) + /// + Front = 0b00000001, + } + + /// + /// Device Tilt status + /// + public enum Tilt : byte + { + /// + /// Has the device been shaken + /// + Shake = 0b10000000, + /// + /// Has the device been tapped + /// + Tap = 0b00100000, + } + } +} diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Registers.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Registers.cs new file mode 100644 index 0000000000..48fb0b5be4 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Registers.cs @@ -0,0 +1,15 @@ +namespace Meadow.Foundation.Sensors.Motion +{ + public partial class Mma7660fc + { + public enum Registers : byte + { + XOUT = 0x00, + YOUT = 0x01, + ZOUT = 0x02, + TILT = 0x03, + Mode = 0x07, + SleepRate = 0x08 + } + } +} diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.cs new file mode 100644 index 0000000000..0b419055e3 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.cs @@ -0,0 +1,135 @@ +using System; +using System.Threading.Tasks; +using Meadow.Hardware; +using Meadow.Peripherals.Sensors.Motion; +using Meadow.Units; + +namespace Meadow.Foundation.Sensors.Motion +{ + /// + /// Represents Mma7660fc 3-axis acclerometer + /// + public partial class Mma7660fc : ByteCommsSensorBase, IAccelerometer + { + /// + /// Raised when new acceleration data is processed + /// + public event EventHandler> Acceleration3DUpdated = delegate { }; + + /// + /// Current Acceleration3d value + /// + public Acceleration3D? Acceleration3D => Conditions; + + public DirectionType Direction { get; set; } = DirectionType.Unknown; + public OrientationType Orientation { get; set; } = OrientationType.Unknown; + + /// + /// Create a new instance of the Mma7660fc communicating over the I2C interface. + /// + /// Address of the I2C sensor + /// I2C bus + public Mma7660fc(II2cBus i2cBus, Addresses address = Addresses.Default) + : this(i2cBus, (byte)address) + { + } + + /// + /// Create a new instance of the Mma7660fc communicating over the I2C interface. + /// + /// Address of the I2C sensor + /// I2C bus + public Mma7660fc(II2cBus i2cBus, byte address) + : base(i2cBus, address) + { + Initialize(); + } + + void Initialize() + { + SetMode(SensorPowerMode.Standby); + SetSampleRate(SampleRate._32); + SetMode(SensorPowerMode.Active); + } + + void SetMode(SensorPowerMode mode) + { + Peripheral.WriteRegister((byte)Registers.Mode, (byte)mode); + } + + /// + /// Set sample rate in samples per second + /// + /// sample rate + public void SetSampleRate(SampleRate rate) + { + Peripheral.WriteRegister((byte)Registers.SleepRate, (byte)rate); + } + + /// + /// Read sensor data from registers + /// + /// + protected override Task ReadSensor() + { + return Task.Run(() => + { + Direction = (DirectionType)(Peripheral.ReadRegister((byte)Registers.TILT) & 0x1C); + + Orientation = (OrientationType)(Peripheral.ReadRegister((byte)Registers.TILT) & 0x03); + + int xAccel, yAccel, zAccel; + byte x, y, z; + + //Signed byte 6-bit 2’s complement data with allowable range of +31 to -32 + //[5] is 0 if the g direction is positive, 1 if the g direction is negative. + do + { + x = Peripheral.ReadRegister((byte)Registers.XOUT); + } + //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again + while (x >= 64); + + //check bit 5 and flip to negative + if ((x & (1 << 5)) != 0) xAccel = x - 64; + else xAccel = x; + + do + { + y = Peripheral.ReadRegister((byte)Registers.YOUT); + } + //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again + while (y >= 64); + + if ((y & (1 << 5)) != 0) yAccel = y - 64; + else yAccel = y; + + do + { + z = Peripheral.ReadRegister((byte)Registers.ZOUT); + } + //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again + while (y >= 64); + + if ((z & (1 << 5)) != 0) zAccel = z - 64; + else zAccel = z; + + return new Acceleration3D( + new Acceleration(xAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity), + new Acceleration(yAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity), + new Acceleration(zAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity) + ); + }); + } + + /// + /// Raise event and notify subscribers + /// + /// Acceleration3d data + protected override void RaiseEventsAndNotify(IChangeResult changeResult) + { + Acceleration3DUpdated?.Invoke(this, changeResult); + base.RaiseEventsAndNotify(changeResult); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Sensors.Motion.Mma7660fc.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Sensors.Motion.Mma7660fc.csproj new file mode 100644 index 0000000000..a9f0f23b0c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Sensors.Motion.Mma7660fc.csproj @@ -0,0 +1,22 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + Mma7660fc + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Sensors.Motion.Mma7660fc + https://github.com/WildernessLabs/Meadow.Foundation + Meadow.Foundation, Mma7660fc, Accelerometer, Motion + 0.1.0 + false + Mma7660fc I2C 3-axis accelerometer + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/MeadowApp.cs new file mode 100644 index 0000000000..343a594088 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/MeadowApp.cs @@ -0,0 +1,63 @@ +using System; +using System.Threading.Tasks; +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Motion; +using Meadow.Units; +using AU = Meadow.Units.Acceleration.UnitType; + +namespace Sensors.Motion.Mma7660fc_Sample +{ + public class MeadowApp : App + { + // + + Mma7660fc sensor; + + public MeadowApp() + { + Console.WriteLine("Initializing"); + + // create the sensor driver + sensor = new Mma7660fc(Device.CreateI2cBus()); + + // classical .NET events can also be used: + sensor.Updated += (sender, result) => { + Console.WriteLine($"Accel: [X:{result.New.X.MetersPerSecondSquared:N2}," + + $"Y:{result.New.Y.MetersPerSecondSquared:N2}," + + $"Z:{result.New.Z.MetersPerSecondSquared:N2} (m/s^2)]" + + $" Direction: {sensor.Direction}" + + $" Orientation: {sensor.Orientation}"); + }; + + // Example that uses an IObersvable subscription to only be notified when the filter is satisfied + var consumer = Mma7660fc.CreateObserver( + handler: result => Console.WriteLine($"Observer: [x] changed by threshold; new [x]: X:{result.New.X:N2}, old: X:{result.Old?.X:N2}"), + // only notify if there's a greater than 0.5G change in the Z direction + filter: result => { + if (result.Old is { } old) { //c# 8 pattern match syntax. checks for !null and assigns var. + return ((result.New - old).Z > new Acceleration(0.5, AU.Gravity)); + } + return false; + }); + sensor.Subscribe(consumer); + + //==== one-off read + ReadConditions().Wait(); + + // start updating + sensor.StartUpdating(TimeSpan.FromMilliseconds(1000)); + } + + protected async Task ReadConditions() + { + var result = await sensor.Read(); + Console.WriteLine("Initial Readings:"); + Console.WriteLine($"Accel: [X:{result.X.MetersPerSecondSquared:N2}," + + $"Y:{result.Y.MetersPerSecondSquared:N2}," + + $"Z:{result.Z.MetersPerSecondSquared:N2} (m/s^2)]"); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj new file mode 100644 index 0000000000..79a2715846 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj @@ -0,0 +1,15 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Exe + App + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Program.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Program.cs new file mode 100644 index 0000000000..ea43fb5b4e --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Program.cs @@ -0,0 +1,17 @@ +using System.Threading; +using Meadow; + +namespace Sensors.Motion.Mma7660fc_Sample +{ + class Program + { + static IApp app; + + public static void Main(string[] args) + { + app = new MeadowApp(); + + Thread.Sleep(Timeout.Infinite); + } + } +} diff --git a/Source/Meadow.Foundation.sln b/Source/Meadow.Foundation.sln index b05ddca287..f5b30f0c21 100644 --- a/Source/Meadow.Foundation.sln +++ b/Source/Meadow.Foundation.sln @@ -1044,9 +1044,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Weather.SwitchingRa EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SwitchingRainGauge_Sample", "Meadow.Foundation.Peripherals\Sensors.Weather.SwitchingRainGauge\Samples\SwitchingRainGauge_Sample\SwitchingRainGauge_Sample.csproj", "{AFCF1EBC-B7FC-445A-A8E5-AF3724DA8F78}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.Contracts", "..\..\Meadow.Contracts\Source\Meadow.Contracts\Meadow.Contracts.csproj", "{150569EE-4053-4097-98EE-A455287610B5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Contracts", "..\..\Meadow.Contracts\Source\Meadow.Contracts\Meadow.Contracts.csproj", "{150569EE-4053-4097-98EE-A455287610B5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.Units", "..\..\Meadow.Units\Source\Meadow.Units\Meadow.Units.csproj", "{46394970-4495-408F-8A9C-31BEBC47E899}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Units", "..\..\Meadow.Units\Source\Meadow.Units\Meadow.Units.csproj", "{46394970-4495-408F-8A9C-31BEBC47E899}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sensors.Motion.Mma7660fc", "Sensors.Motion.Mma7660fc", "{8C70DC80-3DD8-40F7-B781-CDF6D9F8EA42}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Motion.Mma7660fc", "Meadow.Foundation.Peripherals\Sensors.Motion.Mma7660fc\Driver\Sensors.Motion.Mma7660fc\Sensors.Motion.Mma7660fc.csproj", "{4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{9D13043C-8A59-461A-9A4D-3735D06CED77}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mma7660fc_Sample", "Meadow.Foundation.Peripherals\Sensors.Motion.Mma7660fc\Samples\Mma7660fc_Sample\Mma7660fc_Sample.csproj", "{A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -2430,6 +2438,18 @@ Global {46394970-4495-408F-8A9C-31BEBC47E899}.Debug|Any CPU.Build.0 = Debug|Any CPU {46394970-4495-408F-8A9C-31BEBC47E899}.Release|Any CPU.ActiveCfg = Release|Any CPU {46394970-4495-408F-8A9C-31BEBC47E899}.Release|Any CPU.Build.0 = Release|Any CPU + {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Release|Any CPU.Build.0 = Release|Any CPU + {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Release|Any CPU.Deploy.0 = Release|Any CPU + {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Release|Any CPU.Build.0 = Release|Any CPU + {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2951,6 +2971,10 @@ Global {AFCF1EBC-B7FC-445A-A8E5-AF3724DA8F78} = {A29C80C8-E116-4344-A49F-7E58529DC338} {150569EE-4053-4097-98EE-A455287610B5} = {65C50059-6C22-43E9-88DE-AD73F7F108C8} {46394970-4495-408F-8A9C-31BEBC47E899} = {65C50059-6C22-43E9-88DE-AD73F7F108C8} + {8C70DC80-3DD8-40F7-B781-CDF6D9F8EA42} = {64623FCA-6086-4F0A-A59D-2BF372EA38AA} + {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9} = {8C70DC80-3DD8-40F7-B781-CDF6D9F8EA42} + {9D13043C-8A59-461A-9A4D-3735D06CED77} = {8C70DC80-3DD8-40F7-B781-CDF6D9F8EA42} + {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED} = {9D13043C-8A59-461A-9A4D-3735D06CED77} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AF7CA16F-8C38-4546-87A2-5DAAF58A1520}