Skip to content

Commit abe94d7

Browse files
Tinyu-Zhaolbuque
authored andcommitted
lib/unit: Roller485 add slave control command.
Signed-off-by: Tinyu <[email protected]>
1 parent 79f05fb commit abe94d7

File tree

2 files changed

+104
-89
lines changed

2 files changed

+104
-89
lines changed

m5stack/libs/unit/main.py

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from M5 import *
66
from hardware import *
77
from roller485 import Roller485Unit
8+
from myenv import ENVUnit
89
import time
910

1011
# i2c0 = None
@@ -32,12 +33,16 @@ def setup():
3233
invert=0,
3334
flow=0,
3435
)
35-
roller485_0 = Roller485Unit(
36-
uart, address=0x00, i2c_address=0x44, mode=Roller485Unit._RS485_TO_I2C_MODE
37-
)
36+
roller485_0 = Roller485Unit(uart, address=0x01, mode=Roller485Unit._RS485_TO_I2C_MODE)
37+
env2_0 = ENVUnit(i2c=roller485_0, type=2)
38+
print(f"roller485_0 instance: {roller485_0}") # 打印实例信息
3839
Widgets.fillScreen(0xFF9900)
3940

40-
roller485_0.set_motor_output_state(0)
41+
print(env2_0.read_temperature())
42+
43+
# roller485_0.scan()
44+
45+
# roller485_0.set_motor_output_state(0)
4146
# I2C Communication
4247
# roller485_0.write_i2c_slave(bytes((0x2C, 0x06)),0)
4348
# read_buffer=roller485_0.read_i2c_slave(0x06)
@@ -49,9 +54,9 @@ def setup():
4954

5055
# # #SYSTEM REGISTER
5156
# roller485_0.set_rgb_color(0x33ff33)
52-
print(roller485_0.get_rgb_color())
53-
roller485_0.set_rgb_color(0x11FF33)
54-
print(roller485_0.get_rgb_color())
57+
# print(roller485_0.get_rgb_color())
58+
# roller485_0.set_rgb_color(0x11ff33)
59+
# print(roller485_0.get_rgb_color())
5560

5661
# print(f"get_rgb_brightness:{roller485_0.get_rgb_brightness()}")
5762
# roller485_0.set_rgb_brightness(100)
@@ -119,14 +124,14 @@ def setup():
119124
# roller485_0.set_rgb_brightness(100)
120125

121126
# # Speed Mode
122-
roller485_0.set_motor_output_state(0)
123-
roller485_0.set_motor_mode(1)
124-
roller485_0.set_motor_speed(100)
125-
roller485_0.set_speed_max_current(1200)
126-
roller485_0.set_motor_output_state(1)
127-
print(f"get_motor_status:{roller485_0.get_motor_status()}")
128-
print(f"get_motor_error_code:{roller485_0.get_motor_error_code()}")
129-
print(f"get_motor_speed_readback:{roller485_0.get_motor_speed_readback()}")
127+
# roller485_0.set_motor_output_state(0)
128+
# roller485_0.set_motor_mode(1)
129+
# roller485_0.set_motor_speed(100)
130+
# roller485_0.set_speed_max_current(1200)
131+
# roller485_0.set_motor_output_state(1)
132+
# print(f"get_motor_status:{roller485_0.get_motor_status()}")
133+
# print(f"get_motor_error_code:{roller485_0.get_motor_error_code()}")
134+
# print(f"get_motor_speed_readback:{roller485_0.get_motor_speed_readback()}")
130135

131136
# # Position Mode
132137
# roller485_0.set_motor_output_state(0)
@@ -161,8 +166,8 @@ def loop():
161166
# global i2c0, roller485_0
162167
global roller485_0
163168

