我正在尝试编写一个c#库,该库查看树莓派上所有可用的USB串行端口,以便我可以枚举,识别并通过USB集线器与一组连接到Pi的arduino进行通信。
我能够使这个工作在我的windows机器(几个Arduinos连接到我的台式电脑),甚至已经能够使它在我的Pi上工作,然而,我正在努力理解如何推广修复。
如果我尝试在Pi上自己运行程序,我可以打开串行端口并发送数据,但是,我无法从Arduinos接收任何东西:我得到超时异常。我理解Mono的SerialPort实现是有限的,我必须使用SerialPort. readbyte()而不是Readline()和接收到的数据事件(我的解决方案是基于howtosystemiopports的代码)。我的串口枚举使用的方法在这里的另一个堆栈交换响应中概述。
我的超时目前设置为4秒,这比我期望接收消息的时间长几个数量级。
经过大量的谷歌搜索,我偶然提到使用minicom来初始化这里的串行端口,令我惊讶的是,这允许我从Arduino接收数据。最大的缺点是我需要使用minicom初始化端口,并且每次启动Pi时都打开该进程。我似乎也不知道如何使这个工作与多个arduino。
这是我到目前为止所尝试的:
- 将Pi固件和软件更新到最新版本
- 试图同时使用Arduino MEGA 2560 R3和Arduino UNO
- 将tty*端口的所有者(在本例中为ttyACM0和ttyUSB0)更改为我的用户和组
- 通过minicom成功配置端口,使进程运行并启动程序并读写数据。一个手动过程,似乎只适用于一个Arduino在同一时间
- 程序在Windows下正常运行
- 验证arduino被Pi识别运行"dmesg | grep tty"
以下是我希望解决的问题:
- Arduino串口的自动设置/初始化。无论是通过shell脚本在主程序之前运行还是在Mono代码中运行,以便下面的代码可以按预期运行。
这是我的连接代码:
public bool StartArduinoComms()
{
string[] ports = GetPortNames();
foreach (string port in ports)
{
mLogger.LogMessage(ProsthesisCore.Utility.Logger.LoggerChannels.Arduino, string.Format("Found serial port {0}", port));
}
bool foundCorrectArduino = false;
var idPacket = new ArduinoMessageBase();
idPacket.ID = ArduinoMessageValues.kIdentifyValue;
string jsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(idPacket);
foreach (string port in ports)
{
SerialPort serialPort = new SerialPort(port, kArduinoCommsBaudRate);
serialPort.Parity = Parity.None;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
//Only check unopened ports
if (!serialPort.IsOpen)
{
serialPort.Open();
//Disable telemtry just incase
var toggle = new { ID = ArduinoMessageValues.kTelemetryEnableValue, EN = false };
string disableTelem = Newtonsoft.Json.JsonConvert.SerializeObject(toggle);
serialPort.Write(disableTelem);
//Discard any built up data
serialPort.DiscardInBuffer();
serialPort.Write(jsonOutput);
serialPort.ReadTimeout = kIDTimeoutMilliseconds;
string response = string.Empty;
for (int i = 0; i < kNumRetries; ++i)
{
try
{
//This is guaranteed to timeout if not configured through minicom
response = ReadLine(serialPort);
break;
}
//Catch case where the serial port is unavailable. MOve to next port
catch (TimeoutException)
{
continue;
}
}
if (!string.IsNullOrEmpty(response))
{
//Perform response validation
}
else
{
//Got no response
}
if (!foundCorrectArduino)
{
serialPort.Close();
}
}
}
return foundCorrectArduino;
}
/// <summary>
/// From https://stackoverflow.com/questions/434494/serial-port-rs232-in-mono-for-multiple-platforms
/// </summary>
/// <returns></returns>
private static string[] GetPortNames()
{
int p = (int)Environment.OSVersion.Platform;
List<string> serial_ports = new List<string>();
// Are we on Unix?
if (p == 4 || p == 128 || p == 6)
{
string[] ttys = System.IO.Directory.GetFiles("/dev/", "tty*");
foreach (string dev in ttys)
{
//Arduino MEGAs show up as ttyACM due to their different USB<->RS232 chips
if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM"))
{
serial_ports.Add(dev);
}
}
}
else
{
serial_ports.AddRange(SerialPort.GetPortNames());
}
return serial_ports.ToArray();
}
看一下stty命令。它会让你设置/读取终端设置
http://linux.about.com/od/lna_guide/a/gdelna38t01.htm将给出它的使用概述。它将更容易调用到比minicom,设置留在设备上。
我做过和你一样的事。我必须通过USB串行适配器读写数据,并且没有使用minicom。它可能不是很好的代码,但我发现,为了读取数据,我可以创建一个新的线程,并检查数据,我的代码包括很多东西,但基本上我这样做:
System.Threading.Thread newThread;
newThread = new System.Threading.Thread(this.check_get_data);
和check_get_data方法
public void check_get_data ()
{
byte tmpByte = 0;
while (m_objSerialPort.BytesToRead != 0) {
tmpByte = (byte)m_objSerialPort.ReadByte ();
DoSomethingWithByte(tmpByte);
Thread.Sleep(20);
}
}
当前与两个usbserials一起运行。不知道是否有帮助,但希望你找到你的解决方案