Val (Customer) asked a question.

How to connect P1AM-200 to C-more HMI using Circuitpyhton

Was wondering how I can control P1AM-200 which runs CircuitPyhton from C-more or any other HMI. I can only find Arduino code for Modbus TCP communication with C-more EA-9. Anyone knows about Modbus TCP or RTU code example or library for circuitpyhton I can use? Thanks!


  • ADC Community_02 (Automationdirect.com)

    Try the below to see if it gets you started:

    1. """
    2. =====
    3. This program is free software: you can redistribute it and/or modify
    4. it under the terms of the GNU General Public License as published by
    5. the Free Software Foundation, either version 3 of the License, or
    6. (at your option) any later version.
    7.  
    8. This program is distributed in the hope that it will be useful,
    9. but WITHOUT ANY WARRANTY; without even the implied warranty of
    10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    11. GNU General Public License for more details.
    12.  
    13. You should have received a copy of the GNU General Public License
    14. along with this program. If not, see <https://www.gnu.org/licenses/>.
    15. =====
    16.  
    17. Modified 11 December 2023
    18. by AutomationDirect.com
    19. Modbus TCP Server for P1AM-ETH with access to P1 Input/Output Modules
    20. This sketch creates a Modbus TCP Server on the P1AM-ETH shield.
    21.  
    22. Slot 1 Inputs are mapped to Modbus Input Bits 10001 to 10008.
    23. CPU Toggle switch is mapped to Modbus Input Bit 10009.
    24. Slot 2 Outputs are controlled by Modbus Coil Bits 00001 to 00008.
    25. Slot 3 Analog Inputs are mapped to Modbus Input Registers 30001 to 30004 and are disabled by default.
    26. Slot 4 Analog Outputs are controlled by Modbus Holding Registers 40005 to 40008 and are disabled by default.
    27. Modbus Holding Register 40001 increments once every second.
    28. Modbus Register 40002 to 40004 control the CPU RGB LED
    29. 40002 - Red channel
    30. 40003 - Green channel
    31. 40004 - Blue channel
    32.  
    33. The P1AM-200 CPU will require external 24vdc power for the IO modules to function.
    34. NOTE: Before running this example:
    35. Please ensure you have updated your board libraries using the link below.
    36. https://github.com/facts-engineering/ProductivityOpen_CircuitPython_Bundle/releases/latest
    37.  
    38. Required Libraries which need to be installed on the CPU.
    39. uModbus
    40. https://github.com/facts-engineering/pycom-modbus)
    41. """
    42.  
    43. import time
    44. import asyncio
    45. import P1AM
    46. import p1am_200_helpers as helper
    47. import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
    48. from uModBus.tcp import TCPServer # NOTE: the uModbus library must be installed on the CPU first
    49.  
    50. eth = helper.get_ethernet(False) # DHCP False
    51.  
    52. IP_ADDRESS = (10, 0, 0, 150)
    53. SUBNET_MASK = (255, 255, 255, 0)
    54. GATEWAY_ADDRESS = (10, 0, 0, 1)
    55. DNS_SERVER = (8, 8, 8, 8)
    56. eth.ifconfig = (IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER)
    57.  
    58. socket.set_interface(eth)
    59. server_ip = eth.pretty_ip(eth.ip_address)
    60. mb_server = TCPServer(
    61. socket,
    62. server_ip,
    63. number_coils=0xFF,
    64. number_input_registers=0xFF,
    65. number_discrete_inputs=0xFF,
    66. number_holding_registers=0xFF,
    67. )
    68.  
    69. mb_server.input_registers = list(range(16)) # set input register value to their address
    70.  
    71. color = [0, 255, 0] # LED color
    72. for i in range(1, 4): # set starting values
    73. mb_server.holding_registers[i] = color[i-1]
    74.  
    75. toggle = helper.get_switch(); # CPU toggle switch
    76.  
    77.  
    78. #P1 IO modules
    79. base = P1AM.Base() # Intializes base. Returns the base object.
    80. slot1 = base[1] # module object for slot 1
    81. slot2 = base[2] # module object for slot 2
    82. #slot3 = base[3] # module object for slot 3
    83. #slot4 = base[4] # module object for slot 4
    84.  
    85. async def main():
    86. modbus_server_task = asyncio.create_task(modbus_server())
    87. neopixel_task = asyncio.create_task(neopixel_control())
    88. await asyncio.gather(neopixel_task, modbus_server_task)
    89. async def modbus_server():
    90. count = 0
    91. lastseconds = 0
    92. while True:
    93. #try:
    94. mb_server.poll() #timeout=.1) # Regularly poll the modbus server to handle incoming requests
    95. #except RuntimeError as e:
    96. # pass # Ignore errors in case the client disconnects mid-poll
    97.  
    98. mb_server.discrete_inputs[8] = toggle.value # value of toggle switch
    99. for i in range(1,9):
    100. # Read from Discrete Input Module and then write into Modbus memory
    101. mb_server.discrete_inputs[i-1] = slot1[i].value # set discrete inputs
    102. # Write from Modbus memory to Discrete Output Module
    103. slot2[i].value = mb_server.coils[i-1] # set discrete outputs
    104. # To Read from Analog Input Module in slot 3 and then write into Modbus memory 30001 - 30004, uncomment the following 2 lines
    105. #for j in range(1,5):
    106. # mb_server.input_registers[j-1] = slot3.inputs[j].value # Read from Analog Inputs Modbus memory
    107. # To Write the values in Modbus Registers 40005, 40006, 40007, & 40008 to Analog Output Module channels in slot 4, uncomment the following 3 lines
    108. #for k in range(1,3):
    109. # slot4.outputs[k].value = mb_server.holding_registers[k+4] # Write Modbus memory to Analog Outputs
    110. # NOTE: for Analog Outputs, the value being written to the analog output channel must be within the resolution of the module (e.g. 12-bit resolution is 0-4095)
    111. if (time.monotonic() - lastseconds) > 1:
    112. lastseconds = time.monotonic()
    113. count += 1
    114. if count > 32767:
    115. count = 0 # reset count
    116. color[0] = mb_server.holding_registers[1] # red
    117. color[1] = mb_server.holding_registers[2] # green
    118. color[2] = mb_server.holding_registers[3] # blue
    119. mb_server.holding_registers[0] = count # set holding register 0 to count value
    120. await asyncio.sleep(0.05)
    121. # Set LED to current value of global color variable
    122. async def neopixel_control():
    123. #Neopixel RGB LED
    124. p = helper.get_neopixel() # get neopixel object
    125. p.brightness = 0.1 # Brightness level
    126.  
    127. while True:
    128. p[0] = [int(val) for val in color] # Write to neopixel
    129. await asyncio.sleep(0.01)
    130. asyncio.run(main())

     

     

    Expand Post
  • Val (Customer)

    Thank you for your code!

    I uploaded board library to bundle-8 and installed uModbus but getting error 'no module named 'adafruit_wiznet5k.adafruit_wiznet5k_socket'

    Checked bundle-8 and seems like there is no .mpy file with such name in adafruit_wiznet5k folder

    imageAm I downloading wrong bundle?

    Expand Post
    • FACTS_AdamC (AutomationDirect)

      Looks like our libraries are slightly out of date, I'll start digging into this and see if I can get everything corrected for you

    • FACTS_AdamC (AutomationDirect)

      Ok, so I'll need to get the public code updated, but I believe the fix for this is pretty easy.

       

      Change:

      1. import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket

      to

      1. import adafruit_wiznet5k.adafruit_wiznet5k_socketpool as SocketPool

      and add this line before the mb_server declaration

       

      1. socket = SocketPool.SocketPool(eth) # add this line
      2.  
      3. server_ip = eth.pretty_ip(eth.ip_address)
      4. mb_server = TCPServer(
      5. socket,
      6. server_ip,
      7. number_coils=0xFF,
      8. number_input_registers=0xFF,
      9. number_discrete_inputs=0xFF,
      10. number_holding_registers=0xFF,
      11. )

       

       

      Expand Post
      • Val (Customer)

        Thank you. Code is running fine now but I still have trouble controlling P1AM-200 though C-more HMI, keep getting 'PLC communication timeout'. ETH module works, I can connect to Ethernet. When configuring panel I am choosing Modicon Modbus TCP protocol, using P1AM-200 IP and specifying 40002, 40003 and 40004 addressed for RGB LED color control. But no luck. Is it possible to share your CM5 project file for above code?

        Expand Post
  • Val (Customer)

    I tried multiple different CM5 Protocol Manager configurations but keep getting 'Ethernet test fail' message, below. Everything works fine in Arduino. So it has something to do either with uModbus parameters or its incompatibility with new libraries, last time it was updated is 2018..

     

    IMG_0913

    Expand Post