在上一篇《遥控篇》文章中,我们介绍了Sony PS2手柄信号的采集和编程,通过简单的封装,以事件的方式向我们提供按键信息。本篇文章主要介绍.NET Micro Framework系统接受到按键信息后,如何驱动小车马达和控制机械手的。

无论是驱动小车马达还是控制机械手,都是通过输出PWM来控制的,只是控制PWM输出的方式有些不同而已,我们先介绍一下小车马达的控制。

由于驱动马达需要相对比较大的电流,所以主芯片的IO是无法直接驱动的,中间需要连接一个驱动器。也就是说主芯片输出PWM控制驱动器,由驱动器输出大电流来驱动马达。

一般情况下一个驱动器可以驱动两路马达,而驱动一个马达一般需要两路信号,通过控制两路PWM的输出,来控制马达的转速和方向。我们这款小车选用的是一个带光电隔离,高功率的一个驱动器,一路马达,需要三路IO控制,其中2路是控制方向,一路输出PWM控制小车的转速。

一个驱动器模块,需要4个GPIO(控制方向)2路PWM,加上一路3V3和GND,共8路,我们采用标准.NET Gadgeteer接口进行连接(10个pin:1个3V3,1个5V,1个GND,7个GPIO通道),可以直接插入凌霄开发板上的两个.NET Gadgeteer接口上,接线显的简单直接(上图所示的两个扁平电缆就是)。

机械手控制就更为容易了,一个舵机三根线,电源(5V),地和信号线(PWM),三个舵机,一共需要3路PWM输出控制。注意电源也需要特别提供。PWM由凌霄开发板IO直接输出。

下面介绍一下.NET Micro Framework的PWM接口函数类。

public class PWM : IDisposable

    {

        public PWM(Cpu.PWMChannel channel, double frequency_Hz, double dutyCycle, bool invert);

        public PWM(Cpu.PWMChannel channel, uint period, uint duration, PWM.ScaleFactor scale, bool invert);

        public uint Duration { get; set; }

        public double DutyCycle { get; set; }

        public double Frequency { get; set; }

        public uint Period { get; set; }

        public void Start();

       public void Stop();

      //… 省略一些非主要函数

   }

两个构造函数,分别介绍一下。

PWM(Cpu.PWMChannel channel, double frequency_Hz, double dutyCycle, bool invert);

channel – 通道,不同的系统,支持的通道个数不同,比如凌霄系统支持16路,应该算比较多的。

frequency_Hz – 频率,单位是Hz,发出脉冲的频率值。

dutyCycle – 占空比, 一个0~1之间的数,表示一个周期中,高电平持续时间和整个周期的比值。

Invert – 信号翻转,高低电平翻转切换,一般底层都没有处理该参数,所以一般设置为false。

public PWM(Cpu.PWMChannel channel, uint period, uint duration, PWM.ScaleFactor scale, bool invert);

channel – 通道。

period – 周期。单位和scale的选项一致。

duration – 高电平持续时间,单位和周期一致。

scale – 周期的时间单位,可以是毫秒、微秒、纳秒,建议选择微秒。

Invert – 信号翻转。

第一个构造函数,一般控制马达用,参数设置显的比较直观。频率可以是1K~250KHz(建议10K左右),通过设置占空比的大小(0就是停止,1就是全速),来进行调速。

第二个构造函数,适合控制舵机用,舵机典型的控制曲线如下:

F就是所谓的周期了,如果我们设置scale为微秒,则可以直接设置为20000,所谓的脉宽就是duration的值,你可以设置为1000~2000之间(不同舵机,这个区域的值会有不同,请根据实际进行调整)。

有了以上的介绍,我们就可以很容易地完成马达驱动和舵机控制了。

A.驱动马达

