1
0

ADUCv2p1.py 14 KB

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