first commit

This commit is contained in:
pandacraft 2025-03-21 16:04:17 +01:00
commit a5a0434432
1126 changed files with 439481 additions and 0 deletions

View file

@ -0,0 +1,18 @@
using System;
using System.Threading.Tasks;
namespace GrovePi.Common
{
public static class Delay
{
public static void Milliseconds(int milliseconds)
{
Task.Delay(milliseconds).Wait();
}
public static void Microseconds(int microseconds)
{
Task.Delay(new TimeSpan(microseconds*10)).Wait();
}
}
}

View file

@ -0,0 +1,11 @@
namespace GrovePi
{
internal static class Constants
{
public const byte Unused = 0;
public const byte GroveVcc = 5;
public const byte AdcVoltage = 5;
public const int GroveRgpLcdMaxLength = 16;
public const int GroveRgpLcdRows = 2;
}
}

View file

@ -0,0 +1,430 @@
using GrovePi.I2CDevices;
using GrovePi.Sensors;
using System;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Devices.I2c;
namespace GrovePi
{
public static class DeviceFactory
{
public static IBuildGroveDevices Build = new DeviceBuilder();
}
public interface IBuildGroveDevices
{
IGrovePi GrovePi();
IGrovePi GrovePi(int address);
IRelay Relay(Pin pin);
ILed Led(Pin pin);
ITemperatureSensor TemperatureSensor(Pin pin);
ITemperatureAndHumiditySensor TemperatureAndHumiditySensor(Pin pin, Model model);
IDHTTemperatureAndHumiditySensor DHTTemperatureAndHumiditySensor(Pin pin, DHTModel model);
IUltrasonicRangerSensor UltraSonicSensor(Pin pin);
IAccelerometerSensor AccelerometerSensor(Pin pin);
IAirQualitySensor AirQualitySensor(Pin pin);
IRealTimeClock RealTimeClock(Pin pin);
ILedBar BuildLedBar(Pin pin);
IFourDigitDisplay FourDigitDisplay(Pin pin);
IChainableRgbLed ChainableRgbLed(Pin pin);
IRotaryAngleSensor RotaryAngleSensor(Pin pin);
IBuzzer Buzzer(Pin pin);
ISoundSensor SoundSensor(Pin pin);
ILightSensor LightSensor(Pin pin);
IButtonSensor ButtonSensor(Pin pin);
IRgbLcdDisplay RgbLcdDisplay();
IRgbLcdDisplay RgbLcdDisplay(int rgbAddress, int textAddress);
ISixAxisAccelerometerAndCompass SixAxisAccelerometerAndCompass();
IPIRMotionSensor PIRMotionSensor(Pin pin);
IGasSensorMQ2 GasSensorMQ2(Pin pin);
IMiniMotorDriver MiniMotorDriver();
IMiniMotorDriver MiniMotorDriver(int ch1Address1, int ch2Address2);
IOLEDDisplay9696 OLEDDisplay9696();
IOLEDDisplay128X64 OLEDDisplay128X64();
IThreeAxisAccelerometerADXL345 ThreeAxisAccelerometerADXL345();
IWaterAtomizer WaterAtomizer(Pin pin);
ISHTTemperatureAndHumiditySensor SHTTemperatureAndHumiditySensor();
}
internal class DeviceBuilder : IBuildGroveDevices
{
private const string I2CName = "I2C1"; /* For Raspberry Pi 2, use I2C1 */
private const byte GrovePiAddress = 0x04;
private const byte DisplayRgbI2CAddress = 0xC4;
private const byte DisplayTextI2CAddress = 0x7C;
private const byte SixAxisAccelerometerI2CAddress = 0x1e;
private const byte MiniMotorDriverCH1I2cAddress = 0xC4;
private const byte MiniMotorDriverCH2I2cAddress = 0xC0;
private const byte OLED96_96I2cAddress = 0x3C;
private const byte OLED128_64I2cAddress = 0x3C;
private const byte ThreeAxisAccelemeterADXL345I2cAddress = 0x53;
private const byte SHT31TemperatureAndHumidityI2CAddress = 0x44;
private GrovePi _device;
private RgbLcdDisplay _rgbLcdDisplay;
private SixAxisAccelerometerAndCompass _sixAxisAccelerometerAndCompass;
private MiniMotorDriver _miniMotorDriver;
private OLEDDisplay9696 _oledDisplay9696;
private OLEDDisplay128X64 _oledDisplay128X64;
private ThreeAxisAccelerometerADXL345 _ThreeAxisAccelerometerADXL345;
private SHTTemperatureAndHumiditySensor _shtTemperatureAndHumiditySensor;
public IGrovePi GrovePi()
{
return BuildGrovePiImpl(GrovePiAddress);
}
public IGrovePi GrovePi(int address)
{
return BuildGrovePiImpl(address);
}
public IRelay Relay(Pin pin)
{
return DoBuild(x => new Relay(x, pin));
}
public ILed Led(Pin pin)
{
return DoBuild(x => new Led(x, pin));
}
public ITemperatureSensor TemperatureSensor(Pin pin)
{
return DoBuild(x => new TemperatureSensor(x, pin));
}
public ITemperatureAndHumiditySensor TemperatureAndHumiditySensor(Pin pin, Model model)
{
return DoBuild(x => new TemperatureAndHumiditySensor(x, pin, model));
}
public IDHTTemperatureAndHumiditySensor DHTTemperatureAndHumiditySensor(Pin pin, DHTModel model)
{
return DoBuild(x => new DHTTemperatureAndHumiditySensor(x, pin, model));
}
public IAirQualitySensor AirQualitySensor(Pin pin)
{
return DoBuild(x => new AirQualitySensor(x, pin));
}
public IUltrasonicRangerSensor UltraSonicSensor(Pin pin)
{
return DoBuild(x => new UltrasonicRangerSensor(x, pin));
}
public IAccelerometerSensor AccelerometerSensor(Pin pin)
{
return DoBuild(x => new AccelerometerSensor(x, pin));
}
public IRealTimeClock RealTimeClock(Pin pin)
{
return DoBuild(x => new RealTimeClock(x, pin));
}
public IRotaryAngleSensor RotaryAngleSensor(Pin pin)
{
return DoBuild(x => new RotaryAngleSensor(x, pin));
}
public IBuzzer Buzzer(Pin pin)
{
return DoBuild(x => new Buzzer(x, pin));
}
public ISoundSensor SoundSensor(Pin pin)
{
return DoBuild(x => new SoundSensor(x, pin));
}
public ILedBar BuildLedBar(Pin pin)
{
return DoBuild(x => new LedBar(x, pin));
}
public IFourDigitDisplay FourDigitDisplay(Pin pin)
{
return DoBuild(x => new FourDigitDisplay(x, pin));
}
public IChainableRgbLed ChainableRgbLed(Pin pin)
{
return DoBuild(x => new ChainableRgbLed(x, pin));
}
public ILightSensor LightSensor(Pin pin)
{
return DoBuild(x => new LightSensor(x, pin));
}
public IRgbLcdDisplay RgbLcdDisplay(int rgbAddress, int textAddress)
{
return BuildRgbLcdDisplayImpl(rgbAddress, textAddress);
}
public IRgbLcdDisplay RgbLcdDisplay()
{
return BuildRgbLcdDisplayImpl(DisplayRgbI2CAddress, DisplayTextI2CAddress);
}
public ISixAxisAccelerometerAndCompass SixAxisAccelerometerAndCompass()
{
return BuildSixAxisAccelerometerAndCompassImpl();
}
public IMiniMotorDriver MiniMotorDriver()
{
return BuildMiniMotorDriverImpl(MiniMotorDriverCH1I2cAddress, MiniMotorDriverCH2I2cAddress);
}
public IMiniMotorDriver MiniMotorDriver(int ch1Address, int ch2Address)
{
return BuildMiniMotorDriverImpl(ch1Address, ch2Address);
}
public IOLEDDisplay9696 OLEDDisplay9696()
{
return BuildOLEDDisplayImpl();
}
public IOLEDDisplay128X64 OLEDDisplay128X64()
{
return BuildOLEDDisplay128X64Impl();
}
public IThreeAxisAccelerometerADXL345 ThreeAxisAccelerometerADXL345()
{
return BuildThreeAxisAccelerometerADXL345Impl();
}
public IButtonSensor ButtonSensor(Pin pin)
{
return DoBuild(x => new ButtonSensor(x, pin));
}
private TSensor DoBuild<TSensor>(Func<GrovePi, TSensor> factory)
{
var device = BuildGrovePiImpl(GrovePiAddress);
return factory(device);
}
private GrovePi BuildGrovePiImpl(int address)
{
if (_device != null)
{
return _device;
}
/* Initialize the I2C bus */
var settings = new I2cConnectionSettings(address)
{
BusSpeed = I2cBusSpeed.StandardMode
};
_device = Task.Run(async () =>
{
var dis = await GetDeviceInfo();
// Create an I2cDevice with our selected bus controller and I2C settings
var device = await I2cDevice.FromIdAsync(dis[0].Id, settings);
return new GrovePi(device);
}).Result;
return _device;
}
private RgbLcdDisplay BuildRgbLcdDisplayImpl(int rgbAddress, int textAddress)
{
if (null != _rgbLcdDisplay)
{
return _rgbLcdDisplay;
}
/* Initialize the I2C bus */
var rgbConnectionSettings = new I2cConnectionSettings(rgbAddress>>1)
{
BusSpeed = I2cBusSpeed.StandardMode
};
var textConnectionSettings = new I2cConnectionSettings(textAddress>>1)
{
BusSpeed = I2cBusSpeed.StandardMode
};
_rgbLcdDisplay = Task.Run(async () =>
{
var dis = await GetDeviceInfo();
// Create an I2cDevice with our selected bus controller and I2C settings
var rgbDevice = await I2cDevice.FromIdAsync(dis[0].Id, rgbConnectionSettings);
var textDevice = await I2cDevice.FromIdAsync(dis[0].Id, textConnectionSettings);
return new RgbLcdDisplay(rgbDevice, textDevice);
}).Result;
return _rgbLcdDisplay;
}
private SixAxisAccelerometerAndCompass BuildSixAxisAccelerometerAndCompassImpl()
{
if (_sixAxisAccelerometerAndCompass != null)
{
return _sixAxisAccelerometerAndCompass;
}
var settings = new I2cConnectionSettings(SixAxisAccelerometerI2CAddress)
{
BusSpeed = I2cBusSpeed.StandardMode
};
_sixAxisAccelerometerAndCompass = Task.Run(async () =>
{
var dis = await GetDeviceInfo();
var device = await I2cDevice.FromIdAsync(dis[0].Id, settings);
return new SixAxisAccelerometerAndCompass(device);
}).Result;
return _sixAxisAccelerometerAndCompass;
}
private MiniMotorDriver BuildMiniMotorDriverImpl(int ch1Address, int ch2Address)
{
if (_miniMotorDriver != null)
{
return _miniMotorDriver;
}
var motor1ConnectionSettings = new I2cConnectionSettings(ch1Address>>1)
{
BusSpeed = I2cBusSpeed.StandardMode
};
var motor2ConnectionSettings = new I2cConnectionSettings(ch2Address>>1)
{
BusSpeed = I2cBusSpeed.StandardMode
};
_miniMotorDriver = Task.Run(async () =>
{
var dis = await GetDeviceInfo();
var miniMotor1 = await I2cDevice.FromIdAsync(dis[0].Id, motor1ConnectionSettings);
var miniMotor2 = await I2cDevice.FromIdAsync(dis[0].Id, motor2ConnectionSettings);
return new MiniMotorDriver(miniMotor1, miniMotor2);
}).Result;
return _miniMotorDriver;
}
private OLEDDisplay9696 BuildOLEDDisplayImpl()
{
if(_oledDisplay9696 != null)
{
return _oledDisplay9696;
}
var connectionSettings = new I2cConnectionSettings(OLED96_96I2cAddress)
{
BusSpeed = I2cBusSpeed.StandardMode
};
_oledDisplay9696 = Task.Run(async () =>
{
var dis = await GetDeviceInfo();
var device = await I2cDevice.FromIdAsync(dis[0].Id, connectionSettings);
return new OLEDDisplay9696(device);
}).Result;
return _oledDisplay9696;
}
private OLEDDisplay128X64 BuildOLEDDisplay128X64Impl()
{
if (_oledDisplay128X64 != null)
{
return _oledDisplay128X64;
}
var connectionSettings = new I2cConnectionSettings(OLED128_64I2cAddress)
{
BusSpeed = I2cBusSpeed.StandardMode
};
_oledDisplay128X64 = Task.Run(async () =>
{
var dis = await GetDeviceInfo();
var device = await I2cDevice.FromIdAsync(dis[0].Id, connectionSettings);
return new OLEDDisplay128X64(device);
}).Result;
return _oledDisplay128X64;
}
private ThreeAxisAccelerometerADXL345 BuildThreeAxisAccelerometerADXL345Impl()
{
if (_ThreeAxisAccelerometerADXL345 != null)
{
return _ThreeAxisAccelerometerADXL345;
}
var connectionSettings = new I2cConnectionSettings(ThreeAxisAccelemeterADXL345I2cAddress)
{
BusSpeed = I2cBusSpeed.StandardMode
};
_ThreeAxisAccelerometerADXL345 = Task.Run(async () =>
{
var dis = await GetDeviceInfo();
var device = await I2cDevice.FromIdAsync(dis[0].Id, connectionSettings);
return new ThreeAxisAccelerometerADXL345(device);
}).Result;
return _ThreeAxisAccelerometerADXL345;
}
private SHTTemperatureAndHumiditySensor BuildSHTTemperatureAndHumiditySensorImpl()
{
if (_shtTemperatureAndHumiditySensor != null)
{
return _shtTemperatureAndHumiditySensor;
}
var _shtTemperatureAndHumiditySensorSettings = new I2cConnectionSettings(SHT31TemperatureAndHumidityI2CAddress)
{
BusSpeed = I2cBusSpeed.StandardMode,
SlaveAddress = SHT31TemperatureAndHumidityI2CAddress
};
_shtTemperatureAndHumiditySensor = Task.Run(async () => {
var dis = await GetDeviceInfo();
var shtSensor = await I2cDevice.FromIdAsync(dis[0].Id, _shtTemperatureAndHumiditySensorSettings);
return new SHTTemperatureAndHumiditySensor(shtSensor, SHTModel.Sht31, MeasurementMode.MediumRepeat);
}).Result;
return _shtTemperatureAndHumiditySensor;
}
private static async Task<DeviceInformationCollection> GetDeviceInfo()
{
//Find the selector string for the I2C bus controller
var aqs = I2cDevice.GetDeviceSelector(I2CName);
//Find the I2C bus controller device with our selector string
var dis = await DeviceInformation.FindAllAsync(aqs);
return dis;
}
public IPIRMotionSensor PIRMotionSensor(Pin pin)
{
return DoBuild(x => new PIRMotionSensor(x, pin));
}
public IGasSensorMQ2 GasSensorMQ2(Pin pin)
{
return DoBuild(x => new GasSensorMQ2(x, pin));
}
public IWaterAtomizer WaterAtomizer(Pin pin)
{
return DoBuild(x => new WaterAtomizer(x, pin));
}
public ISHTTemperatureAndHumiditySensor SHTTemperatureAndHumiditySensor()
{
return BuildSHTTemperatureAndHumiditySensorImpl();
}
}
}

