#!/usr/bin/env python #import subprocess import time from time import sleep #import os import sys from os import system from os import path from PIL import Image, ImageDraw, ImageFont, ImageColor import serial import random import subprocess def output(pin, value): command = "gpio -g write " + str(pin) + " " + str(value) system(command) print(command) def uptime_seconds(): try: system("sudo cat /proc/uptime > /home/pi/CubeSatSim/uptime") file = open("/home/pi/CubeSatSim/uptime") up = file.read().split(" ")[0] print(up) uptime = float(up) print(uptime) file.close() return uptime except Exception as e: print(f"An error occurred: {e}") print(" failed") def input(pin): # command = "gpio -g read " + str(pin) query = ["gpio", "-g", "read", str(pin)] # Read GPIO pin command = "gpio -g read " + str(pin) try: result = subprocess.run(query, capture_output=True, text=True, check=True) # print(f"Command run was: {query}") # print("Sucess!") # print(f"Output of the command (stdout): {result.stdout}") # print(f"{command}: {result.stdout}") return int(result.stdout) except subprocess.CalledProcessError as e: # print(f"Command failed with return code: {e.returncode}") # print(f"Command run was: {e.cmd}") # print(f"Output of the command (stdout): {e.stdout}") # print(f"Error output of the command (stderr): {e.stderr}") print(f"{command}: -1") return -1 def setup(pin, config): if config == "in" or config == "out" or config == "up" or config == "down": command = "gpio -g mode " + str(pin) + " " + config system(command) print(command) else: print(f"Unknown gpio setup configuration: {config}") def blink(times): powerPin = 16 for i in range(times): system("gpio -g write " + str(powerPin) + " 0") # blink two times sleep(0.1) system("gpio -g write " + str(powerPin) + " 1") sleep(0.1) def sim_failure_check(): try: global card global cam_fail global sim_mode global sim_config cam_fail = False file = open("/home/pi/CubeSatSim/failure_mode.txt") fail_mode = int(file.read(2)) # print("Fail_mode: ") # print(fail_mode) if (fail_mode == 11): card = "Device" # Change audio so no FM audio plays print("Failure mode no FM audio") sim_mode = True elif (fail_mode == 7): cam_fail = True print("Failure mode camera fail") sim_mode = True card = "Headphones" elif (fail_mode == -1): print("No failure mode") card = "Headphones" if sim_config: sim_mode = True else: print("Other failure mode") card = "Headphones" sim_mode = True except: print("No failure mode") card = "Headphones" if sim_config: sim_mode = True def battery_saver_check(): try: global txc f = open("/home/pi/CubeSatSim/battery_saver", "r") f.close() txc = False print("Safe Mode!") print("battery saver activated") except: print("battery saver not activated") # txc = True def blink(times): powerPin = 16 for i in range(times): output(powerPin, 0) # blink sleep(0.1) output(powerPin, 1) sleep(0.1) def increment_mode(): print("increment mode") powerPin = 16 try: file = open("/home/pi/CubeSatSim/.mode") mode = file.read(1) except: # mode = "f" if (debug_mode == 1): print("Can't open .mode file") # , defaulting to FSK") file.close() print("Mode is: ") print(mode) if (mode == 'a'): mode = 'f' blink(2) sleep(2.5) elif (mode == 'f'): mode = 'b' blink(3) sleep(2.5) elif (mode == 'b'): mode = 's' blink(4) sleep(2.5) elif (mode == 's'): mode = 'm' blink(5) sleep(2.5) else: mode = 'a' blink(1) sleep(2.5) try: file = open("/home/pi/CubeSatSim/.mode", "w") count_string = str(command_count) file.write(mode) file.close() print(".mode file written") output(txLed, 0) output(powerPin, 0) print("sudo reboot -h now") setup(powerPin, "out") output(powerPin, 0); # system("reboot -h now") # release = True; print("Changing mode now") # system("/home/pi/CubeSatSim/config -" + mode) system("reboot -h now") sleep(10); except: print("can't write to .mode file") def camera_photo(): global cam_fail global os_status sim_failure_check() system("sudo rm /home/pi/CubeSatSim/camera_out.jpg") stored_image = False try: if os_status == "bookworm": system("rpicam-still -o /home/pi/CubeSatSim/camera_out.jpg --width 320 --height 256") # > /dev/null 2>&1") else: system("raspistill -o /home/pi/CubeSatSim/camera_out.jpg -w 320 -h 256") f = open("/home/pi/CubeSatSim/camera_out.jpg") f.close() print("Photo taken") if (cam_fail == True): system("cp /home/pi/CubeSatSim/sstv//sstv_image_2_320_x_256.jpeg /home/pi/CubeSatSim/camera_out.jpg") print("Using stored image") stored_image = True except: system("cp /home/pi/CubeSatSim/sstv//sstv_image_2_320_x_256.jpeg /home/pi/CubeSatSim/camera_out.jpg") print("Using stored image") stored_image = True if (stored_image == False): file='/home/pi/CubeSatSim/camera_out.jpg' font1 = ImageFont.truetype('DejaVuSerif.ttf', 20) font2 = ImageFont.truetype('DejaVuSerif-Bold.ttf', 16) try: filep = open("/home/pi/CubeSatSim/telem_string.txt") telem_string = filep.readline() except: telem_string = "" if (debug_mode == 1): print("Can't read telem_string.txt") print(telem_string) img = Image.open(file) draw = ImageDraw.Draw(img) # draw.text((10, 10), callsign, font=font2, fill='white') # draw.text((120, 10), telem_string, font=font2, fill='white') draw.text((12, 12), callsign, font=font1, fill='black') draw.text((10, 10), callsign, font=font1, fill='white') draw.text((112, 12), telem_string, font=font2, fill='black') # was 122 draw.text((110, 10), telem_string, font=font2, fill='white') # was 120 img.save(file) return True else: return False def program_fm(rx, tx, rxpl_value, sq, txpl_value): try: global gpsd_status global pd global ptt global two_meter_rpitx global txc global restore_txc if (gpsd_status == "active"): print("Stopping gpsd.socket") system("sudo systemctl stop gpsd.socket") print("Programming FM module!\n"); txf = float(tx) rxf = float(rx) if (txf > 144.0) and (txf < 148.0): two_meter_rpitx = True print("Transmitting in 2m band using rptix") # if (txc): # restore_txc = True # print("Restore FM with 70cm band") txc = False tx = "434.9000" # elif (two_meter_rpitx): # two_meter_rpitx = False # print("Stop transmitting in 2m bacnd using rptix") # if (restore_txc): # txc = True # restore_txc = False # print("Restoring FM with 70cm band") # print("Rebooting") # system("sudo reboot now") if (txf > 450.0) or ((txf < 420.0) and (txf > 148.0)) or (txf < 144.0) : tx = "434.9000" print("Transmit frequency out of amateur bands") if (rxf > 450.0) or (rxf < 420.0): rx = "435.0000" print("Receive frequency out of FM bounds") output(pd, 1) output (ptt, 1) try: ser = serial.Serial("/dev/ttyAMA0", 9600) print(ser.portstr) # uhf_string = "AT+DMOSETGROUP=0," + rx +"," + tx + ",0,3,0,0\r\n" uhf_string = "AT+DMOSETGROUP=0," + rx + "," + tx + "," + rxpl_value + "," + sq + "," + txpl_value + ",0\r\n" print(uhf_string) for i in range(6): # ser.write(b"AT+DMOSETGROUP=0,435.0000,434.9000,0,3,0,0\r\n") ser.write(uhf_string.encode()) sleep(0.1) ser.close() ser = serial.Serial("/dev/ttyAMA0", 115200) # reset back to 115200 for cubesatsim code for payload sensor data except Exception as e: print(f"An error occurred: {e}") print("Error in serial write") # output(pd, 0) # Don't turn off receiver if (gpsd_status == "active"): print("Restarting gpsd.socket") system("sudo systemctl restart gpsd.socket") except Exception as e: print(f"An error occurred: {e}") print("program_fm failed") def start_repeater(tx_freq_hz, rx_freq_hz): global txLed print("Starting repeater") if abs(rx_freq_hz - 3 * tx_freq_hz) < 10000: tx_freq_hz = tx_freq_hz + 30000 print("Adjusting Repeater TX frequency to avoid 3rd harmonic RX") output(txLed, 1) txr = "{:.3f}".format(tx_freq_hz/1e3) print(txr) system("sudo nc -l 8011 | csdr convert_i16_f | csdr gain_ff 4000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + txr + " > /dev/null 2>&1 &") sleep(0.5) system("sudo arecord -D shared_mic -r48000 -fS16_LE -c1 | nc localhost 8011 &") def stop_repeater(): global txLed # print("No carrier detected, stopping repeater") output(txLed, 0) system("sudo rpitx -i null > /dev/null 2>&1") system("sudo killall -9 arecord > /dev/null 2>&1") system("sudo killall -9 nc > /dev/null 2>&1") # system("sudo killall -9 rpitx > /dev/null 2>&1") print("Resetting audio") system("sudo /etc/init.d/alsa-utils stop") system("sudo /etc/init.d/alsa-utils start") print("Finished resetting audio") # print("Ready to detect carrier") def update_doppler(fm="yes"): try: global start_time global tx_doppler_freq_hz global rx_doppler_freq_hz global rxpl_value global txpl_value global sq global mode global tx global rxf global txr global rigctl print("update_doppler") with open("/home/pi/CubeSatSim/frequency.txt", "r") as file: frequencies = file.read().split() tx_frequency = int(frequencies[0]) rx_frequency = int(frequencies[1]) # Not used right now as FT857 emulation only updates transmit frequency print(f"New TX Frequency: {tx_frequency}, new RX Frequency: {rx_frequency}") if rigctl: if (tx_frequency > 145955000) and (tx_frequency <= 145965000): tx_center = 145960000 # AO-91 rx_center = 435250000 print("AO-91 detected!") elif (tx_frequency > 145965000) and (tx_frequency < 145975000): tx_center = 145970000 # AO-73 is shifted up 10kHz to avoid overlap with AO-91 rx_center = 435140000 print("AO-73 detected!") elif (tx_frequency > 145795000) and (tx_frequency < 145805000): tx_center = 145800000 # ISS U/V Repeater rx_center = 437800000 print("ISS U/V detected!") elif (tx_frequency > 145945000) and (tx_frequency <= 145955000): tx_center = 145950000 # AO-7 rx_center = 432150000 print("AO-7 detected!") else: tx_center = tx_frequency rx_center = rxf * 1e6 # default RX requency print("No Satellite detected. Using default RX frequency with no doppler shift") if (rx_center != rxf * 1e6): # don't Doppler shift default RX frequency since don't know the shift tx_doppler_shift = tx_frequency - tx_center rx_doppler_shift = -1 * (rx_center/tx_center) * tx_doppler_shift new_tx_frequency = tx_frequency new_rx_frequency = rx_center + rx_doppler_shift print("Calculating RX frequency using offset from TX frequency!") print(f"Tx Doppler Shift: {tx_doppler_shift:.0f} Frequency: {new_tx_frequency:.0f}") print(f"Rx Doppler Shift: {rx_doppler_shift:.0f} Frequency: {new_rx_frequency:.0f}") else: new_tx_frequency = tx_frequency new_rx_frequency = rxf * 1e6 # default RX frequency or should we use same as tx frequency with doppler shift? print(f"Tx Frequency: {new_tx_frequency:.0f}") print(f"Rx Frequency: {new_rx_frequency:.0f}") else: new_tx_frequency = tx_frequency new_rx_frequency = rx_frequency print(f"Tx Frequency: {new_tx_frequency:.0f}") print(f"Rx Frequency: {new_rx_frequency:.0f}") if (tx_doppler_freq_hz != new_tx_frequency) or (rx_doppler_freq_hz != new_rx_frequency): tx_doppler_freq_hz = new_tx_frequency rx_doppler_freq_hz = new_rx_frequency print("Applying Doppler shift!") # print(f"Tx Doppler shift: {tx_doppler_freq_hz:.0f}") # rx_doppler_freq_hz = rx_doppler_start_hz + rx_doppler_shift_hz # print(f"Tx Doppler shift: {tx_doppler_freq_hz:.0f}") rx = "{:.4f}".format(rx_doppler_freq_hz/1e6) if (mode != 'e'): tx = "{:.4f}".format(tx_doppler_freq_hz/1e6) # print(tx) else: txr = "{:.3f}".format(tx_doppler_freq_hz/1e6) if (fm != "no"): program_fm(rx,tx,rxpl_value,sq,txpl_value) else: print("Not applying Doppler shift!") except Exception as e: print(f"An error occurred: {e}") print("update_doppler failed") morse_table = [ # 0-9, A-Z only by (ASCII - 48) [ 3, 3, 3, 3, 3, 0 ], # 0 [ 1, 3, 3, 3, 3, 0 ], # 1 [ 1, 1, 3, 3, 3, 0 ], # 2 [ 1, 1, 1, 3, 3, 0 ], # 3 [ 1, 1, 1, 1, 3, 0 ], # 4 [ 1, 1, 1, 1, 1, 0 ], # 5 [ 3, 1, 1, 1, 1, 0 ], # 6 [ 3, 3, 1, 1, 1, 0 ], # 7 [ 3, 3, 3, 1, 1, 0 ], # 8 [ 3, 3, 3, 3, 1, 0 ], # 9 [ 0, 0, 0, 0, 0, 0 ], # - [ 0, 0, 0, 0, 0, 0 ], # - [ 0, 0, 0, 0, 0, 0 ], # - [ 0, 0, 0, 0, 0, 0 ], # - [ 0, 0, 0, 0, 0, 0 ], # - [ 0, 0, 0, 0, 0, 0 ], # - [ 0, 0, 0, 0, 0, 0 ], # - [ 1, 3, 0, 0, 0, 0 ], # A [ 3, 1, 1, 1, 0, 0 ], # B [ 3, 1, 3, 1, 0, 0 ], # C [ 3, 1, 1, 0, 0, 0 ], # D [ 1, 0, 0, 0, 0, 0 ], # E [ 1, 1, 3, 1, 0, 0 ], # F [ 3, 3, 1, 0, 0, 0 ], # G [ 1, 1, 1, 1, 0, 0 ], # H [ 1, 1, 0, 0, 0, 0 ], # I [ 1, 3, 3, 3, 0, 0 ], # J [ 3, 1, 3, 0, 0, 0 ], # K [ 1, 3, 1, 1, 0, 0 ], # L [ 3, 3, 0, 0, 0, 0 ], # M [ 3, 1, 0, 0, 0, 0 ], # N [ 3, 3, 3, 0, 0, 0 ], # O [ 1, 3, 3, 1, 0, 0 ], # P [ 3, 3, 1, 3, 0, 0 ], # Q [ 1, 3, 1, 0, 0, 0 ], # R [ 1, 1, 1, 0, 0, 0 ], # S [ 3, 0, 0, 0, 0, 0 ], # T [ 1, 1, 3, 0, 0, 0 ], # U [ 1, 1, 1, 3, 0, 0 ], # V [ 1, 3, 3, 0, 0, 0 ], # W [ 3, 1, 1, 3, 0, 0 ], # X [ 3, 1, 3, 3, 0, 0 ], # Y [ 3, 3, 1, 1, 0, 0 ] # Z ] def cw_transmit_fm(morse, tx): global txLed # global no_command global debug_mode # global sim_mode # global callsign # global tx # global txr try: output(txLed, 1) print("Transmit FM CW " + morse) # status = "" # if not no_command: # status = status + " C" # if sim_mode: # status = status + " S" # if (mode != 'e'): if (debug_mode == 1): system("echo 'hi hi de " + morse + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3") else: system("echo 'hi hi de " + morse + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") # else: # if (debug_mode == 1): # system("echo 'hi hi de " + morse + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + txr + "e3") # else: # system("echo 'hi hi de " + morse + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + txr + "e3 > /dev/null 2>&1") output(txLed, 0) except Exception as e: print(f"An error occurred: {e}") print("cw_transmit_fm failed") def cw_transmit_string(string): global morse_timing for character in string: if (character != ' '): update_doppler() cw_transmit_char(character); else: sleep(7.0 * morse_timing); def cw_transmit_char(character): global morse_timing # update_doppler("no") i = 0 duration = morse_table[(ord(character.upper()) - ord('0')) % 44][i] if duration == 1: duration = 1.2 # print(duration) while (duration != 0): transmit_carrier(duration * morse_timing) sleep(morse_timing * 0.4) # 6) i=i+1 duration = morse_table[(ord(character.upper()) - ord('0')) % 44][i] if duration == 1: duration = 1.2 sleep(morse_timing * 2.0) # 3) # 1.5); def transmit_carrier(duration): global tx_doppler_freq_hz global txLed update_doppler("no") command = "timeout -k 0.5 " + str(duration) + " sudo tune -f " + str(tx_doppler_freq_hz) + " > /dev/null 2>&1" # 434.9e6 start = "sudo tune -f " + str(tx_doppler_freq_hz) + " &" # + " & > /dev/null 2>&1" # 434.9e6 stop = "sudo rpitx -f 434.9e6 &" # killrpitx = "sudo killall -9 rpitx &" killtune = "sudo killall -9 tune &" output(txLed, 1) # system(start) system(command) # sleep(duration) # system(stop) output(txLed, 0) # system(killrpitx) # system(killtune) print("CubeSatSim v2.2 transmit.py starting...") system("sudo systemctl restart frequency") pd = 21 ptt = 20 txc_pin = 7 squelch = 6 green = 16 powerPin = 16 morse_timing = 0.09 # 0.1 two_meter_rpitx = False restore_txc = False command_tx = True setup(13, "up") setup(12, "up") setup(27, "up") setup(txc_pin, "up") setup(green, "out") output(powerPin, 1) transmit = False txLed = 27 if input(12) == False: print("LPF present") transmit = True else: print("No LPF") setup(txLed, "out") setup(pd, "out") #output(pd, 1) output(pd, 0) setup(ptt, "out") output(ptt, 1) txc = False if input(txc_pin) == False: print("TXC is present") txc = True else: print("TXC not present") # False # forcing it off output(txLed, 1) sleep(1) output(txLed, 0) battery_saver_check() # print(1) print(txLed) debug_mode = 0 # change to 1 to debug transmit skip = False tx_doppler_freq_hz = 0 rx_doppler_freq_hz = 0 if __name__ == "__main__": mode = "y" if (len(sys.argv)) > 1: # print("There are arguments!") if (('d' == sys.argv[1]) or ('-d' in sys.argv[1])): debug_mode = 1 elif (('x' == sys.argv[1]) or ('-x' in sys.argv[1])): mode = "x" print("Forcing APRS mode") elif (('s' == sys.argv[1]) or ('-s' in sys.argv[1])): skip = True print("Skipping delay and CW ID") print(transmit) uptime_time = 55 # 55 second boot time if Pi Zero try: f = open("/home/pi/CubeSatSim/pi_zero2", "r") f.close() print("Pi Zero 2 detected!") uptime_time = 30 # 30 second boot time if Pi Zero 2 except: print("Pi Zero 2 not detected") # try: # system("sudo cat /proc/uptime > /home/pi/CubeSatSim/uptime") # file = open("/home/pi/CubeSatSim/uptime") # up = file.read().split(" ")[0] # print(up) # uptime = float(up) # print(uptime) if (uptime_seconds() < uptime_time): print("Uptime < threshold seconds") else: print("Uptime > threshold seconds") print("Skip CW ID") skip = True # file.close() # except: # print("Can't open /proc/uptime") print(skip) if ( mode == "y"): try: file = open("/home/pi/CubeSatSim/.mode") mode = file.read(1) except: mode = "f" if (debug_mode == 1): print("Can't open .mode file, defaulting to FSK") print("Mode is: ") print(mode) try: file = open("/home/pi/CubeSatSim/beacon_off") file.close() command_tx = False except: command_tx = True if (debug_mode == 1): print("Can't open beacon_off file, defaulting to False") print("Command_tx: ") print(command_tx) if (mode != "p") or (command_tx == False): system("sudo systemctl stop pacsatsim") try: file = open("/home/pi/CubeSatSim/command_count.txt", "r") string = file.read() command_count = int(string) except: command_count = 0 if (debug_mode == 1): print("Can't open command_count file, setting to 0") file = open("/home/pi/CubeSatSim/command_count.txt", "w") count_string = str(command_count) file.write(count_string) file.close() print("Command_count: ") print(command_count) tx_value = '0' rx_value = '0' sq = '0' tx = '434.9000' rx = '435.0000' txr = '144.9000' sim_mode = False sim_config = False hab_mode = False doppler_mode = False rigctl = False try: file = open("/home/pi/CubeSatSim/sim.cfg") # callsign = file.readline().split(" ")[0] config = file.readline().split() callsign = config[0] if len(config) > 4: if config[4] == 'y' or config[4] == 'yes': sim_mode = True sim_config = True print("Simulated telemetry mode is configured") else: try: if path.isfile("/home/pi/CubeSatSim/sim_mode_auto"): print("Simulated telemetry mode automatically turned on!") sim_mode = True sim_config = True except: if (debug_mode == 1): print("/home/pi/CubeSatSim/sim_mode_auto not found") if len(config) > 5: if (mode != 'p') and (mode != 'P'): # squelch off for Pacsat sq = config[5] print(f'squelch: {sq}') if len(config) > 6: txf = float(config[6]) tx = "{:.4f}".format(txf) txrf = 0 if (mode == 'e'): if (txf > 420.0) and (txf < 450.0): txrf = (txf - 290.0) # - 0.1 # Cross Band Repeater mode transmit frequency in 2m band print("Repeater mode subtracting 290 MHz from TX Frequency") elif (txf > 144.0) and (txf < 148.0): txrf = txf # Cross Band Repeater mode transmit frequency is already in 2m band print("Repeater mode using 2m TX Frequency") else: txf = 144.9 txr = "{:.4f}".format(txrf) print("Transmit frequency: ",txr) else: print("Transmit frequency: ",tx) if len(config) > 7: rxf = float(config[7]) rx = "{:.4f}".format(rxf) print(rx) if len(config) > 8: if config[8] == 'y' or config[8] == 'yes': hab_mode = True print("Balloon (HAB) mode is configured.") if len(config) > 9: rxpl = float(config[9]) # print(rxpl) # print( "{:.0f}".format(rxpl)) rxpl_value = "{:.0f}".format(rxpl) print(rxpl_value) if len(config) > 10: txpl = float(config[10]) # print(txpl) # print( "{:.0f}".format(txpl)) txpl_value = "{:.0f}".format(txpl) print(txpl_value) if len(config) > 13: if config[13] == 'sim': doppler_mode = True # system("sudo systemctl restart frequency") print("Simulated Doppler frequency shift is enabled.") elif config[13] == 'rig': doppler_mode = True rigctl = True # system("sudo systemctl restart frequency") print("rigctl Doppler frequency shift is enabled.") # else: # system("sudo systemctl stop rigctld") else: system("sudo systemctl stop rigctld") print(config) print # print(callsign) print(sq) # if sq == '8': # print("squelch set to 8, no command input!") # no_command = True # else: no_command = False print(no_command) except: callsign = "AMSAT" if (debug_mode == 1): print("Can't read callsign from sim.cfg file, defaulting to AMSAT") file.close() no_command = True try: f = open("/home/pi/CubeSatSim/command_control", "r") no_command = False f.close() # setup(squelch, "up") ## pull up in case pin is not connected # if input(squelch) == False: # print("squelch not set correctly, no command input!") # else: # if (mode != 'n') and (mode != 'x'): # print("command and control is activated") # no_command = False # system("sudo systemctl start command") # else: # print("Command and control not activated since Transmit Commands mode") # txc = True # Transmit commands only works with FM transceiver, so bypass Battery Saver if activated except: print("command and control not activated") print(callsign) query = ["grep", "VERSION_CODENAME=bullseye", "/etc/os-release"] try: result = subprocess.run(query, capture_output=True, text=True, check=True) print(f"Command run was: {query}") os_status = result.stdout.strip() print(f"Output of the command (stdout): {os_status}") except subprocess.CalledProcessError as e: # print(f"Command failed with return code: {e.returncode}") print(f"Command run was: {e.cmd}") os_status = e.stdout.strip() print(f"Output of the command (stdout): {e.stdout}") # print(f"Error output of the command (stderr): {e.stderr}") if os_status != "VERSION_CODENAME=bullseye": os_status = "bookworm" else: os_status = "bullseye" print (os_status) card = "Headphones" # default using pcm audio output of Pi Zero # card = "Device" # using USB sound card for audio output query = ["sudo", "systemctl", "is-active", "gpsd.socket"] try: result = subprocess.run(query, capture_output=True, text=True, check=True) print(f"Command run was: {query}") gpsd_status = result.stdout.strip() print(f"Output of the command (stdout): {gpsd_status}") except subprocess.CalledProcessError as e: # print(f"Command failed with return code: {e.returncode}") print(f"Command run was: {e.cmd}") gpsd_status = e.stdout.strip() print(f"Output of the command (stdout): {e.stdout}") # print(f"Error output of the command (stderr): {e.stderr}") # if (mode != 'e'): program_fm(rx,tx,rxpl_value,sq,txpl_value) if ((doppler_mode == True) and (rigctl == True) and (command_tx == True) and (skip == False)) or (mode == 'e'): cw_transmit_fm(callsign + "QSY", tx) if (doppler_mode == True): # if (command_tx == True) and (skip == False): # cw_transmit_fm("QSY", tx) if (mode == 'e'): tx_doppler_start_hz = txrf * 1e6 else: tx_doppler_start_hz = txf * 1e6 tx_doppler_shift_hz = 0 print(f"Tx center frequency: {tx_doppler_start_hz}") rx_doppler_start_hz = rxf * 1e6 rx_doppler_shift_hz = 0 print(f"Rx center frequency: {rx_doppler_start_hz}") # TARGET_PASS = 85 # Maximum elevation profile # doppler_table = iss_doppler_passes[TARGET_PASS] # print(f"Pass Max Elevation: {TARGET_PASS}°") print("MODE: ") print(mode) update_doppler() if (mode == 'm') and (skip == False): print("Sleeping 15 seconds") sleep(15) # avoid CW jumping around at start result = subprocess.run("systemctl get-default | grep graphical.target", shell=True, capture_output=True, text=True) gui_result = result.stdout.strip() print(gui_result) if gui_result == "graphical.target": print("Sleep another 30 seconds") sleep(30) # sleep another 30 seconds for cpu to settle down sim_failure_check() status = "" if not no_command: status = status + " C" if sim_mode: status = status + " S" if (hab_mode == True) and (mode == 'a'): print("Don't transmit CW ID since APRS HAB mode is active") else: if (((mode == 'a') or (mode == 'b') or (mode == 'f') or (mode == 's') or (mode == 'j') or (mode == 'p') or (mode == 'P')) and (command_tx == True) and (skip == False)) or ((mode == 'e') and (command_tx == True)): # battery_saver_mode # output(txLed, 1) # print("Transmit CW ID") if (mode != 'e'): cw_transmit_fm(callsign + status, tx) # if (debug_mode == 1): # system("echo 'hi hi de " + callsign + status + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3") # else: # system("echo 'hi hi de " + callsign + status + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") else: cw_transmit_fm(callsign + status, txr) # if (debug_mode == 1): # system("echo 'hi hi de " + callsign + status + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + txr + "e3") # else: # system("echo 'hi hi de " + callsign + status + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + txr + "e3 > /dev/null 2>&1") # # output(txLed, 0) sleep(1) else: print("Don't transmit CW ID since command_tx is False or APRS mode or change of mode") if (transmit): # print 'Length: ', len(sys.argv) # if (len(sys.argv)) > 1: # print("There are arguments!") if (mode == 'a') or (mode == 'x') or (mode == 'n') or (mode == 'p') or (mode == 'P'): # command_control_check() output(pd, 1) output(ptt, 1) if (mode == 'a'): print("AFSK") elif (mode == 'p') or (mode == 'P'): if (mode == 'P'): print("Pacsat Ground Station") else: print("Pacsat") if (command_tx == True): system("sudo systemctl restart pacsatsim") print("Starting PacSatSim") output(txLed, 0) print("0") rpitx = "arecord -D plughw:CARD=Loopback,DEV=1 -f S16_LE -r 48000 -c 1 | csdr convert_s16_f | csdr gain_ff 4000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1 &" # stop_rpitx = "sudo killall -9 rpitx && sudo killall -9 arecord && sudo rpitx -m RF -f 434.9e3 > /dev/null 2>&1" stop_rpitx = "sudo killall -9 arecord && sudo rpitx -m RF -f 434.9e3 > /dev/null 2>&1" if not txc: print("txc is:") print(txc) system(stop_rpitx) # system(rpitx) print("Safe Mode!!") while (True): if (txc): sleep(0.1) while (input(ptt) != 0): sleep(0.2) output(txLed, 1) # print("1") while (input(ptt) != 1): sleep(0.2) output(txLed, 0) if (mode == 'p') and (doppler_mode): update_doppler() # print("0") else: # sleep(0.1) while (input(17) == 0): sleep(0.05) system(rpitx) output(txLed, 1) # print("1") while (input(17) == 1): sleep(0.05) system(stop_rpitx) output(txLed, 0) if (mode == 'p') and (doppler_mode): update_doppler() # "no") rpitx = "arecord -D plughw:CARD=Loopback,DEV=1 -f S16_LE -r 48000 -c 1 | csdr convert_s16_f | csdr gain_ff 4000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1 &" # print("0") # sleep(10) else: print("Transmit APRS Commands") system("sudo systemctl stop command") # while True: # sleep(0.1) # if (mode != 'n'): # system("touch /home/pi/CubeSatSim/ready") while True: try: f = open("/home/pi/CubeSatSim/ready") f.close() if (debug_mode == 1): print("Packet ready!") system("gen_packets -o /home/pi/CubeSatSim/telem.wav /home/pi/CubeSatSim/t.txt -r 48000 > /dev/null 2>&1") system("cat /home/pi/CubeSatSim/t.txt") if (command_tx == True): output(txLed, 1) if (doppler_mode == True): update_doppler() txf = tx_doppler_freq_hz / 1e6 tx = "{:.4f}".format(txf) if (txc): sim_failure_check() # output(pd, 1) sleep(0.1) # add delay before transmit output (ptt, 0) sleep(0.3) # add even more time at start system("aplay -D plughw:CARD=" + card + ",DEV=0 /home/pi/CubeSatSim/telem.wav") sleep(0.2) # add more time at end output (ptt, 1) # output(pd, 0) else: # system("echo 'AMSAT-11>APCSS:010101/hi hi ' >> t.txt") system("echo 'AMSAT-11>APCSS:010101/hi hi ' | sudo tee -a /home/pi/CubeSatSim/t.txt") if (debug_mode == 1): system("gen_packets -o /home/pi/CubeSatSim/telem.wav /home/pi/CubeSatSim/t.txt -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/telem.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3") else: system("gen_packets -o /home/pi/CubeSatSim/telem.wav /home/pi/CubeSatSim/t.txt -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/telem.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") sleep(0.1) # output (ptt, 1) # output(pd, 0) output(txLed, 0) system("sudo rm /home/pi/CubeSatSim/ready") f.close() if (debug_mode == 1): print("Ready for next packet!") sleep(0.5) except Exception as e: # print(f"An error occurred: {e}") # command_control_check() sleep(1) elif (mode == 'm'): # system("touch /home/pi/CubeSatSim/cwready") print("CW") while True: # command_control_check() output (pd, 1) output (ptt, 1) try: f = open("/home/pi/CubeSatSim/cwready") f.close() system("sudo rm /home/pi/CubeSatSim/cwready") ## ch = 1 for chan in range(7): if (doppler_mode): try: # update_doppler() filename="/home/pi/CubeSatSim/cw" + str(chan) + ".txt" print(filename) file = open(filename) cw_string = file.readline() print(cw_string) cw_transmit_string(cw_string) except Exception as e: print(f"An error occurred: {e}") print("error reading cw string " + str(chan)) else: command = "gen_packets -M 20 -o /home/pi/CubeSatSim/morse.wav /home/pi/CubeSatSim/cw" + str(chan) + ".txt -r 48000 > /dev/null 2>&1" print(command) system(command) ## chan = chan + 1 if (command_tx == True): output(txLed, 1) if (doppler_mode == True): update_doppler() txf = tx_doppler_freq_hz / 1e6 tx = "{:.4f}".format(txf) if (txc): sim_failure_check() # output (pd, 1) sleep(0.3) output (ptt, 0) system("aplay -D plughw:CARD=" + card + ",DEV=0 /home/pi/CubeSatSim/morse.wav") sleep(0.1) output (ptt, 1) # output (pd, 0) else: if (debug_mode == 1): system("cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3") else: system("cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") output(txLed, 0) # command_control_check() sleep(2) f.close() sleep(10) except: # command_control_check() # print("cw not ready") sleep(1) elif (mode == 's'): print("SSTV") # command_control_check() output (ptt, 1) output(pd, 1) try: # from picamera import PiCamera # from pysstv.sstv import SSTV # camera = PiCamera() print("Testing for camera") if os_status == "bookworm": system("rpicam-still -o /home/pi/CubeSatSim/camera_out.jpg --width 320 --height 256") # > /dev/null 2>&1") else: system("raspistill -o /home/pi/CubeSatSim/camera_out.jpg -w 320 -h 256") f = open("/home/pi/CubeSatSim/camera_out.jpg") f.close() print("Camera present") camera_present = 1 # camera.close() except: print("No camera available") print(" -> if camera plugged in, is software enabled?") camera_present = 0 # while 1: output(txLed, 0) # output (ptt, 1) # output(pd, 0) if (camera_present == 1): try: file = open("/home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg") print("First SSTV stored image detected") system("/home/pi/PiSSTVpp/pisstvpp -r 48000 -p s2 /home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg") # command_control_check() if (command_tx == True): print ("Sending SSTV image") if (doppler_mode): update_doppler() txf = tx_doppler_freq_hz / 1e6 tx = "{:.4f}".format(txf) output(txLed, 1) # battery_saver_check() if (txc): sim_failure_check() # output(pd, 1) output (ptt, 0) system("aplay -D plughw:CARD=" + card + ",DEV=0 /home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg.wav") output (ptt, 1) # output(pd, 0) else: if (debug_mode == 1): system("cat /home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg.wav | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3") else: system("cat /home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg.wav | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") output(txLed, 0) # sleep(1) except: print("image 2 did not load - copy from CubeSatSim/sstv directory") while 1: # command_control_check() camera_photo() system("/home/pi/PiSSTVpp/pisstvpp -r 48000 -p s2 /home/pi/CubeSatSim/camera_out.jpg") system("sudo rm /home/pi/CubeSatSim/camera_out.jpg > /dev/null 2>&1") if (command_tx == True): print ("Sending SSTV image") if (doppler_mode): update_doppler() txf = tx_doppler_freq_hz / 1e6 tx = "{:.4f}".format(txf) output(txLed, 1) # battery_saver_check() if (txc): # print(card) sim_failure_check() # output(pd, 1) output (ptt, 0) system("aplay -D plughw:CARD=" + card + ",DEV=0 /home/pi/CubeSatSim/camera_out.jpg.wav") output(ptt, 1) # output (pd, 0) else: if (debug_mode == 1): system("cat /home/pi/CubeSatSim/camera_out.jpg.wav | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3") else: system("cat /home/pi/CubeSatSim/camera_out.jpg.wav | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") output(txLed, 0) # output (ptt, 1) # output(pd, 0) system("sudo rm /home/pi/CubeSatSim/camera_out.jpg.wav > /dev/null 2>&1") sleep(10) else: try: # command_control_check() file = open("/home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg") print("First SSTV stored image detected") system("/home/pi/PiSSTVpp/pisstvpp -r 48000 -p s2 /home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg") # command_control_check() if (command_tx == True): print ("Sending SSTV image") if (doppler_mode): update_doppler() txf = tx_doppler_freq_hz / 1e6 tx = "{:.4f}".format(txf) output(txLed, 1) # battery_saver_check() if (txc): sim_failure_check() # output(pd, 1) output (ptt, 0) system("aplay -D plughw:CARD=" + card + ",DEV=0 /home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg.wav") output(ptt, 1) # output (pd, 0) else: if (debug_mode == 1): system("cat /home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg.wav | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3") else: system("cat /home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg.wav | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") output(txLed, 0) # output (ptt, 1) # output(pd, 0) sleep(1) except: print("image 1 did not load - copy from CubeSatSim/sstv directory") try: # command_control_check() file = open("/home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg") print("Second SSTV stored image detected") system("/home/pi/PiSSTVpp/pisstvpp -r 48000 -p s2 /home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg") while 1: if (command_tx == True): print ("Sending SSTV image") if (doppler_mode): update_doppler() txf = tx_doppler_freq_hz / 1e6 tx = "{:.4f}".format(txf) output(txLed, 1) # battery_saver_check() if (txc): sim_failure_check() # output(pd, 1) output (ptt, 0) system("aplay -D plughw:CARD=" + card + ",DEV=0 /home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg.wav") output(ptt, 1) # output (pd, 0) else: if (debug_mode == 1): system("cat /home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg.wav | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3") else: system("cat /home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg.wav | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") output(txLed, 0) # output (ptt, 1) # output(pd, 0) sleep(10) except: print("image 2 did not load - copy from CubeSatSim/sstv directory") if (txc == False): if (command_tx == True): system("(while true; do (sleep 10 && cat /home/pi/CubeSatSim/wav/sstv.wav); done) | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &") while 1: if (command_tx == True): if (doppler_mode): update_doppler() txf = tx_doppler_freq_hz / 1e6 tx = "{:.4f}".format(txf) output(txLed, 1) if (txc): sim_failure_check() # output(pd, 1) output (ptt, 0) system("aplay -D plughw:CARD=" + card + ",DEV=0 /home/pi/CubeSatSim/sstv.wav") output(ptt, 1) # output (pd, 0) else: sleep(60) output(txLed, 0) # output (ptt, 1) # output(pd, 0) sleep(10) elif (mode == 'b') or (mode == 'j'): # command_control_check() if (mode == 'b'): print("BPSK") else: print("FUNcube") if (doppler_mode): print("No doppler shift in this mode") print("turn on FM rx") output(pd, 1) output(ptt, 1) if (command_tx == True): # system("sudo nc -l 8080 | csdr convert_i16_f | csdr fir_interpolate_cc 2 | csdr dsb_fc | csdr bandpass_fir_fft_cc 0.002 0.06 0.01 | csdr fastagc_ff | sudo /home/pi/rpitx/sendiq -i /dev/stdin -s 96000 -f 434.9e6 -t float &") system("sudo nc -l 8080 | csdr convert_i16_f | csdr fir_interpolate_cc 2 | csdr dsb_fc | csdr bandpass_fir_fft_cc 0.002 0.06 0.01 | csdr fastagc_ff | sudo /home/pi/rpitx/sendiq -i /dev/stdin -s 96000 -f " + tx + "e6 -t float &") print("Turning LED on/off and listening for carrier") image_id = random.randint(0, 255) print("Initial image_id: " + str(image_id) + "\n") while 1: # print ("LED on") output(txLed, 0) sleep(0.4) # if (command_tx == False): # output(txLed, 1) # sleep(0.03) # output(txLed, 0) # command_control_check() if (command_tx == True): output(txLed, 1) if (mode == 'b'): sleep(4.2) else: # FUNcube mode image for i in range(4): # print("Checking image_file.bin") try: file = open("/home/pi/CubeSatSim/image_file.bin") file.close() # image_present = True sleep(1.0) except: # image_present = False # if (image_present == False): start = time.perf_counter() camera_photo() system("/home/pi/ssdv/ssdv -e -n -i " + str(image_id) + " -q 3 -J /home/pi/CubeSatSim/camera_out.jpg /home/pi/CubeSatSim/image_file.bin") print("image_id: " + str(image_id) + "\n") image_id = ( image_id + 1 ) % 256 print("new image_id: " + str(image_id) + "\n") elapsed_time = time.perf_counter() - start print("Elapsed time: ") print(elapsed_time) if (elapsed_time < 9): sleep(9 - time.perf_counter() + start) # else: sleep(0.6) elif (mode == 'e'): # code based on https://zr6aic.blogspot.com/2016/11/creating-2m-fm-repeater-with-raspberry.html print("Cross Band Repeater Mode") # print("Stopping command and control") # system("sudo systemctl stop command") print("turn on FM rx") output(pd, 1) output(ptt, 1) setup(squelch, "up") ## pull up in case pin is not connected # txf = float(tx) - 288.9 # print("Transmit frequency: ",txf) if (command_tx != True): print("Beacon mode off so no repeater transmission") print("Ready to detect carrier") # if (doppler_mode): # update_doppler() # txr = "{:.3f}".format(tx_doppler_freq_hz/1e6) # cw_transmit_fm(callsign + status, txr) start_time = time.perf_counter() while True: if (input(squelch) == False) and (command_tx == True): print("Carrier detected") if (doppler_mode): update_doppler() start_repeater(tx_doppler_freq_hz, rx_doppler_freq_hz) else: start_repeater(txrf * 1e6, rxf * 1e6) while (input(squelch) == False): sleep(1) print("No carrier detected") stop_repeater() if ((time.perf_counter() - start_time) > 10) and doppler_mode: update_doppler() start_time = time.perf_counter() else: print("FSK") if (doppler_mode): print("No doppler shift in this mode") print("turn on FM rx") output(pd, 1) output(ptt, 1) if (command_tx == True): system("sudo nc -l 8080 | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3 &") print("Turning LED on/off and listening for carrier") while 1: output(txLed, 0) sleep(0.4) # if (command_tx == False): # output(txLed, 1) # sleep(0.03) # output(txLed, 0) # command_control_check() if (command_tx == True): output(txLed, 1) sleep(4.2) else: print("No Low Pass Filter so no telemetry transmit. See http://cubesatsim.org/wiki for instructions on how to build the LPF.") while 1: sleep(5)