controlling a physical device via c# [closed] - c#

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I want to control a physical device. ie: blink some LEDs or turn a servo. (just so simple that I will connect my LED's legs to USB's legs or serial ports pins and send a signal to one of the LED's leg and lit it and same with a servo.)
Question: How can I make this in C#? How can i send a signal through either usb or serial port? What are the things that I need? and how can I manage it? thanks.
messageBox.Show("How to control a physical device via c# ?");
messageBox.Show("thanks");

You can use Your serial port like this:
SerialPort port = new SerialPort("COM1", 2400, Parity.None, 8, StopBits.One);
port.Open();
port.Write(new byte[] {0x00, 0xFF, 0xFF}, 0, 3);
port.Close();
The whole thing will be send bit by bit on one wire on serial port and with additional bits for transmission control.
You can blink LED with this. You need to connect LED to pin Transmit Data and to Ground that is usually the plug cover or one of pins. Check this for reference. You need also resistor to lower the current. 3k [ohm] resistor should do.
Driving small servo motor is possible but not that easy. Its better to control servo with microcontroller connected to Your computer.
You can connect two computers and exchange data with this.
You can burn Your equipment so be careful.
You can also buy or build something like this
EDIT:
Ok, lots of questions.
QUESTION 1) why its hard? cant i just send a signal to the servo and
make it run just like i did on the LED?
Serial port is a communication port so its purpose is to communicate and NOT to drive equipment. Its power capabilities are low. This port will store data to send in buffer and send bit by bit. So its extremely hard to shape PWM \ PPM signal to drive servo and after all result are not gonna be brilliant as well. Depending on motor that You have You may need other control method, but it will be hard to implement with serial port as well. If You really want to drive hardware from a port I would advice parallel port.
QUESTION 2) in which cases i burn my equipment? and do u mean i burn my serial port? or i burn LED or the servo?
QUESTION 3) you said "Your PC should also have current limited output"
so as you referred if i put a resistor then i can manage this? and
does 3k solves in all case?
In case You do not know enough about electrical circuits, networks and analysis then You have big chance to damage Your equipment. You can burn all of them and in worst case scenario also Your PC and house! First two problems that You need to worry about are short circuit and electrostatic discharge
Current limited output should lower current when resistors value is too low. This should prevent the damage of serial port driver on mainboard of PC.
3k resistor complies with serial port specification requirements (3-7[kOhm] <2500[pF]). It should drop taken current below 4[mA]. So in theory it should solve all cases.
QUESTION 4) where will i write your code? in to the button1 clicked? i mean lest say i have a winform and a button there, will i write your code in to the button clicked event?
You can open port on opening Your program. Then write to port on button click. Then close port on close program. All the code on button click should work as well.
PS.: Its also possible to connect serial port to audio input of sound card and then send data on serial port and record it as audio. It works as simple oscilloscope. (You can damage Your PC with this)

