【发布时间】:2019-08-11 15:08:33
【问题描述】:
我正在制作一个将 LED 照明指令发送到 sparkfun pro micro 的 c# 程序。它通常一开始可以工作,但是在更改其中一个颜色滑块时有可能会失败,导致 com 端口繁忙且无法使用,直到我断开 pro micro 并将其代码重新上传到它
我试图在我的 catch 语句中关闭端口,但它似乎根本没有帮助(我认为实际上让事情变得更糟)。我不确定是我的串口类是问题还是 pro 微代码是问题,所以我将两者都发布
首先,串口类。这是在每个轨迹栏的 Scroll 事件上运行的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows.Forms;
using System.Diagnostics;
namespace LED_Controller
{
public class SerialPortsAccess
{
public string testString;
private SerialPort port;// = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One);
[STAThread]
static void createNew(string[] args)
{
//new SerialPortsAccess("COM3");
}
public SerialPortsAccess(string COM)
{
string[] lastInfo = System.IO.File.ReadAllLines(@"C:\Users\Alex\source\repos\LED Controler\LED Controler\Last.txt");
string stringout = "";
port = new SerialPort(COM, 9600, Parity.None, 8, StopBits.One);
try
{
port.Open();
for (int i = 0; i < lastInfo.Length; i++)
{
//port.WriteLine(lastInfo[i]);
stringout += lastInfo[i];
if ((i + 1) < lastInfo.Length)
{
stringout += '|';
}
}
stringout += '\n';
port.Write(stringout);
Debug.WriteLine(stringout);
port.Close();
}
catch
{
//try
//{
//port.Close();
//}
//catch
//{
//}
Debug.WriteLine("NO DEVICE FOUND");
}
}
}
}
这是我的 arduino 代码。它很长,但大多数 getData() 函数都在为每个变量重复相同的过程(我是新手,所以我的技术可能很糟糕):
#include <SPI.h>
#include <Adafruit_DotStar.h>
#define NUMPIXELS 60
Adafruit_DotStar strip = Adafruit_DotStar(NUMPIXELS, DOTSTAR_BRG);
// Variables
int mode;
int numColors;
int fadeSpeed;
int BBCC;
int R;
int G;
int B;
int Bright;
int readLine(int readch, char * buffer, int len)
{
static int pos = 0;
int rpos;
if (readch > 0)
{
switch(readch)
{
case '\r':
{
break;
}
case '\n':
{
rpos = pos;
pos = 0;
return rpos;
}
default:
{
if (pos < len-1)
{
buffer[pos++] = readch;
buffer[pos] = 0;
}
}
}
return 0;
}
}
void loop() {
getData();
if (mode == 1)
{
for (int i = 0; i < NUMPIXELS; i++)
{
strip.setPixelColor(i, G, R, B);
}
strip.setBrightness(Bright);
strip.show();
}
else
{
strip.setPixelColor(0, 255, 255, 255);
strip.setBrightness(25);
strip.show();
}
}
void getData() // this function has a do while loop for each variable. Sorry if this is bad form
{
char buf[80];
bool redo = true;
if(readLine(Serial.read(), buf, 80) > 0)
{
int i = 0;
int j = 0;
bool skip = false;
char fin[3];
if (skip == false)
{
do// mode
{
switch (buf[i])
{
case '\n':
{
skip = true;
redo = false;
break;
}
case '|':
{
mode = atoi(fin);
//Serial.print(mode);
i++;
redo = false;
break;
}
default:
{
fin[j] = buf[i];
i++;
break;
}
}
j++;
}while(redo);
redo = true;
j = 0;
}
if (skip == false)
{
do// number of colors
{
switch (buf[i])
{
case '\n':
{
skip = true;
redo = false;
break;
}
case '|':
{
numColors = atoi(fin);
//Serial.print(numColors);
i++;
redo = false;
break;
}
default:
{
fin[j] = buf[i];
i++;
break;
}
}
j++;
}while(redo);
redo = true;
j = 0;
}
if (skip == false)
{
do//
{
switch (buf[i])
{
case '\n':
{
skip = true;
redo = false;
break;
}
case '|':
{
fadeSpeed = atoi(fin);
//Serial.print(fadeSpeed);
i++;
redo = false;
break;
}
default:
{
fin[j] = buf[i];
i++;
break;
}
}
j++;
}while(redo);
redo = true;
j = 0;
}
if (skip == false)
{
do
{
switch (buf[i])
{
case '\n':
{
skip = true;
redo = false;
break;
}
case '|':
{
BBCC = atoi(fin);
//Serial.print(BBCC);
i++;
redo = false;
break;
}
default:
{
fin[j] = buf[i];
i++;
break;
}
}
j++;
}while(redo);
redo = true;
j = 0;
}
if (skip == false)
{
do
{
switch (buf[i])
{
case '\n':
{
skip = true;
redo = false;
break;
}
case '|':
{
R = atoi(fin);
//Serial.print(R);
i++;
redo = false;
break;
}
default:
{
fin[j] = buf[i];
i++;
break;
}
}
j++;
}while(redo);
redo = true;
j = 0;
}
if (skip == false)
{
do
{
switch (buf[i])
{
case '\n':
{
skip = true;
redo = false;
break;
}
case '|':
{
G = atoi(fin);
//Serial.print(G);
i++;
redo = false;
break;
}
default:
{
fin[j] = buf[i];
i++;
break;
}
}
j++;
}while(redo);
redo = true;
j = 0;
}
if (skip == false)
{
do
{
switch (buf[i])
{
case '\n':
{
skip = true;
redo = false;
break;
}
case '|':
{
B = atoi(fin);
//Serial.print(B);
i++;
redo = false;
break;
}
default:
{
fin[j] = buf[i];
i++;
break;
}
}
j++;
}while(redo);
redo = true;
j = 0;
}
if (skip == false)
{
do
{
switch (buf[i])
{
case '\n':
{
Bright = atoi(fin);
//Serial.println(Bright);
i++;
redo = false;
break;
}
default:
{
fin[j] = buf[i];
i++;
break;
}
}
j++;
}while(redo);
redo = true;
j = 0;
}
}
}
c# 代码应该在每次跟踪栏更改时将数据发送到表单一次,然后关闭端口,直到进行另一次更改。 pro micro 应该接收代码并解释它。但是,在此过程中的某个地方,连接已断开并且不会重新建立。这里出了什么问题?
编辑:我尝试使用数据接收事件,但现在端口甚至无法打开。因为访问被拒绝。我用错了吗?新的c#代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows.Forms;
using System.Diagnostics;
namespace LED_Controller
{
public class SerialPortsAccess
{
public string testString;
bool fail = false;
private SerialPort port;// = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One);
[STAThread]
static void createNew(string[] args)
{
//new SerialPortsAccess("COM3");
}
public SerialPortsAccess(string COM)
{
port = new SerialPort(COM, 9600, Parity.None, 8, StopBits.One);
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
//try
//{
port.Open();
//}
//catch
//{
//Debug.WriteLine("ERROR OPENING PORT");
//}
}
public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string[] lastInfo = System.IO.File.ReadAllLines(@"C:\Users\Alex\source\repos\LED Controler\LED Controler\Last.txt");
string stringout = "";
do
{
try
{
//port.Open();
for (int i = 0; i < lastInfo.Length; i++)
{
//port.WriteLine(lastInfo[i]);
stringout += lastInfo[i];
if ((i + 1) < lastInfo.Length)
{
stringout += '|';
}
}
stringout += '\n';
port.Write(stringout);
Debug.WriteLine(stringout);
port.Close();
}
catch
{
fail = true;
Debug.WriteLine("DEVICE LOST");
port.Close();
}
} while (fail == false);//port.BytesToRead != 0);
}
}
}
【问题讨论】:
-
使用同步 Serial.read() 会导致读取不均匀。最好使用异步方法。同步读取被机器上的其他进程阻塞,而异步读取使用在其他进程运行时不会被阻塞的事件。
-
是否有异步 Serial.read() 等效项?我很难找到一个
-
查看以下 msdn 页面事件 DataReceived : docs.microsoft.com/en-us/dotnet/api/…
-
我很困惑。那么我的 Arduino 代码可以吗,但是我的串行端口类是问题所在?或者是周围的其他方式?另外,如果我将数据发送到我的 C# 程序,DataRecieved 事件是否适用,或者我应该将 DataRecieved 事件添加到我的专业微代码中?
-
两者都不是。您的机器是多处理器并与您的代码并行运行其他进程。由于其他应用程序正在运行,您正在接收数据而不是处理。因此,您会在接收缓冲区中积压,从而创建随机时间。使用 Async (Events) 可以让您的应用更均匀地处理接收到的数据。
标签: c# arduino serial-port led