马达驱动控制参数定义:

 static PWM[] motor_pwm = new PWM[];

    static double[] frequency = new double[] { , , ,  };        

    static double[] dutyCycle = new double[] { , , , };                         

    static bool[] states1 = new bool[] { true, false, true, false, true, false, true, false };

    static bool[] states2 = new bool[] { false, true, false, true, false, true, false, true };

    static OutputPort[] In = new OutputPort[];

马达驱动初始化:

  //初始化马达控制

    //方向IO

    Cpu.Pin[] pins = new Cpu.Pin[] { Mainboard.Gadgeteer.Socket2.Pin4, Mainboard.Gadgeteer.Socket2.Pin5, Mainboard.Gadgeteer.Socket2.Pin6, Mainboard.Gadgeteer.Socket2.Pin7,

                                        Mainboard.Gadgeteer.Socket1.Pin4, Mainboard.Gadgeteer.Socket1.Pin5, Mainboard.Gadgeteer.Socket1.Pin6, Mainboard.Gadgeteer.Socket1.Pin7};           

    for (int i = ; i < In.Length; i++)

    {

        In[i] = new OutputPort(pins[i], false);

    }

    //马达速度PWM输出

    Cpu.PWMChannel[] motor_chanels = new Cpu.PWMChannel[] { Mainboard.PWM.Channel13, Mainboard.PWM.Channel14, Mainboard.PWM.Channel2, Mainboard.PWM.Channel3 };

    for (int i = ; i < motor_pwm.Length; i++)

    {

        motor_pwm[i] = new PWM(motor_chanels[i], frequency[i], dutyCycle[i], false);

        motor_pwm[i].Start();

    }

马达控制:

在Sony PS2的事件代码中,我们填写如下代码:

static void ps2_Click(object sender, PS2.ButtonArgs e)

    {

if(e.key == PS2.Key.RRocker)

        {

            PS2 ps2 = (PS2)sender;

            PS2.ButtonArgs button = ps2.GetButton(PS2.Key.L2);

            if (button.state == ) //L2按下

            {

                byte[] buffer = new byte[] { 0xAA, (byte)e.x, (byte)e.y, 0x55 };

                piPort.Write(buffer, , );

                piPort.Flush();

                //左右旋转

                steering_pwm[].Duration = (UInt32)(durations[] + ( - e.x) * );

                //上下旋转

                steering_pwm[].Duration = (UInt32)(durations[] + ( - e.y) * );

            }

            Else  //L2抬起

            {

                //小车运动

                UInt32[] values = new UInt32[];

                UInt32 x = (UInt32)(System.Math.Abs(e.x - ));

                UInt32 y = (UInt32)(System.Math.Abs(e.y - ));

                for (int i = ; i < values.Length; i++) values[i] = y;

                if (e.y < )

                {

                    //前进

                    for (int i = ; i < In.Length; i++) In[i].Write(states2[i]);

                    //拐弯

                    if (x > )

                    {

                        if (e.x < )

                        {

                            values[] = x;

                            values[] = x;

                        }

                        else

                        {

                            values[] = x;

                            values[] = x;

                        }

                    }

                }

                else

                {

                    //后退

                    for (int i = ; i < In.Length; i++) In[i].Write(states1[i]);

                    //拐弯

                    if (x > )

                    {

                        if (e.x < )

                        {

                            values[] = x;

                            values[] = x;

                        }

                        else

                        {

                            values[] = x;

                            values[] = x;

                        }

                    }

                }

                //设置占空比

                for (int i = ; i < motor_pwm.Length; i++) motor_pwm[i].DutyCycle = (values[i] / 128.0);

            }

        }

    }      

B、驱动舵机

舵机参数定义:

static PWM[] steering_pwm = new PWM[];

    static UInt32[] periods = new UInt32[] { , , , ,  };//周期        static UInt32[] durations = new UInt32[] { 1390, 1500, 1390, 1550, 1420 };   //脉宽

舵机初始化:

