5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
查看: 12385|回复: 65
打印 上一主题 下一主题

[原创]直接使用计算机控制舵机

[复制链接]
跳转到指定楼层
楼主
发表于 2009-4-13 22:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
                              转载请注明出处
昨晚装FPV机的时候突发奇想,给自己的电脑摄像头上也装个舵机,嘿嘿 远程可以观看自己家里和一切.....
初步实验成功,舵可转向的角度大概有140度的样样子.使用并口控制.接发很简单 看图, 计算机接在 LPT口上
两共根线,其中绿色是地,和舵机的负极接上,  白色接舵机信号线  
控制程序

SteeringCtrl.part1.rar (178 KB, 下载次数: 263)

SteeringCtrl.part2.rar (70.98 KB, 下载次数: 188)


舵机的红线 和地线上 再外接一个 5V电源 驱动舵机动作,也可从USB口取电




操作录像





最后代码送上 



{*******************************************************}
{                                                       }
{       PWM 舵机控制                                   }
{                                                       }
{       版权所有 (C) 2009 笑熬浆糊                      }
{                                                       }
{*******************************************************}
unit clMain;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls,uSteeringCtrl, WinSkinData, Buttons, Spin,
  ComCtrls;
type
  TForm1 = class(TForm)
    Label1: TLabel;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    CheckBox5: TCheckBox;
    CheckBox6: TCheckBox;
    CheckBox7: TCheckBox;
    CheckBox8: TCheckBox;
    CheckBox9: TCheckBox;
    CheckBox10: TCheckBox;
    ScrollBar1: TScrollBar;
    ComboBox1: TComboBox;
    Timer1: TTimer;
    SkinData1: TSkinData;
    CheckBox11: TCheckBox;
    Timer2: TTimer;
    procedure CheckBox1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure CheckBox9Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure CheckBox10Click(Sender: TObject);
    procedure ScrollBar1Change(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ComboBox1Change(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
    procedure CheckBox11Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
  SteeCtrl:TSteeCtrl;
implementation
{$R *.dfm}
procedure TForm1.CheckBox1Click(Sender: TObject);
var
b:BYTE;
begin
    b:=0;
    if CheckBox1.Checked then
    b:=b or $01;
     if CheckBox2.Checked then
    b:=b or $02;
     if CheckBox3.Checked then
    b:=b or $04;
    if CheckBox4.Checked then
    b:=b or $08;
    if CheckBox5.Checked then
    b:=b or $10;
    if CheckBox6.Checked then
    b:=b or $20;
    if CheckBox7.Checked then
    b:=b or $40;
    if CheckBox8.Checked then
    b:=b or $80;
    WritePort($378,b); //写数据端口
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
B:BYTE;
begin
B:=ReadPort($378); //读数据端口
CheckBox1.Checked:=((B or $FE)=$FF);
CheckBox2.Checked:=((B or $FD)=$FF);
CheckBox3.Checked:=((B or $FB)=$FF);
CheckBox4.Checked:=((B or $F7)=$FF);
CheckBox5.Checked:=((B or $EF)=$FF);
CheckBox6.Checked:=((B or $DF)=$FF);
CheckBox7.Checked:=((B or $BF)=$FF);
CheckBox8.Checked:=((B or $7F)=$FF);
end;
procedure TForm1.CheckBox9Click(Sender: TObject);
begin
Timer1.Enabled:=CheckBox9.Checked;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
if InitializeWinIo=False then
begin
  Messagebox(handle,'初始化失败!','提示',MB_OK+MB_IconError)
end;
SteeCtrl:=TSteeCtrl.Create;
SteeCtrl.m_HighTime:=(10/140 *ScrollBar1.Position +4 ) * 100;
Label1.Caption:=Format('角度: %d',[ScrollBar1.Position-70]);
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
SteeCtrl.Suspend;
CanClose:=True;
end;
procedure TForm1.CheckBox10Click(Sender: TObject);
begin
SteeCtrl.Suspended:=CheckBox10.Checked;
end;
procedure TForm1.ScrollBar1Change(Sender: TObject);
begin
SteeCtrl.m_HighTime:=(10/140 *ScrollBar1.Position +4 ) * 100;
Label1.Caption:=Format('角度: %d',[ScrollBar1.Position-70]);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SteeCtrl.Terminate;
ShutdownWinIo;
end;
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
   ScrollBar1.Position:=35*  (ComboBox1.ItemIndex) ;
end;
{$J+}
procedure TForm1.Timer2Timer(Sender: TObject);
const
  Step:Integer=2;
begin
   ScrollBar1.Position := ScrollBar1.Position + Step;
   if (ScrollBar1.Position >= ScrollBar1.Max) or (ScrollBar1.Position<=1) then Step:=0-Step;
end;
procedure TForm1.CheckBox11Click(Sender: TObject);
begin
Timer2.Enabled:=CheckBox11.Checked;
end;
end.




=================================================================

评分

参与人数 1威望 +2 收起 理由
☆奇多☆ + 2 精品文章,感谢分享!

查看全部评分

欢迎继续阅读楼主其他信息

沙发
 楼主| 发表于 2009-4-13 22:58 | 只看该作者




{*******************************************************}
{                                                       }
{       PWM 舵机控制                                   }
{                                                       }
{       版权所有 (C) 2009 笑熬浆糊                      }
{                                                       }
{*******************************************************}

unit uSteeringCtrl;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes,mmsystem;
function  ReadPort(Port:WORD):BYTE;
procedure WritePort(Port:WORD;ConByte:BYTE);
procedure SetSignal(_pos:Integer;const Signal:BOOL=False);
procedure ChannelCtrl(index:Integer);
function InitializeWinIo:Boolean;stdcall;external 'WinIo.dll' name'InitializeWinIo';
function InstallWinIoDriver(pszWinIoDriverPathString;IsDemandLoaded:boolean=false):Boolean;stdcall;external 'WinIo.dll' name 'InstallWinIoDriver';
function RemoveWinIoDriver:Boolean;stdcall;external 'WinIo.dll' name 'RemoveWinIoDriver';
function GetPortVal(PortAddr:WordortValDWord;bSize:Byte):Boolean;stdcall;external 'WinIo.dll' name 'GetPortVal';
function SetPortVal(PortAddr:WordortValWord;bSize:Byte):Boolean;stdcall;external 'WinIo.dll' name 'SetPortVal';
function GetPhysLong(PhysAddrBytehysValDWord):Boolean;stdcall;external 'WinIo.dll' name 'GetPhysLong';
function SetPhysLong(PhysAddrBytehysValWord):Boolean;stdcall;external 'WinIo.dll' name 'SetPhysLong';
function MapPhysToLin(PhysAddrBytehysSizeWordhysMemHandleHandle)Byte;stdcall;external 'WinIo.dll' name 'MapPhysToLin';
function UnMapPhysicalMemory(PhysMemHandle:THandle;LinAddrByte):Boolean;stdcall;external 'WinIo.dll' name 'UnmapPhysicalMemory';
procedure ShutdownWinIo;stdcall;external 'WinIo.dll' name'ShutdownWinIo';

type  
  TSteeCtrl = class(TThread)
  private
    m_LastHighTime: Double ;
  protected
    procedure Execute; override;
  public
    m_HighTime ouble;
   constructor Create;
end;

implementation
constructor TSteeCtrl.Create;
begin
   m_HighTime:=2;
   inherited Create(False);
end;
procedure TSteeCtrl.Execute;
var
   r1,L_Base,L_ALLouble;
   c1:int64;
   t1,t2:int64;
   
begin
  { Place thread code here }
  QueryPerformanceFrequency(c1);//WINDOWS API 返回计数频率(Intel86:1193180)(获得系统的高性能频率计数器在一毫秒内的震动次数)
  L_Base:=0;
  while not Terminated do
  begin
   QueryPerformanceCounter(t1);//WINDOWS API 获取开始计数值
   if (L_Base > 20*1000)  then
     begin
       L_Base:=0;
     end;
       if m_LastHighTime = m_HighTime then
          begin
          if L_ALL> 500*1000  then  //每次动作由 500MS 时间完成,防止抖舵
             begin
               Sleep(1);
               Continue;
             end;
           end
          else
           begin
             L_ALL:=0;
             m_LastHighTime := m_HighTime
           end;
      
     if L_Base < m_HighTime then   //高电平时间
      begin
        SetSignal(1,True);
      end
      else
      begin
        SetSignal(1,False);     //低电平
        sleep(1);
      end;
     QueryPerformanceCounter(t2);//获取结束计数值
     r1:=(t2-t1) / c1*1000000;//取得计时时间,单位微秒
     L_Base:=L_Base+r1;
     L_ALL:=L_ALL+r1;
  end;
end;


function ReadPort(Port:WORD):BYTE;
var
B:BYTE;
begin
ASM
MOV DX, Port;
IN AL, DX;
MOV B, AL;
END;
Result:=B;
end;
procedure WritePort(Port:WORD;ConByte:BYTE);
begin
ASM
MOV DX, Port;
MOV AL, ConByte;
OUT DX, AL;
END;
end;
procedure SetSignal(_pos:Integer;const Signal:BOOL=False);
var
  b:Byte;
begin
   b:=0;
   if Signal then
    begin
       case _pos of  //每位表示一个通道
          1:
          b:=b or $01;
           2:
          b:=b or $02;
           3:
          b:=b or $04;
          4:
          b:=b or $08;
          5:
          b:=b or $10;
          6:
          b:=b or $20;
          7:
          b:=b or $40;
          8:
          b:=b or $80;
       end;
     end;
    WritePort($378,b); //写数据端口
end;  

procedure ys(n:integer);//延时子程序头部说明
  var
   i,j:integer;
  begin
    j:=1;
    while j<N do
    begin
     i:=1;
       while i<100 do  i:=i+1;
     j:=j+1;
    end;
  end;
  
procedure ChannelCtrl(index:Integer);
var
  x,n:Integer;
begin
   for x:=1 to 80 do   {某一舵机位置初始化定位}
   n:=0;
     begin
       //WritePort($378,b):=32; {并行口数据线的第6位置“1”,}
       SetSignal(index,True);
       ys(300);        {调用延时子程序,参数300,观察舵机转动的位置}
       //port[$378]:=0;
       SetSignal(index,False);
       Sleep(20);
     end;
   for x:=300 to 500 do
     begin
      // port[$378]:=32;
      SetSignal(index,True);
       ys(x);   {参数x从300随着循环变量而增加到500,观察舵机转动的位置和方式}
       //port[$378]:=0;
       SetSignal(index,False);
       Sleep(20);
       //delay(20);
     end;
end;  

initialization
end.





{*******************************************************}
{                                                       }
{       PWM 舵机控制                                   }
{                                                       }
{       版权所有 (C) 2009 笑熬浆糊                      }
{                                                       }
{*******************************************************}
program SteeringCtrl;
uses
  Forms,
  clMain in 'clMain.pas' {Form1},
  uSteeringCtrl in 'uSteeringCtrl.pas';
{$R *.res}
begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

[ 本帖最后由 zhude111 于 2009-4-14 11:04 编辑 ]
3
发表于 2009-4-13 23:18 | 只看该作者
不错,平顺些就更好了
4
发表于 2009-4-13 23:57 | 只看该作者
太强了 不顶对不起人民啊
5
发表于 2009-4-14 00:08 | 只看该作者
牛是牛,不知道应用在什么地方呢:em03:
6
发表于 2009-4-14 00:36 | 只看该作者
原帖由 王立刚 于 2009-4-13 23:57 发表
太强了 不顶对不起人民啊

:em26: :loveliness:
7
发表于 2009-4-14 00:43 | 只看该作者
先顶!在看!精华定是好东西
8
发表于 2009-4-14 00:46 | 只看该作者
强! 这种帖子看到必须得顶
9
发表于 2009-4-14 01:24 | 只看该作者
强!:em26: :em26:
10
发表于 2009-4-14 02:50 | 只看该作者
delphi 呵呵,没想到还能这样弄:em05:
11
发表于 2009-4-14 08:07 | 只看该作者
强人啊:em26:
12
发表于 2009-4-14 08:13 | 只看该作者
电脑没并口,搞个USB版本的出来好了
13
发表于 2009-4-14 08:52 | 只看该作者
强大  不懂程序   但是懂顶
14
发表于 2009-4-14 09:04 | 只看该作者
好东西,我顶我顶我顶顶顶~~~~~
15
发表于 2009-4-14 10:01 | 只看该作者
:em07: 真的很有创意
16
发表于 2009-4-14 13:20 | 只看该作者
创意十足,回去试试,是否可行
17
发表于 2009-4-14 13:54 | 只看该作者
接线图看的不是很明白,LZ能不能详细点。谢谢!
18
发表于 2009-4-14 13:59 | 只看该作者
delphi ,haha
19
发表于 2009-4-14 14:20 | 只看该作者
严重的顶!!
20
发表于 2009-4-14 15:14 | 只看该作者
:em26: :funk: :em26:
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /1 下一条

快速回复 返回顶部 返回列表