164-
roller485_0.write_i2c_slave(bytes((0x2C, 0x06)), 0)
165-
read_buffer = roller485_0.read_i2c_slave(0x06)
169+
roller485_0.writeto(0x44, bytes((0x2C, 0x06)), False)
170+
read_buffer = roller485_0.readfrom(0x44, 0x06)
166171
print("hex: ", " ".join(f"{byte:02x}" for byte in read_buffer))
167172
temp = ((((read_buffer[0] * 256.0) + read_buffer[1]) * 175) / 65535.0) - 45
168173
print("Temperature: ", temp)
@@ -175,12 +180,12 @@ def loop():
175180
if __name__ == "__main__":
176181
try:
177182
setup()
178-
while True:
179-
elapsed_time = time.time() - start_time
180-
if elapsed_time > 10:
181-
print("超过10秒,循环终止")
182-
break
183-
loop()
183+
# while True:
184+
# elapsed_time = time.time() - start_time
185+
# if elapsed_time > 10:
186+
# print("超过10秒,循环终止")
187+
# break
188+
# loop()
184189
except (Exception, KeyboardInterrupt) as e:
185190
try:
186191
from utility import print_error_msg

m5stack/libs/unit/roller485.py

Lines changed: 76 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,28 @@ def read(self, register, length) -> bytes:
7171
def write(self, register, data: bytes) -> None:
7272
raise NotImplementedError("Subclasses should implement this method!")
7373

74-
def read_i2c_slave(self, length) -> bytes:
74+
def readfrom_mem(self, addr: int, mem_addr: int, nbytes: int) -> bytes: # 0x60
7575
raise NotImplementedError("Subclasses should implement this method!")
7676

77-
def write_i2c_slave(self, byte_list, stop_bit) -> None:
77+
def readfrom_mem_into(self, addr: int, mem_addr: int, buf: bytearray) -> None: # 0x60
7878
raise NotImplementedError("Subclasses should implement this method!")
7979

80-
def read_i2c_slave_register(self, register, length) -> bytes:
80+
def writeto_mem(self, addr: int, mem_addr: int, byte_list) -> Literal[True]: # 0x61
8181
raise NotImplementedError("Subclasses should implement this method!")
8282

83-
def write_i2c_slave_register(self, register, bytes) -> None:
83+
def readfrom(self, addr: int, nbytes: int): # 0x62
84+
raise NotImplementedError("Subclasses should implement this method!")
85+
86+
def readfrom_into(self, addr: int, buf: bytearray) -> None: # 0x62
87+
raise NotImplementedError("Subclasses should implement this method!")
88+
89+
def writeto(self, addr: int, buf: bytes | bytearray, stop: bool = True):
90+
raise NotImplementedError("Subclasses should implement this method!")
91+
92+
def scan(self) -> list:
93+
raise NotImplementedError("Subclasses should implement this method!")
94+
95+
def deinit(self) -> None:
8496
raise NotImplementedError("Subclasses should implement this method!")
8597

8698
#! MOTOR CONFIGURATION API !#
@@ -484,7 +496,7 @@ def write(self, register, bytes) -> None:
484496

485497