View file

@ -0,0 +1,122 @@
using System;
using Windows.Devices.I2c;
using GrovePi.Common;
namespace GrovePi
{
public interface IGrovePi
{
string GetFirmwareVersion();
byte DigitalRead(Pin pin);
void DigitalWrite(Pin pin, byte value);
int AnalogRead(Pin pin);
void AnalogWrite(Pin pin, byte value);
void PinMode(Pin pin, PinMode mode);
void Flush();
}
internal sealed class GrovePi : IGrovePi
{
internal GrovePi(I2cDevice device)
{
if (device == null) throw new ArgumentNullException(nameof(device));
DirectAccess = device;
}
internal I2cDevice DirectAccess { get; }
public string GetFirmwareVersion()
{
var wbuffer = new byte[4] {(byte) Command.Version, Constants.Unused, Constants.Unused, Constants.Unused};
var rbuffer = new byte[4];
var i2cTransferResult = DirectAccess.WritePartial(wbuffer);
if (i2cTransferResult.Status != I2cTransferStatus.FullTransfer)
{
return "0.0.0";
}
i2cTransferResult = DirectAccess.ReadPartial(rbuffer);
if (i2cTransferResult.Status != I2cTransferStatus.FullTransfer)
{
return "0.0.0";
}
return $"{rbuffer[1]}.{rbuffer[2]}.{rbuffer[3]}";
}
public byte DigitalRead(Pin pin)
{
var wbuffer = new byte[4] {(byte) Command.DigitalRead, (byte) pin, Constants.Unused, Constants.Unused};
var rBuffer = new byte[1];
var i2cTransferResult = DirectAccess.WritePartial(wbuffer);
Delay.Milliseconds(10);
if (i2cTransferResult.Status != I2cTransferStatus.FullTransfer)
{
return 0;
}
i2cTransferResult = DirectAccess.ReadPartial(rBuffer);
if (i2cTransferResult.Status != I2cTransferStatus.FullTransfer)
{
return 0;
}
return rBuffer[0];
}
public void DigitalWrite(Pin pin, byte value)
{
var buffer = new byte[4] {(byte) Command.DigitalWrite, (byte) pin, value, Constants.Unused};
DirectAccess.WritePartial(buffer);
Delay.Milliseconds(10);
}
public int AnalogRead(Pin pin)
{
var wbuffer = new byte[4]{(byte) Command.AnalogRead, (byte) pin, Constants.Unused, Constants.Unused};
var rbuffer = new byte[3];
var i2cTransferResult = DirectAccess.WritePartial(wbuffer);
Delay.Milliseconds(10);
if (i2cTransferResult.Status != I2cTransferStatus.FullTransfer)
{
return 0;
}
i2cTransferResult = DirectAccess.ReadPartial(rbuffer);
if (i2cTransferResult.Status != I2cTransferStatus.FullTransfer)
{
return 0;
}
return rbuffer[1]*256 + rbuffer[2];
}
public void AnalogWrite(Pin pin, byte value)
{
var buffer = new byte[4] {(byte) Command.AnalogWrite, (byte) pin, value, Constants.Unused};
DirectAccess.WritePartial(buffer);
Delay.Milliseconds(10);
}
public void PinMode(Pin pin, PinMode mode)
{
var buffer = new byte[4] {(byte) Command.PinMode, (byte) pin, (byte) mode, Constants.Unused};
DirectAccess.WritePartial(buffer);
Delay.Milliseconds(10);
}
public void Flush()
{
var buffer = new byte[4] { Constants.Unused, Constants.Unused, Constants.Unused, Constants.Unused };
DirectAccess.WritePartial(buffer);
}
private enum Command
{
DigitalRead = 1,
DigitalWrite = 2,
AnalogRead = 3,
AnalogWrite = 4,
PinMode = 5,
Version = 8,
//DhtProSensorTemp = 40,
};
}
}

View file

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A667742A-B887-4B46-8EC1-C671E8BEC5E4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GrovePi</RootNamespace>
<AssemblyName>GrovePi</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<GenerateLibraryLayout>true</GenerateLibraryLayout>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<GenerateLibraryLayout>true</GenerateLibraryLayout>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="GrovePi.nuspec" />
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="Common\Delay.cs" />
<Compile Include="Constants.cs" />
<Compile Include="DeviceFactory.cs" />
<Compile Include="GrovePi.cs" />
<Compile Include="I2CDevices\MiniMotorDriver.cs" />
<Compile Include="I2CDevices\OLEDDisplay128X64.cs" />
<Compile Include="I2CDevices\OLEDDisplay9696.cs" />
<Compile Include="I2CDevices\RgbLcdDisplay.cs" />
<Compile Include="I2CDevices\SixAxisAccelerometerAndCompass.cs" />
<Compile Include="I2CDevices\ThreeAxisAccelerometerADXL345.cs" />
<Compile Include="Sensors\AirQualitySensor.cs" />
<Compile Include="Sensors\ButtonSensor.cs" />
<Compile Include="Sensors\Buzzer.cs" />
<Compile Include="I2CDevices\SHTTemperatureAndHumiditySensor.cs" />
<Compile Include="Sensors\GasSensorMQ2.cs" />
<Compile Include="Sensors\Led.cs" />
<Compile Include="Pin.cs" />
<Compile Include="PinMode.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sensors\AccelerometerSensor.cs" />
<Compile Include="Sensors\ChainableRgbLed.cs" />
<Compile Include="Sensors\FourDigitDisplay.cs" />
<Compile Include="Sensors\LedBar.cs" />
<Compile Include="Sensors\LightSensor.cs" />
<Compile Include="Sensors\PIRMotionSensor.cs" />
<Compile Include="Sensors\RealTimeClock.cs" />
<Compile Include="Sensors\Relay.cs" />
<Compile Include="Sensors\RotaryAngleSensor.cs" />
<Compile Include="Sensors\Sensor.cs" />
<Compile Include="Sensors\SensorStatus.cs" />
<Compile Include="Sensors\SoundSensor.cs" />
<Compile Include="Sensors\DHTTemperatureAndHumiditySensor .cs" />
<Compile Include="Sensors\TemperatureAndHumiditySensor.cs" />
<Compile Include="Sensors\TemperatureSensor.cs" />
<Compile Include="Sensors\UltrasonicRangerSensor.cs" />
<Compile Include="Sensors\WaterAtomizer.cs" />
<Content Include="Properties\client.winU.rd.xml" />
</ItemGroup>
<ItemGroup>
<SDKReference Include="WindowsIoT, Version=10.0.10240.0">
<Name>Windows IoT Extensions for the UWP</Name>
</SDKReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
-->
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">
<Exec Command="nuget pack $(MSBuildProjectFile) -OutputDirectory $(OutDir) -Symbols -Prop Configuration=$(Configuration) -Prop TargetPath=$(OutDir)$(AssemblyName)$(TargetExt)" />
</Target>
</Project>

View file

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<package >
<metadata>
<id>GrovePi</id>
<version>1.0.10.0</version>
<title>GrovePi for Windows IoT</title>
<authors>Exadon, Ryan Pedersen</authors>
<owners>Jonathan Robson</owners>
<licenseUrl>http://opensource.org/licenses/MS-PL</licenseUrl>
<projectUrl>https://github.com/robsonj/GrovePi</projectUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<description>GrovePi IoT C# library</description>
<summary>Windows IoT C# library to support GrovePi RaspberryPi 2 sensors</summary>
<releaseNotes>Added new sensors.</releaseNotes>
<language />
<tags>iot, grovepi, windows, arm, internet of things, grove, sensors</tags>
<dependencies />
</metadata>
</package>

