Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
daf8cb8
Part numbers for small angular motor
mutesplash Jan 17, 2022
76acbb6
3x3 LED part numbers
mutesplash Jan 17, 2022
dc8302c
Add bricklink url to motor
mutesplash Jan 17, 2022
7fea0ed
Note python class used for 3x3
mutesplash Jan 17, 2022
9b94567
Adding Build HAT .NET documentation
Ellerbach Jan 18, 2022
86d7d40
Update compat.adoc
joerk Jan 21, 2022
917e640
Tweak
Feb 3, 2022
924bdd6
Merge pull request #2364 from Ellerbach/adding-build-hat-net
Feb 3, 2022
d9d9d62
Tweak
Feb 3, 2022
8cb83e6
Adding Build HAT .NET documentation
Ellerbach Jan 18, 2022
6b6de39
Merge branch 'dotnet-for-lego' of github.com:raspberrypi/documentatio…
Feb 3, 2022
b881a64
Tweak
Feb 3, 2022
b3c9425
Adding Build HAT .NET documentation
Ellerbach Jan 18, 2022
25fd4b0
Merge branch 'dotnet-for-lego' of github.com:raspberrypi/documentatio…
Feb 3, 2022
8796373
Initial structural changes, started textual changes
Feb 3, 2022
ed60750
Rough cut
Feb 3, 2022
4c5663f
Fix link
Feb 3, 2022
6f01fca
Fix NOTE
Feb 3, 2022
eda92ed
typo
Feb 3, 2022
2d157a8
Reworded
Feb 3, 2022
cacdac1
Reworded
Feb 3, 2022
002af3a
Get rid of 'here' as a link
Feb 3, 2022
3273e0b
Removed not needed header
Feb 3, 2022
0b73642
Tweak header
Feb 3, 2022
30a1349
Fixed up compat table (unrelated fix)
Feb 3, 2022
2ce8559
ccessories/camera/csi-2-usage.adoc : add comma on words
RuffaloLavoisier Feb 4, 2022
158549d
accessories/camera/csi-2-usage.adoc : correct spelling on configure
RuffaloLavoisier Feb 4, 2022
622dae9
accessories/camera/csi-2-usage.adoc : revert words
RuffaloLavoisier Feb 4, 2022
85a85ab
Merge pull request #2403 from RuffaloLavoisier/typo-patch
Feb 4, 2022
87210be
accessories/camera/libcamera_hello.adoc : correct spelling on preceded
RuffaloLavoisier Feb 4, 2022
3f73590
Merge pull request #2404 from RuffaloLavoisier/typo
Feb 4, 2022
dc03b18
Merge pull request #2361 from mutesplash/patch-1
Feb 4, 2022
efb0fe8
Merge branch 'develop' into patch-1
Feb 4, 2022
a636122
Merge pull request #2377 from joerk/patch-1
Feb 4, 2022
8206d56
raspberry-pi-schematics.adoc : correct name on Raspberry Pi Zero 2 W
RuffaloLavoisier Feb 6, 2022
9c1964d
sd-cards.adoc : correct name on Zero 2 W
RuffaloLavoisier Feb 6, 2022
0a8157c
boot-msd.adoc : correct name on Zero 2 W
RuffaloLavoisier Feb 6, 2022
845da38
No network-boot on Zero 2 W
lurch Feb 6, 2022
0670e52
building.adoc : correct case character
RuffaloLavoisier Feb 6, 2022
e754444
Merge pull request #2406 from RuffaloLavoisier/0_2_w
Feb 7, 2022
bcda6dd
Merge pull request #2402 from raspberrypi/dotnet-for-lego
Feb 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions documentation/asciidoc/accessories/build-hat.adoc
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
// Intro

include::build-hat/introduction.adoc[]

include::build-hat/preparing-build-hat.adoc[]

include::build-hat/installing-software.adoc[]
// Python

include::build-hat/py-installing-software.adoc[]

include::build-hat/py-motors.adoc[]

include::build-hat/py-sensors.adoc[]

// .NET

include::build-hat/net-installing-software.adoc[]

include::build-hat/net-brick.adoc[]

include::build-hat/net-motors.adoc[]

include::build-hat/motors.adoc[]
include::build-hat/net-sensors.adoc[]

