Cryotel CT/MT/GT

Hi all! I’m currently running CryoTel CT and MT cryocoolers ( https://www.sunpowerinc.com/products/stirling-cryocoolers/cryotel-cryocoolers/mt), will likely be running a GT as well. I’m looking to be able to control the coolers and datalog via Python. Any chance anyone has any experience with this? Any help would be greatly appreciated!

You can check out PySerial. That might be helpful as a starting point. You would also need to go through the device’s manual or API documentation to find out the communication protocol.

Will have a look. Thanks!

Always nice to see the cool things you can do with Python.

1 Like

Python is very flexible unlike many people think. And, now, the grammar/statements are becoming more readable unlike Java or C++.

Hey, all. Been jumping between this and reading from a temperature monitor and have come to this point.

import serial
import time

ser.close()
ser = serial.Serial(port='COM8',\
                   baudrate=4800,\
                   parity=serial.PARITY_NONE,\
                   stopbits=serial.STOPBITS_ONE,\
                   bytesize=serial.EIGHTBITS,\
                   timeout=1)

while True:
    cmd = input
    if cmd == 'exit':
        ser.close()
        quit()
    else:
        ser.write((('STATE'+'\r')).encode('ascii'))
        out = ser.read_until().decode('ascii')
        time.sleep(.5)
ser.close()

Output:

I’m hoping to clean up the output a bit. Specifically, eliminate the blank lines in between and have all the returned in one block rather than wait the .5s for each read. Any thoughts?

Hmm, not sure where your output’s coming from. Do you have any print calls that aren’t visible in the code you posted?

Sorry! Copied from a previous iteration. There’s print call after ‘out = …’ and time.sleep(.5).

import serial
import time

ser.close()
ser = serial.Serial(port='COM8',\
                   baudrate=4800,\
                   parity=serial.PARITY_NONE,\
                   stopbits=serial.STOPBITS_ONE,\
                   bytesize=serial.EIGHTBITS,\
                   timeout=1)

while True:
    cmd = input
    if cmd == 'exit':
        ser.close()
        quit()
    else:
        ser.write((('STATE'+'\r')).encode('utf-8'))
        out = ser.read_until().decode('utf-8')
        print(out)
        time.sleep(.5)
ser.close()

Ah yeah, thought it might be! In that case, you can remove the double-spacing in one of two ways:

# Remove the newline from the string
print(out.strip()) # or print(out.rstrip("\r\n")
# Ask print to not add a newline of its own
print(out, end="")

As to returning it all in one block - that one I can’t help with; you’d have to test what happens when you remove the sleep call. It might be fine.

A few small points though. cmd = input doesn’t actually prompt the user for input (cmd = input() would do that), so all you’re doing is checking whether the input function is equal to the string "exit", which it never will be. And when you werite out your command, there’s no need to go to all that effort; either of these calls will be exactly equivalent:

ser.write('STATE\r'.encode('utf-8'))
ser.write(b'STATE\r')

Won’t make a lot of difference to your program’s behaviour, but it might be easier to read.

Finally, this version of the code probably doesn’t work, since you begin right at the top of the script by attempting to close the serial port that you haven’t opened yet. I would definitely recommend running the script before posting it, to make sure your code, output, and question are all aligned. Though if you’re working interactively in something like Jupyter, rather than using a script per se, that might be a little harder; but it can still be worth making a script version of the code before posting, to ensure that it’s self-contained and internally consistent.

In any case, things seem to be broadly working, so from here, it’s minor refinements - yay!

Nailed it! Adding end=“” knocked out the blank lines, and time.sleep(.5) was spacing out the readouts. Though I will need the time.sleep at some point to get reads at regular intervals

Yeah, the cmd function will probably be taken out. This all came from a dummy code I cobbled together and have been building from for three different units. I have a hand full of commands I want to combine into one for data logging and this is my first ever python project I accidentally got myself into when I suggested to my boss that we automate everything, including data logs. It has been a journey so far :sweat_smile: Thanks dude!

1 Like

Awesome! Sounds like a success story for scripting. Win!

Here’s where I am at the moment and I’ve hit a coding block.

import serial
import time

ser.close()
ser = serial.Serial(port='COM7',\
                    baudrate=4800,\
                    parity=serial.PARITY_NONE,\
                    stopbits=serial.STOPBITS_ONE,\
                    bytesize=serial.EIGHTBITS,\
                    timeout=1)

while True:
    cmd = input()
    if cmd == 'exit':
        ser.close()
        quit()
    elif cmd == 'start':
        ser.write((('SET SSTOP=0' + '\r')).encode('utf-8'))
        out = ser.read_until().decode('utf-8')

    elif cmd == 'stop':
        ser.write((('SET SSTOP=1' + '\r')).encode('utf-8'))
        out = ser.read_until().decode('utf-8')

    else:
        while True:
            ser.write((('TC'+'\r')).encode('utf-8'))

            out1 = ser.read_until().decode('utf-8')
            out2 = out1.replace("TC", "").lstrip()
            print(out2, end="")
            time.sleep(.5)
ser.close()

I’d like to apply this to a second port. Everything is the same (serial params and commands), I’d just like to send the commands to both COM7 and COM8 simultaneously. Any thoughts?

It’s time to think about running more than one thing at a time. Explore threading, asyncio, and other options, and have fun with it! :slight_smile:

Seems like overkill for this application. With just two connections that should both do the same thing, just sending the commands sequentially will be indistinguishable from a more sophisticated solution.

import serial
import time

PORTS = ["COM7", "COM8"]
SERS = [serial.Serial(p, baudrate=4800, timeout=1) for p in PORTS]


def start():
    for s in SERS:
        s.write((("SET SSTOP=0" + "\r")).encode("utf-8"))
        out = s.read_until().decode("utf-8")
        # You might want to do something with 'out' here.


def stop():
    for s in SERS:
        s.write((("SET SSTOP=1" + "\r")).encode("utf-8"))
        out = s.read_until().decode("utf-8")
        # Here, too.


def do_stuff():
    # I'm not really clear on what you are telling your device to do here, so rename
    # this function to something more appropriate.
    for s in SERS:
        s.write((("TC" + "\r")).encode("utf-8"))
        out1 = s.read_until().decode("utf-8")
        out2 = out1.replace("TC", "").lstrip()
        print(out2, end="")


while True:
    cmd = input()

    if cmd == "exit":
        for s in SERS:
            s.close()
        break
    elif cmd == "start":
        start()
    elif cmd == "stop":
        stop()
    else:
        while True:
            do_stuff()
            time.sleep(0.5)

You will probably want to add some way to leave the inner while loop.

This assumes that the connected devices respond to commands more or less immediately. If there is significant waiting time between sending a command and getting a response, you could split the functions into senders and receivers. First send all commands, then collect all replies, instead of stopping to wait for each device to respond as above.