API Usage

This section explains how to use the API.

Getting Started

Before calling any function, the qmh_pyclient.QMH.QMH.ServerConn() must be called first.

Example:

from qmh_pyclient import *

QMH.ServerConn(serverHost='localhost',serverPort=50007)
Prog=SD4Yv02(REF='SD4Yv02',Baudrate=115200,V_PSI5_h=11,V_PSI5_l=5.5) # REF is the com port number
SENSOR=AS5172E(Driver=Prog,Name="AS5172E")

Valid Sensor Names

Some base classes should not be called directly, hence the following classes can be directly initiated:

Coding examples

AS5171

The following code can be used to program an AS5171A/AS5171B.

 1from qmh_pyclient import *
 2import numpy
 3
 4QMH.ServerConn(serverHost='localhost',serverPort=50007)
 5
 6## Settings ##
 7Burn=False  ## Use burn with caution is it can happen only once ##
 8Custlock=False ## If Burn is True it is better to custom lock the part, so it will start in functional mode ##
 9
10# Prog=SD4Yv02(REF='SD4Yv02',Baudrate=115200)
11# Prog=SD4Yv01(REF='SD4Yv02')
12# Prog=UART_PCB(REF='com21',Baudrate=9600)
13Prog=Sim()
14SENSOR=AS5171A(Driver=Prog,Name="AS5171A")
15OTP_dict,_=SENSOR.REG_Read_OTP()
16print("Initial OTP::")
17print(OTP_dict)
18
19MAG,AGC=SENSOR.Read_Mag_AGC(NoOfReads=5) 
20print(f"MAG={numpy.average(MAG)}, AGC={numpy.average(AGC)}") # logs Mag and Agc or use them to check if magnet in range/exist.
21T1=int(numpy.average(SENSOR.Read_Cordic(5)))
22## The following code calculates the Gain,BP and other parameters need for defining the output ##
23Gain, BP, Offset, NoQ, RedAngle, CLH, CLL=SENSOR.RampCalc(T1=round(T1),T2=T1+1,Direction='cw',No_Q=1,CLH=0,CLL=0)
24
25
26print(f"Gain={Gain}, BP={BP}, Offset={Offset}, NoQ={NoQ}, RedAngle={RedAngle}, CLH={CLH}, CLL={CLL}")
27
28CLH_lo=CLH&0x0FF
29CLH_hi=(CLH&0xF00)>>8 # Shift Left by 8 (multiply)
30SENSOR.OTP14|=CLH_lo
31SENSOR.OTP15|=CLH_hi
32
33CLL_lo=(CLL&0x00F)<<4 # Shift Left by 4 (multiply)
34CLL_hi=(CLL&0xFF0)>>4 # Shift Right by 4 (divide)
35SENSOR.OTP15|=CLL_lo
36SENSOR.OTP16|=CLL_hi
37
38
39Offset_lo= Offset&0x0000FF
40Offset_mi=(Offset&0x00FF00)>>8 # Shift Right by 8 (divide)
41Offset_hi=(Offset&0xF0000)>>16 # Shift Right by 16 (divide)
42SENSOR.OTP17|=Offset_lo
43SENSOR.OTP18|=Offset_mi
44SENSOR.OTP19|=Offset_hi
45
46
47
48Gain_lo=(Gain & 0x00000F)<<4  # Shift Left by 4 (multiply) as it is stored at [4:7]
49Gain_mi=(Gain & 0x000FF0)>>4  # Shift Right by 4 (divide)
50Gain_hi=(Gain & 0x01F000)>>12 # Shift Right by 12 (divide)
51SENSOR.OTP19|=Gain_lo
52SENSOR.OTP1a|=Gain_mi
53SENSOR.OTP1b|=Gain_hi
54
55
56
57BP_lo =(BP & 0x0007)<<5  # Shift Left by 5 (multiply) as it is stored at [5:7]
58BP_mi =(BP & 0x07F8)>>3  # Shift Right by 3 (divide)
59BP_hi =(BP & 0x3800)>>11 # Shift Right by 11 (divide)
60SENSOR.OTP1b|=BP_lo
61SENSOR.OTP1c|=BP_mi
62SENSOR.OTP1d|=BP_hi
63
64if Burn==True:
65    if Custlock == True:
66        SENSOR.OTP1d|=0x80
67
68## Other settings can be changed as described in the datasheet of the product ##
69
70OTP_Array = [getattr(SENSOR, f'OTP{format(i, "02x")}', None) for i in range(0x1,0x1E)]
71SENSOR.REG_Write_Array(OTP_Array) ## Writing the OTP with signature calculated ##
72_1E=SENSOR.Signature_Calc() ## Signature calculation ##
73SENSOR.Write(0x1E,_1E<<8)
74time.sleep(5)
75OTP_dict_final,_=SENSOR.REG_Read_OTP() ## Final read to check if the data was written correctly ##
76## Checks if the data written is equal to the last write step ##
77# OTP_Array.append(_1E)
78OTP_Array[-1]=_1E
79
80if OTP_dict_final==OTP_Array:
81    print("Data was written")
82else:
83    raise NameError("The written data does not match")
84print(OTP_dict_final)
85if Burn==True:
86    if SENSOR.Fuse():
87        print("Data was fused")
88    else:
89        raise NameError("The fused data does not match")
90else:
91    SENSOR.Pass2Func()
92
93SENSOR.CloseDev()

