Skip to content

Commit ee34017

Browse files
committed
Add gyroscope calibration in Tools
- Modify name to Bittle X+Arm - Change name Debugger to Tools - Add gyroscope calibration in Tools
1 parent 7cb3242 commit ee34017

File tree

68 files changed

+4880
-6157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+4880
-6157
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ pyUI/README.txt
2222
pyUI/README_Mac.txt
2323
pyUI/README_Windows.txt
2424
serialMaster/logfile.log
25+
.cursor/*

OpenCatPythonAPI/PetoiRobot/ardSerial.py

Lines changed: 96 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import os
1313
from . import config
1414
import glob
15+
import re
1516

1617
FORMAT = '%(asctime)-15s %(name)s - %(levelname)s - %(message)s'
1718
'''
@@ -51,7 +52,7 @@ def txt(key):
5152
# printH("txt('lan'):", txt('lan'))
5253

5354

54-
logger.info("ardSerial date: Jun. 20, 2024")
55+
logger.info("ardSerial date: Feb. 27, 2025")
5556

5657
def encode(in_str, encoding='utf-8'):
5758
if isinstance(in_str, bytes):
@@ -146,6 +147,7 @@ def serialWriteByte(port, var=None):
146147
if var is None:
147148
var = []
148149
token = var[0][0]
150+
# printH("token:",token)
149151
# print var
150152
if (token == 'c' or token == 'm' or token == 'i' or token == 'b' or token == 'u' or token == 't') and len(var) >= 2:
151153
in_str = ""
@@ -162,6 +164,7 @@ def serialWriteByte(port, var=None):
162164
else:
163165
in_str = token + '\n'
164166
logger.debug(f"!!!!!!! {in_str}")
167+
# printH("in_str:", in_str)
165168
port.Send_data(encode(in_str))
166169
time.sleep(0.01)
167170

@@ -181,7 +184,7 @@ def printSerialMessage(port, token, timeout=0):
181184
if port:
182185
response = port.main_engine.readline().decode('ISO-8859-1')
183186
if response != '':
184-
# logger.debug(f"response is: {response}")
187+
logger.debug(f"response is: {response}")
185188
responseTrim = response.split('\r')[0]
186189
logger.debug(f"responseTrim is: {responseTrim}")
187190
if responseTrim.lower() == token.lower():
@@ -205,6 +208,7 @@ def printSerialMessage(port, token, timeout=0):
205208

206209
def sendTask(PortList, port, task, timeout=0): # task Structure is [token, var=[], time]
207210
logger.debug(f"{task}")
211+
# printH("task:",task)
208212
global returnValue
209213
# global sync
210214
# print(task)
@@ -215,8 +219,9 @@ def sendTask(PortList, port, task, timeout=0): # task Structure is [token, var=
215219
logger.debug(f"Previous buffer: {previousBuffer}")
216220
pass
217221
if len(task) == 2:
218-
# print('a')
219-
# print(task[0])
222+
# print('a')
223+
# print(task[0])
224+
# printH("port is:", port)
220225
serialWriteByte(port, [task[0]])
221226
elif isinstance(task[1][0], int):
222227
# print('b')
@@ -252,8 +257,9 @@ def sendTaskParallel(ports, task, timeout=0):
252257
# sync = 0
253258
threads = list()
254259
for p in ports:
255-
t = threading.Thread(target=sendTask, args=(goodPorts, p, task, timeout), daemon=True)
260+
t = threading.Thread(target=sendTask, args=(goodPorts, p, task, timeout))
256261
threads.append(t)
262+
t.daemon = True
257263
t.start()
258264
for t in threads:
259265
if t.is_alive():
@@ -292,15 +298,18 @@ def splitTaskForLargeAngles(task):
292298
def send(port, task, timeout=0):
293299
# printH('*** @@@ open port ',port) #debug
294300
if isinstance(port, dict):
301+
# print("port is dict.")
295302
p = list(port.keys())
296303
elif isinstance(port, list):
304+
# print("port is list.")
297305
p = port
298306
queue = splitTaskForLargeAngles(task)
299307
for task in queue:
300308
# printH("task",task)
301309
if len(port) > 1:
302310
returnResult = sendTaskParallel(p, task, timeout)
303311
elif len(port) == 1:
312+
# print("port len is 1.")
304313
returnResult = sendTask(goodPorts, p[0], task, timeout)
305314
else:
306315
# print('no ports')
@@ -338,7 +347,8 @@ def closeAllSerial(ports, clearPorts=True):
338347
send(ports, ['d', 0], 1)
339348

340349
for p in ports:
341-
t = threading.Thread(target=closeSerialBehavior, args=(p,), daemon=True)
350+
t = threading.Thread(target=closeSerialBehavior, args=(p,))
351+
t.daemon = True
342352
t.start()
343353
t.join()
344354

@@ -453,7 +463,7 @@ def closeAllSerial(ports, clearPorts=True):
453463
postureDict = {
454464
'Nybble': postureTableNybble,
455465
'Bittle': postureTableBittle,
456-
'BittleR': postureTableBittleR,
466+
'BittleX+Arm': postureTableBittleR,
457467
'DoF16': postureTableDoF16
458468
}
459469
model = 'Bittle'
@@ -581,8 +591,9 @@ def checkPortList(PortList, allPorts, needTesting=True):
581591
serialObject = Communication(p, 115200, 1)
582592
if needTesting is True:
583593
t = threading.Thread(target=testPort,
584-
args=(PortList, serialObject, p.split('/')[-1]), daemon=True) # remove '/dev/' in the port name
594+
args=(PortList, serialObject, p.split('/')[-1])) # remove '/dev/' in the port name
585595
threads.append(t)
596+
t.daemon = True
586597
t.start()
587598
else:
588599
logger.debug(f"Adding in checkPortList: {p}")
@@ -593,7 +604,7 @@ def checkPortList(PortList, allPorts, needTesting=True):
593604
for t in threads:
594605
if t.is_alive():
595606
# print("t is alive")
596-
t.join(timeout=5)
607+
t.join(timeout=8)
597608

598609

599610
def keepCheckingPort(portList, cond1=None, check=True, updateFunc = lambda:None):
@@ -644,25 +655,59 @@ def keepCheckingPort(portList, cond1=None, check=True, updateFunc = lambda:None)
644655
updateFunc()
645656
allPorts = copy.deepcopy(currentPorts)
646657

658+
def get_raspberry_pi_model():
659+
"""Detects the Raspberry pi model."""
660+
try :
661+
with open('/proc/cpuinfo','r')as cpuinfo:
662+
for line in cpuinfo:
663+
if "Model" in line:
664+
model_info = line.split(':')[1].strip()
665+
if "Raspberry Pi 3" in model_info:
666+
return "Raspberry Pi 3"
667+
elif "Raspberry Pi 4" in model_info:
668+
return "Raspberry pi 4"
669+
elif "Raspberry Pi 5" in model_info:
670+
return "Raspberry Pi 5"
671+
else:
672+
#if not 3,4,or 5,attempt to get revision code
673+
with open('/proc/cpuinfo','r')as cpuinfo2:
674+
for line2 in cpuinfo2:
675+
if"Revision" in line2:
676+
revision_code =line2.split(':')[1].strip()
677+
#basic check for revision codes that indicate pi5
678+
if re.match(r'^d[0-3]8', revision_code):
679+
return "Raspberry Pi 5"
680+
else:
681+
return "Raspberry Pi(Unknown Model)"
682+
return "Not a Raspberry pi"
683+
except FileNotFoundError:
684+
return "Not a Raspberry Pi"
685+
647686
def showSerialPorts(allPorts):
648687
# currently an issue in pyserial where for newer raspiberry pi os
649688
# (Kernel version: 6.1, Debian version: 12 (bookworm)) or ubuntus (22.04)
650689
# it classifies the /dev/ttyS0 port as a platform port and therefore won't be queried
651690
# https://github.com/pyserial/pyserial/issues/489
652691
if os.name == 'posix' and sys.platform.lower()[:5] == 'linux':
653-
extra_ports = glob.glob('/dev/ttyS*')
692+
raspPiModelName = get_raspberry_pi_model()
693+
if raspPiModelName != "Raspberry Pi 5":
694+
extra_ports = glob.glob('/dev/ttyS*')
695+
else:
696+
extra_ports = glob.glob('/dev/ttyAMA*')
697+
654698
for port in extra_ports:
655699
if port not in allPorts:
656700
allPorts.append(port)
657-
for item in allPorts:
658-
if 'AMA0' in item:
659-
allPorts.remove(item)
660-
701+
# printH("allPorts:", allPorts)
702+
661703
allPorts = deleteDuplicatedUsbSerial(allPorts)
662704
for index in range(len(allPorts)):
663705
logger.debug(f"port[{index}] is {allPorts[index]} ")
664-
print("\n*** Available serial ports: ***")
665-
print(*allPorts, sep = "\n")
706+
logger.info(f"*** Available serial ports: ***")
707+
# print(*allPorts, sep = "\n")
708+
for index in range(len(allPorts)):
709+
logger.info(f"{allPorts[index]} ")
710+
666711
if platform.system() != "Windows":
667712
for p in allPorts:
668713
if 'cu.usb' in p:
@@ -704,7 +749,6 @@ def connectPort(PortList, needTesting=True, needSendTask=True, needOpenPort=True
704749
portName = allPorts[0].split('/')[-1]
705750
portStrList.insert(0, portName) # remove '/dev/' in the port name
706751

707-
708752

709753
def replug(PortList, needSendTask=True, needOpenPort=True):
710754
global timePassed
@@ -757,8 +801,8 @@ def countdown(start,ap):
757801
else:
758802
dif = list(set(curPorts)-set(ap))
759803
dif = deleteDuplicatedUsbSerial(dif)
760-
# print("diff:",end=" ")
761-
# print(dif)
804+
print("diff:",end=" ")
805+
print(dif)
762806

763807
success = False
764808
for p in dif:
@@ -890,28 +934,28 @@ def monitoringJoint(ports, jointIndex, timer, callback):
890934
print("Current Angel:" + str(angel))
891935

892936
def read_MCU_loop(PortList, callback=None):
893-
result = send(PortList, ['gP', 0])
894-
print("send results " + str(result))
895-
p = list(PortList.keys())
896-
serialObject = p[0]
897-
while True:
898-
try:
899-
if PortList:
900-
data = serialObject.main_engine.readline()
901-
if data:
902-
try:
903-
decoded_data = data.decode('ISO-8859-1').strip()
904-
if callback is not None:
905-
callback(decoded_data)
906-
else:
907-
print(str(decoded_data))
908-
except Exception as e:
909-
logger.error(f"Error decoding serial port data: {e}")
910-
time.sleep(0.005) # avoid high CPU usage
911-
except Exception as e:
912-
logger.error(f"Error reading serial port data: {e}")
913-
break
914-
937+
result = send(PortList, ['gP', 0])
938+
print("send results " + str(result))
939+
p = list(PortList.keys())
940+
serialObject = p[0]
941+
while True:
942+
try:
943+
if PortList:
944+
data = serialObject.main_engine.readline()
945+
if data:
946+
try:
947+
decoded_data = data.decode('ISO-8859-1').strip()
948+
if callback is not None:
949+
callback(decoded_data)
950+
else:
951+
print(str(decoded_data))
952+
except Exception as e:
953+
logger.error(f"Error decoding serial port data: {e}")
954+
time.sleep(0.005) # avoid high CPU usage
955+
except Exception as e:
956+
logger.error(f"Error reading serial port data: {e}")
957+
break
958+
915959
#if need to open serial port, use objects goodPorts
916960
goodPorts = {} # goodPorts is a dictionary, the structure is {SerialPort Object(<class 'SerialCommunication.Communication'>): portName(string), ...}
917961

@@ -938,16 +982,21 @@ def distanceHanle(distance):
938982
if __name__ == '__main__':
939983
try:
940984
connectPort(goodPorts)
941-
t = threading.Thread(target=keepCheckingPort, args=(goodPorts,), daemon=True)
985+
t = threading.Thread(target=keepCheckingPort, args=(goodPorts,))
986+
t.daemon = True
942987
t.start()
943-
t1=threading.Thread(target=read_MCU_loop, args=(goodPorts, None))
944-
t1.start()
988+
# t1=threading.Thread(target=read_MCU_loop, args=(goodPorts, None))
989+
# t1.daemon = True
990+
# t1.start()
945991
### Monitor Threads
946-
# t_monitor_voltage = threading.Thread(target=monitoringVoltage, args=(goodPorts, 0xA7, 60, voltageHanle), daemon=True)
992+
# t_monitor_voltage = threading.Thread(target=monitoringVoltage, args=(goodPorts, 0xA7, 60, voltageHanle))
993+
# t_monitor_voltage.daemon = True
947994
# t_monitor_voltage.start()
948-
# t_monitor_distance = threading.Thread(target=monitoringDistance, args=(goodPorts, 16, 17, 0.5, distanceHanle), daemon=True)
995+
# t_monitor_distance = threading.Thread(target=monitoringDistance, args=(goodPorts, 16, 17, 0.5, distanceHanle))
996+
# t_monitor_distance.daemon = True
949997
# t_monitor_distance.start()
950-
# t_monitor_joint = threading.Thread(target=monitoringJoint, args=(goodPorts, 0 , 0.5, None), daemon=True)
998+
# t_monitor_joint = threading.Thread(target=monitoringJoint, args=(goodPorts, 0 , 0.5, None))
999+
# t_monitor_joint.daemon = True
9511000
# t_monitor_joint.start()
9521001

9531002
if len(sys.argv) >= 2:

0 commit comments

Comments
 (0)