本猿是球迷动漫迷歌迷军迷,反正就是很迷
今日吃饱了撑在午睡的时候冒出这么一个灵感然后动手造了个近防炮
主要是临近2018珠海航展了我挺激动的
然后就从实验室的边角料里诞生了这么一个
没火控雷达没开火系统没弹药没底座只会转
莫得感情也莫得伤害的近防支架
我们真的有控制系统啦!
江湖规矩,上设计思路:
板子是Arduino UNO的,对应的开发环境自然是Arduino的那个Genuino
两个舵机Servo,一大一小
支架什么的根据自己的模型打造吧(差点忘了我也算模型迷吧,这个系统本来想装在战列舰模型上的,先验证一下)
一开始还想再加个舵机控制橡皮筋发射的
不过感觉加了反正也参不了展,也莫得国家愿意下单预订多少套去对抗YJ系列(而且也打不过)
顺便讲讲舵机怎么连
这种Servo有三根颜色不同的线,一般中间的是红色的,边上有时候是黑线和黄线有时候又是棕线和黄线
颜色更深的一般是黑线一样的GND吧,可以先试试
红线连5V黑线连GND,另外一根则是连到Arduino的一个接口上用于控制
本系统的大舵机控制水平方向上的转动,小舵机控制垂直方向上的倾角
大舵机控制线连到接口9,小舵机连到接口6
用面包板共用5V和GND
然后串口连接到宿主机,待会儿要拿串口通信的(WiFi可以么?当然ojbk,不过串口更可靠,哪有拿WiFi控制这么强悍的武器的)
如果连接正确了,就可以先开发一下开发板程序了:
#include <Servo.h>
Servo myservo; // 大舵机
Servo myservo2; // 小舵机
int pos = 0; // 大舵机角度
int pos2 = 0; // 小舵机角度
String comdata = ""; // 接收到的串口数据
void setup() {
Serial.begin(9600); // 串口波特率为9600
myservo.attach(9); // 大舵机用接口9控制
myservo2.attach(6); // 小舵机用接口6控制
}
void loop() {
// 监听串口消息
while(Serial.available() > 0){
comdata += char(Serial.read());
delay(2);
}
// 处理数据
if(comdata.length() > 0){
Serial.println("Get rangle:" + comdata);
int R = comdata.toInt();
// 大于400的值认为是小舵机的指令
if(R > 400){
R -= 400;
if(R > pos2){
for(;pos2 < R;pos2++){
myservo2.write(pos2);
delay(15);
}
}
else if(R < pos2){
for(;pos2 > R;pos2--){
myservo2.write(pos2);
delay(15);
}
}
else{
// no action
}
}
// 小于400的值认为是大舵机的指令
else{
if(R > pos){
for(;pos < R;pos++){
myservo.write(pos);
delay(15);
}
}
else if(R < pos){
for(;pos > R;pos--){
myservo.write(pos);
delay(15);
}
}
else{
// no action
}
}
// 清空接收变量
comdata = "";
}
}
Arduino的开发环境自带串口监视器,可以先在那调试一下能不能控制转动
然后就是主机上的转动控制程序啦
开发这个程序其实本来也是想作为一个Server然后能中继一下手机APP发来的控制指令
好吧我一开始也想拿手机控制我的近防炮的
军火也随一下移动端大流嘛
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
namespace FiregunServer
{
public partial class Form1 : Form
{
// 串口变量
private static SerialPort serialPort = null;
// 炮台角度变量
private int horizen; // 水平角度
private int vertical; // 垂直角度
// 支持项
private const int DELAY_TIME = 25;
public Form1()
{
InitializeComponent();
horizen = 0;
vertical = 20;
}
public void launch(string msg)
{
byte[] sendData;
sendData = System.Text.Encoding.Default.GetBytes(msg);
if (serialPort == null)
{
serialPort = new SerialPort("COM5", 9600, Parity.None, 8, StopBits.One);
serialPort.ReadBufferSize = 1024;
serialPort.WriteBufferSize = 1024;
}
if (!serialPort.IsOpen)
{
serialPort.Open();
}
//发送数据
serialPort.Write(sendData, 0, sendData.Length);
}
// 水平角度增加
private void button1_Click(object sender, EventArgs e)
{
left();
}
// 水平角度减少
private void button3_Click(object sender, EventArgs e)
{
right();
}
// 垂直角度增加
private void button2_Click(object sender, EventArgs e)
{
up();
}
// 垂直角度减少
private void button4_Click(object sender, EventArgs e)
{
down();
}
// 炮台往左
private void left()
{
if (horizen < 180)
{
horizen++;
textBox1.Text = horizen + "";
}
launch(horizen + "");
textBox3.AppendText("水平:" + horizen + "\r\n");
}
// 炮台往右
private void right()
{
if (horizen > 0)
{
horizen--;
textBox1.Text = horizen + "";
}
launch(horizen + "");
textBox3.AppendText("水平:" + horizen + "\r\n");
}
// 炮口太高
private void up()
{
if (vertical < 180)
{
vertical++;
textBox2.Text = vertical + "";
}
launch((vertical + 400) + "");
textBox3.AppendText("垂直:" + vertical + "\r\n");
}
// 炮口降低
private void down()
{
if (vertical > 0)
{
vertical--;
textBox2.Text = vertical + "";
}
launch((vertical + 400) + "");
textBox3.AppendText("垂直:" + vertical + "\r\n");
}
// 快速定位动作
public void quickLocate(int H, int V)
{
// 检验值
if (H < 0 || H > 180 || V < 0 || V > 90)
{
textBox4.Text = "0";
textBox5.Text = "0";
return;
}
// 确定转动距离
int dH, dV;
dH = H - horizen;
dV = V - vertical;
// 转动水平角度
if (dH > 0)
{
for (int i = 0; i < dH; i++)
{
left();
Delay(DELAY_TIME);
}
}
else
{
for (int i = 0; i < -dH; i++)
{
right();
Delay(DELAY_TIME);
}
}
// 转动垂直角度
if (dV > 0)
{
for (int i = 0; i < dV; i++)
{
up();
Delay(DELAY_TIME);
}
}
else
{
for (int i = 0; i < -dV; i++)
{
down();
Delay(DELAY_TIME);
}
}
}
// 快速定位
private void button5_Click(object sender, EventArgs e)
{
// 获取设定值
int H = int.Parse(textBox4.Text);
int V = int.Parse(textBox5.Text);
quickLocate(H, V);
}
// 延迟函数
public static void Delay(int milliSecond)
{
int start = Environment.TickCount;
while (Math.Abs(Environment.TickCount - start) < milliSecond)//毫秒
{
Application.DoEvents();//可执行某无聊的操作
}
}
// 炮口复位
private void button6_Click(object sender, EventArgs e)
{
quickLocate(0, 20);
}
}
}
程序界面在上面有哦,背景是我们的校徽嘿嘿
今天学到了什么呢?
1、Arduino的串口开发和舵机控制开发
2、C#的串口程序开发
3、人别想太多
4、男人的快乐很简单
添加一下效果:
快速定位
自动复位