Skip to content

Commit

Permalink
Simplify MCP3008 (#663)
Browse files Browse the repository at this point in the history
* Make Mcp3008's InputConfiguration internal

* Simplify Mcp3008 implementation

* docs

* remove refs to InputConfiguration from README
  • Loading branch information
krwq authored Aug 14, 2019
1 parent ef2a4e5 commit bc7d3dd
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 33 deletions.
64 changes: 34 additions & 30 deletions src/devices/Mcp3008/Mcp3008.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,62 +8,66 @@

namespace Iot.Device.Mcp3008
{
/// <summary>
/// MCP3008 Analog to Digital Converter (ADC)
/// </summary>
public class Mcp3008 : IDisposable
{
private SpiDevice _spiDevice;

public enum InputConfiguration
{
Differential = 0,
SingleEnded = 1
}

/// <summary>
/// Constructs Mcp3008 instance
/// </summary>
/// <param name="spiDevice">Device used for SPI communication</param>
public Mcp3008(SpiDevice spiDevice)
{
_spiDevice = spiDevice;
}

/// <summary>
/// Disposes Mcp3008 instances
/// </summary>
public void Dispose()
{
_spiDevice?.Dispose();
_spiDevice = null;
}

public int Read(int channel, InputConfiguration inputConfiguration = InputConfiguration.SingleEnded)
/// <summary>
/// Reads 10-bit (0..1023) value from the device
/// </summary>
/// <param name="channel">Channel which value should be read from (valid values: 0-7)</param>
/// <returns>10-bit value corresponding to relative voltage level on specified device channel</returns>
public int Read(int channel)
{
if (channel < 0 || channel > 7)
{
throw new ArgumentException("ADC channel must be within 0-7 range.");
}

return ReadSpi(channel, inputConfiguration);
}
Span<byte> writeBuffer = stackalloc byte[3];
Span<byte> readBuffer = stackalloc byte[3];

private static byte GetConfigurationBits(int channel, InputConfiguration inputConfiguration)
{
int configurationBits = (0b0001_1000 | channel) << 3;
// first we send 5 bits, rest is ignored
// start bit = 1
// conversion bit = 1 (single ended)
// next 3 bits are channel
writeBuffer[0] = (byte)((0b1_1000 | channel) << 3);
_spiDevice.TransferFullDuplex(writeBuffer, readBuffer);

if (inputConfiguration == InputConfiguration.Differential)
// we ignore first 7 bits then read following 10
// 7 bits:
// - 5 are used for writing start bit, conversion bit and channel
// - next bit is ignored so device has time to sample
// - following bit should be 0
if ((readBuffer[0] & 0b10) != 0)
{
configurationBits &= 0b1011_1111; // Clear mode bit.
throw new InvalidOperationException("Invalid data was read from the sensor");
}

return (byte)configurationBits;
}

// Ported: https://github.com/adafruit/Adafruit_Python_MCP3008/blob/master/Adafruit_MCP3008/MCP3008.py
private int ReadSpi(int channel, InputConfiguration inputConfiguration)
{
byte configurationBits = GetConfigurationBits(channel, inputConfiguration);
byte[] writeBuffer = new byte[] { configurationBits, 0, 0 };
byte[] readBuffer = new byte[3];

_spiDevice.TransferFullDuplex(writeBuffer, readBuffer);

int result = (readBuffer[0] & 0b0000_0001) << 9;
result |= (readBuffer[1] & 0b1111_1111) << 1;
result |= (readBuffer[2] & 0b1000_0000) >> 7;
result = result & 0b0011_1111_1111;
int result = (readBuffer[0] & 1) << 9;
result |= readBuffer[1] << 1;
result |= readBuffer[2] >> 7;
return result;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/devices/Mcp3008/samples/Mcp3008.Sample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static void Main(string[] args)
{
while (true)
{
double value = mcp.Read(0, Mcp3008.Mcp3008.InputConfiguration.SingleEnded);
double value = mcp.Read(0);
value = value / 10.24;
value = Math.Round(value);
Console.WriteLine($"{value}%");
Expand Down
4 changes: 2 additions & 2 deletions src/devices/Mcp3008/samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ using (Mcp3008.Mcp3008 mcp = new Mcp3008.Mcp3008(spi))
{
while (true)
{
double value = mcp.Read(0, Mcp3008.Mcp3008.InputConfiguration.SingleEnded);
double value = mcp.Read(0);
value = value / 10.24;
value = Math.Round(value);
Console.WriteLine($"{value}%");
Expand Down Expand Up @@ -56,7 +56,7 @@ using (Mcp3008.Mcp3008 mcp = new Mcp3008.Mcp3008(spi))
{
while (true)
{
double value = mcp.Read(0, Mcp3008.Mcp3008.InputConfiguration.SingleEnded);
double value = mcp.Read(0);
value = value / 10.24;
value = Math.Round(value);
Console.WriteLine($"{value}%");
Expand Down

0 comments on commit bc7d3dd

Please sign in to comment.