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

Serial port change port settings (number of data bits) #368

Closed sertho closed 1 year ago

sertho commented 1 year ago

We would like to use Modelica_DeviceDrivers to send data through a serial port. The receiving device uses the serial port settings as shown in the image below, in particular 7 data bits.

serielport_settings

We use the MDD component Modelica_DeviceDrivers.Blocks.Communication.SerialPortSend. Is there a way to change the number of data bits within the MDD Library? So far we haven't found a way to change this parameter to 7 (instead of 8, which seems to be used by the MDD Library as standard value).

We tried to change the header file by setting dcb.ByteSize = 7;, but with no success. https://github.com/modelica-3rdparty/Modelica_DeviceDrivers/blob/8267f35ef33f0893e65df5a3c047514936df6afd/Modelica_DeviceDrivers/Resources/Include/MDDSerialPort.h#L202-L212

How could we approach this problem? Do we have to change the header file and recompile the files within the Modelica_DeviceDrivers 2.1.1\Resources folder? We appreciate any help, as our knowledge with c-code compilation is limited.. : s

tbeu commented 1 year ago

These dbc settings should not be altered by the user.

Can you please tell what is the observed behaviour and what is the expected behaviour. Can you please attach a Modelica model such that we can try to reproduce. Thanks.

sertho commented 1 year ago

The modelica model is very simple:

ModelicaModel


We have a test setup where we try to send a string "DL31" to turn on the led on the board and "DL30" to turn it off.

Hardware


The problem is, that our hardware uses the serial port data format 7-E-1 (7 data bits, even parity, 1 stop bit).


To find the problem, we used an oscilloscope and when running the modelica model we saw that the sent data is only interpreted correctly if we change the data format on the oscilloscope from 7bits to 8bits.

oscilloscope


Would it be worth a try to adopt the header file and recompile the files within the MDD Resources folder?

tbeu commented 1 year ago

Thanks for the detailed information. You are right, by setting dcb.ByteSize = 7; in header file MDDSerialPort.h, data will be sent as 7 bit data. This should be a parameter of the SerialSend block and not hard-coded.

What is your Modelica simulation environment? If you use Dymola as Modelica Environment, there is no need to recompile any sources of MDD (it is a header-only library). If you use SimulationX, you would need to recompile the ITI_MDD.dll to apply the changes.

sertho commented 1 year ago

Thank you @tbeu for the very quick and helpful support! Yes, I think it would make sense if this is a parameter in the SerialSend block.

We use Dymola. I will try to change the header file and test it in the next dais, then I give a feedback.

tbeu commented 1 year ago

I will try to change the header file and test it in the next dais, then I give a feedback.

@sertho Did it work out finally?

sertho commented 1 year ago

@tbeu Dear Thomas Yes it worked! We finally could test it and it worked perfectly, thank you so much : )

Now I am struggling with sending and receiving strings. When I send a command e.g. "DL31" the board should e.g. turn the led on and then send back "DL31".

I am not able to receive strings in dymola from the board. For my test example I use an Arduino Uno board (for now using the standard 8bit data) with this sketch:

void setup() {
  // Serial.begin(38400, SERIAL_7E1);
  Serial.begin(38400, SERIAL_8E1);
}

void loop() {

  Serial.write("Hallo\0");
  delay(1000);
}

and the following modelica model:

ModelicaModel_ReceiveString

ModelicaModel_ReceiveString_PortSettings

Modelica code:

model Test_ReceiveString_06
  extends Modelica.Icons.Example;

  Modelica_DeviceDrivers.Blocks.Communication.SerialPortReceive serialPortReceive(
    enableExternalTrigger=true,
    autoBufferSize=false,
    userBufferSize=6,
    Serial_Port="COM4",
    baud=Modelica_DeviceDrivers.Utilities.Types.SerialBaudRate.B38400,
    parity=1) "to send and receive data "
    annotation (Placement(transformation(extent={{-50,50},{-30,30}})));
  Modelica.Blocks.Logical.Not not1 annotation (Placement(transformation(
        extent={{-10,-10},{10,10}},
        rotation=180,
        origin={20,60})));
  Modelica.Blocks.Sources.BooleanPulse booleanPulse(period(displayUnit=
          "s") = 2)
               annotation (Placement(transformation(
        extent={{-10,-10},{10,10}},
        rotation=180,
        origin={60,60})));
  Modelica_DeviceDrivers.Utilities.TriggeredPrint triggeredPrint(message=
        getString.data)
    annotation (Placement(transformation(extent={{-50,72},{-30,92}})));
  GetString                                                        getString(
      dataBitSize=8, bufferSize=6)
    annotation (Placement(transformation(extent={{-10,-30},{10,-10}})));
equation 
  connect(triggeredPrint.trigger, not1.y) annotation (Line(points={{-40,76},
          {-40,60},{9,60}},                 color={255,0,255}));
  connect(booleanPulse.y, not1.u)
    annotation (Line(points={{49,60},{32,60}}, color={255,0,255}));
  connect(not1.y, serialPortReceive.trigger) annotation (Line(points={{9,60},
          {-40,60},{-40,52}}, color={255,0,255}));
  connect(serialPortReceive.pkgOut, getString.pkgIn)
    annotation (Line(points={{-29.2,40},{0,40},{0,-9.2}}, color={0,0,0}));
  annotation (Icon(coordinateSystem(preserveAspectRatio=false, extent={{-140,
            -120},{140,120}})),Diagram(coordinateSystem(preserveAspectRatio=
            false, extent={{-140,-120},{140,120}})),
    experiment(StopTime=30, __Dymola_Algorithm="Dassl"));
end Test_ReceiveString_06;

I get the following error:

ModelicaError_ReceiveString

I studied all the examples within the MDD Library but still not understanding how to make it work. Must all strings be null terminated with \0 or could they also be terminated with carriage return \r or new line feed \n and so on? Could you help me with this too? Should I create a new issue for this?

Vielen Dank und beste Grüsse!

tbeu commented 1 year ago

Should I create a new issue for this?

Done in #373. Let's continue there. But later.

I would keep this issue open for the sake of

This should be a parameter of the SerialSend block and not hard-coded.

sertho commented 1 year ago

@tbeu Hi I am again working on this project and I tested your implementation #378 . This works perfectly, thank you!

But maybe the Modelica Block "Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.GetString" should also be updated? I am not sure, but wanted to ask because I was looking at this line inside that Block:

when initial() then
    pkgIn.autoPkgBitSize = if nu == 1 then alignAtByteBoundary(pkgOut[1].autoPkgBitSize)*8 + bufferSize*8 else bufferSize*8;
end when;

Shouldn't the "8" be replaced with the new introduced byte size parameter?

If yes, then this should be done for all similar blocks within the package "Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager":

Thank you!

sertho commented 1 year ago

@tbeu Maybe this Modelica function should also be updated (but not sure): "Modelica_DeviceDrivers.Packaging.alignAtByteBoundary"

grafik

tbeu commented 1 year ago

@sertho I am happy that it works for you. I think, we can leave the packaing on 8 bit boundaries as is then.