1.舵機原理簡介

控制信号由接收機的通道進入信号調制晶片,獲得直流偏置電壓。它内部有一個基準電路,産生周期為20ms,寬度為1.5ms的基準信号,将獲得的直流偏置電壓與電位器的電壓比較,獲得電壓差輸出。最後,電壓差的正負輸出到電機驅動晶片決定電機的正反轉。當電機轉速一定時,通過級聯減速齒輪帶動電位器旋轉,使得電壓差為0,電機停止轉動。
舵機的控制一般需要一個20ms左右的時基脈沖,該脈沖的高電平部分一般為0.5ms-2.5ms範圍内的角度控制脈沖部分,總間隔為2ms。以180度角度伺服為例,那麼對應的控制關系是這樣的:
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;
2.arduino下位機源碼
相關源碼已壓縮上傳,需要請下載下傳對應附件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<code>#include<Servo.h> //庫檔案</code>
<code>Servo servo1; </code>
<code>static</code> <code>int</code> <code>v=0;</code>
<code>String mycommand=</code><code>""</code><code>;</code>
<code>void</code> <code>setup()</code>
<code> </code><code>{</code>
<code> </code><code>Serial.begin(9600);</code><code>//此處為序列槽設定的波特率 ,可以修改 必須同上位機設定的波特路一緻。</code>
<code> </code><code>servo1.attach(3); </code><code>// 控制的端口是~3号</code>
<code> </code><code>servo1.write(90);</code>
<code> </code><code>}</code>
<code>void</code> <code>loop() </code>
<code> </code><code>{</code>
<code> </code><code>while</code><code>(Serial.available()>0)</code>
<code> </code><code>{</code>
<code> </code><code>mycommand+=</code><code>char</code><code>(Serial.read());</code>
<code> </code><code>delay(2);</code>
<code> </code><code>}</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>m=0;m<mycommand.length();m++) </code><code>// </code>
<code> </code><code>{</code>
<code> </code><code>char</code> <code>ch = mycommand[m]; </code><code>//讀取序列槽資料</code>
<code> </code><code>switch</code><code>(ch)</code>
<code> </code><code>{</code>
<code> </code><code>case</code> <code>'0'</code><code>...</code><code>'9'</code><code>:</code>
<code> </code><code>v = v*10 + ch - </code><code>'0'</code><code>; </code><code>//字元轉換成十進制</code>
<code> </code><code>break</code><code>;</code>
<code> </code><code>case</code> <code>'a'</code><code>: </code><code>//如果資料後帶a,則表示是一号舵機的資料,比如序列槽發送85a</code>
<code> </code><code>//if(v >= 5 || v <= 175 ) </code>
<code> </code><code>servo1.write(v); </code><code>// 讓A從66度旋轉到9度 (可修改角度) </code>
<code> </code><code>//用于設定舵機旋轉角度的語句,可設定的角度範圍是0°到180°,“V”得到所輸入的值而改變角度,比如85a為85度角</code>
<code> </code><code>Serial.println(v+</code><code>"°"</code><code>);</code><code>//舵機角度改變後 發送改變的角度到上位機。</code>
<code> </code><code>v = 0;</code>
<code> </code><code>break</code><code>;</code>
<code> </code><code>}</code>
<code> </code>
<code> </code><code>} </code>
<code> </code><code>mycommand=</code><code>""</code><code>;</code>
<code>}</code>
我選擇我的是arduino Uno,舵機的接線方法是紅色(VCC)端接控制闆的5V處,棕色端接闆子的GND,舵機的橙色線為信号線,接闆子上的3号口;
3.C#上位機源碼及界面
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<code>using</code> <code>System;</code>
<code>using</code> <code>System.Collections.Generic;</code>
<code>using</code> <code>System.ComponentModel;</code>
<code>using</code> <code>System.Data;</code>
<code>using</code> <code>System.Drawing;</code>
<code>using</code> <code>System.Linq;</code>
<code>using</code> <code>System.Text;</code>
<code>using</code> <code>System.Threading.Tasks;</code>
<code>using</code> <code>System.Windows.Forms;</code>
<code>namespace</code> <code>舵機上位機源碼</code>
<code>{</code>
<code> </code><code>public</code> <code>partial </code><code>class</code> <code>Form1 : Form</code>
<code> </code><code>bool</code> <code>open = </code><code>false</code><code>;</code>
<code> </code><code>public</code> <code>delegate</code> <code>void</code> <code>HandleInterfaceUpdataDelegate(</code><code>string</code> <code>text);</code>
<code> </code><code>private</code> <code>HandleInterfaceUpdataDelegate interfaceUpdataHandle;</code>
<code> </code><code>int</code> <code>a;</code>
<code> </code><code>public</code> <code>Form1()</code>
<code> </code><code>{</code>
<code> </code><code>InitializeComponent();</code>
<code> </code><code>}</code>
<code> </code><code>private</code> <code>void</code> <code>Form1_Load(</code><code>object</code> <code>sender, EventArgs e)</code>
<code> </code><code>comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());</code><code>//從系統擷取已有序列槽</code>
<code> </code><code>if</code> <code>(comboBox1.Items.Count > 0)</code>
<code> </code><code>{</code>
<code> </code><code>comboBox1.SelectedIndex = 0;</code><code>//序列槽變量初始化</code>
<code> </code><code>serialPort1.RtsEnable = </code><code>true</code><code>;</code><code>//DataReceived事件委托</code>
<code> </code><code>serialPort1.ReceivedBytesThreshold = 1;</code><code>//設定 DataReceived 事件發生前内部輸入緩沖區中的位元組數</code>
<code> </code><code>serialPort1.DataReceived += </code><code>new</code> <code>System.IO.Ports.SerialDataReceivedEventHandler(</code><code>this</code><code>.serialPort1_DataReceived);</code>
<code> </code><code>comboBox2.SelectedIndex = 6;</code>
<code> </code><code>}</code>
<code> </code><code>else</code>
<code> </code><code>MessageBox.Show(</code><code>"未檢測到裝置\r\n"</code><code>);</code>
<code> </code><code>//監聽序列槽</code>
<code> </code><code>private</code> <code>void</code> <code>serialPort1_DataReceived(</code><code>object</code> <code>sender, System.IO.Ports.SerialDataReceivedEventArgs e)</code>
<code> </code><code>try</code>
<code> </code><code>string</code> <code>text = </code><code>string</code><code>.Empty;</code>
<code> </code><code>byte</code><code>[] result = </code><code>new</code> <code>byte</code><code>[serialPort1.BytesToRead];</code>
<code> </code><code>serialPort1.Read(result, 0, serialPort1.BytesToRead);</code>
<code> </code><code>text = Encoding.UTF8.GetString(result);</code>
<code> </code><code>catch</code>
<code> </code>
<code> </code><code>//序列槽重新整理按鈕</code>
<code> </code><code>private</code> <code>void</code> <code>button2_Click(</code><code>object</code> <code>sender, EventArgs e)</code>
<code> </code><code>comboBox1.Items.Clear();</code>
<code> </code><code>comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());</code>
<code> </code><code>comboBox1.SelectedIndex = 0;</code>
<code> </code><code>MessageBox.Show(</code><code>"未檢測到序列槽\r\n"</code><code>);</code>
<code> </code>
<code> </code><code>//打開序列槽</code>
<code> </code><code>private</code> <code>void</code> <code>btnOpen_Click(</code><code>object</code> <code>sender, EventArgs e)</code>
<code> </code><code>if</code> <code>(open == </code><code>false</code><code>)</code>
<code> </code>
<code> </code><code>if</code> <code>(serialPort1.IsOpen)</code>
<code> </code><code>{</code>
<code> </code><code>MessageBox.Show(</code><code>"序列槽已經打開"</code><code>, </code><code>"提示"</code><code>, MessageBoxButtons.OK, MessageBoxIcon.Information);</code>
<code> </code><code>return</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>//序列槽</code>
<code> </code><code>if</code> <code>(comboBox1.Text == </code><code>string</code><code>.Empty)</code>
<code> </code><code>MessageBox.Show(</code><code>"請選擇序列槽"</code><code>, </code><code>"提示"</code><code>, MessageBoxButtons.OK, MessageBoxIcon.Information);</code>
<code> </code><code>//波特率</code>
<code> </code><code>if</code> <code>(comboBox2.Text == </code><code>string</code><code>.Empty)</code>
<code> </code><code>MessageBox.Show(</code><code>"請選擇波特率"</code><code>, </code><code>"提示"</code><code>, MessageBoxButtons.OK, MessageBoxIcon.Information);</code>
<code> </code><code>serialPort1.BaudRate = </code><code>int</code><code>.Parse(comboBox2.Text);</code>
<code> </code><code>try</code>
<code> </code><code>serialPort1.PortName = comboBox1.SelectedItem.ToString();</code>
<code> </code><code>serialPort1.Open();</code>
<code> </code><code>catch</code>
<code> </code><code>try</code>
<code> </code><code>{</code>
<code> </code><code>comboBox1.SelectedIndex = comboBox1.SelectedIndex + 1;</code>
<code> </code><code>}</code>
<code> </code><code>catch</code>
<code> </code><code>comboBox1.SelectedIndex = 0;</code>
<code> </code><code>serialPort1.Close();</code>
<code> </code><code>btnOpen.Text = </code><code>"關閉"</code><code>;</code>
<code> </code><code>comboBox1.Enabled = </code><code>false</code><code>;</code>
<code> </code><code>comboBox2.Enabled = </code><code>false</code><code>;</code>
<code> </code><code>open = </code><code>true</code><code>;</code>
<code> </code><code>trackBarSend_Scroll(</code><code>this</code><code>, </code><code>null</code><code>);</code>
<code> </code><code>btnReserch.Enabled = </code><code>false</code><code>;</code>
<code> </code><code>btnsend.Enabled = </code><code>true</code><code>;</code>
<code> </code><code>tbxSend.Enabled = </code><code>true</code><code>;</code>
<code> </code><code>trackBarSend.Enabled = </code><code>true</code><code>;</code>
<code> </code><code>pictureBox1.BackColor = Color.Lime;</code>
<code> </code><code>btnOpen.Text = </code><code>"打開"</code><code>;</code>
<code> </code><code>open = </code><code>false</code><code>;</code>
<code> </code><code>comboBox1.Enabled = </code><code>true</code><code>;</code>
<code> </code><code>comboBox2.Enabled = </code><code>true</code><code>;</code>
<code> </code><code>btnReserch.Enabled = </code><code>true</code><code>;</code>
<code> </code><code>btnsend.Enabled = </code><code>false</code><code>;</code>
<code> </code><code>tbxSend.Enabled = </code><code>false</code><code>;</code>
<code> </code><code>trackBarSend.Enabled = </code><code>false</code><code>;</code>
<code> </code><code>pictureBox1.BackColor = Color.Silver;</code>
<code> </code><code>private</code> <code>void</code> <code>trackBarSend_Scroll(</code><code>object</code> <code>sender, EventArgs e)</code>
<code> </code><code>if</code> <code>(serialPort1.IsOpen)</code>
<code> </code><code>a = trackBarSend.Value;</code>
<code> </code><code>string</code> <code>duojiA = trackBarSend.Value.ToString() + </code><code>"a"</code><code>;</code>
<code> </code><code>serialPort1.WriteLine(duojiA);</code>
<code> </code><code>tbxSend.Text = a.ToString(); ; ;</code>
<code> </code><code>private</code> <code>void</code> <code>btnsend_Click(</code><code>object</code> <code>sender, EventArgs e)</code>
<code> </code><code>byte</code><code>[] SendBuf = </code><code>new</code> <code>byte</code><code>[100000];</code>
<code> </code><code>SendBuf = System.Text.Encoding.Default.GetBytes(tbxSend.Text+</code><code>"a"</code><code>);</code>
<code> </code><code>serialPort1.Write(SendBuf, 0, SendBuf.Length);</code>
<code> </code><code>catch</code> <code>(Exception err)</code>
<code> </code><code>serialPort1.Close();</code><code>//如果是寫資料時出錯,此時視窗狀态為開,就應關閉序列槽,防止下次不能使用,序列槽是不能重複打開和關閉的</code>
<code> </code><code>MessageBox.Show(err.ToString(), </code><code>"錯誤"</code><code>);</code>
<code> </code><code>private</code> <code>void</code> <code>tbxSend_ValueChanged(</code><code>object</code> <code>sender, EventArgs e)</code>
<code> </code><code>trackBarSend.Value = (</code><code>int</code><code>)tbxSend.Value;</code>
未連接配接裝置狀态
連接配接裝置後
這是自己做的機械臂控制軟體 相關源碼也有
這是wifi智能小車控制軟體
第一次寫博文,有不好的地方還請多多包涵。