none
關於serialport 通訊一問 RRS feed

  • 問題

  • 請教各位長官

    這問題,雖然問的有點籠統,但請各位長官見諒。

    請問,小弟的AP,抓取了3~5不同的MODBUS的硬體資訊。

    假設:硬體有3組分:A、B、C三組,我將B、C使用串連方式,與A並接在RS485轉RS232的轉接器上,然後插在我的電腦。

    有時候B硬體,會出現亂值,這部分在通訊上,各位長官,有比較好的作法嗎?能夠給我一些方向作思考嗎?

    A、B、C三組的通訊上接收的格式,都與下面一樣,另外小弟採去的方式是A、B、C,循訊一個一個接收。
                    Try
                        srlPort.Write(crc_byte, 0, 8)
                        Thread.Sleep(500)
                        If srlPort.BytesToRead = "21" Then
                            srlPort.Read(com3_buff, 0, 21)
                            close_MP_XXTH = 1
                        End If
                    Catch ex As Exception
                        Application.DoEvents()
                    End Try


    2010年3月8日 上午 05:07

解答

  • 1. 是否有環境干擾 ? (不過說實話這發生的機率不高)
    2. B硬體換一組看看, 會不會是它的firmware本身就怪怪的
    3. 看起來是先Send一個訊號完後, 等待 ModBus硬體回覆. 0.5秒的間隔應該是夠讓ModBus硬體處理了才對
    4. 你所謂的亂碼是收碼不全, 例如要收40 bytes卻只收了38bytes回來, 還是其中有某幾個byte值和預期不同 ?
      
    MSDN 文件庫很重要
    問題本身越具體, 越容易得到大家的回應
    回應幫助你的人是一種禮貌, 良好的禮貌有助於激發大家對你問題回應的熱情
    2010年3月8日 上午 05:57
    版主
  • 研華的類比轉數位,你是用研華預設的自訂的通訊協定 #010 這種,還是用標準的 ModBus ?我有碰過研華自訂通訊協定會跟部分表頭打架,改用 ModBus 則沒事。
    一句老話,跟廠商要通訊協定說明,很多設備都有乘子,部分有偏移量,我在測試時,是先看值依照 Input 改變會不會變化,只看值的量不見得對,因為 Modbus 只有 Integer ,有小數的都是要算出來的。

    所以我會開 AccessPort 來監看。AccessPort 是一套免費的軟體,有繁中介面可選。
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    • 已標示為解答 percy682 2010年3月8日 下午 02:59
    • 已取消標示為解答 percy682 2010年3月8日 下午 02:59
    • 已標示為解答 璉璉Moderator 2010年3月20日 下午 01:33
    2010年3月8日 下午 02:25
  • Modbus設備可以去找Modscan這個程式來測,標準Modbus的設備Modscan都可以掃,不管是Modbus Tcp還是用Serial的;用工具程式掃一下,就可以確定是自己的程式有問題,還是資料回來就錯了。
    請注意討論區相關規則,良好的討論環境需要大家共同努力、遵守
    2010年3月8日 下午 02:50
    版主