Cpu.PWMChannel[] steering_chanels = new Cpu.PWMChannel[] { Mainboard.PWM.Channel8, Mainboard.PWM.Channel9, Mainboard.PWM.Channel6, Mainboard.PWM.Channel0, Mainboard.PWM.Channel4 };

    for (int i = ; i < steering_pwm.Length; i++)

    {

        steering_pwm[i] = new PWM(steering_chanels[i], periods[i], durations[i], PWM.ScaleFactor.Microseconds, false);

        steering_pwm[i].Start();

    }

舵机控制:

static void ps2_Click(object sender, PS2.ButtonArgs e)

    {

       if (e.key == PS2.Key.LRocker) //左摇杆事件

        {

            //控制机械臂左右旋转

            steering_pwm[].Duration = (UInt32)(durations[] + ( - e.x) * );

            //控制机械臂上下旋转

            steering_pwm[].Duration = (UInt32)(durations[] + ( - e.y) * );

        }

        else if (e.key == PS2.Key.R2)  //按下右R2键

        {

            //打开钳子

            value += ; if (value > ) value = ;

            steering_pwm[].Duration = (UInt32)(durations[] + (value - ) * );

        }

        else if (e.key == PS2.Key.R1)  //按下右R1键

        {  

            //闭合钳子

            value -= ;if (value < ) value = ;

            steering_pwm[].Duration = (UInt32)(durations[] + (value - ) * );

        }

     }

C、视频演示

视频链接:http://v.youku.com/v_show/id_XNjY2MTE1NjQ0.html

文章导航:

1、【树莓派+.NET MF打造视频监控智能车】遥控篇

2、【树莓派+.NET MF打造视频监控智能车】控制篇(.NET MF)

3、【树莓派+.NET MF打造视频监控智能车】控制篇(树莓派)

4、【树莓派+.NET MF打造视频监控智能车】视频篇

小结:

1、 .NET Micro Framework PWM类的设计,非常符合用户的认知和使用习惯,可以非常方便地实现相应功能。

2、 通过VS2010/VS2012在线调试,可以快速地测试出合适的控制值。

3、 以上代码大概十几分钟就可以完成,充分体现了.NET Micro Framework快速开发的特性。

【树莓派+.NET MF打造视频监控智能车】控制篇(.NET MF)的更多相关文章

  1. 【树莓派+.NET MF打造视频监控智能车】控制篇(树莓派)

    对已经具备一定Linux基础的人来说,树莓派学习起来应该非常简单自然.在他们眼中,树莓派就是一个简易版的,卡通版的Linux而已.但是对我这样一个早已习惯微软技术生态系统的人或者初学者来说,要实现一个 ...

  2. 【树莓派+.NET MF打造视频监控智能车】遥控篇

    树莓派是最近比较火热的开源硬件,其设备只有信用卡大小,运行着Linux系统,专为学生编程教育而设计.我十多年的技术路线基本以学习微软的技术为主,中间也曾试图学习过linux,但是相对陡峭的学习曲线,只 ...

  3. 深度 | AI芯片之智能边缘计算的崛起——实时语言翻译、图像识别、AI视频监控、无人车这些都需要终端具有较强的计算能力,从而AI芯片发展起来是必然,同时5G网络也是必然

    from:https://36kr.com/p/5103044.html 到2020年,大多数先进的ML袖珍电脑(你仍称之为手机)将有能力执行一整套任务.个人助理将变的更加智能,它是打造这种功能的切入 ...

  4. 【miscellaneous】监狱智能视频监控系统设计解决方案

    监狱智能视频监控系统设计解决方案 一.系统概况 随着司法监狱管理系统内视频监控系统的日益发展,现有的被动式人工监控这一传统模式已无法满足新形势下的监管工作需求,尤其是现在靠轮询的视频监控方式,无法对突 ...

  5. 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 开源倾情奉献系列链接 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码 开源倾 ...

  6. 基于.NET打造IP智能网络视频监控系统

    开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码   开源倾情奉献系列链接 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码 开源倾情奉献:基于.NET打造 ...

  7. 【miscellaneous】监狱安防系统智能视频监控系统设计方案

    1监狱安防新需求 随着司法监狱管理系统内视频监控系统的日益发展,现有的被动式人工监控这一传统模式已无法满足新形势下的监管工作需求,尤其是现在靠轮询的视频监控方式,无法对突发恶性事件做到第一时间的防御和 ...

  8. 【miscellaneous】华为智能视频监控系统设计解决方案

    [导读] 近年来,随着经济的快速增长.社会的迅速进步,校园.工厂园区.中小企业.楼宇等领域对安全防范和现场记录报警系统的需求与日俱增,视频监控在工作.生活各方面得到了非常广泛的应用. 1.中小型视频监 ...

  9. 基于Spring4+SpringMVC4+Mybatis3+Hibernate4+Junit4框架构建高性能企业级的部标1077视频监控平台

    开发企业级的部标GPS监控平台,投入的开发力量很大,开发周期也很长,选择主流的开发语言以及成熟的开源技术框架来构建基础平台,是最恰当不过的事情,在设计之初就避免掉了技术选型的风险,避免以后在开发过程中 ...

