class jzSerial { public: jzSerial() { } String readString(char terminalChar = '\n') { char rcv='\0'; String str=""; while (rcv!=terminalChar) { while (Serial.available()>0) { rcv=Serial.read(); str+=rcv; } } return str; } int readInteger(char terminalChar='\n') { char * value; String s; s=readString(terminalChar); value = &s[0]; return atoi(value); } void printString(String value) { int len; char c; len= value.length(); for (int i=0; i<len; i++) { c=value[i]; Serial.print(char(c)); } } void printLineString (String value) { printString(value); Serial.println(""); } void printInteger(int value) { int bufSize = 20; char buf[bufSize]; itoa(value,buf,10); char c; int i=0; c=buf[i]; while (c!='\0') { Serial.print(char(c)); i++; c=buf[i]; } } void printLineInteger(int value) { printInteger(value); Serial.println(""); } float readFloat(char terminalChar='\n') { String str=""; char * buf; str=readString(terminalChar); buf=&str[0]; return (atof(buf)); } void printFloat(float value) { Serial.print(value); } void printLineFloat(float value) { Serial.println(value); } }; //测试 jzSerial newSerial; int i; String s; void setup() { Serial.begin(9600); Serial.print(236545845); Serial.println("Read integer from keyboard"); i=newSerial.readInteger(); newSerial.printLineInteger(i); Serial.println("Read string from keyboard"); s=newSerial.readString(); newSerial.printLineString(s); } void loop() { Serial.println("Read float from keyboard"); Serial.println(newSerial.readFloat()); }
2012年1月25日星期三
将读取/发送字符的功能封装在类中间
由于HardwareSerial没有函数直接读取字符、整数等,而在实际应用中却常常会用到,因此把这部分功能封装到类中间去,便于今后调用。最好的方式是子类化HardwareSerial类,但是该类的构造函数比较复杂,因此先将读取或者发送字符的功能封装到普通的类,在实现过程中调用Serial实例。
2011年8月19日星期五
Arduino软件生成遥控方波与AUX遥控器原始方波的对比
这篇博客是前面AUX遥控器红外信号分析的续篇。
由于红外协议有好几种,功力原因,分析起来比较困难,因此权衡之后,还是决定采取用软件方式,模拟AUX空调的遥控信号。
前面博文分析得出结论是,帧与帧之间的间隔(这个词语可能跟标准术语有区别,在此是指相邻的下降沿和上升沿之间的间隔时间)是760us,源代码中设置的间隔为912us,这个数字是综合考虑delay以及源程序中其它指令的耗时等因素,以及考察红外方波波形之后计算所得。
而实际产生的波形与遥控器的原始波形之间,存在比较大的差异,而且这个差异比较怪异,
源代码:
char *strOpen="000000000111101101101010101011011011011011010101010110101010101011011011011010101101010101010101010101011010101010101010101010101010101101010101010101010101010101010101010101010101010110101010101010101101101101101011010101010101010101101101010110";
int lenOfOpen =246;
unsigned int openCode[246];
int pinOut= 28;
void setup()
{
pinMode(pinOut,OUTPUT);
Serial.begin(9600);
StringToArray();
}
void StringToArray()
{
int i;
char c;
for (i=0; i<lenOfOpen; i++)
{
c= strOpen[i];
//Serial.print(c);
//Serial.print('|');
if (c=='1')
openCode[i]=1;
else
openCode[i]=0;
//debug mode
//Serial.println(openCode[i]);
}
}
void loop()
{
int i;
for (i=0; i< lenOfOpen; i++)
{
digitalWrite(pinOut, openCode[i]);
delayMicroseconds(912);
//Serial.println(openCode[i]);
}
}
需要重新计算间隔时间。
由于红外协议有好几种,功力原因,分析起来比较困难,因此权衡之后,还是决定采取用软件方式,模拟AUX空调的遥控信号。
前面博文分析得出结论是,帧与帧之间的间隔(这个词语可能跟标准术语有区别,在此是指相邻的下降沿和上升沿之间的间隔时间)是760us,源代码中设置的间隔为912us,这个数字是综合考虑delay以及源程序中其它指令的耗时等因素,以及考察红外方波波形之后计算所得。
而实际产生的波形与遥控器的原始波形之间,存在比较大的差异,而且这个差异比较怪异,
- 整个信号宽度比原始信号要宽出一截(见图1);
- 1T、2T波形的宽度有比较大的差距,比原始信号要宽(见图2);
- 4T比原始信号宽度要窄(见图3);
- 两个9T信号之间几乎没有差别(见图3)。
![]() |
| 图1 |
![]() |
| 图2 |
![]() |
| 图3 |
源代码:
char *strOpen="000000000111101101101010101011011011011011010101010110101010101011011011011010101101010101010101010101011010101010101010101010101010101101010101010101010101010101010101010101010101010110101010101010101101101101101011010101010101010101101101010110";
int lenOfOpen =246;
unsigned int openCode[246];
int pinOut= 28;
void setup()
{
pinMode(pinOut,OUTPUT);
Serial.begin(9600);
StringToArray();
}
void StringToArray()
{
int i;
char c;
for (i=0; i<lenOfOpen; i++)
{
c= strOpen[i];
//Serial.print(c);
//Serial.print('|');
if (c=='1')
openCode[i]=1;
else
openCode[i]=0;
//debug mode
//Serial.println(openCode[i]);
}
}
void loop()
{
int i;
for (i=0; i< lenOfOpen; i++)
{
digitalWrite(pinOut, openCode[i]);
delayMicroseconds(912);
//Serial.println(openCode[i]);
}
}
需要重新计算间隔时间。
2011年8月15日星期一
Arduino中digitalWrite的一点疑惑
做Blink试验时,就曾经有点疑惑,digitalWrite往某个pin写入HIGH或LOW之后,该pin的状态是如何维护的呢?用万用表量输出脚的电压时,HIGH状态时是4.90v,LOW状态时是0.00v,但是示波器查看到的波形却有点不一致:
从图上看出,状态设置为HIGH or LOW之后,该输出脚的状态处在一个中间值,而并不是一直处于HIGH or LOW,跟万用表量到的数据似乎有点矛盾。
源代码:
int P13=13;
boolean val=true;
void setup()
{
pinMode(P13,OUTPUT);
Serial.begin(96000);
}
void loop()
{
if (val)
digitalWrite(P13,HIGH);
else
digitalWrite(P13,LOW);
delay(1500);
val = !val;
//Serial.println(val);
}
![]() |
| pin13电压波形图 |
![]() |
| 采集到的电压峰值为正负0.3v,中间处于0v上下 |
源代码:
int P13=13;
boolean val=true;
void setup()
{
pinMode(P13,OUTPUT);
Serial.begin(96000);
}
void loop()
{
if (val)
digitalWrite(P13,HIGH);
else
digitalWrite(P13,LOW);
delay(1500);
val = !val;
//Serial.println(val);
}
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);
}
当然上面的代码只是为了演示和学习需要,所以会很不完善甚至有错误的地方。
功能需求:
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);
}
}
}
}
先把代码贴出来,错误有待慢慢去修改。
接线图
上位机的问题就是,当单击停止按钮关闭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;
char* Str; //strings received
int PWMValue; //PWM value received from PC
int PinOUT=10;
void setup()
{
Serial.begin(9600);
pinMode(PinOUT, OUTPUT);
}
{
Serial.begin(9600);
pinMode(PinOUT, OUTPUT);
}
int ReadPWM()
{
int Result=255;
while (!Serial.available())
{
//等到有输入再退出等待
}
Result = Serial.read();
{
int Result=255;
while (!Serial.available())
{
//等到有输入再退出等待
}
Result = Serial.read();
Serial.flush();
return Result;
}
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;
}
}
{
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);
}
}
{
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日星期五
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
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.
标签:
Arduino,
Stepper Motor,
ULN2003
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);
}
刚才从网上抄来一段程序,就是利用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);
}
2011年7月2日星期六
Arduino离我还有多远
Arduino是一款开源硬件产品,比较适合像我这类小白菜,本来打算入手一个,连东西都放进购物车了的,结帐时候才发现,数字证书已经在几个月之前失效。:(
这个是从网上找来的Arduino Mega 1280的参数
Arduino MEGA 规格参数:
1.微控制器核心:ATmega1280-16AU
2.工作电压:+5V
3.外部输入电压:+7V~+12V(建议)
4.外部输入电压(极值):+6V≤Vin≤+20V
5.数字信号I/O接口:54(其中14个PWM输出接口)
6.模拟信号输入接口:16
7.DC I/O接口电流:40 mA
7.Flash容量:128 KB (其他4K用于bootloader)
8.SRAM静态存储容量:8KB
9.EEPROM存储容量:4KB
10.时钟频率:16MHz
下面是一些值得去的网站:
www.arduino.cc
这个是从网上找来的Arduino Mega 1280的参数
Arduino MEGA 规格参数:
1.微控制器核心:ATmega1280-16AU
2.工作电压:+5V
3.外部输入电压:+7V~+12V(建议)
4.外部输入电压(极值):+6V≤Vin≤+20V
5.数字信号I/O接口:54(其中14个PWM输出接口)
6.模拟信号输入接口:16
7.DC I/O接口电流:40 mA
7.Flash容量:128 KB (其他4K用于bootloader)
8.SRAM静态存储容量:8KB
9.EEPROM存储容量:4KB
10.时钟频率:16MHz
下面是一些值得去的网站:
www.arduino.cc
订阅:
博文 (Atom)











