-
Notifications
You must be signed in to change notification settings - Fork 625
Added TCA9548A device binding #1908
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
378f982
TCA9548A tested
asheesh1996 151977e
Merge branch 'dotnet:main' into TCA9548A-dev
asheesh1996 16c044b
Removed white spaces from readme
asheesh1996 6e6971f
Removed white spaces from readme
asheesh1996 e7ed93a
Resolved Review Suggestions
asheesh1996 b413f6f
Merge branch 'dotnet:main' into TCA9548A-dev
asheesh1996 ecdac95
Removed blank lines from Readme.md
asheesh1996 f9918df
Removed blank lines from Readme.md
asheesh1996 750a909
Removed blank lines from Readme.md
asheesh1996 2062b54
updated device creation
asheesh1996 bdd0c8c
Merge branch 'dotnet:main' into TCA9548A-dev
asheesh1996 c8cf082
Resolved Issues
asheesh1996 4964e71
Updates on TCA
asheesh1996 cc74f6b
Updated readme
asheesh1996 d79aa17
Rename folder, to be more generic for future additional of similar de…
pgrawehr 616ad30
Adjust namespace
pgrawehr 19b6998
Merge remote-tracking branch 'remotes/dotnet/main' into TCA9548A-dev
pgrawehr 31ea8f7
Update path
pgrawehr 4fc9fce
Documentation and API cleanup
pgrawehr c2a8a6c
Review findings, fixed channel implementation
pgrawehr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| { | ||
| /// <summary> | ||
| /// Available channels | ||
| /// </summary> | ||
| [Flags] | ||
| public enum MultiplexerChannel : byte | ||
| { | ||
| /// <summary> | ||
| /// No channel is selected | ||
| /// </summary> | ||
| None = 0, | ||
|
|
||
| /// <summary> | ||
| /// Channel 0 Byte (2^0 = 1) | ||
| /// </summary> | ||
| Channel0 = 0x01, | ||
|
|
||
| /// <summary> | ||
| /// Channel 1 Byte (2^1 = 2) | ||
| /// </summary> | ||
| Channel1 = 0x02, | ||
|
|
||
| /// <summary> | ||
| /// Channel 2 Byte (2^2 = 4) | ||
| /// </summary> | ||
| Channel2 = 0x04, | ||
|
|
||
| /// <summary> | ||
| /// Channel 3 Byte (2^3 = 8) | ||
| /// </summary> | ||
| Channel3 = 0x08, | ||
|
|
||
| /// <summary> | ||
| /// Channel 4 Byte (2^4 = 16) | ||
| /// </summary> | ||
| Channel4 = 0x10, | ||
|
|
||
| /// <summary> | ||
| /// Channel 5 Byte (2^5 = 32) | ||
| /// </summary> | ||
| Channel5 = 0x20, | ||
|
|
||
| /// <summary> | ||
| /// Channel 6 Byte (2^6 = 64) | ||
| /// </summary> | ||
| Channel6 = 0x40, | ||
|
|
||
| /// <summary> | ||
| /// Channel 7 Byte (2^7 = 128) | ||
| /// </summary> | ||
| Channel7 = 0x80 | ||
| } | ||
|
|
||
| } |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 [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 | ||
|
|
||
|  | ||
|
|
||
| ## Possible TCA9548A Addresses | ||
|
|
||
|  | ||
|
|
||
| ## 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. | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| { | ||
| /// <summary> | ||
| /// Tca9548A - 8-Channel I2C Switch/Multiplexer | ||
| /// </summary> | ||
| [Interface("Tca9548A - 8-Channel I2C Switch/Multiplexer")] | ||
| public class Tca9548A : IList<I2cBus>, IDisposable | ||
| { | ||
| private readonly bool _shouldDispose; | ||
| private readonly List<Tca9548AChannelBus> _channelBuses = new List<Tca9548AChannelBus>(); | ||
| private MultiplexerChannel? _activeChannels; | ||
|
|
||
| /// <summary> | ||
| /// The default I2C Address, page 15 of the main documentation | ||
| /// https://www.ti.com/lit/ds/symlink/tca9548a.pdf | ||
| /// </summary> | ||
| public const byte DefaultI2cAddress = 0x70; | ||
|
|
||
| /// <summary> | ||
| /// Array of all possible Multiplexer Channels | ||
| /// </summary> | ||
| 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; | ||
|
|
||
| /// <summary> | ||
| /// Creates a Multiplexer Instance | ||
| /// </summary> | ||
| /// <param name="i2cDevice">The I2C Device of the Mux itself</param> | ||
| /// <param name="mainBus">The bus the mux is connected to</param> | ||
| /// <param name="shouldDispose">true to dispose the I2C device at dispose</param> | ||
| /// <exception cref="ArgumentNullException">Exception thrown if I2C device is null</exception> | ||
| 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)); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets Channel busses of the multiplexer | ||
| /// </summary> | ||
| /// <param name="index">channel number</param> | ||
| /// <returns></returns> | ||
| public I2cBus this[int index] => _channelBuses[index]; | ||
|
|
||
| /// <summary> | ||
| /// Select a group of multiplexer channels. | ||
| /// </summary> | ||
| /// <param name="multiplexChannels">The channels to select</param> | ||
| /// <remarks> | ||
| /// 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. | ||
| /// </remarks> | ||
| public void SelectChannel(MultiplexerChannel multiplexChannels) | ||
| { | ||
| if (TryGetSelectedChannel(out var channel) && channel != multiplexChannels) | ||
| { | ||
| _i2CDevice.WriteByte(Convert.ToByte(multiplexChannels)); | ||
| _activeChannels = multiplexChannels; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Try getting the selected channel on Multiplexer | ||
| /// </summary> | ||
| /// <param name="selectedChannel"> selected Multiplexer Channel</param> | ||
| /// <returns> true if able to retrieve selected channel</returns> | ||
| 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; | ||
| } | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public void Dispose() | ||
| { | ||
| if (_shouldDispose) | ||
| { | ||
| _i2CDevice?.Dispose(); | ||
| } | ||
|
|
||
| _i2CDevice = null!; | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public int Count => _channelBuses.Count; | ||
|
|
||
| /// <inheritdoc/> | ||
| public bool IsReadOnly => true; | ||
|
|
||
| I2cBus IList<I2cBus>.this[int index] { get => _channelBuses[index]; set => _channelBuses[index] = (Tca9548AChannelBus)value; } | ||
|
|
||
| /// <inheritdoc/> | ||
| public int IndexOf(I2cBus item) | ||
| { | ||
| return _channelBuses.IndexOf((Tca9548AChannelBus)item); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public void Insert(int index, I2cBus item) | ||
| { | ||
| _channelBuses.Insert(index, (Tca9548AChannelBus)item); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public void RemoveAt(int index) | ||
| { | ||
| _channelBuses.RemoveAt(index); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public void Add(I2cBus item) | ||
| { | ||
| _channelBuses.Add((Tca9548AChannelBus)item); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public void Clear() | ||
| { | ||
| _channelBuses.Clear(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public bool Contains(I2cBus item) | ||
| { | ||
| return _channelBuses.Contains((Tca9548AChannelBus)item); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public void CopyTo(I2cBus[] array, int arrayIndex) | ||
| { | ||
| _channelBuses.CopyTo((Tca9548AChannelBus[])array, arrayIndex); | ||
|
|
||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public bool Remove(I2cBus item) | ||
| { | ||
| return _channelBuses.Remove((Tca9548AChannelBus)item); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public IEnumerator<I2cBus> GetEnumerator() | ||
| { | ||
| return _channelBuses.GetEnumerator(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| IEnumerator IEnumerable.GetEnumerator() | ||
| { | ||
| return GetEnumerator(); | ||
| } | ||
| } | ||
|
|
||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.