modelica-3rdparty / Modelica_DeviceDrivers

Free library for interfacing hardware drivers to Modelica models. There is support for joysticks, keyboards, UDP, TCP/IP, LCM, MQTT, shared memory, AD/DA converters, serial port and other devices.
BSD 3-Clause "New" or "Revised" License
77 stars 31 forks source link

A spurious byte sent at the end of simulation #352

Closed max-privato closed 3 years ago

max-privato commented 3 years ago

Consider the below model IntU16SendOnly.mo: IntU16SendOnly.mo.txt

It sends a few instances of decimal 10 over a serial connection. Its hexadecimal representation, with the byte order of Modelica Device Drivers (little endian) is 0x0a 0x00. Below the screenshot of what is received by RealTerm: image As you can see, at the end of the sequence there is a spurious 0x00 byte.

This is not totally harmless: if we let RealTerm (or other receiving software) interpret the sequences as u16 integers, there will be a misalignment of bytes, and therefore, if we launch the exe from IntU16SendOnly.mo several times in sequence, the received interpreted numbers will toggle between 10=0x000a and 2516=0x0a00.

bernhard-thiele commented 3 years ago

Strange. Unfortunately, I don't understand the Windows serial code very well (was contributed by others). If I look into the destructor, there is code which sends a "0" byte (MDD_serialPortSend(p_serial, &c, 1);) before closing the handle:

DllExport void MDD_serialPortDestructor(void * p_serial) {
    MDDSerialPort * serial = (MDDSerialPort *) p_serial;
    if (serial) {
        char c = 0;
        serial->receiving = 0;
        EscapeCommFunction(serial->hComm, CLRDTR);
        PurgeComm(serial->hComm, PURGE_TXABORT | PURGE_TXCLEAR);
        PurgeComm(serial->hComm, PURGE_RXABORT | PURGE_RXCLEAR);
        MDD_serialPortSend(p_serial, &c, 1);
        /*
             ... 
        */
        CloseHandle(serial->hComm);
        free(serial);
    }
}

We don't have that in the Linux version. Would be good to have somebody comment who knows about serial programming in Windows why this is done.

max-privato commented 3 years ago

I would like to make tests on my PC, just commenting out the row MDD_serialPortSend(p_serial, &c, 1);

Is there a way for me to do this? I suppose I should create a new dll (I don't know which dll and how to do: which compiler, what options, etc.).

Or, in case for you @bernhard-thiele is straightforward, can you create such dll and make it available to me for testing? Thanks

bernhard-thiele commented 3 years ago

@max-privato You can simply comment out the line in

https://github.com/modelica-3rdparty/Modelica_DeviceDrivers/blob/8267f35ef33f0893e65df5a3c047514936df6afd/Modelica_DeviceDrivers/Resources/Include/MDDSerialPort.h#L318

and do your test with OpenModelica or Dymola. Both simply include the complete C code in MDDSerialPort.h (just check that the model is really retranslated and not only resimulated with an already existing binary). For most devices it is not needed to build a DLL, since respective external C code is directly included (exception: SimulationX uses DLLs for all devices).

max-privato commented 3 years ago

Thanks a lot! I commented out that row, and got the expected result!. This solves my issue. I don't close this ticket yet, because, I suppose, we should wait for someone to say what the rationale beyond row 318 of MDDSerislPort.h is, and whether it should be deleted for everyone (I mean, for the official library).

Thanks again.

tbeu commented 3 years ago

I took it from line 176 of com_port.cpp (of com_port_Rx_Thread.zip (login required)) when I implemented it in 7717f0cb67b691b462c4e071d9c610e4399ba3e1 almost 45 months ago. I have to admit that I do not know the purpose behind that code.

/////////////////////////////////////////////////////////////////////////
BOOL CloseComPort( void )
{
    // ...
    char c = 0;
    // ...
    WriteComPort( &c, 1 );  // Event to wake RX thread
    // ...
}
bernhard-thiele commented 3 years ago

Thanks, since @max-privato tested it and it seems to work fine without that line I'd say we just take it out. I'll do a commit soon.