所有回覆

  • 1. 是否有環境干擾 ? (不過說實話這發生的機率不高)
    2. B硬體換一組看看, 會不會是它的firmware本身就怪怪的
    3. 看起來是先Send一個訊號完後, 等待 ModBus硬體回覆. 0.5秒的間隔應該是夠讓ModBus硬體處理了才對
    4. 你所謂的亂碼是收碼不全, 例如要收40 bytes卻只收了38bytes回來, 還是其中有某幾個byte值和預期不同 ?
      
    MSDN 文件庫很重要
    問題本身越具體, 越容易得到大家的回應
    回應幫助你的人是一種禮貌, 良好的禮貌有助於激發大家對你問題回應的熱情
    2010年3月8日 上午 05:57
    版主
  • 抱歉!

    果然還是BILL大,經驗老道!

    1. 是否有環境干擾 ? (不過說實話這發生的機率不高):
    :我想也不太可能


    2. B硬體換一組看看, 會不會是它的firmware本身就怪怪的
    :本身韌體應該沒什麼問題,我想應該也不太可能

    3. 看起來是先Send一個訊號完後, 等待 ModBus硬體回覆. 0.5秒的間隔應該是夠讓ModBus硬體處理了才對
    :恩嗯,我也跟BILL想的一樣,因為我是有參考到您之前教導的。


    4. 你所謂的亂碼是收碼不全, 例如要收40 bytes卻只收了38bytes回來, 還是其中有某幾個byte值和預期不同 ?
    :這部分小弟沒有說清楚,應該說,B組硬體抓到的數據,不太合理,譬如說,硬體上面顯的是資料是:0.25,但我抓到的卻是354.98,類似這樣的意思。


            Try
                If srlPort.BaudRate <> meter_array(system_i, i_time, baudrate) Then srlPort.BaudRate = meter_array(system_i, i_time, baudrate)
            Catch ex As Exception
            End Try
            crc_byte(0) = i_time
            crc_byte(1) = 3
            crc_byte(2) = 0
            crc_byte(3) = 0
            crc_byte(4) = 0
            crc_byte(5) = 8
            crc_length = 6
            Try
                crc16()
            Catch ex As Exception
            End Try
            crc_array(i_time, 0) = crc_code
            crc_byte(6) = Int(crc_array(i_time, 0) Mod 256) '68  '16196 Mod 256
            crc_byte(7) = Int(crc_array(i_time, 0) / 256) '63  'Int(16196 / 256)

            com3_buff(0) = 255

            'For read_counter = 0 To 5
            If close_MP_XXTH = 0 Then
                If com3_buff(0) <> i_time Or com3_buff(1) <> 3 Then
                    Array.Clear(com3_buff, 0, 21)
                    'Try
                    '    srlPort.ReadExisting()
                    'Catch ex As Exception
                    'End Try
                    Try
                        srlPort.Write(crc_byte, 0, 8)
                        Thread.Sleep(500)
                        If srlPort.BytesToRead = "21" Then
                            srlPort.Read(com3_buff, 0, 21)
                            close_MP_XXTH = 1
                            'Else
                            '    Exit Function
                        End If
                    Catch ex As Exception
                        Application.DoEvents()
                    End Try
                End If
            End If

    2010年3月8日 上午 07:24
  • 我自己是用 AccessPort 去監聽 送收 內容,再依據內容去找問題。

    一般會有亂碼,通常是你的 485 迴路中,有兩個 Master 或是有其他通訊協定干擾,例如有些設備用 Modbus ,有些用 Ascii (指自訂協定,非 Modbus ASCII)

    若是你一次讀的資料量很長,你的接收回圈最好寫乾淨點,免得有資料沒收完,被你自己錯誤判斷為干擾,這種可看 AccessPort 監聽的結果。

    你也可以把 AccessPort 監聽結果你認為有問題的地方貼出來,我的經驗大部分是程式沒寫好,比如說沒讀完、逾期或反應時間設定過短、錯誤拋棄等。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2010年3月8日 上午 08:30
  • 硬體上顯示的數據可能經過換算,你必須看廠商提供的通訊協定來判讀才準。

    比如說研華的 ADAM (類比轉數位) ,485 讀到的值要*Scale-偏移量 ,有的廠商只給值域對應範圍,Scale 跟偏移量都要自己算,所以對於值不正確,可向硬體製造商洽詢。
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2010年3月8日 上午 08:33


  • 4. 你所謂的亂碼是收碼不全, 例如要收40 bytes卻只收了38bytes回來, 還是其中有某幾個byte值和預期不同 ?
    :這部分小弟沒有說清楚,應該說,B組硬體抓到的數據,不太合理,譬如說,硬體上面顯的是資料是:0.25,但我抓到的卻是354.98,類似這樣的意思。


    A/B/C聽你的描述應該是不同種類的硬體吧 ?
    所以是不是在程式碼中的問題應該是當你把那部份的Byte值要轉換為數值型態時的Code有問題,
    我猜應該可以這樣來看, 如果硬體顯示的和你抓回來的有絕對的對應關係,
    如硬體0.25抓回來就一定是354.98, 硬體是0.26, 抓回來就一定是356.65之類, 而且每次抓起來結果都一樣
    那就應該是出在Byte轉換成數值時的碼有問題.


    MSDN 文件庫很重要
    問題本身越具體, 越容易得到大家的回應
    回應幫助你的人是一種禮貌, 良好的禮貌有助於激發大家對你問題回應的熱情
    2010年3月8日 上午 09:12
    版主
  • 心冷大,BILL大您好,感謝你們。

    兩位說的,我思考了一下。
    A、B、C確實是三種不同的硬體。其中B和C兩個是同一家廠商所製,沒錯,A,是研華的類比轉數位器。

    另外

    A、B、C資料讀取上,只有B會有資料讀取上的問題。

    譬如上偏所說的,假設硬體是0.25,電腦假設抓到卻是326.58。資料讀取中,發現好像只有B硬體會這樣。

    所以思考一下兩位大大所說的,個人感覺上,好像是心冷大一開始所說的有其他通訊協定干擾,如果是這樣。

    這類的問題,兩位大大怎麼排除呢?還是我加一個終端電阻會有用呢?

    另外請教心冷大,您說您的經驗經驗大部分是程式沒寫好,比如說沒讀完、逾期或反應時間設定過短、錯誤拋棄等。

    這樣如何做呢?

    2010年3月8日 下午 02:16
  • 研華的類比轉數位,你是用研華預設的自訂的通訊協定 #010 這種,還是用標準的 ModBus ?我有碰過研華自訂通訊協定會跟部分表頭打架,改用 ModBus 則沒事。
    一句老話,跟廠商要通訊協定說明,很多設備都有乘子,部分有偏移量,我在測試時,是先看值依照 Input 改變會不會變化,只看值的量不見得對,因為 Modbus 只有 Integer ,有小數的都是要算出來的。

    所以我會開 AccessPort 來監看。AccessPort 是一套免費的軟體,有繁中介面可選。
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    • 已標示為解答 percy682 2010年3月8日 下午 02:59
    • 已取消標示為解答 percy682 2010年3月8日 下午 02:59
    • 已標示為解答 璉璉Moderator 2010年3月20日 下午 01:33
    2010年3月8日 下午 02:25
  • Modbus設備可以去找Modscan這個程式來測,標準Modbus的設備Modscan都可以掃,不管是Modbus Tcp還是用Serial的;用工具程式掃一下,就可以確定是自己的程式有問題,還是資料回來就錯了。
    請注意討論區相關規則,良好的討論環境需要大家共同努力、遵守
    2010年3月8日 下午 02:50
    版主
  • 心冷大,您果然高招。

    小弟用的是#010,並非用modbus。

    我瞭解心冷大多的,小弟使用研華的設備,來抓取太陽日照及大氣溫度。

    通常都是研華再干擾,其他硬體資訊。我把A:研華的ADDRESS設定為1,B的ADDRESS設為2,C的ADDRESS設為3。

    通常都是B硬體出現有這樣的問題。

    感謝
    2010年3月8日 下午 02:59
  • 我也有在用 modscan32 ...
    你把迴圈 1 To 3 改為 3 To 1 Step -1 試看看,研華自訂通訊協定放後面抓比較不容易出問題,或是你把研華設備先斷電,看看只有 b, c 是否正常。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2010年3月8日 下午 03:34
  • 感謝心冷大大

    您說的這部分,我會再嘗試看看。

    不過我先一個一個測試,只有抓B硬體,其他不抓,B硬體會出現一樣的情況。

    該會不就像是BILL大大說的,硬體本身的問題?


    感謝各位大大

    另,再請教通訊介面上的寫法

    Try
                If srlPort.BaudRate <> meter_array(system_i, i_time, baudrate) Then srlPort.BaudRate = meter_array(system_i, i_time, baudrate)
            Catch ex As Exception
            End Try
            crc_byte(0) = i_time
            crc_byte(1) = 3
            crc_byte(2) = 0
            crc_byte(3) = 0
            crc_byte(4) = 0
            crc_byte(5) = 8
            crc_length = 6
            Try
                crc16()
            Catch ex As Exception
            End Try
            crc_array(i_time, 0) = crc_code
            crc_byte(6) = Int(crc_array(i_time, 0) Mod 256) '68  '16196 Mod 256
            crc_byte(7) = Int(crc_array(i_time, 0) / 256) '63  'Int(16196 / 256)

            com3_buff(0) = 255

            'For read_counter = 0 To 5
            If close_MP_XXTH = 0 Then
                If com3_buff(0) <> i_time Or com3_buff(1) <> 3 Then
                    Array.Clear(com3_buff, 0, 21)
                    'Try
                    '    srlPort.ReadExisting()
                    'Catch ex As Exception
                    'End Try
                    Try
                        srlPort.Write(crc_byte, 0, 8)
                        Thread.Sleep(500)
                        If srlPort.BytesToRead = "21" Then
                            srlPort.Read(com3_buff, 0, 21)
                            close_MP_XXTH = 1
                            'Else
                            '    Exit Function
                        End If
                    Catch ex As Exception
                        Application.DoEvents()
                    End Try
                End If
            End If

    這樣的寫法,有不好的地方嗎?

    2010年3月9日 上午 07:16
  • 2010年3月9日 上午 07:40
  • 資料收到就會進入 DataReceived 事件,這時 Data 還沒收全,所以有很多處理方式。

    看起來你是像把 ADAM 改為 Modbus ,要一次讀 8 個頻道,這樣寫法當然不好,誰說 500 ms 就一定能把資料收全?

    還有 Write 完為啥有這句?
      If srlPort.BytesToRead = "21" Then

    那要是沒傳完怎麼辦?

    這邊慣例仍然是配合無限迴圈、逾時檢查、資料判讀來處理。
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2010年3月9日 下午 12:11
  • 各位長官好

    小弟寫這個目的,就是在於,沒傳完就不與讀取。等於抓到的值是空值。


    心冷大及各位大所寫的,在下在好好思考思考。

    感謝 

    2010年3月10日 上午 12:39