我已购买SainSmart 16 Channel controller USB HID Programmable Control Relay Module来控制相应的16通道继电器板。
提供的源代码非常糟糕,但包括一个cmd行程序,可以很好地控制继电器。我试图使用C#创建一个GUI来向程序发送命令。我在这个网站上做了一些阅读,但我并没有走得太远。
最终我需要发送参数" afEd5打开01"然后暂停几秒,然后发送参数" afEd5关闭01"到CommandApp.exe。
非常感谢任何帮助,谢谢。
更新:到目前为止找出了大部分编码,我现在只有一个小问题是CommandApp.exe的位置。我更喜欢它位于应用程序的主要exe而不是C的根目录。
using System;
using System.Threading.Tasks;
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.Diagnostics;
namespace GenesisDigitalInterface
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Toggle Power Button relay
private void PowerButton_Click(object sender, EventArgs e)
{
Process controlusb = new Process();
controlusb.StartInfo = new ProcessStartInfo("C:\\CommandApp.exe");
controlusb.StartInfo.Arguments = "afEd5 open 01";
controlusb.StartInfo.UseShellExecute = false;
controlusb.StartInfo.LoadUserProfile = true;
controlusb.StartInfo.RedirectStandardInput = true;
controlusb.StartInfo.RedirectStandardOutput = true;
controlusb.StartInfo.RedirectStandardError = true;
controlusb.Start();
Thread.Sleep(100);
controlusb.StartInfo = new ProcessStartInfo("C:\\CommandApp.exe");
controlusb.StartInfo.Arguments = "afEd5 close 01";
controlusb.StartInfo.UseShellExecute = false;
controlusb.StartInfo.LoadUserProfile = true;
controlusb.StartInfo.RedirectStandardInput = true;
controlusb.StartInfo.RedirectStandardOutput = true;
controlusb.StartInfo.RedirectStandardError = true;
controlusb.Start();
}
}
}
}
答案 0 :(得分:0)
我猜您错误地初始化了ProcessStartInfo
。它将程序名称作为参数,但我不知道你传递了什么,所以我猜你应该通过"C:\\CommandApp.exe"
并且你应该传递"afEd5 open 01"
作为其参数,而不是启动过程。
所以代码应如下所示:
Process controlusb = new Process();
controlusb.StartInfo = new ProcessStartInfo("C:\\CommandApp.exe");
controlusb.StartInfo.Arguments = "afEd5 open 01";
controlusb.StartInfo.UseShellExecute = false;
controlusb.StartInfo.LoadUserProfile = true;
controlusb.StartInfo.RedirectStandardInput = true;
controlusb.StartInfo.RedirectStandardOutput = true;
controlusb.StartInfo.RedirectStandardError = true;
controlusb.Start();
答案 1 :(得分:0)
我最近不得不在我们正在开发的测试夹具中使用这个特殊的电路板。该文档包含一个没有描述或示例的十六进制值表。字节数据包的长度为 17 个字节,并具有地址、开/关命令和一些反向地址检查字节。其余字节对于单次开启和关闭是“固定的”。我在 C# 中组合了一个 Windows 应用程序,用于操作每个单独的继电器。 (一次一个。我从来没有让全开和全关工作。)我将在此处包含代码,但我希望我能附上整个解决方案。
注意事项:
除此之外,它似乎有效。祝你好运!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
// 16ChannelTest.cs v1.0
// Program to test C# operation of Sain SMART 16 Channel Serial Relay Board
// 7/1/2021 - mwille
// Program "assumes" Com4 is the Serial Relay Board. - Will post an error msg in the textbox if it can't find Com4.
// Developed to support testing and calibration of controller boards.
//
namespace _16ChannelTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
static byte[] TXbuffer = new byte[17] {0x3A,0x46,0x45,0x30,0x35,0x30,0x30,0x30,0x30,0x46,0x46,0x30,0x30,0x46,0x45,0x0D,0x0A};
static byte[] Convert_Address = new byte[17] { 0x00,0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 };
static byte[] T_On_Chk_Value = new byte[17] { 0x00,0x45, 0x44, 0x43, 0x42, 0x41, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x46 };
static byte[] T_Off_Chk_Value = new byte[17] { 0x00, 0x44, 0x43, 0x42, 0x41, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x46, 0x45 };
static byte[] RXbuffer = new byte[18];
static int Relay_Number = 1;
private void btn_Start_Click_1(object sender, EventArgs e)
{
serialPort1.PortName = "COM4";
serialPort1.BaudRate = 9600;
try
{
serialPort1.Open();
}
catch (Exception exc)
{
tb_Logging.AppendText("Exception Thrown \r\n");
tb_Logging.AppendText("" + exc);
tb_Logging.AppendText("\r\n");
}
if (serialPort1.IsOpen)
{
tb_Logging.AppendText("Data Logging Started...");
tb_Logging.AppendText("\r\n");
}
}
public void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (serialPort1.BytesToRead == 17)
serialPort1.Read(RXbuffer, 0, 17);
/* Return to UI thread */
this.Invoke(new EventHandler(DisplayText));
serialPort1.DiscardInBuffer();
}
private void DisplayText(object sender, EventArgs e)
{
tb_Logging.AppendText("--> ");
tb_Logging.AppendText(BitConverter.ToString(RXbuffer));
tb_Logging.AppendText("\r\n");
}
private void clear_RX_Buffer()
{
for (int i = 0; i < 19; i++)
{
RXbuffer[i] = 0x00;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen)
serialPort1.Close();
}
private void Send_Relay_Cmd(byte Relay_ID, byte RCmd, byte Check) // Relay_ID = 1->16, RCmd = 0x46 to turn-on, 0x30 to turn-off, Check = manufacturer set value???
{
// If the port is closed, don't try to send a character.
if (!serialPort1.IsOpen) return;
serialPort1.DiscardInBuffer();
// If the port is Open, setup byte[] array with appropriate elements.
// First, assign hex address using numeric pointer.
TXbuffer[8] = Relay_ID; //Relay Address
TXbuffer[9] = RCmd; // Control Byte #1 -
TXbuffer[10] = RCmd; // Control Byte #2 - 0x46 to turn-on, 0x30 to turn-off
TXbuffer[14] = Check; //Some kind of reverse order check???
Thread.Sleep(500);
// Send the TXbuffer
serialPort1.Write(TXbuffer, 0, 17);
Thread.Sleep(500);
write_Text();
}
private void write_Text()
{
tb_Logging.AppendText("<-- ");
tb_Logging.AppendText(BitConverter.ToString(TXbuffer));
tb_Logging.AppendText("\r\n");
}
// This is the Turn-On button function. It performs the majority of byte formatting for the TX function.
private void Btn_T_On_Click(object sender, EventArgs e)
{
byte Relay_Address;
byte Relay_Cmd;
byte Relay_Check_Byte;
// Using the integer number as the index, return the manufacturers specific hex address byte.
Relay_Address = Convert_Address[Relay_Number];
// Since this is the "Turn-On" button, set the command
Relay_Cmd = 0x46;
// Using the integer number as the index, return the manufacturers specific hex check byte.
Relay_Check_Byte = T_On_Chk_Value[Relay_Number];
Send_Relay_Cmd(Relay_Address,Relay_Cmd,Relay_Check_Byte);
}
private void Btn_T_Off_Click(object sender, EventArgs e)
{
byte Relay_Address;
byte Relay_Cmd;
byte Relay_Check_Byte;
// Using the integer number as the index, return the manufacturers specific hex address byte.
Relay_Address = Convert_Address[Relay_Number];
// Since this is the "Turn-On" button, set the command
Relay_Cmd = 0x30;
// Using the integer number as the index, return the manufacturers specific hex check byte.
Relay_Check_Byte = T_Off_Chk_Value[Relay_Number];
Send_Relay_Cmd(Relay_Address, Relay_Cmd, Relay_Check_Byte);
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 1;
}
private void radioButton2_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 2;
}
private void radioButton3_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 3;
}
private void radioButton4_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 4;
}
private void radioButton5_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 5;
}
private void radioButton6_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 6;
}
private void radioButton7_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 7;
}
private void radioButton8_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 8;
}
private void radioButton9_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 9;
}
private void radioButton10_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 10;
}
private void radioButton11_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 11;
}
private void radioButton12_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 12;
}
private void radioButton13_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 13;
}
private void radioButton14_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 14;
}
private void radioButton15_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 15;
}
private void radioButton16_CheckedChanged(object sender, EventArgs e)
{
Relay_Number = 16;
}
}
}
答案 2 :(得分:-1)
我尝试使用https://github.com/ondrej1024/crelay/files/194375/sain-usb-hid.c.txt中的代码,但它对我不起作用。我之前尝试了许多其他解决方案,但它们也不适用于我。
所以,我为SainSmart 16通道控制器USB HID可编程控制继电器(一个替换CommandApp.exe的控制台应用程序)编写了自己的代码。你可以用它。
代码如下:
Process controlusb = new Process();
controlusb.StartInfo = new ProcessStartInfo("C:\\sain-usb-hid-relay-16.exe");
controlusb.StartInfo.Arguments = "1 1";
controlusb.StartInfo.UseShellExecute = false;
controlusb.StartInfo.LoadUserProfile = true;
controlusb.StartInfo.RedirectStandardInput = true;
controlusb.StartInfo.RedirectStandardOutput = true;
controlusb.StartInfo.RedirectStandardError = true;
controlusb.Start();
用法:sain-usb-hid-relay-16.exe Param1 Param2
参数1:
T or t - Test of relays from 1 to 16 by ON and OFF. Use Param2 as delay in msec.
A or a - All relays.
1..16 - Relay number.
参数2:
1 or 0 - 1 = Relay to ON, 0 = Relay to OFF.
示例:
Example: sain-usb-hid-relay-16.exe 5 1
- Relay #5 is ON.
Example: sain-usb-hid-relay-16.exe 10 0
- Relay #10 is OFF.
Example: sain-usb-hid-relay-16.exe a 1
- All relays is ON.
Example: sain-usb-hid-relay-16.exe t 3000
- All relays will test ON and OFF with each delay = 3000 msec.
sain-usb-hid-relay-16.exe a 1
Relay 65535 ON
sain-usb-hid-relay-16.exe a 0
Relay 65535 OFF
Where 65535 = All relays.
您可以在其他应用中使用它,像“sain-usb-hid-relay-16.exe a 1&gt; result.txt”一样执行app 然后您可以读取文件“result.txt”来解析结果。