多语言展示
当前在线:537今日阅读:168今日分享:49

如何用c#编写关于全局定位实时显示地图的上位机

这是一个基于某省机器人设计大赛的环境下做出的一个小功能,可以用于测试机器人的性能,以及相关自检和决策。这里只是小车在场上的位置显示。
工具/原料

上位机C#的编程环境和arduino编程环境

方法/步骤
1

上位机程序namespace 全局定位1{    public partial class Form1 : Form    {        Stopwatch sw = new Stopwatch();                //PID暂存        double x = 0.0;        double y = 0.0;        double p = 0.0;        bool drawornot = false;                       public Form1()        {            InitializeComponent();            //获取端口列表            pictureBox2.Image = Image.FromFile('车.PNG');            pictureBox1.Image = Image.FromFile('比赛场地.PNG');            string[] ports = SerialPort.GetPortNames();//得到接口名字            //将端口列表添加到comboBox            this.comboBox2.Items.AddRange(ports);            serialPort1.DataReceived += DataReceivedHandler;            sw.Start();            Control.CheckForIllegalCrossThreadCalls = false;  //防止跨线程出错            //定时器中断时间            timer1.Interval = 100;            timer2.Interval = 100;            timer3.Interval = 300;                   }        static int buffersize = 18;   //十六进制数的大小(假设为9Byte,可调整数字大小)        byte[] buffer = new Byte[buffersize];   //创建缓冲区                private void Form1_Load(object sender, EventArgs e)        {            comboBox1.Items.Add('1200');            comboBox1.Items.Add('2400');            comboBox1.Items.Add('4800');            comboBox1.Items.Add('9600');            comboBox1.Items.Add('14400');            comboBox1.Items.Add('19200');            comboBox1.Items.Add('28800');            comboBox1.Items.Add('38400');//常用的波特率            try            {                string[] ports = SerialPort.GetPortNames();//得到接口名字                //将端口列表添加到comboBox                this.comboBox2.Items.AddRange(ports);                ///设置波特率                serialPort1.BaudRate = Convert.ToInt32(comboBox1.Text);                            }            catch (Exception ex)            {                            }                   }        private void pictureBox1_Click(object sender, EventArgs e)//用于显示地图        {                    }        private void button2_Click(object sender, EventArgs e)//接收/暂停数据按钮        {            if (serialPort1.IsOpen)////(更新)如果按下按钮之前串口是开的,就断开//如果按下按钮之前 flag的内容是false 按下之后 内容改成true 然后打开串口            {                serialPort1.Close();                button2.Text = '连接';                timer3.Stop();            }            else            {                //要打开串口要看波特率 串口等有没有设置对                bool no_error_flag = true;                try                {                    serialPort1.BaudRate = Convert.ToInt32(comboBox1.SelectedItem);                }                catch (ArgumentException e1)                {                    this.errorProvider1.SetError(this.comboBox1, '不能为空');                    no_error_flag = false;                }                try                {                    serialPort1.PortName = Convert.ToString(comboBox2.SelectedItem);                }                catch (ArgumentException e2)                {                    this.errorProvider1.SetError(this.comboBox2, '不能为空');                    no_error_flag = false;                }                try                {                    serialPort1.Open();                }                catch                {                    MessageBox.Show('端口错误', '警告');                    no_error_flag = false;                }                if (no_error_flag)                {                    button2.Text = '断开连接';                 }              }         }             private void timer3_Tick(object sender, EventArgs e)//第三定位器        {            if (serialPort1.IsOpen)            {                textBox1.Text = data_warehouse;                textBox1.SelectionStart = textBox1.TextLength;//光标定位到文本最后                textBox1.ScrollToCaret();                UpdateQueueValue();            }            if (drawornot)            {                MessageBox.Show('数据接收失败!', '系统提示');                }          }                               //串口接收完成事件——接收所有数据        string data_warehouse = '';        public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)        {            //读取串口中的所有数据            string readfromport = serialPort1.ReadExisting();            data_warehouse += readfromport;                    }        //更新队列程序        string[] separators = { 'A:', 'B:', 'X:', 'Y:', 'P:' };        int pos = 0;        private void UpdateQueueValue()        {            while (data_warehouse.Length > 35)            {                //第一个换行符的位置                pos = data_warehouse.IndexOf('\n');                //断句第一个换行符                Debug.WriteLine('' + pos);                string s = data_warehouse.Remove(pos).ToUpper();                //删掉读到的第一句话                data_warehouse = data_warehouse.Remove(0, pos + 1);                //开始断句                string[] words = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);                //读取断句中的数据                try                {                    //float d1 = Convert.ToSingle(words[0]);                    //float d2 = Convert.ToSingle(words[1]);                    x = Convert.ToDouble(words[2]);                    y = Convert.ToDouble(words[3]);                    p = Convert.ToDouble(words[4]);                    Debug.WriteLine(words[3]);                }                catch (Exception e)                {                    Debug.WriteLine(e.ToString());                }            }        }                private void button4_Click(object sender, EventArgs e)//开始画图按钮        {             this.pictureBox2.Image.RotateFlip(RotateFlipType.Rotate90FlipXY);//这里我需要得到陀螺仪给的角度p,然后用if语句判断角                                                                                   //度p来执行这条语句, 实现90度旋转             this.pictureBox2.Refresh();             if (data_warehouse.Length>0)             {                                  MessageBox.Show('数据接收成功!', '系统提示');             }             else             {                 MessageBox.Show('数据接受失败!', '警告');             }            timer1.Start();            timer2.Start();            timer3.Start();

2

arduino程序#include #include #include #include #define OLED_RESET 4Adafruit_SSD1306 display(OLED_RESET);const int X_dir = 9;const int Y_dir = 10;double X_juli, Y_juli;const byte X_interruptPin = 2;const byte Y_interruptpin = 3;volatile byte xstate = HIGH;volatile byte ystate = HIGH;double x = 0, y = 0;void setup(){  display.begin(SSD1306_SWITCHCAPVCC);  Serial.begin(9600);  pinMode(X_dir, INPUT_PULLUP);  pinMode(X_interruptPin, INPUT_PULLUP);  pinMode(Y_dir, INPUT_PULLUP);  pinMode(Y_interruptpin, INPUT_PULLUP);  attachInterrupt(digitalPinToInterrupt(X_interruptPin), xblink, FALLING );  attachInterrupt(digitalPinToInterrupt(Y_interruptpin), yblink, FALLING );  }void loop(){  X_juli = 1.0 * x / 256 * 118.3;  Y_juli = 1.0 * y / 256 * 118.3;    Serial.print(X_juli);  Serial.print(' ');  Serial.println(Y_juli);  /*display.setTextSize(1);  display.setTextColor(WHITE);  display.setCursor(0, 0);  display.clearDisplay();  display.print('x =');  display.println(X_juli);  display.print('y =');  display.println(Y_juli);  display.display();*/  delay(1);}void xblink(){  xstate = digitalRead(X_dir);  if (xstate == HIGH)    x--;  else    x++;}void yblink(){  ystate = digitalRead(Y_dir);  if (ystate == HIGH)    y++;  else    y--;}

注意事项

考虑到各种因素,我会把源程序上传网盘,有兴趣的同学可以去看一看,这些程序是功能的累计,可根据自己需要学习。

推荐信息