CocoPi.py 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564
  1. '''
  2. =========================================================
  3. ______ ______
  4. /\ _ \ /\ _ \ __
  5. \ \ \/\_\ ____ ____ ___\ \ \_\ \/\_\
  6. \ \ \/_/_ / __ \ / __ \ / __'\ \ __/\/_/_
  7. \ \ \_\ \/\ \_\ \/\ \__//\ \_\ \ \ \/ /\ \
  8. \ \____/\ \____/\ \____\ \____/\ \_\ \ \_\
  9. \/___/ \/___/ \/____/\/___/ \/_/ \/_/
  10. __
  11. /\ \ __ ----------------
  12. \ \ \ /\_\ ____ __ __ __ _ pi.cocorobo.cn
  13. \ \ \ \/_/_ / _ \/\ \/\ \/\ \/ \ ----------------
  14. \ \ \____ /\ \/\ \/\ \ \ \_\ \/> </ SYSTEM VERSION
  15. \ \_____\\ \_\ \_\ \_\ \____//\_/\_\ -- 24.07.05 ---
  16. \/_____/ \/_/\/_/\/_/\/___/ \//\/_/ ----------------
  17. =========================================================
  18. '''
  19. #########################################################
  20. # ------------------------------------------------------
  21. #| 封装包内容: | 类名称: |
  22. #|-------------------------------|----------------------|
  23. #| 2023.02.16: | |
  24. #| 【添加】 | |
  25. #| 1、AHT20温湿度传感器 | AHT20 |
  26. #| 2、MPU6050陀螺仪六轴传感器 | MPU6050 |
  27. #| 3、板载4颗按钮A、B、C、D | BUTTON |
  28. #| 4、光线强度传感器 | LIGHTINTENSITY |
  29. #| 5、板载LED灯! | LED |
  30. #| 6、直流电机 | DCMOTOR |
  31. #| 7、模拟舵机 | SERVO |
  32. #|------------------------------------------------------|
  33. #| 2023.02.27: | |
  34. #| 【修复完善】 | BUTTON、LED |
  35. #| 【添加】 | WIFI |
  36. #|------------------------------------------------------|
  37. #| 2023.03.09: | |
  38. #| 【修复完善】 | LED |
  39. #|------------------------------------------------------|
  40. #| 2023.03.14: | |
  41. #| 【修复完善】 | SERVO |
  42. #|-------------------------------------------------------
  43. #| 2023.06.01: | |
  44. #| 【替换】 | BUTTON |
  45. #| 【替换】 | LED |
  46. #| 【替换】 | DCMOTOR |
  47. #| 【替换】 | SERVO |
  48. #| 【添加】 | RGB |
  49. #| 【添加】 | ADC |
  50. #| 【添加】 | DAC |
  51. #| 【添加】 | INPUT |
  52. #| 【添加】 | OUT |
  53. #| 【添加】 | UvcVideo |
  54. #|-------------------------------------------------------
  55. #| 2023.06.15: | |
  56. #| 【更改】 | STM8S |
  57. #|-------------------------------------------------------
  58. #| 2023.08.17: | |
  59. #| 【更改】 | DCMOTOR |
  60. #|-------------------------------------------------------
  61. #| 2023.08.25: | |
  62. #| 【更改】 | BUZZER |
  63. #|-------------------------------------------------------
  64. #| 2023.09.28: | |
  65. #| 【更改】 | QMI8658 |
  66. #########################################################
  67. #|-------------------------------------------------------
  68. #| 2024.02.22: | |
  69. #| 【更改】 | QMI8658 |
  70. #########################################################
  71. #| 2024.02.28: | |
  72. #| 【更改】 | STM8S |
  73. #########################################################
  74. #| 2024.03.07: | |
  75. #| 【添加】 | GPTrequest |
  76. #########################################################
  77. #| 2024.03.11: | |
  78. #| 【修改】 | LED |
  79. #| 【修改】 | DCMOTOR |
  80. #########################################################
  81. #| 2024.03.22: | |
  82. #| 【增加】 | RTC |
  83. #| 【增加】 | PCA9685 |
  84. #########################################################
  85. #| 2024.04.10: | |
  86. #| 【修改】 | GPTrequest |
  87. #########################################################
  88. #| 2024.07.05: | |
  89. #| 【增加】 | LazyImport |
  90. #| 【针对】 | GPTrequest |
  91. #| 【针对】 | uuid |
  92. #| 【针对】 | json |
  93. #| 【针对】 | base64 |
  94. #| 【修改】 | STM8S |
  95. #| 【修改】 | DCMOTOR |
  96. #| 【修改】 | multiFuncGpio |
  97. #| 【增加】 | DS3231 |
  98. #| 【增加】 | SPI_WS2812 |
  99. #| 【增加】 | HCSR04 |
  100. #| 【增加】 | extDcMotor |
  101. #| 【增加】 | extServo |
  102. #| 【增加】 | extGpio |
  103. #| 【拆分】 | GPTrequest |
  104. #########################################################
  105. from smbus2 import SMBus, i2c_msg
  106. import time
  107. import math
  108. import os
  109. import sys
  110. import struct
  111. from math import floor
  112. # ============================================================
  113. # 【关键修复】全局唯一的 SMBus 实例
  114. # 三个类 PCA9685 / MCP23017 / ADS1115 共用同一个总线对象,
  115. # 避免多个 SMBus(2) 同时打开 /dev/i2c-2 引起的 Errno 70 (ECOMM)
  116. # ============================================================
  117. _BUS = SMBus(2)
  118. def _bus_write_byte(addr, reg, val, retries=3, delay=0.005):
  119. for _ in range(retries):
  120. try:
  121. _BUS.write_byte_data(addr, reg, val)
  122. return True
  123. except OSError:
  124. time.sleep(delay)
  125. except Exception:
  126. time.sleep(delay)
  127. return False
  128. def _bus_read_byte(addr, reg, retries=3, delay=0.005):
  129. for _ in range(retries):
  130. try:
  131. return _BUS.read_byte_data(addr, reg)
  132. except OSError:
  133. time.sleep(delay)
  134. except Exception:
  135. time.sleep(delay)
  136. return None
  137. def _bus_read_block(addr, reg, length, retries=3, delay=0.005):
  138. for _ in range(retries):
  139. try:
  140. return _BUS.read_i2c_block_data(addr, reg, length)
  141. except OSError:
  142. time.sleep(delay)
  143. except Exception:
  144. time.sleep(delay)
  145. return None
  146. try:
  147. from maix import gpio
  148. except Exception:
  149. gpio = None
  150. try:
  151. import SUNXI_GPIO
  152. except Exception:
  153. SUNXI_GPIO = None
  154. try:
  155. from maix import camera
  156. except Exception:
  157. camera = None
  158. try:
  159. from maix import spi as _maix_spi
  160. except Exception:
  161. _maix_spi = None
  162. sys.path.append('/root/preset/server')
  163. import threading # noqa
  164. ##################################
  165. # 1、AHT20温湿度传感器 #
  166. ##################################
  167. AHT20_I2CADDR = 0x38
  168. AHT20_CMD_SOFTRESET = [0xBA]
  169. AHT20_CMD_INITIALIZE = [0xBE, 0x08, 0x00]
  170. AHT20_CMD_MEASURE = [0xAC, 0x33, 0x00]
  171. AHT20_STATUSBIT_BUSY = 7
  172. AHT20_STATUSBIT_CALIBRATED = 3
  173. class AHT20:
  174. def __init__(self, bus_num=2):
  175. self.bus_num = bus_num
  176. self.bus = _BUS
  177. def _initialize_sensor(self):
  178. self._write_command([0xBA])
  179. time.sleep(0.04)
  180. self._write_command([0xBE, 0x08, 0x00])
  181. time.sleep(0.01)
  182. while not self._is_calibrated():
  183. time.sleep(0.01)
  184. def _write_command(self, command):
  185. msg = i2c_msg.write(0x38, command)
  186. self.bus.i2c_rdwr(msg)
  187. def _read_data(self, length):
  188. msg = i2c_msg.read(0x38, length)
  189. self.bus.i2c_rdwr(msg)
  190. return list(msg)
  191. def _is_calibrated(self):
  192. status = self._read_data(1)[0]
  193. return (status >> 3) & 1
  194. def _trigger_measurement(self):
  195. self._write_command([0xAC, 0x33, 0x00])
  196. start_time = time.time()
  197. time.sleep(85 * 10 ** -3)
  198. while True:
  199. data = self._read_data(7)
  200. if not (data[0] >> 7) & 1:
  201. return data
  202. if time.time() - start_time > 0.08:
  203. raise TimeoutError("AHT20 measurement timeout")
  204. time.sleep(0.01)
  205. def _crc8(self, data):
  206. crc = 0xFF
  207. for byte in data:
  208. crc ^= byte
  209. for _ in range(8):
  210. if crc & 0x80:
  211. crc = (crc << 1) ^ 0x31
  212. else:
  213. crc <<= 1
  214. crc &= 0xFF
  215. return crc
  216. def read_raw_data(self):
  217. data = self._trigger_measurement()
  218. crc = self._crc8(data[:6])
  219. if crc != data[6]:
  220. raise ValueError("CRC check failed")
  221. return data
  222. def get_humidity(self):
  223. data = self.read_raw_data()
  224. raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4
  225. return (raw_humidity * 100.0) / (2 ** 20)
  226. def get_temperature(self):
  227. data = self.read_raw_data()
  228. raw_temp = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]
  229. return (raw_temp * 200.0) / (2 ** 20) - 50.0
  230. ##################################
  231. # 2、MPU6050陀螺仪六轴传感器 #
  232. ##################################
  233. SLAVE_ADDR = 0x68
  234. PWR_MGMT_1 = 0x6B
  235. PWR_MGMT_2 = 0x6C
  236. WHO_AM_I = 0x75
  237. GYRO_X = 0x43
  238. GYRO_Y = 0x45
  239. GYRO_Z = 0x47
  240. ACCL_X = 0x3B
  241. ACCL_Y = 0x3D
  242. ACCL_Z = 0x3F
  243. class MPU6050:
  244. def __init__(self, BusNum=2):
  245. self.BusNum = BusNum
  246. self.cmd_soft_reset()
  247. def cmd_soft_reset(self):
  248. _BUS.write_byte_data(SLAVE_ADDR, PWR_MGMT_1, 0)
  249. time.sleep(0.04)
  250. def read_byte(self, addr):
  251. return _BUS.read_byte_data(SLAVE_ADDR, addr)
  252. def read_word(self, addr):
  253. h = _BUS.read_byte_data(SLAVE_ADDR, addr)
  254. l = _BUS.read_byte_data(SLAVE_ADDR, addr + 1)
  255. return (h << 8) + l
  256. def read_word_i2c(self, addr):
  257. val = self.read_word(addr)
  258. if val >= 0x8000:
  259. return -((65535 - val) + 1)
  260. return val
  261. def dist(self, x, y):
  262. return math.sqrt((x * x) + (y * y))
  263. def get_x_rotat(self, x, y, z):
  264. rad = math.atan2(y, self.dist(x, z))
  265. return math.degrees(rad)
  266. def get_y_rotat(self, x, y, z):
  267. rad = math.atan2(x, self.dist(y, z))
  268. return -math.degrees(rad)
  269. def read_gyro(self):
  270. GYR_X = self.read_word_i2c(GYRO_X)
  271. GYR_Y = self.read_word_i2c(GYRO_Y)
  272. GYR_Z = self.read_word_i2c(GYRO_Z)
  273. return (GYR_X / 131), (GYR_Y / 131), (GYR_Z / 131)
  274. def read_acc(self):
  275. ACC_X = self.read_word_i2c(ACCL_X)
  276. ACC_Y = self.read_word_i2c(ACCL_Y)
  277. ACC_Z = self.read_word_i2c(ACCL_Z)
  278. CALC_ACC_X = ACC_X / 16384.0
  279. CALC_ACC_Y = ACC_Y / 16384.0
  280. CALC_ACC_Z = ACC_Z / 16384.0
  281. return (CALC_ACC_X, CALC_ACC_Y, CALC_ACC_Z,
  282. self.get_x_rotat(CALC_ACC_X, CALC_ACC_Y, CALC_ACC_Z),
  283. self.get_y_rotat(CALC_ACC_X, CALC_ACC_Y, CALC_ACC_Z))
  284. def get_gyro_x(self):
  285. return self.read_gyro()[0]
  286. def get_gyro_y(self):
  287. return self.read_gyro()[1]
  288. def get_gyro_z(self):
  289. return self.read_gyro()[2]
  290. def get_acc_x(self):
  291. return self.read_acc()[0]
  292. def get_acc_y(self):
  293. return self.read_acc()[1]
  294. def get_acc_z(self):
  295. return self.read_acc()[2]
  296. def get_angle_x(self):
  297. return self.read_acc()[3]
  298. def get_angle_y(self):
  299. return self.read_acc()[4]
  300. ##################################
  301. # 3、板载4颗按钮A、B、C、D #
  302. ##################################
  303. class BUTTON:
  304. def __init__(self, gpioId):
  305. self.gpio = 224 + gpioId
  306. SUNXI_GPIO.setcfg(self.gpio, SUNXI_GPIO.IN)
  307. def is_pressed(self):
  308. self.getValue = SUNXI_GPIO.input(self.gpio)
  309. return self.getValue != 1
  310. ##################################
  311. # 4、光线强度传感器 #
  312. ##################################
  313. class LIGHTINTENSITY:
  314. def __init__(self, addr=b"0x05070080") -> None:
  315. self.addr = addr
  316. self.path = "/sys/class/sunxi_dump/dump"
  317. self.file = open(self.path, "wb+")
  318. self.last = self.value()
  319. def value(self):
  320. self.file.write(b"0x05070080")
  321. self.file.seek(0)
  322. return int(self.file.read()[:-1], 16)
  323. def __del__(self):
  324. try:
  325. if self.file:
  326. self.file.close()
  327. del self.file
  328. except Exception:
  329. pass
  330. ##################################
  331. # 5、板载LED灯 #
  332. ##################################
  333. class LED:
  334. def __init__(self, gpioId=69):
  335. self.gpioId = gpioId
  336. SUNXI_GPIO.setcfg(self.gpioId, SUNXI_GPIO.OUT)
  337. SUNXI_GPIO.setcfg(259, SUNXI_GPIO.OUT)
  338. def out(self, value):
  339. if value == 0 or value == 1:
  340. self.value = 1 - value
  341. else:
  342. self.value = 0
  343. SUNXI_GPIO.output(self.gpioId, self.value)
  344. SUNXI_GPIO.output(259, self.value)
  345. ##################################
  346. # 6、QMI8658 #
  347. ##################################
  348. class QMI8658(object):
  349. def __init__(self, smbus=2, address=0X6B):
  350. self._address = address
  351. self._bus = _BUS
  352. bRet = self.WhoAmI()
  353. if bRet:
  354. self.Read_Revision()
  355. else:
  356. return None
  357. self.Config_apply()
  358. def _read_byte(self, cmd):
  359. rec = self._bus.read_i2c_block_data(int(self._address), int(cmd), 1)
  360. return rec[0]
  361. def _read_block(self, reg, length=1):
  362. rec = self._bus.read_i2c_block_data(int(self._address), int(reg), length)
  363. return rec
  364. def _read_u16(self, cmd):
  365. LSB = self._bus.read_i2c_block_data(int(self._address), int(cmd), 1)
  366. MSB = self._bus.read_i2c_block_data(int(self._address), int(cmd) + 1, 1)
  367. return (MSB[0] << 8) + LSB[0]
  368. def _write_byte(self, cmd, val):
  369. self._bus.write_i2c_block_data(int(self._address), int(cmd), bytes([int(val)]))
  370. def WhoAmI(self):
  371. return (0x05) == self._read_byte(0x00)
  372. def Read_Revision(self):
  373. return self._read_byte(0x01)
  374. def Config_apply(self):
  375. self._write_byte(0x02, 0x40)
  376. self._write_byte(0x08, 0x03)
  377. self._write_byte(0x03, 0x04)
  378. self._write_byte(0x04, 0x64)
  379. self._write_byte(0x06, 0x11)
  380. def Read_Raw_XYZ(self):
  381. xyz = [0, 0, 0, 0, 0, 0]
  382. vals = {}
  383. raw_timestamp = self._read_block(0x30, 3)
  384. raw_acc_xyz = self._read_block(0x35, 6)
  385. raw_gyro_xyz = self._read_block(0x3b, 6)
  386. raw_xyz = self._read_block(0x35, 12)
  387. timestamp = (raw_timestamp[2] << 16) | (raw_timestamp[1] << 8) | (raw_timestamp[0])
  388. for i in range(6):
  389. xyz[i] = (raw_xyz[(i * 2) + 1] << 8) | (raw_xyz[i * 2])
  390. if xyz[i] >= 32767:
  391. xyz[i] = xyz[i] - 65535
  392. vals["AcX"] = xyz[0]
  393. vals["AcY"] = xyz[1]
  394. vals["AcZ"] = xyz[2]
  395. vals["GyX"] = xyz[3]
  396. vals["GyY"] = xyz[4]
  397. vals["GyZ"] = xyz[5]
  398. return vals
  399. def Read_XYZ(self):
  400. xyz = [0, 0, 0, 0, 0, 0]
  401. raw_xyz = self.Read_Raw_XYZ()
  402. acc_lsb_div = (1 << 12)
  403. gyro_lsb_div = 64
  404. for i in range(3):
  405. xyz[i] = raw_xyz[i] / acc_lsb_div
  406. xyz[i + 3] = raw_xyz[i + 3] * 1.0 / gyro_lsb_div
  407. return xyz
  408. def get_accel(self, samples=10, calibration=None):
  409. result = {}
  410. for _ in range(samples):
  411. v = self.Read_Raw_XYZ()
  412. for m in v.keys():
  413. result[m] = result.get(m, 0) + v[m] / samples
  414. if calibration:
  415. for m in calibration.keys():
  416. if m == "AcZ":
  417. pass
  418. else:
  419. result[m] -= calibration[m]
  420. return result
  421. def calibrate(self, threshold=50):
  422. print('Calibrating QMI8658... ', end='')
  423. while True:
  424. v1 = self.get_accel(100)
  425. v2 = self.get_accel(100)
  426. if all(abs(v1[m] - v2[m]) < threshold for m in v1.keys()):
  427. print('Done.')
  428. return v1
  429. def getPitchYawRollGxGyGz(self, calibration):
  430. caliData = self.get_accel(10, calibration)
  431. pitch = caliData["AcX"] / 182.04
  432. yaw = caliData["AcY"] / 182.04
  433. roll = caliData["AcZ"] / 182.04
  434. groX = caliData["GyX"]
  435. groY = caliData["GyY"]
  436. groZ = caliData["GyZ"]
  437. if roll < 0:
  438. if pitch >= 0:
  439. pitch = 180 - pitch
  440. elif pitch < 0:
  441. pitch = (180 + pitch) * (-1)
  442. if yaw >= 0:
  443. yaw = 180 - yaw
  444. elif pitch < 0:
  445. yaw = (180 + yaw) * (-1)
  446. return [pitch, yaw, roll, groX, groY, groZ]
  447. ##################################
  448. # 7、STM8S #
  449. ##################################
  450. class stm8s(object):
  451. address = 0x50
  452. def __init__(self):
  453. self.bus = _BUS
  454. self.reset()
  455. time.sleep(0.05)
  456. def clear(self):
  457. self.write(1, 1)
  458. self.reset()
  459. time.sleep(0.05)
  460. def write(self, addr, val):
  461. return _bus_write_byte(self.address, addr, val)
  462. def fastWrite(self, addr, valBlock):
  463. try:
  464. self.bus.write_i2c_block_data(self.address, addr, valBlock)
  465. return True
  466. except Exception:
  467. return False
  468. def read(self, addr):
  469. return _bus_read_byte(self.address, addr)
  470. def reset(self):
  471. self.write(0, 1)
  472. time.sleep(0.05)
  473. def dump(self):
  474. for i in range(0, 32):
  475. print(i, self.read(i))
  476. class singleRgb(stm8s):
  477. def __init__(self):
  478. super().__init__()
  479. self.valR = 0
  480. self.valG = 0
  481. self.valB = 0
  482. self.brightness = 255
  483. self.show()
  484. def setColor(self, r, g, b):
  485. self.valR = int(r * self.brightness / 255) if 0 <= r <= 255 else 0
  486. self.valG = int(g * self.brightness / 255) if 0 <= g <= 255 else 0
  487. self.valB = int(b * self.brightness / 255) if 0 <= b <= 255 else 0
  488. def setBrightness(self, brightness):
  489. self.brightness = brightness if 0 <= brightness <= 255 else 0
  490. def show(self):
  491. self.write(31, self.valB)
  492. self.write(30, self.valG)
  493. self.write(29, self.valR)
  494. self.write(28, 6)
  495. class dcMotor(stm8s):
  496. def __init__(self, id):
  497. super().__init__()
  498. self.id = id
  499. def m1a(self, val=0):
  500. self.write(4, 5); self.write(7, val)
  501. def m1b(self, val=0):
  502. self.write(8, 5); self.write(11, val)
  503. def m2a(self, val=0):
  504. self.write(12, 5); self.write(15, val)
  505. def m2b(self, val=0):
  506. self.write(16, 5); self.write(19, val)
  507. def dcMotorCtrl(self, dir, speed):
  508. dir = 1 - dir
  509. if 0 < speed < 255:
  510. if self.id == 1:
  511. if dir == 0:
  512. self.m1a(speed); self.m1b(255)
  513. else:
  514. self.m1a(255); self.m1b(speed)
  515. elif self.id == 2:
  516. if dir == 0:
  517. self.m2a(speed); self.m2b(255)
  518. else:
  519. self.m2a(255); self.m2b(speed)
  520. elif speed == 0:
  521. if self.id == 1:
  522. self.m1a(255); self.m1b(255)
  523. elif self.id == 2:
  524. self.m2a(255); self.m2b(255)
  525. elif speed == 255:
  526. if self.id == 1:
  527. if dir == 0:
  528. self.m1a(0); self.m1b(255)
  529. else:
  530. self.m1a(255); self.m1b(0)
  531. elif self.id == 2:
  532. if dir == 0:
  533. self.m2a(0); self.m2b(255)
  534. else:
  535. self.m2a(255); self.m2b(0)
  536. class multiFuncGpio(stm8s):
  537. def __init__(self, id=0, mode=0):
  538. super().__init__()
  539. self.id = id
  540. self.rgbId = 0
  541. self.brightness = 255
  542. self.mode = mode
  543. self.write(20 + self.id * 4, self.mode)
  544. self.rgbSerial = [0, 0, 0] * 16
  545. time.sleep(0.05)
  546. def servoCtrl(self, angle):
  547. if 0 <= angle <= 180:
  548. self.write(23 + self.id * 4, angle)
  549. def digitalRead(self):
  550. try:
  551. self.gpioVal = self.read(23 + self.id * 4)
  552. if self.gpioVal is not None:
  553. return self.gpioVal
  554. except Exception:
  555. print("ERROR 233")
  556. def digitalWrite(self, val):
  557. if 0 <= val <= 1:
  558. self.write(23 + self.id * 4, val)
  559. def analogRead(self):
  560. try:
  561. self.adcValH = self.read(22 + self.id * 4)
  562. self.adcValL = self.read(23 + self.id * 4)
  563. if self.adcValH is not None and self.adcValL is not None:
  564. self.adcVal = self.adcValL + (self.adcValH << 8)
  565. return self.adcVal
  566. except Exception:
  567. print("ERROR 2333")
  568. def analogWrite(self, val):
  569. if 0 <= val <= 255:
  570. self.write(23 + self.id * 4, val)
  571. def beep(self, frequency):
  572. if 20 <= frequency <= 12000:
  573. self.write(22 + self.id * 4, frequency >> 8)
  574. self.write(23 + self.id * 4, frequency & 0b11111111)
  575. def pixelInit_(self):
  576. for i in range(16):
  577. self.setPixelColor(i, 0, 0, 0)
  578. self.pixelShow()
  579. self.write(23 + self.id * 4, 1)
  580. def setBrightness(self, brightness):
  581. self.brightness = brightness if 0 <= brightness <= 255 else 0
  582. def setPixelColor(self, rgbId, r, g, b):
  583. self.setRgbSerialColor(rgbId, r, g, b)
  584. def pixelShow(self):
  585. for i in range(16):
  586. self.write(32 + self.id * 48 + i * 3, self.rgbSerial[i * 3])
  587. self.write(33 + self.id * 48 + i * 3, self.rgbSerial[i * 3 + 1])
  588. self.write(34 + self.id * 48 + i * 3, self.rgbSerial[i * 3 + 2])
  589. self.write(23 + self.id * 4, 1)
  590. def setRgbSerialColor(self, rgbId, r, g, b):
  591. self.rgbId = rgbId if 0 <= rgbId <= 15 else 0
  592. self.valR = int(r * self.brightness / 255) if 0 <= r <= 255 else 0
  593. self.valG = int(g * self.brightness / 255) if 0 <= g <= 255 else 0
  594. self.valB = int(b * self.brightness / 255) if 0 <= b <= 255 else 0
  595. self.rgbSerial[self.rgbId * 3] = self.valR
  596. self.rgbSerial[self.rgbId * 3 + 1] = self.valG
  597. self.rgbSerial[self.rgbId * 3 + 2] = self.valB
  598. def rgbSerialShow(self):
  599. self.pixelShow()
  600. ##################################
  601. # 8、UvcVideo #
  602. ##################################
  603. if camera is not None:
  604. class UvcVideo(camera.MaixVideo):
  605. def __init__(self, source="/dev/videoX"):
  606. self.source = source
  607. super(UvcVideo, self).__init__()
  608. usb_path = '/sys/devices/platform/soc/usbc0/otg_role'
  609. if os.popen('cat %s' % usb_path).read().strip() != 'usb_host':
  610. os.system('echo "usb_host" > %s' % usb_path)
  611. time.sleep(2)
  612. def config(self, size=None, video=2, horizontal=0, vertical=0):
  613. if size is None:
  614. size = (320, 240)
  615. super(UvcVideo, self).config(size)
  616. print('[camera] config input size(%d, %d, %d)' %
  617. (self.width(), self.height(), video))
  618. if self.cam:
  619. self.cam = None
  620. try:
  621. import _coco_camera
  622. self.cam = _coco_camera.Camera(self.width(), self.height(),
  623. video, horizontal, vertical)
  624. except Exception as e:
  625. print(e)
  626. self.cam = None
  627. def read(self):
  628. if self.cam is None:
  629. self.config()
  630. if self.cam:
  631. ret, frame = self.cam.read()
  632. if ret:
  633. return frame
  634. else:
  635. try:
  636. self.config()
  637. except Exception as e:
  638. print(e)
  639. return None
  640. def __del__(self):
  641. if self.cam:
  642. self.cam = None
  643. else:
  644. class UvcVideo(object):
  645. def __init__(self, *args, **kwargs):
  646. raise RuntimeError("maix.camera not available")
  647. ##################################
  648. # 9、DS3231 #
  649. ##################################
  650. class DS3231(object):
  651. def __init__(self):
  652. self.bus = _BUS
  653. self.address = 0x68
  654. def bcd_to_int(self, bcd, n=2):
  655. return int(('%x' % bcd)[-n:])
  656. def int_to_bcd(self, x, n=2):
  657. return int(str(x)[-n:], 0x10)
  658. def read(self, addr):
  659. return _bus_read_byte(self.address, addr)
  660. def write(self, addr, val):
  661. return _bus_write_byte(self.address, addr, val)
  662. def setYear(self, year):
  663. self.write(0x06, self.int_to_bcd(year % 100))
  664. def setMonth(self, month):
  665. if not 1 <= month <= 12:
  666. raise ValueError('Month is out of range [1,12].')
  667. self.write(0x05, self.int_to_bcd(month))
  668. def setDay(self, day):
  669. if not 1 <= day <= 31:
  670. raise ValueError('Day is out of range [1,31].')
  671. self.write(0x04, self.int_to_bcd(day))
  672. def setDayOfWeek(self, dayOfWeek):
  673. if not 1 <= dayOfWeek <= 7:
  674. raise ValueError('Day of week is out of range [1,7].')
  675. self.write(0x03, self.int_to_bcd(dayOfWeek))
  676. def setHour(self, hour):
  677. if not 0 <= hour < 24:
  678. raise ValueError('Hours is out of range [0,23].')
  679. self.write(0x02, self.int_to_bcd(hour) & 0x3F)
  680. def setMinutes(self, minutes):
  681. if not 0 <= minutes < 59:
  682. raise ValueError('Minutes is out of range [0,59].')
  683. self.write(0x01, self.int_to_bcd(minutes))
  684. def setSeconds(self, seconds):
  685. if not 0 <= seconds < 60:
  686. raise ValueError('Seconds is out of range [0,59].')
  687. self.write(0x00, self.int_to_bcd(seconds))
  688. def setDateTime(self, year, month, day, dayOfWeek, hour, minutes, seconds):
  689. self.setYear(year)
  690. self.setMonth(month)
  691. self.setDay(day)
  692. self.setDayOfWeek(dayOfWeek)
  693. self.setHour(hour)
  694. self.setMinutes(minutes)
  695. self.setSeconds(seconds)
  696. def getYear(self):
  697. return self.bcd_to_int(self.read(0x06))
  698. def getMonth(self):
  699. temp = self.read(0x05)
  700. return self.bcd_to_int((temp << 4 >> 4) & 0x7F)
  701. def getDay(self):
  702. return self.bcd_to_int(self.read(0x04))
  703. def getDayOfWeek(self):
  704. return self.bcd_to_int(self.read(0x03))
  705. def getHour(self):
  706. temp = self.read(0x02)
  707. if temp == 0x64:
  708. temp = 0x40
  709. return self.bcd_to_int((temp << 4 >> 4) & 0x3F)
  710. def getMinutes(self):
  711. return self.bcd_to_int(self.read(0x01))
  712. def getSeconds(self):
  713. return self.bcd_to_int(self.read(0x00))
  714. def getDateTime(self):
  715. return [self.getYear(), self.getMonth(), self.getDay(),
  716. self.getDayOfWeek(), self.getHour(),
  717. self.getMinutes(), self.getSeconds()]
  718. def convertToByteType(self, number):
  719. return bytes([number])
  720. def decodeToDec(self, byte):
  721. return ((byte[0] >> 4) * 10) + (byte[0] & 0x0F)
  722. def encodeToByte(self, dec):
  723. tens = floor(dec / 10)
  724. ones = dec - tens * 10
  725. return (tens << 4) + ones
  726. def decodeAlarmType(self, alarmTime):
  727. if len(alarmTime) > 4:
  728. m1Bit = (alarmTime[3] & 0x80) >> 7
  729. else:
  730. m1Bit = False
  731. m2Bit = (alarmTime[2] & 0x80) >> 7
  732. m3Bit = (alarmTime[1] & 0x80) >> 7
  733. m4Bit = (alarmTime[0] & 0x80) >> 7
  734. dayBit = (alarmTime[0] & 0x40) >> 6
  735. if m1Bit and m2Bit and m3Bit and m4Bit:
  736. return "everySecond"
  737. elif not m1Bit and m2Bit and m3Bit and m4Bit:
  738. return "everyMinute"
  739. elif not m1Bit and not m2Bit and m3Bit and m4Bit:
  740. return "everyHour"
  741. elif not m1Bit and not m2Bit and not m3Bit and m4Bit:
  742. return "everyDay"
  743. elif not dayBit and not m1Bit and not m2Bit and not m3Bit and not m4Bit:
  744. return "everyMonth"
  745. elif dayBit and not m1Bit and not m2Bit and not m3Bit and not m4Bit:
  746. return "everyWeek"
  747. else:
  748. return "noValidAlarmType"
  749. def decodeAlarmTime(self, alarmTime):
  750. alarmTime[0] = self.decodeToDec(self.convertToByteType(alarmTime[0] & 0x3F))
  751. alarmTime[1] = self.decodeToDec(self.convertToByteType(alarmTime[1] & 0x3F))
  752. alarmTime[2] = self.decodeToDec(self.convertToByteType(alarmTime[2] & 0x7F))
  753. if len(alarmTime) > 4:
  754. alarmTime[3] = self.decodeToDec(self.convertToByteType(alarmTime[3] & 0x7F))
  755. return alarmTime
  756. def encodeAlarmType(self, alarmType):
  757. table = {
  758. "everySecond": 15, "everyMinute": 14, "everyHour": 12,
  759. "everyDay": 8, "everyMonth": 0, "everyWeek": 16,
  760. }
  761. if alarmType not in table:
  762. raise ValueError("Not a supported alarmType.")
  763. return table[alarmType]
  764. def encodeDateTime(self, day, hour, minutes, seconds, alarmType):
  765. alarmBits = self.encodeAlarmType(alarmType)
  766. alarmTime = [0, 0, 0, 0]
  767. alarmTime[0] = (self.encodeToByte(day) & 0x3F) | \
  768. ((alarmBits & 0x10) << 2) | ((alarmBits & 0x08) << 4)
  769. alarmTime[1] = (self.encodeToByte(hour) & 0x3F) | ((alarmBits & 0x04) << 5)
  770. alarmTime[2] = (self.encodeToByte(minutes) & 0x7F) | ((alarmBits & 0x02) << 6)
  771. alarmTime[3] = (self.encodeToByte(seconds) & 0x7F) | ((alarmBits & 0x01) << 7)
  772. return alarmTime
  773. ##################################
  774. # 10、SPI_WS2812 #
  775. ##################################
  776. class SPI_WS2812(object):
  777. def __init__(self, num):
  778. self.num = num
  779. if _maix_spi is not None:
  780. self.spi = _maix_spi.SpiDev()
  781. self.spi.open(0, 0)
  782. self.spi.mode = 3
  783. self.spi.bits_per_word = 8
  784. self.spi.max_speed_hz = 20000000
  785. else:
  786. self.spi = None
  787. self.data = [[0, 0, 0]] * self.num
  788. self.brightness = 255
  789. def setRgbColor(self, id, r, g, b):
  790. if id > (self.num - 1):
  791. raise ValueError("Out of range!")
  792. self.data[id] = [int(g * self.brightness / 255),
  793. int(r * self.brightness / 255),
  794. int(b * self.brightness / 255)]
  795. def setBrightness(self, brightness):
  796. if brightness > 255 or brightness < 0:
  797. raise ValueError("Out of range!")
  798. self.brightness = brightness
  799. def rgbShow(self):
  800. if self.spi is None:
  801. return
  802. tx = []
  803. for rgb in self.data:
  804. for byte in rgb:
  805. for ibit in range(3, -1, -1):
  806. tx.append(((byte >> (2 * ibit + 1)) & 1) * 0x60 +
  807. ((byte >> (2 * ibit + 0)) & 1) * 0x06 +
  808. 0x88)
  809. print([hex(v) for v in tx])
  810. tx[0] = 0b1000000
  811. tx.append(0b1000000)
  812. self.spi.xfer(tx, int(4 / 1.05e-6))
  813. def __del__(self):
  814. try:
  815. self.data = [[0, 0, 0]] * self.num
  816. self.rgbShow()
  817. except Exception:
  818. pass
  819. ##################################
  820. # 11、HCSR04 #
  821. ##################################
  822. class HCSR04:
  823. def __init__(self, Trig, Echo):
  824. pinNum = {"TXD": "198", "RXD": "199", "CLK": "224",
  825. "MOSI": "225", "MISO": "226", "CS": "227"}
  826. os.system("insmod /home/drivers/hcsr04.ko")
  827. pinCmd = pinNum.get(Trig) + "," + pinNum.get(Echo) + ",23200,0"
  828. os.system('echo "' + pinCmd + '" > /sys/class/hcsr04/value')
  829. def getDistance(self):
  830. startTime = round(time.time(), 3)
  831. while True:
  832. dis = os.popen("cat /sys/class/hcsr04/value").read()
  833. if "-1" in dis:
  834. pass
  835. else:
  836. dis = round(int(dis) / 58, 2)
  837. if dis < 250:
  838. return dis
  839. if (round(time.time(), 3) - startTime) >= 1.200:
  840. return -1
  841. def __del__(self):
  842. os.system("rmmod /home/drivers/hcsr04.ko")
  843. ##################################
  844. # 12、MCP23017 #
  845. ##################################
  846. class MCP23017(object):
  847. address = 0x20
  848. iodira = 0x00
  849. iodirb = 0x01
  850. gppua = 0x0c
  851. gppub = 0x0d
  852. gpioa = 0x12
  853. gpiob = 0x13
  854. DIR_A_V = 0xff
  855. DIR_B_V = 0xff
  856. GPPU_A_V = 0x00
  857. GPPU_B_V = 0x00
  858. GPIO_A_V = 0x00
  859. GPIO_B_V = 0x00
  860. def __init__(self):
  861. self.bus = _BUS
  862. self.reset()
  863. def reset(self):
  864. self.DIR_A = self.DIR_A_V
  865. self.DIR_B = self.DIR_B_V
  866. self.GPPU_A = self.GPPU_A_V
  867. self.GPPU_B = self.GPPU_B_V
  868. self.GPIO_A = self.GPIO_A_V
  869. self.GPIO_B = self.GPIO_B_V
  870. self.byteWrite(self.iodira, self.DIR_A_V)
  871. self.byteWrite(self.iodirb, self.DIR_B_V)
  872. self.byteWrite(self.gppua, self.GPPU_A_V)
  873. self.byteWrite(self.gppub, self.GPPU_B_V)
  874. self.byteWrite(self.gpioa, self.GPIO_A_V)
  875. self.byteWrite(self.gpiob, self.GPIO_B_V)
  876. print("mcp23017 reset completed!")
  877. def byteWrite(self, addr, val):
  878. return _bus_write_byte(self.address, addr, val)
  879. def byteRead(self, addr):
  880. return _bus_read_byte(self.address, addr)
  881. def bitWrite(self, reg, num, val):
  882. return ((reg >> (num + 1) << (num + 1))
  883. | (val << num)
  884. | (reg << (8 - num) & 0xFF) >> (8 - num))
  885. def bitRead(self, reg, num):
  886. return ((reg << (7 - num) & 0xFF) >> 7)
  887. def setGpioDir(self, channel, pinId, direction):
  888. if channel == "A":
  889. self.DIR_A = self.bitWrite(self.DIR_A, pinId, direction)
  890. self.byteWrite(self.iodira, self.DIR_A)
  891. elif channel == "B":
  892. self.DIR_B = self.bitWrite(self.DIR_B, pinId, direction)
  893. self.byteWrite(self.iodirb, self.DIR_B)
  894. else:
  895. raise ValueError("Error Channel!")
  896. def setGppuEnable(self, channel, pinId, pullup):
  897. if channel == "A":
  898. self.GPPU_A = self.bitWrite(self.GPPU_A, pinId, pullup)
  899. self.byteWrite(self.gppua, self.GPPU_A)
  900. elif channel == "B":
  901. self.GPPU_B = self.bitWrite(self.GPPU_B, pinId, pullup)
  902. self.byteWrite(self.gppub, self.GPPU_B)
  903. else:
  904. raise ValueError("Error Channel!")
  905. def setGpioLevel(self, channel, pinId, level):
  906. if channel == "A":
  907. self.GPIO_A = self.bitWrite(self.GPIO_A, pinId, level)
  908. self.byteWrite(self.gpioa, self.GPIO_A)
  909. elif channel == "B":
  910. self.GPIO_B = self.bitWrite(self.GPIO_B, pinId, level)
  911. self.byteWrite(self.gpiob, self.GPIO_B)
  912. else:
  913. raise ValueError("Error Channel!")
  914. def getGpioLevel(self, channel, pinId):
  915. if channel == "A":
  916. v = self.byteRead(self.gpioa)
  917. elif channel == "B":
  918. v = self.byteRead(self.gpiob)
  919. else:
  920. raise ValueError("Error Channel!")
  921. return None if v is None else self.bitRead(v, pinId)
  922. def __del__(self):
  923. try:
  924. self.reset()
  925. time.sleep(0.001)
  926. except Exception:
  927. pass
  928. print("del mcp23017")
  929. ##################################
  930. # 13、ADS1115 #
  931. ##################################
  932. class ADS1115(object):
  933. DEVICE_REG_CONVERSION = 0x00
  934. DEVICE_REG_CONFIG = 0x01
  935. DEVICE_REG_LO_THRESH = 0x02
  936. DEVICE_REG_HI_THRESH = 0x03
  937. CONFIG_OS = 0x8000
  938. CONFIG_OS_START = 0x8000
  939. CONFIG_OS_PERFORMING_CONVERSION = 0x0000
  940. CONFIG_OS_NOT_PERFORMING_OPERATION = 0x8000
  941. CONFIG_MUX_AIN0P_AIN1N = 0x0000
  942. CONFIG_MUX_AIN1P_AIN3N = 0x1000
  943. CONFIG_MUX_AIN2P_AIN3N = 0x2000
  944. CONFIG_MUX_AIN3P_AIN3N = 0x3000
  945. CONFIG_MUX_AIN0P_GNDN = 0x4000
  946. CONFIG_MUX_AIN1P_GNDN = 0x5000
  947. CONFIG_MUX_AIN2P_GNDN = 0x6000
  948. CONFIG_MUX_AIN3P_GNDN = 0x7000
  949. CONFIG_FSR_6V144 = 0x0000
  950. CONFIG_FSR_4V096 = 0x0200
  951. CONFIG_FSR_2V048 = 0x0400
  952. CONFIG_FSR_1V024 = 0x0600
  953. CONFIG_FSR_0V512 = 0x0800
  954. CONFIG_FSR_0V256 = 0x0A00
  955. CONFIG_MODE_CONTINUOUS = 0x0000
  956. CONFIG_MODE_SINGLE_SHOT = 0x0100
  957. CONFIG_DATA_RATE_8SPS = 0x0000
  958. CONFIG_DATA_RATE_16SPS = 0x0020
  959. CONFIG_DATA_RATE_32SPS = 0x0040
  960. CONFIG_DATA_RATE_64SPS = 0x0060
  961. CONFIG_DATA_RATE_128SPS = 0x0080
  962. CONFIG_DATA_RATE_2508SPS = 0x00A0
  963. CONFIG_DATA_RATE_475SPS = 0x00C0
  964. CONFIG_DATA_RATE_860SPS = 0x00E0
  965. CONFIG_COMP_MODE_TRADITIONAL = 0x0000
  966. CONFIG_COMP_MODE_WINDOW = 0x0010
  967. CONFIG_COMP_POL_ACTIVE_LOW = 0x0000
  968. CONFIG_COMP_POL_ACTIVE_HIGH = 0x0008
  969. CONFIG_COMP_LAT = 0x0004
  970. CONFIG_COMP_LAT_NON_LATCHING = 0x0000
  971. CONFIG_COMP_LAT_LATCHING = 0x0004
  972. CONFIG_COMP_QUE = 0x0003
  973. CONFIG_COMP_QUE_1_CONV = 0x0000
  974. CONFIG_COMP_QUE_2_CONV = 0x0001
  975. CONFIG_COMP_QUE_4_CONV = 0x0002
  976. CONFIG_COMP_QUE_DISABLE = 0x0003
  977. addr = 0x49
  978. def __init__(self):
  979. self.bus = _BUS
  980. self.address = 0x49
  981. self.config = 0x0000
  982. def swap(self, val):
  983. return ((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)
  984. def readAdc(self, channel):
  985. if channel > 3 or channel < 0:
  986. return False
  987. self.config = (self.CONFIG_OS_START +
  988. ((channel + 4) << 12) +
  989. self.CONFIG_FSR_6V144 +
  990. self.CONFIG_MODE_SINGLE_SHOT +
  991. self.CONFIG_DATA_RATE_128SPS +
  992. self.CONFIG_COMP_MODE_TRADITIONAL +
  993. self.CONFIG_COMP_POL_ACTIVE_LOW +
  994. self.CONFIG_COMP_LAT_NON_LATCHING +
  995. self.CONFIG_COMP_QUE_DISABLE)
  996. # 写配置(带重试,原来这里就是 Errno 70 抛出的地方)
  997. ok = False
  998. for _ in range(3):
  999. try:
  1000. _BUS.write_word_data(self.address, self.DEVICE_REG_CONFIG,
  1001. self.swap(self.config))
  1002. ok = True
  1003. break
  1004. except OSError:
  1005. time.sleep(0.02)
  1006. except Exception:
  1007. time.sleep(0.02)
  1008. if not ok:
  1009. return None
  1010. deadline = time.time() + 0.5
  1011. while time.time() < deadline:
  1012. try:
  1013. status = self.swap(_BUS.read_word_data(
  1014. self.address, self.DEVICE_REG_CONFIG))
  1015. except OSError:
  1016. time.sleep(0.005)
  1017. continue
  1018. if (status & self.CONFIG_OS) != self.CONFIG_OS_PERFORMING_CONVERSION:
  1019. break
  1020. try:
  1021. result = self.swap(_BUS.read_word_data(
  1022. self.address, self.DEVICE_REG_CONVERSION))
  1023. except OSError:
  1024. return None
  1025. volt = round((result * 6.144 / 32768), 3)
  1026. return [result, volt]
  1027. ##################################
  1028. # 14、PCA9685 #
  1029. ##################################
  1030. class PCA9685(object):
  1031. def __init__(self, freq=400, min_us=460, max_us=2400,
  1032. address=0x40, degrees=180):
  1033. self.bus = _BUS
  1034. self.address = address
  1035. self.period = 1000000 / freq
  1036. self.min_duty = self._us2duty(min_us)
  1037. self.max_duty = self._us2duty(max_us)
  1038. self.freq(freq)
  1039. self.reset()
  1040. print("Pca9685 init")
  1041. def write(self, addr, val):
  1042. return _bus_write_byte(self.address, addr, val)
  1043. def read(self, addr):
  1044. return _bus_read_byte(self.address, addr)
  1045. def reset(self):
  1046. self.write(0x00, 0x00)
  1047. def freq(self, freq=None):
  1048. if freq is None:
  1049. v = self.read(0xfe)
  1050. if v is None:
  1051. return 400
  1052. return int(25000000.0 / 4096 / (v - 0.5))
  1053. prescale = int(25000000.0 / 4096 / freq + 0.5)
  1054. self.write(0x00, 0x10)
  1055. self.write(0xfe, prescale)
  1056. self.reset()
  1057. time.sleep(0.01)
  1058. self.write(0x00, 0xa1)
  1059. def pwm(self, index, on=None, off=None):
  1060. if not 0 <= index <= 15:
  1061. raise ValueError("Pin ID out of range!")
  1062. if on is None or off is None:
  1063. return _bus_read_block(self.address, 0x06 + index * 4, 4)
  1064. data = [0] * 4
  1065. data[0] = int(hex(on & 0xff), 16)
  1066. data[1] = int(hex((on >> 8) & 0xff), 16)
  1067. data[2] = int(hex(off & 0xff), 16)
  1068. data[3] = int(hex((off >> 8) & 0xff), 16)
  1069. for i in range(0, 4):
  1070. self.write(0x06 + i + index * 4, data[i])
  1071. def duty(self, index, value=None):
  1072. if value is None:
  1073. return self.pwm(index)
  1074. elif not 0 <= value <= 4095:
  1075. raise ValueError("Out of range!")
  1076. elif value == 0:
  1077. self.pwm(index, 0, 4096)
  1078. elif value == 4095:
  1079. self.pwm(index, 4096, 0)
  1080. else:
  1081. self.pwm(index, 0, value)
  1082. def _us2duty(self, value):
  1083. return 4095 * value / self.period
  1084. # 【关键修复】原来的 __del__ 会 for i in range(16): duty(i,0),
  1085. # 退出时会把 P0 舵机所在通道也清零,导致舵机被强行拉回 0°。
  1086. # 这里改成 pass,退出时不动任何通道。
  1087. def __del__(self):
  1088. pass
  1089. class extDcMotor(PCA9685):
  1090. def __init__(self, motorId):
  1091. PCA9685.__init__(self)
  1092. self.motorPin = [11, 12, 13, 10, 9, 8, 5, 6, 7, 4, 3, 2]
  1093. self.motorId = motorId
  1094. def speedControl(self, speed):
  1095. self.speed = abs(speed)
  1096. if not -255 <= speed <= 255:
  1097. raise ValueError("Out of range!")
  1098. if self.motorId == "C":
  1099. if speed < 0:
  1100. self.duty(self.motorPin[0], 4095)
  1101. self.duty(self.motorPin[1], 0)
  1102. self.duty(self.motorPin[2], int(self.speed * 16))
  1103. else:
  1104. self.duty(self.motorPin[0], 0)
  1105. self.duty(self.motorPin[1], 4095)
  1106. self.duty(self.motorPin[2], int(self.speed * 16))
  1107. elif self.motorId == "D":
  1108. if speed < 0:
  1109. self.duty(self.motorPin[3], 4095)
  1110. self.duty(self.motorPin[4], 0)
  1111. self.duty(self.motorPin[5], int(self.speed * 16))
  1112. else:
  1113. self.duty(self.motorPin[3], 0)
  1114. self.duty(self.motorPin[4], 4095)
  1115. self.duty(self.motorPin[5], int(self.speed * 16))
  1116. elif self.motorId == "E":
  1117. if speed < 0:
  1118. self.duty(self.motorPin[6], 4095)
  1119. self.duty(self.motorPin[7], 0)
  1120. self.duty(self.motorPin[8], int(self.speed * 16))
  1121. else:
  1122. self.duty(self.motorPin[6], 0)
  1123. self.duty(self.motorPin[7], 4095)
  1124. self.duty(self.motorPin[8], int(self.speed * 16))
  1125. elif self.motorId == "F":
  1126. if speed < 0:
  1127. self.duty(self.motorPin[9], 4095)
  1128. self.duty(self.motorPin[10], 0)
  1129. self.duty(self.motorPin[11], int(self.speed * 16))
  1130. else:
  1131. self.duty(self.motorPin[9], 0)
  1132. self.duty(self.motorPin[10], 4095)
  1133. self.duty(self.motorPin[11], int(self.speed * 16))
  1134. def __del__(self):
  1135. try:
  1136. if self.motorId == "C":
  1137. for i in range(3):
  1138. self.duty(self.motorPin[i], 0)
  1139. elif self.motorId == "D":
  1140. for i in range(3, 6):
  1141. self.duty(self.motorPin[i], 0)
  1142. elif self.motorId == "E":
  1143. for i in range(6, 9):
  1144. self.duty(self.motorPin[i], 0)
  1145. elif self.motorId == "F":
  1146. for i in range(9, 12):
  1147. self.duty(self.motorPin[i], 0)
  1148. except Exception:
  1149. pass
  1150. time.sleep(0.001)
  1151. class extServo(PCA9685):
  1152. def __init__(self, servoId):
  1153. PCA9685.__init__(self)
  1154. self.servoId = servoId
  1155. self.servoPin = [14, 15, 1, 0]
  1156. self.degrees = 180
  1157. def position(self, degrees=None):
  1158. if degrees is None:
  1159. return
  1160. if self.max_duty > 3800:
  1161. self.max_duty = 3800
  1162. span = self.max_duty - self.min_duty
  1163. duty = self.min_duty + span * degrees / self.degrees
  1164. duty = int(min(self.max_duty, max(self.min_duty, int(duty))))
  1165. self.duty(self.servoPin[self.servoId], duty)
  1166. def release(self):
  1167. self.duty(self.servoPin[self.servoId], 0)
  1168. def __del__(self):
  1169. try:
  1170. self.duty(self.servoPin[self.servoId], 0)
  1171. except Exception:
  1172. pass
  1173. class extOutputPin(PCA9685):
  1174. def __init__(self):
  1175. PCA9685.__init__(self)
  1176. self.pin = [14, 15, 1, 0]
  1177. self.pinId = 0
  1178. def digitalSet(self, pinId, val):
  1179. self.pinId = pinId
  1180. if val == 0:
  1181. self.duty(self.pin[self.pinId], 0)
  1182. else:
  1183. self.duty(self.pin[self.pinId], 4095)
  1184. def pwmWrite(self, pinId, val):
  1185. self.pinId = pinId
  1186. self.duty(self.pin[self.pinId], val * 16)
  1187. def __del__(self):
  1188. try:
  1189. self.duty(self.pin[self.pinId], 0)
  1190. except Exception:
  1191. pass
  1192. # ============================================================
  1193. # 【关键修复】extGpio 不再继承 extOutputPin(PCA9685)
  1194. # —— 只保留 MCP23017 + ADS1115
  1195. #
  1196. # 原因:extOutputPin 里的通道映射 [14,15,1,0] 与 extServo 完全一致,
  1197. # 一旦使用 a0-a3 / p0-p3,就会和 extServo 抢同一个 PCA9685 通道,
  1198. # 导致 P0 舵机被搞死。
  1199. #
  1200. # analogWrite 被移除(原来是通过 PCA9685 输出的 PWM)。
  1201. # 若确实需要 PWM 输出,请单独创建一个 extOutputPin 实例,
  1202. # 并避开 extServo 使用的通道。
  1203. # ============================================================
  1204. class extGpio(MCP23017, ADS1115):
  1205. def __init__(self):
  1206. MCP23017.__init__(self)
  1207. ADS1115.__init__(self)
  1208. self.address = 0x20 # 默认选择 MCP23017
  1209. # ---------------- pinMode ----------------
  1210. def pinMode(self, pinId, mode):
  1211. self.address = 0x20
  1212. # pinId: 0~3 = p0~p3 | 4~7 = a0~a3
  1213. # mode : 0 = 输入 | 1 = 输出
  1214. if 0 <= pinId <= 3:
  1215. if mode == 0:
  1216. if pinId == 0:
  1217. self.setGpioDir("B", 2, 0); self.setGpioLevel("B", 2, 1)
  1218. self.setGpioDir("B", 3, 1)
  1219. elif pinId == 1:
  1220. self.setGpioDir("B", 1, 0); self.setGpioLevel("B", 1, 1)
  1221. self.setGpioDir("B", 0, 1)
  1222. elif pinId == 2:
  1223. self.setGpioDir("B", 6, 0); self.setGpioLevel("B", 6, 1)
  1224. self.setGpioDir("A", 1, 1)
  1225. elif pinId == 3:
  1226. self.setGpioDir("B", 5, 0); self.setGpioLevel("B", 5, 1)
  1227. self.setGpioDir("B", 4, 1)
  1228. elif mode == 1:
  1229. if pinId == 0:
  1230. self.setGpioDir("B", 2, 0); self.setGpioLevel("B", 2, 1)
  1231. self.setGpioDir("B", 3, 0)
  1232. elif pinId == 1:
  1233. self.setGpioDir("B", 1, 0); self.setGpioLevel("B", 1, 1)
  1234. self.setGpioDir("B", 0, 0)
  1235. elif pinId == 2:
  1236. self.setGpioDir("B", 6, 0); self.setGpioLevel("B", 6, 1)
  1237. self.setGpioDir("A", 1, 0)
  1238. elif pinId == 3:
  1239. self.setGpioDir("B", 5, 0); self.setGpioLevel("B", 5, 1)
  1240. self.setGpioDir("B", 4, 0)
  1241. elif 4 <= pinId <= 7:
  1242. if mode == 0:
  1243. if pinId == 4: # a0
  1244. self.setGpioDir("A", 4, 0); self.setGpioLevel("A", 4, 1)
  1245. self.setGpioDir("A", 5, 1)
  1246. elif pinId == 5: # a1
  1247. self.setGpioDir("A", 3, 0); self.setGpioLevel("A", 3, 1)
  1248. self.setGpioDir("A", 7, 1)
  1249. elif pinId == 6: # a2
  1250. self.setGpioDir("A", 2, 0); self.setGpioLevel("A", 2, 1)
  1251. self.setGpioDir("A", 6, 1)
  1252. elif pinId == 7: # a3
  1253. self.setGpioDir("B", 7, 0); self.setGpioLevel("B", 7, 1)
  1254. self.setGpioDir("A", 0, 1)
  1255. elif mode == 1:
  1256. if pinId == 4:
  1257. self.setGpioDir("A", 4, 0); self.setGpioLevel("A", 4, 1)
  1258. self.setGpioDir("A", 5, 0)
  1259. elif pinId == 5:
  1260. self.setGpioDir("A", 3, 0); self.setGpioLevel("A", 3, 1)
  1261. self.setGpioDir("A", 7, 0)
  1262. elif pinId == 6:
  1263. self.setGpioDir("A", 2, 0); self.setGpioLevel("A", 2, 1)
  1264. self.setGpioDir("A", 6, 0)
  1265. elif pinId == 7:
  1266. self.setGpioDir("B", 7, 0); self.setGpioLevel("B", 7, 1)
  1267. self.setGpioDir("A", 0, 0)
  1268. # ---------------- digitalWrite ----------------
  1269. def digitalWrite(self, pinId, level):
  1270. self.address = 0x20
  1271. if 0 <= pinId <= 3:
  1272. if pinId == 0:
  1273. self.setGpioLevel("B", 3, level)
  1274. elif pinId == 1:
  1275. self.setGpioLevel("B", 0, level)
  1276. elif pinId == 2:
  1277. self.setGpioLevel("A", 1, level)
  1278. elif pinId == 3:
  1279. self.setGpioLevel("B", 4, level)
  1280. elif 4 <= pinId <= 7:
  1281. if pinId == 4:
  1282. self.setGpioLevel("A", 5, level)
  1283. elif pinId == 5:
  1284. self.setGpioLevel("A", 7, level)
  1285. elif pinId == 6:
  1286. self.setGpioLevel("A", 6, level)
  1287. elif pinId == 7:
  1288. self.setGpioLevel("A", 0, level)
  1289. # ---------------- digitalRead ----------------
  1290. def digitalRead(self, pinId):
  1291. self.address = 0x20
  1292. if 0 <= pinId <= 3:
  1293. if pinId == 0:
  1294. return self.getGpioLevel("B", 3)
  1295. elif pinId == 1:
  1296. return self.getGpioLevel("B", 0)
  1297. elif pinId == 2:
  1298. return self.getGpioLevel("A", 1)
  1299. elif pinId == 3:
  1300. return self.getGpioLevel("B", 4)
  1301. elif 4 <= pinId <= 7:
  1302. if pinId == 4:
  1303. return self.getGpioLevel("A", 5)
  1304. elif pinId == 5:
  1305. return self.getGpioLevel("A", 7)
  1306. elif pinId == 6:
  1307. return self.getGpioLevel("A", 6)
  1308. elif pinId == 7:
  1309. return self.getGpioLevel("A", 0)
  1310. return None
  1311. # ---------------- analogRead (a0-a3) ----------------
  1312. def analogRead(self, pinId):
  1313. adcPin = [3, 1, 0, 2]
  1314. if not 4 <= pinId <= 7:
  1315. return None
  1316. self.address = 0x20
  1317. if pinId == 4: # a0
  1318. self.setGpioDir("A", 4, 1)
  1319. self.setGpioLevel("A", 4, 0)
  1320. elif pinId == 5: # a1
  1321. self.setGpioDir("A", 3, 1)
  1322. self.setGpioLevel("A", 3, 0)
  1323. elif pinId == 6: # a2
  1324. self.setGpioDir("A", 2, 1)
  1325. self.setGpioLevel("A", 2, 0)
  1326. elif pinId == 7: # a3
  1327. self.setGpioDir("B", 7, 0)
  1328. self.setGpioLevel("B", 7, 0)
  1329. # 给 MCP23017 通道切换留点时间,否则下一条 I2C 会打到 0x49 时总线刚切完
  1330. time.sleep(0.005)
  1331. self.address = 0x49
  1332. try:
  1333. return self.readAdc(adcPin[pinId - 4])
  1334. finally:
  1335. self.address = 0x20
  1336. # ---------------- __del__ ----------------
  1337. def __del__(self):
  1338. try:
  1339. self.address = 0x20
  1340. MCP23017.__del__(self)
  1341. except Exception:
  1342. pass
  1343. ##################################
  1344. # 15、LazyImport #
  1345. ##################################
  1346. class LazyImport(object):
  1347. def __init__(self, name):
  1348. self.name = name
  1349. self.module = None
  1350. def __getattr__(self, item):
  1351. if self.module is None:
  1352. self.module = __import__(self.name)
  1353. return getattr(self.module, item)