diff --git a/src/flight-software/lib/requirements.txt b/src/flight-software/lib/requirements.txt index 880dd29..2d07534 100644 --- a/src/flight-software/lib/requirements.txt +++ b/src/flight-software/lib/requirements.txt @@ -3,7 +3,6 @@ adafruit-circuitpython-asyncio @ git+https://github.com/adafruit/adafruit_circui adafruit-circuitpython-drv2605==1.3.4 adafruit-circuitpython-lis2mdl==2.1.23 adafruit-circuitpython-lsm6ds==4.5.13 -adafruit-circuitpython-mcp9808==3.3.24 adafruit-circuitpython-neopixel==6.3.12 adafruit-circuitpython-register==1.10.1 adafruit-circuitpython-rfm==1.0.3 @@ -15,3 +14,4 @@ adafruit-circuitpython-hashlib==1.4.19 Adafruit_CircuitPython_MCP230xx proves-circuitpython-rv3028 @ git+https://github.com/proveskit/PROVES_CircuitPython_RV3028@1.0.0 proves-circuitpython-sx1280 @ git+https://github.com/proveskit/CircuitPython_SX1280@1.0.3 +circuitpython-hmac @ git+https://github.com/jimbobbennett/CircuitPython_HMAC@0.2.1 diff --git a/src/flight-software/main.py b/src/flight-software/main.py index 0855078..389b9a3 100644 --- a/src/flight-software/main.py +++ b/src/flight-software/main.py @@ -11,6 +11,7 @@ from lib.pysquared.beacon import Beacon from lib.pysquared.cdh import CommandDataHandler from lib.pysquared.config.config import Config +from lib.pysquared.config.jokes_config import JokesConfig from lib.pysquared.hardware.busio import _spi_init, initialize_i2c_bus from lib.pysquared.hardware.digitalio import initialize_pin from lib.pysquared.hardware.imu.manager.lsm6dsox import LSM6DSOXManager @@ -45,6 +46,7 @@ logger.debug("Initializing Config") config: Config = Config("config.json") +jokes_config: JokesConfig = JokesConfig("jokes.json") loiter_time: int = 5 for i in range(loiter_time): @@ -138,7 +140,7 @@ 0.2, ) - cdh = CommandDataHandler(logger, config, uhf_packet_manager) + cdh = CommandDataHandler(logger, config, uhf_packet_manager, jokes_config) beacon = Beacon( logger, diff --git a/src/flight-software/repl.py b/src/flight-software/repl.py index 1cf4028..d4ecef9 100644 --- a/src/flight-software/repl.py +++ b/src/flight-software/repl.py @@ -1,3 +1,4 @@ +import json import os import time @@ -8,6 +9,7 @@ from lib.pysquared.beacon import Beacon from lib.pysquared.cdh import CommandDataHandler from lib.pysquared.config.config import Config +from lib.pysquared.config.jokes_config import JokesConfig from lib.pysquared.file_validation.manager.file_validation import FileValidationManager from lib.pysquared.hardware.burnwire.manager.burnwire import BurnwireManager from lib.pysquared.hardware.busio import _spi_init, initialize_i2c_bus @@ -22,7 +24,7 @@ from lib.pysquared.hardware.radio.manager.rfm9x import RFM9xManager from lib.pysquared.hardware.radio.manager.sx1280 import SX1280Manager from lib.pysquared.hardware.radio.packetizer.packet_manager import PacketManager -from lib.pysquared.hardware.temperature_sensor.manager.mcp9808 import MCP9808Manager +from lib.pysquared.hardware.temperature_sensor.manager.tmp112 import TMP112Manager from lib.pysquared.logger import Logger from lib.pysquared.nvm.counter import Counter from lib.pysquared.protos.power_monitor import PowerMonitorProto @@ -49,6 +51,7 @@ logger.debug("Initializing Config") config: Config = Config("config.json") +jokes_config: JokesConfig = JokesConfig("jokes.json") def get_temp(sensor): @@ -163,8 +166,7 @@ def get_temp(sensor): 0.2, ) -cdh = CommandDataHandler(logger, config, uhf_packet_manager) - +cdh = CommandDataHandler(logger, config, uhf_packet_manager, jokes_config) beacon = Beacon( logger, config.cubesat_name, @@ -278,46 +280,46 @@ def all_faces_on(): # temp_sensor6 = None # temp_sensors.append(temp_sensor6) -# TCA-connected temp sensors +# TCA-connected temp sensors (TMP112 default address 0x48) try: - sensor = MCP9808Manager(logger, tca[0], addr=27) + sensor = TMP112Manager(logger, tca[0]) # type: ignore[arg-type] temp_sensors.append(sensor) except Exception: logger.debug("WARNING!!! Temp sensor (TCA[0]) failed") temp_sensors.append(None) try: - sensor = MCP9808Manager(logger, tca[1], addr=27) + sensor = TMP112Manager(logger, tca[1]) # type: ignore[arg-type] temp_sensors.append(sensor) except Exception: logger.debug("WARNING!!! Temp sensor 1 failed") temp_sensors.append(None) try: - sensor = MCP9808Manager(logger, tca[2], addr=27) + sensor = TMP112Manager(logger, tca[2]) # type: ignore[arg-type] temp_sensors.append(sensor) except Exception: logger.debug("WARNING!!! Temp sensor 2 failed") temp_sensors.append(None) try: - sensor = MCP9808Manager(logger, tca[3], addr=27) + sensor = TMP112Manager(logger, tca[3]) # type: ignore[arg-type] temp_sensors.append(sensor) except Exception: logger.debug("WARNING!!! Temp sensor 3 failed") temp_sensors.append(None) try: - sensor = MCP9808Manager(logger, tca[5], addr=24) + sensor = TMP112Manager(logger, tca[5]) # type: ignore[arg-type] temp_sensors.append(sensor) except Exception: logger.debug("WARNING!!! Temp sensor 4 failed (Z- Face Bottom pins") temp_sensors.append(None) # these are the bottom 6 pins on the z- face connection, uncomment if that is where you plug in a face for the z- board # try: -# sensor = MCP9808Manager(logger, tca[6], addr=24) +# sensor = TMP112Manager(logger, tca[6]) # temp_sensors.append(sensor) # except Exception: # logger.debug("WARNING!!! Temp sensor 4 failed (Z- Face Top pins)") # # temp_sensors.append(None) try: - sensor = MCP9808Manager(logger, tca[7], addr=25) + sensor = TMP112Manager(logger, tca[7]) # type: ignore[arg-type] temp_sensors.append(sensor) except Exception: logger.debug("WARNING!!! Temp sensor 5 failed (Antenna Board)") @@ -337,3 +339,174 @@ def all_faces_on(): antenna_deployment = BurnwireManager( logger, burnwire_heater_enable, burnwire1_fire, enable_logic=True ) + + +def test_magnetorquer(): + print("____ Test: Magnetorquer _______") + m_val_1 = magnetometer.get_magnetic_field().value + print("Magnetorquer value (initial):", m_val_1) + print("You have 2 seconds to move the FC board") + time.sleep(2) + m_val_2 = magnetometer.get_magnetic_field().value + print("Magnetorquer value (after):", m_val_2) + diff = tuple(m_val_1[i] - m_val_2[i] for i in range(3)) + print("Difference:", diff) + return input("Is this acceptable? (Y/N): ").strip().upper() + + +def test_imu(): + print("\n____ Test: IMU Sensors _______") + imu_results = {} + # Acceleration + acc1 = imu.get_acceleration().value + print("Initial acceleration:", acc1) + print("You have 2 seconds to move the FC board") + time.sleep(2) + acc2 = imu.get_acceleration().value + print("New acceleration:", acc2) + acc_diff = tuple(acc1[i] - acc2[i] for i in range(3)) + print("Acceleration difference:", acc_diff) + imu_results["acceleration"] = input("Is this acceptable? (Y/N): ").strip().upper() + # Angular velocity + ang1 = imu.get_angular_velocity().value + print("Initial angular velocity:", ang1) + print("You have 2 seconds to move the FC board") + time.sleep(2) + ang2 = imu.get_angular_velocity().value + print("New angular velocity:", ang2) + ang_diff = tuple(ang1[i] - ang2[i] for i in range(3)) + print("Angular velocity difference:", ang_diff) + imu_results["angular_velocity"] = ( + input("Is this acceptable? (Y/N): ").strip().upper() + ) + # Temperature + temp1 = imu.get_temperature().value + print("Initial temperature:", temp1) + print("You have 10 seconds to heat the temp sensor") + time.sleep(10) + temp2 = imu.get_temperature().value + print("New temperature:", temp2) + temp_diff = temp1 - temp2 + print("Temperature difference:", temp_diff) + imu_results["temperature"] = input("Is this acceptable? (Y/N): ").strip().upper() + return imu_results + + +def test_burnwire(): + print("\n____ Test: Burnwire _______") + choice = input("Would you like to try the burnwire test (Y/N)?: ").strip().lower() + if choice == "y": + print("Burning for 5 seconds....") + antenna_deployment.burn(5) + print("Finished burning.") + return input("Did the burnwire get hot? (Y/N): ").strip().upper() + return "N/A" + + +def test_light_sensors(): + print("\n____ Test: LEDs and Light Sensors _______") + load_switches = [ + load_switch_0, + load_switch_1, + load_switch_2, + load_switch_3, + load_switch_4, + ] + light_results = {} + for i, switch in enumerate(load_switches): + print(f"\nTesting Load Switch {i}") + switch.disable_load() + led_off = input("Did a face LED turn OFF? (Y/N): ").strip().upper() + switch.enable_load() + led_on = input("Did the face LED turn ON? (Y/N): ").strip().upper() + sensor = light_sensors[i] + if sensor is not None: + lux_before = sensor.get_lux().value + print("Initial lux:", lux_before) + time.sleep(2) + lux_after = sensor.get_lux().value + print("New lux:", lux_after) + sensor_result = ( + input("Did the lux value change noticeably? (Y/N): ").strip().upper() + ) + else: + lux_before = lux_after = "N/A" + sensor_result = "N" + light_results[f"load_switch_{i}"] = { + "led_off": led_off, + "led_on": led_on, + "lux_changed": sensor_result, + } + return light_results + + +def test_radio(): + print("\n____ Test: UHF Radio _______") + message = {"command": "ping"} + print("Sending Ping Command...") + uhf_packet_manager.send(json.dumps(message).encode("utf-8")) + count = 0 + result = "N" + while count < 10: + count += 1 + b = uhf_packet_manager.listen(1) + time.sleep(1) + uhf_packet_manager.send(json.dumps(message).encode("utf-8")) + + if b is not None: + if b != b"ACK": + print("Received not ACK :") + else: + print("Received ACK response:", b.decode("utf-8")) + result = "Y" + break + return result + + +def test_battery_monitor(): + print("\n____ Test: Battery Power Monitor _______") + value_with_batteries = battery_power_monitor.get_bus_voltage().value + print("Voltage with batteries:", value_with_batteries) + input("Please unplug the batteries and press Enter when done.") + value_without_batteries = battery_power_monitor.get_bus_voltage().value + print("Voltage without batteries:", value_without_batteries) + if (value_with_batteries - value_without_batteries) >= 4.0: + print("Voltage dropped by more than 4V. PASS.") + return "Y" + else: + print("Voltage drop too small. FAIL.") + return "N" + + +def test_solar_monitor(): + print("\n____ Test: Solar Power Monitor _______") + solar_with_light = solar_power_monitor.get_bus_voltage().value + print("Voltage with light:", solar_with_light) + input("Please cover the solar panels and press Enter when ready.") + solar_without_light = solar_power_monitor.get_bus_voltage().value + print("Voltage without light:", solar_without_light) + if (solar_with_light - solar_without_light) >= 0.5: + print("Solar voltage dropped significantly. PASS.") + return "Y" + else: + print("Solar voltage did not drop enough. FAIL.") + return "N" + + +# ========== MAIN FUNCTION ========== + + +def test_all(): + results = {} + results["magnetorquer"] = test_magnetorquer() + imu_results = test_imu() + results.update({f"imu_{k}": v for k, v in imu_results.items()}) + results["burnwire"] = test_burnwire() + light_results = test_light_sensors() + results.update(light_results) + results["radio_send"] = test_radio() + results["battery_power_monitor"] = test_battery_monitor() + results["solar_power_monitor"] = test_solar_monitor() + print("\n===== FINAL RESULTS =====") + for key, val in results.items(): + print(f"{key}: {val}") diff --git a/src/ground-station/lib/requirements.txt b/src/ground-station/lib/requirements.txt index 7048407..95427a2 100644 --- a/src/ground-station/lib/requirements.txt +++ b/src/ground-station/lib/requirements.txt @@ -2,3 +2,4 @@ adafruit-circuitpython-asyncio @ git+https://github.com/adafruit/adafruit_circui adafruit-circuitpython-rfm==1.0.3 adafruit-circuitpython-ticks==1.1.1 pysquared-ground-station @ git+https://github.com/proveskit/pysquared@d1b22be#subdirectory=circuitpython-workspaces/ground-station +circuitpython-hmac @ git+https://github.com/jimbobbennett/CircuitPython_HMAC@0.2.1