Skip to content

Commit be8bf89

Browse files
authored
Merge pull request #1003 from gammeflamme/master
Support for Sinilink PSUs
2 parents a559c9e + 2b63a8e commit be8bf89

File tree

4 files changed

+279
-0
lines changed

4 files changed

+279
-0
lines changed

scopehal/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ set(SCOPEHAL_SOURCES
192192
RohdeSchwarzHMC8012Multimeter.cpp
193193
RohdeSchwarzHMC804xPowerSupply.cpp
194194
RidenPowerSupply.cpp
195+
SinilinkPowerSupply.cpp
195196
KuaiquPowerSupply.cpp
196197

197198
StandardColors.cpp

scopehal/SinilinkPowerSupply.cpp

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/***********************************************************************************************************************
2+
* *
3+
* libscopehal *
4+
* *
5+
* Copyright (c) 2012-2024 Andrew D. Zonenberg and contributors *
6+
* All rights reserved. *
7+
* *
8+
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
9+
* following conditions are met: *
10+
* *
11+
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
12+
* following disclaimer. *
13+
* *
14+
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
15+
* following disclaimer in the documentation and/or other materials provided with the distribution. *
16+
* *
17+
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
18+
* derived from this software without specific prior written permission. *
19+
* *
20+
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
21+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
22+
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
23+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
24+
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
25+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
26+
* POSSIBILITY OF SUCH DAMAGE. *
27+
* *
28+
***********************************************************************************************************************/
29+
30+
/**
31+
@file
32+
@brief Implementation of SinilinkPowerSupply
33+
@ingroup psudrivers
34+
*/
35+
36+
37+
#include "scopehal.h"
38+
#include "SinilinkPowerSupply.h"
39+
40+
using namespace std;
41+
42+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
43+
// Construction / destruction
44+
45+
/**
46+
@brief Initialize the driver
47+
48+
@param transport SCPITransport connected to the instrument
49+
*/
50+
51+
52+
53+
SinilinkPowerSupply::SinilinkPowerSupply(SCPITransport* transport)
54+
: SCPIDevice(transport, false), SCPIInstrument(transport, false), ModbusInstrument(transport)
55+
{
56+
// Only supports one channel for Sinilink PSUs
57+
m_channels.push_back(new PowerSupplyChannel("CH1", this, "#008000", 0));
58+
m_vendor = "sinilink";
59+
// Read model number
60+
uint16_t modelNumber = ReadRegister(REGISTER_MODEL);
61+
m_model = to_string(modelNumber/10) +"-" + to_string(modelNumber%10);
62+
// Read serial number
63+
uint16_t serialNumber = ReadRegister(REGISTER_SERIAL);
64+
m_serial = to_string(serialNumber);
65+
// Read firmware version number
66+
float firmwareVersion = ((float)ReadRegister(REGISTER_FIRMWARE))/100;
67+
m_fwVersion = to_string(firmwareVersion);
68+
// Unlock remote control
69+
WriteRegister(REGISTER_LOCK,0x00);
70+
}
71+
72+
SinilinkPowerSupply::~SinilinkPowerSupply()
73+
{
74+
75+
}
76+
77+
78+
79+
80+
81+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82+
// Device info
83+
84+
///@brief Return the constant driver name "SiniLink"
85+
string SinilinkPowerSupply::GetDriverNameInternal()
86+
{
87+
return "SiniLink";
88+
}
89+
90+
uint32_t SinilinkPowerSupply::GetInstrumentTypesForChannel([[maybe_unused]] size_t i) const
91+
{
92+
return INST_PSU;
93+
}
94+
95+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
96+
// Device capabilities
97+
98+
bool SinilinkPowerSupply::SupportsIndividualOutputSwitching()
99+
{
100+
return true;
101+
}
102+
103+
bool SinilinkPowerSupply::SupportsVoltageCurrentControl(int chan)
104+
{
105+
return (chan == 0);
106+
}
107+
108+
109+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
110+
// Actual hardware interfacing
111+
112+
bool SinilinkPowerSupply::IsPowerConstantCurrent(int chan)
113+
{
114+
if(chan == 0)
115+
return (ReadRegister(REGISTER_CVCC)==0x01);
116+
else
117+
return false;
118+
}
119+
120+
double SinilinkPowerSupply::GetPowerVoltageActual(int chan)
121+
{
122+
if(chan != 0)
123+
return 0;
124+
return ((double)ReadRegister(REGISTER_V_OUT))/100;
125+
}
126+
127+
double SinilinkPowerSupply::GetPowerVoltageNominal(int chan)
128+
{
129+
if(chan != 0)
130+
return 0;
131+
return ((double)ReadRegister(REGISTER_V_SET))/100;
132+
}
133+
134+
double SinilinkPowerSupply::GetPowerCurrentActual(int chan)
135+
{
136+
if(chan != 0)
137+
return 0;
138+
return ((double)ReadRegister(REGISTER_I_OUT))/1000;
139+
}
140+
141+
double SinilinkPowerSupply::GetPowerCurrentNominal(int chan)
142+
{
143+
if(chan != 0)
144+
return 0;
145+
return ((double)ReadRegister(REGISTER_I_SET))/1000;
146+
}
147+
148+
bool SinilinkPowerSupply::GetPowerChannelActive(int chan)
149+
{
150+
if(chan != 0)
151+
return false;
152+
return (ReadRegister(REGISTER_ON_OFF)==0x0001);
153+
}
154+
155+
void SinilinkPowerSupply::SetPowerVoltage(int chan, double volts)
156+
{
157+
if(chan != 0)
158+
return;
159+
WriteRegister(REGISTER_V_SET,(uint16_t)(volts*100));
160+
}
161+
162+
void SinilinkPowerSupply::SetPowerCurrent(int chan, double amps)
163+
{
164+
if(chan != 0)
165+
return;
166+
WriteRegister(REGISTER_I_SET,(uint16_t)(amps*1000));
167+
}
168+
169+
void SinilinkPowerSupply::SetPowerChannelActive(int chan, bool on)
170+
{
171+
if(chan != 0)
172+
return;
173+
WriteRegister(REGISTER_ON_OFF, (on ? 0x01 : 0x00));
174+
}

scopehal/SinilinkPowerSupply.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/***********************************************************************************************************************
2+
* *
3+
* libscopehal *
4+
* *
5+
* Copyright (c) 2012-2024 Andrew D. Zonenberg and contributors *
6+
* All rights reserved. *
7+
* *
8+
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
9+
* following conditions are met: *
10+
* *
11+
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
12+
* following disclaimer. *
13+
* *
14+
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
15+
* following disclaimer in the documentation and/or other materials provided with the distribution. *
16+
* *
17+
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
18+
* derived from this software without specific prior written permission. *
19+
* *
20+
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
21+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
22+
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
23+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
24+
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
25+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
26+
* POSSIBILITY OF SUCH DAMAGE. *
27+
* *
28+
***********************************************************************************************************************/
29+
30+
/**
31+
@file
32+
@brief Declaration of SinilinkPowerSupply
33+
@ingroup psudrivers
34+
*/
35+
36+
#ifndef SinilinkPowerSupply_h
37+
#define SinilinkPowerSupply_h
38+
39+
/**
40+
@brief Implementation for Sinilink PSUs such as XY-S3580, XY6020L
41+
@ingroup psudrivers
42+
*/
43+
class SinilinkPowerSupply
44+
: public virtual SCPIPowerSupply
45+
, public virtual ModbusInstrument
46+
{
47+
public:
48+
SinilinkPowerSupply(SCPITransport* transport);
49+
virtual ~SinilinkPowerSupply();
50+
51+
//Device information
52+
virtual uint32_t GetInstrumentTypesForChannel(size_t i) const override;
53+
54+
//Device capabilities
55+
virtual bool SupportsIndividualOutputSwitching() override;
56+
virtual bool SupportsVoltageCurrentControl(int chan) override;
57+
58+
//Read sensors
59+
virtual double GetPowerVoltageActual(int chan) override; //actual voltage after current limiting
60+
virtual double GetPowerVoltageNominal(int chan) override; //set point
61+
virtual double GetPowerCurrentActual(int chan) override; //actual current drawn by the load
62+
virtual double GetPowerCurrentNominal(int chan) override; //current limit
63+
virtual bool GetPowerChannelActive(int chan) override;
64+
65+
//Configuration
66+
virtual void SetPowerVoltage(int chan, double volts) override;
67+
virtual void SetPowerCurrent(int chan, double amps) override;
68+
virtual void SetPowerChannelActive(int chan, bool on) override;
69+
virtual bool IsPowerConstantCurrent(int chan) override;
70+
71+
protected:
72+
73+
enum Registers : uint8_t
74+
{
75+
REGISTER_MODEL = 0x16,
76+
REGISTER_SERIAL = 0x19,
77+
REGISTER_FIRMWARE = 0x17,
78+
79+
REGISTER_TEMP_C = 0x0D,
80+
REGISTER_TEMP_F = 0x0E,
81+
82+
REGISTER_V_SET = 0x00,
83+
REGISTER_I_SET = 0x01,
84+
REGISTER_V_OUT = 0x02,
85+
REGISTER_I_OUT = 0x03,
86+
87+
REGISTER_WATT = 0x04,
88+
REGISTER_V_INPUT = 0x05,
89+
REGISTER_LOCK = 0x0F,
90+
REGISTER_ERROR = 0x10,
91+
REGISTER_CVCC = 0x11,
92+
93+
REGISTER_ON_OFF = 0x12
94+
};
95+
96+
97+
public:
98+
static std::string GetDriverNameInternal();
99+
POWER_INITPROC(SinilinkPowerSupply);
100+
};
101+
102+
#endif

scopehal/scopehal.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include "RohdeSchwarzHMC804xPowerSupply.h"
8080
#include "SiglentPowerSupply.h"
8181
#include "RidenPowerSupply.h"
82+
#include "SinilinkPowerSupply.h"
8283
#include "KuaiquPowerSupply.h"
8384

8485
#include "SiglentLoad.h"
@@ -276,6 +277,7 @@ void DriverStaticInit()
276277
AddPowerSupplyDriverClass(HP662xAPowerSupply);
277278
AddPowerSupplyDriverClass(AlientekPowerSupply);
278279
AddPowerSupplyDriverClass(RidenPowerSupply);
280+
AddPowerSupplyDriverClass(SinilinkPowerSupply);
279281
AddPowerSupplyDriverClass(KuaiquPowerSupply);
280282

281283
AddRFSignalGeneratorDriverClass(SiglentVectorSignalGenerator);

0 commit comments

Comments
 (0)