mirror of
https://github.com/infiniteCable2/panda.git
synced 2026-02-18 17:23:52 +08:00
Sync: commaai/panda:master → sunnypilot/panda:master
This commit is contained in:
6
.github/workflows/update-cppcheck.yml
vendored
6
.github/workflows/update-cppcheck.yml
vendored
@@ -17,7 +17,11 @@ jobs:
|
||||
- name: Get latest cppcheck version
|
||||
id: version
|
||||
run: |
|
||||
LATEST=$(curl -fsSL https://api.github.com/repos/danmar/cppcheck/releases/latest | jq -r .tag_name)
|
||||
# Tags are sorted by time (newest first), so get the first version-like tag
|
||||
LATEST=$(curl -fsSL "https://api.github.com/repos/danmar/cppcheck/tags?per_page=20" | \
|
||||
jq -r '.[].name' | \
|
||||
grep -E '^[0-9]+\.[0-9]+(\.[0-9]+)?$' | \
|
||||
head -n 1)
|
||||
echo "vers=$LATEST" >> "$GITHUB_OUTPUT"
|
||||
- name: Update VERS in install.sh
|
||||
run: |
|
||||
|
||||
@@ -139,8 +139,8 @@ base_project_h7 = {
|
||||
# Common autogenerated includes
|
||||
with open("board/obj/gitversion.h", "w") as f:
|
||||
version = get_version(BUILDER, BUILD_TYPE)
|
||||
f.write(f'extern const uint8_t gitversion[{len(version)}];\n')
|
||||
f.write(f'const uint8_t gitversion[{len(version)}] = "{version}";\n')
|
||||
f.write(f'extern const uint8_t gitversion[{len(version)+1}];\n')
|
||||
f.write(f'const uint8_t gitversion[{len(version)+1}] = "{version}";\n')
|
||||
|
||||
with open("board/obj/version", "w") as f:
|
||||
f.write(f'{get_version(BUILDER, BUILD_TYPE)}')
|
||||
|
||||
@@ -502,11 +502,8 @@ static void usb_setup(void) {
|
||||
control_req.length = setup.b.wLength.w;
|
||||
|
||||
resp_len = comms_control_handler(&control_req, response);
|
||||
// response pending if -1 was returned
|
||||
if (resp_len != -1) {
|
||||
USB_WritePacket(response, MIN(resp_len, setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
}
|
||||
USB_WritePacket(response, MIN(resp_len, setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
case 0xd6:
|
||||
COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE);
|
||||
memcpy(resp, gitversion, sizeof(gitversion));
|
||||
resp_len = sizeof(gitversion);
|
||||
resp_len = sizeof(gitversion) - 1U;
|
||||
break;
|
||||
// **** 0xd8: reset ST
|
||||
case 0xd8:
|
||||
|
||||
@@ -12,7 +12,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("--all", action="store_true", help="Recover all panda jungle devices")
|
||||
args = parser.parse_args()
|
||||
|
||||
subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) {board_path}", shell=True)
|
||||
subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) .", shell=True)
|
||||
|
||||
if args.all:
|
||||
serials = PandaJungle.list()
|
||||
|
||||
@@ -13,7 +13,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("--all", action="store_true", help="Recover all panda jungle devices")
|
||||
args = parser.parse_args()
|
||||
|
||||
subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) {board_path}", shell=True)
|
||||
subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) .", shell=True)
|
||||
|
||||
serials = PandaJungle.list() if args.all else [None]
|
||||
for s in serials:
|
||||
|
||||
@@ -131,11 +131,6 @@ class Panda:
|
||||
|
||||
INTERNAL_DEVICES = (HW_TYPE_TRES, HW_TYPE_CUATRO)
|
||||
|
||||
MAX_FAN_RPMs = {
|
||||
HW_TYPE_TRES: 6600,
|
||||
HW_TYPE_CUATRO: 5000,
|
||||
}
|
||||
|
||||
HARNESS_STATUS_NC = 0
|
||||
HARNESS_STATUS_NORMAL = 1
|
||||
HARNESS_STATUS_FLIPPED = 2
|
||||
@@ -149,9 +144,9 @@ class Panda:
|
||||
self._can_speed_kbps = can_speed_kbps
|
||||
|
||||
if cli and serial is None:
|
||||
self._connect_serial = self._cli_select_panda()
|
||||
self._connect_serial = self._cli_select_panda()
|
||||
else:
|
||||
self._connect_serial = serial
|
||||
self._connect_serial = serial
|
||||
|
||||
# connect and set mcu type
|
||||
self.connect(claim)
|
||||
|
||||
@@ -9,6 +9,6 @@ if __name__ == "__main__":
|
||||
while True:
|
||||
p.set_fan_power(power)
|
||||
time.sleep(5)
|
||||
print("Power: ", power, "RPM:", str(p.get_fan_rpm()), "Expected:", int(6500 * power / 100))
|
||||
print("Power: ", power, "RPM:", str(p.get_fan_rpm()))
|
||||
power += 10
|
||||
power %= 110
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import time
|
||||
import threading
|
||||
|
||||
from panda import Panda
|
||||
|
||||
def drain_serial(p):
|
||||
ret = []
|
||||
while True:
|
||||
d = p.serial_read(0)
|
||||
if len(d) == 0:
|
||||
break
|
||||
ret.append(d)
|
||||
return ret
|
||||
|
||||
|
||||
fan_cmd = 0.
|
||||
|
||||
def logger(event):
|
||||
# requires a build with DEBUG_FAN
|
||||
with Panda(claim=False) as p, open('/tmp/fan_log', 'w') as f:
|
||||
power = None
|
||||
target_rpm = None
|
||||
rpm_fast = None
|
||||
t = time.monotonic()
|
||||
|
||||
drain_serial(p)
|
||||
while not event.is_set():
|
||||
p.set_fan_power(fan_cmd)
|
||||
|
||||
for l in drain_serial(p)[::-1]:
|
||||
ns = l.decode('utf8').strip().split(' ')
|
||||
if len(ns) == 4:
|
||||
target_rpm, rpm_fast, power = (int(n, 16) for n in ns)
|
||||
break
|
||||
|
||||
dat = {
|
||||
't': time.monotonic() - t,
|
||||
'cmd_power': fan_cmd,
|
||||
'pwm_power': power,
|
||||
'target_rpm': target_rpm,
|
||||
'rpm_fast': rpm_fast,
|
||||
'rpm': p.get_fan_rpm(),
|
||||
}
|
||||
f.write(json.dumps(dat) + '\n')
|
||||
time.sleep(1/16.)
|
||||
p.set_fan_power(0)
|
||||
|
||||
def get_overshoot_rpm(p, power):
|
||||
global fan_cmd
|
||||
|
||||
# make sure the fan is stopped completely
|
||||
fan_cmd = 0.
|
||||
while p.get_fan_rpm() > 100:
|
||||
time.sleep(0.1)
|
||||
time.sleep(3)
|
||||
|
||||
# set it to 30% power to mimic going onroad
|
||||
fan_cmd = power
|
||||
max_rpm = 0
|
||||
max_power = 0
|
||||
for _ in range(70):
|
||||
max_rpm = max(max_rpm, p.get_fan_rpm())
|
||||
max_power = max(max_power, p.health()['fan_power'])
|
||||
time.sleep(0.1)
|
||||
|
||||
# tolerate 10% overshoot
|
||||
expected_rpm = Panda.MAX_FAN_RPMs[bytes(p.get_type())] * power / 100
|
||||
overshoot = (max_rpm / expected_rpm) - 1
|
||||
|
||||
return overshoot, max_rpm, max_power
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
event = threading.Event()
|
||||
threading.Thread(target=logger, args=(event, )).start()
|
||||
|
||||
try:
|
||||
p = Panda()
|
||||
for power in range(10, 101, 10):
|
||||
overshoot, max_rpm, max_power = get_overshoot_rpm(p, power)
|
||||
print(f"Fan power {power}%: overshoot {overshoot:.2%}, Max RPM {max_rpm}, Max power {max_power}%")
|
||||
finally:
|
||||
event.set()
|
||||
@@ -5,28 +5,30 @@ from panda import Panda
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.test_panda_types(Panda.INTERNAL_DEVICES),
|
||||
pytest.mark.test_panda_types([Panda.HW_TYPE_TRES])
|
||||
]
|
||||
|
||||
MAX_RPM = 5000
|
||||
|
||||
@pytest.mark.timeout(2*60)
|
||||
def test_fan_curve(p):
|
||||
# ensure fan curve is (roughly) linear
|
||||
|
||||
for power in (30, 50, 80, 100):
|
||||
p.set_fan_power(0)
|
||||
while p.get_fan_rpm() > 0:
|
||||
time.sleep(0.1)
|
||||
|
||||
# wait until fan spins up, then wait a bit more for the RPM to converge
|
||||
rpms = []
|
||||
for power in (30, 70, 100):
|
||||
# wait until fan spins up
|
||||
p.set_fan_power(power)
|
||||
for _ in range(20):
|
||||
time.sleep(1)
|
||||
if p.get_fan_rpm() > 1000:
|
||||
break
|
||||
time.sleep(5)
|
||||
time.sleep(2) # wait for RPM to converge
|
||||
rpms.append(p.get_fan_rpm())
|
||||
|
||||
print(rpms)
|
||||
diffs = [b - a for a, b in zip(rpms, rpms[1:])]
|
||||
assert all(x > 0 for x in diffs), f"Fan RPMs not strictly increasing: {rpms=}"
|
||||
assert rpms[-1] > (0.75*MAX_RPM)
|
||||
|
||||
expected_rpm = Panda.MAX_FAN_RPMs[bytes(p.get_type())] * power / 100
|
||||
assert 0.75 * expected_rpm <= p.get_fan_rpm() <= 1.25 * expected_rpm
|
||||
|
||||
def test_fan_cooldown(p):
|
||||
# if the fan cooldown doesn't work, we get high frequency noise on the tach line
|
||||
@@ -35,5 +37,5 @@ def test_fan_cooldown(p):
|
||||
time.sleep(3)
|
||||
p.set_fan_power(0)
|
||||
for _ in range(5):
|
||||
assert p.get_fan_rpm() <= Panda.MAX_FAN_RPMs[bytes(p.get_type())]
|
||||
assert p.get_fan_rpm() <= MAX_RPM*2
|
||||
time.sleep(0.5)
|
||||
|
||||
Reference in New Issue
Block a user