Python Forum
Help with applying this instrument monitoring code to multiple inputs.
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help with applying this instrument monitoring code to multiple inputs.
#1
Hello, world.

I have some working code (below) that communicates with a pressure gauge, takes the reading, saves it to a log file, and displays a live plot.

I am hoping that someone is willing to help with rewriting it so that I can neatly apply it to my other gauges. Right now I have a single plot, and I output a log file with two columns (time and pressure). I think that what I want is to have a function inside the animation loop that takes in instrumentID and "Title" as inputs, and maybe add an argument to the whole script that tells it how many gauges I have and how to arrange the subplots. That last bit might be dumb though?

Extra credit (I would be super appreciative if you help with these, but don't feel that you need to, to help with the above):
1) I've seen in other forum posts that I should be using "return line," instead of plt.draw(), but I can't seem to get that to display my datetime axis properly, if it works at all. Should I change it to this? If so, how?
2) I'd like to add a header line to the log file. This has made me realize I have a problem, though. What happens if I start the program with (GaugeA, GaugeB, GaugeC), then close it and reopen later with (GaugeB, GaugeA, GaugeD). This seems like a serious problem.
3) Also, just in general, it should be obvious that I am a total n00b. I would appreciate comments on how to write this code better in general (e.g. variable naming, order of operations, etc)

My thanks in advance,
Mike

import visa
from datetime import datetime
import time
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, (ax1) = plt.subplots(1, 1)

#-------------------------------------------------------

date = datetime.today().strftime('%Y-%m-%d') + '.txt'
logfile = open(date,'a')                 # Create or open a log file with today's date

rm = visa.ResourceManager()                     # Open up the visa RM that looks for connected instruments
CapGauge = rm.open_resource('ASRL3::INSTR')     # Open up the specific instrument I care about
CapGauge.read_termination = '\r\n'              # Fix the terminations so that I get a response at all
CapGauge.write_termination = '\r\n'

#-------------------------------------------------------
x = []
y = []

def animate(i):                                             # This is the animation loop for my live plot
    current_time = datetime.now().strftime("%H:%M:%S")      # Format the date how I like it
    CapGauge.query('PR1')                                   # I send the query to the instrument asking for Pressue Reading on gauge 1
                                                            # The instrument then replies with "\x06\x13\x10" (ACKNOWLEDGE CR LF)
                                                            # Or, if reading is unsuccessful,  "\x15\x13\x10" (NEGATIVE ACKNOWLEDGE CR LF)
    tempstr = CapGauge.query('\x05')                        # Then I send the "\x05" (ENQUIRY) character

    if len(tempstr)>1:                                      # This catches the junk feedback lines that happen sometimes because I'm a bad programmer
        tempstr = tempstr.split(',')[1]                     # The gauge sends a string with format "a,sxx.xxxxEsxx"
                                                            # where a is a status integer, s is a sign, and sxx.xxxxEsxx is my pressure reading
        x.append(datetime.now().replace(microsecond=0))     # I strip away the microseconds here just coz they annoy me, but I keep the datetime format
        y.append(float(tempstr))                            # Turn the pressure reading string into a float
        logfile.write(current_time + '\t')                  # Write it to my log file as well
        logfile.write(tempstr + '\n')
        logfile.flush()                                     # Save my logfile so that I don't lose the data if something goes wrong
        ax1.clear()                                         # Clear the axes
        ax1.plot(x,y)                                       # Plot the data (including the newly appended point)
        ax1.set_title("Capacitance Manometer")              # Make the live plot look nice
        ax1.set_xlabel("Time")                              # Make the live plot look nice
        ax1.set_ylabel("Pressure (mbar)")                   # Make the live plot look nice
    time.sleep(0.5)                                         # Wait to take the next data point
    plt.draw()                                              # I admit I'm not at all clear on what plt.draw() does, vs ax1.plot() and plt.show()

anim = animation.FuncAnimation(fig, animate, frames = 200, interval = 20) # Do the animation
plt.show()                                                  # Show the plot

CapGauge.close()
logfile.close()
raise SystemExit

Reply
#2
Okay, this is how far I've gotten (see below).

I decided to make a Class called "Instrument" that initializes with the instrumentID, the name string I want for the instrument, and empty lists for x-y coords for the plot. It also takes in the necessary terminator string which is different for a few of the gauges I have, as well as a type (manufacturer) identifier to tell it what comms protocol to use, because that, again, is different between the different gauge types.