AS5172

The following code can be used to program an AS5172E.

  1from qmh_pyclient import *
  2import numpy
  3
  4QMH.ServerConn(serverHost='localhost',serverPort=443)
  5
  6
  7# Prog=SD4Yv02(REF='SD4Yv02',Baudrate=115200,V_PSI5_h=11,V_PSI5_l=5.5)
  8# Prog=PSI5_PCBv01(REF='com21',Baudrate=38400)
  9Prog=Sim()
 10SENSOR=AS5172E(Driver=Prog,Name="AS5172E")
 11
 12MAG,AGC=SENSOR.Read_Mag_AGC(NoOfReads=5) 
 13print(f"MAG={numpy.average(MAG)}, AGC={numpy.average(AGC)}") # logs Mag and Agc or use them to check if magnet in range/exist.
 14T1=int(numpy.average(SENSOR.Read_Cordic(5)))
 15## The following code calculates the Gain,BP and other parameters need for defining the output ##
 16
 17Gain, BP, Offset, Quad, RedAngle, CLH, CLL=SENSOR.RampCalc(T1=round(T1),T2=T1+1,Direction='cw',No_Q=1,PSI5_mode=14)
 18
 19Velocity_Filter=0
 20velocity_range=1250
 21ExtRangeDis=False
 22RedAngle=False
 23FilterCFG=0
 24InitPhaseDis=True
 25DirBit=False
 26BitMode14=False
 27PSI5Mode=SENSOR.P16CRC_5003H_Timeslot1
 28LowPower=0
 29Pass2Func=True
 30
 31OTP,_=SENSOR.REG_Read_OTP()
 32# MSB >> LSB #
 33
 34## DirectionBit ##
 35# 0x01[2]
 36# 0000 0X00
 37if DirBit==False:
 38    SENSOR.OTP01&=0xFB
 39elif DirBit==True:
 40    SENSOR.OTP01|=0x04
 41
 42## VelocityRange 0x01.[0] & 0x01[6]
 43    # 0x01[0]
 44    # 0x01[6]
 45    # 0X00 000X
 46if velocity_range==1250:
 47    SENSOR.OTP01&=0xBE
 48elif velocity_range==4608:
 49    SENSOR.OTP01&=0xBE
 50    SENSOR.OTP01|=0x01
 51elif velocity_range==5000:
 52    SENSOR.OTP01&=0xBE
 53    SENSOR.OTP01|=0x40
 54else:
 55    raise NameError(f'velocity_range ({velocity_range}) is Out of range') # RAISE An Error
 56    
 57
 58## 14BitMode ##
 59# 0x01[3]
 60# 0000 X000
 61if BitMode14==False:
 62    SENSOR.OTP01&=0xF7
 63elif BitMode14==True:
 64        SENSOR.OTP01|=8
 65
 66## InitPhaseDisable ##
 67# 0x12[5]
 68# 00X0 0000
 69if InitPhaseDis==False:
 70    SENSOR.OTP12&=0xDF
 71elif InitPhaseDis==True:
 72    SENSOR.OTP12|=0x20 
 73
 74## Quad ##
 75    # 0x13[3:4]
 76    # 000x x000
 77if (Quad>=0) and (Quad <= 3):
 78    Quad=Quad <<3 ## Bit shift
 79    SENSOR.OTP13|=Quad
 80else:
 81    raise NameError(f'Quad ({Quad}) is Out of range') # RAISE An Error
 82
 83
 84## Velocity Filter ##
 85    # 0x13[5:7]
 86    # XXX0 0000
 87if (Velocity_Filter>=0) and (Velocity_Filter <= 7):
 88    Velocity_Filter=Velocity_Filter<<5 # Shift Left by 5 (multiply) as it is stored at [5:7]
 89    SENSOR.OTP13|=Velocity_Filter 
 90else:
 91    raise NameError(f'Velocity_Filter ({Velocity_Filter}) is Out of range') # RAISE An Error
 92    
 93## CLH ##
 94    # CLH[00:07] > 0x14[0:7]
 95    # CLH[08:11] > 0x15[0:3]
 96    # xxxx xxxx
 97    # 0000 xxxx
 98if (CLH>=0) and (CLH <= (2**12)-1):
 99    CLH_lo= CLH & 0x00FF