You need a device that will translate your USB signals to signals your device understands (likely a simple on or off for LED's).
I have used the U421 in the past, they have a library that you just load the DLL using P/Invoke then you can send signals to the pins on the chip. You will then need to wire whatever you want to control to the chip (correctly, but that is beyond the scope of Stack Overflow, you may want to try Electronics.StackExchange.com). See the U4x1 Application Notes section on the USBMicro website for example code and wiring diagrams.
Example code from the webiste:
⁄⁄ needed to import the .dll
using System.Runtime.InteropServices;
public class USBm
{
public static byte BitA0 = 0x00;
public static byte BitA1 = 0x01;
public static byte BitA2 = 0x02;
public static byte BitA3 = 0x03;
public static byte BitA4 = 0x04;
public static byte BitA5 = 0x05;
public static byte BitA6 = 0x06;
public static byte BitA7 = 0x07;
public static byte BitB0 = 0x08;
public static byte BitB1 = 0x09;
public static byte BitB2 = 0x0A;
public static byte BitB3 = 0x0B;
public static byte BitB4 = 0x0C;
public static byte BitB5 = 0x0D;
public static byte BitB6 = 0x0E;
public static byte BitB7 = 0x0F;
⁄⁄ USBm.dll - C# pInvoke examples
⁄⁄ "Commands"
⁄⁄ [DllImport("USBm.dll", EntryPoint = "USBm_FindDevices", CharSet = CharSet.Auto)]
[DllImport("USBm.dll")]
public static extern bool USBm_FindDevices();
[DllImport("USBm.dll")]
public static extern int USBm_NumberOfDevices();
[DllImport("USBm.dll")]
public static extern bool USBm_DeviceValid(int Device);
[DllImport("USBm.dll")]
public static extern bool USBm_About(StringBuilder About);
[DllImport("USBm.dll")]
public static extern bool USBm_Version(StringBuilder Version);
[DllImport("USBm.dll")]
public static extern bool USBm_Copyright(StringBuilder Copyright);
[DllImport("USBm.dll")]
public static extern bool USBm_DeviceMfr(int Device, StringBuilder Mfr);
[DllImport("USBm.dll")]
public static extern bool USBm_DeviceProd(int Device, StringBuilder Prod);
[DllImport("USBm.dll")]
public static extern int USBm_DeviceFirmwareVer(int Device);
[DllImport("USBm.dll")]
public static extern bool USBm_DeviceSer(int Device, StringBuilder dSer);
[DllImport("USBm.dll")]
public static extern int USBm_DeviceDID(int Device);
[DllImport("USBm.dll")]
public static extern int USBm_DevicePID(int Device);
[DllImport("USBm.dll")]
public static extern int USBm_DeviceVID(int Device);
[DllImport("USBm.dll")]
public static extern bool USBm_DebugString(StringBuilder DBug);
[DllImport("USBm.dll")]
public static extern bool USBm_RecentError(StringBuilder rError);
[DllImport("USBm.dll")]
public static extern bool USBm_ClearRecentError();
[DllImport("USBm.dll")]
public static extern bool USBm_SetReadTimeout(uint TimeOut);
[DllImport("USBm.dll")]
public static extern bool USBm_ReadDevice(int Device, byte[] inBuf);
[DllImport("USBm.dll")]
public static extern bool USBm_WriteDevice(int Device, byte[] outBuf);
[DllImport("USBm.dll")]
public static extern bool USBm_CloseDevice(int Device);
}
Example of function calling
⁄⁄ Test USBm device attached
if ( !USBm.USBm_FindDevices() )
{
MessageBox.Show( string.Format("No Device Present"), "USBm Devices", MessageBoxButtons.OK, MessageBoxIcon.Information );
return;
} ⁄⁄ implied else
⁄⁄Walk the USBm.dll functions
⁄⁄ some containers
StringBuilder sb = new StringBuilder( 200 );
bool result = false; ⁄⁄ return values
⁄⁄ .DLL FindDevices returns the number of devices
result = USBm.USBm_FindDevices();
⁄⁄ return the number of devices
int TotalDevices = USBm.USBm_NumberOfDevices();
int Device = TotalDevices -1; ⁄⁄ only One device is ever attached so ...
⁄⁄ .DLL About info
result = USBm.USBm_About( sb );
⁄⁄ .DLL Version info
result = USBm.USBm_Version( sb );
⁄⁄ .DLL Copyright info
result = USBm.USBm_Copyright( sb );
⁄⁄ Device Valid
result = USBm.USBm_DeviceValid( Device );
⁄⁄ Device Manufacturer
result = USBm.USBm_DeviceMfr( Device, sb );
⁄⁄ Device Product String
result = USBm.USBm_DeviceProd( Device, sb );
⁄⁄ Device Firmware Version
int FirmVer = USBm.USBm_DeviceFirmwareVer(Device);
⁄⁄ Device SerialNumber [ ]
result = USBm.USBm_DeviceSer(Device, sb);
⁄⁄ Device DiD
int DID = USBm.USBm_DeviceDID(Device);
⁄⁄ Device PiD
int PID = USBm.USBm_DevicePID(Device);
⁄⁄ Device ViD
int VID = USBm.USBm_DeviceVID(Device);
⁄⁄ Device Debug String
result = USBm.USBm_DebugString(sb);
⁄⁄ Device Recent Error - always returns true
result = USBm.USBm_RecentError(sb);
⁄⁄ Device Clear Recent Error
result = USBm.USBm_ClearRecentError();
⁄⁄ Device SetReadTimeout [ sixteen-bit millisecond value]
uint tOUT = 3000;
result = USBm.USBm_SetReadTimeout(tOUT);
⁄⁄ Device WriteDevice [ 8 byte to write (device raw commands)]
byte[] OutBuf = { 0, 21, 3, 65, 8, 17, 60, 0 };
result = USBm.USBm_WriteDevice(Device, OutBuf);
⁄⁄ Device ReadDevice [ ]
byte[] InBuf = { 0, 0, 0, 0, 0, 0, 0, 0 };
result = USBm.USBm_ReadDevice(Device, InBuf);
// Device CloseDevice [ ]
result = USBm.USBm_CloseDevice(Device);

Related

Make a C# console app (.net core 3.1) to automatically connect Joycons in paring mode (InTheHand and BluetoothAPIs.dll)

I am trying to write a program in C# that connects to the Nintendo Switch JoyCon controller (which is a Bluetooth HID device) using the InTheHand library and BluetoothAPIs.dll on Windows 11 (But should work for Win10).
My goals are to:
remove/unpair all paired Joycon in a first step
list all Joycon devices in pairing mode state
automatically pair them
I'm using a mix of InTheHand library and BluetoothAPIs.dll Win32 API (Imported inside of C#) and running into issues.
BluetoothClient client = new BluetoothClient();
// Getting connected devices and disconnecting Joycon before repairing them
var connectedDevices = client.PairedDevices;
foreach (BluetoothDeviceInfo d in connectedDevices)
{
Console.WriteLine(d.DeviceName);
if (d.DeviceName.Contains("Joy-Con") == true)
{
Console.WriteLine(d.DeviceName + "-" + d.Connected + "-" + d.Authenticated + "-" + d.DeviceAddress);
UInt32 removingResult = BlueToothStuff.Unpair(d.DeviceAddress);
if (removingResult == 0)
{
Console.WriteLine("SUCCESS!");
}
else
{
Console.Write("ERROR... {0}", removingResult);
}
}
}
The code for BlueToothStuff.Unpair is here:
static public UInt32 Unpair(UInt64 Address)
{
BLUETOOTH_ADDRESS Addr = new BLUETOOTH_ADDRESS();
Addr.ullLong = Address;
UInt32 result = BluetoothRemoveDevice(ref Addr);
return result;
}
[StructLayout(LayoutKind.Explicit)]
public struct BLUETOOTH_ADDRESS
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.I8)]
public UInt64 ullLong;
[FieldOffset(0)]
[MarshalAs(UnmanagedType.U1)]
public Byte rgBytes_0;
[FieldOffset(1)]
[MarshalAs(UnmanagedType.U1)]
public Byte rgBytes_1;
[FieldOffset(2)]
[MarshalAs(UnmanagedType.U1)]
public Byte rgBytes_2;
[FieldOffset(3)]
[MarshalAs(UnmanagedType.U1)]
public Byte rgBytes_3;
[FieldOffset(4)]
[MarshalAs(UnmanagedType.U1)]
public Byte rgBytes_4;
[FieldOffset(5)]
[MarshalAs(UnmanagedType.U1)]
public Byte rgBytes_5;
};
[DllImport("BluetoothAPIs.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.U4)]
static extern UInt32 BluetoothRemoveDevice([param: In, Out] ref BLUETOOTH_ADDRESS pAddress);
}
For the 2) and 3) I use InTheHand:
var task = Task.Run(async () => {
while (true)
{
Console.WriteLine("Looking...");
var devices = client.DiscoverDevices();
foreach (BluetoothDeviceInfo d in devices)
{
if (d.DeviceName.Contains("Joy-Con") == true)
{
client.Connect(d.DeviceAddress, BluetoothService.HumanInterfaceDevice);
}
}
}
});
Console.WriteLine("\nLOOKING FOR Joycon NOW, --> Press any key when all your Joycon are paired!");
Console.ReadKey(true);
My issue is that client.Connect(d.DeviceAddress, BluetoothService.HumanInterfaceDevice); is systematically crashing:
System.Net.Sockets.SocketException (0x80004005): A socket operation failed because the destination host was down
at InTheHand.Net.Sockets.Win32Socket.ThrowOnSocketError(Int32 result, Boolean throwOnDisconnected)
at InTheHand.Net.Sockets.Win32Socket.Connect(EndPoint remoteEP)
at InTheHand.Net.Sockets.BluetoothClient.DoConnect(BluetoothAddress address, Guid service)
at InTheHand.Net.Sockets.BluetoothClient.Connect(BluetoothAddress address, Guid service)
at BTJoyConTest.Program.Main(String[] args) in Program.cs:line 36
The Joycon seems connected and paired in the Bluetooth window, but if I relaunch my program, InTheHand method to list paired devices (client.PairedDevices) don't see them at all... so they can't be unpaired again.
As a quick solution I would say that maybe using BluetoothAPIs.dll to pair the Joycon would work better, but I don't have any clue of the .dll function I should use here (If someone knows it will help).
Other solution would be to make it work with InTheHand. Is someone else had already the issue?
Thx in advance.

