Tekpower TP3005p power supply control code

For PC type software that runs under some PC opsys.

Tekpower TP3005p power supply control code

Postby Doug Coulter » Tue Nov 21, 2017 6:52 pm

I just bought a couple of these supplies to power H bridges for some fusor HV work, and of course, want to control them remotely. This is supposed to be possible via USB, which is really emulated serial in this case, from a PC (or whatever). They publish a manual with the protocol, and boy, does this merit some comment as you'll see below.
I noticed some real severe flaws in the Chinglish interpretation going in both directions - they misinterpreted the near-standard they were copying, and...then documented it in a way no one would "get".
Otherwise, these look like nice supplies at a reasonable price.

There is a fairly serious flaw here, and in fixing it, there might wind up being a lot more to this thread than the usual "here's the review and my code".
USB things, serial emulators specifically, are supposed to report a unique name when the opsys picks them up. In linux, this shows up under /dev/Serial/by-name/.
Now one can write software that looks for a particular piece of gear by name, and it'll always get the right one, or fail. No chance of sending commands to the wrong thing - like windows com ports for example, that can be re-mapped just by replugging a device - it was com2, now it's com11 say. Linux has that functionality too for brain dead coders - in this case serial things are also mapped to ttyUSB# (the # being whatever number) but I and other Linux users are getting spoiled with its superior handling of most things like this.
The TP3005 supplies all report the exact same "unique" ID, which evidently is just the factory one for the USB chip they reverse engineered and stole IP from.

In this case, I got two supplies which will be driving two very different things and sending the commands to the wrong one means smoke and danger. This isn't a cute little oversight on their part.

They all report as: usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 under /dev/serial/, and I'm not yet sure what linux is going to do with two identical file names, probably add (1) at the end of one of them. But that wouldn't tell me which is which, and it matters. This could change depending on what machine it's hooked to, which one powers up first, and any number of other uncontrolled variables.

If I have to use a raspberry pi or ESP8266 for each one to be sure I'm talking to the right one, I'll do that and just build it into the supply itself. Kinda galling to spend that money because some Chinese guy couldn't read or didn't care (this would likely mess up windows too...).

That other mistake is laughable. Anyone who writes any code knows that /n stands for newline, not the two characters slash and enn. This is standard in just about every language, from C to Java, to python, to perl...the slash means "next character should use a special interpretation". Guess what? Where the standard format used by tektronix, GW Insek and others shows a command followed by /n, they mean newline, no programmer needs that explained. Except the guys at Tekpower, evidently. I couldn't get it going from a terminal emulator at first, till I really looked at the python code written by a third party and shared and noticed //n - which means "escape the slash and in this case send it literally" and of course, now the n is just an n. Yup, that's what this brain-dead thinks is the command delimiter - not the new line, but a literal '/n'!

I'm writing a nice little perl gui, but if I can't come up with a software fix for the "don't know which unit" problem, it may go much further, as it really matters here, and no, I can't afford another few minutes of setup on every run especially if it requires physical presence to do it.

Here's some python contributed by a guy who goes by Circumflex designs:
http://www.circumflex.systems/
Code: Select all
# Circumflex Designs 2017
#
#   init_comm(port_name)        Opens named com port and initializes comm
#   end_comm()                  Closes comm port
#
#   output_state(out_on)        If state is < 1 then output is turned off.  Otherwise, it is turned on.
#
#   volts_setpoint_set(volts)   Sets output voltage to volts
#   volts_setpoint_get()        Returns voltage setpoint from power supply
#   volts_meas()                Returns the output voltage measurement from the power supply
#
#   amps_setpoint_set(amps)     Sets output current (limit) to amps
#   volts_setpoint_get()        Returns current setpoint from power supply
#   volts_meas()                Returns the output current measurement from the power supply
#
#   status_get()                Returns the power supply status flags
#

import serial
import time

#Create the global serial object
ser1 = serial.Serial()


#Time delay - should instead use time.sleep()
def delay(secs):
    start = time.time()
    while ((time.time() - start) < secs):
        continue



#Initiate comm with PS
def init_comm(port):
    global ser1

    ser1 = serial.Serial(port, 9600, timeout=1)
    print(ser1.name)
    print ("Serial Port is Open: %d\n" % ser1.is_open)
    ser1.reset_input_buffer()
    ser1.reset_output_buffer()
    time.sleep(1)
    print (status_get())
    time.sleep(0.1)

def end_comm():
    ser1.close()


def output_state(out_on):
    time.sleep(0.05)
    if out_on >= 1:
        cmd = b'OUTPUT1:\\r\\n'
        print("Output On")
    else:
        cmd = b'OUTPUT0\\r\\n'
        print ("Output Off")
    ser1.write(cmd)
    #print (cmd)
    #print (out_on)
    time.sleep(0.05)


