2011年7月31日星期日

C#与Arduino的通讯试验

        这几天一直在搞PC机作为上位机,通过与Arduino单片机的通讯,来控制LED闪烁或者渐明渐暗。之前有一篇博客记录了试验过程中遇到的问题,不过之前的描述不怎么准确,这两天又重写了Arduino程序,并对C#上位机的程序也做了一些修改,终于可以达到预期功能。

功能需求:
        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类型的无符号数,解决了这个问题。

        运行界面如下:


        上位机源代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class frmMain : Form
       {
        int FlashTimes;
        int FlashCounts;
        Label FlashingLED;
        string TextRead;
        public frmMain()
        {
            InitializeComponent();
        }
        private int  FillSerialPorts()
        {
            int PortCount;
            PortCount = 0;
            //加载串口列表
            SerialPort _tempPort;
            String[] Portname = SerialPort.GetPortNames();
            foreach (string str in Portname)
            {
                try
                {
                    _tempPort = new SerialPort(str);
                    _tempPort.Open();
                    if (_tempPort.IsOpen)
                    {
                        cboCOMPorts.Items.Add(str);
                        _tempPort.Close();
                        PortCount++;
                    }
                }
                catch (Exception ex)
                {
                    tsMessage.Text = ex.ToString();
                }
            }
            if (!(PortCount ==0))
                cboCOMPorts.SelectedIndex =0;
            tsCOMPort.Text = cboCOMPorts.Text;
            return PortCount;
        }
        private void trkPWM_ValueChanged(object sender, EventArgs e)
        {
            lblPWM.Text = trkPWM.Value.ToString ();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            txtRead.Clear();
            if (cboCOMPorts.Text == "")
            {
                tsMessage.Text = "尚未选择串口!";
            }
            else
            {
                if (!serialPort1.IsOpen)
                {
                    serialPort1.PortName = cboCOMPorts.Text;
                    serialPort1.Open();
                    try
                    {
                        tsCOMPort.Text = cboCOMPorts.Text;
                        tsCOMState.Text = "开启";
                    }
                    catch (Exception ex)
                    {
                        tsMessage.Text = ex.ToString(); // "串口打开过程中遇到错误,串口不存在或者已经被占用!";
                        tsCOMPort.Text = "";
                        tsCOMState.Text = "已断开";
                    }
                }
                if (serialPort1.IsOpen)
                {
                    if (rbFading.Checked)
                    {
                        serialPort1.Write("F");
                        byte[] bytesToSend = new byte[1] ;
                        bytesToSend[0] =Convert.ToByte ( trkPWM.Value *2.55 ); //疑问:当Value=100,ToByte=255,但是((int)(trkPWM.Value * 2.55)).ToString()却是254?
                        serialPort1.Write(bytesToSend, 0, 1);
                       
                        //serialPort1.Write( ((Char ) ((int) trkPWM.Value *2.55 )).ToString () ); //这个方法不能传递高于127的数
                        //tsMessage.Text = ((int)(trkPWM.Value * 2.55)).ToString();
                    }
                    else
                    {
                        serialPort1.Write("B");
                        serialPort1.Write(Convert.ToChar(Convert.ToInt16(trkPWM.Value)).ToString());
                    }
                    FlashLED(lblRX, 10);
                }
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            FillSerialPorts();
            trkPWM.Value = 80;
        }
        private void FlashLED(Label LED, int Count)
        {
            FlashingLED = LED;
            FlashCounts = Count;
            timer1.Enabled = true;
        }
        private void DisplayText(object sender, EventArgs e)
        {
            txtRead.AppendText(TextRead);
        }
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (chkReceive.Checked)
            {
                TextRead = serialPort1.ReadExisting();
                this.Invoke(new EventHandler(DisplayText));
                FlashLED(lblRX, 10);
            }
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            //add flash times
            if (FlashTimes <= FlashCounts)
            {
                FlashingLED.Visible = !FlashingLED.Visible;
                FlashTimes++;
            }
            else
            {
                timer1.Enabled = false;
                FlashCounts = 0;
                FlashTimes = 0;
                FlashingLED.Visible = true;
            }
        }

        private void frmMain_Activated(object sender, EventArgs e)
        {
            if (cboCOMPorts.Items.Count ==0 )
                FillSerialPorts ();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            serialPort1.Close();
            timer1.Enabled = false;
        }
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            pictureBox1.Invalidate();
            int yOffset=100;
            int yBase = 40;
            int xOffset = 40;
            int i ;
            int x=0;
            Pen p = new Pen(Color.Yellow ,1);
            Graphics g = e.Graphics;
            if (trkPWM.Value ==100)
                g.DrawLine(p, pictureBox1.Left , pictureBox1.Height - yOffset , pictureBox1.Left + 10 , pictureBox1.Height - yOffset ); // __
            else
                g.DrawLine(p, pictureBox1.Left , pictureBox1.Height - yBase, pictureBox1.Left + 10 , pictureBox1.Height - yBase); // __
            for (i = 0; i <= 5; i++)
            {
                x = 100 * i;
                if (!((trkPWM.Value ==0 )||(trkPWM.Value ==100)))
                    g.DrawLine(p, pictureBox1.Left + 10 + x, pictureBox1.Height - yBase, pictureBox1.Left + 10 + x, pictureBox1.Height - yOffset); // |
                //p.Color = Color.Blue ;
                xOffset = trkPWM.Value;
                g.DrawLine(p, pictureBox1.Left + 10 + x, pictureBox1.Height - yOffset, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yOffset);//--
                if (!((trkPWM.Value == 0) || (trkPWM.Value == 100)))
                    g.DrawLine(p, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yOffset, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yBase);//|
                g.DrawLine(p,pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yBase, pictureBox1.Left + 10 + xOffset + x + 100 -trkPWM.Value , pictureBox1.Height - yBase);//__
                e.Graphics.DrawString(trkPWM.Value.ToString () + "%", panel1.Font , new SolidBrush(Color.White ), panel1.Left +  120 , 5, StringFormat.GenericDefault);
            }
        }
        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen)
                serialPort1.Close();
        }
        private void 清空ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            txtRead.Clear();
        }
    }
}

