1
votes

DMX 512 receiver , i need to send data in 512 lines through serial port communication .The problem arises when i need to send data at a baud rate 250000 . Then i used DCB Control block with Getcomm state and Set Comm state . and then i writefile but should i use comPort.Write (Serial comPort = new Serial Port) to send data or WriteFile .This is my below program

I have a VB.Net program of Serial Port communication program of sending data to DMX 512 receiver which i need to convert into c# . But i am confused as they have used MSCOMM1.OUTPUT to send data .

Your help highly appreciated

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Public data_array

Private Sub cmd_Start_Click()

setup_com_port

send_comm_data

End Sub



Private Sub cmd_Stop_Click()

If MSComm1.PortOpen = True Then

    ''MSComm1.PortOpen = False
    End
End If
End Sub

Private Sub Form_Load()

 data_array = Array(&H7, &H20, &H7)

 Slider_Red = &H7

  Slider_Green = &H20

    Slider_Blue = &H7
End Sub



Private Sub setup_com_port()

 MSComm1.CommPort = 2

  MSComm1.Settings = "9600,N,8,2"

   'MSComm1.InputLen = 0

  ' MSComm1.InBufferSize = 1024


  ' MSComm1.OutBufferSize = 1024

    MSComm1.PortOpen = True

    SetBaudRate MSComm1, 250000
End Sub

' Set baud rate using Win32 API.
' The PortOpen property should be set to True before calling.
' May raise the following errors:
'   comPortNotOpen  the PortOpen property has not been set to True
'   comDCBError     failed to read current state of the port
'   comSetCommStateFailed  failed to set new baud rate
Sub SetBaudRate(Com As MSComm, baud As Long)
Dim ComDcb As dcb
Dim ret As Long

    ' Check port is open
    If Not Com.PortOpen Then
        Err.Raise comPortNotOpen, Com.Name, _
            "Operation valid only when the port is open"
        Exit Sub
    End If

    ' Get existing Comm state
    ret = GetCommState(Com.CommID, ComDcb)
    If ret = 0 Then
        Err.Raise comDCBError, Com.Name, _
            "Could not read current state of the port"
        Exit Sub
    End If

    ' Modify state with new baud rate
    ComDcb.BaudRate = baud
    ' Set the new Comm state
    ret = SetCommState(Com.CommID, ComDcb)
    If ret = 0 Then
        Err.Raise comSetCommStateFailed, Com.Name, _
            "Could not set port to specified baud rate"
        Exit Sub
    End If
End Sub


Private Sub send_comm_data()
        'com_break (10)

    Do
        com_break (5)
        'DoEvents
        Sleep (5)
        MSComm1.Output = Chr$(0)
        'DoEvents
        'Sleep (1)
        send_char_0
        Sleep (10)
        DoEvents
    Loop

 End Sub



Private Sub com_break(break_in_ms)
    ' Set the Break condition.
    MSComm1.Break = True
    ' Set duration to 1/10 second - 100ms
    'Duration! = Timer + (break_in_ms / 100)         '0.1 = 100ms
    ' Wait for the duration to pass.
    'Do Until Timer > Duration!
     ''   Dummy = DoEvents()
    'Loop
    ' Clear the Break condition.
    Sleep (1)
    MSComm1.Break = False
End Sub 

Private Sub send_char_0()

    Dim strData As String

    strData = ""
    For i = 0 To UBound(data_array)
    ''    MSComm1.Output = Chr$(data_array(i))
        strData = strData & Chr$(data_array(i))
    Next


    For i = 1 To 509
        ''MSComm1.Output = Chr$(50)
        strData = strData & Chr$(50)

    Next

    MSComm1.Output = strData
7    DoEvents

End Sub

Thanks in advance

1
If you have a specific question, please post a minimal reproducible example. To me is sounds much like "gimme the codez". - too honest for this site
Probably I'm not getting you, but the example you posted use mscomm.output because of that us the method to send data through a serial port object. In c# you could use THIS. What about the 250k baud? - LPs

1 Answers

1
votes

I think I got your point since I'm hacking into this for a while now. I found a nice way to send the data correctly. Keep in mind that not all the devices are capable of sending data at 250kbps, so it could be one of your issues. Find the FTDI-based ones to use.

For my approach, we need to send data in two speeds, and this happens because the reset byte must be a zero with a relatively longer time comparing to the other ones. So you will be constantly changing baud rates.

First, configure your device:

var serialPort = new SerialPort("COM0");
serialPort.DataBits = 8;
serialPort.Handshake = Handshake.None;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.Two;

Here I'm starting my serial port instance with all that config you've done too. Don't forget to change the COM port to fit your needs.

Now let's say you have two byte arrays, one for the "big zero" and another for the actual information:

byte[] zero = new byte[] { 0x00 };
byte[] buffer = new byte[513];

You'll ask "why 513 bytes for the buffer?", right? Simply because the first byte is a zero that tells that the actual data is going to be sent. (from 1 to 513, so there are 512 channels)

And finally the main loop: (I obviously recommend for you to do this in a separate thread)

while (true)
{
    serialPort.BaudRate = 96000;
    serialPort.Write(zero, 0, zero.Length);
    serialPort.BaudRate = 250000;
    serialPort.Write(buffer, 0, buffer.Length);
    Thread.Sleep(50);
}

Now I need your help to test it. I'm not confident that it will work flawlessly for longer times without damaging the IC, but I tried it for two hours and nothing harmful happened. Could you test it longer and send me a feedback? I would appreciate it very much. Does anyone have another approach without the need of changing the baud rates?