def volts_setpoint_set(volts):
    time.sleep(0.05)
    cmd = b'VSET1:'                      #b'VSET1:07.00\\r\\n'
    cmd = cmd + format(volts, "=05.2F").encode('ascii')
    cmd = cmd + b'\\r\\n'
    ser1.write(cmd)
    #print(cmd)

def volts_setpoint_get():
    time.sleep(0.05)
    cmd = b'VSET1?\\r\\n'
    ser1.write(cmd)
    line = ser1.readline()
    #print("Response: %s" % line)
    volts = float(line.decode('utf8'))
    return volts

def volts_meas():
    time.sleep(0.05)
    cmd = b'VOUT1?\\r\\n'
    ser1.write(cmd)
    line = ser1.readline()
    #print("Response: %s" % line)
    volts = float(line.decode('utf8'))
    return volts


def amps_setpoint_set(amps):
    time.sleep(0.05)
    cmd = b'ISET1:'                      #b'ISET1:2.500\\r\\n'
    cmd = cmd + format(amps, "=05.3F").encode('ascii')
    cmd = cmd + b'\\r\\n'
    ser1.write(cmd)
    #print(cmd)

def amps_setpoint_get():
    time.sleep(0.05)
    cmd = b'ISET1?\\r\\n'
    ser1.write(cmd)
    line = ser1.readline()
    #print("Response: %s" % line)
    amps = float(line.decode('utf8'))
    return amps

def amps_meas():
    time.sleep(0.05)
    cmd = b'IOUT1?\\r\\n'
    ser1.write(cmd)
    line = ser1.readline()
    #print("Response: %s" % line)
    amps = float(line.decode('utf8'))
    return amps


def status_get():
    time.sleep(0.05)
    cmd = b'STATUS?\\r\\n'
    ser1.write(cmd)
    line = ser1.readline()
    #print("Response: %s" % line)
    status = int(line.decode('utf8'))
    return status



# Test Program
def test():

    init_comm("Com4")


    volts_setpoint_set(5.5)
    amps_setpoint_set(0.50)
    output_state(1)

    time.sleep(1)

    print ("Setpoints")
    print (volts_setpoint_get())
    print (amps_setpoint_get())

    print ()

    for i in range(5):
        volts_setpoint_set((i+1) * 1)
        time.sleep(0.5)
        print (volts_meas())
        print (amps_meas())

    print()
    print (status_get())

    output_state(0)

    print (status_get())

    end_comm()

    print("Done\n")



#test()

Displaying TP3005P.py.

Which I presume he meant to share - and as I messaged him, he should point out at least that last killer error as most troubleshooting technique would have issues finding that bug.
I'm coming up with a cute little GUI for this, but as mentioned, it might have to be in an ESP8266 web page and need one of those per supply to be safe for remote control.
tpgui.png
my GUI template
tpgui.png (13.12 KiB) Viewed 187 times

For reference the manual - no programmer I know would have read this as putting in a literal /n.
30V 3A 30V 5A PROGRAMMABLE.pdf
Manual - laughable mis-interpretation on their part
(22.94 KiB) Downloaded 8 times


More soon, I hope.
Posting as just me, not as the forum owner. Everything I say is "in my opinion" and YMMV -- which should go for everyone without saying.
User avatar
Doug Coulter
 
Posts: 2984
Joined: Wed Jul 14, 2010 8:05 pm
Location: Floyd county, VA, USA

Re: Tekpower TP3005p power supply control code

Postby Doug Coulter » Thu Nov 23, 2017 1:12 pm

Here's a shot of the insides of this power supply, which I'm reverse engineering. The offending USB interface board has the scope probes on it. In front is a little prototype I'd done earlier with an ESP-12 module for another use, but that's roughly what I'm going to put in here once it works as a prototype. For the real deal I plan to use an ESP-07 module, which has an external antenna jack. That way I can put it inside the steel case and have the wifi antenna external for use.

But that module is kind of a pain to work with - it doesn't even have the amenities that the Adafruit Huzzah has - there aren't even any buttons to press to get it into programming mode, I'd have to lash some up.

So instead of doing that, I'm going to proto on the "easy" one, get over the air updates going on, burn the real target one ONCE the hard way...and proceed from there.

As you can see, it's not a crappy power supply, all the right stuff is there, it looks like a nice thermal design, there are relays to switch transformer taps as the volts are adjusted to keep waste heat down and it uses a microchip PIC 16f887 I've got the datasheet for. That last is a good thing as I was able to get the reset circuit so I can have the ESP reset the main processor and get rid of that "once you've set it up with a computer, you can't use the front panel again without a full power cycle" crap. I'll just have a command to the ESP to pull reset on the thing.
20171123-1316-tekpower-1.jpg
The guts of the tekpower