Arduino程序源代码:

//COPYRIGHT DECLARATION
//THIS APPLICATION IS A DEMOSTRATION APPLICATON FOR EDUCATION PURPOSE ONLY. YOU CAN USE OR
//REDISTRIBUTE IT FREELY ON CONDITION THAT YOU WOULD NOT MAKE MONEY OF IT.
    
//THE DESKTOP APPLICATON WHICH IS PROGRAMMED IN C# WOULD SEND CONTROL CODE AND PARAMETERS, IF ANY,
//TO THE ARDUINO, THE MICROCONTROLLER WOULD MAKE THE LED FADING OR BLINKING IN ACCORDANCE
//WITH THE CONTROL CODE, THEN.
//SINCE THIS IS MY FIRST APPLICATION IN EITHER C# AND ARDUINO, THERE MIGHT BE SOME BUGS IN IT,
//IF YOU RUN INTO ANY EXCEPTIONS, PLEASE REPORT THEM TO ME AT JZOPEN@YEAH.NET.

//HISTORY
//VER 0.101 1:32 2011-7-31
//Add Fade function to the application
//VER 0.100 16:45 2011-7-30
//Add blink function to the application

char CMD;           //command
int pwmValue;       //PWM value
int PinOUT=10;      //output pin
int Interval = 10;

