Windows IoT借助树莓派C#改写步进电机驱动
【摘要】 为了完成一个项目案例,驱动2部步进电机,购买的设备驱动板是和树莓派3B定制的扩展版DRV8825芯片,可以驱动2个电机。整体项目是.net core的根据提供的案例,改写成C#版的。工作硬件准备1、硬件:树莓派3B+32GSD卡,DRV8825扩展版,SM24240两相步进电机2个,12V独立电源2、软件:Windows IoT Core、VS2022展示一下硬件图片,整体组装后还是比较干净...
为了完成一个项目案例,驱动2部步进电机,购买的设备驱动板是和树莓派3B定制的扩展版DRV8825芯片,可以驱动2个电机。整体项目是.net core的根据提供的案例,改写成C#版的。
工作硬件准备
1、硬件:树莓派3B+32GSD卡,DRV8825扩展版,SM24240两相步进电机2个,12V独立电源
2、软件:Windows IoT Core、VS2022
展示一下硬件图片,整体组装后还是比较干净利索。
扩展版,可以通过拨码开关组合支持驱动细分。全部、半步、1/4、1/8、1/16、1/32一共6种细分
电机接口支持3种,但是能同时驱动的就是2部,接口不同但是线路相同的。
根据厂家的Python示例,看到驱动不是用PWM而是用GPIO的高低电平切换,来模拟PWM。
根据代码的语义,用C#重新翻译一下。
在.Net Core下有2种GPIO库,一个是VS开发ID已经集成好的Windows.Devices.Gpio,这里面把Gpio都对象化处理,明显是按照面向对象的方式,每一个Pin都是一个对象。另一个是需要单独引用的System.Device.Gpio,这个库根据说明是微软为了适应IoT各种开发环境特意发布的,功能更强。Gpio通过Controller统一控制,没有把每个GPIO对象化。
Python源码示例
import RPi.GPIO as GPIO
import time
MotorDir = [
'forward',
'backward',
]
ControlMode = [
'hardward',
'softward',
]
class DRV8825():
def __init__(self, dir_pin, step_pin, enable_pin, mode_pins):
self.dir_pin = dir_pin
self.step_pin = step_pin
self.enable_pin = enable_pin
self.mode_pins = mode_pins
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(self.dir_pin, GPIO.OUT)
GPIO.setup(self.step_pin, GPIO.OUT)
GPIO.setup(self.enable_pin, GPIO.OUT)
GPIO.setup(self.mode_pins, GPIO.OUT)
def digital_write(self, pin, value):
GPIO.output(pin, value)
def Stop(self):
self.digital_write(self.enable_pin, 0)
def SetMicroStep(self, mode, stepformat):
"""
(1) mode
'hardward' : Use the switch on the module to control the microstep
'software' : Use software to control microstep pin levels
Need to put the All switch to 0
(2) stepformat
('fullstep', 'halfstep', '1/4step', '1/8step', '1/16step', '1/32step')
"""
microstep = {'fullstep': (0, 0, 0),
'halfstep': (1, 0, 0),
'1/4step': (0, 1, 0),
'1/8step': (1, 1, 0),
'1/16step': (0, 0, 1),
'1/32step': (1, 0, 1)}
print ("Control mode:",mode)
if (mode == ControlMode[1]):
print ("set pins")
self.digital_write(self.mode_pins, microstep[stepformat])
def TurnStep(self, Dir, steps, stepdelay=0.005):
if (Dir == MotorDir[0]):
print ("forward")
self.digital_write(self.enable_pin, 1)
self.digital_write(self.dir_pin, 0)
elif (Dir == MotorDir[1]):
print ("backward")
self.digital_write(self.enable_pin, 1)
self.digital_write(self.dir_pin, 1)
else:
print ("the dir must be : 'forward' or 'backward'")
self.digital_write(self.enable_pin, 0)
return
if (steps == 0):
return
print ("turn step:",steps)
for i in range(steps):
self.digital_write(self.step_pin, True)
time.sleep(stepdelay)
self.digital_write(self.step_pin, False)
time.sleep(stepdelay)
C#改写工作类(1)使用Windows.Devices.Gpio类库
using Recyclable.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Devices.Gpio;
namespace Recyclable.Services
{
internal class DRV8825
{
GpioPin _DirPin;
GpioPin _StepPin;
GpioPin _EnablePin;
List<GpioPin> _ModelPins;
Dictionary<string, int[]> _MicroStep;
/// <summary>
/// 方向引脚
/// </summary>
/// <param name="dirpin">方向引脚13</param>
/// <param name="steppin">步进引脚19</param>
/// <param name="enablepin">使能引脚12</param>
/// <param name="modelpins">细分引脚</param>
public DRV8825(int dirpin, int steppin, int enablepin, int[] modelpins)
{
_MicroStep = new Dictionary<string, int[]>
{
{"fullstep", new int[] {0, 0, 0 } },
{"halfstep", new int[] {1, 0, 0 } },
{"1/4step", new int[] {0, 1, 0 } },
{"1/8step", new int[] {1, 1, 0 } },
{"1/16step", new int[] {0, 0, 1 } },
{"1/32step", new int[] {1, 0, 1 } }
};
var controller = GpioController.GetDefault();
_ModelPins = new List<GpioPin>();
_DirPin = controller.OpenPin(dirpin);
_DirPin.SetDriveMode(GpioPinDriveMode.Output);
_StepPin = controller.OpenPin(steppin);
_StepPin.SetDriveMode(GpioPinDriveMode.Output);
_EnablePin = controller.OpenPin(enablepin);
_EnablePin.SetDriveMode(GpioPinDriveMode.Output);
foreach (var pin in modelpins)
{
controller.TryOpenPin(pin, GpioSharingMode.Exclusive, out GpioPin p, out GpioOpenStatus status);
p.SetDriveMode(GpioPinDriveMode.Output);
_ModelPins.Add(p);
}
}
public void SetMicroStep(ControlMode mode, string stepformat)
{
if (mode == ControlMode.Softward)
{
var format = _MicroStep[stepformat];
for (int i = 0; i < format.Length; i++)
{
_ModelPins[i].Write((GpioPinValue)format[i]);
}
}
}
public void Stop()
{
_EnablePin.Write(GpioPinValue.Low);
}
public async Task TurnStepAsync(MotorDirection dir, int steps, int delay)
{
SetMicroStep(ControlMode.Softward, "fullstep");
_EnablePin.Write(GpioPinValue.High);
if (dir == MotorDirection.Forward)
{
_DirPin.Write(GpioPinValue.Low);
}
else
{
_DirPin.Write(GpioPinValue.High);
}
if (steps > 0)
{
for (int i = 0; i < steps; i++)
{
_StepPin.Write(GpioPinValue.High);
await Task.Delay(delay);
_StepPin.Write(GpioPinValue.Low);
await Task.Delay(delay);
}
}
}
}
}
C#改写工作类(2)使用System.Devices.Gpio类库
using Recyclable.Models;
using System.Collections.Generic;
using System.Device.Gpio;
using System.Threading.Tasks;
namespace Recyclable.Services
{
internal class DRV88252
{
int _DirPin;
int _StepPin;
int _EnablePin;
int[] _ModelPins;
Dictionary<string, int[]> _MicroStep;
GpioController _Controller;
/// <summary>
/// 方向引脚
/// </summary>
/// <param name="dirpin">方向引脚13</param>
/// <param name="steppin">步进引脚19</param>
/// <param name="enablepin">使能引脚12</param>
/// <param name="modelpins">细分引脚</param>
public DRV88252(int dirpin, int steppin, int enablepin, int[] modelpins)
{
_DirPin = dirpin;
_StepPin = steppin;
_EnablePin = enablepin;
_ModelPins = modelpins;
_MicroStep = new Dictionary<string, int[]>
{
{"fullstep", new int[] {0, 0, 0 } },
{"halfstep", new int[] {1, 0, 0 } },
{"1/4step", new int[] {0, 1, 0 } },
{"1/8step", new int[] {1, 1, 0 } },
{"1/16step", new int[] {0, 0, 1 } },
{"1/32step", new int[] {1, 0, 1 } }
};
_Controller = new GpioController(PinNumberingScheme.Logical);
_Controller.OpenPin(_DirPin);
_Controller.SetPinMode(_DirPin, PinMode.Output);
_Controller.OpenPin(_StepPin);
_Controller.SetPinMode(_StepPin, PinMode.Output);
_Controller.OpenPin(_EnablePin);
_Controller.SetPinMode(_EnablePin, PinMode.Output);
Stop();
foreach (var pin in _ModelPins)
{
_Controller.OpenPin(pin);
_Controller.SetPinMode(pin, PinMode.Output);
}
}
public void SetMicroStep(ControlMode mode, string stepformat)
{
if (mode == ControlMode.Softward)
{
var format = _MicroStep[stepformat];
for (int i = 0; i < format.Length; i++)
{
_Controller.Write(_ModelPins[i], (PinValue)format[i]);
}
}
}
public void Stop()
{
_Controller.Write(_EnablePin, PinValue.Low);
}
public async Task TurnStepAsync(MotorDirection dir, int steps, int delay)
{
//SetMicroStep(ControlMode.Softward, "1/32step");
_Controller.Write(_EnablePin, PinValue.High);
if (dir == MotorDirection.Forward)
{
_Controller.Write(_DirPin, PinValue.Low);
}
else
{
_Controller.Write(_DirPin, PinValue.High);
}
if (steps > 0)
{
for (int i = 0; i < steps; i++)
{
_Controller.Write(_StepPin, PinValue.High);
await Task.Delay(delay);
_Controller.Write(_StepPin, PinValue.Low);
await Task.Delay(delay);
}
}
}
}
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)