include::build-hat/sensors.adoc[]
// Close out

include::build-hat/links-to-other.adoc[]

Expand Down
12 changes: 6 additions & 6 deletions documentation/asciidoc/accessories/build-hat/compat.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ SPIKE Prime Expansion Set | 45678, 45680 | Motor | Active | 31

| Medium Angular Motor | White/Cyan | 45603 | Yes | Yes | 45603 | https://www.bricklink.com/v2/catalog/catalogitem.page?S=45603-1#T=S&O={%22iconly%22:0}[Link] | SPIKE Prime Set | 45678 | Motor | Active | 30

| Medium Angular Motor | White/Grey | 6299646, 6359216 | Yes | Yes | 436655 | https://www.bricklink.com/v2/catalog/catalogitem.page?P=54696c01&idColor=86#T=C&C=86[Link] | Mindstorms Robot Inventor | 51515 | Motor | Active | 4B
| Medium Angular Motor | White/Grey | 6299646, 6359216, 6386708 | Yes | Yes | 436655 | https://www.bricklink.com/v2/catalog/catalogitem.page?P=54696c01&idColor=86#T=C&C=86[Link] | Mindstorms Robot Inventor | 51515 | Motor | Active | 4B

| Small Angular Motor | White/Cyan | | Yes| Yes| | | SPIKE Essentials Set| | Motor| Active| 41
| Small Angular Motor | White/Cyan | 45607, 6296520 | Yes| Yes| | https://www.bricklink.com/v2/catalog/catalogitem.page?P=45607c01[Link] | SPIKE Essentials Set| | Motor| Active| 41

| Light/Colour sensor |White/Black | 6217705 |Yes | Yes | | https://www.bricklink.com/v2/catalog/catalogitem.page?P=37308c01&idColor=11#T=C&C=11[Link] | SPIKE Prime Set, SPIKE Prime Expansion Set, Mindstorms Robot Inventor, SPIKE Essentials | 45678, 45680, 51515 | ColorSensor |Active | 3D

| Distance Sensor | White/Black | 6302968 | Yes | Yes | | https://www.bricklink.com/v2/catalog/catalogitem.page?P=37316c01&idColor=11#T=C&C=11[Link] | SPIKE Prime Set, Mindstorms Robot Inventor | 45678, 51515 |DistanceSensor | Active | 3E

| System medium motor | White/Grey | 45303,6138854,6290182,6127110 | Yes | Yes | | | Wedo 2.0, LEGO Ideas Piano, App controlled Batmobile | 76112 | | Passive | 1
| System medium motor | White/Grey | 45303, 6138854, 6290182, 6127110 | Yes | Yes | | | Wedo 2.0, LEGO Ideas Piano, App controlled Batmobile | 76112 | | Passive | 1

| Force Sensor | White/Black | 6254354 | Yes | Yes | 45606 | https://www.bricklink.com/v2/catalog/catalogitem.page?P=37312c01&idColor=11#T=C&C=11[Link] | SPIKE Prime Set | 45678 | ForceSensor | Active | 3F

| 3×3 LED | White/Cyan | | Yes | Yes | | | SPIKE Essentials | | | Active | 40
| 3×3 LED | White/Cyan | 45608, 6297023 | Yes | Yes | | https://www.bricklink.com/v2/catalog/catalogitem.page?P=45608c01[Link] | SPIKE Essentials | | Matrix | Active | 40

| System train motor | Black | 88011 | Yes | Yes | 28740, 88011-1 | https://www.bricklink.com/v2/catalog/catalogitem.page?S=88011-1#T=S&O={%22iconly%22:0}[Link] | Cargo Train, Disney Train and Station, Passenger Train| | | Passive | 2

Expand All @@ -39,8 +39,8 @@ SPIKE Prime Expansion Set | 45678, 45680 | Motor | Active | 31

| Colour + distance sensor | White/Grey | 88007 | Partial | ? | 26912 | https://www.bricklink.com/v2/catalog/catalogitem.page?S=88007-1#T=S&O={%22iconly%22:0}[Link] | | | | Active | 25