View file

@ -0,0 +1,61 @@
using System;
using Windows.Devices.I2c;
namespace GrovePi.I2CDevices
{
public interface IMiniMotorDriver
{
IMiniMotorDriver drive1(int Speed);
IMiniMotorDriver drive2(int Speed);
//IMiniMotorDriver getFault();
}
internal sealed class MiniMotorDriver : IMiniMotorDriver
{
internal MiniMotorDriver(I2cDevice Motor1Device, I2cDevice Motor2Device)
{
if (Motor1Device == null) throw new ArgumentNullException(nameof(Motor1Device));
motor1DirectAccess = Motor1Device;
if (Motor2Device == null) throw new ArgumentNullException(nameof(Motor2Device));
motor2DirectAccess = Motor2Device;
}
~MiniMotorDriver()
{
this.drive1(0);
this.drive2(0);
}
internal I2cDevice motor1DirectAccess { get; }
internal I2cDevice motor2DirectAccess { get; }
public IMiniMotorDriver drive1(int Speed)
{
byte regValue = 0x80;
motor1DirectAccess.Write(new byte[] { 0x1, regValue });
regValue = (byte)Math.Abs(Speed);
if (regValue > 63) regValue = 63;
regValue = (byte)(regValue * 4);
if (Speed < 0) regValue |= 0x01;
else regValue |= 0x02;
motor1DirectAccess.Write(new byte[] { 0x00, regValue});
return this;
}
public IMiniMotorDriver drive2(int Speed)
{
byte regValue = 0x80;
motor2DirectAccess.Write(new byte[] { 0x1, regValue });
regValue = (byte)Math.Abs(Speed);
if (regValue > 63) regValue = 63;
regValue = (byte)(regValue * 4);
if (Speed < 0) regValue |= 0x01;
else regValue |= 0x02;
motor2DirectAccess.Write(new byte[] { 0x00, regValue });
return this;
}
}
}

View file

@ -0,0 +1,440 @@
/*
* Ten Wong (wangtengoo7@gmail.com) 2017 Seeed technology inc.
* Refer to: https://github.com/Seeed-Studio/OLED_Display_128X64
* MIT License
*/
using System;
using Windows.Devices.I2c;
namespace GrovePi.I2CDevices
{
public interface IOLEDDisplay128X64
{
void init();
void setNormalDisplay();
void setInverseDisplay();
void sendCommand(byte command);
void sendData(byte data);
void setPageMode();
void setHorizontalMode();
void setTextXY(byte row, byte column);
void clearDisplay();
void setBrightness(byte brightness);
void putChar(char c);
void putString(string str);
int putNumber(long n);
int putFloat(float floatNumber, byte deci);
int putFloat(float floatNumber);
void drawBitmap(byte[] bitmaparray, int bytes);
void setHorizontalScrollProperties(byte direction, byte startPage, byte endPage, byte scrollSpeed);
void activateScroll();
void deactivateScroll();
}
internal sealed class OLEDDisplay128X64: IOLEDDisplay128X64
{
private const byte SeeedOLED_Max_X = 127; //128 Pixels
private const byte SeeedOLED_Max_Y = 63; //64 Pixels
private const byte PAGE_MODE = 01;
private const byte HORIZONTAL_MODE = 02;
private const byte SeeedOLED_Address = 0x3c;
private const byte SeeedOLED_Command_Mode = 0x80;
private const byte SeeedOLED_Data_Mode = 0x40;
private const byte SeeedOLED_Display_Off_Cmd = 0xAE;
private const byte SeeedOLED_Display_On_Cmd = 0xAF;
private const byte SeeedOLED_Normal_Display_Cmd = 0xA6;
private const byte SeeedOLED_Inverse_Display_Cmd = 0xA7;
private const byte SeeedOLED_Activate_Scroll_Cmd = 0x2F;
private const byte SeeedOLED_Dectivate_Scroll_Cmd = 0x2E;
private const byte SeeedOLED_Set_Brightness_Cmd = 0x81;
private const byte Scroll_Left = 0x00;
private const byte Scroll_Right = 0x01;
private const byte Scroll_2Frames = 0x7;
private const byte Scroll_3Frames = 0x4;
private const byte Scroll_4Frames = 0x5;
private const byte Scroll_5Frames = 0x0;
private const byte Scroll_25Frames = 0x6;
private const byte Scroll_64Frames = 0x1;
private const byte Scroll_128Frames = 0x2;
private const byte Scroll_256Frames = 0x3;
// This font be freely used without any restriction(It is placed in public domain)
private byte[,] BasicFont = new byte[,]
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00},
{0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00},
{0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00},
{0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00},
{0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00},
{0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00},
{0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00},
{0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00},
{0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00},
{0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00},
{0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00},
{0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00},
{0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00},
{0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00},
{0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00},
{0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00},
{0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00},
{0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00},
{0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00},
{0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00},
{0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00},
{0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00},
{0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00},
{0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00},
{0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00},
{0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00},
{0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00},
{0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00},
{0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00},
{0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00},
{0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00},
{0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00},
{0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00},
{0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00},
{0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00},
{0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00},
{0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00},
{0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00},
{0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00},
{0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00},
{0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00},
{0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00},
{0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00},
{0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00},
{0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00},
{0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00},
{0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00},
{0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00},
{0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00},
{0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00},
{0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00},
{0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00},
{0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00},
{0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00},
{0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00},
{0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00},
{0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00},
{0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00},
{0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00},
{0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00},
{0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00},
{0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00},
{0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00},
{0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00},
{0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00},
{0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00},
{0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00},
{0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00},
{0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00},
{0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00},
{0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00},
{0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00},
{0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00},
{0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00},
{0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00},
{0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00},
{0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00},
{0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00},
{0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00},
{0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00},
{0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00},
{0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00},
{0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00},
{0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00},
{0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00},
{0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00},
{0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00},
{0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00},
{0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00},
{0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00},
{0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00},
{0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00},
{0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00}
};
internal I2cDevice DirectAccess { get; }
internal byte addressingMode;
internal OLEDDisplay128X64(I2cDevice Device)
{
if (Device == null) throw new ArgumentNullException(nameof(Device));
DirectAccess = Device;
}
public void init()
{
sendCommand(SeeedOLED_Display_Off_Cmd); //display off
//delay(5);
sendCommand(SeeedOLED_Display_On_Cmd); //display on
//delay(5);
sendCommand(SeeedOLED_Normal_Display_Cmd); //Set Normal Display (default)
}
public void setNormalDisplay()
{
sendCommand(SeeedOLED_Normal_Display_Cmd);
}
public void setInverseDisplay()
{
sendCommand(SeeedOLED_Inverse_Display_Cmd);
}
public void sendCommand(byte command)
{
DirectAccess.Write(new byte[] { SeeedOLED_Command_Mode, command });
}
public void sendData(byte data)
{
DirectAccess.Write(new byte[] { SeeedOLED_Data_Mode, data });
}
public void setPageMode()
{
addressingMode = PAGE_MODE;
sendCommand(0x20); //set addressing mode
sendCommand(0x02); //set page addressing mode
}
public void setHorizontalMode()
{
addressingMode = HORIZONTAL_MODE;
sendCommand(0x20); //set addressing mode
sendCommand(0x00); //set horizontal addressing mode
}
public void setTextXY(byte row, byte column)
{
sendCommand((byte)(0xB0 + row)); //set page address
sendCommand((byte)(0x00 + (8 * column & 0x0F))); //set column lower address
sendCommand((byte)(0x10 + ((8 * column >> 4) & 0x0F))); //set column higher address
}
public void clearDisplay()
{
byte i, j;
sendCommand(SeeedOLED_Display_Off_Cmd); //display off
for (j = 0; j < 8; j++)
{
setTextXY(j, 0);
{
for (i = 0; i < 16; i++) //clear all columns
{
putChar(' ');
}
}
}
sendCommand(SeeedOLED_Display_On_Cmd); //display on
setTextXY(0, 0);
}
public void setBrightness(byte brightness)
{
sendCommand(SeeedOLED_Set_Brightness_Cmd);
sendCommand(brightness);
}
public void putChar(char c)
{
if (c < 32 || c > 127) //Ignore non-printable ASCII characters. This can be modified for multilingual font.
{
c = ' '; //Space
}
byte i = 0;
for (i = 0; i < 8; i++)
{
//read bytes from code memory
sendData(BasicFont[c-32, i]); //font array starts at 0, ASCII starts at 32. Hence the translation
}
}
public void putString(string str)
{
foreach (var c in str)
{
putChar(c);
}
}
public int putNumber(long long_num)
{
char[] char_buffer = new char[10];
int i = 0;
int f = 0;
if (long_num < 0)
{
f = 1;
putChar('-');
long_num = -long_num;
}
else if (long_num == 0)
{
f = 1;
putChar('0');
return f;
}
while (long_num > 0)
{
char_buffer[i++] = (char)(long_num % 10);
long_num /= 10;
}
f = f + i;
for (; i > 0; i--)
{
putChar((char)('0' + (int)(char_buffer[i - 1])));
}
return f;
}
public int putFloat(float floatNumber, byte deci)
{
int temp = 0;
float decy = 0.0F;
float rounding = 0.5F;
int f = 0;
if (floatNumber < 0.0F)
{
putString("-");
floatNumber = -floatNumber;
f += 1;
}
for (int i = 0; i < deci; ++i)
{
rounding /= 10.0F;
}
floatNumber += rounding;
temp = (int)floatNumber;
f += putNumber(temp);
if (deci > 0)
{
putChar('.');
f += 1;
}
decy = floatNumber - temp;//decimal part,
for (int i = 0; i < deci; i++)//4
{
decy *= 10;// for the next decimal
temp = (int)decy;//get the decimal
putNumber(temp);
decy -= temp;
}
f += deci;
return f;
}
public int putFloat(float floatNumber)
{
int deci= 2;
int temp = 0;
float decy = 0.0F;
float rounding = 0.5F;
int f = 0;
if (floatNumber < 0.0)
{
putString("-");
floatNumber = -floatNumber;
f += 1;
}
for (int i = 0; i < deci; ++i)
{
rounding /= 10.0F;
}
floatNumber += rounding;
temp = (int)floatNumber;
f += putNumber(temp);
if (deci > 0)
{
putChar('.');
f += 1;
}
decy = floatNumber - temp;//decimal part,
for (int i = 0; i < deci; i++)//4
{
decy *= 10;// for the next decimal
temp = (int)decy;//get the decimal
putNumber(temp);
decy -= temp;
}
f += deci;
return f;
}
public void drawBitmap(byte[] bitmaparray, int bytes)
{
byte localAddressMode = addressingMode;
if (addressingMode != HORIZONTAL_MODE)
{
//Bitmap is drawn in horizontal mode
setHorizontalMode();
}
for (int i = 0; i < bytes; i++)
{
sendData(bitmaparray[i]);
}
if (localAddressMode == PAGE_MODE)
{
//If pageMode was used earlier, restore it.
setPageMode();
}
}
public void setHorizontalScrollProperties(byte direction, byte startPage, byte endPage, byte scrollSpeed)
{
if (Scroll_Right == direction)
{
//Scroll Right
sendCommand(0x26);
}
else
{
//Scroll Left
sendCommand(0x27);
}
sendCommand(0x00);
sendCommand(startPage);
sendCommand(scrollSpeed);
sendCommand(endPage);
sendCommand(0x00);
sendCommand(0xFF);
}
public void activateScroll()
{
sendCommand(SeeedOLED_Activate_Scroll_Cmd);
}
public void deactivateScroll()
{
sendCommand(SeeedOLED_Dectivate_Scroll_Cmd);
}
}
}

