1
0

ADUCv2p1.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. #!/usr/bin/env python
  2. from smbus import SMBus
  3. import time
  4. from struct import *
  5. import array
  6. import numpy as np
  7. import math
  8. # instead of having some varisable associated to the class that we should
  9. # update continuously with the the chip, we only access to the variables
  10. # to the chip via set_/get_ functions
  11. class ADUCv2p1:
  12. # Initialize the connection to the board
  13. # addr: i2c addres, can be obtained by running "i2detect -y 1" from terminal
  14. # if with_about = True, will print information from the board
  15. def __init__(self,addr,with_about=False):
  16. self.bus_pi = SMBus(1)
  17. self._addr = addr;
  18. self.get_wf_len();
  19. if with_about==True:
  20. print( self.get_text())
  21. print( "----------------\n")
  22. # Read last valid waveform from the microcontroller, up to 256 points
  23. def read_data(self):
  24. dat = []
  25. if self._wf_len>=256:
  26. N=16
  27. self._wf_len = 256
  28. else:
  29. N = int(self._wf_len/16+1)
  30. ## add an error message in case wf_len/16 is not an integer?
  31. self.set_transf(1)# to remove
  32. for i in range(0,N):
  33. block = self.bus_pi.read_i2c_block_data(self._addr,i,32)
  34. buff = pack("32B",*block)
  35. dat = np.append(dat,unpack("<16H",buff))
  36. self.set_transf(0) #to remove
  37. dat=np.uint16(dat)
  38. return dat[0:self._wf_len]
  39. #
  40. def get_text(self):
  41. dat = []
  42. for i in range(0,16):
  43. block = self.bus_pi.read_i2c_block_data(self._addr,i+50,32)
  44. buff = pack("32B",*block)
  45. dat = np.append(dat,unpack("32c",buff))
  46. return ''.join(dat.astype(str))#''.join(str((dat[0:3]).tostring()))
  47. # sets DACX where X is the channel ch to the voltage V (in the range 0 to 4095)
  48. # Make sure you are in a mode where the voltage is not being inmediately overwritten
  49. def set_Vout(self,ch,V):
  50. self.bus_pi.write_word_data(self._addr,100+ch,V)
  51. #execute the setting commande on the chip
  52. self.bus_pi.read_i2c_block_data(self._addr,105,1)
  53. return
  54. def get_Vout(self,ch):
  55. #execute the reading commande on the chip
  56. self.bus_pi.read_i2c_block_data(self._addr,104,1)
  57. block = self.bus_pi.read_i2c_block_data(self._addr,100+ch,2)
  58. buff = pack("2B",*block)
  59. dat = unpack("<H",buff)
  60. dat=np.uint16(dat)
  61. return dat[0]
  62. # Set the input offset (in the range 0 to 4095)
  63. def set_offset(self, V):
  64. set_Vout(0, V)
  65. def get_offset(self):
  66. return self.get_Vout(0)
  67. # sets the value of the coarse output voltage when the box is in learn mode
  68. def set_Vlearn(self,V):
  69. self.bus_pi.write_word_data(self._addr,110,V)
  70. return
  71. def get_Vlearn(self):
  72. block = self.bus_pi.read_i2c_block_data(self._addr,110,2)
  73. buff = pack("2B",*block)
  74. dat = unpack("<H",buff)
  75. dat=np.uint16(dat)
  76. return dat[0]
  77. # reads the height of the last measured signal
  78. def get_Vin(self):
  79. block = self.bus_pi.read_i2c_block_data(self._addr,111,8)
  80. buff = pack("8B",*block)
  81. dat = unpack("<d",buff)
  82. dat=np.float64(dat)
  83. return dat[0]
  84. # reads the height of the last measured ground
  85. def get_Vin_gnd(self):
  86. block = self.bus_pi.read_i2c_block_data(self._addr,112,8)
  87. buff = pack("8B",*block)
  88. dat = unpack("<d",buff)
  89. dat=np.float64(dat)
  90. return dat[0]
  91. #
  92. def get_ID(self):
  93. block = self.bus_pi.read_i2c_block_data(self._addr,120,1)
  94. self._addr = block[0]
  95. return block[0]>>1
  96. def set_ID(self,ID):
  97. self._addr = ID
  98. return self.bus_pi.write_byte_data(self._addr,120,ID<<1)
  99. #
  100. def get_channel(self):
  101. block = self.bus_pi.read_i2c_block_data(self._addr,121,2)
  102. buff = pack("2B",*block)
  103. dat = unpack("<H",buff)
  104. dat=np.uint16(dat)
  105. return dat[0]
  106. def set_channel(self,channel):
  107. return self.bus_pi.write_word_data(self._addr,121,channel)
  108. #
  109. def set_transf(self,status):
  110. return self.bus_pi.write_byte_data(self._addr,122,status)
  111. # Sets the remote_trigg flag. Set to 0 so that the microcontroller uses the trigger
  112. # input, set it to 1 so that it continuously triggers
  113. def set_remote_trigg(self,status):
  114. return self.bus_pi.write_byte_data(self._addr,115,status)
  115. def get_remote_trigg(self):
  116. block = self.bus_pi.read_i2c_block_data(self._addr,115,2)
  117. buff = pack("2B",*block)
  118. dat = unpack("<H",buff)
  119. dat=np.uint16(dat)
  120. return dat[0]
  121. # Sets the number of recorded points, up to a maximum of 256. Sampling frequency is approx. 1MHz.
  122. def set_wf_len(self,wf_len):
  123. self._wf_len = wf_len
  124. if wf_len>256:
  125. print( "sorry, it is not possible to have more than 256 point per waveform.\n")
  126. self._wf_len = 256
  127. return self.bus_pi.write_word_data(self._addr,123,self._wf_len)
  128. def get_wf_len(self):
  129. block = self.bus_pi.read_i2c_block_data(self._addr,123,2)
  130. buff = pack("2B",*block)
  131. dat = unpack("<H",buff)
  132. dat=np.uint16(dat)
  133. self._wf_len = dat[0]
  134. return dat[0]
  135. #
  136. def get_trigg_cnt(self):
  137. block = self.bus_pi.read_i2c_block_data(self._addr,124,4)
  138. buff = pack("4B",*block)
  139. dat = unpack("<I",buff)
  140. dat=np.uint32(dat)
  141. return dat[0]
  142. #
  143. def get_wf_cnt(self):
  144. block = self.bus_pi.read_i2c_block_data(self._addr,113,8)
  145. buff = pack("8B",*block)
  146. dat = unpack("<Q",buff)
  147. dat=np.uint64(dat)
  148. return int(dat[0])
  149. #
  150. def get_v_cnt(self):
  151. block = self.bus_pi.read_i2c_block_data(self._addr,114,8)
  152. buff = pack("8B",*block)
  153. dat = unpack("<I",buff)
  154. dat=np.uint32(dat)
  155. return dat[0]
  156. #
  157. def set_test(self,tmp):
  158. self.bus_pi.write_word_data(self._addr,141,tmp)
  159. self.bus_pi.read_i2c_block_data(self._addr,105,1)
  160. return
  161. def get_test(self):
  162. self.bus_pi.read_i2c_block_data(self._addr,104,1)
  163. block = self.bus_pi.read_i2c_block_data(self._addr,141,2)
  164. buff = pack("2B",*block)
  165. dat = unpack("<H",buff)
  166. dat=np.uint16(dat)
  167. return dat[0]
  168. #
  169. def set_erase(self):
  170. #self.bus_pi.read_i2c_block_data(self._addr,106,1)
  171. self.bus_pi.write_byte_data(self._addr,106,0)
  172. time.sleep(0.04)
  173. return
  174. #
  175. def get_probe(self):
  176. block = self.bus_pi.read_i2c_block_data(self._addr,142,2)
  177. buff = pack("2B",*block)
  178. dat = unpack("<H",buff)
  179. dat=np.uint16(dat)
  180. return dat[0]
  181. #
  182. def set_probe(self,tmp):
  183. self.bus_pi.write_word_data(self._addr,142,tmp)
  184. return
  185. # Set the value we are aiming to achieve in the signal when in lock mode
  186. def set_Vset(self,Vset):
  187. return self.bus_pi.write_word_data(self._addr,125,Vset)
  188. def get_Vset(self):
  189. block = self.bus_pi.read_i2c_block_data(self._addr,125,2)
  190. buff = pack("2B",*block)
  191. dat = unpack("<H",buff)
  192. dat=np.uint16(dat)
  193. return dat[0]
  194. # Set the number of waveforms to average before stabilizing
  195. def set_N(self,N):
  196. return self.bus_pi.write_word_data(self._addr,126,N)
  197. def get_N(self):
  198. block = self.bus_pi.read_i2c_block_data(self._addr,126,2)
  199. buff = pack("2B",*block)
  200. dat = unpack("<H",buff)
  201. dat=np.uint16(dat)
  202. return dat[0]
  203. #
  204. def get_FEE_addr(self):
  205. block = self.bus_pi.read_i2c_block_data(self._addr,140,2)
  206. buff = pack("2B",*block)
  207. dat = unpack("<H",buff)
  208. dat=np.uint16(dat)
  209. return dat[0]
  210. def set_FEE_addr(self,FEE_addr):
  211. return self.bus_pi.write_word_data(self._addr,140,FEE_addr)
  212. # Set the point at which we start measuring the signal
  213. def set_start(self,start):
  214. return self.bus_pi.write_word_data(self._addr,127,start)
  215. def get_start(self):
  216. block = self.bus_pi.read_i2c_block_data(self._addr,127,2)
  217. buff = pack("2B",*block)
  218. dat = unpack("<H",buff)
  219. dat=np.uint16(dat)
  220. return dat[0]
  221. # Set the point at which we stop measuring the signal
  222. def get_stop(self):
  223. block = self.bus_pi.read_i2c_block_data(self._addr,128,2)
  224. buff = pack("2B",*block)
  225. dat = unpack("<H",buff)
  226. dat=np.uint16(dat)
  227. return dat[0]
  228. def set_stop(self,stop):
  229. return self.bus_pi.write_word_data(self._addr,128,stop)
  230. # Set the point at which we start measuring the background
  231. def set_start_gnd(self,start_gnd):
  232. return self.bus_pi.write_word_data(self._addr,131,start_gnd)
  233. def get_start_gnd(self):
  234. block = self.bus_pi.read_i2c_block_data(self._addr,131,2)
  235. buff = pack("2B",*block)
  236. dat = unpack("<H",buff)
  237. dat=np.uint16(dat)
  238. return dat[0]
  239. # Set the point at which we stop measuring the background
  240. def set_stop_gnd(self,stop_gnd):
  241. return self.bus_pi.write_word_data(self._addr,132,stop_gnd)
  242. def get_stop_gnd(self):
  243. block = self.bus_pi.read_i2c_block_data(self._addr,132,2)
  244. buff = pack("2B",*block)
  245. dat = unpack("<H",buff)
  246. dat=np.uint16(dat)
  247. return dat[0]
  248. # Set whether the microcontroller should automatically select the best offset
  249. # and gain when in learn mode. auto_set_pga=0 to turn off the functionality and
  250. # to do it manually using set_pga and set_Vout(0, x)
  251. def set_auto_set_pga(self,auto_set_pga):
  252. return self.bus_pi.write_word_data(self._addr,129,auto_set_pga)
  253. def get_auto_set_pga(self):
  254. block = self.bus_pi.read_i2c_block_data(self._addr,129,2)
  255. buff = pack("2B",*block)
  256. dat = unpack("<H",buff)
  257. dat=np.uint16(dat)
  258. return dat[0]
  259. # Set the ratio of sensitivities of the fine to coarse voltage outputs of the board
  260. # This is 20 as per circuit design, but can be tuned more precisely
  261. def set_coarse_fine_ratio(self,coarse_fine_ratio):
  262. return self.bus_pi.write_word_data(self._addr,130,coarse_fine_ratio)
  263. def get_coarse_fine_ratio(self):
  264. block = self.bus_pi.read_i2c_block_data(self._addr,130,2)
  265. buff = pack("2B",*block)
  266. dat = unpack("<H",buff)
  267. dat=np.uint16(dat)
  268. return dat[0]
  269. # Set whether the microcontroller should subtract the background when measuring.
  270. # status=0 to disable this. status=1 to enable it.
  271. def set_enab_gnd(self,status):
  272. return self.bus_pi.write_byte_data(self._addr,133,status)
  273. def get_enab_gnd(self):
  274. block = self.bus_pi.read_i2c_block_data(self._addr,133,2)
  275. buff = pack("2B",*block)
  276. dat = unpack("<H",buff)
  277. dat=np.uint16(dat)
  278. return dat[0]
  279. # Set the pga_state, this is defined via state = g*16+8 where g is such that the gain G
  280. # in the input measurements is G=2^g and G is one of {1, 2, 4, 8, 16, 32, 64, 128}
  281. # i.e. 0<g<7
  282. def set_pga_state(self,state):
  283. self.bus_pi.write_byte_data(self._addr,136,state)
  284. #execute set on the chip
  285. self.bus_pi.read_i2c_block_data(self._addr,137,1)
  286. return
  287. def get_pga_state(self):
  288. block = self.bus_pi.read_i2c_block_data(self._addr,136,2)
  289. buff = pack("2B",*block)
  290. dat = unpack("<H",buff)
  291. dat=np.uint16(dat)
  292. return dat[0]
  293. def read_pga_state(self):
  294. #execute set on the chip
  295. self.bus_pi.read_i2c_block_data(self._addr,138,1)
  296. return
  297. def set_input_gain(self, gain):
  298. state = int(math.log2(gain))*16 + 8
  299. self.set_pga_state(state)
  300. def get_input_gain(self):
  301. state = self.get_pga_state()
  302. return 2**(state-8)//16
  303. # Set the feedback gain
  304. def set_Gain(self,Gain):
  305. tmp = (Gain)
  306. buff = pack("<f",Gain)
  307. dat = unpack("4B",buff)
  308. return self.bus_pi.write_i2c_block_data(self._addr,134,[dat[0],dat[1],dat[2],dat[3]])
  309. def get_Gain(self):
  310. block = self.bus_pi.read_i2c_block_data(self._addr,134,4)
  311. buff = pack("4B",*block)
  312. dat = unpack("<f",buff)
  313. dat=np.float32(dat)
  314. return dat[0]
  315. # Set the maximum step step_max, allowed in one iteration of the loop
  316. def set_step_max(self,step_max):
  317. return self.bus_pi.write_word_data(self._addr,135,step_max)
  318. def get_step_max(self):
  319. block = self.bus_pi.read_i2c_block_data(self._addr,135,2)
  320. buff = pack("2B",*block)
  321. dat = unpack("<H",buff)
  322. dat=np.uint16(dat)
  323. return dat[0]
  324. # Read whether we are in learn (0) or lock mode (1)
  325. def get_mode(self):
  326. block = self.bus_pi.read_i2c_block_data(self._addr,139,2)
  327. buff = pack("2B",*block)
  328. dat = unpack("<H",buff)
  329. dat=np.uint16(dat)
  330. return dat[0]
  331. # Set the relative sensitivities of the coarse and fine output
  332. def set_coarse_fine_ratio(self,ratio):
  333. tmp = (ratio)
  334. buff = pack("<f",ratio)
  335. dat = unpack("4B",buff)
  336. return self.bus_pi.write_i2c_block_data(self._addr,140,[dat[0],dat[1],dat[2],dat[3]])
  337. def get_coarse_fine_ratio(self):
  338. block = self.bus_pi.read_i2c_block_data(self._addr,140,4)
  339. buff = pack("4B",*block)
  340. dat = unpack("<f",buff)
  341. dat=np.float32(dat)
  342. return dat[0]
  343. # Read whether we are out of lock
  344. def get_out_of_lock(self):
  345. block = self.bus_pi.read_i2c_block_data(self._addr,141,2)
  346. buff = pack("2B",*block)
  347. dat = unpack("<H",buff)
  348. dat=np.uint16(dat)
  349. return dat[0]
  350. # Debugging
  351. def read_all_param(self):
  352. print( "start = %d" %self.get_start())
  353. print( "stop = %d" %self.get_stop())
  354. print( "Vset = %d" %self.get_Vset())
  355. print( "wf_len = %d" %self.get_wf_len())
  356. print ("step = %d" %self.get_step())
  357. print( "N = %d" %self.get_N())
  358. print( "Channel = %d" %self.get_channel())
  359. print( "ID = %d" %self.get_ID())
  360. '''def set_test_all_param(self):
  361. self.set_start(0)
  362. self.set_stop(10)
  363. self.set_Vset(20)
  364. self.set_wf_len(30)
  365. self.set_step(40)
  366. self.set_N(60)'''