随机推荐

  1. SVG.js 基础图形绘制整理(一)

    一.矩形 //指定width和height 画矩形 //返回rect对象 var draw = SVG('svg1').size(300, 300); var rect = draw.rect(100 ...

  2. java的mock测试框架

    无论是敏捷开发.持续交付,还是测试驱动开发(TDD)都把单元测试作为实现的基石.随着这些先进的编程开发模式日益深入人心,单元测试如今显得越来越重要了.在敏捷开发.持续交付中要求单元测试一定要快(不能访 ...

  3. Java多线程知识-Callable和Future

    Callable和Future出现的原因 创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需 ...

  4. Spring Boot工程结构推荐程结构(最佳实践)

    工程结构(最佳实践) Spring Boot框架本身并没有对工程结构有特别的要求,但是按照最佳实践的工程结构可以帮助我们减少可能会遇见的坑,尤其是Spring包扫描机制的存在,如果您使用最佳实践的工程 ...

  5. 存储过程参数CHAR传过来null导致超时.

    调用的时候不要传NULL,可以传 '' ALTER PROCEDURE [dbo].[up_UC_GetUCExecuteEPList]          @Code VARCHAR(3) ,--ch ...

  6. 洛谷P1284 三角形牧场

    题目描述 和所有人一样,奶牛喜欢变化.它们正在设想新造型的牧场.奶牛建筑师Hei想建造围有漂亮白色栅栏的三角形牧场.她拥有N(3≤N≤40)块木板,每块的长度Li(1≤Li≤40)都是整数,她想用所有 ...

  7. Java学习笔记——File类文件管理及IO读写、复制操作

    File类的总结: 1.文件和文件夹的创建 2.文件的读取 3.文件的写入 4.文件的复制(字符流.字节流.处理流) 5.以图片地址下载图片 文件和文件夹 相关函数  (boolean) mkdir( ...

  8. 为sharepoint的内部页面添加后台代码

    我们知道,存储在数据库里的SharePoint页面是不能直接添加后台代码的,这给我们带来了很多的不方便,比如想要在页面上实现一些东西,都必 须使用Webpart或者自定义控件的方式,哪怕仅仅是很简单的 ...

  9. AI 经典书单 | 人工智能学习该读哪些书

    转载 2018年01月16日 00:00:00   人工智能相关岗位中,涉及到的内容包含: 算法.深度学习.机器学习.自然语言处理.数据结构.Tensorflow.Python .数据挖掘.搜索开发. ...

  10. Wide and Deep Learning Model

    https://blog.csdn.net/starzhou/article/details/78845931 The Wide and Deep Learning Model(译文+Tensorlf ...