void setup()
{
    Serial.begin(9600);
    pinMode(PinOUT, OUTPUT);    //set the pin 10 as output pin�
    CMD = 'F';
    pwmValue = 50;
}
void loop()
{
    if (Serial.available())
    {
        char PrevCMD;
        PrevCMD = CMD;
        CMD = Serial.read();
        switch(CMD)
        {
            case 'B':   //Blink
                //read PWM value in readPWMValue routine
                pwmValue = readPWMValue();
                break ;
            //any other CASE statement�
            case 'F':   //Fading
                pwmValue = readPWMValue();
                break;
            default :
                CMD = PrevCMD; //当没有按键或者控制指令无效时,继续执行原来的指令
               break;
        }
    }
   
    //if there is no chars income, then execute the last command
    switch(CMD)
    {
       case 'B':
          setPWM(pwmValue);
          break;
       case 'F':
          ledFading(pwmValue);
          break;
      
       default:
          break;
    }
}
int readPWMValue()
{  
    int Value;
    while (!Serial.available())
    {
        //wait for another incoming char�
    }
    Value=Serial.read();
   
    Serial.print("Parameters received: ");
    Serial.println(Value);
   
    return Value;
}
void setPWM(int Value)
{
    int i;
   
    Serial.println(Value);
   
    for (i=0; i<=100; i++)
      { 
        //debug
        Serial.print(i);
        Serial.print(" / ");
        if (i<= Value)
        {
          digitalWrite(PinOUT,HIGH);
         
          //Debug
          Serial.println("HIGH");
        }
        else
        {
           digitalWrite(PinOUT,LOW);
          
           //DEBUG
           Serial.println("LOW");
        }
        delay(Interval);
    }
}
void ledFading(int Value)
{  
    Serial.print("Fading Value: ");
    Serial.println(Value);
    int i;
    /*
    if (Value>=255)
      Value = 255;
    else
      if (Value<=0);
        Value =0;
    */
   
    //fade in
    for (i=0; i<=Value; i++)
    {
       analogWrite(PinOUT, i);
       Serial.println(i);
       delay(Interval);
    }
   
    delay(500);
   
    //fade out
    for (i=Value; i>=0; i--)
    {
       analogWrite(PinOUT,i);
       Serial.println(i);
       delay(Interval);
    }
   
    delay(500);
   
}


       当然上面的代码只是为了演示和学习需要,所以会很不完善甚至有错误的地方。

2011年7月29日星期五

PC 机与Arduino通信--故障

这是我写的第一个像模像样的C#上位机程序,以前除了写过Hello World之外,没有写过超过20行的C#程序,呵呵,Arduino的程序也是。所以出现bug是很正常的。

接线图



上位机的问题就是,当单击停止按钮关闭COMPort之后,整个窗体处于假死状态,不知道是不是跟.Net的读串口需要另开线程有关,由于是新学,这个问题存疑。

Arduino端的程序问题是,通过串口返回给上位机的信息,i+“ | ”+ Value这个木有返回,更严重的是,返回的东西每隔一段时间就会有乱码。

上位机程序代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;

namespace WindowsFormsApplication1
{
  
    public partial class frmMain : Form
       {
        int FlashTimes;
        int FlashCounts;
        Label FlashingLED;
        string TextRead;
        public frmMain()
        {
            InitializeComponent();
        }
        private int  FillSerialPorts()
        {
            int PortCount;
            PortCount = 0;
            //加载串口列表
            SerialPort _tempPort;
            String[] Portname = SerialPort.GetPortNames();
            foreach (string str in Portname)
            {
                try
                {
                    _tempPort = new SerialPort(str);
                    _tempPort.Open();
                    if (_tempPort.IsOpen)
                    {
                        cboCOMPorts.Items.Add(str);
                        _tempPort.Close();
                        PortCount++;
                    }
                }
                catch (Exception ex)
                {
                    tsMessage.Text = ex.ToString();
                }

            }
            if (!(PortCount ==0))
                cboCOMPorts.SelectedIndex =0;
            tsCOMPort.Text = cboCOMPorts.Text;
            return PortCount;
        }
        private void trkPWM_ValueChanged(object sender, EventArgs e)
        {
            lblPWM.Text = trkPWM.Value.ToString ();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            //if serialPort1.
            if (cboCOMPorts.Text == "")
            {
                tsMessage.Text = "尚未选择串口!";
            }
            else
            {
                if (!serialPort1.IsOpen)
                {
                    serialPort1.PortName = cboCOMPorts.Text;
                    serialPort1.Open();
                    try
                    {
                        tsCOMPort.Text = cboCOMPorts.Text;
                        tsCOMState.Text = "开启";
                    }
                    catch (Exception ex)
                    {
                        tsMessage.Text = ex.ToString(); // "串口打开过程中遇到错误,串口不存在或者已经被占用!";
                        tsCOMPort.Text = "";
                        tsCOMState.Text = "已断开";
                    }
                }
                if (serialPort1.IsOpen)
                {
                    serialPort1.Write("P");
                    serialPort1.Write(Convert.ToChar(Convert.ToInt16(trkPWM.Value)).ToString());
                    FlashLED(lblRX, 10);
                }
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            FillSerialPorts();
            trkPWM.Value = 80;
        }
        private void FlashLED(Label LED, int Count)
        {
            FlashingLED = LED;
            FlashCounts = Count;
            timer1.Enabled = true;
        }
        private void DisplayText(object sender, EventArgs e)
        {
            txtRead.AppendText(TextRead);
        }
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            TextRead  = serialPort1.ReadExisting();
            this.Invoke (new EventHandler ( DisplayText));
            FlashLED(lblRX,10);
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            //add flash times
            if (FlashTimes <= FlashCounts)
            {
                FlashingLED.Visible = !FlashingLED.Visible;
                FlashTimes++;
            }
            else
            {
                timer1.Enabled = false;
                FlashCounts = 0;
                FlashTimes = 0;
                FlashingLED.Visible = true;
            }
        }

