-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
425 additions
and
0 deletions.
There are no files selected for viewing
Binary file added
BIN
+738 KB
Source/Meadow.Foundation.Peripherals/Motors.StepperOnline/Datasheet/BLD-510B_manual.pdf
Binary file not shown.
278 changes: 278 additions & 0 deletions
278
Source/Meadow.Foundation.Peripherals/Motors.StepperOnline/Driver/Controllers/BLD510B.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
using Meadow.Modbus; | ||
using Meadow.Peripherals; | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace Meadow.Foundation.MotorControllers.StepperOnline; | ||
|
||
public class BLD510B : ModbusPolledDevice | ||
{ | ||
public event EventHandler<ErrorConditions> ErrorConditionsChanged; | ||
|
||
private ErrorConditions _lastError; | ||
private ushort _state; | ||
|
||
/// <summary> | ||
/// The default Modbus address for the V10x device. | ||
/// </summary> | ||
public const int DefaultModbusAddress = 1; | ||
|
||
/// <summary> | ||
/// The default baud rate for communication with the V10x device. | ||
/// </summary> | ||
public const int DefaultBaudRate = 9600; | ||
|
||
public BLD510B(ModbusRtuClient client, byte modbusAddress = 0x01, TimeSpan? refreshPeriod = null) | ||
: base(client, modbusAddress, refreshPeriod) | ||
{ | ||
MapHoldingRegistersToField( | ||
startRegister: 0x801b, | ||
registerCount: 1, | ||
fieldName: nameof(_state), | ||
conversionFunction: StateCheckerFunction | ||
); | ||
} | ||
|
||
public async Task<bool> GetStartStopTerminal() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8000, 1); | ||
|
||
return ((r[0] >> 8) & 1) != 0; | ||
} | ||
|
||
public async Task SetStartStopTerminal(bool startEnabled) | ||
{ | ||
var current = (int)(await ReadHoldingRegisters(0x8000, 1))[0]; | ||
if (startEnabled) | ||
{ // set bit 0 | ||
current = current | (1 << 8); | ||
} | ||
else | ||
{ | ||
current = current & ~(1 << 8); | ||
} | ||
await WriteHoldingRegister(0x8000, (ushort)current); | ||
} | ||
|
||
public async Task<RotationDirection> GetDirectionTerminal() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8000, 1); | ||
return ((r[0] >> 9) & 1) == 0 ? RotationDirection.Clockwise : RotationDirection.CounterClockwise; | ||
} | ||
|
||
public async Task SetDirectionTerminal(RotationDirection direction) | ||
{ | ||
int current = ReadHoldingRegisters(0x8000, 1).Result[0]; | ||
if (direction == RotationDirection.Clockwise) | ||
{ // clear bit 1 | ||
current = current & ~(1 << 9); | ||
} | ||
else | ||
{ | ||
current = current | (1 << 9); | ||
} | ||
await WriteHoldingRegister(0x8000, (ushort)current); | ||
} | ||
|
||
public async Task<bool> GetBrakeTerminal() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8000, 1); | ||
return ((r[0] >> 10) & 1) != 0; | ||
} | ||
|
||
public async Task SetBrakeTerminal(bool brakeEnabled) | ||
{ | ||
int current = ReadHoldingRegisters(0x8000, 1).Result[0]; | ||
if (brakeEnabled) | ||
{ // set bit 2 | ||
current = current | (1 << 10); | ||
} | ||
else | ||
{ | ||
current = current & ~(1 << 10); | ||
} | ||
await WriteHoldingRegister(0x8000, (ushort)current); | ||
} | ||
|
||
public async Task<SpeedControl> GetSpeedControl() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8000, 1); | ||
return (SpeedControl)((r[0] >> 11) & 1); | ||
} | ||
|
||
public async Task SetSpeedControl(SpeedControl speedControl) | ||
{ | ||
int current = ReadHoldingRegisters(0x8000, 1).Result[0]; | ||
if (speedControl == SpeedControl.AnalogPot) | ||
{ // clear bit 4 | ||
current = current & ~(1 << 11); | ||
} | ||
else | ||
{ | ||
current = current | (1 << 11); | ||
} | ||
await WriteHoldingRegister(0x8000, (ushort)current); | ||
} | ||
|
||
public async Task<byte> GetNumberOfMotorPolePairs() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8000, 1); | ||
return (byte)(r[0] & 0xff); | ||
} | ||
|
||
public async Task SetNumberOfMotorPolePairs(byte numberOfMotorPolePairs) | ||
{ | ||
var current = (int)(await ReadHoldingRegisters(0x8000, 1))[0]; | ||
current &= 0xff00; | ||
current |= numberOfMotorPolePairs; | ||
// always disable EN if we're doing this operation | ||
current &= ~(1 << 8); | ||
await WriteHoldingRegister(0x8000, (ushort)current); | ||
} | ||
|
||
public async Task<byte> GetStartupTorque() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8002, 1); | ||
return (byte)(r[0] >> 8); | ||
} | ||
|
||
public async Task SetStartupTorque(byte value) | ||
{ | ||
var r = await ReadHoldingRegisters(0x8002, 1); | ||
var current = r[0] & 0x00ff; | ||
current |= value << 8; | ||
await WriteHoldingRegister(0x8002, (ushort)current); | ||
} | ||
|
||
public async Task<byte> GetStartupSpeed() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8002, 1); | ||
return (byte)(r[0] & 0xff); | ||
} | ||
|
||
public async Task SetStartupSpeed(byte value) | ||
{ | ||
var r = await ReadHoldingRegisters(0x8002, 1); | ||
var current = r[0] & 0xff00; | ||
current |= value; | ||
await WriteHoldingRegister(0x8002, (ushort)current); | ||
} | ||
|
||
public async Task<TimeSpan> GetAccelerationTime() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8003, 1); | ||
return TimeSpan.FromSeconds((r[0] >> 8) / 10d); | ||
} | ||
|
||
public async Task SetAccelerationTime(TimeSpan value) | ||
{ | ||
if (value.TotalSeconds < 0 || value.TotalSeconds > 25.5) throw new ArgumentOutOfRangeException(); | ||
var r = await ReadHoldingRegisters(0x8002, 1); | ||
var current = r[0] & 0x00ff; | ||
current |= (byte)(value.TotalSeconds * 10) << 8; | ||
await WriteHoldingRegister(0x8003, (ushort)current); | ||
} | ||
|
||
public async Task<TimeSpan> GetDecelerationTime() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8003, 1); | ||
return TimeSpan.FromSeconds((r[0] & 0xff) / 10d); | ||
} | ||
|
||
public async Task SetDecelerationTime(TimeSpan value) | ||
{ | ||
if (value.TotalSeconds < 0 || value.TotalSeconds > 25.5) throw new ArgumentOutOfRangeException(); | ||
var r = await ReadHoldingRegisters(0x8003, 1); | ||
var current = r[0] & 0xff00; | ||
current |= (byte)(value.TotalSeconds * 10); | ||
await WriteHoldingRegister(0x8003, (ushort)current); | ||
} | ||
|
||
public async Task<byte> GetMaxCurrent() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8004, 1); | ||
return (byte)(r[0] >> 8); | ||
} | ||
|
||
public async Task SetMaxCurrent(byte value) | ||
{ | ||
var r = await ReadHoldingRegisters(0x8004, 1); | ||
var current = r[0] & 0x00ff; | ||
current |= value << 8; | ||
await WriteHoldingRegister(0x8004, (ushort)current); | ||
} | ||
|
||
public async Task<MotorType> GetMotorType() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8004, 1); | ||
return (MotorType)(r[0] & 0xff); | ||
} | ||
|
||
public async Task SetMotorType(MotorType value) | ||
{ | ||
var r = await ReadHoldingRegisters(0x8004, 1); | ||
var current = r[0] & 0xff00; | ||
current |= (int)value; | ||
await WriteHoldingRegister(0x8004, (ushort)current); | ||
} | ||
|
||
/// <summary> | ||
/// The desired speed when using control mode of RS485, this is ignored when control is analog | ||
/// </summary> | ||
public async Task<ushort> GetDesiredSpeed() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8005, 1); | ||
return r[0]; | ||
} | ||
|
||
public async Task SetDesiredSpeed(ushort speed) | ||
{ | ||
// swap endianness | ||
var s = speed << 8 | speed >> 8; | ||
await WriteHoldingRegister(0x8005, (ushort)s); | ||
} | ||
|
||
public async Task<byte> GetModbusAddress() | ||
{ | ||
var r = await ReadHoldingRegisters(0x8007, 1); | ||
return (byte)r[0]; | ||
} | ||
|
||
public async Task SetModbusAddress(byte value) | ||
{ | ||
if (value <= 0 || value > 250) throw new ArgumentOutOfRangeException(); | ||
|
||
await WriteHoldingRegister(0x8007, value); | ||
} | ||
|
||
public async Task<ushort> GetActualSpeed() | ||
{ | ||
ushort[] data; | ||
do | ||
{ | ||
data = await ReadHoldingRegisters(0x8018, 1); | ||
} while (data.Length == 0); | ||
|
||
// swap endianness | ||
return (ushort)(data[0] >> 8 | data[0] << 8); | ||
} | ||
|
||
public ErrorConditions ErrorConditions | ||
{ | ||
get => _lastError; | ||
} | ||
|
||
private object StateCheckerFunction(ushort[] data) | ||
{ | ||
// we use this function to set events | ||
var state = (ErrorConditions)(data[0] >> 8); | ||
|
||
if (state != _lastError) | ||
{ | ||
_lastError = state; | ||
ErrorConditionsChanged?.Invoke(this, state); | ||
} | ||
|
||
return data[0]; | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
Source/Meadow.Foundation.Peripherals/Motors.StepperOnline/Driver/ErrorConditions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System; | ||
|
||
namespace Meadow.Foundation.MotorControllers.StepperOnline; | ||
|
||
[Flags] | ||
public enum ErrorConditions | ||
{ | ||
None = 0x00, | ||
LockedRotor = 0x01, | ||
OverCurrent = 0x02, | ||
HallValueAbnormal = 0x04, | ||
BusVoltageLow = 0x08, | ||
BusVoltageHigh = 0x10, | ||
CurrentPeak = 0x20 | ||
} |
13 changes: 13 additions & 0 deletions
13
...ion.Peripherals/Motors.StepperOnline/Driver/Meadow.Foundation.Motors.StepperOnline.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netstandard2.1</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<LangVersion>11</LangVersion> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\..\..\..\Meadow.Modbus\src\Meadow.Modbus\Meadow.Modbus.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
7 changes: 7 additions & 0 deletions
7
Source/Meadow.Foundation.Peripherals/Motors.StepperOnline/Driver/MotorType.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Meadow.Foundation.MotorControllers.StepperOnline; | ||
|
||
public enum MotorType | ||
{ | ||
Sensored = 0x0f, | ||
Sensorless = 0x10 | ||
} |
Oops, something went wrong.