Skip to content

Commit

Permalink
Merge pull request #1092 from WildernessLabs/feature/stepper-online
Browse files Browse the repository at this point in the history
stepper online motor and controller
  • Loading branch information
adrianstevens authored Jan 8, 2025
2 parents beadcdf + d36308f commit b6766df
Show file tree
Hide file tree
Showing 14 changed files with 1,076 additions and 533 deletions.
Binary file not shown.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Binary file not shown.
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];
}
}
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
}
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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>11</LangVersion>
<AssemblyName>Motors.StepperOnline</AssemblyName>

<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageIcon>icon.png</PackageIcon>
<Authors>Wilderness Labs, Inc</Authors>
<TargetFramework>netstandard2.1</TargetFramework>
<OutputType>Library</OutputType>
<Company>Wilderness Labs, Inc</Company>
<PackageProjectUrl>http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/</PackageProjectUrl>
<PackageId>Meadow.Foundation.Motors.StepperOnline</PackageId>
<RepositoryUrl>https://github.com/WildernessLabs/Meadow.Foundation</RepositoryUrl>
<PackageTags>Meadow.Foundation,Stepper Online,BLDC Motor </PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>Drivers for motors and moto controllers from Stepper Online</Description>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\..\..\Meadow.Modbus\src\Meadow.Modbus\Meadow.Modbus.csproj" />
</ItemGroup>

<ItemGroup>
<None Include=".\Readme.md" Pack="true" PackagePath="" />
<None Include="..\..\..\icon.png" Pack="true" PackagePath="" />
<ProjectReference Include="..\..\..\Meadow.Foundation.Core\Meadow.Foundation.Core.csproj" />
</ItemGroup>
</Project>
Loading

0 comments on commit b6766df

Please sign in to comment.