        private void frmMain_Activated(object sender, EventArgs e)
        {
            if (cboCOMPorts.Items.Count ==0 )
                FillSerialPorts ();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            serialPort1.Close();
            timer1.Enabled = false;
        }
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            pictureBox1.Invalidate();
            int yOffset=100;
            int yBase = 40;
            int xOffset = 40;
            int i ;
            int x=0;
            Pen p = new Pen(Color.Yellow ,1);
            Graphics g = e.Graphics;
            if (trkPWM.Value ==100)
                g.DrawLine(p, pictureBox1.Left , pictureBox1.Height - yOffset , pictureBox1.Left + 10 , pictureBox1.Height - yOffset ); // __
            else
                g.DrawLine(p, pictureBox1.Left , pictureBox1.Height - yBase, pictureBox1.Left + 10 , pictureBox1.Height - yBase); // __
            for (i = 0; i <= 5; i++)
            {
                x = 100 * i;
                if (!((trkPWM.Value ==0 )||(trkPWM.Value ==100)))
                    g.DrawLine(p, pictureBox1.Left + 10 + x, pictureBox1.Height - yBase, pictureBox1.Left + 10 + x, pictureBox1.Height - yOffset); // |
                //p.Color = Color.Blue ;
                xOffset = trkPWM.Value;
                g.DrawLine(p, pictureBox1.Left + 10 + x, pictureBox1.Height - yOffset, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yOffset);//--
                if (!((trkPWM.Value == 0) || (trkPWM.Value == 100)))
                    g.DrawLine(p, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yOffset, pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yBase);//|
                g.DrawLine(p,pictureBox1.Left + 10 + xOffset + x, pictureBox1.Height - yBase, pictureBox1.Left + 10 + xOffset + x + 100 -trkPWM.Value , pictureBox1.Height - yBase);//__
                e.Graphics.DrawString(trkPWM.Value.ToString () + "%", panel1.Font , new SolidBrush(Color.White ), panel1.Left +  120 , 5, StringFormat.GenericDefault);
            }
        }
    }
}
原图中没有LED显示方式,借用新图



Arduino端程序与串口监视工具界面:
char CMD;      //Command included in the chars received from PC
char* Str;     //strings received
int PWMValue;  //PWM value received from PC
int PinOUT=10;
void setup()
{
    Serial.begin(9600);
    pinMode(PinOUT, OUTPUT);
}
int ReadPWM()
{
  int Result=255;
  while (!Serial.available())
  {
    //等到有输入再退出等待
  }
  Result = Serial.read();
  Serial.flush();
  return Result;
}
void loop()
{
   int i=0;
   if (Serial.available())
   {
      CMD = Serial.read();
      Serial.flush();
      switch(CMD)                          //根据不同的控制命令,来决定是否需要接收参数
      {
         case 'P':
           PWMValue = ReadPWM();
           //PWMWave(PWMValue);            //取消
           Serial.println(PWMValue);
           break;
      }
   }
                                          //根据不同的控制命令,实现对应的功能
   switch(CMD)
   {
      case 'P':
       
        //Debug
        Serial.println("");
        Serial.println("command P");
        Serial.println("");
       
        PWMWave(PWMValue);
        break;
   }
}
void PWMWave(int Value)
{
    int i;
    for (i=0; i<=100; i++)
      {
        
        //debug
        Serial.println(i+" | "+ Value);
       
        if (i<= Value)
        {
          digitalWrite(PinOUT,HIGH);
         
          //Debug
          Serial.println("HIGH");
         
         // delay(10);
        }
        else
        {
           digitalWrite(PinOUT,LOW);
          
           //DEBUG
           Serial.println("LOW");
          
        }
        delay(10);
      }
}