| WeDo 2.0 Motion sensor | White/Grey | 45304 | | | 5003423-1| https://www.bricklink.com/v2/catalog/catalogitem.page?S=9583-1#T=S&O={%22iconly%22:0}}[Link] | | | | Active | 35
| WeDo 2.0 Motion sensor | White/Grey | 45304, 6138855 | | | 5003423-1| https://www.bricklink.com/v2/catalog/catalogitem.page?S=9583-1#T=S&O={%22iconly%22:0}}[Link] | | | | Active | 35

| WeDo 2.0 Tilt sensor | White/Grey | 45305 | | | 5003423-1 | https://www.bricklink.com/v2/catalog/catalogitem.page?S=9584-1#T=S&O={%22iconly%22:0}[Link] | | | | Active | 34
| WeDo 2.0 Tilt sensor | White/Grey | 45305, 6138856 | | | 5003423-1 | https://www.bricklink.com/v2/catalog/catalogitem.page?S=9584-1#T=S&O={%22iconly%22:0}[Link] | | | | Active | 34

|===
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.
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.
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.
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.
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.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ You can download documentation on the,
* https://datasheets.raspberrypi.com/build-hat/build-hat-serial-protocol.pdf[Raspberry Pi Build HAT Serial Protocol]
* https://datasheets.raspberrypi.com/build-hat/build-hat-python-library.pdf[Raspberry Pi Build HAT Python Library]

and full details of the Python Library documentation can also be found https://buildhat.readthedocs.io/[on ReadTheDocs].
and full details of the Python Library documentation can also be found https://buildhat.readthedocs.io/[on ReadTheDocs]. You can find more information on the .NET library in the https://github.com/dotnet/iot/tree/main/src/devices/BuildHat[.NET IoT] Github repository.

You can also follow along with projects from the Raspberry Pi Foundation,

Expand Down
114 changes: 114 additions & 0 deletions documentation/asciidoc/accessories/build-hat/net-brick.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
=== Using the Build HAT from .NET

The Raspberry Pi Built HAT is refered to "Brick" in LEGO® parlance and you can talk directly to it from .NET using the https://datasheets.raspberrypi.com/build-hat/build-hat-serial-protocol.pdf[Build HAT Serial Protocol].

You can create a `brick` object as below,

[csharp]
----
Brick brick = new("/dev/serial0");
----

but you need to remember to dispose of the `brick` at the end of your code.

[csharp]
----
brick.Dispose();
----

WARNING: If you do not call `brick.Dispose()` you program will not terminate.

If you want to avoid calling `brick.Dispose` at the end, then create your brick with the `using` statement:

[csharp]
----
using Brick brick = new("/dev/serial0");
----

In this case, when reaching the end of the program, your brick will be automatically disposed.

==== Displaying the information

You can gather the various software versions, the signature, and the input voltage:

[csharp]
----
var info = brick.BuildHatInformation;
Console.WriteLine($"version: {info.Version}, firmware date: {info.FirmwareDate}, signature:");
Console.WriteLine($"{BitConverter.ToString(info.Signature)}");
Console.WriteLine($"Vin = {brick.InputVoltage.Volts} V");
----

NOTE: the input voltage is read only once at boot time and is not read again afterwards.

==== Getting sensors and motors details

The functions `GetSensorType`, `GetSensor` will allow you to retrieve any information on connected sensor.

[csharp]
----
SensorType sensor = brick.GetSensorType((SensorPort)i);
Console.Write($"Port: {i} {(Brick.IsMotor(sensor) ? "Sensor" : "Motor")} type: {sensor} Connected: ");
----

In this example, you can as well use the `IsMotor` static function to check if the connected element is a sensor or a motor.

[csharp]
----
if (Brick.IsActiveSensor(sensor))
{
ActiveSensor activeSensor = brick.GetActiveSensor((SensorPort)i);
}
else
{
var passive = (Sensor)brick.GetSensor((SensorPort)i);
Console.WriteLine(passive.IsConnected);
}
----

`ActiveSensor` have a collection of advanced properties and functions allowing to understand every element of the sensor. It is also possible to call the primitive functions from the brick from them. This will allow you to select specific modes and do advance scenarios. While this is possible, motor and sensor classes have been created to make your life easier.

==== Events

Most sensors implements events on their special properties. You can simply subscribe to `PropertyChanged` and `PropertyUpdated`. The changed one will be fired when the value is changing while the updated one when there is a success update to the property. Depending on the modes used, some properties may be updated in the background all the time while some others occasionally.

You may be interested only when a color is changing or the position of the motor is changing, using it as a tachometer. In this case, the `PropertyChanged` is what you need!

[csharp]
----
Console.WriteLine("Move motor on Port A to more than position 100 to stop this test.");
brick.WaitForSensorToConnect(SensorPort.PortA);
var active = (ActiveMotor)brick.GetMotor(SensorPort.PortA);
bool continueToRun = true;
active.PropertyChanged += MotorPropertyEvent;
while (continueToRun)
{
Thread.Sleep(50);
}

active.PropertyChanged -= MotorPropertyEvent;
Console.WriteLine($"Current position: {active.Position}, eventing stopped.");

void MotorPropertyEvent(object? sender, PropertyChangedEventArgs e)
{
Console.WriteLine($"Property changed: {e.PropertyName}");
if (e.PropertyName == nameof(ActiveMotor.Position))
{
if (((ActiveMotor)brick.GetMotor(SensorPort.PortA)).Position > 100)
{
continueToRun = false;
}
}
}
----

==== Waiting for initialization

The brick can take long before it initializes. A wait for sensor to be connected has been implemented,

[csharp]
----
brick.WaitForSensorToConnect(SensorPort.PortB);
----

It does as well take a `CancellationToken` if you want to implement advance features like warning the user after some time and retrying.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
== Using the Build HAT from .NET

=== Installing the .NET Framework

The .NET framework from Microsoft is not available via `apt` on Raspberry Pi. However, you can follow the https://docs.microsoft.com/en-us/dotnet/iot/deployment[official instructions] from Microsoft to install the .NET framework. Alternatively, there is a simplified https://www.petecodes.co.uk/install-and-use-microsoft-dot-net-5-with-the-raspberry-pi/[third party route] to get the .NET toolchain on to your Raspberry Pi.

WARNING: The installation script is run as `root`. You should read it first and make sure you understand what it is doing. If you are at all unsure you should follow the https://docs.microsoft.com/en-us/dotnet/iot/deployment[official instructions] manually.

[.bash]
----
$ wget -O - https://raw.githubusercontent.com/pjgpetecodes/dotnet5pi/master/install.sh | sudo bash
----

After installing the .NET framework you also need to install the nuget packages:

[.bash]
----
$ dotnet add package System.Device.Gpio --source https://pkgs.dev.azure.com/dotnet/IoT/_packaging/nightly_iot_builds/nuget/v3/index.json
$ dotnet add package Iot.Device.Bindings --source https://pkgs.dev.azure.com/dotnet/IoT/_packaging/nightly_iot_builds/nuget/v3/index.json
----

You can now create a project and edit it.
128 changes: 128 additions & 0 deletions documentation/asciidoc/accessories/build-hat/net-motors.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
=== Using Motors from .NET

There are two types of motors, the *passive* ones and the *active* ones. Active motors will provide detailed position, absolute position and speed while passive motors can only be controlled with speed.

A common set of functions to control the speed of the motors are available. There are 2 important ones: `SetPowerLimit` and `SetBias`:

[csharp]
----
train.SetPowerLimit(1.0);
train.SetBias(0.2);
----

The accepted values are only from 0.0 to 1.0. The power limit is a convenient ay to reduce in proportion the maximum power.

The bias value sets for the current port which is added to positive motor drive values and subtracted from negative motor drive values. This can be used to compensate for the fact that most DC motors require a certain amount of drive before they will turn at all.

The default values when a motor is created is 0.7 for the power limit and 0.3 for the bias.

==== Passive Motors

.Train motor, https://www.bricklink.com/v2/catalog/catalogitem.page?S=88011-1&name=Train%20Motor&category=%5BPower%20Functions%5D%5BPowered%20Up%5D#T=S&O={%22iconly%22:0}[Image from Bricklink]
image::images/train-motor.png[Train motor,width="60%"]

The typical passive motor is a train and older Powered Up motors. The `Speed` property can be set and read. It is the target and the measured speed at the same time as those sensors do not have a way to measure them. The value is from -100 to +100.

Functions to control `Start`, `Stop` and `SetSpeed` are also available. Here is a example of how to use it:

[csharp]
----
Console.WriteLine("This will run the motor for 20 secondes incrementing the PWM");
train.SetPowerLimit(1.0);
train.Start();
for (int i = 0; i < 100; i++)
{
train.SetSpeed(i);
Thread.Sleep(250);
}

Console.WriteLine("Stop the train for 2 seconds");
train.Stop();
Thread.Sleep(2000);
Console.WriteLine("Full speed backward for 2 seconds");
train.Start(-100);
Thread.Sleep(2000);
Console.WriteLine("Full speed forward for 2 seconds");
train.Start(100);
Thread.Sleep(2000);
Console.WriteLine("Stop the train");
train.Stop();
----

NOTE: Once the train is started, you can adjust the speed and the motor will adjust accordingly.

==== Active Motors

.Active motor, https://www.bricklink.com/v2/catalog/catalogitem.page?S=88014-1&name=Technic%20XL%20Motor&category=%5BPower%20Functions%5D%5BPowered%20Up%5D#T=S&O={%22iconly%22:0}[Image from Bricklink]
image::images/active-motor.png[Active motor,width="60%"]

Active motors have `Speed`, `AbsolutePosition`, `Position` and `TargetSpeed` as special properties. They are read continuously even when the motor is stopped.

The code snippet shows how to get the motors, start them and read the properties:

[csharp]
----
brick.WaitForSensorToConnect(SensorPort.PortA);
brick.WaitForSensorToConnect(SensorPort.PortD);
var active = (ActiveMotor)brick.GetMotor(SensorPort.PortA);
var active2 = (ActiveMotor)brick.GetMotor(SensorPort.PortD);
active.Start(50);
active2.Start(50);
// Make sure you have an active motor plug in the port A and D
while (!Console.KeyAvailable)
{
Console.CursorTop = 1;
Console.CursorLeft = 0;
Console.WriteLine($"Absolute: {active.AbsolutePosition} ");
Console.WriteLine($"Position: {active.Position} ");
Console.WriteLine($"Speed: {active.Speed} ");
Console.WriteLine();
Console.WriteLine($"Absolute: {active2.AbsolutePosition} ");
Console.WriteLine($"Position: {active2.Position} ");
Console.WriteLine($"Speed: {active2.Speed} ");
}

active.Stop();
active2.Stop();
----

NOTE: You should not forget to start and stop your motors when needed.

Advance features are available for active motors. You can request to move for seconds, to a specific position, a specific absolute position. Here are couple of examples:

[csharp]
----
// From the previous example, this will turn the motors back to their initial position:
active.TargetSpeed = 100;
active2.TargetSpeed = 100;
// First this motor and will block the thread
active.MoveToPosition(0, true);
// Then this one and will also block the thread
active2.MoveToPosition(0, true);
----

Each function allow you to block or not the thread for the time the operation will be performed. Note that for absolute and relative position moves, there is a tolerance of few degrees.

[csharp]
----
brick.WaitForSensorToConnect(SensorPort.PortA);
var active = (ActiveMotor)brick.GetMotor(SensorPort.PortA);
active.TargetSpeed = 70;
Console.WriteLine("Moving motor to position 0");
active.MoveToPosition(0, true);
Console.WriteLine("Moving motor to position 3600 (10 turns)");
active.MoveToPosition(3600, true);
Console.WriteLine("Moving motor to position -3600 (so 20 turns the other way");
active.MoveToPosition(-3600, true);
Console.WriteLine("Moving motor to absolute position 0, should rotate by 90°");
active.MoveToAbsolutePosition(0, PositionWay.Shortest, true);
Console.WriteLine("Moving motor to position 90");
active.MoveToAbsolutePosition(90, PositionWay.Shortest, true);
Console.WriteLine("Moving motor to position 179");
active.MoveToAbsolutePosition(179, PositionWay.Shortest, true);
Console.WriteLine("Moving motor to position -180");
active.MoveToAbsolutePosition(-180, PositionWay.Shortest, true);
active.Float();
----

You can place the motor in a float position, meaning, there are no more constrains on it. This is a mode that you can use when using the motor as a tachometer, moving it and reading the position. If you still have constrains on the motors, you may not be able to move it.
Loading