diff --git a/src/devices/Device-Index.md b/src/devices/Device-Index.md index 0219676212..3210c03601 100755 --- a/src/devices/Device-Index.md +++ b/src/devices/Device-Index.md @@ -113,6 +113,7 @@ * [STUSB4500 - Autonomous USB-C PD controller for Power Sinks / UFP](StUsb4500/README.md) * [System.Device.Model - attributes for device bindings](System.Device.Model/README.md) * [TCS3472x Sensors](Tcs3472x/README.md) +* [TCA954X Multiplexer](Tca954x/README.md) * [TLC1543 - 10-bit ADC with 11 input channels](Tlc1543/README.md) * [TM1637 - Segment Display](Tm1637/README.md) * [TSL256x - Illuminance sensor](Tsl256x/README.md) diff --git a/src/devices/Pca95x4/README.md b/src/devices/Pca95x4/README.md index 976f3b6283..3d67b2a485 100644 --- a/src/devices/Pca95x4/README.md +++ b/src/devices/Pca95x4/README.md @@ -1,6 +1,6 @@ # Pca95x4 - I2C GPIO Expander -The PCA95x4 provides 8 bits of General Purpose parallel Input/Output (GPIO) expansion for I2C-bus applications. +The PCA95x4 provides 8 bits of General Purpose parallel Input/Output (GPIO) expansion for I2C-bus applications. Not to be confused with the PCA954x, which is a group of I2C bus multiplexers. ## Documentation diff --git a/src/devices/README.md b/src/devices/README.md index ad9ad556ff..a4097de8e3 100755 --- a/src/devices/README.md +++ b/src/devices/README.md @@ -211,6 +211,7 @@ Our vision: the majority of .NET bindings are written completely in .NET languag * [Mcp23xxx - I/O Expander device family](Mcp23xxx/README.md) * [NXP/TI PCx857x](Pcx857x/README.md) * [Pca95x4 - I2C GPIO Expander](Pca95x4/README.md) +* [TCA9548A - TCA9548A Low-Voltage 8-Channel I2C Switch with Reset](Tca954x/README.md) ### CAN BUS libraries/modules diff --git a/src/devices/Tca954x/MultiplexerChannel.cs b/src/devices/Tca954x/MultiplexerChannel.cs new file mode 100644 index 0000000000..adf2c2c36e --- /dev/null +++ b/src/devices/Tca954x/MultiplexerChannel.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Iot.Device.Tca954x +{ + /// + /// Available channels + /// + [Flags] + public enum MultiplexerChannel : byte + { + /// + /// No channel is selected + /// + None = 0, + + /// + /// Channel 0 Byte (2^0 = 1) + /// + Channel0 = 0x01, + + /// + /// Channel 1 Byte (2^1 = 2) + /// + Channel1 = 0x02, + + /// + /// Channel 2 Byte (2^2 = 4) + /// + Channel2 = 0x04, + + /// + /// Channel 3 Byte (2^3 = 8) + /// + Channel3 = 0x08, + + /// + /// Channel 4 Byte (2^4 = 16) + /// + Channel4 = 0x10, + + /// + /// Channel 5 Byte (2^5 = 32) + /// + Channel5 = 0x20, + + /// + /// Channel 6 Byte (2^6 = 64) + /// + Channel6 = 0x40, + + /// + /// Channel 7 Byte (2^7 = 128) + /// + Channel7 = 0x80 + } + +} diff --git a/src/devices/Tca954x/PossibleMuxAddress.png b/src/devices/Tca954x/PossibleMuxAddress.png new file mode 100644 index 0000000000..b1c9027d46 Binary files /dev/null and b/src/devices/Tca954x/PossibleMuxAddress.png differ diff --git a/src/devices/Tca954x/README.md b/src/devices/Tca954x/README.md new file mode 100644 index 0000000000..2c3201d4fd --- /dev/null +++ b/src/devices/Tca954x/README.md @@ -0,0 +1,115 @@ +# TCA954X - TCA954X Low-Voltage Multi-Channel I2C Switch with Reset + +The TCA954X/PCA954X group of devices is a set of I2C switches. Several types are available, with 2, 4 or 8 channels, and different voltage specifications. The first letter is sometimes also "P". Not to be confused with PCA95x4, which is a set of GPIO expanders. + +The TCA9548A device has eight bidirectional translating switches that can be controlled through the I2C bus. The SCL/SDA upstream pair fans out to eight downstream pairs, or channels. + +All operations for basic usage has been developed. If needed, RESET operation can also be implemented. + +## Documentation + +![TCA9548A](./TCA9548A.jpg) + +TCA9548A [datasheet](https://www.ti.com/lit/ds/symlink/tca9548a.pdf) + +You will find this device as ["Adafruit TCA9548A 1-to-8 I2C Multiplexer Breakout"](https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-breakout) + +A list of [different variants](https://www.ti.com/interface/i2c/switches-and-multiplexers/products.html?keyMatch=TCA9548) is available on the Texas Instruments Website. + +## Usage + +Create a ```Tca9548A``` class and pass the I2C device. The default I2C address is provided in the class. + +```csharp + Console.WriteLine("Hello TCA9548A!"); + var bus = I2cBus.Create(1); + Tca9548A tca9548a = new Tca9548A(bus.CreateDevice(Tca9548A.DefaultI2cAddress), bus); + + // Get all connected I2C interfaces + foreach (var channelBuses in tca9548a) + { + var deviceAddress = ((Tca9548AChannelBus)channelBuses).PerformBusScan(); + foreach (var device in deviceAddress) + { + if (device == Bno055Sensor.DefaultI2cAddress || device == Bno055Sensor.SecondI2cAddress) + { + Bno055Sensor bno055Sensor = new Bno055Sensor(channelBuses.CreateDevice(device)); + Console.WriteLine($"Id: {bno055Sensor.Info.ChipId}, AccId: {bno055Sensor.Info.AcceleratorId}, GyroId: {bno055Sensor.Info.GyroscopeId}, MagId: {bno055Sensor.Info.MagnetometerId}"); + Console.WriteLine($"Firmware version: {bno055Sensor.Info.FirmwareVersion}, Bootloader: {bno055Sensor.Info.BootloaderVersion}"); + Console.WriteLine($"Temperature source: {bno055Sensor.TemperatureSource}, Operation mode: {bno055Sensor.OperationMode}, Units: {bno055Sensor.Units}"); + Console.WriteLine($"Powermode: {bno055Sensor.PowerMode}"); + var calibrationStatus = bno055Sensor.GetCalibrationStatus(); + Console.WriteLine($"Calibration Status : {calibrationStatus}"); + var magneto = bno055Sensor.Magnetometer; + Console.WriteLine($"Magnetometer X: {magneto.X} Y: {magneto.Y} Z: {magneto.Z}"); + var gyro = bno055Sensor.Gyroscope; + Console.WriteLine($"Gyroscope X: {gyro.X} Y: {gyro.Y} Z: {gyro.Z}"); + var accele = bno055Sensor.Accelerometer; + Console.WriteLine($"Acceleration X: {accele.X} Y: {accele.Y} Z: {accele.Z}"); + var orien = bno055Sensor.Orientation; + Console.WriteLine($"Orientation Heading: {orien.X} Roll: {orien.Y} Pitch: {orien.Z}"); + var line = bno055Sensor.LinearAcceleration; + Console.WriteLine($"Linear acceleration X: {line.X} Y: {line.Y} Z: {line.Z}"); + var gravity = bno055Sensor.Gravity; + Console.WriteLine($"Gravity X: {gravity.X} Y: {gravity.Y} Z: {gravity.Z}"); + var qua = bno055Sensor.Quaternion; + Console.WriteLine($"Quaternion X: {qua.X} Y: {qua.Y} Z: {qua.Z} W: {qua.W}"); + var temp = bno055Sensor.Temperature.DegreesCelsius; + Console.WriteLine($"Temperature: {temp} °C"); + } + else if (device == Bmp180.DefaultI2cAddress) + { + using Bmp180 i2cBmp280 = new(channelBuses.CreateDevice(device)); + // set samplings + i2cBmp280.SetSampling(Sampling.Standard); + // read values + Temperature tempValue = i2cBmp280.ReadTemperature(); + Console.WriteLine($"Temperature: {tempValue.DegreesCelsius:0.#}\u00B0C"); + Pressure preValue = i2cBmp280.ReadPressure(); + Console.WriteLine($"Pressure: {preValue.Hectopascals:0.##}hPa"); + + // Note that if you already have the pressure value and the temperature, you could also calculate altitude by + // calling WeatherHelper.CalculateAltitude(preValue, Pressure.MeanSeaLevel, tempValue) which would be more performant. + Length altValue = i2cBmp280.ReadAltitude(WeatherHelper.MeanSeaLevel); + + Console.WriteLine($"Altitude: {altValue:0.##}m"); + Thread.Sleep(1000); + + // set higher sampling + i2cBmp280.SetSampling(Sampling.UltraLowPower); + + // read values + tempValue = i2cBmp280.ReadTemperature(); + Console.WriteLine($"Temperature: {tempValue.DegreesCelsius:0.#}\u00B0C"); + preValue = i2cBmp280.ReadPressure(); + Console.WriteLine($"Pressure: {preValue.Hectopascals:0.##}hPa"); + + // Note that if you already have the pressure value and the temperature, you could also calculate altitude by + // calling WeatherHelper.CalculateAltitude(preValue, Pressure.MeanSeaLevel, tempValue) which would be more performant. + altValue = i2cBmp280.ReadAltitude(WeatherHelper.MeanSeaLevel); + Console.WriteLine($"Altitude: {altValue:0.##}m"); + } + + Thread.Sleep(1000); + } + + } +``` + +### Sample wiring + +**Important** to understand: +If you are getting lower data rate from sensor connected via Multiplexer on Raspberry Pi, you need to adjust the bus speed. + +This example uses the I2C bus 1 with GPIO 2 and 3 on raspberry pi and gathers data from to BNO055 sensors and 4 BMP180 sensors over TCA9548A Mux + +![Wiring sample](TCA9548A_Connections.png) + +## Possible TCA9548A Addresses + +![Possible Addresses](PossibleMuxAddress.png) + +## TCA9546A - Low Voltage 4-Channel I2C + +TCA9546A [datasheet](https://www.ti.com/lit/ds/symlink/tca9546a.pdf) +You can use the same class to control the 4-Channel Multiplexer also. diff --git a/src/devices/Tca954x/TCA9548A.jpg b/src/devices/Tca954x/TCA9548A.jpg new file mode 100644 index 0000000000..32759d61c0 Binary files /dev/null and b/src/devices/Tca954x/TCA9548A.jpg differ diff --git a/src/devices/Tca954x/TCA9548A_Connections.png b/src/devices/Tca954x/TCA9548A_Connections.png new file mode 100644 index 0000000000..cdafee02fa Binary files /dev/null and b/src/devices/Tca954x/TCA9548A_Connections.png differ diff --git a/src/devices/Tca954x/TCA9548A_usage.fzz b/src/devices/Tca954x/TCA9548A_usage.fzz new file mode 100644 index 0000000000..fbf73630d4 Binary files /dev/null and b/src/devices/Tca954x/TCA9548A_usage.fzz differ diff --git a/src/devices/Tca954x/Tca9548A.cs b/src/devices/Tca954x/Tca9548A.cs new file mode 100644 index 0000000000..af48149575 --- /dev/null +++ b/src/devices/Tca954x/Tca9548A.cs @@ -0,0 +1,197 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Device.I2c; +using System.Device.Model; +using System.IO; + +namespace Iot.Device.Tca954x +{ + /// + /// Tca9548A - 8-Channel I2C Switch/Multiplexer + /// + [Interface("Tca9548A - 8-Channel I2C Switch/Multiplexer")] + public class Tca9548A : IList, IDisposable + { + private readonly bool _shouldDispose; + private readonly List _channelBuses = new List(); + private MultiplexerChannel? _activeChannels; + + /// + /// The default I2C Address, page 15 of the main documentation + /// https://www.ti.com/lit/ds/symlink/tca9548a.pdf + /// + public const byte DefaultI2cAddress = 0x70; + + /// + /// Array of all possible Multiplexer Channels + /// + private static readonly MultiplexerChannel[] DeviceChannels = new MultiplexerChannel[] + { + MultiplexerChannel.Channel0, MultiplexerChannel.Channel1, MultiplexerChannel.Channel2, MultiplexerChannel.Channel3, MultiplexerChannel.Channel4, + MultiplexerChannel.Channel5, MultiplexerChannel.Channel6, MultiplexerChannel.Channel7 + }; + + private I2cDevice _i2CDevice; + + /// + /// Creates a Multiplexer Instance + /// + /// The I2C Device of the Mux itself + /// The bus the mux is connected to + /// true to dispose the I2C device at dispose + /// Exception thrown if I2C device is null + public Tca9548A(I2cDevice i2cDevice, I2cBus mainBus, bool shouldDispose = true) + { + _i2CDevice = i2cDevice ?? throw new ArgumentNullException(nameof(i2cDevice)); + _shouldDispose = shouldDispose; + _activeChannels = null; // We don't know the state of the multiplexer + foreach (var channel in DeviceChannels) + { + _channelBuses.Add(new Tca9548AChannelBus(this, mainBus, channel)); + } + } + + /// + /// Gets Channel busses of the multiplexer + /// + /// channel number + /// + public I2cBus this[int index] => _channelBuses[index]; + + /// + /// Select a group of multiplexer channels. + /// + /// The channels to select + /// + /// In most cases, a single channel will be selected at a time, but it is possible to write to several channels at once. Reading + /// from multiple channels at once will result in undefined behavior. + /// + public void SelectChannel(MultiplexerChannel multiplexChannels) + { + if (TryGetSelectedChannel(out var channel) && channel != multiplexChannels) + { + _i2CDevice.WriteByte(Convert.ToByte(multiplexChannels)); + _activeChannels = multiplexChannels; + } + } + + /// + /// Try getting the selected channel on Multiplexer + /// + /// selected Multiplexer Channel + /// true if able to retrieve selected channel + public bool TryGetSelectedChannel(out MultiplexerChannel selectedChannel) + { + try + { + if (_activeChannels.HasValue) + { + selectedChannel = _activeChannels.Value; + return true; + } + + var channel = _i2CDevice.ReadByte(); + if (Enum.IsDefined(typeof(MultiplexerChannel), channel)) + { + selectedChannel = (MultiplexerChannel)channel; + return true; + } + else + { + selectedChannel = MultiplexerChannel.Channel0; + return false; + } + } + catch (Exception) + { + selectedChannel = MultiplexerChannel.Channel0; + return false; + } + } + + /// + public void Dispose() + { + if (_shouldDispose) + { + _i2CDevice?.Dispose(); + } + + _i2CDevice = null!; + } + + /// + public int Count => _channelBuses.Count; + + /// + public bool IsReadOnly => true; + + I2cBus IList.this[int index] { get => _channelBuses[index]; set => _channelBuses[index] = (Tca9548AChannelBus)value; } + + /// + public int IndexOf(I2cBus item) + { + return _channelBuses.IndexOf((Tca9548AChannelBus)item); + } + + /// + public void Insert(int index, I2cBus item) + { + _channelBuses.Insert(index, (Tca9548AChannelBus)item); + } + + /// + public void RemoveAt(int index) + { + _channelBuses.RemoveAt(index); + } + + /// + public void Add(I2cBus item) + { + _channelBuses.Add((Tca9548AChannelBus)item); + } + + /// + public void Clear() + { + _channelBuses.Clear(); + } + + /// + public bool Contains(I2cBus item) + { + return _channelBuses.Contains((Tca9548AChannelBus)item); + } + + /// + public void CopyTo(I2cBus[] array, int arrayIndex) + { + _channelBuses.CopyTo((Tca9548AChannelBus[])array, arrayIndex); + + } + + /// + public bool Remove(I2cBus item) + { + return _channelBuses.Remove((Tca9548AChannelBus)item); + } + + /// + public IEnumerator GetEnumerator() + { + return _channelBuses.GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + +} diff --git a/src/devices/Tca954x/Tca9548AChannelBus.cs b/src/devices/Tca954x/Tca9548AChannelBus.cs new file mode 100644 index 0000000000..3c360d28f9 --- /dev/null +++ b/src/devices/Tca954x/Tca9548AChannelBus.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Device.I2c; +using Iot.Device.Board; + +namespace Iot.Device.Tca954x +{ + /// + /// I2C BUs of TCA9548A channel + /// + public class Tca9548AChannelBus : I2cBus + { + private readonly I2cBus _channelBus; + private readonly Tca9548A _tca9548A; + private readonly MultiplexerChannel _tcaChannel; + + /// + /// Creates new I2C bus Instance for multiplexer channel + /// + /// TCA9548A multiplexer + /// Main Bus + /// Selected Channel on Multiplexer + internal Tca9548AChannelBus(Tca9548A tca9548A, I2cBus mainBus, MultiplexerChannel channels) + { + _tca9548A = tca9548A; + _tcaChannel = channels; + _channelBus = mainBus; + } + + private void SelectDeviceChannel() => _tca9548A.SelectChannel(_tcaChannel); + + /// + /// Creates I2C device + /// + /// Device address related with the device to create. + /// I2cDevice instance. + public override I2cDevice CreateDevice(int deviceAddress) + { + SelectDeviceChannel(); + return new Tca9548AI2cDevice(_tca9548A, _tcaChannel, _channelBus.CreateDevice(deviceAddress)); + } + + /// + /// Returns all the connected device on selected channel + /// + /// The list of used addresses + public List PerformBusScan() + { + SelectDeviceChannel(); + return _channelBus.PerformBusScan(); + } + + /// + /// Removes I2C device. + /// + /// Device address to remove.m + public override void RemoveDevice(int deviceAddress) + { + SelectDeviceChannel(); + _channelBus.RemoveDevice(deviceAddress); + } + + } +} diff --git a/src/devices/Tca954x/Tca9548ADevice.cs b/src/devices/Tca954x/Tca9548ADevice.cs new file mode 100644 index 0000000000..48b336a9b5 --- /dev/null +++ b/src/devices/Tca954x/Tca9548ADevice.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Device.I2c; + +namespace Iot.Device.Tca954x +{ + internal class Tca9548AI2cDevice : I2cDevice + { + private readonly I2cDevice _channelDevice; + private readonly Tca9548A _tca9548A; + private readonly MultiplexerChannel _tcaChannel; + + /// + /// The connection settings of a device on an I2C bus. + /// + public override I2cConnectionSettings ConnectionSettings => _channelDevice.ConnectionSettings; + + /// + /// Initializes a new instance of the class on the of TCA mux that will use the specified settings to communicate with the I2C device. + /// + /// Instance on TCA9548A device + /// Channel on which device is + /// I2C device (from the parent bus) + internal Tca9548AI2cDevice(Tca9548A tca9548A, MultiplexerChannel tcaChannel, I2cDevice device) + { + _tca9548A = tca9548A; + _tcaChannel = tcaChannel; + _channelDevice = device; + } + + private void SelectDeviceChannel() => _tca9548A.SelectChannel(_tcaChannel); + + /// + /// Reads data from the I2C device. + /// + /// + /// The buffer to read the data from the I2C device. + /// The length of the buffer determines how much data to read from the I2C device. + /// + public override void Read(Span buffer) + { + SelectDeviceChannel(); + _channelDevice.Read(buffer); + } + + /// + /// Reads a byte from the I2C device. + /// + /// A byte read from the I2C device. + public override byte ReadByte() + { + SelectDeviceChannel(); + return _channelDevice.ReadByte(); + } + + /// + /// Writes data to the I2C device. + /// + /// + /// The buffer that contains the data to be written to the I2C device. + /// The data should not include the I2C device address. + /// + public override void Write(ReadOnlySpan buffer) + { + SelectDeviceChannel(); + _channelDevice.Write(buffer); + } + + /// + /// Writes a byte to the I2C device. + /// + /// The byte to be written to the I2C device. + public override void WriteByte(byte value) + { + SelectDeviceChannel(); + _channelDevice.WriteByte(value); + } + + /// + /// Performs an atomic operation to write data to and then read data from the I2C bus on which the device is connected, + /// and sends a restart condition between the write and read operations. + /// + /// + /// The buffer that contains the data to be written to the I2C device. + /// The data should not include the I2C device address. + /// + /// The buffer to read the data from the I2C device. + /// The length of the buffer determines how much data to read from the I2C device. + /// + public override void WriteRead(ReadOnlySpan writeBuffer, Span readBuffer) + { + SelectDeviceChannel(); + _channelDevice.WriteRead(writeBuffer, readBuffer); + } + + /// + protected override void Dispose(bool disposing) + { + _channelDevice.Dispose(); + base.Dispose(disposing); + } + } +} diff --git a/src/devices/Tca954x/Tca9548a.sln b/src/devices/Tca954x/Tca9548a.sln new file mode 100644 index 0000000000..288dbb942b --- /dev/null +++ b/src/devices/Tca954x/Tca9548a.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32519.111 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tca954x", "Tca954x.csproj", "{28EDCECC-F951-4004-8213-FAF1ACD3DFD2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tca9548a.sample", "samples\Tca9548a.sample.csproj", "{A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|x64.ActiveCfg = Debug|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|x64.Build.0 = Debug|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|x86.ActiveCfg = Debug|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Debug|x86.Build.0 = Debug|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|Any CPU.Build.0 = Release|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|x64.ActiveCfg = Release|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|x64.Build.0 = Release|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|x86.ActiveCfg = Release|Any CPU + {28EDCECC-F951-4004-8213-FAF1ACD3DFD2}.Release|x86.Build.0 = Release|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|x64.ActiveCfg = Debug|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|x64.Build.0 = Debug|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|x86.ActiveCfg = Debug|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Debug|x86.Build.0 = Debug|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|Any CPU.Build.0 = Release|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|x64.ActiveCfg = Release|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|x64.Build.0 = Release|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|x86.ActiveCfg = Release|Any CPU + {A2232C4D-B1C5-4B59-A0D9-BC7CA364ACF2}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7B84C9EE-D5AF-4ABC-ACEE-2F126D8738EA} + EndGlobalSection +EndGlobal diff --git a/src/devices/Tca954x/Tca954x.csproj b/src/devices/Tca954x/Tca954x.csproj new file mode 100644 index 0000000000..fed1b33c01 --- /dev/null +++ b/src/devices/Tca954x/Tca954x.csproj @@ -0,0 +1,12 @@ + + + + $(DefaultBindingTfms) + false + + + + + + + diff --git a/src/devices/Tca954x/category.txt b/src/devices/Tca954x/category.txt new file mode 100644 index 0000000000..120d076e1c --- /dev/null +++ b/src/devices/Tca954x/category.txt @@ -0,0 +1 @@ +Multiplexer \ No newline at end of file diff --git a/src/devices/Tca954x/samples/Program.cs b/src/devices/Tca954x/samples/Program.cs new file mode 100644 index 0000000000..407413b4ec --- /dev/null +++ b/src/devices/Tca954x/samples/Program.cs @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading; +using System.Device.I2c; +using Iot.Device.Tca954x; +using Iot.Device.Bno055; +using Iot.Device.Bmp180; +using UnitsNet; +using Iot.Device.Common; +using Iot.Device.Board; + +namespace Tca9548a.Sample +{ + /// + /// Sample Test Class + /// + public static class Program + { + /// + /// Program Entry Point + /// + public static void Main() + { + Console.WriteLine("Hello TCA9548A!"); + var bus = I2cBus.Create(1); + Tca9548A tca9548a = new Tca9548A(bus.CreateDevice(Tca9548A.DefaultI2cAddress), bus); + + // Get all connected I2C interfaces + foreach (var channelBuses in tca9548a) + { + var deviceAddress = ((Tca9548AChannelBus)channelBuses).PerformBusScan(); + foreach (var device in deviceAddress) + { + if (device == Bno055Sensor.DefaultI2cAddress || device == Bno055Sensor.SecondI2cAddress) + { + Bno055Sensor bno055Sensor = new Bno055Sensor(channelBuses.CreateDevice(device)); + Console.WriteLine($"Id: {bno055Sensor.Info.ChipId}, AccId: {bno055Sensor.Info.AcceleratorId}, GyroId: {bno055Sensor.Info.GyroscopeId}, MagId: {bno055Sensor.Info.MagnetometerId}"); + Console.WriteLine($"Firmware version: {bno055Sensor.Info.FirmwareVersion}, Bootloader: {bno055Sensor.Info.BootloaderVersion}"); + Console.WriteLine($"Temperature source: {bno055Sensor.TemperatureSource}, Operation mode: {bno055Sensor.OperationMode}, Units: {bno055Sensor.Units}"); + Console.WriteLine($"Powermode: {bno055Sensor.PowerMode}"); + var calibrationStatus = bno055Sensor.GetCalibrationStatus(); + Console.WriteLine($"Calibration Status : {calibrationStatus}"); + var magneto = bno055Sensor.Magnetometer; + Console.WriteLine($"Magnetometer X: {magneto.X} Y: {magneto.Y} Z: {magneto.Z}"); + var gyro = bno055Sensor.Gyroscope; + Console.WriteLine($"Gyroscope X: {gyro.X} Y: {gyro.Y} Z: {gyro.Z}"); + var accele = bno055Sensor.Accelerometer; + Console.WriteLine($"Acceleration X: {accele.X} Y: {accele.Y} Z: {accele.Z}"); + var orien = bno055Sensor.Orientation; + Console.WriteLine($"Orientation Heading: {orien.X} Roll: {orien.Y} Pitch: {orien.Z}"); + var line = bno055Sensor.LinearAcceleration; + Console.WriteLine($"Linear acceleration X: {line.X} Y: {line.Y} Z: {line.Z}"); + var gravity = bno055Sensor.Gravity; + Console.WriteLine($"Gravity X: {gravity.X} Y: {gravity.Y} Z: {gravity.Z}"); + var qua = bno055Sensor.Quaternion; + Console.WriteLine($"Quaternion X: {qua.X} Y: {qua.Y} Z: {qua.Z} W: {qua.W}"); + var temp = bno055Sensor.Temperature.DegreesCelsius; + Console.WriteLine($"Temperature: {temp} °C"); + } + else if (device == Bmp180.DefaultI2cAddress) + { + using Bmp180 i2cBmp280 = new(channelBuses.CreateDevice(device)); + // set samplings + i2cBmp280.SetSampling(Sampling.Standard); + // read values + Temperature tempValue = i2cBmp280.ReadTemperature(); + Console.WriteLine($"Temperature: {tempValue.DegreesCelsius:0.#}\u00B0C"); + Pressure preValue = i2cBmp280.ReadPressure(); + Console.WriteLine($"Pressure: {preValue.Hectopascals:0.##}hPa"); + + // Note that if you already have the pressure value and the temperature, you could also calculate altitude by + // calling WeatherHelper.CalculateAltitude(preValue, Pressure.MeanSeaLevel, tempValue) which would be more performant. + Length altValue = i2cBmp280.ReadAltitude(WeatherHelper.MeanSeaLevel); + + Console.WriteLine($"Altitude: {altValue:0.##}m"); + Thread.Sleep(1000); + + // set higher sampling + i2cBmp280.SetSampling(Sampling.UltraLowPower); + + // read values + tempValue = i2cBmp280.ReadTemperature(); + Console.WriteLine($"Temperature: {tempValue.DegreesCelsius:0.#}\u00B0C"); + preValue = i2cBmp280.ReadPressure(); + Console.WriteLine($"Pressure: {preValue.Hectopascals:0.##}hPa"); + + // Note that if you already have the pressure value and the temperature, you could also calculate altitude by + // calling WeatherHelper.CalculateAltitude(preValue, Pressure.MeanSeaLevel, tempValue) which would be more performant. + altValue = i2cBmp280.ReadAltitude(WeatherHelper.MeanSeaLevel); + Console.WriteLine($"Altitude: {altValue:0.##}m"); + } + + Thread.Sleep(1000); + } + + } + } + } +} diff --git a/src/devices/Tca954x/samples/Tca9548a.sample.csproj b/src/devices/Tca954x/samples/Tca9548a.sample.csproj new file mode 100644 index 0000000000..e39417d491 --- /dev/null +++ b/src/devices/Tca954x/samples/Tca9548a.sample.csproj @@ -0,0 +1,12 @@ + + + + Exe + $(DefaultSampleTfms) + + + + + + +