(项目更新为RC-3(2023年3月30日发布)
这个项目是对我们令人敬畏的由草地驱动的快速原型制作板Project Lab的介绍。在本指南中,我们将向您展示如何将它与它自己的 NuGet 包一起使用,该包封装了所有外围设备的接线,让您可以立即专注于构建您的 IoT Meadow 解决方案。
在您开始这个项目之前,请确保您的 Meadow 板和开发环境是完全最新的。检查发行说明部分以仔细检查。
在 Visual Studio 2022 for Windows或macOS中创建一个新的Meadow Application项目并将其命名为ProjLab_Demo 。
对于这个项目,搜索并安装以下 NuGet 包:
显示控制器.cs
复制下面的代码:
public class DisplayController
{
readonly MicroGraphics graphics;
public (Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance)? AtmosphericConditions
{
get => atmosphericConditions;
set
{
atmosphericConditions = value;
Update();
}
}
(Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance)? atmosphericConditions;
public Illuminance? LightConditions
{
get => lightConditions;
set
{
lightConditions = value;
Update();
}
}
Illuminance? lightConditions;
public (Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Temperature? Temperature) AccelerationConditions
{
get => accelerationConditions;
set
{
accelerationConditions = value;
Update();
}
}
(Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Temperature? Temperature) accelerationConditions;
public bool UpButtonState
{
get => upButtonState;
set
{
upButtonState = value;
Update();
}
}
bool upButtonState = false;
public bool DownButtonState
{
get => downButtonState;
set
{
downButtonState = value;
Update();
}
}
bool downButtonState = false;
public bool LeftButtonState
{
get => leftButtonState;
set
{
leftButtonState = value;
Update();
}
}
bool leftButtonState = false;
public bool RightButtonState
{
get => rightButtonState;
set
{
rightButtonState = value;
Update();
}
}
bool rightButtonState = false;
bool isUpdating = false;
bool needsUpdate = false;
public DisplayController(IGraphicsDisplay display)
{
graphics = new MicroGraphics(display)
{
CurrentFont = new Font12x16()
};
graphics.Clear(true);
}
public void Update()
{
if (isUpdating)
{ //queue up the next update
needsUpdate = true;
return;
}
isUpdating = true;
graphics.Clear();
Draw();
graphics.Show();
isUpdating = false;
if (needsUpdate)
{
needsUpdate = false;
Update();
}
}
void DrawStatus(string label, string value, Color color, int yPosition)
{
graphics.DrawText(x: 2, y: yPosition, label, color: color);
graphics.DrawText(x: 238, y: yPosition, value, alignmentH: HorizontalAlignment.Right, color: color);
}
void Draw()
{
graphics.DrawText(x: 2, y: 0, "Hello PROJ LAB!", WildernessLabsColors.AzureBlue);
if (AtmosphericConditions is { } conditions)
{
if (conditions.Temperature is { } temp)
{
DrawStatus("Temperature:", $"{temp.Celsius:N1}C", WildernessLabsColors.GalleryWhite, 35);
}
if (conditions.Pressure is { } pressure)
{
DrawStatus("Pressure:", $"{pressure.StandardAtmosphere:N1}atm", WildernessLabsColors.GalleryWhite, 55);
}
if (conditions.Humidity is { } humidity)
{
DrawStatus("Humidity:", $"{humidity.Percent:N1}%", WildernessLabsColors.GalleryWhite, 75);
}
}
if (LightConditions is { } light)
{
DrawStatus("Lux:", $"{light:N0}Lux", WildernessLabsColors.GalleryWhite, 95);
}
if (AccelerationConditions is { } acceleration)
{
if (acceleration.Acceleration3D is { } accel3D)
{
DrawStatus("Accel:", $"{accel3D.X.Gravity:0.#},{accel3D.Y.Gravity:0.#},{accel3D.Z.Gravity:0.#}g", WildernessLabsColors.AzureBlue, 115);
}
if (acceleration.AngularVelocity3D is { } angular3D)
{
DrawStatus("Gyro:", $"{angular3D.X:0},{angular3D.Y:0},{angular3D.Z:0}rpm", WildernessLabsColors.AzureBlue, 135);
}
}
DrawStatus("Left:", $"{(LeftButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 200);
DrawStatus("Down:", $"{(DownButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 180);
DrawStatus("Up:", $"{(UpButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 160);
DrawStatus("Right:", $"{(RightButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 220);
}
}
此类的目的是控制来自 Project Lab 板载外围设备的信息并将其显示到其 240x240 显示器中,使用MicroGraphics
. 我们有以下属性:
AtmosphericConditions
- 该元组存储BME688大气传感器返回的值,能够测量温度、湿度、压力和气体阻力。LightConditions
- 存储来自BH1750光传感器的照度值。AccelerationConditions
- 另一个存储BMI270传感器给出的 3D 加速度、3D 角速度甚至温度的元组。UpButtonState
- 存储向上按钮状态的布尔值。DownButtonState
- 存储向下按钮状态的布尔值。LeftButtonState
- 存储左键状态的布尔值。RightButtonState
- 存储右按钮状态的布尔值。
请注意,在所有这些属性的设置器中,它将调用Update()
将运行逻辑以使用MicroGraphics 更新显示器上的值的方法。
MeadowApp.cs
复制下面的代码:
// Change F7FeatherV2 to F7FeatherV1 for V1.x boards
public class MeadowApp : App
{
DisplayController displayController;
RgbPwmLed onboardLed;
IProjectLabHardware projLab;
public override Task Initialize()
{
Resolver.Log.Loglevel = Meadow.Logging.LogLevel.Trace;
Resolver.Log.Info("Initialize hardware...");
//==== RGB LED
Resolver.Log.Info("Initializing onboard RGB LED");
onboardLed = new RgbPwmLed(
redPwmPin: Device.Pins.OnboardLedRed,
greenPwmPin: Device.Pins.OnboardLedGreen,
bluePwmPin: Device.Pins.OnboardLedBlue,
CommonType.CommonAnode);
Resolver.Log.Info("RGB LED up");
//==== instantiate the project lab hardware
projLab = ProjectLab.Create();
Resolver.Log.Info($"Running on ProjectLab Hardware {projLab.RevisionString}");
//---- display controller (handles display updates)
if (projLab.Display is { } display)
{
Resolver.Log.Trace("Creating DisplayController");
displayController = new DisplayController(display);
Resolver.Log.Trace("DisplayController up");
}
//---- BH1750 Light Sensor
if (projLab.LightSensor is { } bh1750)
{
bh1750.Updated += Bh1750Updated;
}
//---- BME688 Atmospheric sensor
if (projLab.EnvironmentalSensor is { } bme688)
{
bme688.Updated += Bme688Updated;
}
//---- BMI270 Accel/IMU
if (projLab.MotionSensor is { } bmi270)
{
bmi270.Updated += Bmi270Updated;
}
//---- buttons
if (projLab.RightButton is { } rightButton)
{
rightButton.PressStarted += (s, e) => displayController.RightButtonState = true;
rightButton.PressEnded += (s, e) => displayController.RightButtonState = false;
}
if (projLab.DownButton is { } downButton)
{
downButton.PressStarted += (s, e) => displayController.DownButtonState = true;
downButton.PressEnded += (s, e) => displayController.DownButtonState = false;
}
if (projLab.LeftButton is { } leftButton)
{
leftButton.PressStarted += (s, e) => displayController.LeftButtonState = true;
leftButton.PressEnded += (s, e) => displayController.LeftButtonState = false;
}
if (projLab.UpButton is { } upButton)
{
upButton.PressStarted += (s, e) => displayController.UpButtonState = true;
upButton.PressEnded += (s, e) => displayController.UpButtonState = false;
}
//---- heartbeat
onboardLed.StartPulse(WildernessLabsColors.PearGreen);
Resolver.Log.Info("Initialization complete");
return base.Initialize();
}
public override Task Run()
{
Resolver.Log.Info("Run...");
//---- BH1750 Light Sensor
if (projLab.LightSensor is { } bh1750)
{
bh1750.StartUpdating(TimeSpan.FromSeconds(5));
}
//---- BME688 Atmospheric sensor
if (projLab.EnvironmentalSensor is { } bme688)
{
bme688.StartUpdating(TimeSpan.FromSeconds(5));
}
//---- BMI270 Accel/IMU
if (projLab.MotionSensor is { } bmi270)
{
bmi270.StartUpdating(TimeSpan.FromSeconds(5));
}
if (displayController != null)
{
displayController.Update();
}
Resolver.Log.Info("starting blink");
onboardLed.StartBlink(WildernessLabsColors.PearGreen, TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(2000), 0.5f);
return base.Run();
}
private void Bmi270Updated(object sender, IChangeResult<(Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Temperature? Temperature)> e)
{
Resolver.Log.Info($"BMI270: {e.New.Acceleration3D.Value.X.Gravity:0.0},{e.New.Acceleration3D.Value.Y.Gravity:0.0},{e.New.Acceleration3D.Value.Z.Gravity:0.0}g");
if (displayController != null)
{
displayController.AccelerationConditions = e.New;
}
}
private void Bme688Updated(object sender, IChangeResult<(Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance)> e)
{
Resolver.Log.Info($"BME688: {(int)e.New.Temperature?.Celsius}C - {(int)e.New.Humidity?.Percent}% - {(int)e.New.Pressure?.Millibar}mbar");
if (displayController != null)
{
displayController.AtmosphericConditions = e.New;
}
}
private void Bh1750Updated(object sender, IChangeResult e)
{
Resolver.Log.Info($"BH1750: {e.New.Lux}");
if (displayController != null)
{
displayController.LightConditions = e.New;
}
}
}
在我们的主类中,主要需要考虑的是:
Initialize()
方法中,我们在做的时候先创建了一个ProjectLab对象(命名为projLab )ProjectLab.Create()
,它方便的封装了它板载的所有外设,所以我们只关注使用它们而不是在每个项目上实例化它上面的每个组件。if (projLab.Display is { } display)
表示如果Display
的属性projLab
不为null,则其对象赋值给display
,我们可以将其作为参数传给我们的DisplayController
类。Updated
详细了解我们如何使用传感器)。PressStarted
和PressEnded
事件,并将状态分配给 上显示的相应属性DisplayController
,因此当您按下任何按钮时,它们将立即在显示屏上更新。Run()
方法中,我们调用Update()
该DisplayController
对象以显示初始 UI 以及所有具有当前值的外围设备,并使 Meadow 的板载 LED 闪烁为绿色。单击Visual Studio中的“运行”按钮。它应该类似于以下 GIF:
就您可以使用 Meadow.Foundation 做的大量令人兴奋的事情而言,这个项目只是冰山一角。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !