helicalscan commissioned at ESB_MX!
This commit is contained in:
@@ -34,7 +34,10 @@ Modes:
|
||||
3: sine bode closed loop
|
||||
4: chirp bode closed loop
|
||||
5: full bode open loop record of both motors (including init_stage
|
||||
|
||||
10: bode of current step -> does not work because gathering phase data not implemented
|
||||
-> check https://github.com/klauer/ppmac for fast data gathering server which supports
|
||||
phase gathering -> not yet compiling: /home/zamofing_t/Documents/prj/SwissFEL/PowerBrickInspector/ppmac/fast_gather
|
||||
BUT data acquired and stored in: /media/zamofing_t/DataUbuHD/VirtualBox/shared/data
|
||||
TODO:
|
||||
use openloopsine to create a bode diagram of the 'strecke'
|
||||
'''
|
||||
@@ -48,6 +51,8 @@ import subprocess as sprc
|
||||
import telnetlib
|
||||
from scipy.signal.waveforms import chirp
|
||||
from scipy import signal
|
||||
from scipy import interpolate
|
||||
from scipy import stats
|
||||
from utilities import *
|
||||
|
||||
class PBTuning:
|
||||
@@ -71,8 +76,9 @@ class PBTuning:
|
||||
fnLoc=self.fnLoc
|
||||
except AttributeError:
|
||||
fnLoc = '/tmp/gather.txt'
|
||||
cmd=(PBGatherPlot,'-m24','-v0','--host',host,'--dat',fnLoc)
|
||||
p = sprc.Popen(cmd, shell=False, stdin=sprc.PIPE, stdout=sprc.PIPE, stderr=sprc.PIPE)
|
||||
cmd=(PBGatherPlot,'-m24','-v255','--host',host,'--dat',fnLoc)
|
||||
#p = sprc.Popen(cmd, shell=False, stdin=sprc.PIPE, stdout=sprc.PIPE, stderr=sprc.PIPE)
|
||||
p = sprc.Popen(cmd, shell=False)
|
||||
retval = p.wait()
|
||||
print(p.stderr.read())
|
||||
#print(p.stdout.read())
|
||||
@@ -312,11 +318,10 @@ class PBTuning:
|
||||
f=np.load(file)
|
||||
bode=f['bode']
|
||||
meta=f['meta'].item()
|
||||
frq=bode[:,0]
|
||||
mag=bode[:,1]
|
||||
phase=np.unwrap(bode[:,2])
|
||||
frq=[bode[:,0],]
|
||||
mag=[bode[:,1],]
|
||||
phase=[np.unwrap(bode[:,2]),]
|
||||
|
||||
l=[0,len(frq)]
|
||||
#for fn in ('chirp_ol_mot%da.npz','chirp_ol_mot%db.npz','chirp_ol_mot%dc.npz','chirp_ol_mot%dd.npz'):
|
||||
# fn=fn%mot
|
||||
# file=os.path.join(base,fn)
|
||||
@@ -325,7 +330,7 @@ class PBTuning:
|
||||
f=np.load(file)
|
||||
data=f['data']
|
||||
meta=f['meta'].item()
|
||||
tSec=meta['tSec']
|
||||
tSec=float(meta['tSec'])
|
||||
minFrq=meta['minFrq']
|
||||
maxFrq=meta['maxFrq']
|
||||
amp=meta['amp']
|
||||
@@ -342,42 +347,68 @@ class PBTuning:
|
||||
ftX=np.fft.rfft(c)
|
||||
ftY=np.fft.rfft(o)
|
||||
i=int(minFrq*tSec); j=int(maxFrq*tSec); #print(w[i],w[j])
|
||||
f=np.arange(n+1)/tSec #Hz
|
||||
f=f[i:j+1]
|
||||
frq_=np.arange(n+1)/tSec #Hz
|
||||
frq_=frq_[i:j+1]
|
||||
ftX=ftX[i:j+1]
|
||||
ftY=ftY[i:j+1]
|
||||
|
||||
ft=ftY/ftX
|
||||
frq=np.concatenate((frq,f))
|
||||
frq.append(frq_)
|
||||
phase_=np.unwrap(np.angle(ft))
|
||||
if phase_[0]>0:
|
||||
phase_-=2*np.pi
|
||||
phase=np.concatenate((phase,phase_))
|
||||
mag=np.concatenate((mag,(np.abs(ftY)/np.abs(ftX))))
|
||||
l.append(len(frq))
|
||||
phase.append(phase_)
|
||||
mag.append(np.abs(ftY)/np.abs(ftX))
|
||||
|
||||
|
||||
db_mag=20*np.log10(mag)
|
||||
phase=np.degrees(phase)# numpy.unwrap(p, discont=3.141592653589793, axis=-1)
|
||||
numFrq=1000
|
||||
fFrq= np.logspace(np.log10(frq[0][0]), np.log10(frq[-1][-1]),numFrq)
|
||||
fdb_mag = np.zeros(fFrq.shape)
|
||||
fdeg_phase = np.zeros(fFrq.shape)
|
||||
|
||||
fig = plt.figure()
|
||||
fig.canvas.set_window_title('full bode of motor %d'%mot)
|
||||
ax = fig.add_subplot(2, 1, 1)
|
||||
ax1 = fig.add_subplot(2, 1, 1)
|
||||
ax2 = fig.add_subplot(2, 1, 2)
|
||||
plt.title('bode of motor %d'%mot)
|
||||
for i in range(len(l)-1):
|
||||
ax.semilogx(frq[l[i]:l[i+1]], db_mag[l[i]:l[i+1]],'-') # Bode magnitude plot
|
||||
ax.yaxis.set_label_text('dB ampl')
|
||||
ax.set_xlim(1,2000)
|
||||
plt.grid(True)
|
||||
#ax.loglog(frqLst, bode[:,0],'.-') # Bode magnitude plot
|
||||
ax = fig.add_subplot(2, 1, 2)
|
||||
for i in range(len(l)-1):
|
||||
ax.semilogx(frq[l[i]:l[i+1]], phase[l[i]:l[i+1]],'-')#,zorder=i) # Bode phase plot
|
||||
ax.yaxis.set_label_text('phase')
|
||||
ax.xaxis.set_label_text('frequency [Hz]')
|
||||
ax.set_xlim(1,2000)
|
||||
ax.set_ylim(-360,0)
|
||||
plt.grid(True)
|
||||
for i in range(len(frq)):
|
||||
db_mag = 20 * np.log10(mag[i])
|
||||
deg_phase = np.degrees(phase[i]) # numpy.unwrap(p, discont=3.141592653589793, axis=-1)
|
||||
if deg_phase[0]>0:
|
||||
deg_phase-=360
|
||||
|
||||
|
||||
ax1.semilogx(frq[i], db_mag,'-') # Bode magnitude plot
|
||||
ax2.semilogx(frq[i], deg_phase, '-') # ,zorder=i) # Bode phase plot
|
||||
|
||||
#fill the final magnitude and phase
|
||||
if i==0:
|
||||
f=interpolate.interp1d(frq[i], db_mag,bounds_error=False)
|
||||
fdb_mag=f(fFrq)
|
||||
f=interpolate.interp1d(frq[i], deg_phase,bounds_error=False)
|
||||
fdeg_phase=f(fFrq)
|
||||
else:
|
||||
print((frq[i][0],frq[i][-1]))
|
||||
s=stats.binned_statistic(frq[i], db_mag,'mean',fFrq)[0]
|
||||
b=~np.isnan(s); fdb_mag[:-1][b]=s[b] #[:-2][b] because the statistics has one less entry than the count of bins
|
||||
s=stats.binned_statistic(frq[i], deg_phase,'mean',fFrq)[0]
|
||||
b=~np.isnan(s); fdeg_phase[:-1][b]=s[b]
|
||||
pass
|
||||
|
||||
ax1.semilogx(fFrq, fdb_mag,'y')
|
||||
ax2.semilogx(fFrq, fdeg_phase, 'y')
|
||||
#export bode plot fot matlab analysis
|
||||
fn = os.path.join(base,'full_bode_mot%d.mat'%mot)
|
||||
import scipy.io
|
||||
scipy.io.savemat(fn, mdict={'db_mag':fdb_mag,'deg_phase':fdeg_phase})
|
||||
#scipy.io.savemat('/home/zamofing_t/afs/ESB-MX/data/' + fn + '.mat', mdict=f)
|
||||
|
||||
ax1.yaxis.set_label_text('dB ampl')
|
||||
ax1.set_xlim(1,2000)
|
||||
ax1.grid(True)
|
||||
ax2.yaxis.set_label_text('phase')
|
||||
ax2.xaxis.set_label_text('frequency [Hz]')
|
||||
ax2.set_xlim(1,2000)
|
||||
ax2.set_ylim(-360,0)
|
||||
ax2.grid(True)
|
||||
pass
|
||||
|
||||
def bode_model_plot(self, mot,base):
|
||||
self.bode_full_plot(mot,base)
|
||||
@@ -481,7 +512,7 @@ class PBTuning:
|
||||
den=den1*den2*den3*den4*den5*denc
|
||||
mdl= signal.lti(num, den) #num denum
|
||||
bode(mdl)
|
||||
w=np.logspace(0,3,1000)*2*np.pi
|
||||
w=np.logspace(0,np.log10(2000),1000)*2*np.pi
|
||||
w,mag,phase = signal.bode(mdl,w)
|
||||
f=w/(2*np.pi)
|
||||
ax=fig.axes[0]
|
||||
@@ -490,8 +521,24 @@ class PBTuning:
|
||||
ax.semilogx(f, phase,'-k',lw=2) # Bode phase plot
|
||||
# tp print see also: print(np.poly1d([1,2,3], variable='s')), print(np.poly1d([1,2,3], r=True, variable='s'))
|
||||
|
||||
def bode_current(self,openloop=True,motor=1,magMove=1000,magPhase=500,dwell=10,file='/tmp/bode.npz'):
|
||||
#currentstep 2 1000 500 10
|
||||
#magPhase: set this current to move the stage at a stable position: vslue in bits
|
||||
#magMove: set this current to measure the current transition: value in bits
|
||||
#dwell: measurement time in ms.the time the current is set
|
||||
|
||||
# Amplifier specs (Power Brick LV User Manual.pdf p.19)
|
||||
# 5A_rms continous current
|
||||
# 15A_rms peak current
|
||||
# 14 bit ADC resolution
|
||||
# 2us PWM deadBand
|
||||
# 33.85A Maximum ADC Current (corresponds to a DAC Value 32737 ==2^15)
|
||||
|
||||
data = self.do_command('currentstep', motor, magMove, magPhase, dwell)
|
||||
|
||||
|
||||
def bode(mdl):
|
||||
w,mag,phase = signal.bode(mdl)
|
||||
w,mag,phase = signal.bode(mdl,1000)
|
||||
f=w/(2*np.pi)
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(2, 1, 1)
|
||||
@@ -626,6 +673,10 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
|
||||
tune.bode_chirp(openloop=True,file=file[:-4]+'c.npz',motor=mot,amp=50,minFrq=300,maxFrq=1500,tSec=10)
|
||||
tune.init_stage()
|
||||
tune.bode_chirp(openloop=True,file=file[:-4]+'d.npz',motor=mot,amp=100,minFrq=300,maxFrq=2000,tSec=10)
|
||||
elif mode==10:
|
||||
#for mot in (1,2):
|
||||
tune.bode_current(motor=mot, magMove=1000, magPhase=500, dwell=10, file='/tmp/curr_step%d.npz'%mot)
|
||||
print 'done'
|
||||
plt.show()
|
||||
#------------------ Main Code ----------------------------------
|
||||
#ssh_test()
|
||||
|
||||
Reference in New Issue
Block a user