另外从上位机发PWM值,有时候arduino似乎只循环一次,之后LED灯熄灭,但是从串口监视工具发指令,似乎又正常。

先把代码贴出来,错误有待慢慢去修改。

2011年7月22日星期五

Excel条件求和公式

N年前曾经在微软中文Office新闻组上面,帮助mjzn同学解决过这个问题,当时仿佛是用了某种技巧,但是微软新闻组已经被停止服务了,以前的帖子也没法查询,所以这次她重新提出这个问题时,只能想另外的辙。

她的要求是判断A列中的数值,如果相同则对B列中的数字求和,求和的结果显示在C列,并且是A列第一次出现某种条件的位置,其余位置不再显示。

条件求和的公式比较简单,使用SUMIF就行,一开始想到的办法是采用VBA做一个加载宏,从上往下判断A列,看第一次出现在什么地方。后来想想也真的很麻烦,还不见得奏效,据她讲,可能有8W多行的数据,VBA就不是一个很理想的方法了。微软对内置函数做了优化,至于VBA就只管提供哪些接口,效率就靠写代码的人来做了 :)。

晚上洗澡时,当凉水冲在头上的时候,突然有个想法,就是增加一个辅助列,把所有的和都显示出来,然后在旁边的列中用公式判断辅助列的特征,当当前行跟上一行的值相同时,就显示为“”,否则就是新出现的条件,显示真正的和。注意前面用的词是新出现,当数据没有按A列条件排序时,有可能出现重复,只有当数据按A列排序后,对辅助列的判断才可能不出现重复。

<
第一行必须存在,并且不能是数据行,可以是空白行,也可以是标题行





10116 754 754 
1015 754 

10132 754 

10135 754 

1016 754 

1017 754 

101590 754 

10117 754 

1019 754 

10132 754 

1013 754 

1012 754 

1010 754 

010228 1402 1402 
01026 1402 

010211 1402 




关键公式为: =IF(SUMIF(A:A,A3,B:B)=OFFSET(C3,-1,0),"",SUMIF(A:A,A3,B:B))



























































































28BYJ-48 5V Stepper Motor

This stepper motor was bought from taobao.com, along with a UNL2003 driver board. I knew nothing about the stepper before so googled online and found the article from this blog, this article showed procedures on how to disclose the motor. The photos he took showed the structure of the motor clearly how it worked.









Because the step angle of the rotor is 5.625, so it needs 64 pulses for the rotor to make a full rotation, and, what's more, this type of motor is reducing one, the slow down ratio is 1:64, so,  there should be 64*64 = 4096 pulses to rotate at 360 degrees for the output shaft.

The internal picture of ULN2003 looks as below:



The ULN2003 acts as a relay, it is not a true stepper driver at point of my view :-).  Since the frequency of arduino's IO is about 500Hz, it would take 8 seconds

approximately to make the shaft turn a round, so the max speed is about 7RPM, oooops, it runs toooo slowly and is not acceptable at all in a real world application.

2011年7月19日星期二

Getting rid of displayNotification in Delphi 2010

Oooops, I ran into this exception once again, last time it worked fine after deleting the cache files of IE, but it did not work this time. It displayed TEmbarcadero.Create on the upper right corner of the IDE, it seemed attempt on getting connected to the homepage of Embarcadero or somewhere, after several attempts, it failed to load the IDE and said displayNotification堆栈溢出 and out of memory.

So I got into the registry to see what I could do, after deleting all the subitems in the  following items
       HKEY_CURRENT_USER\Software\CodeGear\BDS\7.0\Closed Files
       HKEY_CURRENT_USER\Software\CodeGear\BDS\7.0\Closed Projects

and, it is fine now.

2011年7月15日星期五

利用Processing显示Arduino电压