View file

@ -0,0 +1,450 @@
using System;
using Windows.Devices.I2c;
using GrovePi.Common;
using System.Diagnostics;
namespace GrovePi.I2CDevices
{
public interface IOLEDDisplay9696
{
IOLEDDisplay9696 initialize();
IOLEDDisplay9696 setNormalDisplay();
IOLEDDisplay9696 sendCommand(byte cmd);
IOLEDDisplay9696 sendData(byte Data);
IOLEDDisplay9696 setGrayLevel(byte grayLevel);
IOLEDDisplay9696 setVerticalMode();
IOLEDDisplay9696 setHorizontalMode();
IOLEDDisplay9696 setTextXY(byte Row, byte Column);
IOLEDDisplay9696 clearDisplay();
IOLEDDisplay9696 setContrastLevel(byte ContrastLevel);
IOLEDDisplay9696 putChar(char C);
IOLEDDisplay9696 putString(string text);
//IOLEDDisplay9696 putNumber();
//IOLEDDisplay9696 putFloat();
//IOLEDDisplay9696 putFloat();
IOLEDDisplay9696 drawBitmap(byte[] bitmaparray, int bytes);
IOLEDDisplay9696 setHorizontalScrollProperties(bool direction, byte startRow, byte endRow, byte startColumn, byte endColumn, byte scrollSpeed);
IOLEDDisplay9696 activateScroll();
IOLEDDisplay9696 deactivateScroll();
}
internal sealed class OLEDDisplay9696 : IOLEDDisplay9696
{
private const byte VERTICAL_MODE = 1;
private const byte HORIZONTAL_MODE = 2;
private const byte SeeedGrayOLED_Address = 0x3c;
private const byte SeeedGrayOLED_Command_Mode = 0x80;
private const byte SeeedGrayOLED_Data_Mode = 0x40;
private const byte SeeedGrayOLED_Display_Off_Cmd = 0xAE;
private const byte SeeedGrayOLED_Display_On_Cmd = 0xAF;
private const byte SeeedGrayOLED_Normal_Display_Cmd = 0xA4;
private const byte SeeedGrayOLED_Inverse_Display_Cmd = 0xA7;
private const byte SeeedGrayOLED_Activate_Scroll_Cmd = 0x2F;
private const byte SeeedGrayOLED_Dectivate_Scroll_Cmd = 0x2E;
private const byte SeeedGrayOLED_Set_ContrastLevel_Cmd = 0x81;
private const byte Scroll_Left = 0x00;
private const byte Scroll_Right = 0x01;
private const byte Scroll_2Frames = 0x7;
private const byte Scroll_3Frames = 0x4;
private const byte Scroll_4Frames = 0x5;
private const byte Scroll_5Frames = 0x0;
private const byte Scroll_25Frames = 0x6;
private const byte Scroll_64Frames = 0x1;
private const byte Scroll_128Frames = 0x2;
private const byte Scroll_256Frames = 0x3;
private byte grayH = 0;
private byte grayL = 0;
private byte addressingMode = 0;
private byte[,] BasicFont = new byte[,]
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00},
{0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00},
{0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00},
{0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00},
{0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00},
{0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00},
{0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00},
{0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00},
{0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00},
{0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00},
{0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00},
{0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00},
{0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00},
{0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00},
{0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00},
{0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00},
{0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00},
{0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00},
{0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00},
{0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00},
{0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00},
{0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00},
{0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00},
{0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00},
{0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00},
{0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00},
{0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00},
{0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00},
{0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00},
{0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00},
{0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00},
{0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00},
{0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00},
{0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00},
{0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00},
{0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00},
{0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00},
{0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00},
{0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00},
{0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00},
{0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00},
{0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00},
{0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00},
{0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00},
{0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00},
{0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00},
{0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00},
{0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00},
{0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00},
{0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00},
{0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00},
{0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00},
{0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00},
{0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00},
{0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00},
{0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00},
{0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00},
{0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00},
{0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00},
{0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00},
{0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00},
{0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00},
{0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00},
{0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00},
{0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00},
{0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00},
{0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00},
{0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00},
{0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00},
{0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00},
{0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00},
{0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00},
{0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00},
{0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00},
{0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00},
{0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00},
{0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00},
{0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00},
{0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00},
{0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00},
{0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00},
{0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00},
{0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00},
{0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00},
{0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00},
{0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00},
{0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00},
{0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00},
{0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00},
{0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00},
{0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00},
{0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00},
{0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00}
};
internal OLEDDisplay9696(I2cDevice Device)
{
if (Device == null) throw new ArgumentNullException(nameof(Device));
DirectAccess = Device;
}
public IOLEDDisplay9696 initialize()
{
this.sendCommand(0xFD); // unlock IC MCU from entering command.
this.sendCommand(0x12);
this.sendCommand(0xAE); // Set display off
this.sendCommand(0xA8); // set multiplex ratio
this.sendCommand(0x5F); // 96
this.sendCommand(0xA1); // set display start line
this.sendCommand(0x00);
this.sendCommand(0xA2); // set display offset
this.sendCommand(0x60);
this.sendCommand(0xA0); // set remap
this.sendCommand(0x46);
this.sendCommand(0xAB); // set vdd internal
this.sendCommand(0x01); //
this.sendCommand(0x81); // set contrasr
this.sendCommand(0x53); // 100 nit
this.sendCommand(0xB1); // Set Phase Length
this.sendCommand(0X51); //
this.sendCommand(0xB3); // Set Display Clock Divide Ratio/Oscillator Frequency
this.sendCommand(0x01);
this.sendCommand(0xB9); //
this.sendCommand(0xBC); // set pre_charge voltage/VCOMH
this.sendCommand(0x08); // (0x08);
this.sendCommand(0xBE); // set VCOMH
this.sendCommand(0X07); // (0x07);
this.sendCommand(0xB6); // Set second pre-charge period
this.sendCommand(0x01); //
this.sendCommand(0xD5); // enable second precharge and enternal vsl
this.sendCommand(0X62); // (0x62);
this.sendCommand(0xA4); // Set Normal Display Mode
this.sendCommand(0x2E); // Deactivate Scroll
this.sendCommand(0xAF); // Switch on display
Delay.Milliseconds(100);
// Row Address
this.sendCommand(0x75); // Set Row Address
this.sendCommand(0x00); // Start 0
this.sendCommand(0x5f); // End 95
// Column Address
this.sendCommand(0x15); // Set Column Address
this.sendCommand(0x08); // Start from 8th Column of driver IC. This is 0th Column for OLED
this.sendCommand(0x37); // End at (8 + 47)th column. Each Column has 2 pixels(segments)
// Init gray level for text. Default:Brightest White
grayH = 0xF0;
grayL = 0x0F;
return this;
}
internal I2cDevice DirectAccess { get; }
public IOLEDDisplay9696 sendCommand(byte cmd)
{
DirectAccess.Write(new byte[] { SeeedGrayOLED_Command_Mode, cmd });
return this;
}
public IOLEDDisplay9696 setContrastLevel(byte ContrastLevel)
{
this.sendCommand(SeeedGrayOLED_Set_ContrastLevel_Cmd);
this.sendCommand(ContrastLevel);
return this;
}
public IOLEDDisplay9696 setHorizontalMode()
{
this.sendCommand(0xA0); // remap to
this.sendCommand(0x42); // horizontal mode
// Row Address
this.sendCommand(0x75); // Set Row Address
this.sendCommand(0x00); // Start 0
this.sendCommand(0x5f); // End 95
// Column Address
this.sendCommand(0x15); // Set Column Address
this.sendCommand(0x08); // Start from 8th Column of driver IC. This is 0th Column for OLED
this.sendCommand(0x37); // End at (8 + 47)th column. Each Column has 2 pixels(or segments)
return this;
}
public IOLEDDisplay9696 setVerticalMode()
{
this.sendCommand(0xA0); // remap to
this.sendCommand(0x46); // Vertical mode
return this;
}
public IOLEDDisplay9696 setTextXY(byte Row, byte Column)
{
//Column Address
this.sendCommand(0x15); /* Set Column Address */
this.sendCommand((byte)(0x08 + (Column * 4))); /* Start Column: Start from 8 */
this.sendCommand(0x37); /* End Column */
// Row Address
this.sendCommand(0x75); /* Set Row Address */
this.sendCommand((byte)(0x00 + (Row * 8))); /* Start Row*/
this.sendCommand((byte)(0x07 + (Row * 8))); /* End Row*/
return this;
}
public IOLEDDisplay9696 clearDisplay()
{
byte i, j;
for (j = 0; j < 48; j++)
{
for (i = 0; i < 96; i++) //clear all columns
{
this.sendData(0x00);
}
}
return this;
}
public IOLEDDisplay9696 sendData(byte Data)
{
DirectAccess.Write(new byte[] { SeeedGrayOLED_Data_Mode, Data });
return this;
}
public IOLEDDisplay9696 setGrayLevel(byte grayLevel)
{
grayH = (byte)((grayLevel << 4) & 0xF0);
grayL = (byte)(grayLevel & 0x0F);
return this;
}
public IOLEDDisplay9696 putChar(char C)
{
if (C < 32 || C > 127) //Ignore non-printable ASCII characters. This can be modified for multilingual font.
{
C = ' '; //Space
}
for (int i = 0; i < 8; i = i + 2)
{
for (int j = 0; j < 8; j++)
{
// Character is constructed two pixel at a time using vertical mode from the default 8x8 font
byte c = 0x00;
byte bit1 = (byte)((BasicFont[C - 32, i] >> j) & 0x01);
byte bit2 = (byte)((BasicFont[C - 32, i + 1] >> j) & 0x01);
// Each bit is changed to a nibble
c |= (byte)((bit1.Equals(0x01)) ? grayH : 0x00);
c |= (byte)((bit2.Equals(0x01)) ? grayL : 0x00);
this.sendData(c);
}
}
return this;
}
public IOLEDDisplay9696 putString(string text)
{
foreach (var C in text)
{
this.putChar(C);
}
return this;
}
public IOLEDDisplay9696 drawBitmap(byte[] bitmaparray, int bytes)
{
byte localAddressMode = this.addressingMode;
if (addressingMode != HORIZONTAL_MODE)
{
//Bitmap is drawn in horizontal mode
this.setHorizontalMode();
}
//for (int i = 0; i < bytes; i++)
foreach (var Byte in bitmaparray)
{
for (int j = 0; j < 8; j = j + 2)
{
byte c = 0x00;
byte bit1 = (byte)(Byte << j & 0x80);
byte bit2 = (byte)(Byte << (j + 1) & 0x80);
// Each bit is changed to a nibble
c |= (byte)((bit1.Equals(0x80)) ? grayH : 0x00);
// Each bit is changed to a nibble
c |= (byte)((bit2.Equals(0x80)) ? grayL : 0x00);
this.sendData(c);
}
}
if (localAddressMode == VERTICAL_MODE)
{
//If Vertical Mode was used earlier, restore it.
this.setVerticalMode();
}
return this;
}
public IOLEDDisplay9696 setHorizontalScrollProperties(bool direction, byte startRow, byte endRow, byte startColumn, byte endColumn, byte scrollSpeed)
{
/*
Use the following defines for 'direction' :
Scroll_Left
Scroll_Right
Use the following defines for 'scrollSpeed' :
Scroll_2Frames
Scroll_3Frames
Scroll_4Frames
Scroll_5Frames
Scroll_25Frames
Scroll_64Frames
Scroll_128Frames
Scroll_256Frames
*/
if (Scroll_Right.Equals(direction))
{
//Scroll Right
this.sendCommand(0x27);
}
else
{
//Scroll Left
this.sendCommand(0x26);
}
this.sendCommand(0x00); //Dummmy byte
this.sendCommand(startRow);
this.sendCommand(scrollSpeed);
this.sendCommand(endRow);
this.sendCommand((byte)(startColumn + 8));
this.sendCommand((byte)(endColumn + 8));
this.sendCommand(0x00); //Dummmy byte
return this;
}
public IOLEDDisplay9696 activateScroll()
{
this.sendCommand(SeeedGrayOLED_Activate_Scroll_Cmd);
return this;
}
public IOLEDDisplay9696 deactivateScroll()
{
this.sendCommand(SeeedGrayOLED_Dectivate_Scroll_Cmd);
return this;
}
public IOLEDDisplay9696 setNormalDisplay()
{
this.sendCommand(SeeedGrayOLED_Normal_Display_Cmd);
return this;
}
public IOLEDDisplay9696 setInverseDisplay()
{
this.sendCommand(SeeedGrayOLED_Inverse_Display_Cmd);
return this;
}
}
}

