diff --git a/docs/Meadow/Meadow.Foundation/Peripherals/index.md b/docs/Meadow/Meadow.Foundation/Peripherals/index.md index 3a37239cc..673ca4abb 100644 --- a/docs/Meadow/Meadow.Foundation/Peripherals/index.md +++ b/docs/Meadow/Meadow.Foundation/Peripherals/index.md @@ -218,18 +218,18 @@ External peripheral drivers can be added to Meadow projects individually and are | Status badge: working | [Ads1015](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Ads1015) | Ads1015 analog digital converter driver | | Status badge: working | [Ads1115](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Ads1115) | Ads1115 analog digital converter driver | -#### ICs.ADCs.Mcp3xxx +#### ICs.ADC.Mcp3xxx | Status | Driver | Description | |--------|--------|-------------| -| Status badge: working | [Mcp3001](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp3001) | Mcp3001 analog digital converter driver | -| Status badge: working | [Mcp3002](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp3002) | Mcp3002 analog digital converter driver | -| Status badge: working | [Mcp3004](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp3004) | Mcp3004 analog digital converter driver | -| Status badge: working | [Mcp3008](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp3008) | Mcp3008 analog digital converter driver | -| Status badge: working | [Mcp3201](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp3201) | Mcp3201 analog digital converter driver | -| Status badge: working | [Mcp3202](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp3202) | Mcp3202 analog digital converter driver | -| Status badge: working | [Mcp3204](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp3204) | Mcp3204 analog digital converter driver | -| Status badge: working | [Mcp3208](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp3208) | Mcp3208 analog digital converter driver | +| Status badge: working | [Mcp3001](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3001) | Mcp3001 analog digital converter driver | +| Status badge: working | [Mcp3002](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3002) | Mcp3002 analog digital converter driver | +| Status badge: working | [Mcp3004](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3004) | Mcp3004 analog digital converter driver | +| Status badge: working | [Mcp3008](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3008) | Mcp3008 analog digital converter driver | +| Status badge: working | [Mcp3201](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3201) | Mcp3201 analog digital converter driver | +| Status badge: working | [Mcp3202](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3202) | Mcp3202 analog digital converter driver | +| Status badge: working | [Mcp3204](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3204) | Mcp3204 analog digital converter driver | +| Status badge: working | [Mcp3208](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3208) | Mcp3208 analog digital converter driver | #### ICs.DAC.Mcp492x @@ -313,6 +313,14 @@ External peripheral drivers can be added to Meadow projects individually and are | Status badge: working | [Tca9535](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Tca9535) | Tca9535 IO expander driver | | Status badge: working | [Tca9555](/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Tca9555) | Tca9555 IO expander driver | + +#### IOExpanders.Temco.T3xxx + +| Status | Driver | Description | +|--------|--------|-------------| +| Status badge: working | [T322ai](/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T322ai) | T322ai temco driver | +| Status badge: working | [T38i8o6do](/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T38i8o6do) | T38i8o6do temco driver | + ### Leds | Status | Driver | Description | @@ -343,6 +351,7 @@ External peripheral drivers can be added to Meadow projects individually and are | Status | Driver | Description | |--------|--------|-------------| +| Status badge: working | [RTCs.Ab0805](/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Ab0805) | Ab0805 I2C real time clock | | Status badge: working | [RTCs.Ds1307](/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Ds1307) | DS1307 I2C real time clock | | Status badge: working | [RTCs.Pcf8523](/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Pcf8523) | Pcf8523 I2C real time clock | @@ -603,6 +612,7 @@ External peripheral drivers can be added to Meadow projects individually and are | Status | Driver | Description | |--------|--------|-------------| | Status badge: working | [Sensors.Power.CurrentTransducer](/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Power.CurrentTransducer) | Current transducer library | +| Status badge: working | [Sensors.Power.Spm1x](/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Power.Spm1x) | Temco Controls' SPM1-X Modbus Single-Phase Power Meter library | #### Sensors.Power.Ina2xx diff --git a/docs/Meadow/Meadow_Desktop/Meadow_Blazor/index.md b/docs/Meadow/Meadow_Desktop/Meadow_Blazor/index.md new file mode 100644 index 000000000..a5c6b92a4 --- /dev/null +++ b/docs/Meadow/Meadow_Desktop/Meadow_Blazor/index.md @@ -0,0 +1,225 @@ +--- +layout: Meadow +title: Get started with Meadow.Blazor +subtitle: "To get up and running with Meadow.Blazor, follow these steps:" +--- + +Meadow.Blazor in combination with Meadow.Desktop offers an environment for developing Meadow applications that can run on Windows, Mac and Linux. Developing with Meadow.Blazor requires setting up your development machine with some prerequisites. Then, after connecting any external components, you can deploy and run your Meadow application. + +Meadow Blazor enables you to combine a Blazor front-end using Blazor Server while accessing physical components by way of an FTDI breakout board such as FT232H that provides GPIO, SPI, and I2C. + +## Prerequisites + +Before you can get started with Meadow.Blazor, make sure your [development machine is set up for Meadow development](/Meadow/Getting_Started/Hello_World/). + +If it is not already installed, install the .NET 8.0 SDK. You can find the latest version of the .NET SDK from the [.NET downloads](https://dotnet.microsoft.com/download/dotnet/). + +### Using GPIO and SPI + +With an FTDI breakout board like the [FT232H](https://www.adafruit.com/product/2264), you can add GPIO and SPI capabilities to your desktop device. + +## Create your first Meadow.Blazor app + +1. Create a new Blazor Server dotnet app on your development machine and navigate to the project folder. + + ```command + dotnet new blazorserver -n MeadowBlazorSampleApp + cd MeadowBlazorSampleApp + ``` + +1. Add the Meadow.Blazor NuGet package to your project. + + ```command + dotnet add package Meadow.Blazor + ``` + +1. Create a new file named `MeadowApplication` in your project with the following code: + + ```csharp + using Meadow; + + internal class MeadowApplication : App + { + public override Task Initialize() + { + //initialize hardware here and add to sensor service + return base.Initialize(); + } + + public override Task Run() + { + return base.Run(); + } + } + ``` + +1. If using external hardware, you'll need to add the relevant Meadow nuget packages and initialize the drivers in the `Initialize` method: + + ```csharp + using Meadow; + using Meadow.Foundation.ICs.IOExpanders; + using Meadow.Foundation.Leds; + using Meadow.Foundation.Sensors.Atmospheric; + using Meadow.Peripherals.Leds; + + internal class MeadowApplication : App + { + public override Task Initialize() + { + FtdiExpanderCollection.Devices.Refresh(); + var ftdi = FtdiExpanderCollection.Devices[0]; + var output = ftdi.Pins.D7.CreateDigitalOutputPort(false); + Resolver.Services.Add(output); + + var bme680 = new Bme680(ftdi.CreateSpiBus(), ftdi.Pins.C7); + Resolver.Services.Add(bme680); + + var led = new Led(ftdi.Pins.C0); + Resolver.Services.Add(led); + + return base.Initialize(); + } + + public override Task Run() + { + return base.Run(); + } + } + ``` + +1. Meadow.Desktop is initialized via an extension method on `WebApplication` included with Meadow.Blazor named `UseMeadow`. Call `UseMeadow` in your program.cs. + + ```csharp + using Meadow.Blazor; + using Meadow.Blazor.Services; + + var builder = WebApplication.CreateBuilder(args); + + ... + + var app = builder.Build(); + + ... + + app.UseMeadow(); + + ... + + app.Run(); + ``` + +1. Build the app: + + ```command + dotnet build + ``` + +1. Run the app: + + ```command + dotnet run + ``` + +## Access peripherals from a Blazor Server app + +When structuring your Blazor Server application, a common pattern is to create view models to support Razor pages. + +Below is an example to present sensor data for a `BME680` atmospheric sensor. + +![Meadow.Blazor running in a web browser](meadow_blazor.jpg) + +1. Create a view model that exposes sensor data as public properties and includes a `StateChanged` `Action`. Note the use of `Resolver.Services` to access the peripherals you registered in `MeadowApplication`. + + ```csharp + using Meadow.Foundation.Sensors.Atmospheric; + using Meadow.Peripherals.Leds; + using Meadow.Units; + + namespace Meadow.Blazor.Services + { + public class SensorViewModel : IDisposable + { + private readonly Bme680 _bme680; + + public string TemperatureValue { get; private set; } = "0°C"; + public string HumidityValue { get; private set; } = "0%"; + public string PressureValue { get; private set; } = "0atm"; + + public event Action? StateChanged; + + public SensorViewModel() + { + _bme680 = Resolver.Services.Get() ?? throw new Exception("BME680 not found"); + _bme680.Updated += Bme680Updated; + _bme680.StartUpdating(TimeSpan.FromSeconds(2)); + } + + private void Bme680Updated(object? sender, IChangeResult<(Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance)> e) + { + TemperatureValue = $"{e.New.Temperature?.Celsius:n0}°C"; + HumidityValue = $"{e.New.Humidity?.Percent:n0}%"; + PressureValue = $"{e.New.Pressure?.StandardAtmosphere:n2}atm"; + + StateChanged?.Invoke(); + } + + public void Dispose() + { + _bme680?.StopUpdating(); + } + } + } + ``` + +2. Create a razor page that uses the view model: + + ```csharp + @page "/" + @inject Meadow.Blazor.Services.SensorViewModel ViewModel + +
+
+
+ Meadow +
+

