Capture the display of a Rigol DS1000Z series oscilloscope by LAN using LXI SCPI commands
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

OscScreenGrabLAN.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. __author__ = 'RoGeorge'
  2. #
  3. # TODO: Port for Linux
  4. # TODO: Add command line parameters for IP, file path and file format
  5. # TODO: Add GUI
  6. # TODO: Add browse and custom filename selection
  7. # TODO: Create executable distributions
  8. # TODO: Use git, upload to GitHub
  9. #
  10. import telnetlib_receive_all
  11. import time
  12. import Image
  13. import StringIO
  14. import sys
  15. import os
  16. # Update the next lines for your own default settings:
  17. path_to_save = ""
  18. save_format = "PNG"
  19. IP_DS1104Z = "192.168.1.3"
  20. # Port used by Rigol LXI protocol
  21. port = 5555
  22. # Check parameters
  23. script_name = os.path.basename(sys.argv[0])
  24. # Print usage
  25. print
  26. print "Usage:"
  27. print " " + script_name + " [oscilloscope_IP [save_path [PNG | BMP]]]"
  28. print
  29. print "Usage examples:"
  30. print " " + script_name
  31. print " " + script_name + " 192.168.1.3"
  32. print " " + script_name + " 192.168.1.3 my_place_for_osc_captures"
  33. print " " + script_name + " 192.168.1.3 my_place_for_osc_captures BMP"
  34. print
  35. print "This program capture the image displayed"
  36. print " by a Rigol DS1000Z series oscilloscope, then save it on the computer"
  37. print " as a PNG or BMP file with a timestamp in the file name."
  38. print
  39. print " The program is using LXI protocol, so the computer"
  40. print " must have LAN connection with the oscilloscope."
  41. print " USB and/or GPIB connections are not used by this software."
  42. print
  43. print " No VISA, IVI or Rigol drivers are needed."
  44. print
  45. # Create/check if 'path' exists
  46. # Check network response (ping)
  47. response = os.system("ping -n 1 " + IP_DS1104Z + " > nul")
  48. if response != 0:
  49. print
  50. print "No response pinging " + IP_DS1104Z
  51. print "Check network cables and settings."
  52. print "You should be able to ping the oscilloscope."
  53. # Open a modified telnet session
  54. # The default telnetlib drops 0x00 characters,
  55. # so a modified library 'telnetlib_receive_all' is used instead
  56. tn = telnetlib_receive_all.Telnet(IP_DS1104Z, port)
  57. tn.write("*idn?") # ask for instrument ID
  58. instrument_id = tn.read_until("\n", 1)
  59. # Check if instrument is set to accept LAN commands
  60. if instrument_id == "command error":
  61. print instrument_id
  62. print "Check the oscilloscope settings."
  63. print "Utility -> IO Setting -> RemoteIO -> LAN must be ON"
  64. sys.exit("ERROR")
  65. # Check if instrument is indeed a Rigol DS1000Z series
  66. id_fields = instrument_id.split(",")
  67. if (id_fields[0] != "RIGOL TECHNOLOGIES") or \
  68. ((id_fields[1][:3] != "DS1") and (id_fields[1][-1] != "Z")):
  69. print
  70. print "ERROR: No Rigol from series DS1000Z found at ", IP_DS1104Z
  71. sys.exit("ERROR")
  72. print "Instrument ID:"
  73. print instrument_id
  74. # Prepare filename as C:\MODEL_SERIAL_YYYY-MM-DD_HH.MM.SS
  75. timestamp = time.strftime("%Y-%m-%d_%H.%M.%S", time.localtime())
  76. filename = path_to_save + id_fields[1] + "_" + id_fields[2] + "_" + timestamp
  77. # Ask for an oscilloscope display print screen
  78. tn.write("display:data?")
  79. print "Receiving..."
  80. buff = tn.read_until("\n", 10)
  81. # Just in case the transfer did not complete in 10 seconds
  82. while len(buff) < 1152068:
  83. tmp = tn.read_until("\n", 1)
  84. if len(tmp) == 0:
  85. break
  86. buff += tmp
  87. # Strip TMC Blockheader and last 3 bytes
  88. buff = buff[11:-3]
  89. # Save as PNG
  90. im = Image.open(StringIO.StringIO(buff))
  91. im.save(filename + ".png", "PNG")
  92. print "Saved file:", filename + ".png"
  93. # Save as BMP
  94. # scr_file = open(filename + ".bmp", "wb")
  95. # scr_file.write(buff)
  96. # scr_file.close()
  97. tn.close()
  98. # The code after this line was only for debugging purposes.
  99. # It prints the BMP header params, which are always the same.
  100. #
  101. # def print_hex(prt_buff):
  102. # print "(",
  103. # for c in prt_buff:
  104. # print hex(ord(c)),
  105. # print ")"
  106. #
  107. #
  108. # def print_dec(prt_buff):
  109. # n = 0
  110. # for c in reversed(prt_buff):
  111. # n = 256 * n + ord(c)
  112. # print n,
  113. #
  114. #
  115. # def prt_dec_hex(prt_buff):
  116. # print_dec(prt_buff)
  117. # print_hex(prt_buff)
  118. #
  119. #
  120. # def print_next_as(description, nr_of_bytes):
  121. # print description + " " * (50 - len(description)),
  122. # prt_dec_hex(buff[print_next_as.offset:print_next_as.offset+nr_of_bytes])
  123. # print_next_as.offset += nr_of_bytes
  124. # print_next_as.offset = 2
  125. #
  126. #
  127. # print
  128. # print "BMP header"
  129. # print "----------"
  130. # print "Header type: ", buff[0:2],
  131. # print_hex(buff[0:2])
  132. # print_next_as("BMP size in bytes:", 4)
  133. # print_next_as("reserved 2 bytes:", 2)
  134. # print_next_as("reserved 2 bytes:", 2)
  135. # print_next_as("Offset for BMP start of pixels array:", 4)
  136. # print
  137. # print "DIB header"
  138. # print "----------"
  139. # print_next_as("Number of DIB header bytes:", 4)
  140. # print_next_as("Image width (in pixels):", 4)
  141. # print_next_as("Image height (in pixels):", 4)
  142. # print_next_as("Number of color planes:", 4)
  143. # print_next_as("Number of bits per pixel:", 2)
  144. # print_next_as("Compression type used:", 4)
  145. # print_next_as("Size of the raw bitmap data (including padding):", 4)
  146. # print_next_as("Horizontal print resolution (pixels/meter):", 4)
  147. # print_next_as("Vertical print resolution (pixels/meter):", 4)
  148. # print_next_as("Number of colors in palette:", 4)
  149. # print_next_as("Important colors (0 means all):", 4)
  150. # print_next_as("First pixel (BGR):", 3)