486498
class Roller485(RollerBase):
487-
def __init__(self, bus, address=_ROLLER485_RS485_ADDR) -> None:
499+
def __init__(self, bus, address=_ROLLER485_RS485_ADDR, mode=None) -> None:
488500
"""! Initialize the Roller485 object.
489501
490502
@param bus: The RS485 bus instance.
@@ -581,6 +593,7 @@ def read_response(self, cmd, id):
581593
if resp_buf[0:2] == b"\xAA\x55":
582594
if resp_buf[2:4] == bytes([(0x10 + cmd), id]): # Write cmd+10 = response cmd
583595
if self._crc8(resp_buf[2:-1]) == resp_buf[-1]:
596+
print(f"Response: {[hex(byte) for byte in resp_buf]}")
584597
return (True, resp_buf[2:-1])
585598
time.sleep_ms(100)
586599
return (False, 0)
@@ -603,7 +616,7 @@ def _crc8(self, buffer) -> int:
603616

604617

605618
class Roller485ToI2CBus(Roller485):
606-
def __init__(self, bus, address=_ROLLER485_RS485_ADDR, i2c_address=0x64) -> None:
619+
def __init__(self, bus, address=_ROLLER485_RS485_ADDR, mode=None) -> None:
607620
"""! Initialize the Roller485ToI2CBus object.
608621
609622
@param bus: The RS485 bus instance.
@@ -612,90 +625,85 @@ def __init__(self, bus, address=_ROLLER485_RS485_ADDR, i2c_address=0x64) -> None
612625
"""
613626
self._rs485_bus = bus
614627
self._rs485_addr = address # Motor ID == address
615-
self._i2c_addr = i2c_address # I2C slave address
616628
super().__init__(bus, address=address)
617629

618-
def read_i2c_slave(self, length):
619-
"""! Read data from the I2C slave device via RS485.
620-
621-
@param length: The number of bytes to read.
622-
@return: The data read from the I2C slave.
623-
@throws Exception: If the read operation fails.
624-
"""
625-
self.send_command(
626-
_READ_I2C_SLAVE_ADDR, self._rs485_addr, [self._i2c_addr, length], buf_len=5
627-
)
628-
success, output = self.read_response(_READ_I2C_SLAVE_ADDR, self._rs485_addr)
629-
if success and output[2]:
630-
return output[8 : (8 + length)]
631-
else:
632-
raise Exception(
633-
f"Read I2C Slave failed: register {self._i2c_addr:#04x}, length {length}"
634-
)
635-
636-
def write_i2c_slave(self, byte_list, stop_bit):
637-
"""! Write data to the I2C slave device via RS485.
638-
639-
@param byte_list: The data bytes to write.
640-
@param stop_bit: Whether to send a stop bit after writing.
641-
@return: True if the write operation is successful.
642-
@throws Exception: If the write operation fails.
643-
"""
644-
data_len = len(byte_list)
645-
data = [self._i2c_addr, data_len, stop_bit, 0, 0, 0] + list(byte_list)
646-
self.send_command(_WRITE_I2C_SLAVE_ADDR, self._rs485_addr, data, buf_len=25)
647-
success, output = self.read_response(_WRITE_I2C_SLAVE_ADDR, self._rs485_addr)
648-
if success and output[2]:
649-
return True
650-
else:
651-
raise Exception("Write to I2C Slave failed")
652-
653-
def read_i2c_slave_register(self, register, length) -> bytes:
654-
"""! Read data from a specific register of the I2C slave device.
655-
656-
@param register: The register address to read from.
657-
@param length: The number of bytes to read.
658-
@return: The data read from the register.
659-
@throws Exception: If the read operation fails.
660-
"""
661-
byte_len = 2 if register > 0xFF else 1
630+
def readfrom_mem(self, addr: int, mem_addr: int, nbytes: int) -> bytes: # 0x60
631+
byte_len = 2 if mem_addr > 0xFF else 1
662632
if byte_len == 1:
663-
data = [self._i2c_addr, 0, register, 0, length]
633+
data = [addr, 0, mem_addr, 0, nbytes]
664634
else:
665-
data = [self._i2c_addr, 1, register, (register >> 8), length]
635+
data = [addr, 1, mem_addr, (mem_addr >> 8), nbytes]
666636
self.send_command(_READ_I2C_SLAVE_REG_ADDR, self._rs485_addr, data, buf_len=8)
667637
success, output = self.read_response(_READ_I2C_SLAVE_REG_ADDR, self._rs485_addr)
668638
if success and output[2]:
669-
return output[8 : (8 + length)]
639+
return output[8 : (8 + nbytes)]
670640
else:
671641
raise Exception(
672-
f"Read I2C Slave Register failed: register {register:#04x}, length {length}"
642+
f"Read I2C Slave Memory Register failed: register {mem_addr:#04x}, nbytes {nbytes}"
673643
)
674644

675-
def write_i2c_slave_register(self, register, byte_list) -> Literal[True]:
676-
"""! Write data to a specific register of the I2C slave device.
645+
def readfrom_mem_into(self, addr: int, mem_addr: int, buf: bytearray) -> None: # 0x60
646+
data = self.readfrom_mem(addr, mem_addr, len(buf))
647+
buf[: len(data)] = data
677648

678-
@param register: The register address to write to.
679-
@param byte_list: The data bytes to write.
680-
@return: True if the write operation is successful.
681-
@throws Exception: If the write operation fails.
682-
"""
683-
byte_len = 2 if register > 0xFF else 1
649+
def writeto_mem(self, addr: int, mem_addr: int, byte_list) -> Literal[True]: # 0x61
650+
byte_len = 2 if mem_addr > 0xFF else 1
684651
data_len = len(byte_list)
685652
if byte_len == 1:
686-
data = [self._i2c_addr, 0, register, 0, data_len, 0]
653+
data = [addr, 0, mem_addr, 0, data_len, 0]
687654
else:
688-
data = [self._i2c_addr, 1, register, (register >> 8), data_len, 0]
655+
data = [addr, 1, mem_addr, (mem_addr >> 8), data_len, 0]
689656
data += list(byte_list)
690657
self.send_command(_WRITE_I2C_SLAVE_REG_ADDR, self._rs485_addr, data, buf_len=25)
691658
success, output = self.read_response(_WRITE_I2C_SLAVE_REG_ADDR, self._rs485_addr)
692659
if success and output[2]:
693660
return True
694661
else:
695662
raise Exception(
696-
f"Write to I2C Slave Register failed: register {register:#04x}, data {byte_list}"
663+
f"Write to I2C Memory Register failed: register {mem_addr:#04x}, data {byte_list}"
697664
)
698665

666+
def readfrom(self, addr: int, nbytes: int): # 0x62
667+
self.send_command(_READ_I2C_SLAVE_ADDR, self._rs485_addr, [addr, nbytes], buf_len=5)
668+
success, output = self.read_response(_READ_I2C_SLAVE_ADDR, self._rs485_addr)
669+
if success and output[2]:
670+
return output[8 : (8 + nbytes)]
671+
else:
672+
raise Exception(f"Read I2C Slave failed: register {addr:#04x}, nbytes {nbytes}")
673+
674+
def readfrom_into(self, addr: int, buf: bytearray) -> None: # 0x62
675+
data = self.readfrom(addr, len(buf))
676+
buf[: len(data)] = data
677+
678+
def writeto(self, addr: int, buf: bytes | bytearray, stop: bool = True):
679+
data_len = len(buf)
680+
data = [addr, data_len, stop, 0, 0, 0] + list(buf)
681+
682+
self.send_command(_WRITE_I2C_SLAVE_ADDR, self._rs485_addr, data, buf_len=25)
683+
success, output = self.read_response(_WRITE_I2C_SLAVE_ADDR, self._rs485_addr)
684+
if success and output[2]:
685+
return True
686+
687+
def _writeto(self, addr: int, buf: bytes | bytearray, stop: bool = True):
688+
data_len = len(buf)
689+
data = [addr, data_len, stop, 0, 0, 0] + list(buf)
690+
691+
self.send_command(_WRITE_I2C_SLAVE_ADDR, self._rs485_addr, data, buf_len=25)
692+
success, output = self.read_response(_WRITE_I2C_SLAVE_ADDR, self._rs485_addr)
693+
if success and output[2]:
694+
return True
695+
696+
def scan(self) -> list:
697+
found_devices = []
698+
for address in range(0x08, 0x77 + 1):
699+
try:
700+
if self._writeto(address, bytes(0x01), stop=False):
701+
found_devices.append(address)
702+
703+
except OSError:
704+
pass
705+
return found_devices
706+
699707

700708
class Roller485Unit:
701709
"""! A factory class to create Roller instances based on communication mode."""
@@ -718,4 +726,6 @@ def __new__(cls, *args, **kwargs) -> RollerBase:
718726
cls.instance = Roller485(args[0], **kwargs)
719727
elif kwargs["mode"] == cls._RS485_TO_I2C_MODE:
720728
cls.instance = Roller485ToI2CBus(args[0], **kwargs)
729+
else:
730+
raise ValueError("Invalid mode specified")
721731
return cls.instance

0 commit comments

Comments
 (0)