The Instrument class also has an update method which does the pressure reading query, adds the new data to the plot, and writes it to the log file, preceded by a tab. This way, in the animate loop, I can write the current time to the log file, then iterate through a list of all the gauges I have active, running the update and then plotting.

I also made an init function for the animate loop that writes the header line I wanted, using the name property from each Instrument.

Comments would be greatly appreciated.
Thanks,
Mike

import visa
from datetime import datetime
import time
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

class Instrument:
    def __init__(self, InstrumentIdentifierString, InstrumentName, terminator, type):
        global rm
        self.title = InstrumentName
        self.type = type
        self.ID = rm.open_resource(InstrumentIdentifierString)
        self.ID.read_termination = terminator
        self.ID.write_termination = terminator
        self.x = []
        self.y = []

    def update(self):
        global logfile
        tempstr = ""
        counter = 0
        while len(tempstr)<1:
            if self.type == "Pfeiffer":
                self.ID.query('PR1')
                tempstr = self.ID.query('\x05')
            elif self.type == "Jevatec":
                tempstr = self.ID.query('RPV\x2C1')
            counter += 1
            if counter = 10:
                tempstr = " ,'----------"
        tempstr = tempstr.split(',')[1]
        self.x.append(datetime.now().replace(microsecond=0))
        self.y.append(float(tempstr))
        logfile.write('\t' + tempstr)

def animinit(GaugeList):
    global logfile
    global fig
    global axlist
    logfile.write("# Time")
    for iter,instr in enumerate(GaugeList):
        axlist[0][iter].set_title(instr.title)
        axlist[0][iter].set_xlabel("Time")
        axlist[0][iter].set_ylabel("Pressure(mbar)")
        logfile.write('\t "' + instr.title + '"')
    logfile.write('\n')
    logfile.flush()


def animate(i, GaugeList):
    current_time = datetime.now().strftime("%H:%M:%S")
    logfile.write(current_time)
    for iter,instr in enumerate(GaugeList):
        instr.update()
        axlist[0][iter].clear()
        axlist[0][iter].plot(instr.x,instr.y)
    logfile.write('\n')
    logfile.flush()
    time.sleep(60)
    plt.draw()

date = datetime.today().strftime('%Y-%m-%d--%Hh-%Mm') + '.txt'
logfile = open(date,'a')                 # Create or open a log file with today's date

rm = visa.ResourceManager()                     # Open up the visa RM that looks for connected instruments
GaugeList = []
GaugeList.append(Instrument('ASRL4::INSTR','Analysis Chamber','\r\n','Pfeiffer'))
#GaugeList.append(Instrument('ASRL5::INSTR','Detector','\r','Jevatec'))

fig,axlist = plt.subplots(1, len(GaugeList),squeeze=False)

anim = animation.FuncAnimation(fig, animate, frames=200, init_func=animinit(GaugeList), fargs=(GaugeList,), interval=20) # Do the animation
plt.show()                                                  # Show the plot

for instr in GaugeList:
    instr.ID.close()
logfile.close()
raise SystemExit
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Applying Moving Averages formula to a number lynnette1983 1 276 Sep-29-2020, 10:21 AM
Last Post: scidam
  Hi, I need help with defining user's input and applying it to code. jlmorenoc 2 409 Jun-24-2020, 02:10 PM
Last Post: pyzyx3qwerty
  How do you take terminal inputs w/o halting running code? Bhoot 3 379 Apr-17-2020, 08:31 AM
Last Post: deanhystad
  Problem with accepting multiple string inputs Ryan_Todd 5 505 Jan-22-2020, 06:12 PM
Last Post: buran
  multiple problems with code SrijaRamarthy 2 435 Nov-06-2019, 06:24 AM
Last Post: SrijaRamarthy
  OOP and module approaches in a simple app monitoring list of servers hjzxxzjcz 1 348 Nov-01-2019, 04:30 PM
Last Post: nilamo
  applying and(&) ,or(|) in conditions does not result output correctly as expected Smiling29 4 552 Oct-21-2019, 01:39 AM
Last Post: ichabod801
  Applying row height to all rows including and after row 7 curranjohn46 2 845 Oct-14-2019, 03:10 PM
Last Post: curranjohn46
  PYTHON - UNRAR : how can I build a thread to monitoring the downloading status Palerm0_24 2 703 Mar-18-2019, 02:25 PM
Last Post: Palerm0_24
  Watching for inputs from multiple sources concurrently anakaine 4 783 Mar-03-2019, 07:38 PM
Last Post: woooee

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020