RS485 bus with MODBUS communication protocol

Everything else that doesn't fall into one of the other PB categories.
marc_256
Addict
Addict
Posts: 857
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

RS485 bus with MODBUS communication protocol

Post by marc_256 »

Hi,

For my DIY solar system I want to use a energy meter.
So, I can read the voltage, current, power in watt, ...

Is here someone who used PB with a RS485 bus with MODBUS communication protocol ?
I already installed a USB to RS485 converter.

Thanks,
marc
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
User avatar
HeX0R
Addict
Addict
Posts: 1214
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: RS485 bus with MODBUS communication protocol

Post by HeX0R »

Yes, I'm working all day with modbus (RTU / TCP), but I have nothing to share, all my codes are integrated into different tools.
I also made a modbus.dll, but it is too specific (for a terminal program I did) and not of much general use.
But it is a very simple protocol, this here is usually all you need to get it done:
https://www.simplymodbus.ca/FAQ.htm
Each command and the result is explained there.
Good luck!
marc_256
Addict
Addict
Posts: 857
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: RS485 bus with MODBUS communication protocol

Post by marc_256 »

Hi HeX0R,

Thanks for the link, very interesting data there.
Just what I need to start.

Marc
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
User avatar
mk-soft
Always Here
Always Here
Posts: 6312
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: RS485 bus with MODBUS communication protocol

Post by mk-soft »

Modbus/TCP is easier because you do not have to form a CRC there.

Here is an approach for Modbus/RTU

Code: Select all

;-TOP

; Link: https://stackoverflow.com/questions/65734589/understand-modbus-rtu-crc
;
;  uint16_t calculate16CRC(uint16_t Length, uint8_t *Data)
; {
;     /* Reversed Modbus polynomial of 0x8005 -> CRC-16 POLYNOMIAL: P(x) = x16 + x15 + x2 + 1 */
;     uint16_t Poly = 0xa001;
; 
;     uint16_t CRCRegister = 0xFFFF; // Initialize CRC register with all 1's
; 
;     uint16_t b; // Carry Over Checker
;     uint16_t c; // Data Array Index
;     uint16_t i; // Bit Index
; 
;     for (c = 0; c < Length; c++) {
;         CRCRegister ^= Data[c]; // XOR CRC with Byte
;         for (i = 0; i < 8; i++) {
;             b = CRCRegister & 1;
;             CRCRegister >>= 1; // Shift to the right
;             if (b != 0){ // Carry over?
;                 CRCRegister ^= Poly; // Yes
;             }
;         }
;     }
; 
;     return CRCRegister;
; }

Structure ArrayOfByte
  StructureUnion
    a.a[0]
    b.b[0]
  EndStructureUnion
EndStructure

Structure ArrayOfAny
  StructureUnion
    a.a[0]
    b.b[0]
    u.u[0]
    w.w[0]
    l.l[0]
    q.q[0]
  EndStructureUnion
EndStructure

Procedure calculate16CRC(Length, *Data.ArrayOfByte)
  
  ;/* Reversed Modbus polynomial of 0x8005 -> CRC-16 POLYNOMIAL: P(x) = x16 + x15 + x2 + 1 */
  Protected Poly = $A001;
  
  Protected CRCRegister = $FFFF ; // Initialize CRC register with all 1's
  
  Protected b; // Carry Over Checker
  Protected c; // Data Array Index
  Protected i; // Bit Index
  
  For c = 0 To Length-1
    CRCRegister = (CRCRegister ! *Data\a[c]) & $FFFF; // XOR CRC with Byte
    For i = 0 To 7
      b = CRCRegister & 1;
      CRCRegister >> 1   ; // Shift to the right
      If (b <> 0)        ; // Carry over?
        CRCRegister = (CRCRegister ! Poly) & $FFFF; // Yes
      EndIf
    Next
  Next
  
  ProcedureReturn CRCRegister;
EndProcedure

; ----

Procedure bswap16(value.u)
  CompilerIf #PB_Compiler_Backend = #PB_Backend_C
    !return __builtin_bswap16(v_value);
  CompilerElse
    !xor eax,eax
    !mov ax, word [p.v_value]
    !rol ax, 8
    ProcedureReturn
  CompilerEndIf
EndProcedure

; ----

Procedure fc03request(Slave, Offset, Count, *SendData) ; Build Read Holding Registers
  Protected *request.ArrayOfAny = *SendData
  
  *request\a = Slave
  *request + 1
  *request\a = 3
  *request + 1
  *request\u = bswap16(Offset)
  *request + 2
  *request\u = bswap16(Count)
  *request + 2
  *request\u = calculate16CRC(6, *SendData)
  ProcedureReturn 8
EndProcedure

*fc04request = AllocateMemory(100)

len = fc03request(17, 107, 3, *fc04request)
Debug "Len to send = " + len

ShowMemoryViewer(*fc04request, 16)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS485 bus with MODBUS communication protocol

Post by infratec »

marc_256
Addict
Addict
Posts: 857
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: RS485 bus with MODBUS communication protocol

Post by marc_256 »

hi mk-soft and infratec,

Thank you very much for your help.
This is very good stuff.

This will help me to communicate with the energy meter.


Greetings,
marc
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
Post Reply