¿Cómo leer valores enteros del puerto serie en C#?

Tengo una cámara Keyence que se comunica a través de RS-232. Está configurado para generar tres valores enteros cuando se activa. Tengo problemas para leer los valores enteros. Intento usar un búfer de matriz de caracteres, pero solo lee el primer signo + en la salida. Lo probé usando masilla y la salida es algo como esto

+ 346.0, + 261.0,098

Quiero saber si hay algo que deba usar para leer valores enteros como estos.

    static void Main(string[] args)
    {

        char[] buffer1 = new char[200] ;


        SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);

        port.Open();
        if (port.IsOpen) { Console.WriteLine("port is now open"); } else { Console.WriteLine("port not opened correctly"); }

        port.Write("T"); //triggers the camera

        port.Read(buffer1, 0, 200);

        for (int i = 0; i < 200; i++)
        {
            Console.WriteLine(buffer1[i]);
        }
        Console.ReadLine();
    }

preguntado el 27 de julio de 12 a las 16:07

Es posible que tenga que leerlo como una cadena y analizarlo usted mismo, dividiéndolo por comas:

Siempre es mejor mostrar el código que está utilizando que no funciona. Mucho más fácil para la gente decirte dónde te equivocaste que... -

Hola Chris, soy nuevo en stackoverflow y gracias por recordármelo. He añadido el código que estaba usando. -

¿Sabes más sobre el protocolo de comunicación con el dispositivo? ¿Especifica algo para indicar que se terminó de escribir? -

No, solo tengo que enviar comandos como cadenas como R para ejecutar, T para desencadenar, etc. -

3 Respuestas

He tenido problemas antes con la lectura desde el puerto serie y no leía todo lo esperado.

Resulta que estaba leyendo la respuesta del dispositivo y aún no había terminado de escribir. Supuse que el objeto del puerto serie continuaría intentando llenar el búfer hasta que se alcanzara el tiempo de espera de lectura, y eso no era lo que estaba sucediendo.

En mi escenario, sabía cuántos caracteres iba a leer desde el puerto serie. Entonces, si sabe que podría implementar una repetición en la lectura hasta que su búfer de caracteres esté lleno. No sé si se aplicaría lo mismo si está leyendo desde SerialPort.BaseStream.

SerialPort serialPort; 

char[] buffer = new char[expectedLength];
int totalBytesRead = 0;

//continue to read until all of the expected characters have been read
while (totalBytesRead < expectedLength)
{
    totalBytesRead += serialPort.Read(buffer, totalBytesRead, expectedLength - totalBytesRead); 
}

Respondido 27 Jul 12, 16:07

Intenté ingresar su código pero no funcionó, ¿debería retrasar para dejar que termine de escribir todos los valores y luego intentar leer? - ranjith1512

@ ranjith1512 No agregaría un retraso, configurar ReadTimeout en el puerto serie sería una mejor opción. Si todavía está leyendo solo el "+" del puerto con mi código, entonces dudo que agregar un retraso o configurar ReadTimeout funcione, especialmente porque el valor predeterminado de ReadTimeout es infinito. - JG en SD

Este es el código que uso (simplificado):

public class Scanner : SerialPort
{
    private string _word;
    private int _globalCounter;
    private readonly char[] _rxArray = new char[2047];

    public Scanner()
    {
        DataReceived += MyDataReceivedEventHandler;
    }

    public event EventHandler<CodeScannedEventArgs> CodeScanned;
    private void MyDataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e)
    {
        do
        {
            var rxByte = (byte)ReadByte();

            // end of word
            if (rxByte == 10)
            {
                // first byte (02) and last two bytes (13 and 10) are ignored
                _word = new string(_rxArray, 1, _globalCounter - 2);

                DisplayData(_word);

                _globalCounter = 0;
            }
            else
            {
                _rxArray[_globalCounter] = (char)rxByte;
                _globalCounter++;
            }
        } while (BytesToRead > 0);
    }

    private void DisplayData(string receivedText)
    {
        OnCodeScanned(new CodeScannedEventArgs(receivedText));
    }

    protected void OnCodeScanned(CodeScannedEventArgs e)
    {
        EventHandler<CodeScannedEventArgs> handler = CodeScanned;

        if (handler != null)
        {
            handler(this, e);
        }
    }
}

El escáner que uso agrega el byte 02 como prefijo y los bytes 13 y 10 como sufijo a todo lo que escanea, por lo que es bastante fácil para mí dividirlo en palabras. Obviamente, deberá cambiar la implementación ligeramente para que funcione para usted.

Editar - Clase CodeScannedEventArgs:

public class CodeScannedEventArgs : EventArgs
{
    public CodeScannedEventArgs(string scannedCode)
    {
        ScannedCode = scannedCode;
    }

    public string ScannedCode { get; set; }
}

Respondido 27 Jul 12, 21:07

¿Está utilizando este código en formularios de Windows? ¿Se puede usar en una aplicación de consola? - ranjith1512

Lo estoy usando en Windows Forms, pero en realidad no importa, también puede usarlo en la aplicación de consola. - svenvit

¿Qué espacio de nombres debo agregar para usar CodeScannedEventArgs? - ranjith1512

Usé port.ReadTo("\r") y funciona, ya que la salida termina con un retorno de carro.

Pero quiero saber cuál es la ventaja de usar un evento de datos recibidos.

Respondido 27 Jul 12, 21:07

Establecería la propiedad de nueva línea en SerialPort en "\ r", y luego puede llamar a port.ReadLine para realizar la misma función. Al configurar la propiedad de nueva línea, también cambiará la forma en que se escriben las líneas cuando usa WriteLine, terminará la línea con cualquier valor establecido en NewLine. - JG en SD

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.