Meadow Blazor

+

Atmospheric readings from a BME680

+ +
+
+ Temperature: + @ViewModel.TemperatureValue +
+
+ Pressure: + @ViewModel.PressureValue +
+
+ Humidity: + @ViewModel.HumidityValue +
+
+
+
+ + @code { + protected override void OnInitialized() + { + ViewModel.StateChanged += OnViewModelStateChanged; + } + + private void OnViewModelStateChanged() + { + InvokeAsync(StateHasChanged); + } + + public void Dispose() + { + ViewModel.StateChanged -= OnViewModelStateChanged; + } + } + ``` + +## Next steps + +Now that you have your Meadow.Blazor project and hardware set up and your app running, you can start working with the [Meadow.Foundation](../../../Meadow.Foundation/Getting_Started/) libraries to add additional functionality to your Meadow app. Check out the other [samples in the Meadow.Desktop.Samples](https://github.com/WildernessLabs/Meadow.Samples/tree/main/Source/). diff --git a/docs/Meadow/Meadow_Desktop/Meadow_Blazor/meadow_blazor.jpg b/docs/Meadow/Meadow_Desktop/Meadow_Blazor/meadow_blazor.jpg new file mode 100644 index 000000000..5a814075b Binary files /dev/null and b/docs/Meadow/Meadow_Desktop/Meadow_Blazor/meadow_blazor.jpg differ diff --git a/docs/Meadow/Meadow_Desktop/Meadow_Linux/index.md b/docs/Meadow/Meadow_Desktop/Meadow_Linux/index.md index 8ac46c95f..c6a2af344 100644 --- a/docs/Meadow/Meadow_Desktop/Meadow_Linux/index.md +++ b/docs/Meadow/Meadow_Desktop/Meadow_Linux/index.md @@ -27,7 +27,7 @@ You can also find any supported boards in the [Meadow.Linux implementation pinou ## Prerequisites -Before you can get started with Meadow.Linux, make sure your [development machine is set up for Meadow development](../../Hello_World/). +Before you can get started with Meadow.Linux, make sure your [development machine is set up for Meadow development](/Meadow/Getting_Started/Hello_World/). To get started with Meadow.Linux, you will need to install the following prerequisites on your host Linux machine. diff --git a/docs/Meadow/Meadow_Desktop/Meadow_Mac/index.md b/docs/Meadow/Meadow_Desktop/Meadow_Mac/index.md index e69de29bb..59291ddd9 100644 --- a/docs/Meadow/Meadow_Desktop/Meadow_Mac/index.md +++ b/docs/Meadow/Meadow_Desktop/Meadow_Mac/index.md @@ -0,0 +1,136 @@ +--- +layout: Meadow +title: Get started with Meadow.Mac +subtitle: "To get up and running with Meadow.Mac, follow these steps:" +--- + +Meadow.Mac provides an environment for developing Meadow applications on macOS, with optional GPIO support through an add-on accessory. Setting up Meadow.Mac requires configuring your development machine and connecting external components before you can deploy and run your Meadow application. + +unning Meadow applications on a Mac offers a convenient and fast development loop for prototyping and testing. You can use the same components you would on a Meadow Feather or Core-Compute module by connecting an FTDI breakout board like the FT232H, which supports GPIO, SPI, and (in the future) I2C. + +Meadow.Mac also allows for prototyping graphics using an emulated IDisplay object, rendering to a standard window on your Mac. Additionally, running Meadow apps on macOS can leverage the hardware's increased processing power for intensive workloads. + +## Prerequisites + +Before starting with Meadow.Mac, ensure your [development machine is set up for Meadow development](/Meadow/Getting_Started/Hello_World/). + +If you haven't already, install the .NET 8.0 SDK for macOS. You can find the latest version on the [.NET downloads page](https://dotnet.microsoft.com/download/dotnet/). + +### Using GPIO and SPI + +To add GPIO and SPI capabilities to your Mac, you can use an [FTDI breakout board such as FT232H](https://www.adafruit.com/product/2264). + +## Create your first Meadow.Mac app + +1. Create a new .NET console application: + + ```command + dotnet new console --output MeadowMacSampleApp + cd MeadowMacSampleApp + ``` + + This will ensure the Meadow app has the project settings that will work within Meadow.Mac. + +1. Add the Meadow.Mac NuGet package: + + ```command + dotnet add package Meadow.Mac + ``` + +1. Replace the contents of the `Program.cs` file: + + ```csharp + using Meadow; + using Meadow.Devices; + + public class MeadowApp : App + { + static async Task Main(string[] args) + { + await MeadowOS.Start(args); + } + + public override Task Initialize() + { + Resolver.Log.Info("Initialize..."); + + return base.Initialize(); + } + + public override Task Run() + { + Resolver.Log.Info("Run..."); + + Resolver.Log.Info("Hello, Meadow.Mac!"); + + return base.Run(); + } + } + ``` + + This simple app logs messages at various stages of the Meadow application. + +1. Build the app: + + ```command + dotnet build + ``` + +1. Run the app: + + ```command + dotnet run + ``` + + The console output should display: + + ```console + Initialize... + Run... + Hello, Meadow.Mac! + ``` + +You now have a Meadow.Mac app running on your Mac development machine. + +## Adapt a Meadow app for Meadow.Mac + +To update an existing Meadow app to target a Mac, adjust the app’s structure as follows: + +1. Update the project file to target an executable: + + ```xml + + + Exe + net8.0 + enable + enable + + + ... + + ``` + +1. Change the app type to Meadow.Mac: + + ```csharp + public class MeadowApp : App + { + ... + } + ``` + +1. Add the Main method to the MeadowApp class: + + ```csharp + public static async Task Main(string[] args) + { + await MeadowOS.Start(args); + } + ``` + +Your Meadow app should now be able to run on macOS, calling into the usual `Initialize` and `Run` methods of your app. + +## Next steps + +With your Meadow.Mac setup complete, start exploring the [Meadow.Foundation](../../../Meadow.Foundation/Getting_Started/) libraries to add functionality to your Meadow app. You can also find additional examples in the [samples in the Meadow.Desktop.Samples](https://github.com/WildernessLabs/Meadow.Samples/tree/main/Source/Mac). diff --git a/docs/Meadow/Meadow_Desktop/Meadow_Windows/index.md b/docs/Meadow/Meadow_Desktop/Meadow_Windows/index.md index 95670236e..fbe3fa8f7 100644 --- a/docs/Meadow/Meadow_Desktop/Meadow_Windows/index.md +++ b/docs/Meadow/Meadow_Desktop/Meadow_Windows/index.md @@ -12,17 +12,17 @@ You can also quickly prototype graphics using an emulated IDisplay object that r ## Prerequisites -Before you can get started with Meadow.Windows, make sure your [development machine is set up for Meadow development](../../Hello_World/). +Before starting with Meadow.Windows, ensure your [development machine is set up for Meadow development](/Meadow/Getting_Started/Hello_World/). -If you don't already have it, you may want to install the .NET 7.0 SDK. You can find the latest version of the .NET SDK for Windows from the [.NET downloads](https://dotnet.microsoft.com/download/dotnet/). (Currently, all Meadow.Windows samples are targeting .NET 7.0, though they also support targeting .NET 6.0.) +If you haven't already, install the .NET 8.0 SDK for macOS. You can find the latest version on the [.NET downloads page](https://dotnet.microsoft.com/download/dotnet/). ### Using GPIO and SPI -With an additional accessory, you can add GPIO and SPI capabilities to your Windows device. You can use an [FTDI breakout board such as FT232H](https://www.adafruit.com/product/2264) to provide GPIO and SPI capabilities. (The FT232H also supports I2C, but in this early stage, Meadow.Windows does not yet support it.) +To add GPIO and SPI capabilities to your Windows PC, you can use an [FTDI breakout board such as FT232H](https://www.adafruit.com/product/2264). ## Create your first Meadow.Windows app -1. Create a new dotnet app on your development machine and navigate to that new project. +1. Create a new .NET console application: ```command dotnet new console --output MeadowWindowsSampleApp @@ -31,13 +31,13 @@ With an additional accessory, you can add GPIO and SPI capabilities to your Wind This will ensure the Meadow app has the project settings that will work within Meadow.Windows. -1. Add the Meadow.Windows NuGet reference to your project. +1. Add the Meadow.Windows NuGet package: ```command dotnet add package Meadow.Windows ``` -1. Replace the contents of the `Program.cs` file in your project with the following. +1. Replace the contents of the `Program.cs` file: ```csharp using Meadow; @@ -68,21 +68,21 @@ With an additional accessory, you can add GPIO and SPI capabilities to your Wind } ``` - This is a simple Meadow.Windows app that will output some messages to the console at various stages of the Meadow app. + This simple app logs messages at various stages of the Meadow application. -1. Build the app for your development machine using either Visual Studio or the `dotnet` tool. +1. Build the app: ```command dotnet build ``` -1. Run the app. +1. Run the app: ```command dotnet run ``` - At the end of the Meadow app launch output, you should see the following output from your app. + The console output should display: ```console Initialize... @@ -90,21 +90,19 @@ With an additional accessory, you can add GPIO and SPI capabilities to your Wind Hello, Meadow.Windows! ``` -You have a Meadow.Windows app running on your Windows development machine. You can continue to develop and test your Meadow app on your development machine. When you are ready, you can deploy your Meadow app to other Windows device like any other .NET app. +You now have a Meadow.Windows app running on your Windows development machine. ## Adapt a Meadow app for Meadow.Windows -You can also modify an existing Meadow app to run on Meadow.Windows by adjusting the `App` type and adding the following static `Main` method to your `MeadowApp` class. +To update an existing Meadow app to target a Windows PC, adjust the apps structure as follows: -For example, here are the changes to make the MeadowApp class work on Meadow.Windows, configured for Windows. - -1. Configure the project type to be an executable by changing the project output type to a .NET 7 executable in the project file. +1. Update the project file to target an executable: ```xml Exe - net7.0 + net8.0 enable enable @@ -113,7 +111,7 @@ For example, here are the changes to make the MeadowApp class work on Meadow.Win ``` -1. Within the Meadow app's class file, change the `App` type to align with your target Meadow.Windows device: `App`. +1. Change the app type to Meadow.Windows: ```csharp public class MeadowApp : App @@ -122,7 +120,7 @@ For example, here are the changes to make the MeadowApp class work on Meadow.Win } ``` -1. Within the `MeadowApp` class, or whatever your app's class name is, add a new `Main` method to give the app a target to launch when the app is run. +1. Add the Main method to the MeadowApp class: ```csharp public static async Task Main(string[] args) @@ -131,7 +129,7 @@ For example, here are the changes to make the MeadowApp class work on Meadow.Win } ``` -Your Meadow app should now be able to run on Meadow.Windows, calling into the usual `Initialize` and `Run` methods of your app. +Your Meadow app should now be able to run on Windows, calling into the usual `Initialize` and `Run` methods of your app. ## Next steps diff --git a/docs/Meadow/Release_Notes/v2/index.md b/docs/Meadow/Release_Notes/v2/index.md index 573db4000..8277b1c06 100644 --- a/docs/Meadow/Release_Notes/v2/index.md +++ b/docs/Meadow/Release_Notes/v2/index.md @@ -10,9 +10,43 @@ subtitle: Release Notes * [Meadow.CLI](/Meadow/Meadow_Tools/Meadow_CLI/) * [Meadow.OS](/Meadow/Getting_Started/Deploying_Meadow%2EOS/) +## v2.3.0.0 + +This is a full-stack (Meadow.OS + managed stack) that includes a huge rework of the OtA functionality of Meadow.OS, making it far simpler and easier to use. It also includes a number of performance enhancements, bug fixes, and a host of new industrial peripheral drivers. Some of the major improvements include: + +* **Automatic OtA** - Over-the-Air (OtA) updates just got a whole lot simpler to use. Instead of having to opt-in to updates and approve the update notification in app code, when you send an update now, it will automatically be applied as long as the device is registered with Meadow.Cloud and has cloud integration turned on. The device can still opt out, or apply the update at a later time, but by default, they will now get applied. This reduces the amount of code needed to integrate OtA into your application to effectively zero. +* **Performance Updates** - Both the file system and TCP/IP stack got big performance updates. +* **Industrial Peripheral Drivers** - A number of peripheral drivers for industrial applications have been added. + +### Meadow.OS + +* TCP/IP write buffering is now also enabled for non-WiFi adapters, bringing enhanced performance. +* `Path.GetTempPath()` and `Path.GetTempFileName()` now work correctly on Meadow. +* `File.Move` now uses `Rename()` instead of doing a copy+delete. +* Fixed “Unable to monitor frequency on pins PB14 or PB15” issue. +* Flash storage driver was improved for better system responsiveness while writing to the filesystem. +* Removed extraneous platform support in the .NET BCL port resolving several runtime issues and reducing the size of the runtime. + +### Meadow.Core + +* Fully reworked the Meadow.Cloud update service logic for improved reliability and resiliency and updates by default +* Fixed F7 CPU temp occasionally wildly wrong +* Separated and extracted `IAnalogInput` port and `IObservableAnalogInputPort` +* Added new Bluetooth events for `ClientConnected` and `ClientDisconnected` + +### Meadow.Foundation + +* Added **Temco SPM1-X** driver +* Added **Temco T3-22i** driver +* Added **AB0805** RTC driver +* Added **MicroScheduler** library +* **MicroGraphics** performance optimizations +* **MicroLayout** API cleanup +* **FT232H** API fixes + ## v2.2.0.0 -This is a full stack release that brings general stability improvements and fixes to the Meadow platform. +This is a full stack release that brings general stability improvements and fixes to the Meadow platform along with Blazor Server support via [Meadow.Blazor](https://developer.wildernesslabs.dev/Meadow/Meadow_Desktop/Meadow_Blazor/)! ### Meadow.OS @@ -21,7 +55,7 @@ This is a full stack release that brings general stability improvements and fixe ### Meadow.Core -* Added support for Blazor Server +* Added [Meadow.Blazor](https://developer.wildernesslabs.dev/Meadow/Meadow_Desktop/Meadow_Blazor/) which brings support for Meadow with Blazor Server * Sequential OTA update packages are now correctly cleared from local store after being applied * Analog inputs have been refactored and separated into `IAnalogInputPort` and `IObservableAnalogInputPort` interfaces. If you were using `IAnalogInputPort` before and no longer compile due to missing polling methods, swap to the `IObservalbleAnalogInputPort` interface. * `Meadow.Units` can now be serialized to and deserialized from JSON(`MicroJson` and `System.Text.Json` are supported) diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Ads7128.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Ads7128.md index efbd70c96..6e751b14c 100644 --- a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Ads7128.md +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Ads7128.md @@ -44,4 +44,3 @@ public override async Task Run() [Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads7128/Samples/Ads7128_Sample) - diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Hp4067.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Hp4067.md new file mode 100644 index 000000000..b96ac8b0c --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Hp4067.md @@ -0,0 +1,12 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Hp4067 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Hp4067 +--- + +| Hp4067 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.AnalogMux) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.AnalogMux/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.AnalogMux | + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3001.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3001.md new file mode 100644 index 000000000..5771f197d --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3001.md @@ -0,0 +1,66 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Mcp3001 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3001 +--- + +| Mcp3001 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.Mcp3xxx | + ### Code Example + +```csharp +Mcp3001 mcp; + +IObservableAnalogInputPort port; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize"); + + IDigitalOutputPort chipSelectPort = Device.CreateDigitalOutputPort(Device.Pins.D01); + + mcp = new Mcp3001(Device.CreateSpiBus(), chipSelectPort); + + port = mcp.CreateAnalogInputPort(); + + port.Updated += (s, result) => + { + Resolver.Log.Info($"Analog event, new voltage: {result.New.Volts:N2}V, old: {result.Old?.Volts:N2}V"); + }; + + var observer = IObservableAnalogInputPort.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Analog observer triggered; new: {result.New.Volts:n2}V, old: {result.Old?.Volts:n2}V"); + }, + filter: result => + { + if (result.Old is { } oldValue) + { + return (result.New - oldValue).Abs().Volts > 0.1; + } + else { return false; } + } + ); + port.Subscribe(observer); + + return base.Initialize(); +} + +public override Task Run() +{ + Resolver.Log.Info("Run"); + + port.StartUpdating(); + + return Task.CompletedTask; +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Samples/Mcp3001_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3002.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3002.md new file mode 100644 index 000000000..64433b4e8 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3002.md @@ -0,0 +1,66 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Mcp3002 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3002 +--- + +| Mcp3002 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.Mcp3xxx | + ### Code Example + +```csharp +Mcp3202 mcp; + +IObservableAnalogInputPort port; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize"); + + IDigitalOutputPort chipSelectPort = Device.CreateDigitalOutputPort(Device.Pins.D01); + + mcp = new Mcp3202(Device.CreateSpiBus(), chipSelectPort); + + port = mcp.CreateAnalogInputPort(mcp.Pins.CH0, 32, TimeSpan.FromSeconds(1), new Voltage(3.3, Voltage.UnitType.Volts), Mcp3xxx.InputType.SingleEnded); + + port.Updated += (s, result) => + { + Resolver.Log.Info($"Analog event, new voltage: {result.New.Volts:N2}V, old: {result.Old?.Volts:N2}V"); + }; + + var observer = IObservableAnalogInputPort.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Analog observer triggered; new: {result.New.Volts:n2}V, old: {result.Old?.Volts:n2}V"); + }, + filter: result => + { + if (result.Old is { } oldValue) + { + return (result.New - oldValue).Abs().Volts > 0.1; + } + else { return false; } + } + ); + port.Subscribe(observer); + + return base.Initialize(); +} + +public override Task Run() +{ + Resolver.Log.Info("Run"); + + port.StartUpdating(); + + return Task.CompletedTask; +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Samples/Mcp3002_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3004.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3004.md new file mode 100644 index 000000000..5e091482b --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3004.md @@ -0,0 +1,66 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Mcp3004 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3004 +--- + +| Mcp3004 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.Mcp3xxx | + ### Code Example + +```csharp +Mcp3004 mcp; + +IObservableAnalogInputPort port; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize"); + + IDigitalOutputPort chipSelectPort = Device.CreateDigitalOutputPort(Device.Pins.D01); + + mcp = new Mcp3004(Device.CreateSpiBus(), chipSelectPort); + + port = mcp.CreateAnalogInputPort(mcp.Pins.CH0, 32, TimeSpan.FromSeconds(1), new Voltage(3.3, Voltage.UnitType.Volts), Mcp3xxx.InputType.SingleEnded); + + port.Updated += (s, result) => + { + Resolver.Log.Info($"Analog event, new voltage: {result.New.Volts:N2}V, old: {result.Old?.Volts:N2}V"); + }; + + var observer = IObservableAnalogInputPort.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Analog observer triggered; new: {result.New.Volts:n2}V, old: {result.Old?.Volts:n2}V"); + }, + filter: result => + { + if (result.Old is { } oldValue) + { + return (result.New - oldValue).Abs().Volts > 0.1; + } + else { return false; } + } + ); + port.Subscribe(observer); + + return base.Initialize(); +} + +public override Task Run() +{ + Resolver.Log.Info("Run"); + + port.StartUpdating(); + + return Task.CompletedTask; +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Samples/Mcp3004_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3008.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3008.md new file mode 100644 index 000000000..465c0d83f --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3008.md @@ -0,0 +1,66 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Mcp3008 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3008 +--- + +| Mcp3008 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.Mcp3xxx | + ### Code Example + +```csharp +Mcp3008 mcp; + +IObservableAnalogInputPort port; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize"); + + IDigitalOutputPort chipSelectPort = Device.CreateDigitalOutputPort(Device.Pins.D01); + + mcp = new Mcp3008(Device.CreateSpiBus(), chipSelectPort); + + port = mcp.CreateAnalogInputPort(mcp.Pins.CH0, 32, TimeSpan.FromSeconds(1), new Voltage(3.3, Voltage.UnitType.Volts), Mcp3xxx.InputType.SingleEnded); + + port.Updated += (s, result) => + { + Resolver.Log.Info($"Analog event, new voltage: {result.New.Volts:N2}V, old: {result.Old?.Volts:N2}V"); + }; + + var observer = IObservableAnalogInputPort.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Analog observer triggered; new: {result.New.Volts:n2}V, old: {result.Old?.Volts:n2}V"); + }, + filter: result => + { + if (result.Old is { } oldValue) + { + return (result.New - oldValue).Abs().Volts > 0.1; + } + else { return false; } + } + ); + port.Subscribe(observer); + + return base.Initialize(); +} + +public override Task Run() +{ + Resolver.Log.Info("Run"); + + port.StartUpdating(); + + return Task.CompletedTask; +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Samples/Mcp3008_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3201.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3201.md new file mode 100644 index 000000000..e3822501a --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3201.md @@ -0,0 +1,68 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Mcp3201 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3201 +--- + +| Mcp3201 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.Mcp3xxx | + ### Code Example + +```csharp +Mcp3201 mcp; + +IObservableAnalogInputPort port; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize"); + + IDigitalOutputPort chipSelectPort = Device.CreateDigitalOutputPort(Device.Pins.D14); + + mcp = new Mcp3201(Device.CreateSpiBus(), chipSelectPort); + + port = mcp.CreateAnalogInputPort(); + + port.Updated += (s, result) => + { + Resolver.Log.Info($"Analog event, new voltage: {result.New.Volts}V, old: {result.Old?.Volts}V"); + }; + + var observer = IObservableAnalogInputPort.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Analog observer triggered; new: {result.New.Volts}V, old: {result.Old?.Volts}V"); + }, + filter: result => + { + if (result.Old is { } oldValue) + { + return (result.New - oldValue).Abs().Volts > 0.1; + } + else { return false; } + } + ); + port.Subscribe(observer); + + return base.Initialize(); +} + +public override Task Run() +{ + Resolver.Log.Info("Run"); + + port.StartUpdating(); + + Resolver.Log.Info("Run complete"); + + return Task.CompletedTask; +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Samples/Mcp3201_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3202.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3202.md new file mode 100644 index 000000000..d6c154256 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3202.md @@ -0,0 +1,66 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Mcp3202 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3202 +--- + +| Mcp3202 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.Mcp3xxx | + ### Code Example + +```csharp +Mcp3202 mcp; + +IObservableAnalogInputPort port; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize"); + + IDigitalOutputPort chipSelectPort = Device.CreateDigitalOutputPort(Device.Pins.D01); + + mcp = new Mcp3202(Device.CreateSpiBus(), chipSelectPort); + + port = mcp.CreateAnalogInputPort(mcp.Pins.CH0, 32, TimeSpan.FromSeconds(1), new Voltage(3.3, Voltage.UnitType.Volts), Mcp3xxx.InputType.SingleEnded); + + port.Updated += (s, result) => + { + Resolver.Log.Info($"Analog event, new voltage: {result.New.Volts:N2}V, old: {result.Old?.Volts:N2}V"); + }; + + var observer = IObservableAnalogInputPort.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Analog observer triggered; new: {result.New.Volts:n2}V, old: {result.Old?.Volts:n2}V"); + }, + filter: result => + { + if (result.Old is { } oldValue) + { + return (result.New - oldValue).Abs().Volts > 0.1; + } + else { return false; } + } + ); + port.Subscribe(observer); + + return base.Initialize(); +} + +public override Task Run() +{ + Resolver.Log.Info("Run"); + + port.StartUpdating(); + + return Task.CompletedTask; +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Samples/Mcp3202_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3204.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3204.md new file mode 100644 index 000000000..0acf959c0 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3204.md @@ -0,0 +1,66 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Mcp3204 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3204 +--- + +| Mcp3204 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.Mcp3xxx | + ### Code Example + +```csharp +Mcp3204 mcp; + +IObservableAnalogInputPort port; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize"); + + IDigitalOutputPort chipSelectPort = Device.CreateDigitalOutputPort(Device.Pins.D01); + + mcp = new Mcp3204(Device.CreateSpiBus(), chipSelectPort); + + port = mcp.CreateAnalogInputPort(mcp.Pins.CH0, 32, TimeSpan.FromSeconds(1), new Voltage(3.3, Voltage.UnitType.Volts), Mcp3xxx.InputType.SingleEnded); + + port.Updated += (s, result) => + { + Resolver.Log.Info($"Analog event, new voltage: {result.New.Volts:N2}V, old: {result.Old?.Volts:N2}V"); + }; + + var observer = IObservableAnalogInputPort.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Analog observer triggered; new: {result.New.Volts:n2}V, old: {result.Old?.Volts:n2}V"); + }, + filter: result => + { + if (result.Old is { } oldValue) + { + return (result.New - oldValue).Abs().Volts > 0.1; + } + else { return false; } + } + ); + port.Subscribe(observer); + + return base.Initialize(); +} + +public override Task Run() +{ + Resolver.Log.Info("Run"); + + port.StartUpdating(); + + return Task.CompletedTask; +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Samples/Mcp3204_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3208.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3208.md new file mode 100644 index 000000000..d530f4851 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3208.md @@ -0,0 +1,66 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Mcp3208 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Mcp3208 +--- + +| Mcp3208 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.Mcp3xxx | + ### Code Example + +```csharp +Mcp3208 mcp; + +IObservableAnalogInputPort port; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize"); + + IDigitalOutputPort chipSelectPort = Device.CreateDigitalOutputPort(Device.Pins.D01); + + mcp = new Mcp3208(Device.CreateSpiBus(), chipSelectPort); + + port = mcp.CreateAnalogInputPort(mcp.Pins.CH0, 32, TimeSpan.FromSeconds(1), new Voltage(3.3, Voltage.UnitType.Volts), Mcp3xxx.InputType.SingleEnded); + + port.Updated += (s, result) => + { + Resolver.Log.Info($"Analog event, new voltage: {result.New.Volts:N2}V, old: {result.Old?.Volts:N2}V"); + }; + + var observer = IObservableAnalogInputPort.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Analog observer triggered; new: {result.New.Volts:n2}V, old: {result.Old?.Volts:n2}V"); + }, + filter: result => + { + if (result.Old is { } oldValue) + { + return (result.New - oldValue).Abs().Volts > 0.1; + } + else { return false; } + } + ); + port.Subscribe(observer); + + return base.Initialize(); +} + +public override Task Run() +{ + Resolver.Log.Info("Run"); + + port.StartUpdating(); + + return Task.CompletedTask; +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.Mcp3xxx/Samples/Mcp3208_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Nxp74HC4051.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Nxp74HC4051.md new file mode 100644 index 000000000..ea0d01231 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Nxp74HC4051.md @@ -0,0 +1,57 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Nxp74HC4051 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Nxp74HC4051 +--- + +| Nxp74HC4051 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.AnalogMux) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.AnalogMux/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.AnalogMux | + ### Code Example + +```csharp +private Nxp74HC4051 mux; + +public override Task Initialize() +{ + Resolver.Log.Info("Initialize..."); + + mux = new Nxp74HC4051( + Device.CreateAnalogInputPort(Device.Pins.A00), // input + Device.CreateDigitalOutputPort(Device.Pins.D00), // s0 + Device.CreateDigitalOutputPort(Device.Pins.D01), // s1 + Device.CreateDigitalOutputPort(Device.Pins.D02), // s2 + Device.CreateDigitalOutputPort(Device.Pins.D03) // enable + ); + + return base.Initialize(); +} + +public override Task Run() +{ + Task.Run(ReadRoundRobin); + + return base.Run(); +} + +public async Task ReadRoundRobin() +{ + while (true) + { + for (var channel = 0; channel < 8; channel++) + { + mux.SetInputChannel(channel); + var read = await mux.Signal.Read(); + Resolver.Log.Info($"ADC Channel {channel} = {read.Volts:0.0}V"); + await Task.Delay(1000); + } + } +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.AnalogMux/Samples/Nxp74HC4051_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Nxp74HC4067.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Nxp74HC4067.md new file mode 100644 index 000000000..5e57b1eb3 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Nxp74HC4067.md @@ -0,0 +1,12 @@ +--- +uid: Meadow.Foundation.ICs.ADC.Nxp74HC4067 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.ICs.ADC.Nxp74HC4067 +--- + +| Nxp74HC4067 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.AnalogMux) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.ADC.AnalogMux/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.ICs.ADC.AnalogMux | + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp23017.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp23017.md index 2aaab451b..211372683 100644 --- a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp23017.md +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Mcp23017.md @@ -29,8 +29,8 @@ public override Task Run() { while (true) { - TestBulkDigitalOutputPortWrites(20); - TestDigitalOutputPorts(2); + //TestBulkDigitalOutputPortWrites(20); + TestDigitalOutputPorts(20); } } @@ -45,30 +45,31 @@ private void TestDigitalOutputPorts(int loopCount) var out06 = mcp.CreateDigitalOutputPort(mcp.Pins.GPA6); var out07 = mcp.CreateDigitalOutputPort(mcp.Pins.GPA7); + var out10 = mcp.CreateDigitalOutputPort(mcp.Pins.GPB0); + var out11 = mcp.CreateDigitalOutputPort(mcp.Pins.GPB1); + var out12 = mcp.CreateDigitalOutputPort(mcp.Pins.GPB2); + var out13 = mcp.CreateDigitalOutputPort(mcp.Pins.GPB3); + var out14 = mcp.CreateDigitalOutputPort(mcp.Pins.GPB4); + var out15 = mcp.CreateDigitalOutputPort(mcp.Pins.GPB5); + var out16 = mcp.CreateDigitalOutputPort(mcp.Pins.GPB6); + var out17 = mcp.CreateDigitalOutputPort(mcp.Pins.GPB7); + var outputPorts = new List() { - out00, out01, out02, out03, out04, out05, out06, out07 + out00, out01, out02, out03, out04, out05, out06, out07, + out10, out11, out12, out13, out14, out15, out16, out17 }; - foreach (var outputPort in outputPorts) - { - outputPort.State = true; - } - for (int l = 0; l < loopCount; l++) { - // loop through all the outputs - for (int i = 0; i < outputPorts.Count; i++) + foreach (var outputPort in outputPorts) { - // turn them all off - foreach (var outputPort in outputPorts) - { - outputPort.State = false; - } - - // turn on just one - outputPorts[i].State = true; - Thread.Sleep(250); + Resolver.Log.Info($"{outputPort.Pin.Name} on"); + outputPort.State = true; + Thread.Sleep(500); + Resolver.Log.Info($"{outputPort.Pin.Name} off"); + outputPort.State = false; + Thread.Sleep(500); } } diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Tca9535.md b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Tca9535.md index bd5093b02..202dde15c 100644 --- a/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Tca9535.md +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.ICs.IOExpanders.Tca9535.md @@ -50,4 +50,3 @@ public override async Task Run() [Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Tca95x5/Samples/Tca9535_Sample) - diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.SimulatedT322ai.md b/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.SimulatedT322ai.md new file mode 100644 index 000000000..67f5ef882 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.SimulatedT322ai.md @@ -0,0 +1,12 @@ +--- +uid: Meadow.Foundation.IOExpanders.SimulatedT322ai +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.SimulatedT322ai +--- + +| SimulatedT322ai | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/IOExpanders.T3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/IOExpanders.T3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.IOExpanders.Temco.T3xxx | + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T322ai.md b/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T322ai.md new file mode 100644 index 000000000..5896f1bdd --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T322ai.md @@ -0,0 +1,12 @@ +--- +uid: Meadow.Foundation.IOExpanders.T322ai +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T322ai +--- + +| T322ai | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/IOExpanders.T3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/IOExpanders.T3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.IOExpanders.Temco.T3xxx | + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T38i8o6do.md b/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T38i8o6do.md new file mode 100644 index 000000000..9b026766f --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T38i8o6do.md @@ -0,0 +1,12 @@ +--- +uid: Meadow.Foundation.IOExpanders.T38i8o6do +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.IOExpanders.T38i8o6do +--- + +| T38i8o6do | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/IOExpanders.T3xxx) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/IOExpanders.T3xxx/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.IOExpanders.Temco.T3xxx | + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Ab0805.md b/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Ab0805.md new file mode 100644 index 000000000..e632e8115 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Ab0805.md @@ -0,0 +1,130 @@ +--- +uid: Meadow.Foundation.RTCs.Ab0805 +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Ab0805 +--- + +| Ab0805 | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/RTCs.Ab0805) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/RTCs.Ab0805/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.RTCs.Ab0805 | + ### Code Example + +```csharp +private Ab0805 rtc; + +public override Task Initialize() +{ + Resolver.Log.Info("Initializing..."); + + rtc = new Ab0805(Device.CreateI2cBus()); + + return base.Initialize(); +} + +public override async Task Run() +{ + // Test basic RTC functionality + await TestBasicRTC(); + + // Test countdown timers + await TestCountdownTimers(); +} + +private async Task TestBasicRTC() +{ + Resolver.Log.Info("=== Testing Basic RTC Functionality ==="); + + var running = rtc.IsRunning; + Resolver.Log.Info($"RTC {(running ? "is running" : "is not running")}"); + + if (!running) + { + Resolver.Log.Info("Starting RTC..."); + rtc.IsRunning = true; + } + + var currentTime = rtc.GetTime(); + Resolver.Log.Info($"RTC current time: {currentTime:MM/dd/yy HH:mm:ss}"); + + // Set RTC to a known time for testing + var testTime = new DateTime(2025, 6, 15, 14, 30, 0); + Resolver.Log.Info($"Setting RTC to: {testTime:MM/dd/yy HH:mm:ss}"); + rtc.SetTime(testTime); + + currentTime = rtc.GetTime(); + Resolver.Log.Info($"RTC time after setting: {currentTime:MM/dd/yy HH:mm:ss}"); + + await Task.Delay(2000); + + currentTime = rtc.GetTime(); + Resolver.Log.Info($"RTC time after 2 second delay: {currentTime:MM/dd/yy HH:mm:ss}"); +} + +private async Task TestCountdownTimers() +{ + Resolver.Log.Info("\n=== Testing Countdown Timer Functionality ==="); + + await TestAlarm(); + await Task.Delay(1000); + await TestBasicTimer(); +} + +private async Task TestBasicTimer() +{ + Resolver.Log.Info("\n--- Test 1: Basic 2-second countdown timer ---"); + + rtc.ResetTimer(); + + Resolver.Log.Info("Starting 2-second countdown timer..."); + rtc.StartTimer(5, Ab0805.DelayTimeUnit.Seconds); + + var startTime = DateTime.Now; + TimeSpan elapsed; + + while (rtc.HasTimerEnded == false) + { + elapsed = DateTime.Now - startTime; + Resolver.Log.Info($"Elapsed: {elapsed.TotalSeconds:F1}s"); + + await Task.Delay(1000); + } + + elapsed = DateTime.Now - startTime; + Resolver.Log.Info($"✓ Timer completed! Interrupt fired after {elapsed.TotalSeconds:F1}s"); + rtc.ResetTimer(); +} + +private async Task TestAlarm() +{ + Resolver.Log.Info("\n--- Test 2: Alarm 5 seconds in the future ---"); + + DateTimeOffset alarmTime = rtc.GetTime().AddSeconds(5); + + Resolver.Log.Info("Monitoring alarm..."); + rtc.SetAlarm(alarmTime); + + var startTime = DateTime.Now; + TimeSpan elapsed; + + while (rtc.HasAlarmTriggered == false) + { + elapsed = DateTime.Now - startTime; + Resolver.Log.Info($"Elapsed: {elapsed.TotalSeconds:F1}s"); + + await Task.Delay(1000); + } + + elapsed = DateTime.Now - startTime; + Resolver.Log.Info($"✓ Alarm triggered! Interrupt fired after {elapsed.TotalSeconds:F1}s"); + + await Task.Delay(5000); + rtc.ResetAlarm(); +} + +``` + +[Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/RTCs.Ab0805/Samples/Ab0805_Sample) + + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Pcf8523.md b/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Pcf8523.md index 801ba9085..80b7434ef 100644 --- a/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Pcf8523.md +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.RTCs.Pcf8523.md @@ -23,9 +23,9 @@ public override Task Initialize() return base.Initialize(); } -public override Task Run() +public override async Task Run() { - var dateTime = new DateTimeOffset(); + DateTimeOffset dateTime; var running = rtc.IsRunning; Resolver.Log.Info($"{(running ? "is running" : "is not running")}"); @@ -37,16 +37,42 @@ public override Task Run() } dateTime = rtc.GetTime(); - Resolver.Log.Info($" RTC current time is: {dateTime.ToString("MM/dd/yy HH:mm:ss")}"); + Resolver.Log.Info($" RTC current time is: {dateTime:MM/dd/yy HH:mm:ss}"); - Resolver.Log.Info($" Setting RTC to : {dateTime.ToString("MM/dd/yy HH:mm:ss")}"); dateTime = new DateTime(2030, 2, 15); + Resolver.Log.Info($" Setting RTC to : {dateTime:MM/dd/yy HH:mm:ss}"); rtc.SetTime(dateTime); dateTime = rtc.GetTime(); - Resolver.Log.Info($" RTC current time is: {dateTime.ToString("MM/dd/yy HH:mm:ss")}"); + Resolver.Log.Info($" RTC current time is: {dateTime:MM/dd/yy HH:mm:ss}"); - return base.Run(); + // Test Timer A + Resolver.Log.Info("Setting Timer A for 5 seconds..."); + rtc.SetTimerA(5, DelayTimeUnit.Seconds); + + // Test Timer B + Resolver.Log.Info("Setting Timer B for 2 seconds..."); + rtc.SetTimerB(2, DelayTimeUnit.Seconds); + + await Task.Delay(2000); + + if (rtc.HasTimerAInterruptTriggered) + { + Resolver.Log.Info("Timer A SUCCESS"); + } + else + { + Resolver.Log.Info("Timer A FAILED"); + } + + if (rtc.HasTimerBInterruptTriggered) + { + Resolver.Log.Info("Timer B SUCCESS"); + } + else + { + Resolver.Log.Info("Timer B FAILED"); + } } ``` diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Power.Spm1x.md b/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Power.Spm1x.md new file mode 100644 index 000000000..c18a8d3a3 --- /dev/null +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Power.Spm1x.md @@ -0,0 +1,12 @@ +--- +uid: Meadow.Foundation.Sensors.Power.Spm1x +slug: /docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Power.Spm1x +--- + +| Spm1x | | +|--------|--------| +| Status | Status badge: working | +| Source code | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/Sensors.Power.Spm1x) | +| Datasheet(s) | [GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/Sensors.Power.Spm1x/Datasheet) | +| NuGet package | NuGet Gallery for Meadow.Foundation.Sensors.Power.Spm1x | + diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Temperature.Max6675.md b/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Temperature.Max6675.md index 6252d70aa..4143aac5e 100644 --- a/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Temperature.Max6675.md +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Temperature.Max6675.md @@ -45,4 +45,3 @@ public override async Task Run() [Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Max6675/Samples/Max6675_Sample) - diff --git a/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Temperature.Mlx90614.md b/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Temperature.Mlx90614.md index 0f4b870a8..506acc317 100644 --- a/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Temperature.Mlx90614.md +++ b/docs/api/Meadow.Foundation/Meadow.Foundation.Sensors.Temperature.Mlx90614.md @@ -30,4 +30,3 @@ public override async Task Run() [Sample project(s) available on GitHub](https://github.com/WildernessLabs/Meadow.Foundation/tree/main/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mlx90614/Samples/Mlx90614_Sample) - diff --git a/src/components/GettingStarted.tsx b/src/components/GettingStarted.tsx index dfa1862bb..6d969b0d1 100644 --- a/src/components/GettingStarted.tsx +++ b/src/components/GettingStarted.tsx @@ -69,6 +69,7 @@ export default function GettingStarted(): JSX.Element {
  • Windows
  • Linux
  • Mac
  • +
  • Blazor