first commit
This commit is contained in:
commit
a5a0434432
1126 changed files with 439481 additions and 0 deletions
18
Software/CSharp/GrovePi/Common/Delay.cs
Normal file
18
Software/CSharp/GrovePi/Common/Delay.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Software/CSharp/GrovePi/Constants.cs
Normal file
11
Software/CSharp/GrovePi/Constants.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
430
Software/CSharp/GrovePi/DeviceFactory.cs
Normal file
430
Software/CSharp/GrovePi/DeviceFactory.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
122
Software/CSharp/GrovePi/GrovePi.cs
Normal file
122
Software/CSharp/GrovePi/GrovePi.cs
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
107
Software/CSharp/GrovePi/GrovePi.csproj
Normal file
107
Software/CSharp/GrovePi/GrovePi.csproj
Normal 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)' < '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>
|
||||
20
Software/CSharp/GrovePi/GrovePi.nuspec
Normal file
20
Software/CSharp/GrovePi/GrovePi.nuspec
Normal 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>
|
||||
61
Software/CSharp/GrovePi/I2CDevices/MiniMotorDriver.cs
Normal file
61
Software/CSharp/GrovePi/I2CDevices/MiniMotorDriver.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
440
Software/CSharp/GrovePi/I2CDevices/OLEDDisplay128X64.cs
Normal file
440
Software/CSharp/GrovePi/I2CDevices/OLEDDisplay128X64.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
450
Software/CSharp/GrovePi/I2CDevices/OLEDDisplay9696.cs
Normal file
450
Software/CSharp/GrovePi/I2CDevices/OLEDDisplay9696.cs
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
78
Software/CSharp/GrovePi/I2CDevices/RgbLcdDisplay.cs
Normal file
78
Software/CSharp/GrovePi/I2CDevices/RgbLcdDisplay.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
16
Software/CSharp/GrovePi/Pin.cs
Normal file
16
Software/CSharp/GrovePi/Pin.cs
Normal 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
|
||||
}
|
||||
}
|
||||
8
Software/CSharp/GrovePi/PinMode.cs
Normal file
8
Software/CSharp/GrovePi/PinMode.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
namespace GrovePi
|
||||
{
|
||||
public enum PinMode
|
||||
{
|
||||
Input = 0,
|
||||
Output = 1
|
||||
}
|
||||
}
|
||||
29
Software/CSharp/GrovePi/Properties/AssemblyInfo.cs
Normal file
29
Software/CSharp/GrovePi/Properties/AssemblyInfo.cs
Normal 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)]
|
||||
33
Software/CSharp/GrovePi/Properties/client.winU.rd.xml
Normal file
33
Software/CSharp/GrovePi/Properties/client.winU.rd.xml
Normal 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>
|
||||
41
Software/CSharp/GrovePi/Sensors/AccelerometerSensor.cs
Normal file
41
Software/CSharp/GrovePi/Sensors/AccelerometerSensor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Software/CSharp/GrovePi/Sensors/AirQualitySensor.cs
Normal file
27
Software/CSharp/GrovePi/Sensors/AirQualitySensor.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Software/CSharp/GrovePi/Sensors/ButtonSensor.cs
Normal file
14
Software/CSharp/GrovePi/Sensors/ButtonSensor.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Software/CSharp/GrovePi/Sensors/Buzzer.cs
Normal file
15
Software/CSharp/GrovePi/Sensors/Buzzer.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
75
Software/CSharp/GrovePi/Sensors/ChainableRgbLed.cs
Normal file
75
Software/CSharp/GrovePi/Sensors/ChainableRgbLed.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Software/CSharp/GrovePi/Sensors/FourDigitDisplay.cs
Normal file
88
Software/CSharp/GrovePi/Sensors/FourDigitDisplay.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Software/CSharp/GrovePi/Sensors/GasSensorMQ2.cs
Normal file
22
Software/CSharp/GrovePi/Sensors/GasSensorMQ2.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Software/CSharp/GrovePi/Sensors/Led.cs
Normal file
16
Software/CSharp/GrovePi/Sensors/Led.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
76
Software/CSharp/GrovePi/Sensors/LedBar.cs
Normal file
76
Software/CSharp/GrovePi/Sensors/LedBar.cs
Normal 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
|
||||
}
|
||||
}
|
||||
35
Software/CSharp/GrovePi/Sensors/LightSensor.cs
Normal file
35
Software/CSharp/GrovePi/Sensors/LightSensor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Software/CSharp/GrovePi/Sensors/PIRMotionSensor.cs
Normal file
28
Software/CSharp/GrovePi/Sensors/PIRMotionSensor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Software/CSharp/GrovePi/Sensors/RealTimeClock.cs
Normal file
31
Software/CSharp/GrovePi/Sensors/RealTimeClock.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Software/CSharp/GrovePi/Sensors/Relay.cs
Normal file
14
Software/CSharp/GrovePi/Sensors/Relay.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
46
Software/CSharp/GrovePi/Sensors/RotaryAngleSensor.cs
Normal file
46
Software/CSharp/GrovePi/Sensors/RotaryAngleSensor.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Software/CSharp/GrovePi/Sensors/Sensor.cs
Normal file
38
Software/CSharp/GrovePi/Sensors/Sensor.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Software/CSharp/GrovePi/Sensors/SensorStatus.cs
Normal file
8
Software/CSharp/GrovePi/Sensors/SensorStatus.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
namespace GrovePi.Sensors
|
||||
{
|
||||
public enum SensorStatus
|
||||
{
|
||||
Off = 0,
|
||||
On = 1
|
||||
}
|
||||
}
|
||||
26
Software/CSharp/GrovePi/Sensors/SoundSensor.cs
Normal file
26
Software/CSharp/GrovePi/Sensors/SoundSensor.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Software/CSharp/GrovePi/Sensors/TemperatureSensor.cs
Normal file
33
Software/CSharp/GrovePi/Sensors/TemperatureSensor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Software/CSharp/GrovePi/Sensors/UltrasonicRangerSensor.cs
Normal file
40
Software/CSharp/GrovePi/Sensors/UltrasonicRangerSensor.cs
Normal 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Software/CSharp/GrovePi/Sensors/WaterAtomizer.cs
Normal file
14
Software/CSharp/GrovePi/Sensors/WaterAtomizer.cs
Normal 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)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
12
Software/CSharp/GrovePi/project.json
Normal file
12
Software/CSharp/GrovePi/project.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.UniversalWindowsPlatform": "5.3.3"
|
||||
},
|
||||
"frameworks": {
|
||||
"uap10.0": {}
|
||||
},
|
||||
"runtimes": {
|
||||
"win10-arm": {},
|
||||
"win10-arm-aot": {}
|
||||
}
|
||||
}
|
||||
14985
Software/CSharp/GrovePi/project.lock.json
Normal file
14985
Software/CSharp/GrovePi/project.lock.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue