Skip to content

Commit 9e89765

Browse files
authored
Add MoveHub Support with Internal Motor and Tilt Sensor (#134)
* Added support for MoveHub * Added example for MoveHub * Renamed DeviceTypes and HubType for MoveHub for clarity * Changed MoveHub Tilt Sensor to disable percentage and removed workaround on port value single encoder when percentage was bigger than an sbyte * No calibration support (unclear behavior, safer for now) * Add support for Virtual Port AttachedHubIO messages during device connection Co-authored-by: cornelius munz <cornelius.munz@gmx.de
1 parent 1da1b1a commit 9e89765

21 files changed

+624
-10
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using SharpBrick.PoweredUp;
4+
5+
namespace Example
6+
{
7+
public class ExampleMoveHubColors : BaseExample
8+
{
9+
public override async Task ExecuteAsync()
10+
{
11+
using (var moveHub = Host.FindByType<MoveHub>())
12+
{
13+
await moveHub.RgbLight.SetRgbColorsAsync(0x00, 0xff, 0x00);
14+
15+
await Task.Delay(2000);
16+
17+
await moveHub.RgbLight.SetRgbColorsAsync(0xff, 0x00, 0x00);
18+
19+
await Task.Delay(2000);
20+
21+
await moveHub.SwitchOffAsync();
22+
}
23+
}
24+
}
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Threading.Tasks;
2+
using SharpBrick.PoweredUp;
3+
4+
namespace Example
5+
{
6+
public class ExampleMoveHubExternalMediumLinearMotorControl : BaseExample
7+
{
8+
public override async Task ExecuteAsync()
9+
{
10+
using (var moveHub = Host.FindByType<MoveHub>())
11+
{
12+
// This is if you have a linear motor plugged into port D (ie. R2D2)
13+
var externalMotor = moveHub.D.GetDevice<MediumLinearMotor>();
14+
15+
await externalMotor.SetAccelerationTimeAsync(3000);
16+
await externalMotor.SetDecelerationTimeAsync(1000);
17+
await externalMotor.StartSpeedForTimeAsync(2000, 90, 100, SpecialSpeed.Hold, SpeedProfiles.AccelerationProfile | SpeedProfiles.DecelerationProfile);
18+
19+
await Task.Delay(50000);
20+
21+
await moveHub.SwitchOffAsync();
22+
}
23+
}
24+
}
25+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System.Threading.Tasks;
2+
using SharpBrick.PoweredUp;
3+
4+
namespace Example
5+
{
6+
public class ExampleMoveHubInternalTachoMotorControl : BaseExample
7+
{
8+
public override async Task ExecuteAsync()
9+
{
10+
using (var moveHub = Host.FindByType<MoveHub>())
11+
{
12+
var internalMotor = moveHub.MotorAtAB;
13+
await internalMotor.StartSpeedAsync(50, 100);
14+
await internalMotor.StartSpeedForTimeAsync(2000, 90, 100, SpecialSpeed.Hold, SpeedProfiles.AccelerationProfile | SpeedProfiles.DecelerationProfile);
15+
16+
await Task.Delay(3000);
17+
await internalMotor.StopByBrakeAsync();
18+
19+
var leftMotor = moveHub.LeftMotorAtB;
20+
var rightMotor = moveHub.RightMotorAtA;
21+
await leftMotor.StartSpeedAsync(10, 100);
22+
await leftMotor.StartSpeedForTimeAsync(1000, 10, 100, SpecialSpeed.Hold, SpeedProfiles.AccelerationProfile | SpeedProfiles.DecelerationProfile);
23+
await rightMotor.StartSpeedAsync(90, 100);
24+
await rightMotor.StartSpeedForTimeAsync(1000, 90, 100, SpecialSpeed.Hold, SpeedProfiles.AccelerationProfile | SpeedProfiles.DecelerationProfile);
25+
26+
await Task.Delay(2000);
27+
28+
await leftMotor.StopByBrakeAsync();
29+
await rightMotor.StopByBrakeAsync();
30+
31+
await moveHub.SwitchOffAsync();
32+
}
33+
}
34+
}
35+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Microsoft.Extensions.Logging;
4+
using SharpBrick.PoweredUp;
5+
6+
namespace Example
7+
{
8+
public class ExampleMoveHubTiltSensor : BaseExample
9+
{
10+
public override async Task ExecuteAsync()
11+
{
12+
using (var moveHub = Host.FindByType<MoveHub>())
13+
{
14+
var device = moveHub.TiltSensor;
15+
await device.TiltConfigOrientationAsync(TiltConfigOrientation.Front);
16+
17+
// Note that you can only have 1 notification running at a time
18+
19+
await device.SetupNotificationAsync(device.ModeIndexTwoAxisFull, true, 1);
20+
using var twoAxisFullSubscription = device.TwoAxisFullObservable.Subscribe(x => Log.LogWarning($"Two Axis Values - Roll: {x.roll}, Pitch: {x.pitch}"));
21+
22+
Console.WriteLine("Press any key to continue");
23+
Console.ReadKey();
24+
25+
await device.SetupNotificationAsync(device.ModeIndexTwoAxisState, true, 1);
26+
using var twoAxisStateSubscription = device.TwoAxisStateObservable.Subscribe(x => Log.LogWarning($"Two Axis State: {x}"));
27+
28+
Console.WriteLine("Press any key to continue");
29+
Console.ReadKey();
30+
31+
await device.SetupNotificationAsync(device.ModeIndexThreeAxisState, true, 1);
32+
using var threeAxisStateSubscription = device.ThreeAxisStateObservable.Subscribe(x => Log.LogWarning($"Three Axis State: {x}"));
33+
34+
Console.WriteLine("Press any key to continue");
35+
Console.ReadKey();
36+
37+
await device.SetupNotificationAsync(device.ModeIndexThreeAxisFull, true, 1);
38+
using var threeAxisFullSubscription = device.ThreeAxisFullObservable.Subscribe(x => Log.LogWarning($"Three Axis Values - Roll: {x.roll}, Pitch: {x.pitch}, Yaw: {x.yaw}"));
39+
40+
Console.WriteLine("Press any key to continue");
41+
Console.ReadKey();
42+
43+
// This configures a minimum threshold for an impact to be registered (should be a light tap) and subscribes to the count of impacts
44+
await device.TiltConfigImpactAsync(10, 1270);
45+
await device.SetupNotificationAsync(device.ModeIndexImpacts, true, deltaInterval: 1);
46+
using var impactSubscription = device.ImpactsObservable.Subscribe(x => Log.LogWarning($"Impact Count: {x.SI}"));
47+
48+
Console.WriteLine("Press any key to continue");
49+
Console.ReadKey();
50+
51+
await moveHub.SwitchOffAsync();
52+
}
53+
}
54+
}
55+
}

examples/SharpBrick.PoweredUp.Examples/Program.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Threading.Tasks;
3+
using Example;
34

45
namespace SharpBrick.PoweredUp.Examples
56
{
@@ -43,7 +44,12 @@ static async Task Main(string[] args)
4344
//example = new Example.ExampleMarioAccelerometer();
4445
//example = new Example.ExampleDuploTrainBase();
4546
//example = new Example.ExampleTechnicColorSensor();
46-
example = new Example.ExampleTechnicDistanceSensor();
47+
//example = new Example.ExampleTechnicDistanceSensor();
48+
//example = new Example.ExampleTechnicMediumHubGestSensor();
49+
//example = new Example.ExampleMoveHubInternalTachoMotorControl();
50+
//example = new Example.ExampleMoveHubExternalMediumLinearMotorControl();
51+
//example = new Example.ExampleMoveHubColors();
52+
example = new Example.ExampleMoveHubTiltSensor();
4753

4854
// NOTE: Examples are programmed object oriented style. Base class implements methods Configure, DiscoverAsync and ExecuteAsync to be overwriten on demand.
4955
await example.InitHostAndDiscoverAsync(enableTrace);

src/SharpBrick.PoweredUp/Devices/Current.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,24 @@ public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Ve
7272
0B-00-44-3B-01-04-6D-41-00-00-00
7373
08-00-44-3B-01-05-10-00
7474
0A-00-44-3B-01-80-01-01-04-00
75+
",
76+
(_, _, SystemType.LegoSystem_MoveHub) => @"
77+
0B-00-43-3B-01-02-02-03-00-00-00
78+
05-00-43-3B-02
79+
11-00-44-3B-00-00-43-55-52-20-4C-00-00-00-00-00-00
80+
0E-00-44-3B-00-01-00-00-00-00-00-F0-7F-45
81+
0E-00-44-3B-00-02-00-00-00-00-00-00-C8-42
82+
0E-00-44-3B-00-03-00-00-00-00-00-C0-18-45
83+
0A-00-44-3B-00-04-6D-41-00-00
84+
08-00-44-3B-00-05-10-00
85+
0A-00-44-3B-00-80-01-01-04-00
86+
11-00-44-3B-01-00-43-55-52-20-53-00-00-00-00-00-00
87+
0E-00-44-3B-01-01-00-00-00-00-00-F0-7F-45
88+
0E-00-44-3B-01-02-00-00-00-00-00-00-C8-42
89+
0E-00-44-3B-01-03-00-00-00-00-00-C0-18-45
90+
0A-00-44-3B-01-04-6D-41-00-00
91+
08-00-44-3B-01-05-10-00
92+
0A-00-44-3B-01-80-01-01-04-00
7593
",
7694
_ => throw new NotSupportedException(),
7795
}).Trim().Split("\n").Select(s => BytesStringUtil.StringToData(s));

src/SharpBrick.PoweredUp/Devices/DeviceFactory.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public Type GetTypeFromDeviceType(DeviceType deviceType)
5656
DeviceType.DuploTrainBaseSpeaker => typeof(DuploTrainBaseSpeaker),
5757
DeviceType.DuploTrainBaseColorSensor => typeof(DuploTrainBaseColorSensor),
5858
DeviceType.DuploTrainBaseSpeedometer => typeof(DuploTrainBaseSpeedometer),
59+
DeviceType.MoveHubInternalMotor => typeof(MoveHubInternalMotor),
60+
DeviceType.MoveHubTiltSensor => typeof(MoveHubTiltSensor),
5961
_ => null,
6062
};
6163

@@ -88,6 +90,8 @@ public static DeviceType GetDeviceTypeFromType(Type type)
8890
nameof(DuploTrainBaseSpeaker) => DeviceType.DuploTrainBaseSpeaker,
8991
nameof(DuploTrainBaseColorSensor) => DeviceType.DuploTrainBaseColorSensor,
9092
nameof(DuploTrainBaseSpeedometer) => DeviceType.DuploTrainBaseSpeedometer,
93+
nameof(MoveHubInternalMotor) => DeviceType.MoveHubInternalMotor,
94+
nameof(MoveHubTiltSensor) => DeviceType.MoveHubTiltSensor,
9195
_ => DeviceType.Unknown,
9296
};
9397
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using SharpBrick.PoweredUp.Protocol;
5+
using SharpBrick.PoweredUp.Utils;
6+
7+
namespace SharpBrick.PoweredUp
8+
{
9+
public class MoveHubInternalMotor : TachoMotor, IPoweredUpDevice
10+
{
11+
public MoveHubInternalMotor()
12+
: base()
13+
{ }
14+
public MoveHubInternalMotor(ILegoWirelessProtocol protocol, byte hubId, byte portId)
15+
: base(protocol, hubId, portId)
16+
{ }
17+
18+
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
19+
=> @"
20+
0B-00-43-00-01-0F-03-06-00-07-00
21+
07-00-43-00-02-06-00
22+
11-00-44-00-00-00-50-4F-57-45-52-00-00-00-00-00-00
23+
0E-00-44-00-00-01-00-00-C8-C2-00-00-C8-42
24+
0E-00-44-00-00-02-00-00-C8-C2-00-00-C8-42
25+
0E-00-44-00-00-03-00-00-C8-C2-00-00-C8-42
26+
0A-00-44-00-00-04-50-43-54-00
27+
08-00-44-00-00-05-00-10
28+
0A-00-44-00-00-80-01-00-01-00
29+
11-00-44-00-01-00-53-50-45-45-44-00-00-00-00-00-00
30+
0E-00-44-00-01-01-00-00-C8-C2-00-00-C8-42
31+
0E-00-44-00-01-02-00-00-C8-C2-00-00-C8-42
32+
0E-00-44-00-01-03-00-00-C8-C2-00-00-C8-42
33+
0A-00-44-00-01-04-50-43-54-00
34+
08-00-44-00-01-05-10-10
35+
0A-00-44-00-01-80-01-00-04-00
36+
11-00-44-00-02-00-50-4F-53-00-00-00-00-00-00-00-00
37+
0E-00-44-00-02-01-00-00-B4-C3-00-00-B4-43
38+
0E-00-44-00-02-02-00-00-C8-C2-00-00-C8-42
39+
0E-00-44-00-02-03-00-00-B4-C3-00-00-B4-43
40+
0A-00-44-00-02-04-44-45-47-00
41+
08-00-44-00-02-05-08-08
42+
0A-00-44-00-02-80-01-02-04-00
43+
".Trim().Split("\n").Select(s => BytesStringUtil.StringToData(s));
44+
}
45+
}

0 commit comments

Comments
 (0)