View file

@ -0,0 +1,78 @@
using System;
using Windows.Devices.I2c;
using GrovePi.Common;
namespace GrovePi.I2CDevices
{
public interface IRgbLcdDisplay
{
IRgbLcdDisplay SetBacklightRgb(byte red, byte green, byte blue);
IRgbLcdDisplay SetText(string text);
}
internal sealed class RgbLcdDisplay : IRgbLcdDisplay
{
private const byte RedCommandAddress = 4;
private const byte GreenCommandAddress = 3;
private const byte BlueCommandAddress = 2;
private const byte TextCommandAddress = 0x80;
private const byte ClearDisplayCommandAddress = 0x01;
private const byte DisplayOnCommandAddress = 0x08;
private const byte NoCursorCommandAddress = 0x04;
private const byte TwoLinesCommandAddress = 0x28;
private const byte SetCharacterCommandAddress = 0x40;
internal RgbLcdDisplay(I2cDevice rgbDevice, I2cDevice textDevice)
{
if (rgbDevice == null) throw new ArgumentNullException(nameof(rgbDevice));
if (textDevice == null) throw new ArgumentNullException(nameof(textDevice));
RgbDirectAccess = rgbDevice;
TextDirectAccess = textDevice;
}
internal I2cDevice RgbDirectAccess { get; }
internal I2cDevice TextDirectAccess { get; }
public IRgbLcdDisplay SetBacklightRgb(byte red, byte green, byte blue)
{
//TODO: Find out what these addresses are for , set const.
RgbDirectAccess.Write(new byte[] {0, 0});
RgbDirectAccess.Write(new byte[] {1, 0});
RgbDirectAccess.Write(new byte[] { DisplayOnCommandAddress, 0xaa});
RgbDirectAccess.Write(new[] {RedCommandAddress, red});
RgbDirectAccess.Write(new[] {GreenCommandAddress, green});
RgbDirectAccess.Write(new[] {BlueCommandAddress, blue});
return this;
}
public IRgbLcdDisplay SetText(string text)
{
TextDirectAccess.Write(new[] {TextCommandAddress, ClearDisplayCommandAddress});
Delay.Milliseconds(50);
TextDirectAccess.Write(new[] {TextCommandAddress, (byte)(DisplayOnCommandAddress | NoCursorCommandAddress)});
TextDirectAccess.Write(new[] {TextCommandAddress, TwoLinesCommandAddress});
var count = 0;
var row = 0;
foreach (var c in text)
{
if (c.Equals('\n') || count == Constants.GroveRgpLcdMaxLength)
{
count = 0;
row += 1;
if (row == Constants.GroveRgpLcdRows)
break;
TextDirectAccess.Write(new byte[] {TextCommandAddress, 0xc0}); //TODO: find out what this address is
if (c.Equals('\n'))
continue;
}
count += 1;
TextDirectAccess.Write(new[] {SetCharacterCommandAddress, (byte) c});
}
return this;
}
}
}

View file

@ -0,0 +1,155 @@
using Windows.Devices.I2c;
namespace GrovePi.I2CDevices
{
/// <summary>
///
/// </summary>
public interface ISHTTemperatureAndHumiditySensor
{
double TemperatureInCelsius { get; }
double TemperatureInFahrenheit { get; }
double RelativeHumidity { get; }
void Measure();
}
/// <summary>
/// Specifies the model of sensor.
/// </summary>
public enum SHTModel
{
Sht31 = 0
}
/// <summary>
/// The repeatability setting influences the measurement duration and the current
/// consumption of the sensor.
/// </summary>
public enum MeasurementMode
{
HighRepeatClockStretch = 0,
MediumRepeatClockStretch,
LowRepeatClockStretch,
HighRepeat,
MediumRepeat,
LowRepeat
}
internal class SHTTemperatureAndHumiditySensor : ISHTTemperatureAndHumiditySensor
{
private readonly SHTModel _model;
internal I2cDevice _device;
private byte[] MeasureHighClockStretch = new byte[2] { 0x2C, 0x06 };
private byte[] MeasureMediumClockStretch = new byte[2] { 0x2C, 0x0D };
private byte[] MeasureLowClockStretch = new byte[2] { 0x2C, 0x10 };
private byte[] MeasureHigh = new byte[2] { 0x24, 0x00 };
private byte[] MeasureMedium = new byte[2] { 0x24, 0x0B };
private byte[] MeasureLow = new byte[2] { 0x24, 0x16 };
private byte[] ReadStatusRegisterCommandAddress = new byte[2] { 0xF3, 0x2D };
private byte[] ClearStatusRegisterCommandAddress = new byte[2] { 0x30, 0x41 };
private byte[] SoftResetCommandAddress = new byte[2] { 0x30, 0xA2 };
private byte[] EnableHeaterCommandAddress = new byte[2] { 0x30, 0x6D };
private byte[] DisableHeaderCommandAddress = new byte[2] { 0x30, 0x66 };
private byte[] BreakCommandAddress = new byte[2] { 0x30, 0x93 };
private byte[] _sensorData = new byte[6];
private byte[] _sensorCommand = new byte[4];
public double TemperatureInCelsius { get; set; }
public double TemperatureInFahrenheit { get; set; }
public double RelativeHumidity { get; set; }
internal SHTTemperatureAndHumiditySensor(I2cDevice sensorDevice, SHTModel model, MeasurementMode measureMode)
{
_device = sensorDevice;
_model = model;
switch (measureMode)
{
case MeasurementMode.HighRepeatClockStretch:
_sensorCommand = MeasureHighClockStretch;
break;
case MeasurementMode.MediumRepeatClockStretch:
_sensorCommand = MeasureMediumClockStretch;
break;
case MeasurementMode.LowRepeatClockStretch:
_sensorCommand = MeasureLowClockStretch;
break;
case MeasurementMode.HighRepeat:
_sensorCommand = MeasureHigh;
break;
case MeasurementMode.MediumRepeat:
_sensorCommand = MeasureMedium;
break;
case MeasurementMode.LowRepeat:
_sensorCommand = MeasureLow;
break;
default:
_sensorCommand = MeasureHigh;
break;
}
}
public void Measure()
{
_device.WriteRead(_sensorCommand, _sensorData);
TemperatureInCelsius = (((_sensorData[0] * 256) + _sensorData[1]) * 175.0) / 65535.0 - 45.0;
TemperatureInFahrenheit = (((_sensorData[0] * 256) + _sensorData[1]) * 315.0) / 65535.0 - 49.0;
RelativeHumidity = (((_sensorData[3] * 256) + _sensorData[4])) * 100.0 / 65535.0 - 6.0;
}
/// <summary>
/// This triggers the sensor to reset its system controller and reloads calibration data from the memory.
/// </summary>
public void Reset()
{
_device.Write(SoftResetCommandAddress);
}
/// <summary>
/// All flags (Bit 15, 11, 10, 4) in the status register can be cleared (set to zero)
/// </summary>
public void ClearStatusRegister()
{
_device.Write(ClearStatusRegisterCommandAddress);
}
/// <summary>
/// The status register contains information on the operational status of the heater, the alert mode and on
/// the execution status of the last command and the last write sequence.
/// </summary>
/// <returns>16bit status register response</returns>
public byte[] ReadStatusRegister()
{
var statusResponse = new byte[2];
_device.WriteReadPartial(ReadStatusRegisterCommandAddress, statusResponse);
return statusResponse;
}
/// <summary>
/// The heater can be switched on and off by command
/// </summary>
public void EnableHeater()
{
_device.Write(EnableHeaterCommandAddress);
}
public void DisableHeater()
{
_device.Write(DisableHeaderCommandAddress);
}
/// <summary>
/// It is rrecommended to stop the periodic data acquisition prior to sending another command using the break command.
/// Upon reception of the break command the sensor enters the single shot mode.
/// </summary>
internal void Break()
{
_device.Write(BreakCommandAddress);
}
}
}

View file