ReadProcessMemory not working with Dolphin emulator

I'm trying to get access to some of the values in the memory of an emulation of Smash Bros Melee running in Dolphin. The Dolphin debug mode says that the address of the value I want is 0x80C6BA10 (I'm assuming that it means 0x00C6BA10, because 0x80C6BA10 goes over the integer limit, and it had previously referred to the same address as 0x00C6BA10). But when I pass this into the ReadProcessMemory function, I get a byte array that is just [0,0,0,0] (I'm using 4 bytes because the value I'm trying to get is an 8 digit hexadecimal number).
I tried to use OllyDbg to check if the address is right, but for some reason Dolphin doesn't work with OllyDbg, maybe because it isn't 64 bit? I've also tried using the unchecked() method in order to pass 0x80C6BA10 instead of 0x00C6BA10.
public class Program
{
//Constant that says we want to just read memory
const int PROCESS_WM_READ = 0x0010;
// **** Imports the functions used to get memory data ****
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool
bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess, int
lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);
static void Main(string[] args)
{
//Gets process by finding the first process with the name dolphin
Process melee = Process.GetProcessesByName("Dolphin")[0];
IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false,
melee.Id);
int bytesRead = 0;
//The list that will be populated by the data we find in the
memory
byte[] buffer = new byte[4];
//Reads the memory at the specified location
ReadProcessMemory((int)processHandle, 0x00C6BA10, buffer,
buffer.Length, ref bytesRead);
//Converts byte array into floating point number -- not currently
being used
float memoryValue = BitConverter.ToSingle(buffer, 0);
foreach (byte b in buffer)
{
Console.WriteLine(b);
}
Console.ReadLine();
}
}
I expect the output to be anything but 0, but what I get back is an array of 0s. I think part of the issue might be that I'm trying to get memory values from a process that is running as a sub-process of Dolphin.

I/O exception error when using serialport.open()

FINAL UPDATE
It was our firmware the whole time. Embarrassing to a degree, but I'm happy we can move forward and I can put learning Java off for another day. My answer is below.
UPDATE
So I have more or less given up on this. I think it is a bug that goes down to the API, but I have neither the time, resources nor skill-set to get to the bottom of it. I think there exists some hardware to whom Windows just gives the middle finger. I have downloaded Eclipse, switched to Java and will try to see if that works. If not, you'll see me back here. However, I would absolutely love to solve this and so if anyone has the time or inclination to dig deep into this one, I'd love to see what you come up with. Obviously I will be checking back here from time to time. Please make sure you '#' me in your comments so I am alerted.
ORIGINAL POST
I know there are a few other people dealing with this issue, but I was hoping someone could help me. I am trying to connect to a COM port, but I am getting an I/O exception when I try to use the serialport.Open() command:
System.IO.IOException: The parameter is incorrect.
at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
at System.IO.Ports.InternalResources.WinIOError()
at System.IO.Ports.SerialStream.InitializeDCB(Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Boolean discardNull)
at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
at System.IO.Ports.SerialPort.Open()
at *programtitlehere.cs*:line 90
I am using a Stellaris LM4F232 to emulate a COM port. I can open, access and I get good results using Termite (a terminal program), but whenever I try with Visual Studio it won't even connect, and I get this error. Now I don't even really know what this error means and despite trying to read elsewhere, I still feel lost.
Can anyone explain to me what is happening here and maybe I can begin to try to figure this out? I can include more code, but to be honest there isn't much there; all the properties of the serial port device are as normal, and it is only happening with this device (I can use an MSP430 no problem with the same details).
My code is shown below for people who would like to see it (note this is just a 'sandbox', not the actual program, but the symptoms are identical):
try
{
serialPort1.PortName = "COM5";
serialPort1.Open();
if (serialPort1.IsOpen == true)
{
textBox1.Text = "CONNECTED";
}
else
{
textBox1.Text = "NOT CONNECTED";
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.ToString(), "ERROR");
}
and the other settings are done with the property manager (the only difference is baud is set to 230400; all others are on their default).
I can open up COM4 with this (an MSP430) which for all intents and purposes is an identical device. I can open COM5 with Termite, so I know the connection is good). And no, I am not trying to open them at the same time. If you need more information let me know and I can post more.
EDIT: I'm on day three of trying to figure this out and still no luck. I don't really understand why I can access this COM port through a terminal program and not my own when, as near as I can see, there is absolutely no difference. Is there a program that can 'examine' a COM port to see the properties of it (besides Windows manager I mean)? I'm getting pretty frustrated and am sort of at a stand still in my project until I figure this out...
EDIT2: I've found an apparent workaround, but I've yet to get it to work here. Now I get a few different I/O errors, but at least it is motion (not sure if it is progress). I've also learned that this is a .NET bug, which has existed since 2.0. I'd still love any help, but if I figure it out I will report back. Zach's code (the workaround linked above) is shown below:
using System;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace SerialPortTester
{
public class SerialPortFixer : IDisposable
{
public static void Execute(string portName)
{
using (new SerialPortFixer(portName))
{
}
}
#region IDisposable Members
public void Dispose()
{
if (m_Handle != null)
{
m_Handle.Close();
m_Handle = null;
}
}
#endregion
#region Implementation
private const int DcbFlagAbortOnError = 14;
private const int CommStateRetries = 10;
private SafeFileHandle m_Handle;
private SerialPortFixer(string portName)
{
const int dwFlagsAndAttributes = 0x40000000;
const int dwAccess = unchecked((int) 0xC0000000);
if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
SafeFileHandle hFile = CreateFile(#"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
IntPtr.Zero);
if (hFile.IsInvalid)
{
WinIoError();
}
try
{
int fileType = GetFileType(hFile);
if ((fileType != 2) && (fileType != 0))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
m_Handle = hFile;
InitializeDcb();
}
catch
{
hFile.Close();
m_Handle = null;
throw;
}
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
StringBuilder lpBuffer, int nSize, IntPtr arguments);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
IntPtr securityAttrs, int dwCreationDisposition,
int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetFileType(SafeFileHandle hFile);
private void InitializeDcb()
{
Dcb dcb = new Dcb();
GetCommStateNative(ref dcb);
dcb.Flags &= ~(1u << DcbFlagAbortOnError);
SetCommStateNative(ref dcb);
}
private static string GetMessage(int errorCode)
{
StringBuilder lpBuffer = new StringBuilder(0x200);
if (
FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
IntPtr.Zero) != 0)
{
return lpBuffer.ToString();
}
return "Unknown Error";
}
private static int MakeHrFromErrorCode(int errorCode)
{
return (int) (0x80070000 | (uint) errorCode);
}
private static void WinIoError()
{
int errorCode = Marshal.GetLastWin32Error();
throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
}
private void GetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat();
for (int i = 0; i < CommStateRetries; i++)
{
if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (GetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
private void SetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat();
for (int i = 0; i < CommStateRetries; i++)
{
if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (SetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
#region Nested type: COMSTAT
[StructLayout(LayoutKind.Sequential)]
private struct Comstat
{
public readonly uint Flags;
public readonly uint cbInQue;
public readonly uint cbOutQue;
}
#endregion
#region Nested type: DCB
[StructLayout(LayoutKind.Sequential)]
private struct Dcb
{
public readonly uint DCBlength;
public readonly uint BaudRate;
public uint Flags;
public readonly ushort wReserved;
public readonly ushort XonLim;
public readonly ushort XoffLim;
public readonly byte ByteSize;
public readonly byte Parity;
public readonly byte StopBits;
public readonly byte XonChar;
public readonly byte XoffChar;
public readonly byte ErrorChar;
public readonly byte EofChar;
public readonly byte EvtChar;
public readonly ushort wReserved1;
}
#endregion
#endregion
}
internal class Program
{
private static void Main(string[] args)
{
SerialPortFixer.Execute("COM1");
using (SerialPort port = new SerialPort("COM1"))
{
port.Write("test");
}
}
}
}
EDIT3: Day 6: I'm still plugging away at this. My water rations are low, but still I struggle on. I feel help must surely be on the horizon. Whoever finds this journal bring my remains back to Canada and find Nicole. Tell her I love her.
But seriously, I have no idea what is causing this problem. I'm wondering if it is purely on the embedded side; maybe because it is USB On-The-Go (OTG), or because the device is capable of being a host also. Has anyone run into that problem? It doesn't explain why I can use Termite (a terminal program, for those viewers just joining us) though. I have been trying to find an open source terminal program that a) works and b) see a). As per usual, I will report back if I discover the issue here as I have now found countless forums where it sounds people have had this issue dating back to 2006.
EDIT4: So as per the advice given, I downloaded a port monitoring software application (I got Eltima Serial Port Monitor), and it does look like a baud issue:
But strangely no matter what baud I set, it still fails. And also can someone explain what the up/down thing means? I tried googling it, but the keywords are too general. As usual, I will keep reporting back any changes.
Also, for the record, I can connect using Eltima at a baud of 115200 (same as Termite). Unfortunately this does not work in Visual Studio.
EDIT5: Our plot takes a surprise twist. I was monitoring what happens when Termite connects to the COM port in question and BLAM! Termite throws the exact same error as my program, but it ignores it. Genius, right? Sloppy, but it works. Now I need to learn how to ignore IOExceptions. I'll report back when I get it figured out.
EDIT6: So as it turns out it is a baud rate issue, but it goes deeper. I have been using Eltima Serial Port Monitoring software, and it is very intuitive and easy to use. I would recommend it. After some research I have learned that you cannot ignore this exception and still connect to the serial port using .NET's library.
So I have to go deeper into the Win32 API and write my own. I have found a few pages that touch on this, but to be honest I have never done anything like this before, so it may be a while before I report back, but I will definitely figure this out and get back to everyone. There are way too many who suffer from this problem.
I have found quite a few forums and websites where I can see the exact same symptoms, but nobody has really done much besides say 'Yeah, .NET sucks'. I plan on writing a full static library class and then publish either on my website, here and wherever else I can. Hopefully .NET will take notice (this bug has existed since 2.0).
This comes from the serial port driver; it is unhappy about one of the settings. With baudrate being a good candidate, drivers tend to allow only up to 115200. Albeit that this should not be a restriction when this is a dedicated CAN bus product.
The best way to tackle this is by using Sysinternals' Portmon utility; you can see what is being sent to the driver. Observe it for Terminate first; that's your known-to-work baseline. Then tinker with SerialPort properties until the initialization commands, as you see them in PortMon, sent by your program matches Termite's. Just the values, not the order. If that doesn't pan out either then take it to the parking lot and back over it with your car several times and buy another brand.
Update: it certainly looks like a baudrate problem. That's an issue in .NET; it is not going to ignore the driver's error return code like your terminal emulator programs do. The actual value should not matter since you are talking to an emulated serial port. There is however a possible issue with the CAN bus speed; rates are variable and it isn't clear to me how they are negotiated. This tended to be done with DIP switches in the olden days, and it may well be that the driver wants you to specify the speed through the baudrate setting. There ought to be something about it on the box or in the manual. Typical speeds are 40, 250 or 500 kbit/s. The manufacturer certainly would know; give them a call.
I faced a similar problem as reported in this thread, but I managed to solve the problem!
I am using STM32F2xx for the VCP!
And indeed it was my firmware problem. I forgot to include serial port settings in my USB callback!
The process of connecting a serial port from PC and firmware:
When a PC opens a serial port communication, the PC will send some command into the "configuration endpoint"
In the firmware, it would have a callback and the firmware will provide all the USB information (they call it a USB descriptor)
USB information is the configuration of each endpoint, (for example, latency, data size transmission, and type of USB - high speed or low speed)
Once the firmware has completed sending all the information, the PC will acknowledge and USB communication is successfully opened
Then, the PC will send a command to get the serial port settings from the firmware
Serial port settings are baudrate, data parity, and bit length.
In firmware, it should reply the serial port settings back to PC (my mistake occurs here; I didn’t not send any serial port settings back to the PC)
If successful, PC will start the serial port communication!
If failed, PC will give an open serial port error (but, do note that this error sometimes is bypassed)
In STM32 firmware code:
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
switch (cmd) {
case CDC_GET_LINE_CODING:
{
// I was missing this part
uint32_t baudrate = 9600;
pbuf[0] = (uint8_t)(baudrate);
pbuf[1] = (uint8_t)(baudrate >> 8);
pbuf[2] = (uint8_t)(baudrate >> 16);
pbuf[3] = (uint8_t)(baudrate >> 24);
pbuf[4] = 0;
pbuf[5] = 0;
pbuf[6] = 8;
break;
}:
....
I ran into the same situation. I am trying to connect serial communication to my 3G USB Dongle (Huawei E303F) at /dev/ttyUSB0. I use Mono in Raspbian (Raspberry Pi 2). On my development PC and macOS, my program runs fine. But when I deploy it into Raspbian, I got the IOException Broken Pipe error on Serial.Open().
It took me three days of debugging, and I tried all possible solutions. Finally I found that I have to set...
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
Before calling .Open().
And so our thrilling tale comes to a close. It was firmware the whole time (i.e. the code on the embedded device). We changed up a few functions and essentially poked around, chopped, added and altogether cleaned up the code and voila, the code is working. This pic sums it up pretty well. Curse you firmware!!
However, the bug described in my (lengthy) question still persists for many people and I know there are lots of people out there who still have it. All I can say is good luck and quadruple check your firmware (apparently triple checking it isn't enough these days).
I had the same problem and setting the baud rate to 1 fixed it!

C# - Read Parallel Port State (Simple Push Switch)

I am updating in C# some software that was originally written in VC++ V1.0 for DOS6.
One aspect of the software is a check on the parallel port, where a simple push-button switch is connected. I don't currently know to which two pins the switch is connected, but I have the source for the old program, the relevant sections of which are below...
#define switch_mask 0x10
void main(int argc, char *argv[])
{
int NewState = 0, OldState = 0;
/* Check switch */
NewState = _bios_printer (_PRINTER_STATUS, 0, 0);
if (NewState != OldState)
{
checkParallelPort (NewState);
OldState = NewState;
}
}
void checkParallelPort (int portState)
{
int SwitchState;
/* Switch bit is Active LOW */
SwitchState = (portState & switch_mask) ? 1 : 0;
}
Now _bios_printer (within bios.h) is obviously not available to me in C#, but I'm struggling to find an alternative that can do this simple task.
Info on _bios_printer is here. I've done plenty of searching for reading/writing to/from the parallel port in .Net, but nothing seems to provide me with the port status.
Also, can you conclude from this code (and how it checks the 'status') where the two switch wires are connected on the DB25 plug?
I'd be grateful if anyone has some help/advice on this please.
Many thanks
It seems to be checking 'Error', pin 15. IIRC, this is pulled up internally, so your switch should pull down pin 15. Connect it between pins 15 and 18.
There are some drivers available that allow the reading of the I/O map ports. You will have to import and make DLL calls and then almost certainly poll the pin :((
I do wish this interface was dead and buried!
Thanks for the reply. Here's what I ended up with...
I used this tutorial on CodeProject...
http://www.codeproject.com/KB/vb/Inpout32_read.aspx
When converted to C#, I used something similar to below. (Apologies if there is an error - I 'paraphrased' the code below from what i've ended up with - it works for me!)
private void button1_Click(object sender, EventArgs e)
{
short InReg = 0x379; // Location of Port Status register
int NewState; // int named NewState
NewState = InpOut32_Declarations.Inp(InReg); //Now NewState has the values in 'Status port'
MessageBox.Show(NewState); //A popup will indicate the current value of NewState
}
static class InpOut32_Declarations
{
[DllImport("inpout32.dll", EntryPoint = "Inp32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
//Inp and Out declarations for port I/O using inpout32.dll.
public static extern int Inp(ushort PortAddress);
[DllImport("inpout32.dll", EntryPoint = "Out32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void Out(ushort PortAddress, short Value);
}
Interestingly, as my Parallel Port starts at 0xE800 and not 0x378, I had to modify the source of inpout32.dll as the out32 method only accepts a short and 0xE800 is too big for a short! changed it to unsigned short.
Thanks for your help

C++ DLL function does not seem to work in C#

I have developed a small program using C# and bird.dll, but the birdRS232WakeUp() function seem not to be working.
When I call the birdRS232WakeUp() function in C++ the program will stop for a while (8-10 seconds). It looks like it is beginning to do the process connecting with the hardware (Flock of bird).
But in C#, it does not stop when calling birdRS232WakeUp(). How do I fix this problem?
The C# code is like the following.
[DllImport(#"Bird.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool birdRS232WakeUp(int nGroupID, Boolean bStandAlone, int nNumDevices,
ref ushort[] pwComport, uint dwBaudRate,
uint dwReadTimeout, uint dwWriteTimeout);
ushort[] COM_port = new ushort[]{0,16,0,0,0};
if ((!birdRS232WakeUp(GROUP_ID, false, DEVCOUNT, ref COM_port, BAUD_RATE, READ_TIMEOUT, WRITE_TIMEOUT)))
{
LWakeUpStatus.Text = "Failde to wake up FOB";
}
And the C++ code is looking like the following.
WORD COM_port[5] = {0,15,0,0,0}
if ((!birdRS232WakeUp(GROUP_ID,
FALSE, // Not stand-alone
DEVCOUNT, // Number of Devices
COM_port, // COM Port
BAUD_RATE, // BAUD
READ_TIMEOUT,WRITE_TIMEOUT, // Reponses timeouts
GMS_GROUP_MODE_ALWAYS)))
{
printf("Can't Wake Up Flock!\n");
Sleep(3000);
exit(-1);}
C++ header file for this function:
birdRS232WakeUp(int nGroupID, BOOL bStandAlone, int nNumDevices,
WORD *pwComport, DWORD dwBaudRate, DWORD dwReadTimeout,
DWORD dwWriteTimeout, int nGroupMode = GMS_GROUP_MODE_ALWAYS);
And the manual states that "pwComport" points to an array of words, each of which is the number of the COM port attached to one of the birds (for example, COM1 = 1, COM2 = 2, etc.)
Update 1:
I have taken a suggestion from elder_george, but the problem still exist. I had to change the C# code to the following.
public static extern bool birdRS232WakeUp(int nGroupID, Boolean bStandAlone, int nNumDevices,
ushort[] pwComport, uint dwBaudRate, uint dwReadTimeout,
uint dwWriteTimeout,int nGroupMode);
if ((!birdRS232WakeUp(GROUP_ID, false, DEVCOUNT, COM_port, BAUD_RATE, READ_TIMEOUT, WRITE_TIMEOUT,2)))
{
LWakeUpStatus.Text = "Failde to wake up FOB";
}
BTW, the int nGroupMode is equal to 2, based on the enum type below .
enum GroupModeSettings
{
// GMS_DEFAULT, // Driver will determine whether or not to use RS232 group mode.
GMS_GROUP_MODE_NEVER, // RS232 group mode will never be used
GMS_GROUP_MODE_ALWAYS, // RS232 group mode will always be used
NUM_GROUP_MODE_SETTINGS
};
Not sure if these points will solve your problem, but:
1) pwComport should be declared as ushort[] pwComport, not ref ushort[] pwComport
2) you need to pass nGroupMode parameter from C#. You can set it to default value if you use C#4, but don't ignore it at all.

Categories