从淘宝买的arduino单片机到手几天了,依葫芦画瓢也成功让LED点亮,甚至用PWM来调节LED的亮度。今天下午还“成功”的让步进电机转动起来,即使转速像蜗牛一般。

刚才从网上抄来一段程序,就是利用Processing来显示Arduino单片机引脚的电压,显示结果如下:



程序来自:http://boolscott.wordpress.com/2010/02/04/arduino-processing-analogue-bar-graph-2/


Arduino部分:
//Sending 8 bit reading (256) so analogue
//reading can be sent in 1 byte

int Analogue0 = 0;    // first analog sensor
int Analogue1 = 0;   // second analog sensor
int Analogue2 = 0;    // digital sensor
int Analogue3 = 0;   // second analog sensor
int Analogue4 = 0;   // second analog sensor
int Analogue5 = 0;   // second analog sensor
int inByte = 0;         // incoming serial byte

void setup()
{
  // start serial port at 9600 bps:
  Serial.begin(9600);

  establishContact();  // send a byte to establish contact until Processing responds
}

void loop()
{
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
    // read first analog input, divide by 4 to make the range 0-255:
    Analogue0 = analogRead(0)/4;
    // delay 10ms to let the ADC recover:
    delay(10);
    // read second analog input, divide by 4 to make the range 0-255:
    Analogue1 = analogRead(1)/4;
    // read  switch, multiply by 155 and add 100
    // so that you're sending 100 or 255:
    delay(10);
    Analogue2 = analogRead(2)/4;
    delay(10);
    Analogue3 = analogRead(3)/4;
    delay(10);
    Analogue4 = analogRead(4)/4;
    delay(10);
    Analogue5 = analogRead(5)/4;
    delay(10);

    // send sensor values:
    Serial.print(Analogue0 , BYTE);
    Serial.print(Analogue1 , BYTE);
    Serial.print(Analogue2 , BYTE);
    Serial.print(Analogue3 , BYTE);
    Serial.print(Analogue4 , BYTE);
    Serial.print(Analogue5 , BYTE);
  }
}

void establishContact() {
 while (Serial.available() <= 0) {
      Serial.print('A', BYTE);   // send a capital A
      delay(300);
  }
}


Processing部分:(在源程序基础之上修改了串口号)

// Feel Free to edit these variables ///////////////////////////
String  xLabel = "Analogue Inputs";
String  yLabel = "Voltage (V)";
String  Heading = "The Graph Sketch";
String  URL = "01/02/2010";
float Vcc = 5.0;    // the measured voltage of your usb
int NumOfVertDivisions=5;      // dark gray
int NumOfVertSubDivisions=10;  // light gray

int NumOfBars=6;    // you can choose the number of bars, but it can cause issues
                    // since you should change what the arduino sends

// if these are changed, background image has problems
// a plain background solves the problem
int ScreenWidth = 600, ScreenHeight=400;
/////////////////////////////////////////////////////////

//  Serial port stuff ///////////////////////
import processing.serial.*;
Serial myPort;
boolean firstContact = false;
int[] serialInArray = new int[6];
int serialCount = 0;
///////////////////////////////////////////////

int LeftMargin=100;
int RightMArgin=80;
int TextGap=50;
int GraphYposition=80;
float BarPercent = 0.4;

int value;

PFont font;
PImage bg;

int temp;
float yRatio = 0.58;
int BarGap, BarWidth, DivisounsWidth;
int[] bars = new int[NumOfBars];

void setup(){

 // bg = loadImage("BG.jpg");

  /// NB SETTINGS ////////////////////////////////////////////////////////
  myPort = new Serial(this, Serial.list()[0], 9600);
  ////////////////////////////////////////////////////////////////////////

  DivisounsWidth = (ScreenWidth-LeftMargin-RightMArgin)/(NumOfBars);
  BarWidth = int(BarPercent*float(DivisounsWidth));
  BarGap = DivisounsWidth - BarWidth;

  size(ScreenWidth,ScreenHeight);
  font = createFont("Arial",12);

  textAlign(CENTER);
  textFont(font);
}

void draw(){

//  background(bg);     // My one used a background image, I've
  background(250);      // commented it out and put a plain colour

  //  Headings();           // Displays bar width, Bar gap or any variable.
  Axis();
  Labels();
  PrintBars();
}

