未验证 提交 fa1960cd 编写于 作者: R Rich Lander 提交者: GitHub

Add BiColorBargraph using Ht16k33 (#1915)

* Add BiColorBargraph using Ht16k33

* Add images

* Update per feedback

* Update notes

* Add Fill method

* Update src/devices/Display/BiColorBarGraph.cs
上级 55a4ec02
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Iot.Device.Display
{
/// <summary>
/// Describes LED colors in a Bargraph.
/// </summary>
public enum BarColor
{
/// <summary>
/// Disable LED.
/// </summary>
Off = 0,
/// <summary>
/// Enable red LED.
/// </summary>
Red = 1,
/// <summary>
/// Enable green LED.
/// </summary>
Green = 2,
/// <summary>
/// Enable both green and red LEDs, producing a yellow color.
/// </summary>
Yellow = 3
}
}
// 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.Display
{
/// <summary>
/// Represents a 24-Segment bargraph that can display multiple colors.
/// </summary>
// Product: https://www.adafruit.com/product/1721
public class BiColorBarGraph : Ht16k33
{
private readonly byte[] _displayBuffer = new byte[7];
private readonly BarColor[] _biColorSegment = new BarColor[24];
/// <summary>
/// Initialize BarGraph display
/// </summary>
/// <param name="i2cDevice">The <see cref="I2cDevice"/> to create with.</param>
public BiColorBarGraph(I2cDevice i2cDevice)
: base(i2cDevice)
{
}
/// <summary>
/// Indexer for <see cref="BiColorBarGraph"/>.
/// </summary>
public BarColor this[int index]
{
get => _biColorSegment[index];
set
{
_biColorSegment[index] = value;
UpdateBuffer(index);
if (BufferingEnabled)
{
Flush();
}
}
}
/// <summary>
/// Enable all LEDs.
/// </summary>
public void Fill(BarColor color)
{
byte fill = 0xFF;
switch (color)
{
case BarColor.Red:
_displayBuffer[1] = fill;
_displayBuffer[3] = fill;
_displayBuffer[5] = fill;
break;
case BarColor.Green:
_displayBuffer[2] = fill;
_displayBuffer[4] = fill;
_displayBuffer[6] = fill;
break;
case BarColor.Yellow:
Span<byte> displayBuffer = _displayBuffer;
displayBuffer.Fill(fill);
displayBuffer[0] = 0x00;
break;
default:
break;
}
if (BufferingEnabled)
{
_i2cDevice.Write(_displayBuffer);
}
}
/// <inheritdoc/>
public override void Clear()
{
_displayBuffer.AsSpan().Clear();
if (BufferingEnabled)
{
_i2cDevice.Write(_displayBuffer);
}
}
/// <inheritdoc/>
public override void Flush() => _i2cDevice.Write(_displayBuffer);
/// <inheritdoc/>
public override void Write(ReadOnlySpan<byte> data, int startAddress = 0)
{
// Note: first byte is command data; does not affect display
foreach (byte b in data)
{
_displayBuffer[startAddress++] = b;
}
if (BufferingEnabled)
{
Flush();
}
}
/*
Task: Update data for the bargraph
The following diagram shows the intended orientation of the bargraph.
pins x x x x x x x x x x x x x x x x x x x x x x x x
23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Each bargraph has three segments, four LEDs each.
For the 24-segment bargraph, that's six segments of four LEDs.
Each segment is addressed separately, with 4 bits (of a byte).
The first and last 4 bits of each byte represent different segments.
Each bit represents an LED. If the bits are on, the LEDs are on.
Each bar contains two LEDs. These are separately controlled.
That means that there are eight bits to consider for each segement,
four for each color. All of which can be separately on or off.
There are seven (7) bytes in the buffer.
The first byte of the buffer is for control/command information.
It should always be `0` unless specifically sending commands (like for blinking).
Each of the following bytes are paired, the first for red and the second for green.
Each of the bytes in the pair are split, the first half for one segment,
and the second half for the matching segement on the other bargraph.
The bytes are laid out this way:
- first segment: first four bits of bytes[2] for red; first four bits of bytes[3] for green
- second segment: first four bits of bytes[4] for red; first four bits of bytes[5] for green
- third segment: first four bits of bytes[6] for red; first four bits of bytes[7] for green
------------- // boundary of the bargraph units
- fourth segment: second four bits of bytes[2] for red; second four bits of bytes[3] for green
- fifth segment: second four bits of bytes[4] for red; second four bits of bytes[5] for green
- sixth segment: second four bits of bytes[6] for red; second four bits of bytes[7] for green
This is more obvious if you write some variation of value to the i2cdevice:
byte[] buffer =
{
0, 255, 0, 0, 255, 255, 255
};
*/
private void UpdateBuffer(int index)
{
// Tasks:
// Determine the location of the bar (for `index`).
// Produce a mask for the correct bit (within four bits).
// bitmask the correct bits dependending on the desired result
// Some basic math to use:
// x = index % 4 // which third (for example, for the 24 bar graph, there are six thirds)
// y = x % 3 // which third of the bar segment to use
// z = index / 12 // which of the bar segments to use
BarColor value = _biColorSegment[index];
int unit = index / 12;
int segment = index / 4;
int third = segment % 3;
int bit = index % 4 + (index / 12) * 4;
int mask = 1 << bit;
int bufferIndex = (third * 2) + 1;
byte red = _displayBuffer[bufferIndex];
byte green = _displayBuffer[bufferIndex + 1];
switch (value)
{
case BarColor.Off:
_displayBuffer[bufferIndex] = (byte)(red & ~mask);
_displayBuffer[bufferIndex + 1] = (byte)(green & ~mask);
break;
case BarColor.Red:
_displayBuffer[bufferIndex] = (byte)(red ^ mask);
break;
case BarColor.Green:
_displayBuffer[bufferIndex + 1] = (byte)(green ^ mask);
break;
case BarColor.Yellow:
_displayBuffer[bufferIndex] = (byte)(red ^ mask);
_displayBuffer[bufferIndex + 1] = (byte)(green ^ mask);
break;
default:
break;
}
}
}
}
......@@ -13,6 +13,8 @@
<Compile Include="FontHelper.cs" />
<Compile Include="ISevenSegmentDisplay.cs" />
<Compile Include="Large4Digit7SegmentDisplay.cs" />
<Compile Include="BiColorBarGraph.cs" />
<Compile Include="BarColor.cs" />
</ItemGroup>
<ItemGroup>
<None Include="README.md" />
......
......@@ -7,6 +7,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{20F2
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Large4Digit7SegmentDisplay.sample", "samples\Large4Digit7SegmentDisplay.sample.csproj", "{C4D7AED7-B340-4DCD-974C-5150C6D5F074}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BiColorBargraph.sample", "samples\BiColorBargraph.sample.csproj", "{C4D7AED7-B340-4DCD-974C-5150C6D5F074}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Display", "Display.csproj", "{4AAE8B9E-8540-4582-8083-D1F14104BAAC}"
EndProject
Global
......
# Segment display driver (HT16K33)
# HT16K33 -- LED Matrix Display Driver
This project contains multipurpose LED display drivers and binding implementations for concrete display configurations.
## Documentation
The **HT16K33** is LED display driver that supports multiple LED configurations and I2C communication.
The [Ht16k33](https://cdn-shop.adafruit.com/datasheets/ht16K33v110.pdf) is a memory mapping and multi-function LED controller driver. It is used as a [backpack driver for several Adafruit products](https://www.adafruit.com/?q=Ht16k33). It supports multiple LED configurations and I2C communication.
Adafruit sells multiple display backpacks built upon this driver:
- [Adafruit LED / SEGMENTED category](https://www.adafruit.com/category/103)
- **Large4Digit7SegmentDisplay** is a binding that supports the **Adafruit 1.2" 4-Digit 7-Segment Display w/I2C Backpack** that comes in 3 colors:
- [Adafruit 1.2" 4-Digit 7-Segment Display w/I2C Backpack - Yellow](https://www.adafruit.com/product/1268)
- [Adafruit 1.2" 4-Digit 7-Segment Display w/I2C Backpack - Green](https://www.adafruit.com/product/1269)
- [Adafruit 1.2" 4-Digit 7-Segment Display w/I2C Backpack - Red](https://www.adafruit.com/product/1270)
- [HT16K33 datasheet](https://cdn-shop.adafruit.com/datasheets/ht16K33v110.pdf)
- [1.2" 4-Digit 7-Segment Display w/I2C Backpack - Yellow](https://www.adafruit.com/product/1268)
- [1.2" 4-Digit 7-Segment Display w/I2C Backpack - Green](https://www.adafruit.com/product/1269)
- [1.2" 4-Digit 7-Segment Display w/I2C Backpack - Red](https://www.adafruit.com/product/1270)
- [Bi-Color (Red/Green) 24-Bar Bargraph w/I2C Backpack Kit](https://www.adafruit.com/product/1721)
More information on wiring can be found on the respective product pages.
More information on wiring can be found on the respective product pages and at [adafruit/Adafruit_CircuitPython_HT16K33
](https://github.com/adafruit/Adafruit_CircuitPython_HT16K33) (Adafruit-maintained Python bindings).
## Usage
## 7-Segment Display Usage
![Adafruit 1.2" 4-Digit 7-Segment Display w/I2C Backpack - Green](https://cdn-shop.adafruit.com/970x728/1268-00.jpg)
```csharp
// Initialize display (busId = 1 for Raspberry Pi 2 & 3)
var display = new Large4Digit7SegmentDisplay(I2cDevice.Create(new I2cConnectionSettings(busId: 1, address: Ht16k33.DefaultI2cAddress));
using var display = new Large4Digit7SegmentDisplay(I2cDevice.Create(new I2cConnectionSettings(busId: 1, address: Ht16k33.DefaultI2cAddress));
// Set max brightness (automatically turns on display)
display.Brightness = display.MaxBrightness;
......@@ -41,7 +38,25 @@ display.Dots = Dot.DecimalPoint;
// Send buffer to the device
display.Flush();
```
// Dispose display object (the device itself will not be turned off until powered down)
display.Dispose();
## Bi-Color Bargraph Usage
![Bi-Color (Red/Green) 24-Bar Bargraph w/I2C Backpack Kit](https://cdn-shop.adafruit.com/970x728/1721-00.jpg)
```csharp
using BiColorBarGraph bargraph = new(I2cDevice.Create(new I2cConnectionSettings(busId: 1, Ht16k33.DefaultI2cAddress)))
{
// Set max brightness
Brightness = Ht16k33.MaxBrightness,
BufferingEnabled = true
};
bargraph.Clear();
bargraph[0] = BarColor.RED;
bargraph[1] = BarColor.GREEN;
bargraph[2] = BarColor.YELLOW;
bargraph[3] = BarColor.OFF;
bargraph[4] = BarColor.RED;
```
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(DefaultSampleTfms)</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Display.csproj" />
<Compile Include="Program.BiColorBargraph.cs" />
</ItemGroup>
</Project>
......@@ -2,8 +2,10 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(DefaultSampleTfms)</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Display.csproj" />
<Compile Include="Program.cs" />
</ItemGroup>
</Project>
// 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;
using System.Threading;
using Iot.Device.Display;
// Initialize display (busId = 1 for Raspberry Pi 2+)
using BiColorBarGraph bargraph = new(I2cDevice.Create(new I2cConnectionSettings(busId: 1, Ht16k33.DefaultI2cAddress)))
{
// Set max brightness
Brightness = Ht16k33.MaxBrightness,
BufferingEnabled = true
};
bargraph.Clear();
bargraph[0] = BarColor.Red;
bargraph[1] = BarColor.Green;
bargraph[2] = BarColor.Yellow;
bargraph[3] = BarColor.Off;
bargraph[4] = BarColor.Red;
Thread.Sleep(1000);
bargraph.Clear();
for (int i = 0; i < 24; i++)
{
if (i % 2 is 1)
{
continue;
}
int num = i % 4;
BarColor color = (BarColor)(i % 3 + 1);
bargraph[i] = color;
Thread.Sleep(100);
}
for (int i = 23; i >= 0; i--)
{
if (i % 2 is 0)
{
continue;
}
int num = i % 4;
BarColor color = (BarColor)(i % 3 + 1);
bargraph[i] = color;
Thread.Sleep(100);
}
Thread.Sleep(1000);
bargraph.Clear();
bargraph[0] = BarColor.Red;
bargraph[6] = BarColor.Green;
bargraph[11] = BarColor.Yellow;
bargraph[12] = BarColor.Yellow;
bargraph[18] = BarColor.Green;
bargraph[23] = BarColor.Red;
Thread.Sleep(1000);
bargraph.Clear();
byte[] customBuffer =
{
0, 255, 0, 0, 255, 255, 255
};
bargraph.Write(customBuffer);
Thread.Sleep(1000);
bargraph.Clear();
bargraph.Fill(BarColor.Red);
Thread.Sleep(1000);
bargraph.Clear();
bargraph.Fill(BarColor.Green);
Thread.Sleep(1000);
bargraph.Clear();
bargraph.Fill(BarColor.Yellow);
Thread.Sleep(1000);
bargraph.Clear();
# Ht16k33
The [Ht16k33](https://cdn-shop.adafruit.com/datasheets/ht16K33v110.pdf) is a memory mapping and multi-function LED controller driver. It is used as a [backpack driver for several Adafruit products](https://www.adafruit.com/?q=Ht16k33).
See the [Display](../Display/) folder for implementations of various products that use the Ht16k33.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册