100    CLH_hi=(CLH & 0x0F00)>>8 # Shift Right by 8 (divide) 
101    SENSOR.OTP14|=CLH_lo
102    SENSOR.OTP15|=CLH_hi
103else:
104    raise NameError(f'CLH ({CLH}) is Out of range') # RAISE An Error
105
106## CLL ##
107    # CLL[00:03] > 0x15[4:7]
108    # CLL[04:11] > 0x16[0:3]
109    # xxxx 0000
110    # xxxx xxxx
111if (CLL>=0) and (CLL <= (2**12)-1):
112    CLL_lo=(CLL & 0x000F)<<4 # Shift Left by 4 (multiply) as it is stored at [4:7]
113    CLL_hi=(CLL & 0x0FF0)>>4 # Shift Right by 4 (divide)
114    SENSOR.OTP15=SENSOR.OTP15|CLL_lo
115    SENSOR.OTP16=SENSOR.OTP16|CLL_hi
116else:
117    raise NameError(f'CLL ({CLL}) is Out of range') # RAISE An Error
118
119## Offset ##
120    # Offset[00:07] > 0x17[0:7]
121    # Offset[08:15] > 0x18[0:7]
122    # Offset[16:19] > 0x19[0:3]
123    # XXXX XXXX
124    # XXXX XXXX
125    # 0000 XXXX
126if (Offset>=0) and (Offset <= (2**20)-1):
127    Offset_lo= Offset & 0x0000FF
128    Offset_mi=(Offset & 0x00FF00)>>8  # Shift Right by 8 (divide) 
129    Offset_hi=(Offset & 0x0F0000)>>16 # Shift Right by 8 (divide) 
130    SENSOR.OTP17|=Offset_lo
131    SENSOR.OTP18|=Offset_mi
132    SENSOR.OTP19|=Offset_hi
133    
134else:
135    raise NameError(f'Offset ({Offset}) is Out of range') # RAISE An Error
136
137## Gain ##
138    # Gain[00:03] > 0x19[4:7]
139    # Gain[04:11] > 0x1A[0:7]
140    # Gain[12:16] > 0x1B[0:3]
141    # XXXX XXXX
142    # XXXX XXXX
143    # 000X XXXX
144if -(2**16) <= Gain <= (2**16 - 1):
145    Gain_lo=(Gain & 0x00000F)<<4  # Shift Left by 4 (multiply) as it is stored at [4:7]
146    Gain_mi=(Gain & 0x000FF0)>>4  # Shift Right by 4 (divide)
147    Gain_hi=(Gain & 0x01F000)>>12 # Shift Right by 12 (divide)
148    SENSOR.OTP19|=Gain_lo
149    SENSOR.OTP1a|=Gain_mi
150    SENSOR.OTP1b|=Gain_hi
151    
152else:
153    raise NameError(f'Gain ({Gain}) is Out of range') # RAISE An Error
154
155## BP ##
156    # BP[00:02] > 0x1B[5:7]
157    # BP[03:10] > 0x1C[0:7]
158    # BP[11:13] > 0x1D[0:2]
159    # XXX0 0000
160    # XXXX XXXX
161    # 0000 0XXX
162if (BP>=0) and (BP <= (2**14)-1):
163    BP_lo =(BP & 0x0007)<<5  # Shift Left by 5 (multiply) as it is stored at [5:7]
164    BP_mi =(BP & 0x07F8)>>3  # Shift Right by 3 (divide)
165    BP_hi =(BP & 0x3800)>>11 # Shift Right by 11 (divide)
166    SENSOR.OTP1b|=BP_lo
167    SENSOR.OTP1c|=BP_mi
168    SENSOR.OTP1d|=BP_hi
169else:
170    raise NameError(f'BP ({BP}) is Out of range') # RAISE An Error
171
172## ExtRangeDis ##
173    # 0x1D[3]
174if ExtRangeDis==False:
175    SENSOR.OTP1d&=0xF7
176elif ExtRangeDis==True:
177    SENSOR.OTP1d|=0x08
178    
179## RedAngle ##
180    # 0x1D[4]
181if RedAngle==False:
182    SENSOR.OTP1d&=0xEF
183elif RedAngle==True:
184    SENSOR.OTP1d|=0x10
185
186  
187OTP_Array=[]
188i=1
189for reg in OTP:
190    _=eval(f'SENSOR.OTP{i:02x}')
191    if (_>=0) and (_<=255):
192        OTP_Array.append(_)
193        i=i+1
194    else:
195        raise NameError(f'({AS5172}.OTP{i:02x}=({_}) is Out of range') # RAISE An Error
196print(f"OTP_Array={OTP_Array}")
197SENSOR.REG_Write_Array(OTP_Array)
198SENSOR.REG_Read_OTP(CheckContent=True)
199
200SENSOR.SetPSI5Mode(PSI5Mode,LowPower=LowPower)
201
202SENSOR.Signature_Calc()
203SENSOR.REG_Write_OTP()
204time.sleep(.5)
205result=SENSOR.REG_Read_OTP(CheckContent=True)
206OTP_Final=result[0]
207Match=result[1]
208if Match==True:
209    pass
210else:
211    raise Exception("OPT Content Do not match")
212OTP_Final_str=';'.join(str(hex(_)) for _ in OTP_Final)
213Report.Add('OTP_Final',OTP_Final_str,1)
214Print(f"OTP_Final={OTP_Final}")
215if Pass2Func==True:
216    SENSOR.Pass2Func()
217
218SENSOR.CloseDev()