You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When the satellite comes out of its pod various things need to happen! The following is a rough timeline of what the flight software needs to do from a cold start.
Design Notes
This is an extremely important subroutine for the flight software. It's a tricky one too because it needs to allocate time for a handling and deployment delay without creating a situation where those delays occur every time the satellite reboots (potentially creating a terrible boot loop where the satellite is stuck in an inert state forever).
Furthermore, it is a known issue in V1.X PROVES Kits that there is a fundamental design flaw with the burn wire circuit (used to deploy the antennas) where overuse of them can cause the circuit to "burn through" and cause a brown out (the whole satellite losing power) due to a trigger of the overcurrent protection circuit. If we underuse the burn wire though, the fishing line won't be cut and the antennas will not actually deploy.
In the original PyCubed codebase you just had to guess what the correct burn wire settings are and try to fire it correctly the first time. We've updated it slightly to allow for multiple attempts and try to use NVM (Non-Volatile Memory) flags to maintain a count of attempts and brownouts across resets.
Example Circuit Python Implementation
Within the pysquared.py class the following flags are setup in NVM (Non-Volatile Memory):
Of particular note are the f_burnarm, f_brownout, f_triedburn, and f_burned flags. These are set in NVM to protect against a loss of information in case of a brownout during burn wire operation.
In main.py the satellite first enters a brief radio listening period before attempting the burn wire. This is to provide "trap door" access to sending a command to the satellite that interrupts the code in case of a looping critical failure during the burn wire routine. The satellite then proceeds as such:
whilec.burnedisFalseandtries<3:
debug_print("Burn attempt try: "+str(tries+1))
iftries==0:
debug_print("Loitering for "+str(loiter_time) +" seconds")
try:
c.neopixel[0] = (0,0,0)
purple= (200, 8, 200)
led_off= (0,0,0)
forstepinrange(0,loiter_time):
c.neopixel[0] =purpletime.sleep(0.5)
c.neopixel[0] =led_offtime.sleep(0.5)
debug_print(f"Entering full flight software in... {loiter_time-step} seconds")
exceptExceptionase:
debug_print("Error in Loiter Sequence: "+''.join(traceback.format_exception(e)))
try:
dutycycle=dutycycle+0.02done=c.smart_burn('1',dutycycle)
tries+=1except:
debug_print("couldnt burn on try "+str(tries+1))
ifdoneisTrue:
debug_print("attempt passed without error!")
ifc.burnedisFalseandtries>=2:
debug_print("Ran Out of Smart Burn Attempts. Will Attempt automated burn...")
wait=0while(wait<5):
wait+=1time.sleep(1)
c.burn('1',0.28,1000,2)
else:
passelse:
debug_print("burn failed miserably!")
break
The smart_burn() function is one of the lengthier ones on the satellite and is provided here for reference:
defsmart_burn(self,burn_num,dutycycle=0.1):
""" Operate burn wire circuits. Wont do anything unless the a nichrome burn wire has been installed. IMPORTANT: See "Burn Wire Info & Usage" of https://pycubed.org/resources before attempting to use this function! burn_num: (string) which burn wire circuit to operate, must be either '1' or '2' dutycycle: (float) duty cycle percent, must be 0.0 to 100 freq: (float) frequency in Hz of the PWM pulse, default is 1000 Hz duration: (float) duration in seconds the burn wire should be on """freq=1000distance1=0distance2=0#self.dist=self.distance()try:
# convert duty cycle % into 16-bit fractional up timedtycycl=int((dutycycle/100)*(0xFFFF))
self.debug_print('----- SMART BURN WIRE CONFIGURATION -----')
self.debug_print('\tFrequency of: {}Hz\n\tDuty cycle of: {}% (int:{})'.format(freq,(100*dtycycl/0xFFFF),dtycycl))
# create our PWM object for the respective pin# not active since duty_cycle is set to 0 (for now)if'1'inburn_num:
burnwire=pwmio.PWMOut(board.BURN_ENABLE, frequency=freq, duty_cycle=0)
else:
returnFalsetry:
distance1=self.distance()
self.debug_print(str(distance1))
ifdistance1>self.dist+2anddistance1>4orself.f_triedburn==True:
self.burned=Trueself.f_brownout=TrueraiseTypeError("Wire seems to have burned and satellite browned out")
else:
self.dist=int(distance1)
self.burnarm=Trueifself.burnarm:
self.burnarm=Falseself.f_triedburn=True# Configure the relay control pin & open relayself.RGB=(0,165,0)
self._relayA.drive_mode=digitalio.DriveMode.PUSH_PULLself.RGB=(255,165,0)
self._relayA.value=1# Pause to ensure relay is opentime.sleep(0.5)
#Start the Burnburnwire.duty_cycle=dtycycl#Burn Timerstart_time=time.monotonic()
#Monitor the burnwhilenotself.burned:
distance2=self.distance()
self.debug_print(str(distance2))
ifdistance2>distance1+1ordistance2>10:
self._relayA.value=0burnwire.duty_cycle=0self.burned=Trueself.f_triedburn=Falseelse:
distance1=distance2time_elapsed=time.monotonic() -start_timeprint("Time Elapsed: "+str(time_elapsed))
iftime_elapsed>4:
self._relayA.value=0burnwire.duty_cycle=0self.burned=Falseself.RGB=(0,0,255)
time.sleep(10)
self.f_triedburn=Falsebreaktime.sleep(5)
distance2=self.distance()
else:
passifdistance2>distance1+2ordistance2>10:
self.burned=Trueself.f_triedburn=FalseexceptExceptionase:
self.debug_print("Error in Burn Sequence: "+''.join(traceback.format_exception(e)))
self.debug_print("Error: "+str(e))
if"no attribute 'LiDAR'"instr(e):
self.debug_print("Burning without LiDAR")
time.sleep(120) #Set to 120 for flightself.burnarm=Falseself.burned=Trueself.f_triedburn=Trueself.burn("1",dutycycle,freq,4)
time.sleep(5)
# Clean upself._relayA.value=0burnwire.duty_cycle=0self.RGB=(0,0,0)
#burnwire.deinit()self._relayA.drive_mode=digitalio.DriveMode.OPEN_DRAINreturnTrueexceptExceptionase:
self.debug_print("Error with Burn Wire: "+''.join(traceback.format_exception(e)))
returnFalsefinally:
self._relayA.value=0burnwire.duty_cycle=0self.RGB=(0,0,0)
burnwire.deinit()
self._relayA.drive_mode=digitalio.DriveMode.OPEN_DRAIN
Development Plan
We probably need to try and get this implemented first in PicoSDK and then translate these functions over to F'.
The text was updated successfully, but these errors were encountered:
Proposed Features
When the satellite comes out of its pod various things need to happen! The following is a rough timeline of what the flight software needs to do from a cold start.
Design Notes
This is an extremely important subroutine for the flight software. It's a tricky one too because it needs to allocate time for a handling and deployment delay without creating a situation where those delays occur every time the satellite reboots (potentially creating a terrible boot loop where the satellite is stuck in an inert state forever).
Furthermore, it is a known issue in V1.X PROVES Kits that there is a fundamental design flaw with the burn wire circuit (used to deploy the antennas) where overuse of them can cause the circuit to "burn through" and cause a brown out (the whole satellite losing power) due to a trigger of the overcurrent protection circuit. If we underuse the burn wire though, the fishing line won't be cut and the antennas will not actually deploy.
In the original PyCubed codebase you just had to guess what the correct burn wire settings are and try to fire it correctly the first time. We've updated it slightly to allow for multiple attempts and try to use NVM (Non-Volatile Memory) flags to maintain a count of attempts and brownouts across resets.
Example Circuit Python Implementation
Within the
pysquared.py
class the following flags are setup in NVM (Non-Volatile Memory):Of particular note are the
f_burnarm
,f_brownout
,f_triedburn
, andf_burned
flags. These are set in NVM to protect against a loss of information in case of a brownout during burn wire operation.In
main.py
the satellite first enters a brief radio listening period before attempting the burn wire. This is to provide "trap door" access to sending a command to the satellite that interrupts the code in case of a looping critical failure during the burn wire routine. The satellite then proceeds as such:The
smart_burn()
function is one of the lengthier ones on the satellite and is provided here for reference:Development Plan
We probably need to try and get this implemented first in PicoSDK and then translate these functions over to F'.
The text was updated successfully, but these errors were encountered: