极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 97140|回复: 39

C#与Arduino的对话

  [复制链接]
发表于 2011-10-10 09:41:52 | 显示全部楼层 |阅读模式
功能需求:
       PC机作为上位机,通过串口发送控制指令 F(ading) or B(link) 给Arduino,根据不同指令来实现LED闪烁或者渐明渐暗。

实现方式:
       单片机选用Arduino MEGA 1280,PWM10脚作为输出口,接220欧限流电阻至高亮LED,再与GND脚共地。
   


       上位机用C#作为编程语言,IDE选择VS2010,.Net版本选择了4.0,不过应该能够兼容其它版本的.net framework。之前上位机跟单片机通信时,传递的是字符串,方法是先将PWM值视为ASCII码,转换成对应的Char,然后将Char再转换成String类型。由于ANSI ASCII码表只支持128个字符,所以128-255之间的数在传递的时候就遇到难题,通过串口监视发现,超过127的ASCII发给arduino之后,都被修改为63,导致传输失效。

       现在的方法改为直接传递byte类型的无符号数,解决了这个问题。

       运行界面如下:



       上位机源代码:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.IO.Ports;
  10. using System.Threading;

  11. namespace WindowsFormsApplication1
  12. {
  13. public partial class frmMain :
  14.   Form
  15.   {
  16.     int FlashTimes;
  17.     int FlashCounts;
  18.     Label FlashingLED;
  19.     string TextRead;
  20.     public frmMain()
  21.     {
  22.       InitializeComponent();
  23.     }
  24.     private int  FillSerialPorts()
  25.     {
  26.       int PortCount;
  27.       PortCount = 0;
  28.       //加载串口列表
  29.       SerialPort _tempPort;
  30.       String[] Portname = SerialPort.GetPortNames();
  31.       foreach (string str in Portname)
  32.       {
  33.         try
  34.         {
  35.           _tempPort = new SerialPort(str);
  36.           _tempPort.Open();
  37.           if (_tempPort.IsOpen)
  38.           {
  39.             cboCOMPorts.Items.Add(str);
  40.             _tempPort.Close();
  41.             PortCount++;
  42.           }
  43.         }
  44.         catch (Exception ex)
  45.         {
  46.           tsMessage.Text = ex.ToString();
  47.         }
  48.       }
  49.       if (!(PortCount ==0))
  50.         cboCOMPorts.SelectedIndex =0;
  51.       tsCOMPort.Text = cboCOMPorts.Text;
  52.       return PortCount;
  53.     }
  54.     private void trkPWM_ValueChanged(object sender, EventArgs e)
  55.     {
  56.       lblPWM.Text = trkPWM.Value.ToString ();
  57.     }
  58.     private void button1_Click(object sender, EventArgs e)
  59.     {
  60.       txtRead.Clear();
  61.       if (cboCOMPorts.Text == "")
  62.       {
  63.         tsMessage.Text = "尚未选择串口!";
  64.       }
  65.       else
  66.       {
  67.         if (!serialPort1.IsOpen)
  68.         {
  69.           serialPort1.PortName = cboCOMPorts.Text;
  70.           serialPort1.Open();
  71.           try
  72.           {
  73.             tsCOMPort.Text = cboCOMPorts.Text;
  74.             tsCOMState.Text = "开启";
  75.           }
  76.           catch (Exception ex)
  77.           {
  78.             tsMessage.Text = ex.ToString(); // "串口打开过程中遇到错误,串口不存在或者已经被占用!";
  79.             tsCOMPort.Text = "";
  80.             tsCOMState.Text = "已断开";
  81.           }
  82.         }
  83.         if (serialPort1.IsOpen)
  84.         {
  85.           if (rbFading.Checked)
  86.           {
  87.             serialPort1.Write("F");
  88.             byte[] bytesToSend = new byte[1] ;
  89.             bytesToSend[0] =Convert.ToByte ( trkPWM.Value *2.55 ); //疑问:当Value=100,ToByte=255,但是((int)(trkPWM.Value * 2.55)).ToString()却是254?
  90.             serialPort1.Write(bytesToSend, 0, 1);

  91.             //serialPort1.Write( ((Char ) ((int) trkPWM.Value *2.55 )).ToString () ); //这个方法不能传递高于127的数
  92.             //tsMessage.Text = ((int)(trkPWM.Value * 2.55)).ToString();
  93.           }
  94.           else
  95.           {
  96.             serialPort1.Write("B");
  97.             serialPort1.Write(Convert.ToChar(Convert.ToInt16(trkPWM.Value)).ToString());
  98.           }
  99.           FlashLED(lblRX, 10);
  100.         }
  101.       }
  102.     }
  103.     private void Form1_Load(object sender, EventArgs e)
  104.     {
  105.       FillSerialPorts();
  106.       trkPWM.Value = 80;
  107.     }
  108.     private void FlashLED(Label LED, int Count)
  109.     {
  110.       FlashingLED = LED;
  111.       FlashCounts = Count;
  112.       timer1.Enabled = true;
  113.     }
  114.     private void DisplayText(object sender, EventArgs e)
  115.     {
  116.       txtRead.AppendText(TextRead);
  117.     }
  118.     private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
  119.     {
  120.       if (chkReceive.Checked)
  121.       {
  122.         TextRead = serialPort1.ReadExisting();
  123.         this.Invoke(new EventHandler(DisplayText));
  124.         FlashLED(lblRX, 10);
  125.       }
  126.     }
  127.     private void timer1_Tick(object sender, EventArgs e)
  128.     {
  129.       //add flash times
  130.       if (FlashTimes <= FlashCounts)
  131.       {
  132.         FlashingLED.Visible = !FlashingLED.Visible;
  133.         FlashTimes++;
  134.       }
  135.       else
  136.       {
  137.         timer1.Enabled = false;
  138.         FlashCounts = 0;
  139.         FlashTimes = 0;
  140.         FlashingLED.Visible = true;
  141.       }
  142.     }

  143.     private void frmMain_Activated(object sender, EventArgs e)
  144.     {
  145.       if (cboCOMPorts.Items.Count ==0 )
  146.         FillSerialPorts ();
  147.     }
  148.     private void button2_Click(object sender, EventArgs e)
  149.     {
  150.       serialPort1.Close();
  151.       timer1.Enabled = false;
  152.     }
  153.     private void pictureBox1_Paint(object sender, PaintEventArgs e)
  154.     {
  155.       pictureBox1.Invalidate();
  156.       int yOffset=100;
  157.       int yBase = 40;
  158.       int xOffset = 40;
  159.       int i ;
  160.       int x=0;
  161.       Pen p = new Pen(Color.Yellow ,1);
  162.       Graphics g = e.Graphics;
  163.       if (trkPWM.Value ==100)
  164.         g.DrawLine(p, pictureBox1.Left , pictureBox1.Height - yOffset , pictureBox1.Left + 10 , pictureBox1.Height - yOffset ); // __
  165.       else
  166.         g.DrawLine(p, pictureBox1.Left , pictureBox1.Height - yBase, pictureBox1.Left + 10 , pictureBox1.Height - yBase); // __
  167.       for (i = 0; i <= 5; i++)
  168.       {
  169.         x = 100 * i;
  170.         if (!((trkPWM.Value ==0 )||(trkPWM.Value ==100)))
  171.           g.DrawLine(p, pictureBox1.Left + 10 + x, pictureBox1.Height - yBase, pictureBox1.Left + 10 + x, pictureBox1.Height - yOffset); // |
  172.         //p.Color = Color.Blue ;
  173.         xOffset = trkPWM.Value;
  174.         g.DrawLine(p, pictureBox1.Left + 10 + x, pictureBox1.Height - yOffset, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yOffset);//--
  175.         if (!((trkPWM.Value == 0) || (trkPWM.Value == 100)))
  176.           g.DrawLine(p, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yOffset, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yBase);//|
  177.         g.DrawLine(p,pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yBase, pictureBox1.Left + 10 + xOffset + x + 100 -trkPWM.Value , pictureBox1.Height - yBase);//__
  178.         e.Graphics.DrawString(trkPWM.Value.ToString () + "%", panel1.Font , new SolidBrush(Color.White ), panel1.Left +  120 , 5, StringFormat.GenericDefault);
  179.       }
  180.     }
  181.     private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
  182.     {
  183.       if (serialPort1.IsOpen)
  184.         serialPort1.Close();
  185.     }
  186.     private void 清空ToolStripMenuItem1_Click(object sender, EventArgs e)
  187.     {
  188.       txtRead.Clear();
  189.     }
  190.   }
  191. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 1 +3 收起 理由
弘毅 + 3 赞一个!

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2011-10-10 09:49:10 | 显示全部楼层
Arduino程序源代码:
  1. //COPYRIGHT DECLARATION
  2. //THIS APPLICATION IS A DEMOSTRATION APPLICATON FOR EDUCATION PURPOSE ONLY. YOU CAN USE OR
  3. //REDISTRIBUTE IT FREELY ON CONDITION THAT YOU WOULD NOT MAKE MONEY OF IT.

  4. //THE DESKTOP APPLICATON WHICH IS PROGRAMMED IN C# WOULD SEND CONTROL CODE AND PARAMETERS, IF ANY,
  5. //TO THE ARDUINO, THE MICROCONTROLLER WOULD MAKE THE LED FADING OR BLINKING IN ACCORDANCE
  6. //WITH THE CONTROL CODE, THEN.
  7. //SINCE THIS IS MY FIRST APPLICATION IN EITHER C# AND ARDUINO, THERE MIGHT BE SOME BUGS IN IT,
  8. //IF YOU RUN INTO ANY EXCEPTIONS, PLEASE REPORT THEM TO ME AT [email protected].

  9. //HISTORY
  10. //VER 0.101 1:32 2011-7-31
  11. //Add Fade function to the application
  12. //VER 0.100 16:45 2011-7-30
  13. //Add blink function to the application

  14. char CMD;           //command
  15. int pwmValue;       //PWM value
  16. int PinOUT=10;      //output pin
  17. int Interval = 10;

  18. void setup()
  19. {
  20.   Serial.begin(9600);
  21.   pinMode(PinOUT, OUTPUT);    //set the pin 10 as output pin
  22.   CMD = 'F';
  23.   pwmValue = 50;
  24. }
  25. void loop()
  26. {
  27.   if (Serial.available())
  28.   {
  29.     char PrevCMD;
  30.     PrevCMD = CMD;
  31.     CMD = Serial.read();
  32.     switch(CMD)
  33.     {
  34.     case 'B':   //Blink
  35.       //read PWM value in readPWMValue routine
  36.       pwmValue = readPWMValue();
  37.       break ;
  38.       //any other CASE statement
  39.     case 'F':   //Fading
  40.       pwmValue = readPWMValue();
  41.       break;
  42.     default :
  43.       CMD = PrevCMD; //当没有按键或者控制指令无效时,继续执行原来的指令
  44.       break;
  45.     }
  46.   }

  47.   //if there is no chars income, then execute the last command
  48.   switch(CMD)
  49.   {
  50.   case 'B':
  51.     setPWM(pwmValue);
  52.     break;
  53.   case 'F':
  54.     ledFading(pwmValue);
  55.     break;

  56.   default:
  57.     break;
  58.   }
  59. }
  60. int readPWMValue()
  61. {  
  62.   int Value;
  63.   while (!Serial.available())
  64.   {
  65.     //wait for another incoming char
  66.   }
  67.   Value=Serial.read();

  68.   Serial.print("Parameters received: ");
  69.   Serial.println(Value);

  70.   return Value;
  71. }
  72. void setPWM(int Value)
  73. {
  74.   int i;

  75.   Serial.println(Value);

  76.   for (i=0; i<=100; i++)
  77.   {  
  78.     //debug
  79.     Serial.print(i);
  80.     Serial.print(" / ");
  81.     if (i<= Value)
  82.     {
  83.       digitalWrite(PinOUT,HIGH);

  84.       //Debug
  85.       Serial.println("HIGH");
  86.     }
  87.     else
  88.     {
  89.       digitalWrite(PinOUT,LOW);

  90.       //DEBUG
  91.       Serial.println("LOW");
  92.     }
  93.     delay(Interval);
  94.   }
  95. }
  96. void ledFading(int Value)
  97. {  
  98.   Serial.print("Fading Value: ");
  99.   Serial.println(Value);
  100.   int i;
  101.   /*
  102.     if (Value>=255)
  103.    Value = 255;
  104.    else
  105.    if (Value<=0);
  106.    Value =0;
  107.    */

  108.   //fade in
  109.   for (i=0; i<=Value; i++)
  110.   {
  111.     analogWrite(PinOUT, i);
  112.     Serial.println(i);
  113.     delay(Interval);
  114.   }

  115.   delay(500);

  116.   //fade out
  117.   for (i=Value; i>=0; i--)
  118.   {
  119.     analogWrite(PinOUT,i);
  120.     Serial.println(i);
  121.     delay(Interval);
  122.   }

  123.   delay(500);

  124. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2011-12-12 22:10:29 | 显示全部楼层
赞一个{:soso_e100:}
回复 支持 反对

使用道具 举报

发表于 2011-12-13 00:12:03 | 显示全部楼层
大神级人物,向您致敬!
回复 支持 反对

使用道具 举报

发表于 2011-12-13 23:54:12 | 显示全部楼层
这个很给力呀。。。直接输入pwm了
回复 支持 反对

使用道具 举报

发表于 2012-2-27 11:20:12 | 显示全部楼层
C#可以直接开发么?求详细资料
回复 支持 反对

使用道具 举报

发表于 2012-2-27 11:25:48 | 显示全部楼层
仔细看了下代码,明白c#只是用来串口通信。呵呵,支持楼主
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-2-28 02:53:10 | 显示全部楼层
h784533 发表于 2012-2-27 11:20
C#可以直接开发么?求详细资料

Netduino是用C#开发的,支持调试,弱点就是库比arduino的少
回复 支持 反对

使用道具 举报

发表于 2012-2-28 10:26:20 | 显示全部楼层
ardyPro 发表于 2012-2-28 02:53
Netduino是用C#开发的,支持调试,弱点就是库比arduino的少

Netduino的致命弱点:速度慢
相同处理器条件下
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-2-29 00:04:11 | 显示全部楼层
SS15 发表于 2012-2-28 10:26
Netduino的致命弱点:速度慢
相同处理器条件下

是吗?我没用过,对我来讲,相同功能,netduino贵多了,不划算。

难道是因为.net CF的原因?今天看到一篇文章介绍,奇瑞汽车自主研发的机械臂,执行用实时系统,但是数据运算就是在WinCE平台上做的,WinCE上面也带的有一坨.net CF呢
回复 支持 反对

使用道具 举报

发表于 2012-2-29 12:35:04 | 显示全部楼层
ardyPro 发表于 2012-2-29 00:04
是吗?我没用过,对我来讲,相同功能,netduino贵多了,不划算。

难道是因为.net CF的原因?今天看 ...

.net 平台的中间代码在翻译成机器代码过程中必然消耗资源,占用时间。

.net 只是WinCE的一个组件,应用程序快慢和.net这个组件没关系,而是与是否运行于这个组件上有关。

一般的机械臂实时性要求不太高,WinCE拿来做两三百公里的无人机飞控运算都基本够用了。速度再高,就得RTOS了。
回复 支持 反对

使用道具 举报

发表于 2012-5-9 13:44:13 | 显示全部楼层
上位机是以后开发的重要支撑,不管是电脑还是手机的上位机,求基础学习资料
回复 支持 反对

使用道具 举报

发表于 2012-7-5 11:50:16 | 显示全部楼层
呵呵!不错啊!
回复 支持 反对

使用道具 举报

发表于 2012-12-14 23:43:45 | 显示全部楼层
if (serialPort1.IsOpen)
        {
          if (rbFading.Checked)
          // 第二个if 是干嘛的?没看懂
回复 支持 反对

使用道具 举报

发表于 2012-12-15 09:44:32 | 显示全部楼层
Dream 发表于 2012-12-14 23:43
if (serialPort1.IsOpen)
        {
          if (rbFading.Checked)

是否显示内容打勾的意思
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-20 12:23 , Processed in 0.054482 second(s), 30 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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