Skip to content

Commit bb234f4

Browse files
committed
feature/unit/pbhub: 6-channel expansion Unit[Port B]
1 parent 824e4e7 commit bb234f4

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed

m5stack/libs/unit/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@
2222
from .encoder8 import ENCODER8
2323
from .lorawan import LoRaWAN
2424
from .gps import GPS
25+
from .hbridge import HBRIDGE
26+
from .pbhub import PBHUB

m5stack/libs/unit/pbhub.py

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
from machine import I2C
2+
from micropython import const
3+
import struct
4+
from .pahub import PAHUB
5+
from .unit_helper import UnitError
6+
import time
7+
8+
try:
9+
from typing import Union
10+
except ImportError:
11+
pass
12+
13+
hub_addr = [0x40, 0x50, 0x60, 0x70, 0x80, 0xA0]
14+
15+
PBHUB_ADDR = 0x61
16+
FW_VER_REG = 0xFE
17+
I2C_ADDR_REG = 0xFF
18+
19+
class PBHUB:
20+
def __init__(self, i2c: Union[I2C, PAHUB], addr=PBHUB_ADDR):
21+
self.i2c_addr = addr
22+
self.pbhub_i2c = i2c
23+
self.init_i2c_address(addr)
24+
25+
def _available(self):
26+
if not (self.i2c_addr in self.pbhub_i2c.scan()):
27+
raise UnitError("Pb.hub unit maybe not connect")
28+
29+
def digitalRead(self, num, pos):
30+
"""
31+
digital read.
32+
num : 0 to 5
33+
pos : 0 or 1
34+
return : 0 or 1
35+
"""
36+
num = max(min(num, 5), 0)
37+
offset = 0x04 if pos else 0x05
38+
data = self.read_reg((hub_addr[num] | offset), 1)[0] > 0
39+
return data
40+
41+
def digitalWrite(self, num, pos, value):
42+
"""
43+
digital write.
44+
num : 0 to 5
45+
pos : 0 or 1
46+
value : 0 or 1
47+
"""
48+
num = max(min(num, 5), 0)
49+
value = 1 if value > 0 else 0
50+
offset = 0x00 if pos else 0x01
51+
self.write_mem_list(hub_addr[num] | offset, [value])
52+
53+
def pwmRead(self, num, pos):
54+
"""
55+
pwm read.
56+
num : 0 to 5
57+
pos : 0 or 1
58+
return : 0 to 100
59+
"""
60+
num = max(min(num, 5), 0)
61+
offset = 0x02 if pos else 0x03
62+
data = self.read_reg((hub_addr[num] | offset), 1)[0]
63+
data = self.map(data, 0, 255, 0, 100)
64+
return data
65+
66+
def pwmWrite(self, num, pos, value):
67+
"""
68+
pwm write.
69+
num : 0 to 5
70+
pos : 0 or 1
71+
value : 0 to 100
72+
"""
73+
num = max(min(num, 5), 0)
74+
value = max(min(value, 100), 0)
75+
value = self.map(value, 0, 100, 0, 255)
76+
offset = 0x02 if pos else 0x03
77+
self.write_mem_list(hub_addr[num] | offset, [value])
78+
79+
def analogRead(self, num):
80+
"""
81+
analog read.
82+
num : 0 to 5
83+
return : 0 to 4095
84+
"""
85+
num = max(min(num, 5), 0)
86+
offset = 0x06
87+
data = self.read_reg((hub_addr[num] | offset),2)
88+
data = struct.unpack('<h', data)[0]
89+
return data
90+
91+
# default: 16
92+
def setRgbNum(self, num, length):
93+
"""
94+
set RGB Max length.
95+
num : 0 to 5
96+
length : 0 to 74
97+
"""
98+
num = max(min(num, 5), 0)
99+
self.write_mem_list(hub_addr[num] | 0x08, [(length & 0xff), ((length >> 8) & 0xff)])
100+
101+
def setColorPos(self, num, led, color_in):
102+
"""
103+
set RGB led Color.
104+
num : 0 to 5
105+
led : 0 to max led
106+
color_in : 0 to 0xfffff
107+
"""
108+
num = max(min(num, 5), 0)
109+
out_buf = led.to_bytes(2, 'little') + color_in.to_bytes(3, 'big')
110+
self.pbhub_i2c.writeto_mem(self.i2c_addr, hub_addr[num] | 0x09, out_buf)
111+
112+
def setColor(self, num, begin, count, color_in):
113+
"""
114+
set RGB led Color.
115+
num : 0 to 5
116+
begin : 0 to 74
117+
pos : begin + (0 to 74)
118+
color_in : 0 to 0xfffff
119+
"""
120+
num = max(min(num, 5), 0)
121+
out_buf = begin.to_bytes(2, 'little') + count.to_bytes(2, 'little') + color_in.to_bytes(3, 'big')
122+
self.pbhub_i2c.writeto_mem(self.i2c_addr, hub_addr[num] | 0x0a, out_buf)
123+
124+
def setBrightness(self, num, value):
125+
"""
126+
set RGB led brightness.
127+
num : 0 to 5
128+
value : 0 to 100
129+
"""
130+
num = max(min(num, 5), 0)
131+
self.write_mem_list(hub_addr[num] | 0x0b, [value])
132+
133+
def setServoAngle(self, num, pos, value):
134+
"""
135+
set servo angle.
136+
num : 0 to 5
137+
pos : 0 or 1
138+
value : 0 to 180
139+
"""
140+
num = max(min(num, 5), 0)
141+
value = max(min(value, 180), 0)
142+
offset = 0x0c if pos else 0x0d
143+
self.write_mem_list(hub_addr[num] | offset, [value])
144+
145+
def setServoPulse(self, num, pos, value):
146+
"""
147+
set servo pulse.
148+
num : 0 to 5
149+
pos : 0 or 1
150+
value : 500 to 2500
151+
"""
152+
num = max(min(num, 5), 0)
153+
value = max(min(value, 2500), 500)
154+
offset = 0x0e if pos else 0x0f
155+
self.write_mem_list(hub_addr[num] | offset, [(value & 0xff), ((value >> 8) & 0xff)])
156+
157+
def read_status(self, mode):
158+
"""
159+
read firmware version and i2c address.
160+
mode : 0xFE and 0xFF
161+
"""
162+
if mode >= FW_VER_REG and mode <= I2C_ADDR_REG:
163+
return self.read_reg(mode, 1)[0]
164+
165+
def init_i2c_address(self, slave_addr = PBHUB_ADDR):
166+
"""
167+
change the i2c address
168+
slave_addr : 1 to 127
169+
"""
170+
if slave_addr >= 1 and slave_addr <= 127:
171+
self.i2c_addr = slave_addr
172+
self._available()
173+
174+
def set_i2c_address(self, addr):
175+
"""
176+
set i2c address.
177+
addr : 1 to 127
178+
"""
179+
if addr >= 1 and addr <= 127:
180+
if addr != self.i2c_addr:
181+
self.write_mem_list(I2C_ADDR_REG, [addr])
182+
self.i2c_addr = addr
183+
184+
def write_mem_list(self, reg, data):
185+
buf = bytearray(data)
186+
self.pbhub_i2c.writeto_mem(self.i2c_addr, reg, buf)
187+
188+
def read_reg(self, reg, num):
189+
buf = bytearray(1)
190+
buf[0] = reg
191+
time.sleep_ms(1)
192+
self.pbhub_i2c.writeto(self.i2c_addr, buf)
193+
buf = bytearray(num)
194+
self.pbhub_i2c.readfrom_into(self.i2c_addr, buf)
195+
return buf
196+
197+
def map(self, x, in_min, in_max, out_min, out_max):
198+
return round((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
199+
200+
def deinit(self):
201+
pass

0 commit comments

Comments
 (0)