@ -0,0 +1,405 @@
using System;
using System.Linq;
using GrovePi.I2CDevices.Configuration;
using Windows.Devices.I2c;
using static System.Math;
namespace GrovePi.I2CDevices
{
public interface ISixAxisAccelerometerAndCompass
{
byte DeviceId();
double[] GetAcceleration();
double[] GetMagnetic();
double GetHeading();
double GetTiltHeading();
ISixAxisAccelerometerAndCompass Configure(Action<ISixAxisAccelerometerAndCompassConfiguration> configuration);
}
public interface ISixAxisAccelerometerAndCompassConfiguration
{
void AccelerationAxes(AccelerationAxes value);
void AccelerationDataRate(AccelerationDataRate value);
void AccelerationDataUpdateMode(AccelerationDataUpdateMode value);
void AccelerationScale(AccelerationScale value);
void MagneticDataRate(MagneticDataRate value);
void MagneticMode(MagneticMode value);
void MagneticResolution(MagneticResolution value);
void MagneticScale(MagneticScale value);
}
internal sealed class SixAxisAccelerometerAndCompass : ISixAxisAccelerometerAndCompass
{
private const int X = 0;
private const int Y = 1;
private const int Z = 2;
private const double Pow_2_15 = 32768;
private const byte WHO_AM_I = 0x0f;
private const byte CTRL_REG0 = 0x1F;
private const byte CTRL_REG1 = 0x20;
private const byte CTRL_REG2 = 0x21;
private const byte CTRL_REG3 = 0x22;
private const byte CTRL_REG4 = 0x23;
private const byte CTRL_REG5 = 0x24;
private const byte CTRL_REG6 = 0x25;
private const byte CTRL_REG7 = 0x26;
private const byte OUT_X_L_M = 0x08;
private const byte OUT_X_H_M = 0x09;
private const byte OUT_Y_L_M = 0x0A;
private const byte OUT_Y_H_M = 0x0B;
private const byte OUT_Z_L_M = 0x0C;
private const byte OUT_Z_H_M = 0x0D;
private const byte OUT_X_L_A = 0x28;
private const byte OUT_X_H_A = 0x29;
private const byte OUT_Y_L_A = 0x2A;
private const byte OUT_Y_H_A = 0x2B;
private const byte OUT_Z_L_A = 0x2C;
private const byte OUT_Z_H_A = 0x2D;
internal I2cDevice DirectAccess
{
get;
}
internal AccelerationAxes AccelerationAxes
{
get;
set;
} = AccelerationAxes.XYZ;
internal AccelerationDataRate AccelerationDataRate
{
get;
set;
} = AccelerationDataRate.Hz_50;
internal AccelerationDataUpdateMode AccelerationDataUpdateMode
{
get;
set;
} = AccelerationDataUpdateMode.Continuous;
internal AccelerationScale AccelerationScale
{
get
{
return accelerationScale;
}
set
{
accelerationScale = value;
switch (accelerationScale)
{
case AccelerationScale.G_2:
accelerationScaleFactor = 2.0;
break;
case AccelerationScale.G_4:
accelerationScaleFactor = 4.0;
break;
case AccelerationScale.G_6:
accelerationScaleFactor = 6.0;
break;
case AccelerationScale.G_8:
accelerationScaleFactor = 8.0;
break;
case AccelerationScale.G_16:
accelerationScaleFactor = 16.0;
break;
}
}
}
private AccelerationScale accelerationScale = AccelerationScale.G_2;
private double accelerationScaleFactor = 2.0;
internal MagneticDataRate MagneticDataRate
{
get;
set;
} = MagneticDataRate.Hz_50;
internal MagneticMode MagneticMode
{
get;
set;
} = MagneticMode.ContinousConversion;
internal MagneticResolution MagneticResolution
{
get;
set;
} = MagneticResolution.Low;
internal MagneticScale MagneticScale
{
get;
set;
} = MagneticScale.Gs_4;
internal SixAxisAccelerometerAndCompass(I2cDevice device)
{
if (device == null)
throw new ArgumentNullException(nameof(device));
DirectAccess = device;
Reconfigure();
}
public byte DeviceId() => ReadRegister(WHO_AM_I);
public double[] GetAcceleration()
{
// Windows is little-endian so read registers from low to high
var input = new[]
{
ReadRegister(OUT_X_L_A), ReadRegister(OUT_X_H_A),
ReadRegister(OUT_Y_L_A), ReadRegister(OUT_Y_H_A),
ReadRegister(OUT_Z_L_A), ReadRegister(OUT_Z_H_A)
};
// calculate two's complement value and scale by acceleration factor
var output = new[]
{
BitConverter.ToInt16(input, 0) / Pow_2_15 * accelerationScaleFactor,
BitConverter.ToInt16(input, 2) / Pow_2_15 * accelerationScaleFactor,
BitConverter.ToInt16(input, 4) / Pow_2_15 * accelerationScaleFactor
};
return output;
}
public double[] GetMagnetic()
{
// Windows is little-endian so read registers from low to high
var input = new[]
{
ReadRegister(OUT_X_L_M), ReadRegister(OUT_X_H_M),
ReadRegister(OUT_Y_L_M), ReadRegister(OUT_Y_H_M),
ReadRegister(OUT_Z_L_M), ReadRegister(OUT_Z_H_M)
};
// calculate two's complement value
var output = new[]
{
BitConverter.ToInt16(input, 0) / Pow_2_15,
BitConverter.ToInt16(input, 2) / Pow_2_15,
BitConverter.ToInt16(input, 4) / Pow_2_15
};
return output;
}
public double GetHeading()
{
var magnetic = GetMagnetic();
var heading = 180 * Atan2(magnetic[Y], magnetic[X]) / PI;
return (heading < 0) ? (heading + 360) : heading;
}
public double GetTiltHeading()
{
var acceleration = GetAcceleration();
var pitch = Asin(-acceleration[X]);
var roll = Asin(acceleration[Y] / Cos(pitch));
var magnetic = GetMagnetic();
var xh = magnetic[X] * Cos(pitch) + magnetic[Z] * Sin(pitch);
var yh = magnetic[X] * Sin(roll) * Sin(pitch) + magnetic[Y] * Cos(roll) - magnetic[Z] * Sin(roll) * Cos(pitch);
var heading = 180 * Atan2(yh, xh) / PI;
return (heading < 0) ? (heading + 360) : heading;
}
public ISixAxisAccelerometerAndCompass Configure(Action<ISixAxisAccelerometerAndCompassConfiguration> configuration)
{
if (configuration != null)
{
configuration(new SixAxisAccelerometerAndCompassConfiguration(this));
Reconfigure();
}
return this;
}
private byte ReadRegister(byte register)
{
var buffer = new byte[1];
DirectAccess.WriteRead(new[] { register }, buffer);
return buffer[0];
}
private void Reconfigure()
{
DirectAccess.Write(new[] { CTRL_REG0, (byte)0 }); // normal mode, FIFO disabled, high-pass filter disabled
DirectAccess.Write(new[] { CTRL_REG1, (byte)((byte)AccelerationDataRate | (byte)AccelerationDataUpdateMode | (byte)AccelerationAxes) });
DirectAccess.Write(new[] { CTRL_REG2, (byte)AccelerationScale });
DirectAccess.Write(new[] { CTRL_REG3, (byte)0 }); // interrupt 1 disabled
DirectAccess.Write(new[] { CTRL_REG4, (byte)0 }); // interrupt 2 disabled
DirectAccess.Write(new[] { CTRL_REG5, (byte)((byte)MagneticResolution | (byte)MagneticDataRate) });
DirectAccess.Write(new[] { CTRL_REG6, (byte)MagneticScale });
DirectAccess.Write(new[] { CTRL_REG7, (byte)MagneticMode });
}
}
internal sealed class SixAxisAccelerometerAndCompassConfiguration : ISixAxisAccelerometerAndCompassConfiguration
{
private readonly SixAxisAccelerometerAndCompass _sensor;
public SixAxisAccelerometerAndCompassConfiguration(SixAxisAccelerometerAndCompass sensor)
{
_sensor = sensor;
}
public void AccelerationAxes(AccelerationAxes value)
{
_sensor.AccelerationAxes = value;
}
public void AccelerationDataRate(AccelerationDataRate value)
{
_sensor.AccelerationDataRate = value;
}
public void AccelerationDataUpdateMode(AccelerationDataUpdateMode value)
{
_sensor.AccelerationDataUpdateMode = value;
}
public void AccelerationScale(AccelerationScale value)
{
_sensor.AccelerationScale = value;
}
public void MagneticDataRate(MagneticDataRate value)
{
if ((value == Configuration.MagneticDataRate.Hz_100) && (_sensor.AccelerationDataRate > Configuration.AccelerationDataRate.None) && (_sensor.AccelerationDataRate <= Configuration.AccelerationDataRate.Hz_50))
{
_sensor.AccelerationDataRate = Configuration.AccelerationDataRate.Hz_100;
}
_sensor.MagneticDataRate = value;
}
public void MagneticMode(MagneticMode value)
{
_sensor.MagneticMode = value;
}
public void MagneticResolution(MagneticResolution value)
{
_sensor.MagneticResolution = value;
}
public void MagneticScale(MagneticScale value)
{
_sensor.MagneticScale = value;
}
}
namespace Configuration
{
[Flags]
public enum AccelerationAxes : byte
{
None = 0,
X = 4,
Y = 2,
Z = 1,
XYZ = X | Y | Z
}
public enum AccelerationDataRate : byte
{
None = 0,
Hz_3_125 = 16,
Hz_6_25 = 32,
Hz_12_5 = 48,
Hz_25 = 64,
Hz_50 = 80,
Hz_100 = 96,
Hz_200 = 112,
Hz_400 = 128,
Hz_800 = 144,
Hz_1600 = 160
}
public enum AccelerationDataUpdateMode : byte
{
Continuous = 0,
OnRead = 8
}
public enum AccelerationScale : byte
{
G_2 = 0,
G_4 = 8,
G_6 = 16,
G_8 = 24,
G_16 = 32
}
public enum MagneticMode : byte
{
ContinousConversion = 0,
SingleConversion = 1,
PowerDown = 3
}
public enum MagneticDataRate : byte
{
Hz_3_125 = 0,
Hz_6_25 = 4,
Hz_12_5 = 8,
Hz_25 = 12,
Hz_50 = 16,
Hz_100 = 20
}
public enum MagneticResolution : byte
{
Low = 0,
High = 96
}
public enum MagneticScale : byte
{
Gs_2 = 0,
Gs_4 = 32,
Gs_8 = 64,
Gs_12 = 96
}
}
}

View file

@ -0,0 +1,91 @@
using System;
using GrovePi.I2CDevices.Configuration;
using Windows.Devices.I2c;
namespace GrovePi.I2CDevices
{
public interface IThreeAxisAccelerometerADXL345
{
IThreeAxisAccelerometerADXL345 Initialize();
double[] GetAcclXYZ();
}
internal sealed class ThreeAxisAccelerometerADXL345 : IThreeAxisAccelerometerADXL345
{
struct Acceleration
{
public double X;
public double Y;
public double Z;
};
private const byte ACCEL_I2C_ADDR = 0x53; /* 7-bit I2C address of the ADXL345 with SDO pulled low */
private const byte ACCEL_REG_POWER_CONTROL = 0x2D; /* Address of the Power Control register */
private const byte ACCEL_REG_DATA_FORMAT = 0x31; /* Address of the Data Format register */
private const byte ACCEL_REG_X = 0x32; /* Address of the X Axis data register */
private const byte ACCEL_REG_Y = 0x34; /* Address of the Y Axis data register */
private const byte ACCEL_REG_Z = 0x36; /* Address of the Z Axis data register */
internal I2cDevice DirectAccess { get; }
internal ThreeAxisAccelerometerADXL345(I2cDevice Device)
{
if (Device == null) throw new ArgumentNullException(nameof(Device));
DirectAccess = Device;
}
public IThreeAxisAccelerometerADXL345 Initialize()
{
/*
* Initialize the accelerometer:
*
* For this device, we create 2-byte write buffers:
* The first byte is the register address we want to write to.
* The second byte is the contents that we want to write to the register.
*/
byte[] WriteBuf_DataFormat = new byte[] { ACCEL_REG_DATA_FORMAT, 0x01 }; /* 0x01 sets range to +- 4Gs */
byte[] WriteBuf_PowerControl = new byte[] { ACCEL_REG_POWER_CONTROL, 0x08 }; /* 0x08 puts the accelerometer into measurement mode */
/* Write the register settings */
DirectAccess.Write(WriteBuf_DataFormat);
DirectAccess.Write(WriteBuf_PowerControl);
return this;
}
public double[] GetAcclXYZ()
{
const int ACCEL_RES = 1024; /* The ADXL345 has 10 bit resolution giving 1024 unique values */
const int ACCEL_DYN_RANGE_G = 8; /* The ADXL345 had a total dynamic range of 8G, since we're configuring it to +-4G */
const int UNITS_PER_G = ACCEL_RES / ACCEL_DYN_RANGE_G; /* Ratio of raw int values to G units */
byte[] RegAddrBuf = new byte[] { ACCEL_REG_X }; /* Register address we want to read from */
byte[] ReadBuf = new byte[6]; /* We read 6 bytes sequentially to get all 3 two-byte axes registers in one read */
/*
* Read from the accelerometer
* We call WriteRead() so we first write the address of the X-Axis I2C register, then read all 3 axes
*/
DirectAccess.WriteRead(RegAddrBuf, ReadBuf);
/*
* In order to get the raw 16-bit data values, we need to concatenate two 8-bit bytes from the I2C read for each axis.
* We accomplish this by using the BitConverter class.
*/
short AccelerationRawX = BitConverter.ToInt16(ReadBuf, 0);
short AccelerationRawY = BitConverter.ToInt16(ReadBuf, 2);
short AccelerationRawZ = BitConverter.ToInt16(ReadBuf, 4);
/* Convert raw values to G's */
double[] accel = new double[3];
accel[0] = (double)AccelerationRawX / UNITS_PER_G;
accel[1] = (double)AccelerationRawY / UNITS_PER_G;
accel[2] = (double)AccelerationRawZ / UNITS_PER_G;
return accel;
}
}
}