FWIW, here's the manual. No programmer I've ever met would assume a literal \n - that's the universal code for the otherwise non-printing <linefeed>. I added the note just under the title...
30V 3A 30V 5A PROGRAMMABLE.pdf
The communication spec...
(22.94 KiB) Downloaded 4 times
Posting as just me, not as the forum owner. Everything I say is "in my opinion" and YMMV -- which should go for everyone without saying.
User avatar
Doug Coulter
 
Posts: 2984
Joined: Wed Jul 14, 2010 8:05 pm
Location: Floyd county, VA, USA

Re: Tekpower TP3005p power supply control code

Postby Doug Coulter » Sat Nov 25, 2017 11:23 am

Well, it's not quite done, but it's coming along nicely. The arduino sketch doesn't yet assign the IO pin for the hardware reset of the power supply, but most of the rest is there and working as far as I can tell. Since C(++) is a horrible place to do text parsing, I didn't do much - most of the commands are just pass-through. I only parsed whether there's a question mark or not - to see if I should wait for and forward a reply from the supply, and whether there's an exclamation point which will be the reset command. Even unfinished, though, this code isn't a bad place to begin something else like this - not too much is specific to this use, but all the over the air update stuff is in and working, my LANDNS unit annoucement code is in there, and it's basically good to go. I'll add the rest and test when I get some level shifters currently "in the mail" from Adafruit - the ESP is 3.3v and the supply is 5v logic. I'll just use a 2n3904 to drive the PIC reset when I get there.
In the meanwhile, I'll finish up (well, as far as I can without testing) the perl GUI stuff, and change the dropdown from using serial ports to UDP and so on. At least this way I can be sure that if I tell a supply to put out full snot - it'll be the correct one...any smoke will then be my own fault.
TP3005.ino.zip
arduino sketch as it is now
(2.12 KiB) Downloaded 4 times


Not quite generic, but I can think of a lot of things this is a good base for - it just converts UDP on a known port and a known IP address/hostname into TTL serial - the special-case code is pretty tiny.
I'll soon try to burn it into an ESP(8266)-07 - these are supplied raw, so I'll have to jigger up the reset switch and the GPIO switch to get it into burn mode. I'm going to test and edit to full operational status with an easier version first.

I didn't yet (and probably won't) put in the code that has the ESP emit a setup web page if it can't find the hardcoded wifi WAP..if this was a product, that'd be a good thing to do. The other tools I've built will tell me if a unit is "there". If nothing else, the command "cat /etc/hosts" lists everyone who is there and doing my LANDNS pretty easy and quick.
Posting as just me, not as the forum owner. Everything I say is "in my opinion" and YMMV -- which should go for everyone without saying.
User avatar
Doug Coulter
 
Posts: 2984
Joined: Wed Jul 14, 2010 8:05 pm
Location: Floyd county, VA, USA

Re: Tekpower TP3005p power supply control code

Postby Doug Coulter » Mon Dec 04, 2017 5:03 pm

OK, here's some code that is close to, if not finished.
The perl contains the gtk3 definitions internally, but of course you have to put in GTK3.pm (I have a script somewhere if anyone asks, it's a pain otherwise due to dependencies).
The .ino assumes a network name of the last 3 bytes of the mac plus _TP2 so the perl can know which is which more easily.
This checks what the power supply is already set to, in case you should connect to one that's already doing stuff...but on reflection, doesn't yet check it's enabled state (easy to add).
On exit we reset the power supply which returns front panel control the the user if they are present.

So, here's the goodies:
TP3005perl.zip
perl and that GTK3 install script (for linux)
(3.45 KiB) Not downloaded yet

TP3005ota.ino.zip
ESP8266-07 sketch with over the air updates enabled
(2.04 KiB) Downloaded 2 times


FWIW, the point of this diversion from fusion is....fusion. The new lashup wants some fairly high power switching stuff. I have a nice H bridge driver design I've built a few of laying around. The weakness of that particular hardware is that it just switches the input DC rail, with no control over that at all. So, to control that, you use a programmable power supply and can even do it remotely if you have something cool like, um, what I just did. Hope it all makes sense now - I'm still keeping eyes on the prize, it's just that the road to there isn't always a straight line.

Along the way, also FWIW - here is a rather nasty hardware bug (or something like that) that made this take too long. And the fix, so you don't hit it yourself.
viewtopic.php?f=6&p=6259#p6259
Posting as just me, not as the forum owner. Everything I say is "in my opinion" and YMMV -- which should go for everyone without saying.
User avatar
Doug Coulter
 
Posts: 2984
Joined: Wed Jul 14, 2010 8:05 pm
Location: Floyd county, VA, USA


Return to PC

Who is online

Users browsing this forum: No registered users and 1 guest

cron