// Send Recieve data //
void serialEvent(Serial myPort) {

  // read a byte from the serial port:
  int inByte = myPort.read();

  if (firstContact == false) {
    if (inByte == 'A') {
      myPort.clear();          // clear the serial port buffer
      firstContact = true;     // you've had first contact from the microcontroller
      myPort.write('A');       // ask for more
    }
  }
  else {
    // Add the latest byte from the serial port to array:
    serialInArray[serialCount] = inByte;
    serialCount++;

    // If we have 6 bytes:
    if (serialCount > 5 ) {

for (int x=0;x<6;x++){

  bars[x] = int (yRatio*(ScreenHeight)*(serialInArray[x]/256.0));

}

      // Send a capital A to request new sensor readings:
      myPort.write('A');
      // Reset serialCount:
      serialCount = 0;
    }
  }
}

/////// Display any variables for testing here//////////////
void Headings(){
  fill(0 );
  text("BarWidth",50,TextGap );
  text("BarGap",250,TextGap );
  text("DivisounsWidth",450,TextGap );
  text(BarWidth,100,TextGap );
  text(BarGap,300,TextGap );
  text(DivisounsWidth,520,TextGap );
}

void PrintBars(){

  int c=0;
  for (int i=0;i<NumOfBars;i++){

    fill((0xe4+c),(255-bars[i]+c),(0x1a+c));
    stroke(90);
    rect(i*DivisounsWidth+LeftMargin,   ScreenHeight-GraphYposition,   BarWidth,   -bars[i]);
    fill(0x2e,0x2a,0x2a);
    text(float(bars[i])/(yRatio*(ScreenHeight))*Vcc,   i*DivisounsWidth+LeftMargin+BarWidth/2,   ScreenHeight-bars[i]-5-GraphYposition );
    text("A",   i*DivisounsWidth+LeftMargin+BarWidth/2 -5,   ScreenHeight-GraphYposition+20 );
    text(i,   i*DivisounsWidth+LeftMargin+BarWidth/2 +5,   ScreenHeight-GraphYposition+20 );
  }
}

void Axis(){

  strokeWeight(1);
  stroke(220);
  for(float x=0;x<=NumOfVertSubDivisions;x++){

    int bars=(ScreenHeight-GraphYposition)-int(yRatio*(ScreenHeight)*(x/NumOfVertSubDivisions));
    line(LeftMargin-15,bars,ScreenWidth-RightMArgin-DivisounsWidth+50,bars);
  }
  strokeWeight(1);
  stroke(180);
  for(float x=0;x<=NumOfVertDivisions;x++){

    int bars=(ScreenHeight-GraphYposition)-int(yRatio*(ScreenHeight)*(x/NumOfVertDivisions));
    line(LeftMargin-15,bars,ScreenWidth-RightMArgin-DivisounsWidth+50,bars);
  }
  strokeWeight(2);
  stroke(90);
  line(LeftMargin-15, ScreenHeight-GraphYposition+2, ScreenWidth-RightMArgin-DivisounsWidth+50, ScreenHeight-GraphYposition+2);
  line(LeftMargin-15,ScreenHeight-GraphYposition+2,LeftMargin-15,GraphYposition);
  strokeWeight(1);
}

void Labels(){
  textFont(font,18);
  fill(50);
  rotate(radians(-90));
  text(yLabel,-ScreenHeight/2,LeftMargin-45);
  textFont(font,16);
  for(float x=0;x<=NumOfVertDivisions;x++){

    int bars=(ScreenHeight-GraphYposition)-int(yRatio*(ScreenHeight)*(x/NumOfVertDivisions));
    text(round(x),-bars,LeftMargin-20);
  }

  textFont(font,18);
  rotate(radians(90));
  text(xLabel,LeftMargin+(ScreenWidth-LeftMargin-RightMArgin-50)/2,ScreenHeight-GraphYposition+40);
  textFont(font,24);
  fill(50);
  text(Heading,LeftMargin+(ScreenWidth-LeftMargin-RightMArgin-50)/2,70);
  textFont(font);

  fill(150);
  text(URL,ScreenWidth-RightMArgin-40,ScreenHeight-15);
  textFont(font);

}