View file

@ -0,0 +1,16 @@
namespace GrovePi
{
public enum Pin
{
AnalogPin0 = 0,
AnalogPin1 = 1,
AnalogPin2 = 2,
DigitalPin2 = 2,
DigitalPin3 = 3,
DigitalPin4 = 4,
DigitalPin5 = 5,
DigitalPin6 = 6,
DigitalPin7 = 7,
DigitalPin8 = 8
}
}

View file

@ -0,0 +1,8 @@
namespace GrovePi
{
public enum PinMode
{
Input = 0,
Output = 1
}
}

View file

@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("GrovePi")]
[assembly: AssemblyDescription("GrovePi library for Windows IoT")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jonathan Robson")]
[assembly: AssemblyProduct("GrovePi")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.10")]
[assembly: AssemblyFileVersion("1.0.10")]
[assembly: ComVisible(false)]

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains Runtime Directives, specifications about types your application accesses
through reflection and other dynamic code patterns. Runtime Directives are used to control the
.NET Native optimizer and ensure that it does not remove code accessed by your library. If your
library does not do any reflection, then you generally do not need to edit this file. However,
if your library reflects over types, especially types passed to it or derived from its types,
then you should write Runtime Directives.
The most common use of reflection in libraries is to discover information about types passed
to the library. Runtime Directives have three ways to express requirements on types passed to
your library.
1. Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
Use these directives to reflect over types passed as a parameter.
2. SubTypes
Use a SubTypes directive to reflect over types derived from another type.
3. AttributeImplies
Use an AttributeImplies directive to indicate that your library needs to reflect over
types or methods decorated with an attribute.
For more information on writing Runtime Directives for libraries, please visit
http://go.microsoft.com/fwlink/?LinkId=613100
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="GrovePi">
<!-- add directives for your library here -->
</Library>
</Directives>

View file

@ -0,0 +1,41 @@
using System;
namespace GrovePi.Sensors
{
public interface IAccelerometerSensor
{
byte[] Read();
}
internal class AccelerometerSensor : IAccelerometerSensor
{
private const byte CommandAddress = 20;
private readonly GrovePi _device;
private readonly Pin _pin;
internal AccelerometerSensor(GrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
_device = device;
_pin = pin;
}
public byte[] Read()
{
var buffer = new [] {CommandAddress, (byte) _pin, Constants.Unused, Constants.Unused};
_device.DirectAccess.Write(buffer);
var readBuffer = new byte[1];
_device.DirectAccess.Read(readBuffer);
if (readBuffer[1] > 32)
readBuffer[1] = (byte) -(readBuffer[1] - 224);
if (readBuffer[2] > 32)
readBuffer[2] = (byte) -(readBuffer[1] - 224);
if (readBuffer[3] > 32)
readBuffer[3] = (byte) -(readBuffer[1] - 224);
return readBuffer;
}
}
}

View file

@ -0,0 +1,27 @@
using System;
namespace GrovePi.Sensors
{
public interface IAirQualitySensor
{
int AirQuality();
}
internal class AirQualitySensor : IAirQualitySensor
{
private readonly GrovePi _device;
private readonly Pin _pin;
internal AirQualitySensor(GrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
device.PinMode(_pin, PinMode.Input);
_device = device;
_pin = pin;
}
public int AirQuality()
{
return _device.AnalogRead(_pin);
}
}
}

View file

@ -0,0 +1,14 @@
namespace GrovePi.Sensors
{
public interface IButtonSensor
{
SensorStatus CurrentState { get; }
}
internal class ButtonSensor : Sensor<IButtonSensor>, IButtonSensor
{
internal ButtonSensor(IGrovePi device, Pin pin) : base(device, pin, PinMode.Input)
{
}
}
}

View file

@ -0,0 +1,15 @@
namespace GrovePi.Sensors
{
public interface IBuzzer
{
SensorStatus CurrentState { get; }
IBuzzer ChangeState(SensorStatus newState);
}
internal class Buzzer : Sensor<IBuzzer>, IBuzzer
{
internal Buzzer(IGrovePi device, Pin pin) : base(device, pin, PinMode.Output)
{
}
}
}

View file

@ -0,0 +1,75 @@
using System;
namespace GrovePi.Sensors
{
public interface IChainableRgbLed
{
IChainableRgbLed Initialise(byte numberOfLeds);
IChainableRgbLed StoreColor(byte red, byte green, byte blue);
IChainableRgbLed Test(byte numberOfLeds, byte testColor);
IChainableRgbLed SetPattern(byte pattern, byte led);
IChainableRgbLed Mudulo(byte offset, byte divisor);
IChainableRgbLed SetLevel(byte level, bool reverse);
}
internal class ChainableRgbLed : IChainableRgbLed
{
public const byte StoreColorCommandAddress = 90;
public const byte InitialiseCommandAddress = 91;
public const byte TestCommandAddress = 92;
public const byte SetPatternCommandAddress = 93;
public const byte SetModuloCommandAddress = 94;
public const byte SetLevelCommmandAddress = 95;
private readonly GrovePi _device;
private readonly Pin _pin;
internal ChainableRgbLed(GrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
_device = device;
_pin = pin;
}
public IChainableRgbLed SetLevel(byte level, bool reverse)
{
var buffer = new[] {level, (byte) _pin, level, reverse ? (byte) 1 : (byte) 0};
_device.DirectAccess.Write(buffer);
return this;
}
public IChainableRgbLed Initialise(byte numberOfLeds)
{
var buffer = new[] {InitialiseCommandAddress, (byte) _pin, numberOfLeds, Constants.Unused};
_device.DirectAccess.Write(buffer);
return this;
}
public IChainableRgbLed StoreColor(byte red, byte green, byte blue)
{
var buffer = new[] {StoreColorCommandAddress, red, green, blue};
_device.DirectAccess.Write(buffer);
return this;
}
public IChainableRgbLed Test(byte numberOfLeds, byte testColor)
{
var buffer = new[] {TestCommandAddress, (byte) _pin, numberOfLeds, testColor};
_device.DirectAccess.Write(buffer);
return this;
}
public IChainableRgbLed SetPattern(byte pattern, byte led)
{
var buffer = new[] {SetPatternCommandAddress, (byte) _pin, pattern, led};
_device.DirectAccess.Write(buffer);
return this;
}
public IChainableRgbLed Mudulo(byte offset, byte divisor)
{
var buffer = new[] {SetModuloCommandAddress, (byte) _pin, offset, divisor};
_device.DirectAccess.Write(buffer);
return this;
}
}
}

View file

@ -0,0 +1,92 @@
using System;
using GrovePi.Common;
namespace GrovePi.Sensors
{
public interface IDHTTemperatureAndHumiditySensor
{
double TemperatureInCelsius { get; }
double TemperatureInFahrenheit { get; }
double Humidity { get; }
void Measure();
}
/// <summary>
/// Specifies the model of sensor.
/// DHT11 - blue one - comes with the GrovePi+ Starter Kit.
/// DHT22 - white one, aka DHT Pro or AM2302.
/// DHT21 - black one, aka AM2301.
/// </summary>
public enum DHTModel
{
/*
*/
Dht11 = 0,
Dht21 = 1,
Dht22 = 2
}
internal class DHTTemperatureAndHumiditySensor : IDHTTemperatureAndHumiditySensor
{
private readonly GrovePi _device;
private readonly DHTModel _model;
private readonly Pin _pin;
private const byte DHTCmd = 40;
private double t = 0;
private double h = 0;
internal DHTTemperatureAndHumiditySensor(GrovePi device, Pin pin, DHTModel model)
{
if (device == null) throw new ArgumentNullException(nameof(device));
_device = device;
_pin = pin;
_model = model;
}
public void Measure()
{
_device.DirectAccess.WritePartial(new byte[4] { DHTCmd, (byte)_pin, (byte)_model, Constants.Unused });
Delay.Milliseconds(600);
var readBuffer = new byte[9];
_device.DirectAccess.ReadPartial(readBuffer);
float t0 = BitConverter.ToSingle(readBuffer, 1);
float h0 = BitConverter.ToSingle(readBuffer, 5);
t = (double)t0;
h = (double)h0;
}
private double CtoF(double c)
{
return c * 9 / 5 + 32;
}
public double TemperatureInCelsius
{
get
{
return t;
}
}
public double TemperatureInFahrenheit
{
get
{
return CtoF(t);
}
}
public double Humidity
{
get
{
return h;
}
}
}
}

View file

@ -0,0 +1,88 @@
using System;
namespace GrovePi.Sensors
{
public interface IFourDigitDisplay
{
IFourDigitDisplay Initialise();
IFourDigitDisplay SetBrightness(byte brightness);
IFourDigitDisplay SetIndividualSegment(byte segment, byte value);
IFourDigitDisplay SetLedsOfSegment(byte segment, byte leds);
IFourDigitDisplay SetScore(byte left, byte right);
IFourDigitDisplay AllOn();
IFourDigitDisplay AllOff();
}
internal class FourDigitDisplay : IFourDigitDisplay
{
private const byte InitialiseCommandAddress = 70;
private const byte BrightnessCommandAddress = 71;
private const byte ValueCommandAddress = 72;
private const byte ValueZerosCommandAddress = 73;
private const byte IndividualDigitCommandAddress = 74;
private const byte IndividualLedsCommandAddress = 75;
private const byte ScoreCommandAddress = 76;
private const byte AnalogReadCommandAddress = 77;
private const byte AllOnCommandAddress = 78;
private const byte AllOffCommandAddress = 79;
private readonly GrovePi _device;
private readonly Pin _pin;
internal FourDigitDisplay(GrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
_device = device;
_pin = pin;
}
public IFourDigitDisplay Initialise()
{
var buffer = new[] {InitialiseCommandAddress, (byte) _pin, Constants.Unused, Constants.Unused};
_device.DirectAccess.Write(buffer);
return this;
}
public IFourDigitDisplay SetBrightness(byte brightness)
{
brightness = Math.Min(brightness, (byte) 7);
var buffer = new[] { BrightnessCommandAddress, (byte) _pin, brightness, Constants.Unused};
_device.DirectAccess.Write(buffer);
return this;
}
public IFourDigitDisplay SetIndividualSegment(byte segment, byte value)
{
var buffer = new[] {IndividualDigitCommandAddress, (byte) _pin, segment, value};
_device.DirectAccess.Write(buffer);
return this;
}
public IFourDigitDisplay SetLedsOfSegment(byte segment, byte leds)
{
var buffer = new[] {IndividualLedsCommandAddress, (byte) _pin, segment, leds};
_device.DirectAccess.Write(buffer);
return this;
}
public IFourDigitDisplay SetScore(byte left, byte right)
{
var buffer = new[] {ScoreCommandAddress, (byte) _pin, left, right};
_device.DirectAccess.Write(buffer);
return this;
}
public IFourDigitDisplay AllOn()
{
var buffer = new[] {AllOnCommandAddress, (byte) _pin, Constants.Unused, Constants.Unused};
_device.DirectAccess.Write(buffer);
return this;
}
public IFourDigitDisplay AllOff()
{
var buffer = new[] {AllOffCommandAddress, (byte) _pin, Constants.Unused, Constants.Unused};
_device.DirectAccess.Write(buffer);
return this;
}
}
}

View file

@ -0,0 +1,22 @@
using System;
namespace GrovePi.Sensors
{
public interface IGasSensorMQ2
{
int SensorValue();
}
internal class GasSensorMQ2 : Sensor<IGasSensorMQ2>, IGasSensorMQ2
{
public GasSensorMQ2(GrovePi device, Pin pin) : base(device,pin,PinMode.Input)
{
}
public int SensorValue()
{
return Device.AnalogRead(Pin);
}
}
}

View file

@ -0,0 +1,16 @@
namespace GrovePi.Sensors
{
public interface ILed
{
SensorStatus CurrentState { get; }
ILed ChangeState(SensorStatus newState);
void AnalogWrite(byte value);
}
internal class Led : Sensor<ILed>, ILed
{
internal Led(IGrovePi device, Pin pin) : base(device, pin, PinMode.Output)
{
}
}
}

View file

@ -0,0 +1,76 @@
using System;
namespace GrovePi.Sensors
{
public interface ILedBar
{
ILedBar Initialize(Orientation orientation);
ILedBar SetOrientation(Orientation orientation);
ILedBar SetLevel(byte level);
ILedBar SetLed(byte level, byte led, SensorStatus state);
ILedBar ToggleLed(byte led);
}
internal class LedBar : ILedBar
{
private const byte InitialiseCommandAddress = 50;
private const byte OrientationCommandAddress = 51;
private const byte LevelCommandAddress = 52;
private const byte SetOneCommandAddress = 53;
private const byte ToggleOneCommandAddress = 54;
//private const byte SetCommandAddress = 55;
//private const byte GetCommandAddress = 56;
private readonly GrovePi _device;
private readonly Pin _pin;
internal LedBar(GrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
_device = device;
_pin = pin;
}
public ILedBar Initialize(Orientation orientation)
{
var buffer = new[] {InitialiseCommandAddress, (byte) _pin, (byte) orientation, Constants.Unused};
_device.DirectAccess.WritePartial(buffer);
return this;
}
public ILedBar SetOrientation(Orientation orientation)
{
var buffer = new[] {OrientationCommandAddress, (byte) _pin, (byte) orientation, Constants.Unused};
_device.DirectAccess.WritePartial(buffer);
return this;
}
public ILedBar SetLevel(byte level)
{
level = Math.Min(level, (byte) 10);
var buffer = new[] {LevelCommandAddress, (byte) _pin, level, Constants.Unused};
_device.DirectAccess.WritePartial(buffer);
return this;
}
public ILedBar SetLed(byte level, byte led, SensorStatus state)
{
var buffer = new[] {SetOneCommandAddress, (byte) _pin, led, (byte) state};
_device.DirectAccess.WritePartial(buffer);
return this;
}
public ILedBar ToggleLed(byte led)
{
var buffer = new[] {ToggleOneCommandAddress, (byte) _pin, led, Constants.Unused};
_device.DirectAccess.WritePartial(buffer);
return this;
}
}
public enum Orientation
{
RedToGreen = 0,
GreenToRed = 1
}
}

View file

@ -0,0 +1,35 @@
using System;
namespace GrovePi.Sensors
{
public interface ILightSensor
{
int SensorValue();
double Resistance();
}
internal class LightSensor : ILightSensor
{
private readonly GrovePi _device;
private readonly Pin _pin;
internal LightSensor(GrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
device.PinMode(_pin, PinMode.Input);
_device = device;
_pin = pin;
}
public int SensorValue()
{
return _device.AnalogRead(_pin);
}
public double Resistance()
{
var sensorValue = SensorValue();
return (double) (1023 - sensorValue)*10/sensorValue;
}
}
}

View file

@ -0,0 +1,28 @@
namespace GrovePi.Sensors
{
public interface IPIRMotionSensor
{
bool IsPeopleDetected();
}
internal class PIRMotionSensor:Sensor<IPIRMotionSensor>, IPIRMotionSensor
{
public PIRMotionSensor(GrovePi device, Pin pin):base(device, pin, PinMode.Input)
{
}
public bool IsPeopleDetected()
{
int sensorValue = Device.DigitalRead(Pin);
if (sensorValue == 0)
{
return false;
}
else
{
return true;
}
}
}
}

View file

@ -0,0 +1,31 @@
using System;
namespace GrovePi.Sensors
{
public interface IRealTimeClock
{
byte[] Read();
}
internal class RealTimeClock : IRealTimeClock
{
private const byte CommandAddress = 30;
private readonly GrovePi _device;
private readonly Pin _pin;
internal RealTimeClock(GrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
_device = device;
_pin = pin;
}
public byte[] Read()
{
var buffer = new[] {CommandAddress, (byte) _pin, Constants.Unused, Constants.Unused};
_device.DirectAccess.Write(buffer);
_device.DirectAccess.Read(buffer);
return buffer;
}
}
}

View file

@ -0,0 +1,14 @@
namespace GrovePi.Sensors
{
public interface IRelay
{
SensorStatus CurrentState { get; }
IRelay ChangeState(SensorStatus newState);
}
internal class Relay : Sensor<IRelay>, IRelay
{
public Relay(IGrovePi device, Pin pin) : base(device, pin, PinMode.Output)
{
}
}
}

View file

@ -0,0 +1,46 @@
using System;
namespace GrovePi.Sensors
{
public interface IRotaryAngleSensor
{
int SensorValue();
double Voltage();
double Degrees();
}
public class RotaryAngleSensor : IRotaryAngleSensor
{
private const int FullAngle = 300;
private readonly GrovePi _device;
private readonly Pin _pin;
internal RotaryAngleSensor(GrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
device.PinMode(_pin, PinMode.Input);
_device = device;
_pin = pin;
}
public int SensorValue()
{
return _device.AnalogRead(_pin);
}
public double Voltage()
{
return Math.Round(((float) SensorValue()*Constants.AdcVoltage/1023), 2);
}
public double Degrees()
{
return Math.Round((Voltage()*FullAngle)/Constants.GroveVcc, 2);
}
public int Brightness()
{
return (int) (Degrees()/FullAngle*255);
}
}
}

View file

@ -0,0 +1,38 @@
using System;
namespace GrovePi.Sensors
{
public abstract class Sensor<TSensorType> where TSensorType : class
{
protected readonly IGrovePi Device;
protected readonly Pin Pin;
internal Sensor(IGrovePi device, Pin pin, PinMode pinMode)
{
if (device == null) throw new ArgumentNullException(nameof(device));
Device = device;
Pin = pin;
device.PinMode(Pin, pinMode);
}
internal Sensor(IGrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
Device = device;
Pin = pin;
}
public SensorStatus CurrentState => (SensorStatus) Device.DigitalRead(Pin);
public TSensorType ChangeState(SensorStatus newState)
{
Device.DigitalWrite(Pin, (byte) newState);
return this as TSensorType;
}
public void AnalogWrite(byte value)
{
Device.AnalogWrite(Pin,value);
}
}
}

View file

@ -0,0 +1,8 @@
namespace GrovePi.Sensors
{
public enum SensorStatus
{
Off = 0,
On = 1
}
}

View file

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GrovePi.Sensors
{
public interface ISoundSensor
{
int SensorValue();
}
internal class SoundSensor : Sensor<ISoundSensor>, ISoundSensor
{
public SoundSensor(IGrovePi device, Pin pin) : base(device, pin, PinMode.Input)
{
}
public int SensorValue()
{
return Device.AnalogRead(Pin);
}
}
}

View file

@ -0,0 +1,46 @@
using System;
namespace GrovePi.Sensors
{
public interface ITemperatureAndHumiditySensor
{
double TemperatureInCelsius();
}
/// <summary>
/// Specifies the model of sensor.
/// DHT11 - blue one - comes with the GrovePi+ Starter Kit.
/// DHT22 - white one, aka DHT Pro or AM2302.
/// DHT21 - black one, aka AM2301.
/// </summary>
public enum Model
{
/*
*/
Dht11 = 3975,
Dht21 = 4250,
Dht22 = 4250
}
internal class TemperatureAndHumiditySensor : ITemperatureAndHumiditySensor
{
private readonly IGrovePi _device;
private readonly Model _model;
private readonly Pin _pin;
internal TemperatureAndHumiditySensor(IGrovePi device, Pin pin, Model model)
{
if (device == null) throw new ArgumentNullException(nameof(device));
_device = device;
_pin = pin;
_model = model;
}
public double TemperatureInCelsius()
{
var result = (double) _device.AnalogRead(_pin);
var resistance = (1023 - result)*10000/result;
return 1/(Math.Log(resistance/10000)/(int) _model + 1/298.15) - 273.15;
}
}
}

View file

@ -0,0 +1,33 @@
using System;
namespace GrovePi.Sensors
{
public interface ITemperatureSensor
{
double TemperatureInCelsius();
}
/// <summary>
/// Temperature Sensor V1.1 & 1.2
/// ref: <http://wiki.seeed.cc/Grove-Temperature_Sensor_V1.2/>
/// </summary>
internal class TemperatureSensor : ITemperatureSensor
{
private readonly IGrovePi _device;
private readonly Pin _pin;
internal TemperatureSensor(IGrovePi device, Pin pin)
{
if (device == null) throw new ArgumentNullException(nameof(device));
_device = device;
_pin = pin;
}
public double TemperatureInCelsius()
{
var result = (double)_device.AnalogRead(_pin);
var resistance = (1023 - result) * 10000 / result;
return 1 / (Math.Log(resistance / 10000) / 4275 + 1 / 298.15) - 273.15;
}
}
}

View file

@ -0,0 +1,40 @@
using GrovePi.Common;
namespace GrovePi.Sensors
{
public interface IUltrasonicRangerSensor
{
int MeasureInCentimeters();
}
internal class UltrasonicRangerSensor : IUltrasonicRangerSensor
{
private const byte CommandAddress = 7;
private readonly GrovePi _device;
private readonly Pin _pin;
internal UltrasonicRangerSensor(GrovePi device, Pin pin)
{
_device = device;
_pin = pin;
}
public int MeasureInCentimeters()
{
var buffer = new byte[4] {CommandAddress, (byte) _pin, Constants.Unused, Constants.Unused};
var result = _device.DirectAccess.WritePartial(buffer);
if (result.Status != Windows.Devices.I2c.I2cTransferStatus.FullTransfer)
{
return -1;
}
Delay.Milliseconds(50);
buffer = new byte[3];
result = _device.DirectAccess.ReadPartial(buffer);
if (result.Status != Windows.Devices.I2c.I2cTransferStatus.FullTransfer)
{
return -1;
}
return buffer[1]*256 + buffer[2];
}
}
}

View file

@ -0,0 +1,14 @@
namespace GrovePi.Sensors
{
public interface IWaterAtomizer
{
SensorStatus CurrentState { get; }
IWaterAtomizer ChangeState(SensorStatus newState);
}
internal class WaterAtomizer : Sensor<IWaterAtomizer>, IWaterAtomizer
{
public WaterAtomizer(IGrovePi device, Pin pin) : base(device, pin, PinMode.Output)
{ }
}
}

View file

@ -0,0 +1,12 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.3.3"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {}
}
}

File diff suppressed because it is too large Load diff