diff --git a/.gitignore b/.gitignore
index 220663f21..c904aa40b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,23 @@ telem.wav
cw.txt
cwready
logr.txt
+command_control
+command_control_direwolf
+command_count.txt
+command_tx
+cw0.txt
+cw1.txt
+cw2.txt
+cw3.txt
+cw4.txt
+cw5.txt
+cw6.txt
+logc.txt
+telem.txt
+telem_string.txt
+test
+transmit_dtmf
+uptime
+beacon_off
+battery_saver
+
diff --git a/README.md b/README.md
index cd6e0db4d..8423ed4bd 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,5 @@
# CubeSatSim
-There is beta release for the new CubeSatSim hardware and software in the beta branch.
-
-### The beta hardware files are here:
-https://CubeSatSim.org/hardware-beta
-
-### The beta wiki instructions are here:
-https://github.com/alanbjohnston/CubeSatSim/wiki/v1.3.2-0.-Home.
-
-### The beta Bill of Materials (BOM) is here:
-https://CubeSatSim.org/bom-beta.
-
-### Information about the latest beta software release is here:
-https://github.com/alanbjohnston/CubeSatSim/releases
-
The CubeSat Simulator https://github.com/alanbjohnston/CubeSatSim/wiki is a low cost satellite emulator that runs on solar panels and batteries, transmits UHF radio telemetry, has a 3D printed frame, and can be extended by additional sensors and modules. This project is sponsored by the not-for-profit [Radio Amateur Satellite Corporation, AMSAT®](https://amsat.org).
There are several hardware versions and software branches to go with them - see below for information.
@@ -36,7 +22,7 @@ The other option is to start with a Raspberry Pi OS (Rasbian) image (Bullseye or
## Disk Image Option Steps
-See the Wiki Software Install page for details: https://github.com/alanbjohnston/CubeSatSim/wiki/2.-Software-Install.
+See the Wiki Software Install page for details: [https://github.com/alanbjohnston/CubeSatSim/wiki/V1.3.2-2.-Software-Install](https://github.com/alanbjohnston/CubeSatSim/wiki/V1.3.2-2.-Software-Install#disk-image-option-steps).
## Installation Script Option Steps
@@ -52,15 +38,15 @@ To get the software follow these steps:
`cd CubeSatSim`
-`git checkout master`
+`git checkout beta`
-You are now ready to install the software using this script in the CubeSatSim directory:
+`# You are now ready to install the software using this script in the CubeSatSim directory:`
`./install`
The installation script will run for quite a while. You will get prompted for your amateur radio callsign in all capitals, if you have one. If you don't you can put some other word which will be transmitted as a CW ID. You will also be prompted for your latitude and longitude for APRS packets. The script will prompt you if you want to modify /boot/config.txt file. Type a `y` and the script will complete. You will need to reboot.
-See the Wiki for more details about the CubeSatSim https://github.com/alanbjohnston/CubeSatSim/wiki
+See the Wiki for more details about the CubeSatSim [https://github.com/alanbjohnston/CubeSatSim/wiki](https://github.com/alanbjohnston/CubeSatSim/wiki/v1.3.2-0.-Home)
Older Versions
diff --git a/command b/command
new file mode 100755
index 000000000..1349f45a7
--- /dev/null
+++ b/command
@@ -0,0 +1,132 @@
+#!/bin/bash
+
+echo -e "\nCommand and Control script for CubeSatSim v2.0\n"
+
+ FILE=/home/pi/CubeSatSim/command_control
+ if [ -f "$FILE" ]; then
+ echo "Radio command and control is ON"
+# echo "Turning Command and control to OFF"
+# sudo rm /home/pi/CubeSatSim/command_control
+# echo "rebooting"
+# sudo systemctl stop rpitx
+# sudo reboot now
+# fi
+
+ else
+ echo "Radio command and control is OFF"
+
+ while true
+ do
+ sleep 60
+ done
+
+# exit 1
+ fi
+
+if [ "$1" = "d" ]; then
+
+ echo "debug mode"
+
+ debug=1
+
+else
+
+ debug=0
+
+fi
+
+echo "Waiting 20 seconds for USB"
+
+sleep 20
+
+FILE=/home/pi/CubeSatSim/command_control_direwolf
+if [[ $(arecord -l | grep "USB Audio Device") ]] && [ -f "$FILE" ]; then
+
+ echo "Starting Direwolf DTMF and APRS Command and Control"
+
+ if [ "$debug" = "1" ]; then
+
+ echo "debug mode"
+
+ direwolf -c /home/pi/CubeSatSim/direwolf-cc.conf -t 0l | python3 /home/pi/CubeSatSim/dtmf_aprs_cc.py d
+
+ else
+
+ direwolf -c /home/pi/CubeSatSim/direwolf-cc.conf -t 0l | python3 /home/pi/CubeSatSim/dtmf_aprs_cc.py
+
+ fi
+else
+
+ if [ -f "$FILE" ]; then
+
+ echo "Direwolf mode set but no USB soundcard detected!"
+
+# echo "Trying RTL-FM"
+
+ timeout 1 rtl_test &> out.txt
+ if [[ $(grep "No supported" out.txt) ]] ; then
+
+ echo "No RTL-SDR detected. Command and control is OFF"
+# sleep 60
+ exit
+
+ else
+
+ echo "RTL-SDR detected."
+ echo "Command and control is OFF"
+# sudo modprobe snd-aloop
+
+# value=`aplay -l | grep "Loopback"`
+# echo "$value" > /dev/null
+# set -- $value
+
+# card=${2:0:1}
+
+# value=`cat /home/pi/CubeSatSim/sim.cfg`
+# echo "$value" > /dev/null
+# set -- $value
+
+# freq=$8
+
+# echo "Current value of rx is"
+# echo $freq
+
+# rtl_fm -M fm -f ${freq}M -s 48k | aplay -D plughw:${card},0,0 -r 48000 -t raw -f S16_LE -c 1 &
+
+# if [ "$debug" = "1" ]; then
+
+# echo "debug mode"
+
+# direwolf -r 48000 -c /home/pi/CubeSatSim/direwolf/direwolf.conf -t 0l | python3 /home/pi/CubeSatSim/dtmf_aprs_cc.py d
+
+# else
+
+# direwolf -r 48000 -c /home/pi/CubeSatSim/direwolf/direwolf.conf -t 0l | python3 /home/pi/CubeSatSim/dtmf_aprs_cc.py
+
+# fi
+
+ sleep 5
+ fi
+ rm out.txt
+ else
+
+ echo "Starting Carrier (squelch) Command and Control"
+
+ fi
+
+ if [ "$1" = "d" ]; then
+
+ echo "debug mode"
+
+ python3 /home/pi/CubeSatSim/squelch_cc.py d
+
+ else
+
+ python3 /home/pi/CubeSatSim/squelch_cc.py
+
+ fi
+fi
+
+sudo killall -9 direwolf &>/dev/null
+sudo killall -9 rtl_fm &>/dev/null
+
diff --git a/config b/config
index 7f0dec97b..51c9035e8 100755
--- a/config
+++ b/config
@@ -1,32 +1,266 @@
#!/bin/bash
-echo "CubeSatSim v1.2 configuration tool"
+function transmit_command_aprs {
-if [ "$2" = "-n" ]; then
- norestart=1
+ FILE=/home/pi/CubeSatSim/transmit_dtmf
+ if [ -f "$FILE" ]; then
+
+ echo "Stopping command and control"
+ sudo systemctl stop command
+
+ echo "Transmit DTMF start"
+ gpio write 28 0 # ptt
+ gpio write 2 1 # tx LED
+ timeout 3 direwolf -c /home/pi/CubeSatSim/direwolf/direwolf-transmit-dtmf-aprs.conf -t 0l
+ gpio write 2 0 # tx LED
+ gpio write 28 1 #ptt
+ echo "Transmit stop"
+
+ echo "Resuming command and control"
+ sudo systemctl start command
+
+ else
+
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=a"
+ sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+ echo $STRING > /home/pi/CubeSatSim/t.txt
+ echo
+ echo -n "Sending APRS packet to change mode to APRS "
+ echo $STRING
+ sudo touch /home/pi/CubeSatSim/ready
+ sleep 3
+
+ fi
+
+ exit
+}
+
+function transmit_command_fsk {
+
+ FILE=/home/pi/CubeSatSim/transmit_dtmf
+ if [ -f "$FILE" ]; then
+
+ echo "Stopping command and control"
+ sudo systemctl stop command
+
+ echo "Transmit DTMF start"
+ gpio write 28 0 # ptt
+ gpio write 2 1 # tx LED
+ timeout 3 direwolf -c /home/pi/CubeSatSim/direwolf/direwolf-transmit-dtmf-fsk.conf -t 0l
+ gpio write 2 0 # tx LED
+ gpio write 28 1 #ptt
+ echo "Transmit stop"
+
+ echo "Resuming command and control"
+ sudo systemctl start command
+
+ else
+
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=f"
+ sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+ echo $STRING > /home/pi/CubeSatSim/t.txt
+ echo
+ echo -n "Sending APRS packet to change mode to FSK"
+ echo $STRING
+ sudo touch /home/pi/CubeSatSim/ready
+ sleep 3
+
+ fi
+
+ exit
+}
+
+function transmit_command_bpsk {
+
+ FILE=/home/pi/CubeSatSim/transmit_dtmf
+ if [ -f "$FILE" ]; then
+
+ echo "Stopping command and control"
+ sudo systemctl stop command
+
+ echo "Transmit DTMF start"
+ gpio write 28 0 # ptt
+ gpio write 2 1 # tx LED
+ timeout 3 direwolf -c /home/pi/CubeSatSim/direwolf/direwolf-transmit-dtmf-bpsk.conf -t 0l
+ gpio write 2 0 # tx LED
+ gpio write 28 1 #ptt
+ echo "Transmit stop"
+
+ echo "Resuming command and control"
+ sudo systemctl start command
+
+ else
+
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=b"
+ sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+ echo $STRING > /home/pi/CubeSatSim/t.txt
+ echo
+ echo -n "Sending APRS packet to change mode to BPSK"
+ echo $STRING
+ sudo touch /home/pi/CubeSatSim/ready
+ sleep 3
+
+ fi
+
+ exit
+}
+
+function transmit_command_sstv {
+
+ FILE=/home/pi/CubeSatSim/transmit_dtmf
+ if [ -f "$FILE" ]; then
+
+ echo "Stopping command and control"
+ sudo systemctl stop command
+
+ echo "Transmit DTMF start"
+ gpio write 28 0 # ptt
+ gpio write 2 1 # tx LED
+ timeout 3 direwolf -c /home/pi/CubeSatSim/direwolf/direwolf-transmit-dtmf-sstv.conf -t 0l
+ gpio write 2 0 # tx LED
+ gpio write 28 1 #ptt
+ echo "Transmit stop"
+
+ echo "Resuming command and control"
+ sudo systemctl start command
+
+ else
+
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=s"
+ sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+ echo $STRING > /home/pi/CubeSatSim/t.txt
+ echo
+ echo -n "Sending APRS packet to change mode to SSTV"
+ echo $STRING
+ sudo touch /home/pi/CubeSatSim/ready
+ sleep 3
+
+ fi
+
+ exit
+}
+
+function transmit_command_cw {
+
+ FILE=/home/pi/CubeSatSim/transmit_dtmf
+ if [ -f "$FILE" ]; then
+
+ echo "Stopping command and control"
+ sudo systemctl stop command
+
+ echo "Transmit DTMF start"
+ gpio write 28 0 # ptt
+ gpio write 2 1 # tx LED
+ timeout 3 direwolf -c /home/pi/CubeSatSim/direwolf/direwolf-transmit-dtmf-cw.conf -t 0l
+ gpio write 2 0 # tx LED
+ gpio write 28 1 #ptt
+ echo "Transmit stop"
+
+ echo "Resuming command and control"
+ sudo systemctl start command
+
+ else
+
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=m"
+ sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+ echo $STRING > /home/pi/CubeSatSim/t.txt
+ echo
+ echo -n "Sending APRS packet to change mode to CW"
+ echo $STRING
+ sudo touch /home/pi/CubeSatSim/ready
+ sleep 3
+
+ fi
+
+ exit
+}
+
+function transmit_command_beacon {
+
+ FILE=/home/pi/CubeSatSim/transmit_dtmf
+ if [ -f "$FILE" ]; then
+
+ echo "Stopping command and control"
+ sudo systemctl stop command
+
+ echo "Transmit DTMF start"
+ gpio write 28 0 # ptt
+ gpio write 2 1 # tx LED
+ timeout 3 direwolf -c /home/pi/CubeSatSim/direwolf/direwolf-transmit-dtmf-beacon.conf -t 0l
+ gpio write 2 0 # tx LED
+ gpio write 28 1 #ptt
+ echo "Transmit stop"
+
+ echo "Resuming command and control"
+ sudo systemctl start command
+
+ else
+
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=o"
+ sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+ echo $STRING > /home/pi/CubeSatSim/t.txt
+ echo
+ echo -n "Sending APRS packet to toggle Beacon"
+ echo $STRING
+ sudo touch /home/pi/CubeSatSim/ready
+ sleep 3
+
+ fi
+
+ exit
+}
+
+echo "CubeSatSim v2.0 configuration tool"
+echo
+# echo $1
+# echo $2
+# echo
+
+sudo modprobe snd-aloop
+
+# if [ "$2" = "n" ] ; then
+if [ -z "$2" ] ; then
+ noreboot=0
else
- norestart=0
+ noreboot=1
+ echo "Reboot disabled"
fi
+# echo "No reboot"
+# echo $noreboot
+
+reboot=0
+restart=0
+
if [ "$1" = "" ]; then
value=`cat /home/pi/CubeSatSim/.mode`
echo "$value" > /dev/null
set -- $value
if [ "$1" = "a" ]; then
- echo "APRS mode is set"
+ echo "Mode is APRS"
elif [ "$1" = "m" ]; then
- echo "CW mode is set"
+ echo "Mode is CW"
elif [ "$1" = "f" ]; then
- echo "FSK mode is set"
+ echo "Mode is FSK"
elif [ "$1" = "b" ]; then
- echo "BPSK mode is set"
+ echo "Mode is BPSK"
elif [ "$1" = "s" ]; then
- echo "SSTV mode is set"
+ echo "Mode is SSTV"
+ elif [ "$1" = "e" ]; then
+ echo "Mode is Repeater"
+ elif [ "$1" = "n" ]; then
+ echo -n "Mode is Transmit Commands with "
+ FILE=/home/pi/CubeSatSim/transmit_dtmf
+ if [ -f "$FILE" ]; then
+ echo -n "DTMF"
+ else
+ echo -n "APRS"
+ fi
else
echo
fi
-
+ echo
value=`cat /home/pi/CubeSatSim/sim.cfg`
echo "$value" > /dev/null
set -- $value
@@ -38,67 +272,198 @@ if [ "$1" = "" ]; then
# sim="no"
echo "Simulated Telemetry is OFF"
fi
-
+ echo
+
+ if [ "$9" = "yes" ] || [ "$9" = "y" ]; then
+ echo "Balloon mode is ON"
+ else
+ echo "Balloon mode is OFF"
+ fi
+
+ echo
+ echo -n "Current command count is: "
+ cat /home/pi/CubeSatSim/command_count.txt
+ echo
+# echo
+# echo "Current beacon transmit mode is:"
+# cat /home/pi/CubeSatSim/command_tx
+# echo
+
+ echo -n "Squelch level is: "
+ echo $6
+ echo
+
+ FILE=/home/pi/CubeSatSim/command_control
+ if [ -f "$FILE" ]; then
+
+ if [[ $(arecord -l | grep card) ]]; then
+ FILE=/home/pi/CubeSatSim/command_control_direwolf
+ if [ -f "$FILE" ]; then
+ echo "Radio DTMF/APRS command and control is ON"
+ else
+ echo "Radio carrier command and control is ON"
+ fi
+ else
+ echo "Radio carrier command and control is ON"
+ fi
+ else
+ echo "Radio command and control is OFF"
+ fi
+
+ echo
+
+ echo -n "RX PL code is: "
+ echo -n ${10}
+# echo
+ echo -n " TX PL code is: "
+ echo ${11}
+ echo
+
+ FILE=/home/pi/CubeSatSim/battery_saver
+ if [ -f "$FILE" ]; then
+ echo "Safe Mode! Battery saver mode is ON"
+ else
+ echo "Battery saver mode is OFF"
+ fi
+
+ echo
+ FILE=/home/pi/CubeSatSim/beacon_off
+ if [ -f "$FILE" ]; then
+ echo "Transmit beacon telemetry is OFF"
+ else
+ echo "Transmit beacon telemetry is ON"
+ fi
+
echo
echo -e "Current sim.cfg configuration file:"
# echo
- echo $1 $2 $3 $4 $5
+ echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
echo
+ echo "To change, include an OPTION"
+ echo "To see options, type config -h"
# echo
-# echo "To change, include an OPTION"
-# echo
- set -- "-h"
-fi
+# set -- "-h"
+# fi
+
+
+elif [ "$1" = "-i" ]; then
+
+ restart=1
-if [ "$1" = "-i" ]; then
- echo "Restarting CubeSatSim"
- sudo systemctl restart cubesatsim
- exit
elif [ "$1" = "-a" ]; then
- echo "changing CubeSatSim to AFSK mode"
- sudo echo "a" > /home/pi/CubeSatSim/.mode
- sudo systemctl restart cubesatsim
- exit
+
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" == "n" ]; then
+
+ transmit_command_aprs
+
+ else
+
+ echo "changing CubeSatSim to AFSK mode"
+ sudo echo "a" > /home/pi/CubeSatSim/.mode
+ if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] ; then
+ FILE=/home/pi/CubeSatSim/battery_saver
+ if [ -f "$FILE" ]; then
+ restart=1
+ else
+ reboot=1
+ fi
+ else
+ restart=1
+ fi
+ fi
+
elif [ "$1" = "-m" ]; then
- echo "changing CubeSatSim to CW mode"
- sudo echo "m" > /home/pi/CubeSatSim/.mode
- sudo systemctl restart cubesatsim
- exit
+
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" == "n" ]; then
+
+ transmit_command_cw
+
+ else
+
+ echo "changing CubeSatSim to CW mode"
+ sudo echo "m" > /home/pi/CubeSatSim/.mode
+ if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] ; then
+ FILE=/home/pi/CubeSatSim/battery_saver
+ if [ -f "$FILE" ]; then
+ restart=1
+ else
+ reboot=1
+ fi
+ else
+ restart=1
+ fi
+ fi
+
elif [ "$1" = "-f" ]; then
- echo "changing CubeSatSim to FSK mode"
- sudo echo "f" > /home/pi/CubeSatSim/.mode
- sudo systemctl restart cubesatsim
- exit
+
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" == "n" ]; then
+
+ transmit_command_fsk
+
+ else
+
+ echo "changing CubeSatSim to FSK mode"
+ sudo echo "f" > /home/pi/CubeSatSim/.mode
+ restart=1
+ fi
+
elif [ "$1" = "-b" ]; then
- echo "changing CubeSatSim to BPSK mode"
- sudo echo "b" > /home/pi/CubeSatSim/.mode
- sudo systemctl restart cubesatsim
- exit
+
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" == "n" ]; then
+
+ transmit_command_bpsk
+
+ else
+
+ echo "changing CubeSatSim to BPSK mode"
+ sudo echo "b" > /home/pi/CubeSatSim/.mode
+ restart=1
+ fi
+
elif [ "$1" = "-s" ]; then
- echo "changing CubeSatSim to SSTV mode"
- sudo echo "s" > /home/pi/CubeSatSim/.mode
- sudo systemctl restart cubesatsim
- exit
-elif [ "$1" = "-h" ]; then
- echo "config OPTION"
- echo
- echo "Changes CubeSatSim mode, resets, or modifies configuration file"
- echo
- echo " -h This help info"
- echo " -a Change to AFSK/APRS mode"
- echo " -m Change to CW mode"
- echo " -f Change to FSK/DUV mode"
- echo " -b Change to BPSK mode"
- echo " -s Change to SSTV mode"
- echo " -i Restarts CubeSatsim software"
- echo " -c Change the CALLSIGN in the configuration file sim.cfg"
- echo " -t Change the Simulated Telemetry setting in sim.cfg"
- echo " -r Change the Resets Count in the configuration file sim.cfg"
- echo " -l Change the Latitude and Longitude in the configuration file sim.cfg"
- echo
- exit
+
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" == "n" ]; then
+
+ transmit_command_sstv
+
+ else
+
+ echo "changing CubeSatSim to SSTV mode"
+ sudo echo "s" > /home/pi/CubeSatSim/.mode
+ if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] ; then
+
+ FILE=/home/pi/CubeSatSim/battery_saver
+ if [ -f "$FILE" ]; then
+ restart=1
+ else
+ reboot=1
+ fi
+ else
+ restart=1
+ fi
+ fi
elif [ "$1" = "-t" ]; then
@@ -119,7 +484,7 @@ elif [ "$1" = "-t" ]; then
echo
-# echo $1 $2 $3 $4
+# $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
echo "Do you want Simulated Telemetry ON (y/n) "
read sim
@@ -133,16 +498,18 @@ elif [ "$1" = "-t" ]; then
echo "Simulated Telemetry is OFF"
fi
+# echo
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
+# echo
+ echo $1 $2 $3 $4 $sim $6 $7 $8 $9 ${10}
+ echo $1 $2 $3 $4 $sim $6 $7 $8 $9 ${10} > /home/pi/CubeSatSim/sim.cfg
echo
- echo -e "\nCubeSatSim configuraation sim.cfg file updated to: \n"
- echo
- echo $1 $2 $3 $4 $sim
- echo $1 $2 $3 $4 $sim > /home/pi/CubeSatSim/sim.cfg
- echo
- echo "Restarting CubeSatSim with new configuraation file"
- echo
+## echo "Rebooting CubeSatSim with new configuration file"
+## echo
- sudo systemctl restart cubesatsim
+ reboot=1
+## sudo reboot now
+# sudo restart cubesatsim
elif [ "$1" = "-c" ]; then
@@ -162,7 +529,7 @@ elif [ "$1" = "-c" ]; then
echo $1
echo
-# echo $1 $2 $3 $4 $5
+# echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
echo "Enter callsign in all capitals: "
read callsign
@@ -174,19 +541,21 @@ elif [ "$1" = "-c" ]; then
norestart=1
else
- echo -e "\nCubeSatSim configuraation sim.cfg file updated to: \n"
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
- echo $callsign $2 $3 $4 $5
- echo $callsign $2 $3 $4 $5 > /home/pi/CubeSatSim/sim.cfg
+ echo $callsign $2 $3 $4 $5 $6 $7 $8 $9 ${10}
+ echo $callsign $2 $3 $4 $5 $6 $7 $8 $9 ${10} > /home/pi/CubeSatSim/sim.cfg
fi
if [ "$norestart" = "1" ]; then
echo
else
echo
- echo "Restarting CubeSatSim with new configuraation file"
- echo
- sudo systemctl restart cubesatsim
+## echo "Rebooting CubeSatSim with new configuration file"
+## echo
+ reboot=1
+## sudo reboot now
+# sudo systemctl restart cubesatsim
fi
elif [ "$1" = "-r" ]; then
@@ -208,7 +577,7 @@ elif [ "$1" = "-r" ]; then
echo $2
echo
-# echo $1 $2 $3 $4 $5
+# echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
echo -e "Enter Reset Count (integer): "
@@ -226,19 +595,21 @@ elif [ "$1" = "-r" ]; then
norestart=1
else
- echo -e "\nCubeSatSim configuraation sim.cfg file updated to: \n"
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
- echo $1 $resets $3 $4 $5
- echo $1 $resets $3 $4 $5 > /home/pi/CubeSatSim/sim.cfg
+ echo $1 $resets $3 $4 $5 $6 $7 $8 $9 ${10}
+ echo $1 $resets $3 $4 $5 $6 $7 $8 $9 ${10} > /home/pi/CubeSatSim/sim.cfg
fi
if [ "$norestart" = "1" ]; then
echo
else
- echo
- echo "Restarting CubeSatSim with new configuraation file"
- echo
- sudo systemctl restart cubesatsim
+## echo
+## echo "Rebooting CubeSatSim with new configuration file"
+## echo
+ reboot=1
+## sudo reboot now
+# sudo systemctl restart cubesatsim
fi
elif [ "$1" = "-l" ]; then
@@ -261,7 +632,7 @@ elif [ "$1" = "-l" ]; then
echo $3
echo
-# echo $1 $2 $3 $4 $5
+# echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
echo -e "Enter latitude (decimal degrees, positive is north): "
@@ -302,18 +673,811 @@ elif [ "$1" = "-l" ]; then
echo "Keeping value of" $long
fi
- echo -e "\nCubeSatSim configuraation sim.cfg file updated to: \n"
- echo $1 $2 $lat $long $5
- echo $1 $2 $lat $long $5 > /home/pi/CubeSatSim/sim.cfg
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
+ echo $1 $2 $lat $long $5 $6 $7 $8 $9 ${10} ${11}
+ echo $1 $2 $lat $long $5 $6 $7 $8 $9 ${10} ${11} > /home/pi/CubeSatSim/sim.cfg
if [ "$norestart" = "1" ]; then
echo
else
+## echo
+## echo "Rebooting CubeSatSim with new configuration file"
+## echo
+ reboot=1
+## sudo reboot now
+# sudo systemctl restart cubesatsim
+ fi
+
+elif [ "$1" = "-S" ]; then
+
+ echo
+ echo "Scan both I2C buses on the Raspberry Pi"
+ echo
+
+ echo "I2C Bus 1"
+ echo
+ i2cdetect -y 1
+ echo
+ echo "I2C Bus 1"
+ echo
+ i2cdetect -y 3
+ echo
+
+elif [ "$1" = "-C" ]; then
+
+ echo
+ echo "Clear logs"
+ echo
+
+ sudo systemctl stop cubesatsim
+ sudo systemctl stop transmit
+ sudo systemctl stop command
+
+ sudo mv -f /home/pi/CubeSatSim/telem.txt /home/pi/CubeSatSim/telem.txt.bk
+
+ sudo journalctl --rotate
+ sudo journalctl --vacuum-time=1s
+
+ reboot=1
+## sudo systemctl reboot now
+
+## echo "rebooting"
+
+elif [ "$1" = "-T" ]; then
+
+ echo
+ echo "Change command and control state"
+ echo
+
+ FILE=/home/pi/CubeSatSim/command_control
+ if [ -f "$FILE" ]; then
+ echo "Radio command and control is ON"
echo
- echo "Restarting CubeSatSim with new configuraation file"
+ echo "Do you want to turn command and control to OFF (y/n) "
+ read reset
echo
- sudo systemctl restart cubesatsim
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Command and control set to OFF"
+ sudo rm /home/pi/CubeSatSim/command_control > /dev/null 2>&1
+# reboot=1
+ echo "restarting command and control"
+ sudo systemctl restart command
+## sudo reboot now
+ fi
+
+ else
+ echo "Radio command and control is OFF"
+ echo
+ echo "Do you want to set command and control to ON (y/n) "
+ read reset
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Command and control set to ON"
+ sudo touch /home/pi/CubeSatSim/command_control
+ echo "restarting command and control"
+# reboot=1
+ sudo systemctl restart command
+## sudo reboot now
+ fi
+
fi
-fi
-# sudo systemctl restart cubesatsim
+elif [ "$1" = "-d" ]; then
+
+ echo
+ echo "Change command and control Direwolf state"
+ echo
+ if [[ $(arecord -l | grep card) ]]; then
+ :
+ else
+ echo "Note: No USB Sound Card is plugged in!"
+ echo "Direwolf will not run unless one is plugged in."
+ fi
+
+ FILE=/home/pi/CubeSatSim/command_control_direwolf
+ if [ -f "$FILE" ]; then
+ echo "Radio command and control with Direwolf for DTMF and APRS is ON"
+ echo
+ echo "Do you want to turn Direwolf OFF and do Carrier command and control (y/n) "
+ read reset
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Command and control Direwolf set to OFF"
+ sudo rm /home/pi/CubeSatSim/command_control_direwolf > /dev/null 2>&1
+# reboot=1
+## echo "rebooting"
+ sudo systemctl restart command
+## sudo reboot now
+ fi
+
+ else
+ echo "Radio command and control with Direwolf for DTMF and APRS is OFF so carrier command and control is enabled"
+ echo
+ echo "Do you want to set command and control with Direwolf for DTMF and APRS to ON (y/n) "
+ read reset
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Command and control Direwolf set to ON"
+ sudo touch /home/pi/CubeSatSim/command_control_direwolf
+## echo "rebooting"
+# reboot=1
+ sudo systemctl restart command
+ if [[ $(arecord -l | grep card) ]]; then
+ restart=1
+### echo "restarting cubesatsim software"
+### sudo systemctl restart cubesatsim
+ fi
+## sudo reboot now
+ fi
+
+ fi
+
+ FILE=/home/pi/CubeSatSim/command_control
+ if [ -f "$FILE" ]; then
+ echo
+
+ else
+ echo "Radio command and control is OFF"
+ echo
+ echo "Do you want to set command and control to ON (y/n) "
+ read reset
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Command and control set to ON"
+ sudo touch /home/pi/CubeSatSim/command_control
+ echo "restarting command and control"
+# reboot=1
+ sudo systemctl restart command
+## sudo reboot now
+ fi
+
+ fi
+
+elif [ "$1" = "-D" ]; then
+
+ echo
+ echo "Change Transmit Commands state"
+ echo
+
+ FILE=/home/pi/CubeSatSim/transmit_dtmf
+ if [ -f "$FILE" ]; then
+ echo "Transmit Commands in DTMF is set"
+ echo
+ echo "Do you want to Transmit Commands in APRS (y/n) "
+ read reset
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Transmit Commands in APRS"
+ sudo rm /home/pi/CubeSatSim/transmit_dtmf > /dev/null 2>&1
+ fi
+
+ else
+ echo "Transmit Commands in APRS is set"
+ echo
+ echo "Do you want to Transmit Commands in DTMF (y/n) "
+ read reset
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Transmit Commands in DTMF"
+ touch /home/pi/CubeSatSim/transmit_dtmf
+ fi
+ fi
+
+elif [ "$1" = "-R" ]; then
+
+ echo
+ echo "Reset the Commands Count in the file command_count.txt"
+ echo
+
+ echo "Current commands count is:"
+ cat /home/pi/CubeSatSim/commands_count.txt
+ echo
+
+ echo "Do you want to reset the commands count to zero (y/n) "
+ read reset
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ sudo rm /home/pi/CubeSatSim/command_count.txt > /dev/null 2>&1
+ echo "Commands count reset to 0"
+ echo "0\n" > /home/pi/CubeSatSim/command_count.txt
+ else
+ echo "Commands count not reset"
+ fi
+
+elif [ "$1" = "-B" ]; then
+
+ echo
+ echo "Manually setting Safe Mode (battery saver mode)"
+ echo
+
+ FILE=/home/pi/CubeSatSim/battery_saver
+ if [ -f "$FILE" ]; then
+ echo "Safe Mode! Battery saver mode is ON."
+ mode=1
+ else
+ echo "Safe Mode is OFF."
+ echo "Battery saver mode is OFF."
+ mode=0
+ fi
+
+ echo
+
+ echo "Do you want Safe Mode (battery saver mode) ON (y/n) "
+ read saver
+ echo
+
+## reboot=0
+
+ if [ "$saver" = "y" ] || [ "$saver" = "yes" ] ; then
+ if [ "$mode" = "0" ] ; then
+ echo "Safe Mode will be turned on! Battery saver will be turned ON"
+ sudo touch /home/pi/CubeSatSim/battery_saver
+ reboot=1
+ fi
+ else
+
+ if [ "$mode" = "1" ] ; then
+ echo "Safe Mode will be turned OFF. Battery saver mode will be turned OFF"
+ sudo rm /home/pi/CubeSatSim/battery_saver > /dev/null 2>&1
+ reboot=1
+ fi
+ fi
+
+ if [ "$reboot" = "1" ] ; then
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" = "a" ] || [ "$1" = "s" ] || [ "$1" = "m" ] ; then
+ reboot=1
+## echo "rebooting"
+## sudo reboot now
+ else
+ restart=1
+## echo "restarting"
+## sudo systemctl restart cubesatsim
+ fi
+ fi
+
+elif [ "$1" = "-q" ]; then
+
+ echo
+ echo "Editing the Squelch setting in"
+ echo "the configuration file for CubeSatSim"
+ echo
+
+ value=`cat /home/pi/CubeSatSim/sim.cfg`
+ echo "$value" > /dev/null
+ set -- $value
+
+ echo
+ echo "Current value of squelch is"
+ echo $6
+ echo
+
+# echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
+
+ echo -e "Enter squelch (integer 1 - 8): "
+
+ read sq
+
+ if [ -z $sq ] ; then
+
+ sq="$6"
+ echo "Keeping value of" $lat
+ fi
+
+ if ! [[ $sq =~ ^[+-]?[0-9]+([.][0-9]+)?$ ]] ; then
+
+ echo "Error: not a number!"
+ sq="$6"
+ echo "Keeping value of" $sq
+ fi
+
+# echo
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
+# echo
+ echo $1 $2 $3 $4 $5 $sq $7 $8 $9 ${10} ${11}
+ echo $1 $2 $3 $4 $4 $sq $7 $8 $9 ${10} ${11} > /home/pi/CubeSatSim/sim.cfg
+ echo
+ echo "Restarting CubeSatSim with new configuration file"
+## echo
+
+# reboot=1
+## sudo reboot now
+ sudo systemctl restart transmit
+
+elif [ "$1" = "-Q" ]; then
+
+# echo
+ echo "Reading current Squelch for 10 seconds"
+ echo "Squelch is active low (0 means squelch broken)"
+ echo
+
+ timeout 10 bash -c -- 'while true; do (gpio read 22 && sleep 1); done'
+
+elif [ "$1" = "-P" ]; then
+
+ echo
+ echo "Editing the PL (Private Line) CTCSS/CDCSS setting in"
+ echo "the configuration file for CubeSatSim"
+ echo
+
+ value=`cat /home/pi/CubeSatSim/sim.cfg`
+ echo "$value" > /dev/null
+ set -- $value
+
+ echo
+ echo "Current value of RX PL is"
+ echo ${10}
+ echo "Current value of TX PL is"
+ echo ${11}
+ echo
+
+# echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
+
+ echo -e "Enter RX PL value integer 0: None, 01-38: CTCSS (analog, 39-121:CDCSS (digital)"
+
+ read rxpl
+
+ if [ -z $rxpl ] ; then
+
+ rxpl="${10}"
+ echo "Keeping value of" $rxpl
+ else
+ restart=1
+ fi
+
+ if ! [[ $rxpl =~ ^[+-]?[0-9]+([.][0-9]+)?$ ]] ; then
+
+ echo "Error: not a number!"
+ rxpl="${10}"
+ echo "Keeping value of" $rxpl
+ else
+ restart=1
+ fi
+
+ echo -e "Enter TX PL value integer 0: None, 01-38: CTCSS (analog, 39-121:CDCSS (digital)"
+
+ read txpl
+
+ if [ -z $txpl ] ; then
+
+ txpl="${11}"
+ echo "Keeping value of" $txpl
+ fi
+
+ if ! [[ $txpl =~ ^[+-]?[0-9]+([.][0-9]+)?$ ]] ; then
+
+ echo "Error: not a number!"
+ txpl="${11}"
+ echo "Keeping value of" $txpl
+ fi
+
+# echo
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
+# echo
+ echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $rxpl $txpl
+ echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $rxpl $txpl > /home/pi/CubeSatSim/sim.cfg
+ echo
+## echo "Rebooting CubeSatSim with new configuration file"
+## echo
+
+ reboot=1
+## sudo reboot now
+# sudo systemctl restart cubesatsim
+
+elif [ "$1" = "-F" ]; then
+
+ echo
+ echo "Editing the tx and rx frequency in the"
+ echo "configuration file for CubeSatSim"
+ echo
+ echo "Return keeps current value."
+# echo -e "Current sim.cfg configuration file:"
+# echo
+
+ value=`cat /home/pi/CubeSatSim/sim.cfg`
+ echo "$value" > /dev/null
+ set -- $value
+
+ echo "Current value of tx is"
+ echo $7
+ echo
+ echo "Current value of rx is"
+ echo $8
+ echo
+
+# echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
+
+ echo "Enter tx frequency as 4XX.XXXX: "
+ read tx
+
+ if [ -z $tx ] ; then
+
+ tx="$7"
+ echo "Keeping value of" $tx
+ fi
+
+ echo "Enter rx frequency as 4XX.XXXX: "
+ read rx
+
+ if [ -z $rx ] ; then
+
+ rx="$8"
+ echo "Keeping value of" $rx
+ fi
+# else
+
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
+
+ echo $1 $2 $3 $4 $5 $6 $tx $rx $9 ${10} ${11}
+ echo $1 $2 $3 $4 $5 $6 $tx $rx $9 ${10} ${11} > /home/pi/CubeSatSim/sim.cfg
+# fi
+
+# if [ "$norestart" = "1" ]; then
+# echo
+# else
+ echo
+ echo "Restarting CubeSatSim with new configuration file"
+## echo
+# reboot=1
+## sudo reboot now
+ sudo systemctl restart transmit
+# fi
+
+elif [ "$1" = "-o" ]; then
+
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" == "n" ]; then
+
+ transmit_command_beacon
+
+ else
+ echo
+ echo "Change telemetry beacon transmit state"
+ echo
+
+ FILE=/home/pi/CubeSatSim/beacon_off
+ if [ -f "$FILE" ]; then
+ echo "Transmit beacon telemetry is off"
+# echo
+# echo "Do you want to turn beacon telemetry ON (y/n) "
+# read reset
+
+ reset="y"
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Turn beacon telemetry ON"
+ sudo rm /home/pi/CubeSatSim/beacon_off > /dev/null 2>&1
+ sudo systemctl restart transmit
+ # restart=1
+ fi
+
+ else
+ echo "Transmit beacon telemetry is on"
+# echo
+# echo "Do you want to turn beacon telemetry OFF (y/n) "
+# read reset
+ reset="y"
+ echo
+
+ if [ "$reset" = "y" ] || [ "$reset" = "yes" ] ; then
+ echo "Turn beacon telemetry OFF"
+ touch /home/pi/CubeSatSim/beacon_off
+ sudo systemctl restart transmit
+ # restart=1
+ fi
+ fi
+ fi
+
+elif [ "$1" = "-H" ]; then
+
+# echo
+ echo "Editing the Balloon mode setting in"
+ echo "the configuration file for CubeSatSim"
+ echo
+
+ value=`cat /home/pi/CubeSatSim/sim.cfg`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$9" = "yes" ] || [ "$9" = "y" ]; then
+ echo "Balloon mode is ON"
+ else
+ echo "Balloon mode is OFF"
+ fi
+
+ echo
+
+# echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
+
+ echo "Do you want Balloon mode ON (y/n) "
+ read hab
+ echo
+
+ if [ "$hab" = "y" ] || [ "$hab" = "yes" ] ; then
+ hab="yes"
+ echo "Balloon mode is ON"
+ else
+ hab="no"
+ echo "Balloon mode is OFF"
+ fi
+
+# echo
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
+# echo
+ echo $1 $2 $3 $4 $5 $6 $7 $8 $hab ${10} ${11}
+ echo $1 $2 $3 $4 $5 $6 $7 $8 $hab ${10} ${11} > /home/pi/CubeSatSim/sim.cfg
+ echo
+## echo "Rebooting CubeSatSim with new configuration file"
+## echo
+
+ reboot=1
+## sudo reboot now
+# sudo systemctl restart cubesatsim
+
+elif [ "$1" = "-p" ]; then
+
+ echo "Real-time output from the serial port from the Pico:"
+ echo
+# sleep 2
+ timeout 2 cat /dev/serial0 > /dev/null
+
+ timeout 3 cat /dev/serial0
+
+elif [ "$1" = "-v" ]; then
+
+ echo "Real-time output from the INA219 voltage and current sensors:"
+ echo
+ /home/pi/CubeSatSim/telem
+
+elif [ "$1" = "-e" ]; then
+
+ echo "changing CubeSatSim to Repeater mode"
+ sudo echo "e" > /home/pi/CubeSatSim/.mode
+
+ restart=1
+
+elif [ "$1" = "-n" ]; then
+
+ echo "changing CubeSatSim to Transmit Commands mode"
+
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" = "n" ]; then
+ echo "Turning Transmit Command and Control mode OFF"
+ echo "Switching to BPSK mode"
+ sudo echo "b" > /home/pi/CubeSatSim/.mode
+ reboot=1
+ else
+ echo "Turning Transmit Command and Control mode ON"
+ sudo echo "n" > /home/pi/CubeSatSim/.mode
+ restart=1
+ fi
+
+elif [ "$1" = "-A" ]; then
+
+ echo "Transmit APRS control packets to control another CubeSatSim"
+ echo
+
+ value=`cat /home/pi/CubeSatSim/.mode`
+ echo "$value" > /dev/null
+ set -- $value
+
+ if [ "$1" != "n" ]; then
+
+ sudo systemctl stop cubesatsim
+ sudo systemctl stop transmit
+ # sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+
+ sudo python3 -u /home/pi/CubeSatSim/transmit.py x > /dev/null 2>&1 & # Force APRS mode
+ fi
+
+ sim="y"
+
+ while [ "$sim" = "y" ]
+ do
+
+ echo "Enter the mode number to change: 1=APRS, 2=FSK, 3=BPSK, 4=SSTV, 5=CW"
+ read MODE
+
+ case $MODE in
+
+ 1)
+ echo "Mode 1 is APRS"
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=a"
+ ;;
+ 2)
+ echo "Mode 2 is FSK"
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=f"
+ ;;
+ 3)
+ echo "Mode 3 is BPSK"
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=b"
+ ;;
+ 4)
+ echo "Mode 4 is SSTV"
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=s"
+ ;;
+ 5)
+ echo "Mode 5 is CW"
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=m"
+ ;;
+ *)
+ echo "Unknown mode"
+ STRING="AMSAT-11>APCSS:=3901.40N\07704.39WShi hi MODE=?"
+ ;;
+ esac
+ sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+ echo $STRING > /home/pi/CubeSatSim/t.txt
+ echo
+ echo -n "Sending APRS packet "
+ echo $STRING
+ sudo touch /home/pi/CubeSatSim/ready
+ sleep 5
+ sudo touch /home/pi/CubeSatSim/ready
+
+ echo
+ echo "Do you want to send another APRS command packet (y/n) "
+ read sim
+ echo
+ done
+ sudo rm /home/pi/CubeSatSim/t.txt > /dev/null 2>&1
+# sudo systemctl restart cubesatsim
+
+ if [ "$1" != "n" ]; then
+
+ reboot=1
+ fi
+
+elif [ "$1" = "-L" ]; then
+
+ echo
+ echo "Setting microphone level for command and control"
+ echo
+
+ echo -e "Enter microphone level in percentage (integer 0 - 100): "
+
+ read mic
+
+ if ! [ -z $mic ] && [[ $mic =~ ^[+-]?[0-9]+([.][0-9]+)?$ ]] ; then
+ echo "Updating mic level"
+ value=`arecord -l | grep "card"` && echo "$value" > /dev/null && set -- $value && amixer -c ${2:0:1} set Mic $mic%
+ else
+ echo "Not updating mic level"
+ fi
+
+elif [ "$1" = "-g" ]; then
+
+ echo "Are you sure you want to reset the CubeSatSim configuration back to the default settings?"
+ echo
+
+ read rset
+ echo
+
+ if [ "$rset" = "y" ] || [ "$rset" = "yes" ] ; then
+
+ echo "Resetting"
+
+ echo "AMSAT 0 0 0 no 3 434.9 435 no 0 0" > /home/pi/CubeSatSim/sim.cfg
+
+ sudo echo "b" > /home/pi/CubeSatSim/.mode
+
+ sudo rm /home/pi/CubeSatSim/battery_saver > /dev/null 2>&1
+
+ sudo rm /home/pi/CubeSatSim/command_control > /dev/null 2>&1
+
+ sudo rm /home/pi/CubeSatSim/command_control_direwolf > /dev/null 2>&1
+
+ sudo rm /home/pi/CubeSatSim/beacon_off > /dev/null 2>&1
+
+ sudo echo "0" > /home/pi/CubeSatSim/command_count.txt
+
+ sudo systemctl stop cubesatsim
+ sudo systemctl stop transmit
+ sudo systemctl stop command
+
+ sudo mv -f /home/pi/CubeSatSim/telem.txt /home/pi/CubeSatSim/telem.txt.bk
+
+ sudo journalctl --rotate
+ sudo journalctl --vacuum-time=1s
+
+ reboot=1
+ else
+
+ echo "Not resetting"
+
+ fi
+
+elif [ "$1" = "-h" ]; then
+
+ echo "config OPTION"
+ echo
+ echo "Changes CubeSatSim mode, resets, or modifies configuration file"
+ echo
+ echo " -h This help info"
+ echo " -a Change to AFSK/APRS mode"
+ echo " -m Change to CW mode"
+ echo " -f Change to FSK/DUV mode"
+ echo " -b Change to BPSK mode"
+ echo " -s Change to SSTV mode"
+ echo " -n Change to Transmit Commands mode"
+ echo " -e Change to Repeater mode"
+ echo " -i Restart CubeSatsim software"
+ echo " -c Change the CALLSIGN in the configuration file sim.cfg"
+ echo " -t Change the Simulated Telemetry setting in sim.cfg"
+ echo " -r Change the Resets Count in the configuration file sim.cfg"
+ echo " -l Change the Latitude and Longitude in the configuration file sim.cfg"
+ echo " -S Scan both I2C buses on the Raspberry Pi"
+ echo " -C Clear logs"
+ echo " -T Change command and control state"
+ echo " -d Change command and control Direwolf state"
+ echo " -R Change the Commands Count in the file command_count.txt"
+ echo " -B Change Safe Mode (battery saver mode) manually"
+ echo " -q Change the Squelch setting for command receiver"
+ echo " -F Change the RX and TX frequency"
+ echo " -H Change the Balloon (HAB) mode"
+ echo " -p Display payload sensor data"
+ echo " -v Display voltage and current data"
+ echo " -P Change the PL (Private Line) CTCSS/CDCSS codes for RX and TX"
+ echo " -A Transmit APRS control packets to control another CubeSatSim"
+ echo " -D Change Transmit Commands state APRS or DTMF"
+ echo " -o Change telemetry beacon transmit state"
+ echo " -L Change microphone level for command and control"
+ echo " -g Reset configuration back to default settings"
+
+ echo
+ exit
+
+else
+# echo
+ echo "Unknown option. Try config -h for a list of supported options."
+ echo
+
+fi
+
+# sudo systemctl restart cubesatsim
+
+# echo "Checking for reboot or restart"
+
+# echo $noreboot
+
+#reboot=0
+#restart=1
+
+if [ "$reboot" = "1" ] ; then
+ if [ "$noreboot" = "0" ] ; then
+ echo 'Reboot due to config change!' | wall
+ echo "Rebooting"
+ sudo systemctl stop transmit
+ sudo reboot now
+ else
+ echo "Reboot needed for changes to take effect"
+ fi
+fi
+
+if [ "$restart" = "1" ] ; then
+ if [ "$reboot" = "0" ] ; then
+ echo "Restarting"
+# sudo systemctl stop transmit
+ sudo systemctl restart cubesatsim
+ sudo systemctl restart transmit
+ else
+ echo "Restart needed for changes to take effect"
+ fi
+fi
diff --git a/direwolf-cc.conf b/direwolf-cc.conf
new file mode 100644
index 000000000..8419355f2
--- /dev/null
+++ b/direwolf-cc.conf
@@ -0,0 +1,2 @@
+ADEVICE hw:CARD=Device,DEV=0 default
+DTMF
diff --git a/direwolf/direwolf-transmit-dtmf-aprs.conf b/direwolf/direwolf-transmit-dtmf-aprs.conf
new file mode 100644
index 000000000..786102cd2
--- /dev/null
+++ b/direwolf/direwolf-transmit-dtmf-aprs.conf
@@ -0,0 +1,5 @@
+ADEVICE hw:CARD=Loopback,DEV=0 hw:CARD=Headphones,DEV=0
+MYCALL AMSAT
+CHANNEL 0
+MODEM 1200
+CBEACON dest="DTMF-3" info="1 #" delay=0
diff --git a/direwolf/direwolf-transmit-dtmf-beacon.conf b/direwolf/direwolf-transmit-dtmf-beacon.conf
new file mode 100644
index 000000000..6c022dea0
--- /dev/null
+++ b/direwolf/direwolf-transmit-dtmf-beacon.conf
@@ -0,0 +1,5 @@
+ADEVICE hw:CARD=Loopback,DEV=0 hw:CARD=Headphones,DEV=0
+MYCALL AMSAT
+CHANNEL 0
+MODEM 1200
+CBEACON dest="DTMF-3" info="10 #" delay=0
diff --git a/direwolf/direwolf-transmit-dtmf-bpsk.conf b/direwolf/direwolf-transmit-dtmf-bpsk.conf
new file mode 100644
index 000000000..a0ae9b54a
--- /dev/null
+++ b/direwolf/direwolf-transmit-dtmf-bpsk.conf
@@ -0,0 +1,5 @@
+ADEVICE hw:CARD=Loopback,DEV=0 hw:CARD=Headphones,DEV=0
+MYCALL AMSAT
+CHANNEL 0
+MODEM 1200
+CBEACON dest="DTMF-3" info="3 #" delay=0
diff --git a/direwolf/direwolf-transmit-dtmf-cw.conf b/direwolf/direwolf-transmit-dtmf-cw.conf
new file mode 100644
index 000000000..8629754f1
--- /dev/null
+++ b/direwolf/direwolf-transmit-dtmf-cw.conf
@@ -0,0 +1,5 @@
+ADEVICE hw:CARD=Loopback,DEV=0 hw:CARD=Headphones,DEV=0
+MYCALL AMSAT
+CHANNEL 0
+MODEM 1200
+CBEACON dest="DTMF-3" info="5 #" delay=0
diff --git a/direwolf/direwolf-transmit-dtmf-fsk.conf b/direwolf/direwolf-transmit-dtmf-fsk.conf
new file mode 100644
index 000000000..f197e5837
--- /dev/null
+++ b/direwolf/direwolf-transmit-dtmf-fsk.conf
@@ -0,0 +1,5 @@
+ADEVICE hw:CARD=Loopback,DEV=0 hw:CARD=Headphones,DEV=0
+MYCALL AMSAT
+CHANNEL 0
+MODEM 1200
+CBEACON dest="DTMF-3" info="2 #" delay=0
diff --git a/direwolf/direwolf-transmit-dtmf-sstv.conf b/direwolf/direwolf-transmit-dtmf-sstv.conf
new file mode 100644
index 000000000..c58cb77fc
--- /dev/null
+++ b/direwolf/direwolf-transmit-dtmf-sstv.conf
@@ -0,0 +1,5 @@
+ADEVICE hw:CARD=Loopback,DEV=0 hw:CARD=Headphones,DEV=0
+MYCALL AMSAT
+CHANNEL 0
+MODEM 1200
+CBEACON dest="DTMF-3" info="4 #" delay=0
diff --git a/direwolf/direwolf.conf b/direwolf/direwolf.conf
new file mode 100644
index 000000000..701d80b4c
--- /dev/null
+++ b/direwolf/direwolf.conf
@@ -0,0 +1 @@
+ADEVICE plughw:CARD=Loopback,DEV=1 plughw:CARD=Loopback,DEV=0
diff --git a/dtmf_aprs_cc.py b/dtmf_aprs_cc.py
new file mode 100644
index 000000000..befe58c73
--- /dev/null
+++ b/dtmf_aprs_cc.py
@@ -0,0 +1,200 @@
+import sys
+from os import system
+import RPi.GPIO as GPIO
+from RPi.GPIO import output
+from time import sleep
+import logging
+logging.basicConfig(format='%(message)s')
+# logging.warning('CC-Warning!')
+
+if __name__ == "__main__":
+ powerPin = 16
+ txLed = 27
+ change_mode = False
+ debug_mode = False
+ counter = 1
+ if (len(sys.argv)) > 1:
+# print("There are arguments!")
+ if ('d' == sys.argv[1]):
+ debug_mode = True
+
+ for line in sys.stdin:
+# if (debug_mode):
+ print(line, end =" ")
+ logging.warning(line)
+
+# if '^c' == line.rstrip():
+# break
+
+ if ((line.find("MODE=a")) > 0):
+ system("echo '\nAPRS Mode!!\n'")
+ mode = 'a'
+ change_mode = True
+ counter = (counter + 1) % 2
+ if ((line.find("DTMF>APDW15:t1#")) > 0):
+ system("echo '\nAPRS Mode!!\n'")
+ mode = 'a'
+ change_mode = True
+ if ((line.find("MODE=f")) > 0):
+ system("echo '\nFSK Mode!!\n'")
+ mode = 'f'
+ change_mode = True
+ counter = (counter + 1) % 2
+ if ((line.find("DTMF>APDW15:t2#")) > 0):
+ system("echo '\nFSK Mode!!\n'")
+ mode = 'f'
+ change_mode = True
+ if ((line.find("MODE=b")) > 0):
+ system("echo '\nBPSK Mode!!\n'")
+ mode = 'b'
+ change_mode = True
+ counter = (counter + 1) % 2
+ if ((line.find("DTMF>APDW15:t3#")) > 0):
+ system("echo '\nBPSK Mode!!\n'")
+ mode = 'b'
+ change_mode = True
+ if ((line.find("MODE=s")) > 0):
+ system("echo '\nSSTV Mode!!\n'")
+ mode = 's'
+ change_mode = True
+ counter = (counter + 1) % 2
+ if ((line.find("DTMF>APDW15:t4#")) > 0):
+ system("echo '\nSSTV Mode!!\n'")
+ mode = 's'
+ change_mode = True
+ if ((line.find("MODE=m")) > 0):
+ system("echo '\nCW Mode!!\n'")
+ mode = 'm'
+ change_mode = True
+ counter = (counter + 1) % 2
+ if ((line.find("DTMF>APDW15:t5#")) > 0):
+ system("echo '\nCW Mode!!\n'")
+ mode = 'm'
+ change_mode = True
+ if ((line.find("MODE=n")) > 0):
+ system("echo '\nTransmit Commands Mode!!\n'")
+ mode = 'n'
+ change_mode = True
+ counter = (counter + 1) % 2
+ if ((line.find("DTMF>APDW15:t11#")) > 0):
+ system("echo '\nTransmit Commands Mode!!\n'")
+ mode = 'n'
+ change_mode = True
+# Currently, C2C does not support Repeater mode e
+ if ((line.find("MODE=o")) > 0):
+ system("echo '\nBeacon Mode toggle!!\n'")
+ mode = 'o'
+ change_mode = True
+ counter = (counter + 1) % 2
+ if ((line.find("DTMF>APDW15:t10#")) > 0):
+ system("echo '\nBeacon Mode toggle!!\n'")
+ mode = 'o'
+ change_mode = True
+
+ if (debug_mode == False) and (change_mode == True) and (counter == 1): # skip every other APRS command since Direwolf prints them twice
+ GPIO.setmode(GPIO.BCM)
+ GPIO.setwarnings(False)
+ GPIO.setup(powerPin, GPIO.OUT)
+ GPIO.setup(txLed, GPIO.OUT)
+
+ if (mode == 'f'):
+ GPIO.output(powerPin, 0) # blink two times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+
+ elif (mode == 'b'):
+ GPIO.output(powerPin, 0) # blink three times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+
+ elif (mode == 's'):
+ GPIO.output(powerPin, 0) # blink four times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+
+ elif (mode == 'm'):
+ GPIO.output(powerPin, 0) # blink five times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1);
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+ elif (mode == 'a'):
+ mode = 'a'
+ GPIO.output(powerPin, 0) # blink one time
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+
+ try:
+ file = open("/home/pi/CubeSatSim/command_count.txt", "r")
+ string = file.read()
+ file.close()
+ command_count = int(string)
+ command_count += 1
+ filec = open("/home/pi/CubeSatSim/command_count.txt", "w")
+ command_count_string = str(command_count)
+ print(command_count_string)
+ string = filec.write(command_count_string)
+ filec.close()
+ except:
+ print("Can't write command_count file!")
+ print("Command_count: ")
+ print(command_count)
+
+ GPIO.output(txLed, 0)
+ GPIO.output(powerPin, 0)
+ system("sudo systemctl stop rpitx")
+# system("sudo systemctl stop cubesatsim")
+
+ print("\n/home/pi/CubeSatSim/config -" + mode)
+ system("/home/pi/CubeSatSim/config -" + mode)
+
+
+ change_mode = False
+
+ print("Waiting 5 seconds to allow unplug and plug of soundcard")
+ sleep(5)
+ print("Done")
+
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1.mnb b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1.mnb
new file mode 100644
index 000000000..71762841c
--- /dev/null
+++ b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1.mnb
@@ -0,0 +1,16 @@
+D1 66.29 64.52 0 1N5817 D-2.5
+D2 72.01 10.49 0 1N5817 D-2.5
+D3 66.45 10.62 180 1N4148 D-2.5
+D4 71.58 64.49 0 1N5817 D-2.5
+D8 59.41 6.91 270 DNI/5V1 Zener 1W ZDIO-2.5
+D9 19.71 45.92 0 DNI/1N5817 D-2.5
+D10 77.50 10.46 0 1N5817 D-2.5
+JP1 72.09 8.41 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP2 24.74 59.61 0 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP3 19.63 58.93 270 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP4 71.53 62.46 0 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP5 74.93 68.28 270 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP6 26.14 37.01 180 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP7 15.95 61.98 90 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP8 37.80 36.96 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+X1 73.61 73.10 270 SC1464-ND PG203J
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1.mnt b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1.mnt
new file mode 100644
index 000000000..13698afc5
--- /dev/null
+++ b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1.mnt
@@ -0,0 +1,37 @@
+C1 19.33 75.46 270 18pF C0603
+C2 19.28 71.32 270 16pF C0603
+C3 16.38 10.11 180 18pF C0603
+C4 20.68 10.16 180 16pF C0603
+C7 55.60 56.62 0 DNI/47uF C0603
+C8 58.42 47.83 270 DNI/100nF C0603
+C10 66.83 3.91 270 DNI/100nF C0603
+D5 66.01 67.21 180 DNI/B5817WS SOD-323F
+D6 72.16 8.69 180 DNI/B5817WS SOD-323F
+D7 66.47 8.84 0 DNI/4148WS SOD-323F
+D11 77.44 8.74 180 DNI/B5817WS SOD-323F
+E1 7.06 75.34 180 ANT-916-CHP-T XDCR_ANT-916-CHP-T
+E2 19.05 3.94 0 ANT-916-CHP-T XDCR_ANT-916-CHP-T
+J1 32.55 66.61 0 CONN_20X2 2X20
+J8 37.19 71.83 0 Sparkfun USB-C Breakout 1X06_NO_SILK
+J9 37.36 73.97 180 DNI/USB4105-GF-A or GT-USB-7010B USB-C-16P-2LAYER-PADS
+L1 17.25 73.38 90 13nH L0603
+L2 18.49 12.17 180 13nH L0603
+R2 56.11 62.23 0 DNI/1k R0603
+R4 60.50 62.23 180 DNI/1k R0603
+R5 30.48 76.28 180 DNI/5.1k R0603
+R6 44.20 76.30 0 DNI/5.1k R0603
+R10 65.68 71.81 0 DNI/1k R0603
+R11 25.17 71.88 0 DNI/100 R0603
+R12 48.56 72.24 0 DNI/220 R0603
+R16 20.07 60.05 0 DNI/68 R0805
+R17 24.61 60.05 270 DNI/180 R0603
+R18 32.94 60.20 180 DNI/68 R0805
+R21 55.42 51.26 0 DNI/100 R0603
+R22 56.59 44.55 0 DNI/220 R0603
+R25 64.24 40.89 90 DNI/4.7k R0603
+R26 74.70 40.61 90 DNI/4.7k R0603
+R28 61.98 8.81 0 DNI/10k R0603
+R31 3.86 44.37 0 DNI/1k R0603
+R32 3.40 60.55 180 DNI/100 R0603
+U1 54.43 24.61 270 Raspberry Pi Pico PICO-PKG-NO_DEBUG
+U6 39.24 51.22 270 SRFRS0W5 SR_FRS_0W5
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bnames.pdf b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bnames.pdf
new file mode 100644
index 000000000..493f2e583
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bnames.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bom.csv.txt b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bom.csv.txt
new file mode 100644
index 000000000..11c1485d9
--- /dev/null
+++ b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bom.csv.txt
@@ -0,0 +1,54 @@
+"Qty";"Value";"Device";"Package";"Parts";"Description";"";
+"2";"100";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R8, R30";"Resistor";"";
+"1";"100";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"R19";"Resistor";"";
+"2";"100nF";"CAPPTH";"CAP-PTH-SMALL";"C6, C9";"Capacitor";"";
+"1";"10K";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R27";"Resistor";"";
+"2";"13nH";"SMD-FERRITE-CHIP-120-OHM-500MA(0603)";"L0603";"L1, L2";"303030001";"";
+"2";"16pF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"C2, C4";"302010097";"";
+"1";"180";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R14";"Resistor";"";
+"2";"18pF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"C1, C3";"302010097";"";
+"2";"1K";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R1, R3";"Resistor";"";
+"1";"1N4148";"DIODE-D-2.5";"D-2.5";"D3";"DIODE";"";
+"4";"1N5817";"DIODE-D-2.5";"D-2.5";"D1, D2, D4, D10";"DIODE";"";
+"2";"1k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R7, R29";"Resistor";"";
+"1";"220";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R9";"Resistor";"";
+"1";"220";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"R20";"Resistor";"";
+"2";"4.7k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R23, R24";"Resistor";"";
+"1";"47uF";"CAPPTH";"CAP-PTH-SMALL";"C5";"Capacitor";"";
+"2";"68";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R13, R15";"Resistor";"";
+"2";"ANT-916-CHP-T";"ANT-916-CHP-T";"XDCR_ANT-916-CHP-T";"E1, E2";"868MHz ISM, LoRa, Sensor Networks, SigFox Chip RF Antenna 863MHz ~ 873MHz 0.5dBi Solder Surface Mount Check prices";"";
+"1";"BME280";"M04NO_SILK_ALL_ROUND";"1X04_NO_SILK_ALL_ROUND";"J5";"Header 4";"";
+"2";"Blue 5mm";"LED3MM";"LED3MM";"LED2, LED4";"LED";"";
+"1";"CONN_20X2";"CONN_20X2";"2X20";"J1";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"3";"DNI/100";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"R11, R21, R32";"301010206";"";
+"2";"DNI/100nF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"C8, C10";"302010097";"";
+"1";"DNI/10k";"R-EU_R0603";"R0603";"R28";"RESISTOR, European symbol";"";
+"1";"DNI/180";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"R17";"301010206";"";
+"1";"DNI/1N5817";"DIODE-D-2.5";"D-2.5";"D9";"DIODE";"";
+"2";"DNI/1k";"R-EU_R0603";"R0603";"R2, R4";"RESISTOR, European symbol";"";
+"2";"DNI/1k";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"R10, R31";"301010206";"";
+"1";"DNI/1x4 pin header";"CONN_041X04_NO_SILK";"1X04_NO_SILK";"J12";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"2";"DNI/220";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"R12, R22";"301010206";"";
+"2";"DNI/4.7k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"R33, R34";"Resistor";"";
+"2";"DNI/4.7k";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"R25, R26";"301010206";"";
+"1";"DNI/4148WS";"DIODESOD-323F";"SOD-323F";"D7";"Diode";"";
+"1";"DNI/47uF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"C7";"302010097";"";
+"2";"DNI/5.1k";"R-EU_R0603";"R0603";"R5, R6";"RESISTOR, European symbol";"";
+"1";"DNI/5V1 Zener 1W";"ZENER-DIODEZD-2.5";"ZDIO-2.5";"D8";"Z-Diode";"";
+"2";"DNI/68";"R-US_R0805";"R0805";"R16, R18";"RESISTOR, American symbol";"";
+"3";"DNI/B5817WS";"DIODESOD-323F";"SOD-323F";"D5, D6, D11";"Diode";"";
+"1";"DNI/Sparkfun QWIIC Breakout";"CONN_041X04_NO_SILK";"1X04_NO_SILK";"J10";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"1";"DNI/Test Point for MIC_IN";"CONN_01PTH_NO_SILK_YES_STOP";"1X01_NO_SILK";"J11";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"1";"DNI/USB4105-GF-A or GT-USB-7010B";"USB_C_2-LAYER_PADS";"USB-C-16P-2LAYER-PADS";"J9";"USB Type C 16Pin Connector";"";
+"2";"Green 5mm";"LED3MM";"LED3MM";"LED1, LED3";"LED";"";
+"3";"JUMPER-SMT_2_NC_TRACE_SILK";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"JP3, JP4, JP6";"Normally closed trace jumper";"";
+"5";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"JP1, JP2, JP5, JP7, JP8";"Normally open jumper";"";
+"1";"MPU6050";"M08NO_SILK_FEMALE_PTH";"1X08_NO_SILK@1";"J4";"Header 8";"";
+"2";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"J6, J7";"Standard 2-pin 0.1" header. Use with";"";
+"1";"RA-SPST";"RA-SPST";"RA-SPST";"S1";"";"";
+"1";"Raspberry Pi Pico";"RASPBERRY_PICO-NO_DEBUG";"PICO-PKG-NO_DEBUG";"U1";"";"";
+"1";"Red 5mm";"LED3MM";"LED3MM";"LED5";"LED";"";
+"1";"SC1464-ND";"PG203J";"PG203J";"X1";"MIC/HEADPHONE JACK";"";
+"2";"SMA-VERT";"SMA-VERT";"SMA-VERT";"X2, X3";"";"";
+"1";"SRFRS0W5";"SR_FRS_0W5";"SR_FRS_0W5";"U6";"";"";
+"1";"Sparkfun USB-C Breakout";"CONN_06NO_SILK_FEMALE_PTH";"1X06_NO_SILK";"J8";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bottom.png b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bottom.png
new file mode 100644
index 000000000..74b6f58d6
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_bottom.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_gerbers.zip b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_gerbers.zip
new file mode 100644
index 000000000..dca7e79e7
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_gerbers.zip differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_pcb.png b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_pcb.png
new file mode 100644
index 000000000..d05ed4960
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_pcb.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_pour.png b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_pour.png
new file mode 100644
index 000000000..06cc698c8
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_pour.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_schematic.pdf b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_schematic.pdf
new file mode 100644
index 000000000..bc1fa3c73
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_schematic.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_tnames.pdf b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_tnames.pdf
new file mode 100644
index 000000000..afd460463
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_tnames.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_top.png b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_top.png
new file mode 100644
index 000000000..261839d71
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.1_top.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3._bottom.png b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3._bottom.png
new file mode 100644
index 000000000..2204c7ed2
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3._bottom.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3.mnb b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3.mnb
new file mode 100644
index 000000000..d707b0c83
--- /dev/null
+++ b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3.mnb
@@ -0,0 +1,14 @@
+D1 63.80 60.53 0 1N5817 D-2.5
+D2 72.01 10.49 0 1N5817 D-2.5
+D3 66.45 10.62 180 1N4148 D-2.5
+D8 59.31 7.52 270 DNI/5V1 Zener 1W ZDIO-2.5
+D9 19.71 45.92 0 DNI/1N5817 D-2.5
+D10 77.50 10.46 0 1N5817 D-2.5
+JP1 72.16 8.66 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP2 24.74 59.61 0 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP3 19.63 58.93 270 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP5 75.08 56.49 270 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP6 26.31 37.01 180 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP7 15.95 61.98 90 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP8 37.92 40.67 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+X1 71.86 61.21 270 SC1464-ND PG203J
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3.mnt b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3.mnt
new file mode 100644
index 000000000..d536d87fc
--- /dev/null
+++ b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3.mnt
@@ -0,0 +1,37 @@
+C1 18.75 76.02 270 18pF C0603
+C2 18.69 71.88 270 16pF C0603
+C3 16.38 10.11 180 18pF C0603
+C4 20.68 10.16 180 16pF C0603
+C7 55.60 56.62 0 DNI/47uF C0603
+C8 59.00 47.55 270 DNI/100nF C0603
+C10 66.83 3.91 270 DNI/100nF C0603
+D5 63.83 62.51 180 DNI/B5817WS SOD-323F
+D6 72.16 8.69 180 DNI/B5817WS SOD-323F
+D7 66.47 8.84 0 DNI/4148WS SOD-323F
+E1 7.06 75.34 180 ANT-916-CHP-T XDCR_ANT-916-CHP-T
+E2 19.05 3.94 0 ANT-916-CHP-T XDCR_ANT-916-CHP-T
+J1 32.55 66.61 0 CONN_20X2 2X20
+J3 8.71 38.41 0 SJ1-2503A CONN_SJ1-2503A
+J8 36.17 72.01 0 Sparkfun USB-C Breakout 1X06_NO_SILK
+J9 36.35 74.15 180 DNI/USB4105-GF-A or GT-USB-7010B USB-C-16P-2LAYER-PADS
+L1 16.76 73.94 90 13nH L0603
+L2 18.49 12.17 180 13nH L0603
+R2 54.00 62.26 0 DNI/1k R0603
+R4 58.39 62.26 180 DNI/1k R0603
+R5 29.46 76.45 180 DNI/5.1k R0603
+R6 43.18 76.48 0 DNI/5.1k R0603
+R10 64.26 72.06 0 DNI/1k R0603
+R11 24.16 72.06 0 DNI/100 R0603
+R12 47.55 72.42 0 DNI/220 R0603
+R16 20.07 60.05 0 DNI/68 R0805
+R17 24.71 60.15 270 DNI/180 R0603
+R18 32.94 60.20 180 DNI/68 R0805
+R21 55.42 51.26 0 DNI/100 R0603
+R22 59.33 44.63 0 DNI/220 R0603
+R25 67.59 40.77 90 DNI/4.7k R0603
+R26 76.53 40.79 90 DNI/4.7k R0603
+R28 61.98 8.81 0 DNI/10k R0603
+R31 3.86 44.37 0 DNI/1k R0603
+R32 3.40 60.55 180 DNI/100 R0603
+U1 54.36 27.48 270 Raspberry Pi Pico PICO-PKG-NO_DEBUG
+U6 39.24 51.22 270 SR105U SR_FRS_0W5
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_gerbers.zip b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_gerbers.zip
new file mode 100644
index 000000000..9828f0aca
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_gerbers.zip differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_pcb.png b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_pcb.png
new file mode 100644
index 000000000..0aadd9470
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_pcb.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_pour.png b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_pour.png
new file mode 100644
index 000000000..8dcc59962
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_pour.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_schematic.pdf b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_schematic.pdf
new file mode 100644
index 000000000..8f92a4ca1
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_schematic.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_top.png b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_top.png
new file mode 100644
index 000000000..9b76469dd
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-STEM-b1.3.2.3_top.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.1b_bottom.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.1b_bottom.png
new file mode 100644
index 000000000..012b63dd5
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.1b_bottom.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.1b_top.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.1b_top.png
new file mode 100644
index 000000000..a68568d96
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.1b_top.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_bottom.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_bottom.png
new file mode 100644
index 000000000..dfeb330e6
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_bottom.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_gerbers.zip b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_gerbers.zip
new file mode 100644
index 000000000..4b48013a9
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_gerbers.zip differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_pcb.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_pcb.png
new file mode 100644
index 000000000..42c58a446
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_pcb.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_pour.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_pour.png
new file mode 100644
index 000000000..35769b63a
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_pour.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_schematic.pdf b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_schematic.pdf
new file mode 100644
index 000000000..06e3cc6b3
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_schematic.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_top.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_top.png
new file mode 100644
index 000000000..3433fa7d7
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2.2_top.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bnames.pdf b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bnames.pdf
new file mode 100644
index 000000000..6bb434266
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bnames.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bom.csv.txt b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bom.csv.txt
new file mode 100644
index 000000000..31a2e012e
--- /dev/null
+++ b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bom.csv.txt
@@ -0,0 +1,16 @@
+"Part";"Value";"Device";"Package";"Description";"COPYRIGHT";"DESCRIPTION";"DIGI-KEY_PART_NUMBER";"DIGI-KEY_PART_NUMBER_1";"DIGI-KEY_PART_NUMBER_2";"DIGI-KEY_PART_NUMBER_3";"DIGI-KEY_PART_NUMBER_4";"MANUFACTURER_PART_NUMBER";"MF";"MFR_NAME";"MP";"PACKAGE";"PURCHASE-URL";"REFDES";"TYPE";
+"BT2";"AA battery holder BH3AA-PC";"BH3AA-PC";"BAT_BH3AA-PC";"Holder Batt 3-Aa Cells Pc Mount";"";" Battery Holder (Open) AA 3 Cell PC Pin ";"BH3AA-PC-ND";"";"";"";"";"";"MPD";"";"BH3AAPC";"None";"https://pricing.snapeda.com/search/part/BH3AAPC/?ref=eda";"";"";
+"C1";"DNI/0.1µF";"CAP_CERAMIC0603";"0603";"Ceramic Capacitors";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"F1";"PTC";"PTCPTH";"PTC";"Resettable Fuse PTC";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"J1";"CONN_20X2";"CONN_20X2";"2X20";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"JP1";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"JP2";"";"CONN_01";"1X01";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"JP3";"";"CONN_01";"1X01";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"JP4";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"JP5";"JUMPER-SMT_2_NC_TRACE_SILK";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"Normally closed trace jumper";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"JP6";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"JP7";"";"CONN_01";"1X01";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"JP8";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"R1";"DNI/R100";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"U1";"INA219 purple board";"INA219";"INA219";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";
+"U2";"INA219AIDR";"INA219AIDR";"D0008A_N";"";"Copyright (C) 2022 Ultra Librarian. All rights reserved.";"";"";"296-23978-1-ND";"296-23978-2-ND";"296-23978-6-ND";"2156-INA219AIDR-ND";"INA219AIDR";"";"Texas Instruments";"";"";"";"RefDes";"TYPE";
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bottom.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bottom.png
new file mode 100644
index 000000000..17c913ea0
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_bottom.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_gerbers.zip b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_gerbers.zip
new file mode 100644
index 000000000..539adccb0
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_gerbers.zip differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_pcb.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_pcb.png
new file mode 100644
index 000000000..85fb997d5
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_pcb.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_pour.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_pour.png
new file mode 100644
index 000000000..ee11aa9ba
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_pour.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_schematic.pdf b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_schematic.pdf
new file mode 100644
index 000000000..8b5e4d29a
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_schematic.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_tnames.pdf b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_tnames.pdf
new file mode 100644
index 000000000..7bbc04886
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_tnames.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_top.png b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_top.png
new file mode 100644
index 000000000..d2cea4b15
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-battery-b1.3.2b_top.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_bottom.png b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_bottom.png
new file mode 100644
index 000000000..6705d6367
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_bottom.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_gerbers.zip b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_gerbers.zip
new file mode 100644
index 000000000..4588fe1e0
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_gerbers.zip differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_pcb.png b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_pcb.png
new file mode 100644
index 000000000..970c44e34
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_pcb.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_pour.png b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_pour.png
new file mode 100644
index 000000000..a05e58e9c
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_pour.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_schematic.pdf b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_schematic.pdf
new file mode 100644
index 000000000..721fb95a9
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_schematic.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_top.png b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_top.png
new file mode 100644
index 000000000..94d79206d
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2.1_top.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._bottom.png b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._bottom.png
new file mode 100644
index 000000000..dd161800c
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._bottom.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._pcb.png b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._pcb.png
new file mode 100644
index 000000000..31e547863
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._pcb.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._pour.png b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._pour.png
new file mode 100644
index 000000000..36aa645f5
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._pour.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._top.png b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._top.png
new file mode 100644
index 000000000..90f293394
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2._top.png differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_bnames.pdf b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_bnames.pdf
new file mode 100644
index 000000000..2161269a6
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_bnames.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_bom.csv.txt b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_bom.csv.txt
new file mode 100644
index 000000000..98f15be60
--- /dev/null
+++ b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_bom.csv.txt
@@ -0,0 +1,18 @@
+"Qty";"Value";"Device";"Package";"Parts";"Description";"";
+"2";"";"CONN_01PTH_NO_SILK_YES_STOP";"1X01_NO_SILK";"JP16, JP19";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"6";"0.1µF";"CAP_CERAMIC0603";"0603";"C2, C3, C4, C5, C6, C7";"Ceramic Capacitors";"";
+"6";"1A/23V/620mV";"DIODE-SCHOTTKY-BAT20J";"SOD-323";"D7, D8, D9, D10, D11, D12";"Schottky diode";"";
+"6";"1N5817";"DIODE-D-2.5";"D-2.5";"D1, D2, D3, D4, D5, D6";"DIODE";"";
+"2";"4.7k";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"R3, R4";"Resistor";"";
+"1";"CONN_20X2";"CONN_20X2";"2X20";"J1";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"2";"DNI-4.7k";"R-US_R0603";"R0603";"R11, R12";"RESISTOR, American symbol";"";
+"2";"DNI-4.7k";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"R7, R8";"Resistor";"";
+"1";"DNI/Sparkfun QWIIC Breakout";"CONN_041X04_NO_SILK";"1X04_NO_SILK";"J5";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"1";"Female socket 1x4";"CONN_06NO_SILK_NO_POP";"1X06_NO_SILK";"J4";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"6";"INA219 purple board";"INA219";"INA219";"U3, U4, U5, U6, U7, U8";"";"";
+"6";"INA219AIDR";"INA219AIDR";"D0008A_N";"U2, U10, U11, U12, U13, U14";"";"";
+"1";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"JP18";"Normally open jumper";"";
+"1";"Micro JST";"CONN_021X02_NO_SILK";"1X02_NO_SILK";"JP8";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"14";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"JP1, JP2, JP3, JP4, JP5, JP6, JP7, JP10, JP11, JP12, JP13, JP14, JP15, JP17";"Standard 2-pin 0.1" header. Use with";"";
+"6";"R100";"R-US_R0805";"R0805";"R1, R2, R5, R6, R9, R10";"RESISTOR, American symbol";"";
+"1";"VDD-EN";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"JP9";"Normally closed trace jumper";"";
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_gerbers.zip b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_gerbers.zip
new file mode 100644
index 000000000..6acd612ae
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_gerbers.zip differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_schematic.pdf b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_schematic.pdf
new file mode 100644
index 000000000..749176d72
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_schematic.pdf differ
diff --git a/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_tnames.pdf b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_tnames.pdf
new file mode 100644
index 000000000..e9fae5fb6
Binary files /dev/null and b/hardware/beta-v1.3.2/cubesatsim-solar-b1.3.2_tnames.pdf differ
diff --git a/hardware/beta-v1.3.2/readme.md b/hardware/beta-v1.3.2/readme.md
new file mode 100644
index 000000000..16c85c0c9
--- /dev/null
+++ b/hardware/beta-v1.3.2/readme.md
@@ -0,0 +1,35 @@
+

+
+Here is information about the Beta version of the CubeSatSim V2 Boards, version beta v1.3.2
+
+There are 3 boards: STEM Payload, Solar (was Main in v1), and Battery
+
+Here's what the files are:
+
+*_gerbers.zip -- All gerber files used to fabricate PCBs along with .TXT drill file
+
+*_schematic.pdf -- Schematic
+
+*_pcb.png -- View of board
+
+*_pour.png -- View of board with fill
+
+*_top.png -- Top view of PCB generated by gerbers
+
+*_bottom.png -- Bottom view of PCB generated by gerbers
+
+*_tNames.pdf -- Top outline of components
+
+*_bNames.pdf -- Bottom outline of components
+
+*.mnt -- top SMD component placement data
+
+*.mnb -- bottom SMD component placement data
+
+*_bom.csv.txt -- Bill of Materials in CSV format
+
+I use PCBWay to fabricate PCBs https://pcbway.com
+
+Here is a very draft bill of materials: https://docs.google.com/spreadsheets/d/1Ta5UaJcinGozcheROrkfwXdGSDUZrXvQ1_nbIBdIIOY/edit?usp=sharing
+
+Draft wiki instructions: https://github.com/alanbjohnston/CubeSatSim/wiki/v1.3.2-0.-Home
diff --git a/hardware/frame/v1.3.2/cubesatsim_frame_side.v1.3.2.stl b/hardware/frame/v1.3.2/cubesatsim_frame_side.v1.3.2.stl
new file mode 100644
index 000000000..96d694348
Binary files /dev/null and b/hardware/frame/v1.3.2/cubesatsim_frame_side.v1.3.2.stl differ
diff --git a/hardware/frame/v1.3.2/cubesatsim_frame_side_camera.v1.3.2.stl b/hardware/frame/v1.3.2/cubesatsim_frame_side_camera.v1.3.2.stl
new file mode 100644
index 000000000..ff97bc1cf
Binary files /dev/null and b/hardware/frame/v1.3.2/cubesatsim_frame_side_camera.v1.3.2.stl differ
diff --git a/hardware/frame/v1.3.2/cubesatsim_frame_top_bottom.v1.3.2.stl b/hardware/frame/v1.3.2/cubesatsim_frame_top_bottom.v1.3.2.stl
new file mode 100644
index 000000000..88e4a6143
Binary files /dev/null and b/hardware/frame/v1.3.2/cubesatsim_frame_top_bottom.v1.3.2.stl differ
diff --git a/hardware/frame/v1.3.2/readme.md b/hardware/frame/v1.3.2/readme.md
new file mode 100644
index 000000000..a09f30a7b
--- /dev/null
+++ b/hardware/frame/v1.3.2/readme.md
@@ -0,0 +1,9 @@
+These are the STL files for printing the frame.
+
+You will need to print two of the top/bottom, and one of each side
+
+The source is availale at:
+
+https://cad.onshape.com/documents/ba47819ff100597297d1d967/w/f19409ec7cd5459afb429cb9/e/a0e0cc37dee6fb879c4bcc2b
+https://cad.onshape.com/documents/5374160b1b209f298471bf23/w/77e97d7333356f1dcfe6c902/e/6c75800e116cf1f6a984aaa4
+https://cad.onshape.com/documents/1e544928f336f4755d6edfbe/w/b9582e1314647916bddf672c/e/41923e90fc3648cd04399c0e
diff --git a/hardware/frame/v2.0/cubesatsim_frame_side.v2.0.stl b/hardware/frame/v2.0/cubesatsim_frame_side.v2.0.stl
new file mode 100644
index 000000000..175042696
Binary files /dev/null and b/hardware/frame/v2.0/cubesatsim_frame_side.v2.0.stl differ
diff --git a/hardware/frame/v2.0/cubesatsim_frame_side_camera.v2.0.stl b/hardware/frame/v2.0/cubesatsim_frame_side_camera.v2.0.stl
new file mode 100644
index 000000000..3e6cf0a76
Binary files /dev/null and b/hardware/frame/v2.0/cubesatsim_frame_side_camera.v2.0.stl differ
diff --git a/hardware/frame/v2.0/cubesatsim_frame_top_bottom.v2.0.stl b/hardware/frame/v2.0/cubesatsim_frame_top_bottom.v2.0.stl
new file mode 100644
index 000000000..88e4a6143
Binary files /dev/null and b/hardware/frame/v2.0/cubesatsim_frame_top_bottom.v2.0.stl differ
diff --git a/hardware/frame/v2.0/readme.md b/hardware/frame/v2.0/readme.md
new file mode 100644
index 000000000..ccb58d268
--- /dev/null
+++ b/hardware/frame/v2.0/readme.md
@@ -0,0 +1,11 @@
+These are the STL files for printing the frame.
+
+
+
+You will need to print two of the top/bottom, and one of each side
+
+The source is availale at:
+
+https://cad.onshape.com/documents/ba47819ff100597297d1d967/w/f19409ec7cd5459afb429cb9/e/a0e0cc37dee6fb879c4bcc2b
+https://cad.onshape.com/documents/1515e31c7fa5f6258ef39ae7/w/36f6069826ee0c0263f8d85e/e/2b7801717a8e1af3df455057
+https://cad.onshape.com/documents/188300bd4469521b14597507/w/546e1730182c1520c46b050d/e/ceef7084a00eb9b26c486bb6
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1.mnb b/hardware/v2.0/cubesatsim-battery-v2.0.1.mnb
new file mode 100644
index 000000000..48b4e2ca1
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-battery-v2.0.1.mnb
@@ -0,0 +1,3 @@
+JP4 12.92 79.27 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP5 66.93 74.27 90 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP6 17.51 69.85 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1.mnt b/hardware/v2.0/cubesatsim-battery-v2.0.1.mnt
new file mode 100644
index 000000000..5646f1682
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-battery-v2.0.1.mnt
@@ -0,0 +1,11 @@
+BT1 44.48 57.58 0 1024 BAT_1024
+BT2 41.27 29.90 0 1012 BAT_1012
+C1 4.88 58.78 0 DNI/0.1µF 0603
+J1 32.68 74.23 0 CONN_20X2 2X20
+JP9 3.38 54.25 0 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP10 6.71 50.72 0 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP11 6.85 54.23 0 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP12 3.31 50.70 0 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+R1 17.45 69.49 0 DNI/R100 R0805
+U1 12.19 67.41 180 INA219 purple board INA219
+U2 4.55 62.79 0 INA219AIDR D0008A_N
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1_bom.csv.txt b/hardware/v2.0/cubesatsim-battery-v2.0.1_bom.csv.txt
new file mode 100644
index 000000000..d7850b630
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-battery-v2.0.1_bom.csv.txt
@@ -0,0 +1,23 @@
+"Part";"Value";"Device";"Package";"Description";"";
+"BT1";"1024";"1024";"BAT_1024";"Check availability";"";
+"BT2";"1012";"1012";"BAT_1012";"Check availability";"";
+"C1";"DNI/0.1µF";"CAP_CERAMIC0603";"0603";"Ceramic Capacitors";"";
+"F1";"PTC";"PTCPTH";"PTC";"Resettable Fuse PTC";"";
+"J1";"CONN_20X2";"CONN_20X2";"2X20";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP1";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP2";"";"CONN_01";"1X01";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP3";"";"CONN_01";"1X01";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP4";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP5";"JUMPER-SMT_2_NC_TRACE_SILK";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"Normally closed trace jumper";"";
+"JP6";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP7";"";"CONN_01";"1X01";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP8";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP9";"JUMPER-SMT_2_NC_TRACE_SILK";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"Normally closed trace jumper";"";
+"JP10";"JUMPER-SMT_2_NC_TRACE_SILK";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"Normally closed trace jumper";"";
+"JP11";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP12";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP13";"";"CONN_01";"1X01";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP14";"";"CONN_01";"1X01";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"R1";"DNI/R100";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"U1";"INA219 purple board";"INA219";"INA219";"";"";
+"U2";"INA219AIDR";"INA219AIDR";"D0008A_N";"";"";
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1_bottom.png b/hardware/v2.0/cubesatsim-battery-v2.0.1_bottom.png
new file mode 100644
index 000000000..41f92256d
Binary files /dev/null and b/hardware/v2.0/cubesatsim-battery-v2.0.1_bottom.png differ
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1_centroid.zip b/hardware/v2.0/cubesatsim-battery-v2.0.1_centroid.zip
new file mode 100644
index 000000000..d72238760
Binary files /dev/null and b/hardware/v2.0/cubesatsim-battery-v2.0.1_centroid.zip differ
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1_gerbers.zip b/hardware/v2.0/cubesatsim-battery-v2.0.1_gerbers.zip
new file mode 100644
index 000000000..273179833
Binary files /dev/null and b/hardware/v2.0/cubesatsim-battery-v2.0.1_gerbers.zip differ
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1_pcb.png b/hardware/v2.0/cubesatsim-battery-v2.0.1_pcb.png
new file mode 100644
index 000000000..1d2f98ad0
Binary files /dev/null and b/hardware/v2.0/cubesatsim-battery-v2.0.1_pcb.png differ
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1_pour.png b/hardware/v2.0/cubesatsim-battery-v2.0.1_pour.png
new file mode 100644
index 000000000..ab4c33853
Binary files /dev/null and b/hardware/v2.0/cubesatsim-battery-v2.0.1_pour.png differ
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1_schematic.pdf b/hardware/v2.0/cubesatsim-battery-v2.0.1_schematic.pdf
new file mode 100644
index 000000000..681a87c72
Binary files /dev/null and b/hardware/v2.0/cubesatsim-battery-v2.0.1_schematic.pdf differ
diff --git a/hardware/v2.0/cubesatsim-battery-v2.0.1_top.png b/hardware/v2.0/cubesatsim-battery-v2.0.1_top.png
new file mode 100644
index 000000000..fa61c7085
Binary files /dev/null and b/hardware/v2.0/cubesatsim-battery-v2.0.1_top.png differ
diff --git a/hardware/v2.0/cubesatsim-main-v2.0.mnb b/hardware/v2.0/cubesatsim-main-v2.0.mnb
new file mode 100644
index 000000000..8d335ba68
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-main-v2.0.mnb
@@ -0,0 +1,18 @@
+D1 63.55 60.58 0 1N5817 D-2.5
+D2 72.01 10.49 0 1N5817 D-2.5
+D3 66.45 10.62 180 1N4148 D-2.5
+D4 63.65 54.61 0 1N5817 D-2.5
+D8 59.31 7.52 270 DNI/5V1 Zener 1W ZDIO-2.5
+D9 19.71 45.92 0 DNI/1N5817 D-2.5
+D10 77.50 10.46 0 1N5817 D-2.5
+JP1 72.17 8.66 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP2 24.73 59.61 0 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP3 19.63 58.93 270 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP4 51.94 53.34 180 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP5 75.08 56.49 270 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP6 26.31 37.01 180 JUMPER-SMT_2_NC_TRACE_SILK SMT-JUMPER_2_NC_TRACE_SILK
+JP7 15.95 61.99 90 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP8 37.93 40.67 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP9 45.17 51.10 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+JP10 63.64 56.54 0 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+X1 71.86 61.21 270 SC1464-ND PG203J
diff --git a/hardware/v2.0/cubesatsim-main-v2.0.mnt b/hardware/v2.0/cubesatsim-main-v2.0.mnt
new file mode 100644
index 000000000..a364bdebd
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-main-v2.0.mnt
@@ -0,0 +1,39 @@
+C1 18.75 76.02 270 18pF C0603
+C2 18.69 71.88 270 16pF C0603
+C3 16.38 10.11 180 18pF C0603
+C4 20.68 10.16 180 16pF C0603
+C7 55.60 56.62 0 DNI/47uF C0603
+C8 59.00 47.55 270 DNI/100nF C0603
+C10 66.83 3.91 270 DNI/100nF C0603
+D5 63.53 62.56 180 DNI/B5817WS SOD-323F
+D6 72.16 8.69 180 DNI/B5817WS SOD-323F
+D7 66.47 8.84 0 DNI/4148WS SOD-323F
+D11 63.65 56.59 180 DNI/B5817WS SOD-323F
+E1 6.80 76.35 180 ANT-916-CHP-T XDCR_ANT-916-CHP-T
+E2 19.18 3.81 0 ANT-916-CHP-T XDCR_ANT-916-CHP-T
+J1 32.55 66.61 0 CONN_20X2 2X20
+J8 36.17 72.01 0 Sparkfun USB-C Breakout 1X06_NO_SILK
+J9 36.35 74.15 180 DNI/USB4105-GF-A or GT-USB-7010B USB-C-16P-2LAYER-PADS
+J13 8.92 31.68 0 SJ1-2503A CONN_SJ1-2503A
+J14 15.95 31.76 0 SJ1-2503A CONN_SJ1-2503A
+L1 16.76 73.94 90 13nH L0603
+L2 18.49 12.17 180 13nH L0603
+R2 54.00 62.26 0 DNI/1k R0603
+R4 58.39 62.26 180 DNI/1k R0603
+R5 29.46 76.45 180 DNI/5.1k R0603
+R6 43.18 76.48 0 DNI/5.1k R0603
+R10 64.26 72.06 0 DNI/1k R0603
+R11 24.16 72.06 0 DNI/100 R0603
+R12 47.55 72.42 0 DNI/220 R0603
+R16 20.07 60.05 0 DNI/68 R0805
+R17 24.71 60.15 270 DNI/180 R0603
+R18 32.94 60.20 180 DNI/68 R0805
+R21 55.42 51.26 0 DNI/100 R0603
+R22 59.33 44.63 0 DNI/220 R0603
+R25 67.59 40.77 90 DNI/4.7k R0603
+R26 76.53 40.79 90 DNI/4.7k R0603
+R28 61.98 8.81 0 DNI/10k R0603
+R31 3.86 44.37 0 DNI/220 R0603
+R32 3.40 60.55 180 DNI/1k R0603
+U1 54.36 27.48 270 Raspberry Pi Pico PICO-PKG-NO_DEBUG
+U6 39.24 51.22 270 SR105U SR_FRS_0W5
diff --git a/hardware/v2.0/cubesatsim-main-v2.0_bom.csv.txt b/hardware/v2.0/cubesatsim-main-v2.0_bom.csv.txt
new file mode 100644
index 000000000..55ff16da5
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-main-v2.0_bom.csv.txt
@@ -0,0 +1,93 @@
+"Part";"Value";"Device";"Package";"Description";"";
+"C1";"18pF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"302010097";"";
+"C2";"16pF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"302010097";"";
+"C3";"18pF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"302010097";"";
+"C4";"16pF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"302010097";"";
+"C5";"47uF";"CAPPTH";"CAP-PTH-SMALL";"Capacitor";"";
+"C6";"100nF";"CAPPTH";"CAP-PTH-SMALL";"Capacitor";"";
+"C7";"DNI/47uF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"302010097";"";
+"C8";"DNI/100nF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"302010097";"";
+"C9";"100nF";"CAPPTH";"CAP-PTH-SMALL";"Capacitor";"";
+"C10";"DNI/100nF";"CERAMIC-10PF-50V-5%-NPO(0603)";"C0603";"302010097";"";
+"D1";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D2";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D3";"1N4148";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D4";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D5";"DNI/B5817WS";"DIODESOD-323F";"SOD-323F";"Diode";"";
+"D6";"DNI/B5817WS";"DIODESOD-323F";"SOD-323F";"Diode";"";
+"D7";"DNI/4148WS";"DIODESOD-323F";"SOD-323F";"Diode";"";
+"D8";"DNI/5V1 Zener 1W";"ZENER-DIODEZD-2.5";"ZDIO-2.5";"Z-Diode";"";
+"D9";"DNI/1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D10";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D11";"DNI/B5817WS";"DIODESOD-323F";"SOD-323F";"Diode";"";
+"E1";"ANT-916-CHP-T";"ANT-916-CHP-T";"XDCR_ANT-916-CHP-T";"868MHz ISM, LoRa, Sensor Networks, SigFox Chip RF Antenna 863MHz ~ 873MHz 0.5dBi Solder Surface Mount Check prices";"";
+"E2";"ANT-916-CHP-T";"ANT-916-CHP-T";"XDCR_ANT-916-CHP-T";"868MHz ISM, LoRa, Sensor Networks, SigFox Chip RF Antenna 863MHz ~ 873MHz 0.5dBi Solder Surface Mount Check prices";"";
+"J1";"CONN_20X2";"CONN_20X2";"2X20";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"J4";"MPU6050";"M08NO_SILK_FEMALE_PTH";"1X08_NO_SILK@1";"Header 8";"";
+"J5";"BME280";"M04NO_SILK_ALL_ROUND";"1X04_NO_SILK_ALL_ROUND";"Header 4";"";
+"J6";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"J7";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"J8";"Sparkfun USB-C Breakout";"CONN_06NO_SILK_FEMALE_PTH";"1X06_NO_SILK";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"J9";"DNI/USB4105-GF-A or GT-USB-7010B";"USB_C_2-LAYER_PADS";"USB-C-16P-2LAYER-PADS";"USB Type C 16Pin Connector";"";
+"J10";"DNI/Sparkfun QWIIC Breakout";"CONN_041X04_NO_SILK";"1X04_NO_SILK";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"J12";"DNI/1x4 pin header";"CONN_041X04_NO_SILK";"1X04_NO_SILK";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"J13";"SJ1-2503A";"SJ1-2503A";"CONN_SJ1-2503A";"";"";
+"J14";"SJ1-2503A";"SJ1-2503A";"CONN_SJ1-2503A";"";"";
+"J15";"";"CONN_06NO_SILK_NO_POP";"1X06_NO_SILK";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP1";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP2";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP3";"JUMPER-SMT_2_NC_TRACE_SILK";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"Normally closed trace jumper";"";
+"JP4";"JUMPER-SMT_2_NC_TRACE_SILK";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"Normally closed trace jumper";"";
+"JP5";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP6";"JUMPER-SMT_2_NC_TRACE_SILK";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"Normally closed trace jumper";"";
+"JP7";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP8";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP9";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP10";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"L1";"13nH";"SMD-FERRITE-CHIP-120-OHM-500MA(0603)";"L0603";"303030001";"";
+"L2";"13nH";"SMD-FERRITE-CHIP-120-OHM-500MA(0603)";"L0603";"303030001";"";
+"LED1";"Yellow 5mm";"LED3MM";"LED3MM";"LED";"";
+"LED2";"White 5mm";"LED3MM";"LED3MM";"LED";"";
+"LED3";"Green 5mm";"LED3MM";"LED3MM";"LED";"";
+"LED4";"Blue 5mm";"LED3MM";"LED3MM";"LED";"";
+"LED5";"Red 5mm";"LED3MM";"LED3MM";"LED";"";
+"R1";"1K";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R2";"DNI/1k";"R-EU_R0603";"R0603";"RESISTOR, European symbol";"";
+"R3";"1K";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R4";"DNI/1k";"R-EU_R0603";"R0603";"RESISTOR, European symbol";"";
+"R5";"DNI/5.1k";"R-EU_R0603";"R0603";"RESISTOR, European symbol";"";
+"R6";"DNI/5.1k";"R-EU_R0603";"R0603";"RESISTOR, European symbol";"";
+"R7";"1k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R8";"100";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R9";"220";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R10";"DNI/1k";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R11";"DNI/100";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R12";"DNI/220";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R13";"68";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R14";"180";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R15";"68";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R16";"DNI/68";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"R17";"DNI/180";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R18";"DNI/68";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"R19";"100";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"Resistor";"";
+"R20";"220";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"Resistor";"";
+"R21";"DNI/100";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R22";"DNI/220";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R23";"4.7k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R24";"4.7k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R25";"DNI/4.7k";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R26";"DNI/4.7k";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R27";"10K";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R28";"DNI/10k";"R-EU_R0603";"R0603";"RESISTOR, European symbol";"";
+"R29";"220";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R30";"1k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R31";"DNI/220";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R32";"DNI/1k";"SMD-RES-1.2K-1%-1/10W(0603)";"R0603";"301010206";"";
+"R33";"DNI/4.7k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"R34";"DNI/4.7k";"RESISTORPTH-1/4W-VERT";"AXIAL-0.1";"Resistor";"";
+"S1";"RA-SPST";"RA-SPST";"RA-SPST";"";"";
+"U1";"Raspberry Pi Pico";"RASPBERRY_PICO-NO_DEBUG";"PICO-PKG-NO_DEBUG";"";"";
+"U6";"SR105U";"SR_FRS_0W5";"SR_FRS_0W5";"";"";
+"X1";"SC1464-ND";"PG203J";"PG203J";"MIC/HEADPHONE JACK";"";
+"X2";"SMA-VERT";"SMA-VERT";"SMA-VERT";"";"";
+"X3";"SMA-VERT";"SMA-VERT";"SMA-VERT";"";"";
diff --git a/hardware/v2.0/cubesatsim-main-v2.0_bottom.png b/hardware/v2.0/cubesatsim-main-v2.0_bottom.png
new file mode 100644
index 000000000..e298f5819
Binary files /dev/null and b/hardware/v2.0/cubesatsim-main-v2.0_bottom.png differ
diff --git a/hardware/v2.0/cubesatsim-main-v2.0_gerbers.zip b/hardware/v2.0/cubesatsim-main-v2.0_gerbers.zip
new file mode 100644
index 000000000..eed74445a
Binary files /dev/null and b/hardware/v2.0/cubesatsim-main-v2.0_gerbers.zip differ
diff --git a/hardware/v2.0/cubesatsim-main-v2.0_pcb.png b/hardware/v2.0/cubesatsim-main-v2.0_pcb.png
new file mode 100644
index 000000000..29633023f
Binary files /dev/null and b/hardware/v2.0/cubesatsim-main-v2.0_pcb.png differ
diff --git a/hardware/v2.0/cubesatsim-main-v2.0_pour.png b/hardware/v2.0/cubesatsim-main-v2.0_pour.png
new file mode 100644
index 000000000..96f242199
Binary files /dev/null and b/hardware/v2.0/cubesatsim-main-v2.0_pour.png differ
diff --git a/hardware/v2.0/cubesatsim-main-v2.0_schematic.pdf b/hardware/v2.0/cubesatsim-main-v2.0_schematic.pdf
new file mode 100644
index 000000000..d266622bf
Binary files /dev/null and b/hardware/v2.0/cubesatsim-main-v2.0_schematic.pdf differ
diff --git a/hardware/v2.0/cubesatsim-main-v2.0_top.png b/hardware/v2.0/cubesatsim-main-v2.0_top.png
new file mode 100644
index 000000000..40cb176e4
Binary files /dev/null and b/hardware/v2.0/cubesatsim-main-v2.0_top.png differ
diff --git a/hardware/v2.0/cubesatsim-solar-v2.0.mnb b/hardware/v2.0/cubesatsim-solar-v2.0.mnb
new file mode 100644
index 000000000..3ac6ed082
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-solar-v2.0.mnb
@@ -0,0 +1,12 @@
+D1 37.58 48.87 180 1N5817 D-2.5
+D2 37.66 42.52 180 1N5817 D-2.5
+D3 37.50 35.95 180 1N5817 D-2.5
+D4 42.94 48.94 0 1N5817 D-2.5
+D5 42.94 42.42 0 1N5817 D-2.5
+D6 42.79 36.07 0 1N5817 D-2.5
+JP9 1.35 57.85 270 VDD-EN SMT-JUMPER_2_NC_TRACE_SILK
+JP18 24.75 62.60 180 JUMPER-SMT_2_NO_SILK SMT-JUMPER_2_NO_SILK
+U5 71.44 19.89 90 INA219 purple board INA219
+U6 8.59 48.95 270 INA219 purple board INA219
+U7 8.46 20.29 270 INA219 purple board INA219
+U8 71.36 48.21 90 INA219 purple board INA219
diff --git a/hardware/v2.0/cubesatsim-solar-v2.0.mnt b/hardware/v2.0/cubesatsim-solar-v2.0.mnt
new file mode 100644
index 000000000..54cb3f584
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-solar-v2.0.mnt
@@ -0,0 +1,29 @@
+C2 17.54 37.77 0 0.1µF 0603
+C3 17.41 21.59 0 0.1µF 0603
+C4 17.56 11.14 0 0.1µF 0603
+C5 17.53 50.09 0 0.1µF 0603
+C6 61.82 19.28 180 0.1µF 0603
+C7 62.06 38.65 180 0.1µF 0603
+D7 42.95 38.00 0 1A/23V/620mV SOD-323
+D8 43.08 44.40 0 1A/23V/620mV SOD-323
+D9 43.43 50.75 0 1A/23V/620mV SOD-323
+D10 37.72 50.67 180 1A/23V/620mV SOD-323
+D11 37.62 37.92 180 1A/23V/620mV SOD-323
+D12 37.90 44.40 180 1A/23V/620mV SOD-323
+J1 32.55 66.61 0 CONN_20X2 2X20
+R1 11.58 43.79 270 R100 R0805
+R2 11.68 15.01 270 R100 R0805
+R5 24.84 14.99 90 R100 R0805
+R6 24.87 43.84 270 R100 R0805
+R9 68.07 25.10 90 R100 R0805
+R10 68.19 53.47 90 R100 R0805
+R11 42.91 62.08 0 DNI-4.7k R0603
+R12 36.87 62.08 0 DNI-4.7k R0603
+U2 17.53 44.60 0 INA219AIDR D0008A_N
+U3 48.65 48.20 90 INA219 purple board INA219
+U4 30.84 48.90 270 INA219 purple board INA219
+U10 17.45 26.75 0 INA219AIDR D0008A_N
+U11 17.68 16.66 0 INA219AIDR D0008A_N
+U12 17.50 55.36 0 INA219AIDR D0008A_N
+U13 61.72 24.82 0 INA219AIDR D0008A_N
+U14 61.58 44.20 0 INA219AIDR D0008A_N
diff --git a/hardware/v2.0/cubesatsim-solar-v2.0_bom.csv.txt b/hardware/v2.0/cubesatsim-solar-v2.0_bom.csv.txt
new file mode 100644
index 000000000..c761de98a
--- /dev/null
+++ b/hardware/v2.0/cubesatsim-solar-v2.0_bom.csv.txt
@@ -0,0 +1,64 @@
+"Part";"Value";"Device";"Package";"Description";"";
+"C2";"0.1µF";"CAP_CERAMIC0603";"0603";"Ceramic Capacitors";"";
+"C3";"0.1µF";"CAP_CERAMIC0603";"0603";"Ceramic Capacitors";"";
+"C4";"0.1µF";"CAP_CERAMIC0603";"0603";"Ceramic Capacitors";"";
+"C5";"0.1µF";"CAP_CERAMIC0603";"0603";"Ceramic Capacitors";"";
+"C6";"0.1µF";"CAP_CERAMIC0603";"0603";"Ceramic Capacitors";"";
+"C7";"0.1µF";"CAP_CERAMIC0603";"0603";"Ceramic Capacitors";"";
+"D1";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D2";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D3";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D4";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D5";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D6";"1N5817";"DIODE-D-2.5";"D-2.5";"DIODE";"";
+"D7";"1A/23V/620mV";"DIODE-SCHOTTKY-BAT20J";"SOD-323";"Schottky diode";"";
+"D8";"1A/23V/620mV";"DIODE-SCHOTTKY-BAT20J";"SOD-323";"Schottky diode";"";
+"D9";"1A/23V/620mV";"DIODE-SCHOTTKY-BAT20J";"SOD-323";"Schottky diode";"";
+"D10";"1A/23V/620mV";"DIODE-SCHOTTKY-BAT20J";"SOD-323";"Schottky diode";"";
+"D11";"1A/23V/620mV";"DIODE-SCHOTTKY-BAT20J";"SOD-323";"Schottky diode";"";
+"D12";"1A/23V/620mV";"DIODE-SCHOTTKY-BAT20J";"SOD-323";"Schottky diode";"";
+"J1";"CONN_20X2";"CONN_20X2";"2X20";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"J5";"DNI/Sparkfun QWIIC Breakout";"CONN_041X04_NO_SILK";"1X04_NO_SILK";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP1";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP2";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP3";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP4";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP5";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP6";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP7";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP8";"Micro JST";"CONN_021X02_NO_SILK";"1X02_NO_SILK";"Multi connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP9";"VDD-EN";"JUMPER-SMT_2_NC_TRACE_SILK";"SMT-JUMPER_2_NC_TRACE_SILK";"Normally closed trace jumper";"";
+"JP10";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP11";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP12";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP13";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP14";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP15";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP16";"";"CONN_01PTH_NO_SILK_YES_STOP";"1X01_NO_SILK";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"JP17";"Micro JST";"M02JST-PTH-VERT";"JST-2-PTH-VERT";"Standard 2-pin 0.1" header. Use with";"";
+"JP18";"JUMPER-SMT_2_NO_SILK";"JUMPER-SMT_2_NO_SILK";"SMT-JUMPER_2_NO_SILK";"Normally open jumper";"";
+"JP19";"";"CONN_01PTH_NO_SILK_YES_STOP";"1X01_NO_SILK";"Single connection point. Often used as Generic Header-pin footprint for 0.1 inch spaced/style header connections";"";
+"R1";"R100";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"R2";"R100";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"R3";"4.7k";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"Resistor";"";
+"R4";"4.7k";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"Resistor";"";
+"R5";"R100";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"R6";"R100";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"R7";"DNI-4.7k";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"Resistor";"";
+"R8";"DNI-4.7k";"RESISTORPTH-1/4W-VERT-KIT";"AXIAL-0.1EZ";"Resistor";"";
+"R9";"R100";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"R10";"R100";"R-US_R0805";"R0805";"RESISTOR, American symbol";"";
+"R11";"DNI-4.7k";"R-US_R0603";"R0603";"RESISTOR, American symbol";"";
+"R12";"DNI-4.7k";"R-US_R0603";"R0603";"RESISTOR, American symbol";"";
+"U2";"INA219AIDR";"INA219AIDR";"D0008A_N";"";"";
+"U3";"INA219 purple board";"INA219";"INA219";"";"";
+"U4";"INA219 purple board";"INA219";"INA219";"";"";
+"U5";"INA219 purple board";"INA219";"INA219";"";"";
+"U6";"INA219 purple board";"INA219";"INA219";"";"";
+"U7";"INA219 purple board";"INA219";"INA219";"";"";
+"U8";"INA219 purple board";"INA219";"INA219";"";"";
+"U10";"INA219AIDR";"INA219AIDR";"D0008A_N";"";"";
+"U11";"INA219AIDR";"INA219AIDR";"D0008A_N";"";"";
+"U12";"INA219AIDR";"INA219AIDR";"D0008A_N";"";"";
+"U13";"INA219AIDR";"INA219AIDR";"D0008A_N";"";"";
+"U14";"INA219AIDR";"INA219AIDR";"D0008A_N";"";"";
diff --git a/hardware/v2.0/cubesatsim-solar-v2.0_bottom.png b/hardware/v2.0/cubesatsim-solar-v2.0_bottom.png
new file mode 100644
index 000000000..d227199f6
Binary files /dev/null and b/hardware/v2.0/cubesatsim-solar-v2.0_bottom.png differ
diff --git a/hardware/v2.0/cubesatsim-solar-v2.0_gerbers.zip b/hardware/v2.0/cubesatsim-solar-v2.0_gerbers.zip
new file mode 100644
index 000000000..5c910832c
Binary files /dev/null and b/hardware/v2.0/cubesatsim-solar-v2.0_gerbers.zip differ
diff --git a/hardware/v2.0/cubesatsim-solar-v2.0_schematic.pdf b/hardware/v2.0/cubesatsim-solar-v2.0_schematic.pdf
new file mode 100644
index 000000000..283f53565
Binary files /dev/null and b/hardware/v2.0/cubesatsim-solar-v2.0_schematic.pdf differ
diff --git a/hardware/v2.0/cubesatsim-solar-v2.0_top.png b/hardware/v2.0/cubesatsim-solar-v2.0_top.png
new file mode 100644
index 000000000..f5afb2ddc
Binary files /dev/null and b/hardware/v2.0/cubesatsim-solar-v2.0_top.png differ
diff --git a/hardware/v2.0/readme.md b/hardware/v2.0/readme.md
new file mode 100644
index 000000000..74dc6a559
--- /dev/null
+++ b/hardware/v2.0/readme.md
@@ -0,0 +1,31 @@
+
+
+Here is information about the CubeSatSim PCBs, version v2.0
+
+There are 3 boards: Main, Solar, and Battery
+
+Here's what the files are:
+
+*_gerbers.zip -- All gerber files used to fabricate PCBs along with .TXT drill file
+
+*_schematic.pdf -- Schematic
+
+*_pcb.png -- View of board
+
+*_pour.png -- View of board with fill
+
+*_top.png -- Top view of PCB generated by gerbers
+
+*_bottom.png -- Bottom view of PCB generated by gerbers
+
+*.mnt -- top SMD component placement data
+
+*.mnb -- bottom SMD component placement data
+
+*_bom.csv.txt -- Bill of Materials in CSV format
+
+I use PCBWay to fabricate PCBs https://pcbway.com
+
+Here is a very draft bill of materials: https://CubeSatSim.org/bom-v2
+
+Wiki instructions: https://github.com/alanbjohnston/CubeSatSim/wiki/
diff --git a/ina219.py b/ina219.py
index 5da9eeecd..6f1b44bd6 100644
--- a/ina219.py
+++ b/ina219.py
@@ -7,6 +7,12 @@
from adafruit_extended_bus import ExtendedI2C as I2C
from adafruit_ina219 import INA219
from adafruit_ina219 import ADCResolution, BusVoltageRange
+import signal
+
+# Don't turn these signal into exceptions, just die.
+# https://stackoverflow.com/questions/26692284/how-to-prevent-brokenpipeerror-when-doing-a-flush-in-python
+signal.signal(signal.SIGINT, signal.SIG_DFL)
+signal.signal(signal.SIGPIPE, signal.SIG_DFL)
if __name__ == "__main__":
# print 'Length: ', len(sys.argv)
@@ -346,8 +352,11 @@
print("Python Error Recovered!")
if not single:
- inp = input()
-# print(inp)
+ try:
+ inp = input()
+# print(inp)
+ except:
+ print("Python error getting input!")
else:
break
diff --git a/install b/install
index c47cb7d37..2991d2b8d 100755
--- a/install
+++ b/install
@@ -1,6 +1,6 @@
#!/bin/bash
-echo -e "\ninstallation script for CubeSatSim v1.2\n"
+echo -e "\ninstallation script for CubeSatSim v2.0\n"
FILE=/home/pi/CubeSatSim/sim.cfg
if [ -f "$FILE" ]; then
@@ -10,6 +10,22 @@ else
echo "AMSAT 1 0.0 0.0" > /home/pi/CubeSatSim/sim.cfg
fi
+FILE=/home/pi/CubeSatSim/command_tx
+if [ -f "$FILE" ]; then
+ echo "$FILE exists."
+else
+ echo "creating $FILE"
+ echo "True\n" > /home/pi/CubeSatSim/command_tx
+fi
+
+FILE=/home/pi/CubeSatSim/command_count.txt
+if [ -f "$FILE" ]; then
+ echo "$FILE exists."
+else
+ echo "creating $FILE"
+ echo "0\n" > /home/pi/CubeSatSim/command_count.txt
+fi
+
cd
CubeSatSim/config -c -n
@@ -18,30 +34,37 @@ CubeSatSim/config -l -n
sudo apt-get update && sudo apt-get dist-upgrade -y
+sudo apt-get remove pulseaudio -y
+
# removed wiringpi and python-picamera python3-picamera
sudo apt-get install -y git libasound2-dev i2c-tools build-essential libgd-dev libmagic-dev minicom
cd /tmp
-wget https://project-downloads.drogon.net/wiringpi-latest.deb
+# wget https://project-downloads.drogon.net/wiringpi-latest.deb
+
+# sudo dpkg -i wiringpi-latest.deb
+
+cd
-sudo dpkg -i wiringpi-latest.deb
+git clone https://github.com/alanbjohnston/WiringPi
+cd WiringPi
+./build debian
+sudo dpkg -i debian-template/wiringpi-2.61-1.deb
cd
#changed to python3-smbus
-sudo apt install -y python3-pip python3-smbus
+sudo apt install -y python3-pip python3-smbus libjpeg-dev zlib1g-dev libfreetype6-dev libopenjp2-7 libtiff5 python3-pil python3-serial
sudo pip3 install --upgrade setuptools
sudo pip3 install adafruit-blinka RPI.GPIO adafruit-extended-bus adafruit-circuitpython-ina219
-
-
cd ~/CubeSatSim
-git pull
+git pull --no-rebase
make debug
@@ -50,7 +73,7 @@ if [ -f "$FILE" ]; then
echo "$FILE exists."
else
echo "creating $FILE"
- echo "ARG1=f" > .mode
+ echo "b" > .mode
fi
cd
@@ -72,7 +95,7 @@ git clone https://github.com/alanbjohnston/pi-power-button.git
cd pi-power-button
-git checkout v1.2
+git checkout master
./script/install
@@ -91,7 +114,6 @@ cp /home/pi/CubeSatSim/sstv/sstv_image_1_320_x_256.jpg /home/pi/CubeSatSim/sstv_
echo "Copying SSTV image 2"
cp /home/pi/CubeSatSim/sstv/sstv_image_2_320_x_256.jpg /home/pi/CubeSatSim/sstv_image_2_320_x_256.jpg
-
cd
git clone https://github.com/alanbjohnston/rpitx.git
@@ -101,15 +123,21 @@ cd rpitx
./install.sh
+cd
+
cd
sudo cp ~/CubeSatSim/systemd/cubesatsim.service /etc/systemd/system/cubesatsim.service
sudo systemctl enable cubesatsim
-sudo cp ~/CubeSatSim/systemd/rpitx.service /etc/systemd/system/rpitx.service
+sudo cp ~/CubeSatSim/systemd/transmit.service /etc/systemd/system/transmit.service
+
+# sudo systemctl enable transmit
+
+sudo cp ~/CubeSatSim/systemd/command.service /etc/systemd/system/command.service
-sudo systemctl enable rpitx
+sudo systemctl enable command
sudo cp /boot/config.txt /boot/config.txt.0
@@ -125,8 +153,13 @@ sudo raspi-config nonint do_legacy 0
#if [ "$1" = "u" ]; then
#fi
- sudo sed -i 's/console=serial0,115200 //g' /boot/cmdline.txt
+## sudo sed -i 's/console=serial0,115200 //g' /boot/cmdline.txt
+
+ sudo sed -i 's/console=serial0,115200 //g' /boot/cmdline.txt
+
+ sudo sed -i 's/console=tty1 r/console=tty1 maxcpus=1 r/g' /boot/cmdline.txt # single core if Pi Zero 2
+
sudo sed -i 's/#dtparam=i2c_arm=on/dtparam=i2c_arm=on/g' /boot/config.txt
if [[ $(grep 'dtoverlay=i2c-gpio,bus=3,i2c_gpio_delay_us=1,i2c_gpio_sda=23,i2c_gpio_scl=24' /boot/config.txt) ]]; then
@@ -164,6 +197,73 @@ sudo raspi-config nonint do_legacy 0
sudo sed -i 's/ rootwait/ rootwait modules-load=dwc2,g_ether/g' /boot/cmdline.txt
fi
+ if [[ $(grep 'dtparam=audio=on' /boot/config.txt) ]]; then
+ echo "dtparam=audio=on already in /boot/config.txt"
+ else
+ echo "adding dtparam=audio=on to /boot/config.txt"
+ sudo sh -c 'echo "\ndtparam=audio=on" >> /boot/config.txt'
+ fi
+
+ if [[ $(grep 'dtoverlay=audremap,enable_jack=on' /boot/config.txt) ]]; then
+ echo "dtoverlay=audremap,enable_jack=on already in /boot/config.txt"
+ else
+ echo "adding dtoverlay=audremap,enable_jack=on to /boot/config.txt"
+ sudo sh -c 'echo "\ndtoverlay=audremap,enable_jack=on" >> /boot/config.txt'
+ fi
+
+ if [[ $(grep 'dtoverlay=pwm,pin=18,func=2' /boot/config.txt) ]]; then
+ echo "dtoverlay=pwm,pin=18,func=2 already in /boot/config.txt"
+ else
+ echo "adding to /boot/config.txt"
+ sudo sh -c 'echo "\ndtoverlay=pwm,pin=18,func=2" >> /boot/config.txt'
+ fi
+
+ if [[ $(grep 'disable_splash=1 ' /boot/config.txt) ]]; then
+ echo "disable_splash=1 already in /boot/config.txt"
+ else
+ echo "adding to /boot/config.txt"
+ sudo sh -c 'echo "\ndisable_splash=1" >> /boot/config.txt'
+ fi
+
+ if [[ $(grep 'boot_delay=0' /boot/config.txt) ]]; then
+ echo "boot_delay=0 already in /boot/config.txt"
+ else
+ echo "adding to /boot/config.txt"
+ sudo sh -c 'echo "\nboot_delay=0" >> /boot/config.txt'
+ fi
+
+ if ! grep -q force_turbo=1 /boot/config.txt ; then sudo sh -c 'echo "force_turbo=1" >> /boot/config.txt'; fi
+
+sudo sh -c 'echo "\n" >> /boot/config.txt'
+
+changed=0
+value=`cat /home/pi/CubeSatSim/sim.cfg`
+echo "$value" > /dev/null
+set -- $value
+
+if [ -z "$1" ] ; then n1="AMSAT" ; changed=1 ; else n1=$1 ; fi # callsign
+if [ -z "$2" ] ; then n2="0" ; changed=1 ; else n2=$2 ; fi # reset count
+if [ -z "$3" ] ; then n3="0" ; changed=1 ; else n3=$3 ; fi # lat
+if [ -z "$4" ] ; then n4="0" ; changed=1 ; else n4=$4 ; fi # lon
+if [ -z "$5" ] ; then n5="no" ; changed=1 ; else n5=$5 ; fi # sim mode
+if [ -z "$6" ] ; then n6="3" ; changed=1 ; else n6=$6 ; fi # squelch
+if [ -z "$7" ] ; then n7="434.9000" ; changed=1 ; else n7=$7 ; fi # transmit frequency
+if [ -z "$8" ] ; then n8="435.0000" ; changed=1 ; else n8=$8 ; fi # receive frequency
+if [ -z "$9" ] ; then n9="no" ; changed=1 ; else n9=$9 ; fi # hab mode
+if [ -z "$10" ] ; then n10="0" ; changed=1 ; else n10=$10 ; fi # rx pl code
+if [ -z "$11" ] ; then n11="0" ; changed=1 ; else n11=$11 ; fi # tx pl code
+
+if [ $changed -eq 1 ]; then
+ echo -e "Current sim.cfg configuration file:"
+ echo
+ echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11
+ echo -e "\nCubeSatSim configuraation sim.cfg file updated to: \n"
+ echo
+ echo $n1 $n2 $n3 $n4 $n5 $n6 $n7 $n8 $n9 $10 $11
+ echo $n1 $n2 $n3 $n4 $n5 $n6 $n7 $n8 $n9 $10 $11 > /home/pi/CubeSatSim/sim.cfg
+ echo
+fi
+
echo "Would you like to reboot to complete the installation (y/n)?"
read -r ANS
diff --git a/log b/log
index 9518703d4..2a3ce9d73 100755
--- a/log
+++ b/log
@@ -2,10 +2,14 @@
echo -e "\nLog file script for CubeSatSim\n"
-if [ "$1" = "-r" ]; then
- sudo journalctl -a -u rpitx > /home/pi/CubeSatSim/logr.txt
- cat /home/pi/CubeSatSim/logr.txt
- echo -e "\nLog file also saved as /home/pi/CubeSatSim/logr.txt"
+if [ "$1" = "-r" ] || [ "$1" = "-t" ] ; then
+ sudo journalctl -a -u transmit > /home/pi/CubeSatSim/logt.txt
+ cat /home/pi/CubeSatSim/logt.txt
+ echo -e "\nTransmit Log file also saved as /home/pi/CubeSatSim/logt.txt"
+elif [ "$1" = "-c" ]; then
+ sudo journalctl -a -u command > /home/pi/CubeSatSim/logc.txt
+ cat /home/pi/CubeSatSim/logc.txt
+ echo -e "\nCommand and Control Log file also saved as /home/pi/CubeSatSim/logc.txt"
else
sudo journalctl -a -u cubesatsim > /home/pi/CubeSatSim/log.txt
cat /home/pi/CubeSatSim/log.txt
diff --git a/main.c b/main.c
index 46c35239f..9ceb0827f 100644
--- a/main.c
+++ b/main.c
@@ -18,35 +18,144 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-
+
#include "main.h"
+//#define HAB // uncomment to change APRS icon from Satellite to Balloon and only BAT telemetry
+
int main(int argc, char * argv[]) {
+
+ printf("\n\nCubeSatSim v2.0 starting...\n\n");
+
+ wiringPiSetup();
+
+ // Open configuration file with callsign and reset count
+ FILE * config_file = fopen("/home/pi/CubeSatSim/sim.cfg", "r");
+ if (config_file == NULL) {
+ printf("Creating config file.");
+ config_file = fopen("/home/pi/CubeSatSim/sim.cfg", "w");
+ fprintf(config_file, "%s %d", " ", 100);
+ fclose(config_file);
+ config_file = fopen("/home/pi/CubeSatSim/sim.cfg", "r");
+ }
+
+// char * cfg_buf[100];
+
+ fscanf(config_file, "%s %d %f %f %s %d %s %s %s %d %d",
+ call, & reset_count, & lat_file, & long_file, sim_yes, & squelch, tx, rx, hab_yes, & rx_pl, & tx_pl);
+ fclose(config_file);
+ fprintf(stderr,"Config file /home/pi/CubeSatSim/sim.cfg contains %s %d %f %f %s %d %s %s %s %d %d\n",
+ call, reset_count, lat_file, long_file, sim_yes, squelch, tx, rx, hab_yes, rx_pl, tx_pl);
+
+ fprintf(stderr, "Transmit on %s MHz Receive on %s MHz\n", tx, rx);
+
+ FILE * uptime_file = fopen("/proc/uptime", "r");
+ fscanf(uptime_file, "%f", & uptime_sec);
+ printf("Uptime sec: %f \n", uptime_sec);
+ fclose(uptime_file);
+// program_radio(); // do in transmit instead
+ if (uptime_sec < 30.0) {
+ reset_count = (reset_count + 1) % 0xffff; // only increment uptime if just rebooted
+ fprintf(stderr,"INFO: Reset Count: %d Uptime since Reset: %ld \n", reset_count, uptime_sec);
+ }
+
+ if ((fabs(lat_file) > 0) && (fabs(lat_file) < 90.0) && (fabs(long_file) > 0) && (fabs(long_file) < 180.0)) {
+ fprintf(stderr, "Valid latitude and longitude in config file\n");
+// convert to APRS DDMM.MM format
+// latitude = toAprsFormat(lat_file);
+// longitude = toAprsFormat(long_file);
+ latitude = lat_file;
+ longitude = long_file;
+ fprintf(stderr, "Lat/Long %f %f\n", latitude, longitude);
+ fprintf(stderr, "Lat/Long in APRS DDMM.MM format: %07.2f/%08.2f\n", toAprsFormat(latitude), toAprsFormat(longitude));
+ newGpsTime = millis();
+
+ } else { // set default
+// latitude = toAprsFormat(latitude);
+// longitude = toAprsFormat(longitude);
+ newGpsTime = millis();
+ }
+
+ if (strcmp(sim_yes, "yes") == 0) {
+ sim_mode = TRUE;
+ fprintf(stderr, "Sim mode is turned ON by configuration\n");
+ sim_config = TRUE;
+ }
+ if (strcmp(hab_yes, "yes") == 0) {
+ hab_mode = TRUE;
+ fprintf(stderr, "HAB mode is ON\n");
+ }
+
+ FILE * command_file = fopen("/home/pi/CubeSatSim/command_control", "r");
+ if (command_file == NULL) {
+ fprintf(stderr,"Command and control is OFF\n");
+ c2cStatus = DISABLED;
+ } else {
+ command_file = fopen("/home/pi/CubeSatSim/command_control_direwolf", "r");
+ if (command_file == NULL) {
+ fprintf(stderr,"Command and control Carrier (squelch) is ON\n");
+ c2cStatus = CARRIER;
+ } else {
+ fprintf(stderr,"Command and control DTMF or APRS is ON\n");
+ c2cStatus = DTMF_APRS;
+ }
+ }
+ printf("c2cStatus: %d \n", c2cStatus);
+
char resbuffer[1000];
- const char testStr[] = "cat /proc/cpuinfo | grep 'Revision' | awk '{print $3}' | sed 's/^1000//' | grep '902120'";
+// const char testStr[] = "cat /proc/cpuinfo | grep 'Revision' | awk '{print $3}' | sed 's/^1000//' | grep '9000'";
+ const char testStr[] = "cat /proc/cpuinfo | grep 'Revision' | awk '{print $3}' | sed 's/^1000//'";
+ const char test2Str[] = "cat /proc/cpuinfo | grep 'Revision' | awk '{print $3}' | sed 's/^1000//' | grep '902120'";
FILE *file_test = sopen(testStr); // see if Pi Zero 2
fgets(resbuffer, 1000, file_test);
-// fprintf(stderr, "test result: %s\n", resbuffer);
+ fprintf(stderr, "Pi Zero test result: %s\n", resbuffer);
fclose(file_test);
-// fprintf(stderr, " %x ", resbuffer[0]);
-// fprintf(stderr, " %x ", resbuffer[1]);
- if (resbuffer[1] != 0)
+// fprintf(stderr, "hex: %x %x %x %x \n", resbuffer[0], resbuffer[1], resbuffer[2], resbuffer[3]);
+ if ((resbuffer[0] != '9') || (resbuffer[1] != '0') || (resbuffer[2] != '0') || (resbuffer[3] != '0'))
{
- sleep(5); // try sleep at start to help boot
- voltageThreshold = 3.7;
- printf("Pi Zero 2 detected");
+ // voltageThreshold = 3.7;
+// if ((resbuffer[0] != '9') || (resbuffer[1] != '0') || (resbuffer[2] != '2') || (resbuffer[3] != '1'))
+ FILE *file2_test = sopen(test2Str); // see if Pi Zero 2
+ fgets(resbuffer, 1000, file2_test);
+ fprintf(stderr, "Pi Zero 2 test result: %s\n", resbuffer);
+ fclose(file2_test);
+ if (strlen(resbuffer) > 5)
+ fprintf(stderr, "Pi Zero 2 detected\n");
+ else
+ fprintf(stderr, "Not a Pi Zero or Pi Zero 2\n");
+
+ pi_zero_2_offset = 500;
+ if (uptime_sec < 30.0) {
+ FILE * transmit_stop = popen("sudo systemctl start transmit", "r");
+ pclose(transmit_stop);
+ fprintf(stderr, "Sleep 5 sec\n");
+ sleep(5); // try sleep at start to help boot
+ }
+ }
+ else {
+ fprintf(stderr,"Pi Zero detected\n");
+ if ((c2cStatus == DISABLED) || (c2cStatus == CARRIER)) {
+ pi_zero_2_offset = 500;
+ }
+ if (uptime_sec < 30.0) {
+ FILE * transmit_stop = popen("sudo systemctl start transmit", "r");
+ pclose(transmit_stop);
+ fprintf(stderr,"Sleep 10 sec\n");
+ sleep(10);
+ }
}
- printf("\n\nCubeSatSim v1.2 starting...\n\n");
-
- FILE * rpitx_stop = popen("sudo systemctl stop rpitx", "r");
- pclose(rpitx_stop);
+// FILE * transmit_stop = popen("sudo systemctl stop transmit", "r");
+// FILE * transmit_stop = popen("sudo systemctl restart transmit", "r");
+
+
+// FILE * cc_start = popen("/home/pi/CubeSatSim/command &", "r");
+// pclose(cc_start);
- FILE * file_deletes = popen("sudo rm /home/pi/CubeSatSim/ready /home/pi/CubeSatSim/cwready > /dev/null", "r");
- pclose(file_deletes);
+// FILE * file_deletes = popen("sudo rm /home/pi/CubeSatSim/ready /home/pi/CubeSatSim/cwready > /dev/null", "r");
+// pclose(file_deletes);
printf("Test bus 1\n");
fflush(stdout);
@@ -58,26 +167,31 @@ int main(int argc, char * argv[]) {
fflush(stdout);
// sleep(2);
+
+//#ifdef HAB
+ if (hab_mode)
+ fprintf(stderr, "HAB mode enabled - in APRS balloon icon and no battery saver or low voltage shutdown\n");
+//#endif
- FILE * rpitx_restart = popen("sudo systemctl restart rpitx", "r");
- pclose(rpitx_restart);
+// FILE * transmit_restart = popen("sudo systemctl restart transmit", "r");
+// pclose(transmit_restart);
- mode = FSK;
+ mode = BPSK;
frameCnt = 1;
if (argc > 1) {
// strcpy(src_addr, argv[1]);
if ( * argv[1] == 'b') {
mode = BPSK;
- printf("Mode BPSK\n");
+ printf("Mode is BPSK\n");
} else if ( * argv[1] == 'a') {
mode = AFSK;
- printf("Mode AFSK\n");
+ printf("Mode is AFSK\n");
} else if ( * argv[1] == 'm') {
mode = CW;
- printf("Mode CW\n");
+ printf("Mode is CW\n");
} else {
- printf("Mode FSK\n");
+ printf("Mode is BPSK\n");
}
if (argc > 2) {
@@ -102,9 +216,9 @@ int main(int argc, char * argv[]) {
fclose(mode_file);
printf("Mode file /home/pi/CubeSatSim/.mode contains %c\n", mode_string);
- if ( mode_string == 'b') {
- mode = BPSK;
- printf("Mode is BPSK\n");
+ if ( mode_string == 'f') {
+ mode = FSK;
+ printf("Mode is FSK\n");
} else if ( mode_string == 'a') {
mode = AFSK;
printf("Mode is AFSK\n");
@@ -114,45 +228,40 @@ int main(int argc, char * argv[]) {
} else if ( mode_string == 'm') {
mode = CW;
printf("Mode is CW\n");
+ } else if ( mode_string == 'e') {
+ mode = REPEATER;
+ printf("Mode is Repeater\n");
+ } else if ( mode_string == 'n') {
+ mode = TXCOMMAND;
+ printf("Mode is Transmit Command\n");
} else {
- printf("Mode is FSK\n");
+ printf("Mode is BPSK\n");
}
}
}
- // Open configuration file with callsign and reset count
- FILE * config_file = fopen("/home/pi/CubeSatSim/sim.cfg", "r");
- if (config_file == NULL) {
- printf("Creating config file.");
- config_file = fopen("/home/pi/CubeSatSim/sim.cfg", "w");
- fprintf(config_file, "%s %d", " ", 100);
- fclose(config_file);
- config_file = fopen("/home/pi/CubeSatSim/sim.cfg", "r");
- }
-
-// char * cfg_buf[100];
-
- fscanf(config_file, "%s %d %f %f %s", call, & reset_count, & lat_file, & long_file, sim_yes);
- fclose(config_file);
- printf("Config file /home/pi/CubeSatSim/sim.cfg contains %s %d %f %f %s\n", call, reset_count, lat_file, long_file, sim_yes);
- reset_count = (reset_count + 1) % 0xffff;
-
- if ((fabs(lat_file) > 0) && (fabs(lat_file) < 90.0) && (fabs(long_file) > 0) && (fabs(long_file) < 180.0)) {
- printf("Valid latitude and longitude in config file\n");
-// convert to APRS DDMM.MM format
- latitude = toAprsFormat(lat_file);
- longitude = toAprsFormat(long_file);
- printf("Lat/Long in APRS DDMM.MM format: %f/%f\n", latitude, longitude);
- } else { // set default
- latitude = toAprsFormat(latitude);
- longitude = toAprsFormat(longitude);
- }
+ // Open telemetry file with STEM Payload Data
+ telem_file = fopen("/home/pi/CubeSatSim/telem.txt", "a");
+ if (telem_file == NULL)
+ printf("Error opening telem file\n");
+ fclose(telem_file);
+ printf("Opened telem file\n");
- if (strcmp(sim_yes, "yes") == 0)
- sim_mode = TRUE;
- wiringPiSetup();
+ battery_saver_mode = battery_saver_check();
+/**/
+ if (battery_saver_mode == ON) {
+ SafeMode = 1;
+ fprintf(stderr, "Safe Mode! Battery_saver_mode is ON\n\n");
+ }
+ else {
+ fprintf(stderr, "\nBattery_saver_mode is OFF\n\n");
+ SafeMode = 0;
+ }
+/**/
+ fflush(stderr);
+
if (mode == AFSK)
{
// Check for SPI and AX-5043 Digital Transceiver Board
@@ -189,92 +298,31 @@ int main(int argc, char * argv[]) {
pclose(file);
}
- txLed = 0; // defaults for vB3 board without TFB
- txLedOn = LOW;
- txLedOff = HIGH;
- if (!ax5043) {
- pinMode(2, INPUT);
- pullUpDnControl(2, PUD_UP);
-
- if (digitalRead(2) != HIGH) {
- printf("vB3 with TFB Present\n");
- vB3 = TRUE;
- txLed = 3;
- txLedOn = LOW;
- txLedOff = HIGH;
- onLed = 0;
- onLedOn = LOW;
- onLedOff = HIGH;
- transmit = TRUE;
- } else {
- pinMode(3, INPUT);
- pullUpDnControl(3, PUD_UP);
-
- if (digitalRead(3) != HIGH) {
- printf("vB4 Present with UHF BPF\n");
- txLed = 2;
- txLedOn = HIGH;
- txLedOff = LOW;
- vB4 = TRUE;
- onLed = 0;
- onLedOn = HIGH;
- onLedOff = LOW;
- transmit = TRUE;
- } else {
- pinMode(26, INPUT);
- pullUpDnControl(26, PUD_UP);
-
- if (digitalRead(26) != HIGH) {
- printf("v1 Present with UHF BPF\n");
- txLed = 2;
- txLedOn = HIGH;
- txLedOff = LOW;
- vB5 = TRUE;
- onLed = 27;
- onLedOn = HIGH;
- onLedOff = LOW;
- transmit = TRUE;
- }
- else {
- pinMode(23, INPUT);
- pullUpDnControl(23, PUD_UP);
-
- if (digitalRead(23) != HIGH) {
- printf("v1 Present with VHF BPF\n");
- txLed = 2;
- txLedOn = HIGH;
- txLedOff = LOW;
- vB5 = TRUE;
- onLed = 27;
- onLedOn = HIGH;
- onLedOff = LOW;
- printf("VHF BPF not yet supported so no transmit\n");
- transmit = FALSE;
- }
- }
- }
- }
+ txLed = 2;
+ txLedOn = HIGH;
+ txLedOff = LOW;
+ vB5 = TRUE;
+ onLed = 27;
+ onLedOn = HIGH;
+ onLedOff = LOW;
+
+ pinMode(26, INPUT);
+ pullUpDnControl(26, PUD_UP);
+
+ if (digitalRead(26) != HIGH) {
+ printf("v1 Present with UHF BPF\n");
+ transmit = TRUE;
}
- pinMode(txLed, OUTPUT);
- digitalWrite(txLed, txLedOff);
- #ifdef DEBUG_LOGGING
- printf("Tx LED Off\n");
- #endif
- pinMode(onLed, OUTPUT);
- digitalWrite(onLed, onLedOn);
- #ifdef DEBUG_LOGGING
- printf("Power LED On\n");
- #endif
config_file = fopen("sim.cfg", "w");
- fprintf(config_file, "%s %d %8.4f %8.4f %s", call, reset_count, lat_file, long_file, sim_yes);
+ fprintf(config_file, "%s %d %8.4f %8.4f %s %d %s %s %s %d %d", call, reset_count, lat_file, long_file, sim_yes, squelch, tx, rx, hab_yes, rx_pl, tx_pl);
// fprintf(config_file, "%s %d", call, reset_count);
fclose(config_file);
config_file = fopen("sim.cfg", "r");
if (vB4) {
- map[BAT] = BUS;
- map[BUS] = BAT;
+ map[BAT] = BAT2;
+ map[BAT2] = BAT;
snprintf(busStr, 10, "%d %d", i2c_bus1, test_i2c_bus(0));
} else if (vB5) {
map[MINUS_X] = MINUS_Y;
@@ -288,8 +336,8 @@ int main(int argc, char * argv[]) {
snprintf(busStr, 10, "%d %d", i2c_bus1, i2c_bus3);
}
} else {
- map[BUS] = MINUS_Z;
- map[BAT] = BUS;
+ map[BAT2] = MINUS_Z;
+ map[BAT] = BAT2;
map[PLUS_Z] = BAT;
map[MINUS_Z] = PLUS_Z;
snprintf(busStr, 10, "%d %d", i2c_bus1, test_i2c_bus(0));
@@ -303,7 +351,7 @@ int main(int argc, char * argv[]) {
char camera_present[] = "supported=1 detected=1";
// printf("strstr: %s \n", strstr( & cmdbuffer1, camera_present));
camera = (strstr( (const char *)& cmdbuffer, camera_present) != NULL) ? ON : OFF;
- // printf("Camera result:%s camera: %d \n", & cmdbuffer1, camera);
+ printf("Camera result:%s camera: %d \n", & cmdbuffer, camera);
pclose(file4);
#ifdef DEBUG_LOGGING
@@ -311,55 +359,19 @@ int main(int argc, char * argv[]) {
#endif
FILE * file5 = popen("sudo rm /home/pi/CubeSatSim/camera_out.jpg > /dev/null 2>&1", "r");
- file5 = popen("sudo rm /home/pi/CubeSatSim/camera_out.jpg.wav > /dev/null 2>&1", "r");
+ //file5 = popen("sudo rm /home/pi/CubeSatSim/camera_out.jpg.wav > /dev/null 2>&1", "r");
pclose(file5);
- // try connecting to STEM Payload board using UART
- // /boot/config.txt and /boot/cmdline.txt must be set correctly for this to work
-
- if (!ax5043 && !vB3 && !(mode == CW) && !(mode == SSTV)) // don't test for payload if AX5043 is present or CW or SSTV modes
+ if (!ax5043) // don't test for payload if AX5043 is present
{
payload = OFF;
-
+ fprintf(stderr,"Opening serial\n");
if ((uart_fd = serialOpen("/dev/ttyAMA0", 115200)) >= 0) { // was 9600
- char c;
- int charss = (char) serialDataAvail(uart_fd);
- if (charss != 0)
- printf("Clearing buffer of %d chars \n", charss);
- while ((charss--> 0))
- c = (char) serialGetchar(uart_fd); // clear buffer
-
- unsigned int waitTime;
- int i;
- for (i = 0; i < 2; i++) {
- if (payload != ON) {
- serialPutchar(uart_fd, 'R');
- printf("Querying payload with R to reset\n");
- waitTime = millis() + 500;
- while ((millis() < waitTime) && (payload != ON)) {
- if (serialDataAvail(uart_fd)) {
- printf("%c", c = (char) serialGetchar(uart_fd));
- fflush(stdout);
- if (c == 'O') {
- printf("%c", c = (char) serialGetchar(uart_fd));
- fflush(stdout);
- if (c == 'K')
- payload = ON;
- }
- }
- printf("\n");
- // sleep(0.75);
- }
- }
- }
- if (payload == ON) {
- printf("\nSTEM Payload is present!\n");
- sleep(2); // delay to give payload time to get ready
- }
- else {
- printf("\nSTEM Payload not present!\n -> Is STEM Payload programed and Serial1 set to 115200 baud?\n");
-
- }
+ fprintf(stderr,"Serial opened to Pico\n");
+// payload = ON;
+ payload = get_payload_serial(FALSE);
+ fprintf(stderr,"Get_payload_status: %d \n", payload); // not debug
+
} else {
fprintf(stderr, "Unable to open UART: %s\n -> Did you configure /boot/config.txt and /boot/cmdline.txt?\n", strerror(errno));
}
@@ -369,7 +381,7 @@ int main(int argc, char * argv[]) {
sim_mode = TRUE;
- printf("Simulated telemetry mode!\n");
+ fprintf(stderr, "Simulated telemetry mode!\n");
srand((unsigned int)time(0));
@@ -414,11 +426,11 @@ int main(int argc, char * argv[]) {
eclipse_time -= period / 2; // if starting in eclipse, shorten interval
}
- tx_freq_hz -= tx_channel * 50000;
+ // tx_freq_hz -= tx_channel * 50000;
if (transmit == FALSE) {
- fprintf(stderr, "\nNo CubeSatSim Band Pass Filter detected. No transmissions after the CW ID.\n");
+ fprintf(stderr, "\nNo CubeSatSim Low Pass Filter detected. No transmissions after the CW ID.\n");
fprintf(stderr, " See http://cubesatsim.org/wiki for info about building a CubeSatSim\n\n");
}
@@ -486,7 +498,7 @@ int main(int argc, char * argv[]) {
get_tlm_fox(); // fill transmit buffer with reset count 0 packets that will be ignored
firstTime = 1;
- if (!sim_mode)
+// if (!sim_mode) // always read sensors, even in sim mode
{
strcpy(pythonStr, pythonCmd);
strcat(pythonStr, busStr);
@@ -507,7 +519,7 @@ int main(int argc, char * argv[]) {
voltage_max[i] = -1000.0;
current_max[i] = -1000.0;
}
- for (int i = 0; i < 17; i++) {
+ for (int i = 0; i < SENSOR_FIELDS; i++) {
sensor_min[i] = 1000.0;
sensor_max[i] = -1000.0;
// printf("Sensor min and max initialized!");
@@ -516,8 +528,7 @@ int main(int argc, char * argv[]) {
other_min[i] = 1000.0;
other_max[i] = -1000.0;
}
-
- long int loopTime;
+
loopTime = millis();
while (loop-- != 0) {
@@ -537,14 +548,139 @@ int main(int argc, char * argv[]) {
uptime = (int) (uptime_sec + 0.5);
// printf("Uptime sec: %f \n", uptime_sec);
// #ifdef DEBUG_LOGGING
- printf("INFO: Reset Count: %d Uptime since Reset: %ld \n", reset_count, uptime);
+// printf("INFO: Reset Count: %d Uptime since Reset: %ld \n", reset_count, uptime);
// #endif
fclose(uptime_file);
+
+ {
+ int count1;
+ char * token;
+ fputc('\n', file1);
+ fgets(cmdbuffer, 1000, file1);
+// fprintf(stderr, "Python read Result: %s\n", cmdbuffer);
+
+// serialPuts(uart_fd, cmdbuffer); // write INA data to Pico over serial
+
+ const char space[2] = " ";
+ token = strtok(cmdbuffer, space);
+
+ for (count1 = 0; count1 < 8; count1++) {
+ if (token != NULL) {
+ voltage[count1] = (float) atof(token);
+ #ifdef DEBUG_LOGGING
+// printf("voltage: %f ", voltage[count1]);
+ #endif
+ token = strtok(NULL, space);
+ if (token != NULL) {
+ current[count1] = (float) atof(token);
+ if ((current[count1] < 0) && (current[count1] > -0.5))
+ current[count1] *= (-1.0f);
+ #ifdef DEBUG_LOGGING
+// printf("current: %f\n", current[count1]);
+ #endif
+ token = strtok(NULL, space);
+ }
+ }
+ if (voltage[map[BAT]] == 0.0)
+ batteryVoltage = 4.5;
+ else {
+ batteryVoltage = voltage[map[BAT]];
+ if (sim_mode && !sim_config) { // if Voltage sensor on Battery board is present, exit simulated telemetry mode
+ sim_mode = FALSE;
+ fprintf(stderr, "Turning off sim_mode since battery sensor is present\n");
+ }
+ }
+ batteryCurrent = current[map[BAT]];
+
+ }
+
+// if (payload == ON) { // moved to here
+ if (!ax5043) {
+// if ((payload == ON) && (mode != BPSK)) { // moved to here
+// STEMBoardFailure = 0;
+ payload = get_payload_serial(FALSE);
+ printf("get_payload_status: %d \n", payload); // not debug
+ fflush(stdout);
+// printf("String: %s\n", buffer2);
+ fflush(stdout);
+ strcpy(sensor_payload, buffer2);
+// printf(" Response from STEM Payload board: %s\n", sensor_payload);
+
+ telem_file = fopen("/home/pi/CubeSatSim/telem.txt", "a");
+// printf("Writing payload string\n");
+ time_t timeStamp;
+ time(&timeStamp); // get timestamp
+// printf("Timestamp: %s\n", ctime(&timeStamp));
+
+ char timeStampNoNl[31], bat_string[31];
+ snprintf(timeStampNoNl, 30, "%.24s", ctime(&timeStamp));
+// printf("TimeStamp: %s\n", timeStampNoNl);
+
+ if (c2cStatus == DISABLED)
+ snprintf(bat_string, 30, "BAT %4.2f %5.1f", batteryVoltage, batteryCurrent);
+ else
+ snprintf(bat_string, 30, "BAT %4.2f %5.1f C", batteryVoltage, batteryCurrent);
+
+ fprintf(telem_file, "%s %s %s\n", timeStampNoNl, bat_string, sensor_payload); // write telemetry string to telem.txt file
+ fclose(telem_file);
+
+ if ((sensor_payload[0] == 'O') && (sensor_payload[1] == 'K')) // only process if valid payload response
+ {
+ int count1;
+ char * token;
+
+ const char space[2] = " ";
+ token = strtok(sensor_payload, space);
+// printf("token: %s\n", token);
+ for (count1 = 0; count1 < SENSOR_FIELDS; count1++) {
+ if (token != NULL) {
+ sensor[count1] = (float) atof(token);
+// #ifdef DEBUG_LOGGING
+// printf("sensor: %f ", sensor[count1]); // print sensor data
+// #endif
+ token = strtok(NULL, space);
+ }
+ }
+
+ printf("\n");
+// if (sensor[GPS1] != 0) {
+ if ((sensor[GPS1] > -90.0) && (sensor[GPS1] < 90.0) && (sensor[GPS1] != 0.0)) {
+ if (sensor[GPS1] != latitude) {
+ latitude = sensor[GPS1];
+ printf("Latitude updated to %f \n", latitude);
+ newGpsTime = millis();
+ }
+ }
+// if (sensor[GPS2] != 0) {
+ if ((sensor[GPS2] > -180.0) && (sensor[GPS2] < 180.0) && (sensor[GPS2] != 0.0)) {
+ if (sensor[GPS2] != longitude) {
+ longitude = sensor[GPS2];
+ printf("Longitude updated to %f \n", longitude);
+ newGpsTime = millis();
+ }
+ }
+ }
+ else
+ ; //payload = OFF; // turn off since STEM Payload is not responding
+ }
+ if ((millis() - newGpsTime) > 60000) {
+ longitude += rnd_float(-0.05, 0.05) / 100.0; // was .05
+ latitude += rnd_float(-0.05, 0.05) / 100.0;
+// printf("GPS Location with Rnd: %f, %f \n", latitude, longitude);
+// printf("GPS Location with Rnd: APRS %07.2f, %08.2f \n", toAprsFormat(latitude), toAprsFormat(longitude));
+ newGpsTime = millis();
+ }
- printf("++++ Loop time: %5.3f sec +++++\n", (millis() - loopTime)/1000.0);
- fflush(stdout);
- loopTime = millis();
-
+ if ((sensor_payload[0] == 'O') && (sensor_payload[1] == 'K')) {
+ for (int count1 = 0; count1 < SENSOR_FIELDS; count1++) {
+ if (sensor[count1] < sensor_min[count1])
+ sensor_min[count1] = sensor[count1];
+ if (sensor[count1] > sensor_max[count1])
+ sensor_max[count1] = sensor[count1];
+ // printf("Smin %f Smax %f \n", sensor_min[count1], sensor_max[count1]);
+ }
+ }
+
if (sim_mode) { // simulated telemetry
double time = ((long int)millis() - time_start) / 1000.0;
@@ -586,15 +722,15 @@ int main(int argc, char * argv[]) {
// IHUcpuTemp = (int)((tempS + rnd_float(-1.0, 1.0)) * 10 + 0.5);
other[IHU_TEMP] = tempS;
- voltage[map[BUS]] = rnd_float(5.0, 5.005);
- current[map[BUS]] = rnd_float(158, 171);
+ voltage[map[BAT2]] = 0.0; // rnd_float(5.0, 5.005);
+ current[map[BAT2]] = 0.0; // rnd_float(158, 171);
// float charging = current[map[PLUS_X]] + current[map[MINUS_X]] + current[map[PLUS_Y]] + current[map[MINUS_Y]] + current[map[PLUS_Z]] + current[map[MINUS_Z]];
float charging = eclipse * (fabs(amps_max[0] * 0.707) + fabs(amps_max[1] * 0.707) + rnd_float(-4.0, 4.0));
- current[map[BAT]] = ((current[map[BUS]] * voltage[map[BUS]]) / batt) - charging;
+ current[map[BAT]] = ((current[map[BAT2]] * voltage[map[BAT2]]) / batt) - charging;
- // printf("charging: %f bat curr: %f bus curr: %f bat volt: %f bus volt: %f \n",charging, current[map[BAT]], current[map[BUS]], batt, voltage[map[BUS]]);
+ // printf("charging: %f bat curr: %f bus curr: %f bat volt: %f bus volt: %f \n",charging, current[map[BAT]], current[map[BAT2]], batt, voltage[map[BAT2]]);
batt -= (batt > 3.5) ? current[map[BAT]] / 30000 : current[map[BAT]] / 3000;
if (batt < 3.0) {
@@ -612,43 +748,7 @@ int main(int argc, char * argv[]) {
// end of simulated telemetry
}
else {
- int count1;
- char * token;
- fputc('\n', file1);
- fgets(cmdbuffer, 1000, file1);
- fprintf(stderr, "Python read Result: %s\n", cmdbuffer);
-
- const char space[2] = " ";
- token = strtok(cmdbuffer, space);
-
- for (count1 = 0; count1 < 8; count1++) {
- if (token != NULL) {
- voltage[count1] = (float) atof(token);
- #ifdef DEBUG_LOGGING
-// printf("voltage: %f ", voltage[count1]);
- #endif
- token = strtok(NULL, space);
- if (token != NULL) {
- current[count1] = (float) atof(token);
- if ((current[count1] < 0) && (current[count1] > -0.5))
- current[count1] *= (-1.0f);
- #ifdef DEBUG_LOGGING
-// printf("current: %f\n", current[count1]);
- #endif
- token = strtok(NULL, space);
- }
- }
}
-
- batteryVoltage = voltage[map[BAT]];
- batteryCurrent = current[map[BAT]];
-
- if (batteryVoltage < 3.6) {
- SafeMode = 1;
- printf("Safe Mode!\n");
- } else
- SafeMode = 0;
-
FILE * cpuTempSensor = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
if (cpuTempSensor) {
// double cpuTemp;
@@ -664,90 +764,41 @@ int main(int argc, char * argv[]) {
// IHUcpuTemp = (int)((cpuTemp * 10.0) + 0.5);
}
fclose(cpuTempSensor);
- }
- if (payload == ON) { // -55
- STEMBoardFailure = 0;
-
-
- char c;
- unsigned int waitTime;
- int i, end, trys = 0;
- sensor_payload[0] = 0;
- sensor_payload[1] = 0;
- while (((sensor_payload[0] != 'O') || (sensor_payload[1] != 'K')) && (trys++ < 10)) {
- i = 0;
- serialPutchar(uart_fd, '?');
- sleep(0.05); // added delay after ?
- printf("%d Querying payload with ?\n", trys);
- waitTime = millis() + 500;
- end = FALSE;
- // int retry = FALSE;
- while ((millis() < waitTime) && !end) {
- int chars = (char) serialDataAvail(uart_fd);
- while ((chars > 0) && !end) {
-// printf("Chars: %d\ ", chars);
- chars--;
- c = (char) serialGetchar(uart_fd);
- // printf ("%c", c);
- // fflush(stdout);
- if (c != '\n') {
- sensor_payload[i++] = c;
- } else {
- end = TRUE;
- }
- }
- }
-
- sensor_payload[i++] = ' ';
- // sensor_payload[i++] = '\n';
- sensor_payload[i] = '\0';
- printf(" Response from STEM Payload board: %s\n", sensor_payload);
- sleep(0.1); // added sleep between loops
- }
- if ((sensor_payload[0] == 'O') && (sensor_payload[1] == 'K')) // only process if valid payload response
- {
- int count1;
- char * token;
-
- const char space[2] = " ";
- token = strtok(sensor_payload, space);
- for (count1 = 0; count1 < 17; count1++) {
- if (token != NULL) {
- sensor[count1] = (float) atof(token);
- #ifdef DEBUG_LOGGING
- // printf("sensor: %f ", sensor[count1]);
- #endif
- token = strtok(NULL, space);
- }
- }
- printf("\n");
- }
- else
- payload = OFF; // turn off since STEM Payload is not responding
- }
- if ((sensor_payload[0] == 'O') && (sensor_payload[1] == 'K')) {
- for (int count1 = 0; count1 < 17; count1++) {
- if (sensor[count1] < sensor_min[count1])
- sensor_min[count1] = sensor[count1];
- if (sensor[count1] > sensor_max[count1])
- sensor_max[count1] = sensor[count1];
- // printf("Smin %f Smax %f \n", sensor_min[count1], sensor_max[count1]);
- }
- }
-// }
+ }
#ifdef DEBUG_LOGGING
- fprintf(stderr, "INFO: Battery voltage: %5.2f V Threshold %5.2f V Current: %6.1f mA Threshold: %6.1f mA\n", batteryVoltage, voltageThreshold, batteryCurrent, currentThreshold);
+// fprintf(stderr, "INFO: Battery voltage: %5.2f V Threshold %5.2f V Current: %6.1f mA Threshold: %6.1f mA\n", batteryVoltage, voltageThreshold, batteryCurrent, currentThreshold);
#endif
-// if ((batteryVoltage > 1.0) && (batteryVoltage < batteryThreshold)) // no battery INA219 will give 0V, no battery plugged into INA219 will read < 1V
-
-/**/
- if ((batteryCurrent > currentThreshold) && (batteryVoltage < voltageThreshold) && !sim_mode) // currentThreshold ensures that this won't happen when running on DC power.
+
+ if ((batteryCurrent > currentThreshold) && (batteryVoltage < (voltageThreshold + 0.15)) && !sim_mode && !hab_mode)
+ {
+ fprintf(stderr,"Battery voltage low\n");
+ if (battery_saver_mode == OFF) {
+ fprintf(stderr,"Switch to battery saver\n");
+ battery_saver(ON);
+ fprintf(stderr, "Safe Mode!\n");
+ SafeMode = 1;
+
+ }
+ } else if ((battery_saver_mode == ON) && (batteryCurrent < 0) && !sim_mode && !hab_mode)
+ {
+ fprintf(stderr,"Battery is being charged - switch battery saver off\n");
+ if (battery_saver_mode == ON) {
+ battery_saver(OFF);
+ fprintf(stderr, "Safe Mode off!\n");
+ SafeMode = 0;
+ }
+ }
+ if ((batteryCurrent > currentThreshold) && (batteryVoltage < voltageThreshold) && !sim_mode && !hab_mode) // currentThreshold ensures that this won't happen when running on DC power.
{
fprintf(stderr, "Battery voltage too low: %f V - shutting down!\n", batteryVoltage);
digitalWrite(txLed, txLedOff);
digitalWrite(onLed, onLedOff);
-
+
+ FILE * file6;
+ file6 = popen("echo 'shutdown due to low battery voltage!' | wall", "r");
+ pclose(file6);
+
sleep(1);
digitalWrite(onLed, onLedOn);
sleep(1);
@@ -757,13 +808,27 @@ int main(int argc, char * argv[]) {
sleep(1);
digitalWrite(onLed, onLedOff);
- FILE * file6 = popen("/home/pi/CubeSatSim/log > shutdown_log.txt", "r");
- pclose(file6);
- sleep(40);
file6 = popen("sudo shutdown -h now > /dev/null 2>&1", "r");
pclose(file6);
sleep(10);
}
+//#endif
+
+ FILE * fp = fopen("/home/pi/CubeSatSim/telem_string.txt", "w");
+ if (fp != NULL) {
+// printf("Writing telem_string.txt\n");
+ if (batteryVoltage != 4.5)
+ if (c2cStatus == DISABLED)
+ fprintf(fp, "BAT %4.2fV %4.0fmA\n", batteryVoltage, batteryCurrent);
+ else
+ fprintf(fp, "BAT %4.2fV %4.0fmA C\n", batteryVoltage, batteryCurrent); // show command and control is on
+ else
+ fprintf(fp, "\n"); // don't show voltage and current if it isn't a sensor value
+
+ fclose(fp);
+ } else
+ printf("Error writing to telem_string.txt\n");
+
/**/
// sleep(1); // Delay 1 second
ctr = 0;
@@ -771,13 +836,42 @@ int main(int argc, char * argv[]) {
// fprintf(stderr, "INFO: Getting TLM Data\n");
#endif
+ FILE * command_file = fopen("/home/pi/CubeSatSim/command_control", "r");
+ if (command_file == NULL) {
+ if (c2cStatus != DISABLED) {
+ fprintf(stderr,"Command and control is OFF\n");
+ c2cStatus = DISABLED;
+ }
+ } else {
+ command_file = fopen("/home/pi/CubeSatSim/command_control_direwolf", "r");
+ if (command_file == NULL) {
+ if (c2cStatus != CARRIER) {
+ fprintf(stderr,"Command and control Carrier (squelch) is ON\n");
+ c2cStatus = CARRIER;
+ }
+ } else {
+ if (c2cStatus != DTMF_APRS) {
+ fprintf(stderr,"Command and control DTMF or APRS is ON\n");
+ c2cStatus = DTMF_APRS;
+ }
+ }
+ }
+ // printf("c2cStatus: %d \n", c2cStatus);
+
if ((mode == AFSK) || (mode == CW)) {
get_tlm();
+ sleep(25);
+// fprintf(stderr, "INFO: Sleeping for 25 sec\n");
+
+ int rand_sleep = (int)rnd_float(0.0, 5.0);
+ sleep(rand_sleep);
+// fprintf(stderr, "INFO: Sleeping for extra %d sec\n", rand_sleep);
+
} else if ((mode == FSK) || (mode == BPSK)) {// FSK or BPSK
get_tlm_fox();
} else { // SSTV
- fprintf(stderr, "Sleeping\n");
- sleep(50);
+// fprintf(stderr, "Sleeping\n");
+ sleep(30);
}
#ifdef DEBUG_LOGGING
@@ -790,17 +884,17 @@ int main(int argc, char * argv[]) {
#ifdef DEBUG_LOGGING
// printf("Tx LED On 1\n");
#endif
- printf("Sleeping to allow BPSK transmission to finish.\n");
+// printf("Sleeping to allow BPSK transmission to finish.\n");
sleep((unsigned int)(loop_count * 5));
- printf("Done sleeping\n");
+ // printf("Done sleeping\n");
// digitalWrite(txLed, txLedOff);
#ifdef DEBUG_LOGGING
// printf("Tx LED Off\n");
#endif
} else if (mode == FSK) {
- printf("Sleeping to allow FSK transmission to finish.\n");
+// printf("Sleeping to allow FSK transmission to finish.\n");
sleep((unsigned int)loop_count);
- printf("Done sleeping\n");
+// printf("Done sleeping\n");
}
return 0;
@@ -857,7 +951,7 @@ void get_tlm(void) {
int tlm[7][5];
memset(tlm, 0, sizeof tlm);
- tlm[1][A] = (int)(voltage[map[BUS]] / 15.0 + 0.5) % 100; // Current of 5V supply to Pi
+ tlm[1][A] = (int)(voltage[map[BAT2]] / 15.0 + 0.5) % 100; // Current of 5V supply to Pi
tlm[1][B] = (int)(99.5 - current[map[PLUS_X]] / 10.0) % 100; // +X current [4]
tlm[1][C] = (int)(99.5 - current[map[MINUS_X]] / 10.0) % 100; // X- current [10]
tlm[1][D] = (int)(99.5 - current[map[PLUS_Y]] / 10.0) % 100; // +Y current [7]
@@ -873,7 +967,7 @@ void get_tlm(void) {
else
tlm[3][A] = (int)((voltage[map[BAT]] * 10.0) + 44.5) % 100; // 0 - 4.5 V for new 3 cell battery
- tlm[3][B] = (int)(voltage[map[BUS]] * 10.0) % 100; // 5V supply to Pi
+ tlm[3][B] = (int)(voltage[map[BAT2]] * 10.0) % 100; // 5V supply to Pi
tlm[4][A] = (int)((95.8 - other[IHU_TEMP]) / 1.48 + 0.5) % 100; // was [B] but didn't display in online TLM spreadsheet
@@ -900,10 +994,13 @@ void get_tlm(void) {
char header_str2b[30]; // for APRS coordinates
char header_lat[10];
char header_long[10];
- char header_str4[] = "hi hi ";
- char footer_str1[] = "\' > t.txt && echo \'";
- char footer_str[] = "-11>APCSS:010101/hi hi ' >> t.txt && touch /home/pi/CubeSatSim/ready"; // transmit is done by rpitx.py
-
+ char header_str4[] = "hi hi de ";
+// char footer_str1[] = "\' > t.txt && echo \'";
+ char footer_str1[] = "\' > t.txt";
+// char footer_str[] = "-11>APCSS:010101/hi hi ' >> t.txt && touch /home/pi/CubeSatSim/ready"; // transmit is done by transmit.py
+ char footer_str[] = " && echo 'AMSAT-11>APCSS:010101/hi hi ' >> t.txt && touch /home/pi/CubeSatSim/ready"; // transmit is done by transmit.py
+ char footer_str2[] = " && touch /home/pi/CubeSatSim/ready";
+
if (ax5043) {
strcpy(str, header_str);
} else {
@@ -918,102 +1015,90 @@ void get_tlm(void) {
if (mode != CW) {
// sprintf(header_str2b, "=%7.2f%c%c%c%08.2f%cShi hi ",4003.79,'N',0x5c,0x5c,07534.33,'W'); // add APRS lat and long
if (latitude > 0)
- sprintf(header_lat, "%7.2f%c", latitude, 'N'); // lat
+ sprintf(header_lat, "%07.2f%c", toAprsFormat(latitude), 'N'); // lat
else
- sprintf(header_lat, "%7.2f%c", latitude * (-1.0), 'S'); // lat
+ sprintf(header_lat, "%07.2f%c", toAprsFormat(latitude) * (-1.0), 'S'); // lat
if (longitude > 0)
- sprintf(header_long, "%08.2f%c", longitude , 'E'); // long
+ sprintf(header_long, "%08.2f%c", toAprsFormat(longitude) , 'E'); // long
else
- sprintf(header_long, "%08.2f%c", longitude * (-1.0), 'W'); // long
+ sprintf(header_long, "%08.2f%c",toAprsFormat( longitude) * (-1.0), 'W'); // long
+
if (ax5043)
sprintf(header_str2b, "=%s%c%sShi hi ", header_lat, 0x5c, header_long); // add APRS lat and long
else
- sprintf(header_str2b, "=%s%c%c%sShi hi ", header_lat, 0x5c, 0x5c, header_long); // add APRS lat and long
-// printf("\n\nString is %s \n\n", header_str2b);
+//#ifdef HAB
+ if (hab_mode)
+ sprintf(header_str2b, "=%s%c%sOhi hi ", header_lat, 0x2f, header_long); // add APRS lat and long with Balloon HAB icon
+//#else
+ else
+ sprintf(header_str2b, "=%s%c%c%sShi hi ", header_lat, 0x5c, 0x5c, header_long); // add APRS lat and long with Satellite icon
+//#endif
+
+ printf("\n\nString is %s \n\n", header_str2b);
strcat(str, header_str2b);
- } else {
+ } else { // CW mode
strcat(str, header_str4);
+ strcat(str, call);
+
+ sprintf(tlm_str, "%s' > cw0.txt", &str);
+ printf("CW string to execute: %s\n", &tlm_str);
+ FILE * cw_file = popen(tlm_str, "r");
+ pclose(cw_file);
+
}
// }
printf("Str: %s \n", str);
-
+ if (mode == CW) {
int channel;
for (channel = 1; channel < 7; channel++) {
- sprintf(tlm_str, "%d%d%d %d%d%d %d%d%d %d%d%d ",
+ sprintf(tlm_str, "echo -n ' %d%d%d %d%d%d %d%d%d %d%d%d ' > cw%1d.txt",
channel, upper_digit(tlm[channel][1]), lower_digit(tlm[channel][1]),
channel, upper_digit(tlm[channel][2]), lower_digit(tlm[channel][2]),
channel, upper_digit(tlm[channel][3]), lower_digit(tlm[channel][3]),
- channel, upper_digit(tlm[channel][4]), lower_digit(tlm[channel][4]));
- // printf("%s",tlm_str);
- strcat(str, tlm_str);
- }
+ channel, upper_digit(tlm[channel][4]), lower_digit(tlm[channel][4]), channel);
- // read payload sensor if available
+ strcat(str, tlm_str);
+
+ printf("CW string to execute: %s\n", &tlm_str);
+
+ FILE * cw_file = popen(tlm_str, "r");
+ pclose(cw_file);
- char sensor_payload[500];
-
- if (payload == ON) {
- char c;
- unsigned int waitTime;
- int i, end, trys = 0;
- sensor_payload[0] = 0;
- sensor_payload[1] = 0;
- while (((sensor_payload[0] != 'O') || (sensor_payload[1] != 'K')) && (trys++ < 10)) {
- i = 0;
- serialPutchar(uart_fd, '?');
- sleep(0.05); // added delay after ?
- printf("%d Querying payload with ?\n", trys);
- waitTime = millis() + 500;
- end = FALSE;
- // int retry = FALSE;
- while ((millis() < waitTime) && !end) {
- int chars = (char) serialDataAvail(uart_fd);
- while ((chars > 0) && !end) {
-// printf("Chars: %d\ ", chars);
- chars--;
- c = (char) serialGetchar(uart_fd);
- // printf ("%c", c);
- // fflush(stdout);
- if (c != '\n') {
- sensor_payload[i++] = c;
- } else {
- end = TRUE;
- }
- }
- }
-
- sensor_payload[i++] = ' ';
- // sensor_payload[i++] = '\n';
- sensor_payload[i] = '\0';
- printf(" Response from STEM Payload board: %s\n", sensor_payload);
- sleep(0.1); // added sleep between loops
- }
+ }
+ if (c2cStatus != DISABLED) {
+ FILE *file_append = sopen("echo 'C' >> cw6.txt");
+ fclose(file_append);
+ }
+ } else { // APRS
- if (mode != CW)
+ if (c2cStatus == 0)
+ sprintf(tlm_str, "BAT %4.2f %5.1f ", voltage[map[BAT]] , current[map[BAT]] );
+ else
+ sprintf(tlm_str, "BAT %4.2f %5.1f C ", voltage[map[BAT]] , current[map[BAT]] );
+
+ strcat(str, tlm_str);
+ }
+ strcpy(sensor_payload, buffer2);
+ printf(" Response from STEM Payload board:: %s\n", sensor_payload);
+// printf(" Str so far: %s\n", str);
+
+ if (mode != CW)
strcat(str, sensor_payload); // append to telemetry string for transmission
- }
if (mode == CW) {
- char cw_str2[1000];
- char cw_header2[] = "echo '";
- char cw_footer2[] = "' > id.txt && gen_packets -M 20 id.txt -o morse.wav -r 48000 > /dev/null 2>&1 && cat morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f 434.897e3";
- char cw_footer3[] = "' > cw.txt && touch /home/pi/CubeSatSim/cwready"; // transmit is done by rpitx.py
-
-// printf("Str str: %s \n", str);
-// fflush(stdout);
- strcat(str, cw_footer3);
-// printf("Str: %s \n", str);
-// fflush(stdout);
- printf("CW string to execute: %s\n", str);
- fflush(stdout);
-
- FILE * cw_file = popen(str, "r");
+// char cw_str2[1000];
+// char cw_header2[] = "echo '";
+// char cw_footer2[] = "' > id.txt && gen_packets -M 20 id.txt -o morse.wav -r 48000 > /dev/null 2>&1 && cat morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/transmit/transmit -i- -m RF -f 434.897e3";
+ char cw_footer3[] = "' > cw.txt && touch /home/pi/CubeSatSim/cwready"; // transmit is done by transmit.py
+ char cwready[] = "touch /home/pi/CubeSatSim/cwready"; // cw frame is complete. transmit is done by transmit.py
+
+ FILE * cw_file = popen(cwready, "r");
pclose(cw_file);
- while ((cw_file = fopen("/home/pi/CubeSatSim/cwready", "r")) != NULL) { // wait for rpitx to be done
+ while ((cw_file = fopen("/home/pi/CubeSatSim/cwready", "r")) != NULL) { // wait for transmit to be done
fclose(cw_file);
-// printf("Sleeping while waiting for rpitx \n");
+// printf("Sleeping while waiting for transmit \n");
// fflush(stdout);
sleep(5);
}
@@ -1041,12 +1126,16 @@ void get_tlm(void) {
}
sleep(4); // was 2
- } else { // APRS using rpitx
+ } else { // APRS using transmit
strcat(str, footer_str1);
- strcat(str, call);
- strcat(str, footer_str);
-// fprintf(stderr, "String to execute: %s\n", str);
+// strcat(str, call);
+ if (battery_saver_mode == ON)
+ strcat(str, footer_str); // add extra packet for transmit transmission
+ else
+ strcat(str, footer_str2);
+
+ fprintf(stderr, "String to execute: %s\n", str);
printf("\n\nTelemetry string is %s \n\n", str);
@@ -1070,8 +1159,10 @@ void get_tlm(void) {
return;
}
-void get_tlm_fox() {
+// generates telemetry which is decoded by AMSAT's FoxTelem: https://www.amsat.org/foxtelem-software-for-windows-mac-linux/
+// for more info about how we use FoxTelem see https://www.g0kla.com/foxtelem/amsat_telemetry_designers_handbook.pdf
+void get_tlm_fox() {
int i;
long int sync = syncWord;
@@ -1094,9 +1185,9 @@ void get_tlm_fox() {
short int rs_frame[rsFrames][223];
unsigned char parities[rsFrames][parityLen], inputByte;
- int id, frm_type = 0x01, NormalModeFailure = 0, groundCommandCount = 0;
+ int id, frm_type = 0x01, NormalModeFailure = 0;
int PayloadFailure1 = 0, PayloadFailure2 = 0;
- int PSUVoltage = 0, PSUCurrent = 0, Resets = 0, Rssi = 2048;
+ int BAT2Voltage = 0, BAT2Current = 0, Resets = 0, Rssi = 2048;
int batt_a_v = 0, batt_b_v = 0, batt_c_v = 0, battCurr = 0;
int posXv = 0, negXv = 0, posYv = 0, negYv = 0, posZv = 0, negZv = 0;
int posXi = 0, negXi = 0, posYi = 0, negYi = 0, posZi = 0, negZi = 0;
@@ -1120,18 +1211,23 @@ void get_tlm_fox() {
/**/
// while ((millis() - sampleTime) < (unsigned int)samplePeriod)
int startSleep = millis();
- if ((millis() - sampleTime) < ((unsigned int)frameTime - 250)) // was 250 100 500 for FSK
- sleep(2.0); // 0.5); // 25); // initial period
- while ((millis() - sampleTime) < ((unsigned int)frameTime - 250)) // was 250 100
+ if ((millis() - sampleTime) < ((unsigned int)frameTime - 750 + pi_zero_2_offset)) // was 250 100 500 for FSK
+// sleep(2.0); // 0.5); // 25); // initial period
+ sleep(1.0); // 0.5); // 25); // initial period
+ while ((millis() - sampleTime) < ((unsigned int)frameTime - 750 + pi_zero_2_offset)) // was 250 100
sleep(0.1); // 25); // 0.5); // 25);
// sleep((unsigned int)sleepTime);
/**/
- printf("Sleep period: %d\n", millis() - startSleep);
+ printf("Start sleep %d Sleep period: %d while period: %d\n", startSleep, millis() - startSleep, (unsigned int)frameTime - 750 + pi_zero_2_offset);
fflush(stdout);
sampleTime = (unsigned int) millis();
} else
printf("first time - no sleep\n");
+
+ printf("++++ Loop time: %5.3f sec +++++\n", (millis() - loopTime)/1000.0);
+ fflush(stdout);
+ loopTime = millis();
// if (mode == FSK)
{ // just moved
@@ -1159,9 +1255,9 @@ void get_tlm_fox() {
if (mode == FSK)
{
if (loop % 32 == 0) { // was 8
- printf("Sending MIN frame \n");
+// printf("Sending MIN frame \n");
frm_type = 0x03;
- for (int count1 = 0; count1 < 17; count1++) {
+ for (int count1 = 0; count1 < SENSOR_FIELDS; count1++) {
if (count1 < 3)
other[count1] = other_min[count1];
if (count1 < 8) {
@@ -1173,9 +1269,9 @@ void get_tlm_fox() {
}
}
if ((loop + 16) % 32 == 0) { // was 8
- printf("Sending MAX frame \n");
+// printf("Sending MAX frame \n");
frm_type = 0x02;
- for (int count1 = 0; count1 < 17; count1++) {
+ for (int count1 = 0; count1 < SENSOR_FIELDS; count1++) {
if (count1 < 3)
other[count1] = other_max[count1];
if (count1 < 8) {
@@ -1229,16 +1325,16 @@ void get_tlm_fox() {
batt_c_v = (int)(voltage[map[BAT]] * 100);
battCurr = (int)(current[map[BAT]] + 0.5) + 2048;
- PSUVoltage = (int)(voltage[map[BUS]] * 100);
- PSUCurrent = (int)(current[map[BUS]] + 0.5) + 2048;
+ BAT2Voltage = (int)(voltage[map[BAT2]] * 100);
+ BAT2Current = (int)(current[map[BAT2]] + 0.5) + 2048;
if (payload == ON)
STEMBoardFailure = 0;
// read payload sensor if available
- encodeA(b, 0 + head_offset, batt_a_v);
- encodeB(b, 1 + head_offset, batt_b_v);
+// encodeA(b, 0 + head_offset, batt_a_v); // replaced by XS2 and XS3 below
+// encodeB(b, 1 + head_offset, batt_b_v);
encodeA(b, 3 + head_offset, batt_c_v);
encodeB(b, 4 + head_offset, (int)(sensor[ACCEL_X] * 100 + 0.5) + 2048); // Xaccel
@@ -1295,14 +1391,14 @@ void get_tlm_fox() {
encodeA(b_max, 9 + head_offset, (int)(current_max[map[BAT]] + 0.5) + 2048);
encodeA(b_max, 3 + head_offset, (int)(voltage_max[map[BAT]] * 100));
- encodeA(b_max, 30 + head_offset, (int)(voltage_max[map[BUS]] * 100));
- encodeB(b_max, 46 + head_offset, (int)(current_max[map[BUS]] + 0.5) + 2048);
+ encodeA(b_max, 30 + head_offset, (int)(voltage_max[map[BAT2]] * 100));
+ encodeB(b_max, 46 + head_offset, (int)(current_max[map[BAT2]] + 0.5) + 2048);
encodeB(b_max, 37 + head_offset, (int)(other_max[RSSI] + 0.5) + 2048);
encodeA(b_max, 39 + head_offset, (int)(other_max[IHU_TEMP] * 10 + 0.5));
encodeB(b_max, 31 + head_offset, ((int)(other_max[SPIN] * 10)) + 2048);
-
- if (sensor_min[0] != 1000.0) // make sure values are valid
+
+ if (sensor_min[TEMP] != 1000.0) // make sure values are valid
{
encodeB(b_max, 4 + head_offset, (int)(sensor_max[ACCEL_X] * 100 + 0.5) + 2048); // Xaccel
encodeA(b_max, 6 + head_offset, (int)(sensor_max[ACCEL_Y] * 100 + 0.5) + 2048); // Yaccel
@@ -1314,10 +1410,14 @@ void get_tlm_fox() {
encodeA(b_max, 42 + head_offset, (int)(sensor_max[GYRO_Y] + 0.5) + 2048);
encodeB(b_max, 43 + head_offset, (int)(sensor_max[GYRO_Z] + 0.5) + 2048);
- encodeA(b_max, 48 + head_offset, (int)(sensor_max[XS1] * 10 + 0.5) + 2048);
- encodeB(b_max, 49 + head_offset, (int)(sensor_max[XS2] * 10 + 0.5) + 2048);
+ encodeA(b_max, 48 + head_offset, (int)(sensor_max[DTEMP] * 10 + 0.5) + 2048);
+// encodeB(b_max, 49 + head_offset, (int)(sensor_max[XS1] * 10 + 0.5) + 2048);
encodeB(b_max, 10 + head_offset, (int)(sensor_max[TEMP] * 10 + 0.5));
encodeA(b_max, 45 + head_offset, (int)(sensor_max[HUMI] * 10 + 0.5));
+
+ encodeB(b_max, 49 + head_offset, (int)(sensor[XS1]));
+ encodeA(b_max, 0 + head_offset, (int)(sensor[XS2]));
+ encodeB(b_max, 1 + head_offset, (int)(sensor[XS3]));
}
else
{
@@ -1330,7 +1430,7 @@ void get_tlm_fox() {
encodeB(b_max, 43 + head_offset, 2048);
encodeA(b_max, 48 + head_offset, 2048);
- encodeB(b_max, 49 + head_offset, 2048);
+// encodeB(b_max, 49 + head_offset, 2048);
}
encodeA(b_min, 12 + head_offset, (int)(voltage_min[map[PLUS_X]] * 100));
encodeB(b_min, 13 + head_offset, (int)(voltage_min[map[PLUS_Y]] * 100));
@@ -1348,14 +1448,14 @@ void get_tlm_fox() {
encodeA(b_min, 9 + head_offset, (int)(current_min[map[BAT]] + 0.5) + 2048);
encodeA(b_min, 3 + head_offset, (int)(voltage_min[map[BAT]] * 100));
- encodeA(b_min, 30 + head_offset, (int)(voltage_min[map[BUS]] * 100));
- encodeB(b_min, 46 + head_offset, (int)(current_min[map[BUS]] + 0.5) + 2048);
+ encodeA(b_min, 30 + head_offset, (int)(voltage_min[map[BAT2]] * 100));
+ encodeB(b_min, 46 + head_offset, (int)(current_min[map[BAT2]] + 0.5) + 2048);
encodeB(b_min, 31 + head_offset, ((int)(other_min[SPIN] * 10)) + 2048);
encodeB(b_min, 37 + head_offset, (int)(other_min[RSSI] + 0.5) + 2048);
encodeA(b_min, 39 + head_offset, (int)(other_min[IHU_TEMP] * 10 + 0.5));
- if (sensor_min[0] != 1000.0) // make sure values are valid
+ if (sensor_min[TEMP] != 1000.0) // make sure values are valid
{
encodeB(b_min, 4 + head_offset, (int)(sensor_min[ACCEL_X] * 100 + 0.5) + 2048); // Xaccel
encodeA(b_min, 6 + head_offset, (int)(sensor_min[ACCEL_Y] * 100 + 0.5) + 2048); // Yaccel
@@ -1367,10 +1467,14 @@ void get_tlm_fox() {
encodeA(b_min, 42 + head_offset, (int)(sensor_min[GYRO_Y] + 0.5) + 2048);
encodeB(b_min, 43 + head_offset, (int)(sensor_min[GYRO_Z] + 0.5) + 2048);
- encodeA(b_min, 48 + head_offset, (int)(sensor_min[XS1] * 10 + 0.5) + 2048);
- encodeB(b_min, 49 + head_offset, (int)(sensor_min[XS2] * 10 + 0.5) + 2048);
+ encodeA(b_min, 48 + head_offset, (int)(sensor_min[DTEMP] * 10 + 0.5) + 2048);
+// encodeB(b_min, 49 + head_offset, (int)(sensor_min[XS1] * 10 + 0.5) + 2048);
encodeB(b_min, 10 + head_offset, (int)(sensor_min[TEMP] * 10 + 0.5));
encodeA(b_min, 45 + head_offset, (int)(sensor_min[HUMI] * 10 + 0.5));
+
+ encodeB(b_min, 49 + head_offset, (int)(sensor[XS1]));
+ encodeA(b_min, 0 + head_offset, (int)(sensor[XS2]));
+ encodeB(b_min, 1 + head_offset, (int)(sensor[XS3]));
}
else
{
@@ -1383,10 +1487,10 @@ void get_tlm_fox() {
encodeB(b_min, 43 + head_offset, 2048);
encodeA(b_min, 48 + head_offset, 2048);
- encodeB(b_min, 49 + head_offset, 2048);
+// encodeB(b_min, 49 + head_offset, 2048);
}
}
- encodeA(b, 30 + head_offset, PSUVoltage);
+ encodeA(b, 30 + head_offset, BAT2Voltage);
encodeB(b, 31 + head_offset, ((int)(other[SPIN] * 10)) + 2048);
@@ -1404,20 +1508,46 @@ void get_tlm_fox() {
encodeA(b, 45 + head_offset, (int)(sensor[HUMI] * 10 + 0.5)); // in place of sensor1
- encodeB(b, 46 + head_offset, PSUCurrent);
- encodeA(b, 48 + head_offset, (int)(sensor[XS1] * 10 + 0.5) + 2048);
- encodeB(b, 49 + head_offset, (int)(sensor[XS2] * 10 + 0.5) + 2048);
-
+ encodeB(b, 46 + head_offset, BAT2Current);
+ encodeA(b, 48 + head_offset, (int)(sensor[DTEMP] * 10 + 0.5) + 2048);
+// encodeB(b, 49 + head_offset, (int)(sensor[XS1] * 10 + 0.5) + 2048);
+
+ encodeB(b, 49 + head_offset, (int)(sensor[XS1]));
+ encodeA(b, 0 + head_offset, (int)(sensor[XS2]));
+ encodeB(b, 1 + head_offset, (int)(sensor[XS3]));
+
+ FILE * command_count_file = fopen("/home/pi/CubeSatSim/command_count.txt", "r");
+ if (command_count_file != NULL) {
+ char count_string[10];
+ if ( (fgets(count_string, 10, command_count_file)) != NULL)
+ groundCommandCount = atoi(count_string);
+// fclose(command_count_file);
+ } else
+ printf("Error opening command_count.txt!\n");
+ fclose(command_count_file);
+
+// printf("Command count: %d\n", groundCommandCount);
+
int status = STEMBoardFailure + SafeMode * 2 + sim_mode * 4 + PayloadFailure1 * 8 +
(i2c_bus0 == OFF) * 16 + (i2c_bus1 == OFF) * 32 + (i2c_bus3 == OFF) * 64 + (camera == OFF) * 128 + groundCommandCount * 256;
encodeA(b, 51 + head_offset, status);
- encodeB(b, 52 + head_offset, rxAntennaDeployed + txAntennaDeployed * 2);
-
+ encodeB(b, 52 + head_offset, rxAntennaDeployed + txAntennaDeployed * 2 + c2cStatus * 4);
+ if (mode == BPSK) {
+ encodeA(b_max, 51 + head_offset, status);
+ encodeA(b_min, 51 + head_offset, status);
+ encodeB(b_max, 52 + head_offset, rxAntennaDeployed + txAntennaDeployed * 2 + c2cStatus * 4);
+ encodeB(b_min, 52 + head_offset, rxAntennaDeployed + txAntennaDeployed * 2 + c2cStatus * 4);
+ }
+
if (txAntennaDeployed == 0) {
txAntennaDeployed = 1;
printf("TX Antenna Deployed!\n");
}
+ if (rxAntennaDeployed == 0) {
+ rxAntennaDeployed = 1;
+ printf("RX Antenna Deployed!\n");
+ }
if (mode == BPSK) { // wod field experiments
unsigned long val = 0xffff;
@@ -1617,9 +1747,11 @@ void get_tlm_fox() {
if (connect(sock, (struct sockaddr * ) & serv_addr, sizeof(serv_addr)) < 0) {
printf("\nConnection Failed \n");
- printf("Error: %s \n", strerror(errno));
+ printf("Error: %s\n", strerror(errno));
error = 1;
- sleep(2.0); // sleep if socket connection refused
+// FILE * transmit_restartf2 = popen("sudo systemctl restart transmit", "r");
+// pclose(transmit_restartf2);
+// sleep(10); // was 5 // sleep if socket connection refused
// try again
error = 0;
@@ -1641,15 +1773,27 @@ void get_tlm_fox() {
if (connect(sock, (struct sockaddr * ) & serv_addr, sizeof(serv_addr)) < 0) {
printf("\nConnection Failed \n");
- printf("Error: %s \n", strerror(errno));
+ printf("Error: %s\n", strerror(errno));
error = 1;
- // sleep(1.0); // sleep if socket connection refused
+// FILE * transmit_restartf = popen("sudo systemctl restart transmit", "r");
+// pclose(transmit_restartf);
+// sleep(10); // was 5 // sleep if socket connection refused
}
}
- if (error == 1)
- ; //rpitxStatus = -1;
- else
+ if (error == 1) {
+ printf("Socket error count: %d\n", error_count);
+// ; //transmitStatus = -1;
+ if (error_count++ > 5) {
+ printf("Restarting transmit\n");
+ FILE * transmit_restartf = popen("sudo systemctl restart transmit", "r");
+ pclose(transmit_restartf);
+ sleep(10); // was 5 // sleep if socket connection refused
+ }
+ }
+ else {
socket_open = 1;
+ error_count = 0;
+ }
}
if (!error && transmit) {
@@ -1657,14 +1801,14 @@ void get_tlm_fox() {
// printf("Sending %d buffer bytes over socket after %d ms!\n", ctr, (long unsigned int)millis() - start);
start = millis();
int sock_ret = send(sock, buffer, (unsigned int)(ctr * 2 + 2), 0);
- printf("socket send 1 %d ms bytes: %d \n\n", (unsigned int)millis() - start, sock_ret);
+// printf("socket send 1 %d ms bytes: %d \n\n", (unsigned int)millis() - start, sock_ret);
fflush(stdout);
if (sock_ret < (ctr * 2 + 2)) {
// printf("Not resending\n");
sleep(0.5);
sock_ret = send(sock, &buffer[sock_ret], (unsigned int)(ctr * 2 + 2 - sock_ret), 0);
- printf("socket send 2 %d ms bytes: %d \n\n", millis() - start, sock_ret);
+// printf("socket send 2 %d ms bytes: %d \n\n", millis() - start, sock_ret);
}
loop_count++;
@@ -1688,7 +1832,7 @@ void get_tlm_fox() {
{
start = millis(); // send frame until buffer fills
sock_ret = send(sock, buffer, (unsigned int)(ctr * 2 + 2), 0);
- printf("socket send %d in %d ms bytes: %d \n\n",times + 2, (unsigned int)millis() - start, sock_ret);
+// printf("socket send %d in %d ms bytes: %d \n\n",times + 2, (unsigned int)millis() - start, sock_ret);
if ((millis() - start) > 500) {
printf("Buffer over filled!\n");
@@ -1711,7 +1855,7 @@ void get_tlm_fox() {
if (sock_ret == -1) {
printf("Error: %s \n", strerror(errno));
socket_open = 0;
- //rpitxStatus = -1;
+ //transmitStatus = -1;
}
}
if (!transmit) {
@@ -1873,3 +2017,224 @@ float toAprsFormat(float input) {
float output = dd * 100 + mm1 + (float)mm2 * 0.01;
return(output);
}
+
+int get_payload_serial(int debug_camera) {
+
+ index1 = 0;
+ flag_count = 0;
+ start_flag_detected = FALSE;
+ start_flag_complete = FALSE;
+ end_flag_detected = FALSE;
+ jpeg_start = 0;
+
+ serialFlush (uart_fd); // flush serial buffer so latest payload is read
+
+// #ifdef GET_IMAGE_DEBUG
+ if (debug_camera)
+ printf("Received from Payload:\n");
+ // #endif
+ finished = FALSE;
+
+ unsigned long time_start = millis();
+ while ((!finished) && ((millis() - time_start) < CAMERA_TIMEOUT)) {
+
+ if (serialDataAvail(uart_fd)) {
+ char octet = (char) serialGetchar(uart_fd);
+ printf("%c", octet);
+ fflush(stdout);
+
+ if (start_flag_complete) {
+// printf("Start flag complete detected\n");
+ buffer2[index1++] = octet;
+ if (octet == end_flag[flag_count]) { // looking for end flag
+// if (end_flag_detected) {
+ flag_count++;
+#ifdef GET_IMAGE_DEBUG
+// if (debug_camera)
+ printf("Found part of end flag!\n");
+#endif
+ if (flag_count >= strlen(end_flag)) { // complete image
+ index1 -= strlen(end_flag);
+ buffer2[index1++] = 0;
+ printf(" Payload length: %d \n",index1);
+
+// write_jpg();
+ finished = TRUE;
+ index1 = 0;
+ start_flag_complete = FALSE;
+ start_flag_detected = FALSE; // get ready for next image
+ end_flag_detected = FALSE;
+ flag_count = 0;
+// delay(6000);
+ }
+ } else {
+ if (flag_count > 1)
+ printf("Resetting. Not end flag.\n");
+ flag_count = 0;
+
+ }
+ /// buffer2[index1++] = octet;
+
+//#ifdef GET_IMAGE_DEBUG
+ if (debug_camera) {
+ char hexValue[5];
+ if (octet != 0x66) {
+ sprintf(hexValue, "%02X", octet);
+// printf(hexValue);
+ } else {
+// Serial.println("\n********************************************* Got a 66!");
+ printf("66");
+ }
+// Serial.write(octet);
+ }
+//#endif
+ if (index1 > 1000) {
+ index1 = 0;
+ printf("Resetting index!\n");
+ }
+// }
+ } else if (octet == start_flag[flag_count]) { // looking for start flag
+ start_flag_detected = TRUE;
+ flag_count++;
+#ifdef GET_IMAGE_DEBUG
+ printf("Found part of start flag! \n");
+#endif
+ if (flag_count >= strlen(start_flag)) {
+ flag_count = 0;
+ start_flag_complete = TRUE;
+#ifdef GET_IMAGE_DEBUG
+ printf("Found all of start flag!\n");
+#endif
+ }
+ } else { // not the flag, keep looking
+ start_flag_detected = FALSE;
+ flag_count = 0;
+#ifdef GET_IMAGE_DEBUG
+ printf("Resetting. Not start flag.\n");
+#endif
+ }
+ }
+// Serial.println("writing to Serial2");
+ }
+ if (debug_camera)
+ printf("\nComplete\n");
+ fflush(stdout);
+ return(finished);
+}
+
+void program_radio() {
+// if (sr_frs_present) {
+ printf("Programming FM module!\n");
+
+ pinMode(28, OUTPUT);
+ pinMode(29, OUTPUT);
+ digitalWrite(29, HIGH); // enable SR_FRS
+ digitalWrite(28, HIGH); // stop transmit
+
+if ((uart_fd = serialOpen("/dev/ttyAMA0", 9600)) >= 0) { // was 9600
+ printf("serial opened 9600\n");
+ for (int i = 0; i < 5; i++) {
+ sleep(1); // delay(500);
+//#ifdef APRS_VHF
+// char vhf_string[] = "AT+DMOSETGROUP=0,144.3900,144.3900,0,3,0,0\r\n";
+// serialPrintf(uart_fd, vhf_string);
+// mySerial.println("AT+DMOSETGROUP=0,144.3900,144.3900,0,3,0,0\r"); // can change to 144.39 for standard APRS
+// mySerial.println("AT+DMOSETGROUP=0,145.0000,145.0000,0,3,0,0\r"); // can change to 145 for testing ASPRS
+//#else
+ char uhf_string[] = "AT+DMOSETGROUP=0,435.0000,434.9000,0,3,0,0\r\n";
+ char uhf_string1a[] = "AT+DMOSETGROUP=0,"; // changed frequency to verify
+ char comma[] = ",";
+ char uhf_string1b[] = ",0,"; // changed frequency to verify
+ char uhf_string1[] = "AT+DMOSETGROUP=0,435.0000,434.9000,0,"; // changed frequency to verify
+ char uhf_string2[] = ",0,0\r\n";
+ char sq_string[2];
+ sq_string[0] = '0' + squelch;
+ sq_string[1] = 0;
+
+// serialPrintf(uart_fd, uhf_string);
+/**/
+ serialPrintf(uart_fd, uhf_string1a);
+ serialPrintf(uart_fd, rx);
+ serialPrintf(uart_fd, comma);
+ serialPrintf(uart_fd, tx);
+ serialPrintf(uart_fd, uhf_string1b);
+ serialPrintf(uart_fd, sq_string);
+ serialPrintf(uart_fd, uhf_string2);
+/**/
+
+// mySerial.println("AT+DMOSETGROUP=0,435.1000,434.9900,0,3,0,0\r"); // squelch set to 3
+//#endif
+ sleep(1);
+ char mic_string[] = "AT+DMOSETMIC=8,0\r\n";
+ serialPrintf(uart_fd, mic_string);
+// mySerial.println("AT+DMOSETMIC=8,0\r"); // was 8
+
+ }
+ }
+//#ifdef APRS_VHF
+// printf("Programming FM tx 144.39, rx on 144.39 MHz\n");
+//#else
+ printf("Programming FM tx 434.9, rx on 435.0 MHz\n");
+//#endif
+// digitalWrite(PTT_PIN, LOW); // transmit carrier for 0.5 sec
+// sleep(0.5);
+// digitalWrite(PTT_PIN, HIGH);
+ digitalWrite(29, LOW); // disable SR_FRS
+ pinMode(28, INPUT);
+ pinMode(29, INPUT);
+
+ serialClose(uart_fd);
+}
+
+int battery_saver_check() {
+ FILE *file = fopen("/home/pi/CubeSatSim/battery_saver", "r");
+ if (file == NULL) {
+// fprintf(stderr,"Battery saver mode is OFF!\n");
+ return(OFF);
+ }
+ fclose(file);
+// fprintf(stderr, "Safe Mode!\n");
+// fprintf(stderr,"Battery saver mode is ON!\n");
+ return(ON);
+}
+
+void battery_saver(int setting) {
+if (setting == ON) {
+ if (battery_saver_check() == OFF) {
+ FILE *command = popen("touch /home/pi/CubeSatSim/battery_saver", "r");
+ pclose(command);
+ fprintf(stderr,"Turning Safe Mode ON\n");
+ fprintf(stderr,"Turning Battery saver mode ON\n");
+ if ((mode == AFSK) || (mode == SSTV) || (mode == CW)) {
+ command = popen("echo 'reboot due to turning ON Safe Mode!' | wall", "r");
+ pclose(command);
+ command = popen("sudo reboot now", "r");
+ pclose(command);
+ sleep(60);
+ return;
+ }
+// } else
+// fprintf(stderr, "Nothing to do for battery_saver\n");
+ }
+ } else if (setting == OFF) {
+ if (battery_saver_check() == ON) {
+ FILE *command = popen("rm /home/pi/CubeSatSim/battery_saver", "r");
+ pclose(command);
+ fprintf(stderr,"Turning Battery saver mode OFF\n");
+ if ((mode == AFSK) || (mode == SSTV) || (mode == CW)) {
+ command = popen("echo 'reboot due to turning OFF Safe Mode!' | wall", "r");
+ pclose(command);
+ command = popen("sudo reboot now", "r");
+ pclose(command);
+ sleep(60);
+ return;
+ }
+// } else
+// fprintf(stderr, "Nothing to do for battery_saver\n");
+ }
+ } else {
+ fprintf(stderr,"battery_saver function error");
+ return;
+ }
+ return;
+}
diff --git a/main.h b/main.h
index f26913ec9..6708d1af1 100644
--- a/main.h
+++ b/main.h
@@ -29,24 +29,29 @@
#define PLUS_X 0
#define PLUS_Y 1
#define BAT 2
-#define BUS 3
+#define BAT2 3
#define MINUS_X 4
#define MINUS_Y 5
#define PLUS_Z 6
#define MINUS_Z 7
-#define TEMP 2
+#define TEMP 2 // OK and BME280 is positions 0 and 1
#define PRES 3
#define ALT 4
#define HUMI 5
-#define GYRO_X 7
+#define GYRO_X 7 // MPU6050 is posisition 6
#define GYRO_Y 8
#define GYRO_Z 9
#define ACCEL_X 10
#define ACCEL_Y 11
#define ACCEL_Z 12
-#define XS1 14
-#define XS2 15
-#define XS3 16
+#define GPS1 14 // GPS is position 13
+#define GPS2 15
+#define GPS3 16
+#define DTEMP 18 // TMP is position 17
+#define XS1 20 // NEW user defined token will be position 19
+#define XS2 21
+#define XS3 22
+#define SENSOR_FIELDS 26
#define RSSI 0
#define IHU_TEMP 2
@@ -54,6 +59,10 @@
#define OFF - 1
#define ON 1
+#define CHECK 0
+#define DISABLED 0
+#define CARRIER 1
+#define DTMF_APRS 2
uint32_t tx_freq_hz = 434900000 + FREQUENCY_OFFSET;
uint8_t data[1024];
@@ -77,6 +86,7 @@ void update_rs(unsigned char parity[32], unsigned char c);
void write_little_endian(unsigned int word, int num_bytes, FILE *wav_file);
static int init_rf();
extern int Encode_8b10b[][256];
+void program_radio();
int socket_open = 0;
int sock = 0;
@@ -89,6 +99,7 @@ char cmdbuffer[1000];
FILE * file1;
short int buffer[2336400]; // max size for 10 frames count of BPSK
FILE *sopen(const char *program);
+FILE *telem_file;
#define S_RATE (48000) // (44100)
@@ -97,8 +108,10 @@ FILE *sopen(const char *program);
#define BPSK 3
#define SSTV 4
#define CW 5
+#define REPEATER 11
+#define TXCOMMAND 12
-int rpitxStatus = -1;
+int transmitStatus = -1;
float amplitude; // = ; // 20000; // 32767/(10%amp+5%amp+100%amp)
float freq_Hz = 3000; // 1200
@@ -121,6 +134,11 @@ float uptime_sec = 0;
long int uptime;
char call[5];
char sim_yes[10];
+char hab_yes[10];
+int squelch = 3; // default squelch
+char rx[12], tx[12];
+int tx_pl = 0;
+int rx_pl = 0;
int bitRate, mode, bufLen, rsFrames, payloads, rsFrameLen, dataLen, headerLen, syncBits, syncWord, parityLen, samples, frameCnt, samplePeriod;
float sleepTime;
@@ -128,17 +146,21 @@ unsigned int sampleTime = 0;
int frames_sent = 0;
int cw_id = ON;
int vB4 = FALSE, vB5 = FALSE, vB3 = FALSE, ax5043 = FALSE, transmit = FALSE, onLed, onLedOn, onLedOff, txLed, txLedOn, txLedOff, payload = OFF;
+// float voltageThreshold = 3.6, batteryVoltage = 4.5, batteryCurrent = 0, currentThreshold = 100;
float voltageThreshold = 3.5, batteryVoltage = 4.5, batteryCurrent = 0, currentThreshold = 100;
float latitude = 39.027702f, longitude = -77.078064f;
float lat_file, long_file;
double cpuTemp;
int frameTime;
+long int newGpsTime;
float axis[3], angle[3], volts_max[3], amps_max[3], batt, speed, period, tempS, temp_max, temp_min, eclipse;
-int i2c_bus0 = OFF, i2c_bus1 = OFF, i2c_bus3 = OFF, camera = OFF, sim_mode = FALSE, SafeMode = FALSE, rxAntennaDeployed = 0, txAntennaDeployed = 0;
+int i2c_bus0 = OFF, i2c_bus1 = OFF, i2c_bus3 = OFF, camera = OFF, sim_mode = FALSE, SafeMode = FALSE;
+int rxAntennaDeployed = 0, txAntennaDeployed = 0, c2cStatus = 0;
+int sim_config = FALSE; // sim mode not set by configuration
double eclipse_time;
-float voltage[9], current[9], sensor[17], other[3];
+float voltage[9], current[9], sensor[SENSOR_FIELDS], other[3];
char sensor_payload[500];
int test_i2c_bus(int bus);
@@ -149,5 +171,35 @@ char pythonStr[100], pythonConfigStr[100], busStr[10];
int map[8] = {0, 1, 2, 3, 4, 5, 6, 7};
char src_addr[5] = "";
char dest_addr[5] = "APCSS";
-float voltage_min[9], current_min[9], voltage_max[9], current_max[9], sensor_max[17], sensor_min[17], other_max[3], other_min[3];
+float voltage_min[9], current_min[9], voltage_max[9], current_max[9], sensor_max[SENSOR_FIELDS], sensor_min[SENSOR_FIELDS], other_max[3], other_min[3];
+int get_payload_serial(int debug_camera);
+int finished = FALSE;
+
+//char buffer2[100001];
+char buffer2[2000];
+int index1 = 0;
+//char start_flag[] = "3d99de816e5ad7742b61a37c39141783";
+char start_flag[] = "_START_FLAG_";
+
+//char end_flag[] = "f681a5c52351befe0e3524eb1a40f14b7803317a";
+char end_flag[] = "_END_FLAG_";
+
+int flag_count = 0;
+int start_flag_detected = FALSE;
+int start_flag_complete = FALSE;
+int end_flag_detected = FALSE;
+int jpeg_start = 0;
+#define CAMERA_TIMEOUT 2000 // 1500 // 2000 // 10000 // 20000 // Payload timeout in milli seconds
+
+void battery_saver(int setting);
+int battery_saver_check();
+int pi_zero_2_offset = 0;
+
+
+int hab_mode = FALSE;
+int battery_saver_mode = FALSE;
+long int loopTime;
+
+int error_count = 0;
+int groundCommandCount = 0;
diff --git a/rpitx.py b/rpitx.py
deleted file mode 100644
index 08f929a10..000000000
--- a/rpitx.py
+++ /dev/null
@@ -1,283 +0,0 @@
-#!/usr/bin/env python
-
-import RPi.GPIO as GPIO
-from RPi.GPIO import output
-#import subprocess
-#import time
-from time import sleep
-#import os
-import sys
-from os import system
-
-print("CubeSatSim v1.1 rpitx.py starting...")
-
-GPIO.setmode(GPIO.BCM)
-GPIO.setwarnings(False)
-GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP)
-GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
-GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_UP)
-
-transmit = False
-if GPIO.input(12) == False:
- print("Version is v1 with UHF BPF")
- transmit = True
- txLed = 27
- txLedOn = 1
- txLedOff = 0
-elif GPIO.input(27) == False:
- print("Version is TFB")
- transmit = True
- txLed = 22
- txLedOn = 0
- txLedOff = 1
-elif GPIO.input(13) == False:
- print("Version is v1 with VHF BPF")
- print("VHF transmit not implemented yet")
-# transmit = True
- txLed = 27
- txLedOn = 1
- txLedOff = 0
-else:
- print("No BPF")
- txLed = 27
- txLedOn = 1
- txLedOff = 0
-
-# GPIO.setup(txLed, GPIO.OUT)
-# output(txLed, txLedOff)
-
-GPIO.setmode(GPIO.BCM) # Repeat to make LED work on Pi 4
-GPIO.setwarnings(False)
-GPIO.setup(txLed, GPIO.OUT)
-
-output(txLed, txLedOn)
-sleep(1)
-output(txLed, txLedOff)
-
-# print(txLedOn)
-print(txLed)
-# GPIO.setup(27, GPIO.OUT)
-# GPIO.output(27, 0)
-
-debug_mode = 0
-
-if __name__ == "__main__":
-
- if (len(sys.argv)) > 1:
-# print("There are arguments!")
- if (('d' == sys.argv[1]) or ('-d' in sys.argv[1])):
- debug_mode = 1
-
- print(transmit)
-
- 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/sim.cfg")
- callsign = file.readline().split(" ")[0]
- except:
- callsign = "AMSAT"
- if (debug_mode == 1):
- print("Can't read callsign from sim.cfg file, defaulting to AMSAT")
- print(callsign)
- GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi 4
- GPIO.setup(txLed, GPIO.OUT)
-
- sleep(1)
- output(txLed, txLedOn)
- if (debug_mode == 1):
- system("echo 'hi hi de " + callsign + "' > 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 434.9e3")
- else:
- system("echo 'hi hi de " + callsign + "' > 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 434.9e3 > /dev/null 2>&1")
-
- sleep(4); # was 8
- output(txLed, txLedOff)
-
- sleep(1)
-
-
- if (transmit):
-
-# print 'Length: ', len(sys.argv)
-
-# if (len(sys.argv)) > 1:
-# print("There are arguments!")
- if (mode == 'a'):
- print("AFSK")
- sleep(5)
- try:
- file = open("/home/pi/CubeSatSim/t.txt")
- file.close()
- except:
- system("echo '" + callsign + "-11>APCSS:hi hi 100 199 199 199 298 299 299 278 380 350 300 300 439 400 400 400 500 500 500 500 600 600 600 650' > /home/pi/CubeSatSim/t.txt && echo 'AMSAT>APCSS:010101/hi hi ' >> /home/pi/CubeSatSim/t.txt")
- for x in range(5):
- output(txLed, txLedOn)
- 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 434.9e3")
- 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 434.9e3 > /dev/null 2>&1")
- sleep(0.2)
- output(txLed, txLedOff)
- sleep(3.8)
- while True:
- try:
- f = open("/home/pi/CubeSatSim/ready")
- output(txLed, txLedOn)
- 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 434.9e3")
- 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 434.9e3 > /dev/null 2>&1")
- output(txLed, txLedOff)
- f.close()
- system("sudo rm /home/pi/CubeSatSim/ready")
- sleep(0.5)
- except:
- sleep(0.5)
- elif (mode == 'm'):
- print("CW")
-# sleep(4)
- try:
- file = open("/home/pi/CubeSatSim/cw.txt")
- file.close()
- except:
- system("echo 'hi hi 100 199 199 199 298 299 299 278 380 350 300 300 439 400 400 400 500 500 500 500 600 600 600 650' > /home/pi/CubeSatSim/cw.txt")
- output(txLed, txLedOn)
- if (debug_mode == 1):
- system("gen_packets -M 20 -o /home/pi/CubeSatSim/morse.wav /home/pi/CubeSatSim/cw.txt -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 434.9e3")
- else:
- system("gen_packets -M 20 -o /home/pi/CubeSatSim/morse.wav /home/pi/CubeSatSim/cw.txt -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 434.9e3 > /dev/null 2>&1")
- output(txLed, txLedOff)
-
- while True:
- try:
- f = open("/home/pi/CubeSatSim/cwready")
- output(txLed, txLedOn)
- if (debug_mode == 1):
- system("gen_packets -M 20 -o /home/pi/CubeSatSim/morse.wav /home/pi/CubeSatSim/cw.txt -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 434.9e3")
- else:
- system("gen_packets -M 20 -o /home/pi/CubeSatSim/morse.wav /home/pi/CubeSatSim/cw.txt -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 434.9e3 > /dev/null 2>&1")
- output(txLed, txLedOff)
- f.close()
- system("sudo rm /home/pi/CubeSatSim/cwready")
- sleep(1)
- except:
- sleep(1)
- elif (mode == 's'):
- print("SSTV")
- try:
-# from picamera import PiCamera
-# from pysstv.sstv import SSTV
-# camera = PiCamera()
- print("Testing for camera")
- system("raspistill -o /home/pi/CubeSatSim/camera_out.jpg -w 320 -h 256")
- f = open("/home/pi/CubeSatSim/camera_out.jpg")
- 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, txLedOff)
- 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")
- print ("Sending SSTV image")
- output(txLed, txLedOn)
- 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 434.9e3")
- 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 434.9e3 > /dev/null 2>&1")
- output(txLed, txLedOff)
- # sleep(1)
- except:
- print("image 2 did not load - copy from CubeSatSim/sstv directory")
- while 1:
- system("raspistill -o /home/pi/CubeSatSim/camera_out.jpg -w 320 -h 256") # > /dev/null 2>&1")
- print("Photo taken")
- 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")
- print ("Sending SSTV image")
- output(txLed, txLedOn)
- 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 434.9e3")
- 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 434.9e3 > /dev/null 2>&1")
- output(txLed, txLedOff)
- system("sudo rm /home/pi/CubeSatSim/camera_out.jpg.wav > /dev/null 2>&1")
- sleep(1)
- else:
- try:
- 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")
- print ("Sending SSTV image")
- output(txLed, txLedOn)
- 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 434.9e3")
- 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 434.9e3 > /dev/null 2>&1")
- output(txLed, txLedOff)
- sleep(1)
- except:
- print("image 1 did not load - copy from CubeSatSim/sstv directory")
- try:
- 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:
- print ("Sending SSTV image")
- output(txLed, txLedOn)
- 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 434.9e3")
- 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 434.9e3 > /dev/null 2>&1")
- output(txLed, txLedOff)
- sleep(5)
- except:
- print("image 2 did not load - copy from CubeSatSim/sstv directory")
- system("(while true; do (sleep 5 && 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 434.9e3 &")
- while 1:
- output(txLed, txLedOn)
- sleep(60)
- output(txLed, txLedOff)
- sleep(1)
-
- elif (mode == 'b'):
- print("BPSK")
- 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 &")
- print("Turning LED on/off")
- while 1:
- output(txLed, txLedOff)
- sleep(0.5)
- output(txLed, txLedOn)
- sleep(4.0)
- else:
- print("FSK")
- 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 434.9e3 &")
- print("Turning LED on/off")
- while 1:
- output(txLed, txLedOff)
- sleep(0.5)
- output(txLed, txLedOn)
- sleep(4.0)
-# else:
-# print("FSK")
-# 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 434.9e3")
-
- else:
- print("No Band Pass Filter so no telemetry transmit. See http://cubesatsim.org/wiki for instructions on how to build the BPF.")
- while 1:
- sleep(5)
diff --git a/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_maxtelemetry.csv b/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_maxtelemetry.csv
new file mode 100644
index 000000000..5e4214929
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_maxtelemetry.csv
@@ -0,0 +1,62 @@
+61,TYPE,FIELD,BITS,UNIT,CONVERSION,MODULE,MODULE_NUM,MODULE_LINE,LINE_TYPE,SHORT_NAME,DESCRIPTION
+0,MAX,Sensor 2,12,integer,1,NONE,6,8,3,Sensor 2,STEM Payload Extra Sensor 2
+1,MAX,Sensor 3,12,integer,1,NONE,6,9,3,Sensor 3,STEM Payload Extra Sensor 3
+2,MAX,BATT_V,12,V,cubesatsim_voltage|FLOAT2,NONE,4,1,3,Battery Voltage,INA219 Battery Voltage
+3,MAX,SatelliteXAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,7,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around X Axis
+4,MAX,SatelliteYAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,8,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Y Axis
+5,MAX,SatelliteZAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,9,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Z Axis
+6,MAX,BATT_I,12,mA,cubesatsim_current,NONE,4,2,3,Battery Current,INA219 Battery Current
+7,MAX,Temperature,12,C,cubesatsim_temperature,NONE,6,2,3,BME280 Temp,BME280 STEM Payload sensor temperature
+8,MAX,posXv,12,V,cubesatsim_voltage|FLOAT2,NONE,7,1,3,Voltage,INA219 +X solar panel Voltage
+9,MAX,posYv,12,V,cubesatsim_voltage|FLOAT2,NONE,8,1,3,Voltage,INA219 +Y solar panel Voltage
+10,MAX,posZv,12,V,cubesatsim_voltage|FLOAT2,NONE,9,1,3,Voltage,INA219 +Z solar panel Voltage
+11,MAX,negXv,12,V,cubesatsim_voltage|FLOAT2,NONE,10,1,3,Voltage,INA219 -X solar panel Voltage
+12,MAX,negYv,12,V,cubesatsim_voltage|FLOAT2,NONE,11,1,3,Voltage,INA219 -Y solar panel Voltage
+13,MAX,negZv,12,V,cubesatsim_voltage|FLOAT2,NONE,12,1,3,Voltage,INA219 -Z solar panel Voltage
+14,MAX,posXi,12,mA,cubesatsim_current,NONE,7,2,3,Current,INA219 +X solar panel Current
+15,MAX,posYi,12,mA,cubesatsim_current,NONE,8,2,3,Current,INA219 +Y solar panel Current
+16,MAX,posZi,12,mA,cubesatsim_current,NONE,9,2,3,Current,INA219 +Z solar panel Current
+17,MAX,negXi,12,mA,cubesatsim_current,NONE,10,2,3,Current,INA219 -X solar panel Current
+18,MAX,negYi,12,mA,cubesatsim_current,NONE,11,2,3,Current,INA219 -Y solar panel Current
+19,MAX,negZi,12,mA,cubesatsim_current,NONE,12,2,3,Current,INA219 -Z solar panel Current
+20,MAX,BATT2_V,12,V,cubesatsim_voltage|FLOAT2,NONE,5,1,3,Battery 2 Voltage,INA219 Battery 2 Voltage
+21,MAX,spin,12,rpm,cubesatsim_rpm,NONE,3,1,3,Spacecraft Spin,Calculated spin rate using solar cells
+22,MAX,Pressure,12,hPa,cubesatsim_pressure,NONE,6,3,3,BME280 Pressure,BME280 STEM Payload sensor pressure
+23,MAX,Altitude,12,m,cubesatsim_altitude,NONE,6,4,3,BME280 Altitude,BME280 STEM Payload sensor altitude
+24,MAX,Resets,12,-,12,NONE,3,2,3,Reset Count, Software Reset Count
+25,MAX,rssi,12,dBm,cubesatsim_rssi|INT,NONE,1,1,3,RSSI,Received Signal Strength Indication
+26,MAX,IHUcpuTemp,12,C,cubesatsim_temperature,NONE,2,1,3,IHU Temp (Pi),Internal temperature of IHU from Pi
+27,MAX,SatelliteXAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,7,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around X Axis
+28,MAX,SatelliteYAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,8,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around Y Axis
+29,MAX,SatelliteZAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,9,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around Z Axis
+30,MAX,Humidity,12,%,cubesatsim_temperature,NONE,6,5,3,BME280 Humidity,BME280 Humidity
+31,MAX,BAT2_I,12,mA,cubesatsim_current,NONE,5,2,3,Battery 2 Current,INA219 Battery 2 Current
+32,MAX,DiodeTemp,12,C,cubesatsim_rpm,NONE,6,6,3,Diode Temp,STEM Payload Diode Temperature
+33,MAX,Sensor 1,12,integer,1,NONE,6,7,3,Sensor 1,STEM Payload Extra Sensor 1
+34,MAX,STEMPayloadStatus,1,-,17,NONE,6,1,0,STEM Payload Status, STEM Payload STEM Payload board failure Indicator
+35,MAX,SafeMode,1,-,STATUS_ON_OFF,NONE,3,2,0,Safe Mode, Safe Mode (Low Battery Voltage)
+36,MAX,SimulatedTelemetry,1,-,STATUS_ON_OFF,NONE,3,4,0,Simulated Telemetry,Simulated Telemetry Indicator
+37,MAX,PayloadStatus1,1,-,17,NONE,6,8,0,Exp 3,STEM Payload status 1 failure indicator
+38,MAX,I2CBus0Failure,1,-,17,NONE,2,2,0,I2C Bus 0,I2C bus 0 failure indicator
+39,MAX,I2CBus1Failure,1,-,17,NONE,2,2,0,I2C Bus 1,I2C bus 1 failure indicator
+40,MAX,I2CBus3Failure,1,-,17,NONE,2,3,0,I2C Bus 3,I2C bus 3 failure indicator
+41,MAX,CameraFailure,1,-,17,NONE,2,4,0,Camera,Camera failure indicator
+42,MAX,GroundCommands,4,-,1,NONE,3,3,0,Ground Commands,Number of ground commands received
+43,MAX,RxAntenna,1,-,16,NONE,1,3,0,RX Antenna,Receive antenna status
+44,MAX,TxAntenna,1,-,16,NONE,1,2,0,TX Antenna,Transmit antenna status
+45,MAX,C2CStatus,2,-,COMMAND_STATUS,NONE,3,5,0,Command Control, Command & Control Status
+46,MAX,ICR3VProt,12,V,43,NONE,7,2,3,3V Prot,ICR 3V Proteted
+47,MAX,ICR2dot5V,12,V,43,NONE,7,3,3,2.5V,ICR 2.5V
+48,MAX,ICR2dot5VProt,12,V,43,NONE,7,4,3,2.5V Prot,ICR 2.5V Protected
+49,MAX,rf6,12,-,0,NONE,0,0,0,None,None
+50,MAX,rf7,12,-,0,NONE,0,0,0,None,None
+51,MAX,MuxTest,12,V,43,NONE,7,5,3,Sensor Power,Sensor Power Voltage at the ICR
+52,MAX,LtVGACtl,12,V,42,NONE,1,4,3,VGA Control,Control Voltage to the Variable Gain Amplifier (VGA)
+53,MAX,pad,4,-,34,NONE,0,0,0,None,Unused
+54,MAX,IHUdiagData,32,-,18,NONE,3,2,0,Diagnostic Info,Diagnostic Data on IHU Performance
+55,MAX,pad1,1,-,0,NONE,0,0,0,NONE,Filler
+56,MAX,wodSize,8,000s,36,NONE,3,3,0,WOD Stored,Number of WOD data payloads kept for each of Science and Housekeeping. In hundreds
+57,MAX,swCmds,32,-,35,NONE,7,6,0,Diagnostic,ICR Diagnostic information
+58,MAX,hwCmdCnt,6,-,1,NONE,7,7,0,HW Command Count,Number of hardware commands since last reset
+59,MAX,swCmdCnt,6,-,1,NONE,7,8,0,SW Command Count,Number of software commands since last reset
+60,MAX,pad2,27,-,0,NONE,0,0,0,NONE,Filler
diff --git a/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_mintelemetry.csv b/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_mintelemetry.csv
new file mode 100644
index 000000000..97dcaa4b5
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_mintelemetry.csv
@@ -0,0 +1,62 @@
+61,TYPE,FIELD,BITS,UNIT,CONVERSION,MODULE,MODULE_NUM,MODULE_LINE,LINE_TYPE,SHORT_NAME,DESCRIPTION
+0,MIN,Sensor 2,12,integer,1,NONE,6,8,3,Sensor 2,STEM Payload Extra Sensor 2
+1,MIN,Sensor 3,12,integer,1,NONE,6,9,3,Sensor 3,STEM Payload Extra Sensor 3
+2,MIN,BATT_V,12,V,cubesatsim_voltage|FLOAT2,NONE,4,1,3,Battery Voltage,INA219 Battery Voltage
+3,MIN,SatelliteXAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,7,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around X Axis
+4,MIN,SatelliteYAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,8,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Y Axis
+5,MIN,SatelliteZAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,9,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Z Axis
+6,MIN,BATT_I,12,mA,cubesatsim_current,NONE,4,2,3,Battery Current,INA219 Battery Current
+7,MIN,Temperature,12,C,cubesatsim_temperature,NONE,6,2,3,BME280 Temp,BME280 STEM Payload sensor temperature
+8,MIN,posXv,12,V,cubesatsim_voltage|FLOAT2,NONE,7,1,3,Voltage,INA219 +X solar panel Voltage
+9,MIN,posYv,12,V,cubesatsim_voltage|FLOAT2,NONE,8,1,3,Voltage,INA219 +Y solar panel Voltage
+10,MIN,posZv,12,V,cubesatsim_voltage|FLOAT2,NONE,9,1,3,Voltage,INA219 +Z solar panel Voltage
+11,MIN,negXv,12,V,cubesatsim_voltage|FLOAT2,NONE,10,1,3,Voltage,INA219 -X solar panel Voltage
+12,MIN,negYv,12,V,cubesatsim_voltage|FLOAT2,NONE,11,1,3,Voltage,INA219 -Y solar panel Voltage
+13,MIN,negZv,12,V,cubesatsim_voltage|FLOAT2,NONE,12,1,3,Voltage,INA219 -Z solar panel Voltage
+14,MIN,posXi,12,mA,cubesatsim_current,NONE,7,2,3,Current,INA219 +X solar panel Current
+15,MIN,posYi,12,mA,cubesatsim_current,NONE,8,2,3,Current,INA219 +Y solar panel Current
+16,MIN,posZi,12,mA,cubesatsim_current,NONE,9,2,3,Current,INA219 +Z solar panel Current
+17,MIN,negXi,12,mA,cubesatsim_current,NONE,10,2,3,Current,INA219 -X solar panel Current
+18,MIN,negYi,12,mA,cubesatsim_current,NONE,11,2,3,Current,INA219 -Y solar panel Current
+19,MIN,negZi,12,mA,cubesatsim_current,NONE,12,2,3,Current,INA219 -Z solar panel Current
+20,MIN,BATT2_V,12,V,cubesatsim_voltage|FLOAT2,NONE,5,1,3,Battery 2 Voltage,INA219 Battery 2 Voltage
+21,MIN,spin,12,rpm,cubesatsim_rpm,NONE,3,1,3,Spacecraft Spin,Calculated spin rate using solar cells
+22,MIN,Pressure,12,hPa,cubesatsim_pressure,NONE,6,3,3,BME280 Pressure,BME280 STEM Payload sensor pressure
+23,MIN,Altitude,12,m,cubesatsim_altitude,NONE,6,4,3,BME280 Altitude,BME280 STEM Payload sensor altitude
+24,MIN,Resets,12,-,12,NONE,3,2,3,Reset Count, Software Reset Count
+25,MIN,rssi,12,dBm,cubesatsim_rssi|INT,NONE,1,1,3,RSSI,Received Signal Strength Indication
+26,MIN,IHUcpuTemp,12,C,cubesatsim_temperature,NONE,2,1,3,IHU Temp (Pi),Internal temperature of IHU from Pi
+27,MIN,SatelliteXAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,7,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around X Axis
+28,MIN,SatelliteYAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,8,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around Y Axis
+29,MIN,SatelliteZAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,9,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around Z Axis
+30,MIN,Humidity,12,%,cubesatsim_temperature,NONE,6,5,3,BME280 Humidity,BME280 Humidity
+31,MIN,BAT2_I,12,mA,cubesatsim_current,NONE,5,2,3,Battery 2 Current,INA219 Battery 2 Current
+32,MIN,DiodeTemp,12,C,cubesatsim_rpm,NONE,6,6,3,Diode Temp,STEM Payload Diode Temperature
+33,MIN,Sensor 1,12,integer,1,NONE,6,7,3,Sensor 1,STEM Payload Extra Sensor 1
+34,MIN,STEMPayloadStatus,1,-,17,NONE,6,1,0,STEM Payload Status, STEM Payload STEM Payload board failure Indicator
+35,MIN,SafeMode,1,-,STATUS_ON_OFF,NONE,3,2,0,Safe Mode, Safe Mode (Low Battery Voltage)
+36,MIN,SimulatedTelemetry,1,-,STATUS_ON_OFF,NONE,3,4,0,Simulated Telemetry,Simulated Telemetry Indicator
+37,MIN,PayloadStatus1,1,-,17,NONE,6,8,0,Exp 3,STEM Payload status 1 failure indicator
+38,MIN,I2CBus0Failure,1,-,17,NONE,2,2,0,I2C Bus 0,I2C bus 0 failure indicator
+39,MIN,I2CBus1Failure,1,-,17,NONE,2,2,0,I2C Bus 1,I2C bus 1 failure indicator
+40,MIN,I2CBus3Failure,1,-,17,NONE,2,3,0,I2C Bus 3,I2C bus 3 failure indicator
+41,MIN,CameraFailure,1,-,17,NONE,2,4,0,Camera,Camera failure indicator
+42,MIN,GroundCommands,4,-,1,NONE,3,3,0,Ground Commands,Number of ground commands received
+43,MIN,RxAntenna,1,-,16,NONE,1,3,0,RX Antenna,Receive antenna status
+44,MIN,TxAntenna,1,-,16,NONE,1,2,0,TX Antenna,Transmit antenna status
+45,MIN,C2CStatus,2,-,COMMAND_STATUS,NONE,3,5,0,Command Control, Command & Control Status
+46,MIN,ICR3VProt,12,V,43,NONE,7,2,3,3V Prot,ICR 3V Proteted
+47,MIN,ICR2dot5V,12,V,43,NONE,7,3,3,2.5V,ICR 2.5V
+48,MIN,ICR2dot5VProt,12,V,43,NONE,7,4,3,2.5V Prot,ICR 2.5V Protected
+49,MIN,rf6,12,-,0,NONE,0,0,0,None,None
+50,MIN,rf7,12,-,0,NONE,0,0,0,None,None
+51,MIN,MuxTest,12,V,43,NONE,7,5,3,Sensor Power,Sensor Power Voltage at the ICR
+52,MIN,LtVGACtl,12,V,42,NONE,1,4,3,VGA Control,Control Voltage to the Variable Gain Amplifier (VGA)
+53,MIN,pad,4,-,34,NONE,0,0,0,None,Unused
+54,MIN,IHUdiagData,32,-,18,NONE,3,2,0,Diagnostic Info,Diagnostic Data on IHU Performance
+55,MIN,pad1,1,-,0,NONE,0,0,0,NONE,Filler
+56,MIN,wodSize,8,000s,36,NONE,3,3,0,WOD Stored,Number of WOD data payloads kept for each of Science and Housekeeping. In hundreds
+57,MIN,swCmds,32,-,35,NONE,7,6,0,Diagnostic,ICR Diagnostic information
+58,MIN,hwCmdCnt,6,-,1,NONE,7,7,0,HW Command Count,Number of hardware commands since last reset
+59,MIN,swCmdCnt,6,-,1,NONE,7,8,0,SW Command Count,Number of software commands since last reset
+60,MIN,pad2,27,-,0,NONE,0,0,0,NONE,Filler
diff --git a/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_rttelemetry.csv b/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_rttelemetry.csv
new file mode 100644
index 000000000..17ef4ab64
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/CubeSatSim_PSK_rttelemetry.csv
@@ -0,0 +1,62 @@
+61,TYPE,FIELD,BITS,UNIT,CONVERSION,MODULE,MODULE_NUM,MODULE_LINE,LINE_TYPE,SHORT_NAME,DESCRIPTION
+0,realTime,Sensor 2,12,integer,1,Experiments,6,8,3,Sensor 2,STEM Payload Extra Sensor 2
+1,realTime,Sensor 3,12,integer,1,Experiments,6,9,3,Sensor 3,STEM Payload Extra Sensor 3
+2,realTime,BATT_V,12,V,cubesatsim_voltage|FLOAT2,Battery,4,1,3,Battery Voltage,INA219 Battery Voltage
+3,realTime,SatelliteXAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,+X Panel,7,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around X Axis
+4,realTime,SatelliteYAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,+Y Panel,8,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Y Axis
+5,realTime,SatelliteZAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,+Z Panel,9,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Z Axis
+6,realTime,BATT_I,12,mA,cubesatsim_current,Battery,4,2,3,Battery Current,INA219 Battery Current
+7,realTime,Temperature,12,C,cubesatsim_temperature,Experiments,6,2,3,BME280 Temp,BME280 STEM Payload sensor temperature
+8,realTime,posXv,12,V,cubesatsim_voltage|FLOAT2,+X Panel,7,1,3,Voltage,INA219 +X solar panel Voltage
+9,realTime,posYv,12,V,cubesatsim_voltage|FLOAT2,+Y Panel,8,1,3,Voltage,INA219 +Y solar panel Voltage
+10,realTime,posZv,12,V,cubesatsim_voltage|FLOAT2,+Z Panel,9,1,3,Voltage,INA219 +Z solar panel Voltage
+11,realTime,negXv,12,V,cubesatsim_voltage|FLOAT2,-X Panel,10,1,3,Voltage,INA219 -X solar panel Voltage
+12,realTime,negYv,12,V,cubesatsim_voltage|FLOAT2,-Y Panel,11,1,3,Voltage,INA219 -Y solar panel Voltage
+13,realTime,negZv,12,V,cubesatsim_voltage|FLOAT2,-Z Panel,12,1,3,Voltage,INA219 -Z solar panel Voltage
+14,realTime,posXi,12,mA,cubesatsim_current,+X Panel,7,2,3,Current,INA219 +X solar panel Current
+15,realTime,posYi,12,mA,cubesatsim_current,+Y Panel,8,2,3,Current,INA219 +Y solar panel Current
+16,realTime,posZi,12,mA,cubesatsim_current,+Z Panel,9,2,3,Current,INA219 +Z solar panel Current
+17,realTime,negXi,12,mA,cubesatsim_current,-X Panel,10,2,3,Current,INA219 -X solar panel Current
+18,realTime,negYi,12,mA,cubesatsim_current,-Y Panel,11,2,3,Current,INA219 -Y solar panel Current
+19,realTime,negZi,12,mA,cubesatsim_current,-Z Panel,12,2,3,Current,INA219 -Z solar panel Current
+20,realTime,BATT2_V,12,V,cubesatsim_voltage|FLOAT2,Battery2,5,1,3,Battery2 Voltage,INA219 Battery2 Voltage
+21,realTime,spin,12,rpm,cubesatsim_rpm,Computer Software,3,1,3,Spacecraft Spin,Calculated spin rate using solar cells
+22,realTime,Pressure,12,hPa,cubesatsim_pressure,Experiments,6,3,3,BME280 Pressure,BME280 STEM Payload sensor pressure
+23,realTime,Altitude,12,m,cubesatsim_altitude,Experiments,6,4,3,BME280 Altitude,BME280 STEM Payload sensor altitude
+24,realTime,Resets,12,-,12,NONE,3,2,3,Reset Count, Software Reset Count
+25,realTime,rssi,12,dBm,cubesatsim_rssi|INT,Radio,1,1,3,RSSI,Received Signal Strength Indication
+26,realTime,IHUcpuTemp,12,C,cubesatsim_temperature,Computer Hardware,2,1,3,IHU Temp (Pi),Internal temperature of IHU from Pi
+27,realTime,SatelliteXAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,+X Panel,7,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around X Axis
+28,realTime,SatelliteYAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,+Y Panel,8,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around Y Axis
+29,realTime,SatelliteZAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,+Z Panel,9,3,3,Rotation,STEM Payload Board MPU6050 Angular veolcity around Z Axis
+30,realTime,Humidity,12,%,cubesatsim_temperature,Experiments,6,5,3,BME280 Humidity,BME280 Humidity
+31,realTime,BAT2_I,12,mA,cubesatsim_current,Battery2,5,2,3,Battery2 Current,INA219 Battery2 Current
+32,realTime,DiodeTemp,12,C,cubesatsim_rpm,Experiments,6,6,3,Diode Temp,STEM Payload Diode Temperature
+33,realTime,Sensor 1,12,integer,1,Experiments,6,7,3,Sensor 1,STEM Payload Extra Sensor 1
+34,realTime,STEMPayloadStatus,1,-,17,Experiments,6,1,0,STEM Payload Status, STEM Payload STEM Payload board failure Indicator
+35,realTime,SafeMode,1,-,STATUS_ON_OFF,Computer Software,3,2,0,Safe Mode, Safe Mode (Low Battery Voltage)
+36,realTime,SimulatedTelemetry,1,-,STATUS_ON_OFF,Computer Software,3,4,0,Simulated Telemetry,Simulated Telemetry Indicator
+37,realTime,PayloadStatus1,1,-,17,NONE,6,8,0,Exp 3,STEM Payload status 1 failure indicator
+38,realTime,I2CBus0Failure,1,-,17,NONE,2,2,0,I2C Bus 0,I2C bus 0 failure indicator
+39,realTime,I2CBus1Failure,1,-,17,Computer Hardware,2,2,0,I2C Bus 1,I2C bus 1 failure indicator
+40,realTime,I2CBus3Failure,1,-,17,Computer Hardware,2,3,0,I2C Bus 3,I2C bus 3 failure indicator
+41,realTime,CameraFailure,1,-,17,Computer Hardware,2,4,0,Camera,Camera failure indicator
+42,realTime,GroundCommands,4,-,1,Computer Software,3,3,0,Ground Commands,Number of ground commands received
+43,realTime,RxAntenna,1,-,16,Radio,1,3,0,RX Antenna,Receive antenna status
+44,realTime,TxAntenna,1,-,16,Radio,1,2,0,TX Antenna,Transmit antenna status
+45,realTime,C2CStatus,2,-,COMMAND_STATUS,Computer Software,3,5,0,Command Control, Command & Control Status
+46,realTime,ICR3VProt,12,V,43,NONE,7,2,3,3V Prot,ICR 3V Proteted
+47,realTime,ICR2dot5V,12,V,43,NONE,7,3,3,2.5V,ICR 2.5V
+48,realTime,ICR2dot5VProt,12,V,43,NONE,7,4,3,2.5V Prot,ICR 2.5V Protected
+49,realTime,rf6,12,-,0,NONE,0,0,0,None,None
+50,realTime,rf7,12,-,0,NONE,0,0,0,None,None
+51,realTime,MuxTest,12,V,43,NONE,7,5,3,Sensor Power,Sensor Power Voltage at the ICR
+52,realTime,LtVGACtl,12,V,42,NONE,1,4,3,VGA Control,Control Voltage to the Variable Gain Amplifier (VGA)
+53,realTime,pad,4,-,34,NONE,0,0,0,None,Unused
+54,realTime,IHUdiagData,32,-,18,NONE,3,2,0,Diagnostic Info,Diagnostic Data on IHU Performance
+55,realTime,pad1,1,-,0,NONE,0,0,0,NONE,Filler
+56,realTime,wodSize,8,000s,36,NONE,3,3,0,WOD Stored,Number of WOD data payloads kept for each of Science and Housekeeping. In hundreds
+57,realTime,swCmds,32,-,35,NONE,7,6,0,Diagnostic,ICR Diagnostic information
+58,realTime,hwCmdCnt,6,-,1,NONE,7,7,0,HW Command Count,Number of hardware commands since last reset
+59,realTime,swCmdCnt,6,-,1,NONE,7,8,0,SW Command Count,Number of software commands since last reset
+60,realTime,pad2,27,-,0,NONE,0,0,0,NONE,Filler
diff --git a/spacecraft/FoxTelem_1.13e/CubeSatSim_maxtelemetry.csv b/spacecraft/FoxTelem_1.13e/CubeSatSim_maxtelemetry.csv
new file mode 100644
index 000000000..c442b89de
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/CubeSatSim_maxtelemetry.csv
@@ -0,0 +1,48 @@
+47,TYPE,FIELD,BITS,UNIT,CONVERSION,MODULE,MODULE_NUM,MODULE_LINE,LINE_TYPE,SHORT_NAME,DESCRIPTION
+0,MAX,Sensor 2,12,integer,1,NONE,6,8,3,Sensor 2,STEM Payload Extra Sensor 2
+1,MAX,Sensor 3,12,integer,1,NONE,6,9,3,Sensor 3,STEM Payload Extra Sensor 3
+2,MAX,BATT_V,12,V,cubesatsim_voltage|FLOAT2,NONE,4,1,3,Battery Voltage,INA219 Battery Voltage
+3,MAX,SatelliteXAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,7,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around X Axis
+4,MAX,SatelliteYAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,8,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Y Axis
+5,MAX,SatelliteZAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,9,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Z Axis
+6,MAX,BATT_I,12,mA,cubesatsim_current,NONE,4,2,3,Battery Current,INA219 Battery Current
+7,MAX,Temperature,12,C,cubesatsim_temperature,NONE,6,2,3,BME280 Temp,STEM Payload Sensor BME280 Temperature
+8,MAX,PANEL_PLUS_X_V,12,V,cubesatsim_voltage|FLOAT2,NONE,7,1,3,Voltage,INA219 +X Panel Voltage
+9,MAX,PANEL_MINUS_X_V,12,V,cubesatsim_voltage|FLOAT2,NONE,10,1,3,Voltage,INA219 -X Panel Voltage
+10,MAX,PANEL_PLUS_Y_V,12,V,cubesatsim_voltage|FLOAT2,NONE,8,1,3,Voltage,INA219 +Y Panel Voltage
+11,MAX,PANEL_MINUS_Y_V,12,V,cubesatsim_voltage|FLOAT2,NONE,11,1,3,Voltage,INA219 -Y Panel Voltage
+12,MAX,PANEL_PLUS_Z_V,12,V,cubesatsim_voltage|FLOAT2,NONE,9,1,3,Voltage,INA219 +Z Panel Voltage
+13,MAX,PANEL_MINUS_Z_V,12,V,cubesatsim_voltage|FLOAT2,NONE,12,1,3,Voltage,INA219 -Z Panel Voltage
+14,MAX,PANEL_PLUS_X_I,12,mA,cubesatsim_current,NONE,7,2,3,Current,INA219 +X Panel Current
+15,MAX,PANEL_MINUS_X_I,12,mA,cubesatsim_current,NONE,10,2,3,Current,INA219 -X Panel Current
+16,MAX,PANEL_PLUS_Y_I,12,mA,cubesatsim_current,NONE,8,2,3,Current,INA219 +Y Panel Current
+17,MAX,PANEL_MINUS_Y_I,12,mA,cubesatsim_current,NONE,11,2,3,Current,INA219 -Y Panel Current
+18,MAX,PANEL_PLUS_Z_I,12,mA,cubesatsim_current,NONE,9,2,3,Current,INA219 +Z Panel Current
+19,MAX,PANEL_MINUS_Z_I,12,mA,cubesatsim_current,NONE,12,2,3,Current,INA219 -Z Panel Current
+20,MAX,BATT2_V,12,V,cubesatsim_voltage|FLOAT2,NONE,5,1,3,Battery 2 Voltage,INA219 Battery 2 Voltage
+21,MAX,SPIN,12,rpm,cubesatsim_rpm,NONE,3,1,3,Spacecraft Spin,Calculated spin rate using solar cells
+22,MAX,Pressure,12,hPa,cubesatsim_pressure,NONE,6,3,3,BME280 Pressure,STEM Payload Sensor BME280 Pressure
+23,MAX,Altitude,12,m,cubesatsim_altitude,NONE,6,4,3,BME280 Altitude,STEM Payload Sensor BME280 Altitude
+24,MAX,Resets,12,-,12,NONE,3,2,3,Reset Count, Software Reset Count
+25,MAX,RSSI,12,dBm,cubesatsim_rssi|INT,NONE,1,1,3,RSSI,Received Signal Strength Indication
+26,MAX,IHUTemperature,12,C,cubesatsim_temperature,NONE,2,1,3,IHU Temp (Pi),Internal Temperature of Pi IHU
+27,MAX,SatelliteXAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,7,3,3,Rotation,STEM Payload Board MPU6050 Angular Veolcity around X Axis
+28,MAX,SatelliteYAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,8,3,3,Rotation,STEM Payload Board MPU6050 Angular Veolcity around Y Axis
+29,MAX,SatelliteZAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,9,3,3,Rotation,STEM Payload Board MPU6050 Angular Veolcity around Z Axis
+30,MAX,Humidity,12,%,cubesatsim_temperature,NONE,6,5,3,BME280 Humidity,STEM Payload Sensor BME280 Humidity
+31,MAX,BATT2_I,12,mA,cubesatsim_current,NONE,5,2,3,Battery 2 Current,INA219 Battery 2 Current
+32,MAX,DiodeTemp,12,C,cubesatsim_rpm,NONE,6,6,3,Diode Temp,STEM Payload Diode Temperature
+33,MAX,Sensor 1,12,integer,1,NONE,6,7,3,Sensor 1,STEM Payload Extra Sensor 1
+34,MAX,STEMPayloadStatus,1,-,17,NONE,6,1,0,STEM Payload Status,STEM Payload Board Status
+35,MAX,SafeMode,1,-,STATUS_ON_OFF,NONE,3,2,0,Safe Mode, Safe Mode (Low Battery Voltage)
+36,MAX,SimulatedTelemetry,1,-,STATUS_ON_OFF,NONE,3,4,0,Simulated Telemetry, Simulated Telemetry Indicator
+37,MAX,PayloadStatus1,1,-,17,NONE,0,0,0,Exp 3,STEM Payload status 1 failure indicator
+38,MAX,I2CBus0Failure,1,-,17,NONE,2,2,0,I2C Bus 0,I2C bus 0 failure indicator
+39,MAX,I2CBus1Failure,1,-,17,NONE,2,2,0,I2C Bus 1,I2C bus 1 failure indicator
+40,MAX,I2CBus3Failure,1,-,17,NONE,2,3,0,I2C Bus 3,I2C bus 3 failure indicator
+41,MAX,CameraFailure,1,-,17,NONE,2,4,0,Camera,Camera failure indicator
+42,MAX,GroundCommands,4,-,1,NONE,3,3,0,Ground Commands,Number of ground commands received
+43,MAX,RXAntenna,1,-,16,NONE,1,3,0,RX Antenna,Receive antenna status
+44,MAX,TXAntenna,1,-,16,NONE,1,2,0,TX Antenna,Transmit antenna status
+45,MAX,C2CStatus,2,-,COMMAND_STATUS,NONE,3,5,0,Command Control, Command & Control Status
+46,MAX,Pad,56,-,0,NONE,0,0,0,NONE,NONE
diff --git a/spacecraft/FoxTelem_1.13e/CubeSatSim_mintelemetry.csv b/spacecraft/FoxTelem_1.13e/CubeSatSim_mintelemetry.csv
new file mode 100644
index 000000000..eefa1e486
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/CubeSatSim_mintelemetry.csv
@@ -0,0 +1,48 @@
+47,TYPE,FIELD,BITS,UNIT,CONVERSION,MODULE,MODULE_NUM,MODULE_LINE,LINE_TYPE,SHORT_NAME,DESCRIPTION
+0,MIN,Sensor 2,12,integer,1,NONE,6,8,3,Sensor 2,STEM Payload Extra Sensor 2
+1,MIN,Sensor 3,12,integer,1,NONE,6,9,3,Sensor 3,STEM Payload Extra Sensor 3
+2,MIN,BATT_V,12,V,cubesatsim_voltage|FLOAT2,NONE,4,1,3,Battery Voltage,INA219 Battery Voltage
+3,MIN,SatelliteXAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,7,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around X Axis
+4,MIN,SatelliteYAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,8,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Y Axis
+5,MIN,SatelliteZAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,9,4,3,Acceleration,STEM Payload Board MPU6050 Acceleration around Z Axis
+6,MIN,BATT_I,12,mA,cubesatsim_current,NONE,4,2,3,Battery Current,INA219 Battery Current
+7,MIN,Temperature,12,C,cubesatsim_temperature,NONE,6,2,3,BME280 Temp,STEM Payload Sensor BME280 Temperature
+8,MIN,PANEL_PLUS_X_V,12,V,cubesatsim_voltage|FLOAT2,NONE,7,1,3,Voltage,INA219 +X Panel Voltage
+9,MIN,PANEL_MINUS_X_V,12,V,cubesatsim_voltage|FLOAT2,NONE,10,1,3,Voltage,INA219 -X Panel Voltage
+10,MIN,PANEL_PLUS_Y_V,12,V,cubesatsim_voltage|FLOAT2,NONE,8,1,3,Voltage,INA219 +Y Panel Voltage
+11,MIN,PANEL_MINUS_Y_V,12,V,cubesatsim_voltage|FLOAT2,NONE,11,1,3,Voltage,INA219 -Y Panel Voltage
+12,MIN,PANEL_PLUS_Z_V,12,V,cubesatsim_voltage|FLOAT2,NONE,9,1,3,Voltage,INA219 +Z Panel Voltage
+13,MIN,PANEL_MINUS_Z_V,12,V,cubesatsim_voltage|FLOAT2,NONE,12,1,3,Voltage,INA219 -Z Panel Voltage
+14,MIN,PANEL_PLUS_X_I,12,mA,cubesatsim_current,NONE,7,2,3,Current,INA219 +X Panel Current
+15,MIN,PANEL_MINUS_X_I,12,mA,cubesatsim_current,NONE,10,2,3,Current,INA219 -X Panel Current
+16,MIN,PANEL_PLUS_Y_I,12,mA,cubesatsim_current,NONE,8,2,3,Current,INA219 +Y Panel Current
+17,MIN,PANEL_MINUS_Y_I,12,mA,cubesatsim_current,NONE,11,2,3,Current,INA219 -Y Panel Current
+18,MIN,PANEL_PLUS_Z_I,12,mA,cubesatsim_current,NONE,9,2,3,Current,INA219 +Z Panel Current
+19,MIN,PANEL_MINUS_Z_I,12,mA,cubesatsim_current,NONE,12,2,3,Current,INA219 -Z Panel Current
+20,MIN,BATT2_V,12,V,cubesatsim_voltage|FLOAT2,NONE,5,1,3,Battery 2 Voltage,INA219 Battery 2 Voltage
+21,MIN,SPIN,12,rpm,cubesatsim_rpm,NONE,3,1,3,Spacecraft Spin,Calculated spin rate using solar cells
+22,MIN,Pressure,12,hPa,cubesatsim_pressure,NONE,6,3,3,BME280 Pressure,STEM Payload Sensor BME280 Pressure
+23,MIN,Altitude,12,m,cubesatsim_altitude,NONE,6,4,3,BME280 Altitude,STEM Payload Sensor BME280 Altitude
+24,MIN,Resets,12,-,12,NONE,3,2,3,Reset Count, Software Reset Count
+25,MIN,RSSI,12,dBm,cubesatsim_rssi|INT,NONE,1,1,3,RSSI,Received Signal Strength Indication
+26,MIN,IHUTemperature,12,C,cubesatsim_temperature,NONE,2,1,3,IHU Temp (Pi),Internal Temperature of Pi IHU
+27,MIN,SatelliteXAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,7,3,3,Rotation,STEM Payload Board MPU6050 Angular Veolcity around X Axis
+28,MIN,SatelliteYAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,8,3,3,Rotation,STEM Payload Board MPU6050 Angular Veolcity around Y Axis
+29,MIN,SatelliteZAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,9,3,3,Rotation,STEM Payload Board MPU6050 Angular Veolcity around Z Axis
+30,MIN,Humidity,12,%,cubesatsim_temperature,NONE,6,5,3,BME280 Humidity,STEM Payload Sensor BME280 Humidity
+31,MIN,BATT2_I,12,mA,cubesatsim_current,NONE,5,2,3,Battery 2 Current,INA219 Battery 2 Current
+32,MIN,DiodeTemp,12,C,cubesatsim_rpm,NONE,6,6,3,Diode Temp,STEM Payload Diode Temperature
+33,MIN,Sensor 1,12,integer,1,NONE,6,7,3,Sensor 1,STEM Payload Extra Sensor 1
+34,MIN,STEMPayloadStatus,1,-,17,NONE,6,1,0,STEM Payload Status,STEM Payload Board Status
+35,MIN,SafeMode,1,-,STATUS_ON_OFF,NONE,3,2,0,Safe Mode, Safe Mode (Low Battery Voltage)
+36,MIN,SimulatedTelemetry,1,-,STATUS_ON_OFF,NONE,3,4,0,Simulated Telemetry, Simulated Telemetry Indicator
+37,MIN,PayloadStatus1,1,-,17,NONE,0,0,0,Exp 3,STEM Payload status 1 failure indicator
+38,MIN,I2CBus0Failure,1,-,17,NONE,2,2,0,I2C Bus 0,I2C bus 0 failure indicator
+39,MIN,I2CBus1Failure,1,-,17,NONE,2,2,0,I2C Bus 1,I2C bus 1 failure indicator
+40,MIN,I2CBus3Failure,1,-,17,NONE,2,3,0,I2C Bus 3,I2C bus 3 failure indicator
+41,MIN,CameraFailure,1,-,17,NONE,2,4,0,Camera,Camera failure indicator
+42,MIN,GroundCommands,4,-,1,NONE,3,3,0,Ground Commands,Number of ground commands received
+43,MIN,RXAntenna,1,-,16,NONE,1,3,0,RX Antenna,Receive antenna status
+44,MIN,TXAntenna,1,-,16,NONE,1,2,0,TX Antenna,Transmit antenna status
+45,MIN,C2CStatus,2,-,COMMAND_STATUS,NONE,3,5,0,Command Control, Command & Control Status
+46,MIN,Pad,56,-,0,NONE,0,0,0,NONE,NONE
diff --git a/spacecraft/FoxTelem_1.13e/CubeSatSim_rttelemetry.csv b/spacecraft/FoxTelem_1.13e/CubeSatSim_rttelemetry.csv
index 10175581f..e69de29bb 100644
--- a/spacecraft/FoxTelem_1.13e/CubeSatSim_rttelemetry.csv
+++ b/spacecraft/FoxTelem_1.13e/CubeSatSim_rttelemetry.csv
@@ -1,47 +0,0 @@
-46,TYPE,FIELD,BITS,UNIT,CONVERSION,MODULE,MODULE_NUM,MODULE_LINE,LINE_TYPE,SHOMIN_NAME,DESCRIPTION
-0,MIN,SENSOR2,12,V,cubesatsim_voltage|FLOAT2,NONE,0,0,3,Sensor2,STEM Payload Extra Sensor2
-1,MIN,SENSOR3,12,V,cubesatsim_voltage|FLOAT2,NONE,0,0,3,Sensor3,STEM Payload Extra Sensor3
-2,MIN,BATT_V,12,V,cubesatsim_voltage|FLOAT2,NONE,4,1,3,Battery Voltage,Battery Voltage
-3,MIN,SatelliteXAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,7,4,3,Acceleration,Acceleration around X Axis
-4,MIN,SatelliteYAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,8,4,3,Acceleration,Acceleration around Y Axis
-5,MIN,SatelliteZAxisAcceleration,12,g,cubesatsim_acceleration|FLOAT2,NONE,9,4,3,Acceleration,Acceleration around Z Axis
-6,MIN,BATT_I,12,mA,cubesatsim_current,NONE,4,2,3,Battery Current,Battery current
-7,MIN,Temperature,12,C,cubesatsim_temperature,NONE,6,2,3,Temperature,STEM Payload Sensor Temperature
-8,MIN,PANEL_PLUS_X_V,12,V,cubesatsim_voltage|FLOAT2,NONE,7,1,3,Voltage,+X Panel
-9,MIN,PANEL_MINUS_X_V,12,V,cubesatsim_voltage|FLOAT2,NONE,10,1,3,Voltage,-X Panel
-10,MIN,PANEL_PLUS_Y_V,12,V,cubesatsim_voltage|FLOAT2,NONE,8,1,3,Voltage,+Y Panel
-11,MIN,PANEL_MINUS_Y_V,12,V,cubesatsim_voltage|FLOAT2,NONE,11,1,3,Voltage,-Y Panel
-12,MIN,PANEL_PLUS_Z_V,12,V,cubesatsim_voltage|FLOAT2,NONE,9,1,3,Voltage,+Z Panel
-13,MIN,PANEL_MINUS_Z_V,12,V,cubesatsim_voltage|FLOAT2,NONE,12,1,3,Voltage,-Z Panel
-14,MIN,PANEL_PLUS_X_I,12,mA,cubesatsim_current,NONE,7,2,3,Current,+X Panel
-15,MIN,PANEL_MINUS_X_I,12,mA,cubesatsim_current,NONE,10,2,3,Current,-X Panel
-16,MIN,PANEL_PLUS_Y_I,12,mA,cubesatsim_current,NONE,8,2,3,Current,+Y Panel
-17,MIN,PANEL_MINUS_Y_I,12,mA,cubesatsim_current,NONE,11,2,3,Current,-Y Panel
-18,MIN,PANEL_PLUS_Z_I,12,mA,cubesatsim_current,NONE,9,2,3,Current,+Z Panel
-19,MIN,PANEL_MINUS_Z_I,12,mA,cubesatsim_current,NONE,12,2,3,Current,-Z Panel
-20,MIN,BATT2_V,12,V,cubesatsim_voltage|FLOAT2,NONE,5,1,3,Battery2 Voltage,Battery2 Voltage
-21,MIN,SPIN,12,rpm,cubesatsim_rpm,NONE,3,1,3,Spacecraft Spin,Calculated spin rate using solar cells
-22,MIN,Pressure,12,bar,cubesatsim_pressure,NONE,6,3,3,Pressure,STEM Payload Sensor Pressure
-23,MIN,Altitude,12,m,cubesatsim_altitude,NONE,6,4,3,Altitude,STEM Payload Sensor Altitude
-24,MIN,Resets,12,-,12,NONE,3,2,3,Reset Count, Software Reset Count
-25,MIN,RSSI,12,dBm,cubesatsim_rssi|INT,NONE,1,1,3,RSSI,Received Signal Strength Indication
-26,MIN,IHUTemperature,12,C,cubesatsim_temperature,NONE,2,1,3,Temperature,Internal Temperature of IHU
-27,MIN,SatelliteXAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,7,3,3,Rotation,Angular Veolcity around X Axis
-28,MIN,SatelliteYAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,8,3,3,Rotation,Angular Veolcity around Y Axis
-29,MIN,SatelliteZAxisAngularVelocity,12,dps,cubesatsim_rotation|INT,NONE,9,3,3,Rotation,Angular Veolcity around Z Axis
-30,MIN,Humidity,12,%,cubesatsim_temperature,NONE,6,5,3,Humidity,STEM Payload Sensor Humidity
-31,MIN,BATT2_I,12,mA,cubesatsim_current,NONE,5,2,3,Battery2 Current,Power Supply DC Current
-32,MIN,DIODE_T,12,signed raw,cubesatsim_rpm,NONE,6,6,3,Diode Temperature,Diode Temperature
-33,MIN,Sensor1,12,signed scaled,cubesatsim_rpm,NONE,6,7,3,Sensor 1,STEM Payload Extra Sensor 1
-34,MIN,STEMPayloadStatus,1,-,17,NONE,6,1,0,STEM Payload Status,STEM Payload Board Status
-35,MIN,Nominal Mode,1,-,17,NONE,3,2,0,Nominal Mode, Nominal Mode (Not Safe Mode)
-36,MIN,PayloadStatus1,1,-,17,NONE,6,7,0,Exp 2,STEM Payload status 1 failure indicator
-37,MIN,PayloadStatus2,1,-,17,NONE,6,8,0,Exp 3,STEM Payload status 2 failure indicator
-38,MIN,I2CBus0Failure,1,-,17,NONE,2,2,0,I2C Bus 0,I2C bus 0 failure indicator
-39,MIN,I2CBus1Failure,1,-,17,NONE,2,3,0,I2C Bus 1,I2C bus 1 failure indicator
-40,MIN,I2CBus3Failure,1,-,17,NONE,2,4,0,I2C Bus 3,I2C bus 3 failure indicator
-41,MIN,CameraFailure,1,-,17,NONE,2,5,0,Camera,Camera failure indicator
-42,MIN,GroundCommands,4,-,1,NONE,3,3,0,Ground Commands,Number of ground commands received
-43,MIN,RXAntenna,1,-,16,NONE,1,3,0,RX Antenna,Receive antenna status
-44,MIN,TXAntenna,1,-,16,NONE,1,2,0,TX Antenna,Transmit antenna status
-45,MIN,Pad,58,-,0,NONE,0,0,0,NONE,NONE
diff --git a/spacecraft/FoxTelem_1.13e/CubeSat_Simulator_DUV.MASTER b/spacecraft/FoxTelem_1.13e/CubeSat_Simulator_DUV.MASTER
new file mode 100644
index 000000000..05812fc69
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/CubeSat_Simulator_DUV.MASTER
@@ -0,0 +1,59 @@
+#Fox 1 Telemetry Decoder Properties
+#Sat Apr 11 13:20:20 EST 2020
+#File named .dat should be in the logfiles directory and is loaded by FoxTelem
+#File named .MASTER should not be edited and is a backup copy in the installation directory
+foxId=7
+displayName=CubeSatSim-FSK
+name=CubeSatSim
+model=0
+IHU_SN=7
+catalogNumber=0
+description=CubeSatSim, the AMSAT CubeSat Simulator, is a functional satellite model that generates real telemetry from solar panels, batteries, and temperature sensors. Use this for DUV FSK telemetry. For more information see http://cubesatsim.org
+BATTERY_CURRENT_ZERO=-1.839
+EXP1=0
+EXP2=0
+EXP3=0
+EXP4=0
+numberOfLayouts=4
+layout0.filename=FOX1A_debug.csv
+layout0.name=DEBUG
+layout1.filename=CubeSatSim_maxtelemetry.csv
+layout1.name=maxtelemetry
+layout2.filename=CubeSatSim_rttelemetry.csv
+layout2.name=rttelemetry
+layout3.filename=CubeSatSim_mintelemetry.csv
+layout3.name=mintelemetry
+#layout4.filename=FOX1A_radtelemetry.csv
+#layout4.name=radtelemetry
+#layout5.filename=FOX1A_radtelemetry2.csv
+#layout5.name=radtelemetry2
+#layout5.parentLayout=radtelemetry
+lookupTable0.filename=FOX1A_rssiFM.tab
+numberOfLookupTables=3
+lookupTable0=RSSI
+lookupTable1.filename=FOX1A_ihuVBattSN7.tab
+lookupTable1=IHU_VBATT
+lookupTable2.filename=FOX1A_ihutempSN7.tab
+lookupTable2=IHU_TEMP
+numberOfStringLookupTables=2
+stringLookupTable0.filename=status_on_off.tab
+stringLookupTable0=STATUS_ON_OFF
+stringLookupTable1=COMMAND_STATUS
+stringLookupTable1.filename=command_status.tab
+telemetryDownlinkFreqkHz=434900
+maxFreqBoundkHz=434950
+minFreqBoundkHz=434850
+measurementsFileName=measurements.csv
+memsRestValueX=2087
+memsRestValueY=2101
+memsRestValueZ=2045
+passMeasurementsFileName=passmeasurements.csv
+numberOfSources=1
+source0.name=amsat.cubesat_simulator.ihu.duv
+source0.formatName=FSK 200bps (Fox1)
+#source1.name=amsat.cubesat_simulator.ihu.highspeed
+track=false
+useIHUVBatt=true
+user_format=FSK 200bps (Fox1)
+useConversionCoeffs=true
+conversionCurvesFileName=CubeSatSim_conversion_curves.csv
diff --git a/spacecraft/FoxTelem_1.13e/CubeSat_Simulator_PSK.MASTER b/spacecraft/FoxTelem_1.13e/CubeSat_Simulator_PSK.MASTER
new file mode 100644
index 000000000..56c22e88d
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/CubeSat_Simulator_PSK.MASTER
@@ -0,0 +1,77 @@
+#Fox 1 Telemetry Decoder Properties
+#Thu Apr 11 13:23:23 EST 2020
+user_mode=4
+foxId=99
+IHU_SN=7
+catalogNumber=0
+model=0
+mpptResistanceError=6.58
+mpptSensorOffThreshold=1600
+name=CubeSatSim
+displayName=CubeSatSim-BPSK
+BATTERY_CURRENT_ZERO=-1.834
+hasImprovedCommandReceiver=true
+EXP1=0
+EXP2=0
+EXP3=0
+EXP4=0
+description=CubeSatSim, the AMSAT CubeSat Simulator, is a functional satellite model that generates real telemetry from solar panels, batteries, and temperature sensors. Use this for BPSK telemetry. For more information see http://cubesatsim.org
+numberOfFrameLayouts=5
+frameLayout0.filename=FOX1E_Type0_ALL_WOD.frame
+frameLayout0.name=All WOD
+frameLayout1.filename=CubeSatSim_PSK_Type1_HEALTH.frame
+frameLayout1.name=Health
+frameLayout2.filename=CubeSatSim_PSK_Type2_MINMAX.frame
+frameLayout2.name=MinMax
+frameLayout3.filename=FOX1E_Type3_REALTIME_BEACON.frame
+frameLayout3.name=Realtime Beacon
+frameLayout4.filename=FOX1E_Type4_WOD_BEACON.frame
+frameLayout4.name=WOD Beacon
+numberOfLayouts=9
+layout0.filename=FOX1A_debug.csv
+layout0.name=DEBUG
+layout1.filename=CubeSatSim_PSK_maxtelemetry.csv
+layout1.name=maxtelemetry
+layout2.filename=CubeSatSim_PSK_rttelemetry.csv
+layout2.name=rttelemetry
+layout3.filename=CubeSatSim_PSK_mintelemetry.csv
+layout3.name=mintelemetry
+layout4.filename=FOX1E_radtelemetry.csv
+layout4.name=radtelemetry
+layout5.filename=FOX1E_radtelemetry2.csv
+layout5.name=radtelemetry2
+layout5.parentLayout=radtelemetry
+layout6.filename=CubeSatSim_PSK_wodtelemetry.csv
+layout6.name=wodtelemetry
+layout7.filename=FOX1E_wodradtelemetry.csv
+layout7.name=wodradtelemetry
+layout8.filename=FOX1E_wodradtelemetry2.csv
+layout8.name=wodradtelemetry2
+layout8.parentLayout=wodradtelemetry
+numberOfLookupTables=3
+lookupTable0.filename=FOX1A_rssiFM.tab
+lookupTable0=RSSI
+lookupTable1.filename=FOX1E_ihuVBattSNx.tab
+lookupTable1=IHU_VBATT
+lookupTable2.filename=FOX1A_ihutempSN7.tab
+lookupTable2=IHU_TEMP
+numberOfStringLookupTables=2
+stringLookupTable0.filename=status_on_off.tab
+stringLookupTable0=STATUS_ON_OFF
+stringLookupTable1=COMMAND_STATUS
+stringLookupTable1.filename=command_status.tab
+maxFreqBoundkHz=434950
+measurementsFileName=measurements.csv
+memsRestValueX=2129
+memsRestValueY=2131
+memsRestValueZ=2103
+minFreqBoundkHz=434850
+passMeasurementsFileName=passmeasurements.csv
+telemetryDownlinkFreqkHz=434900
+track=true
+useIHUVBatt=false
+numberOfSources=1
+source0.name=amsat.cubesat_simulator.ihu.bpsk
+user_format=0
+useConversionCoeffs=true
+conversionCurvesFileName=CubeSatSim_conversion_curves.csv
diff --git a/spacecraft/FoxTelem_1.13e/README.md b/spacecraft/FoxTelem_1.13e/README.md
new file mode 100644
index 000000000..a7ff0428b
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/README.md
@@ -0,0 +1,3 @@
+These files are for FoxTelem version 1.13e in the spacecraft directory.
+
+You can download this version of FoxTelem here: https://www.g0kla.com/foxtelem/downloads/test/
diff --git a/spacecraft/FoxTelem_1.13e/command_status.tab b/spacecraft/FoxTelem_1.13e/command_status.tab
new file mode 100644
index 000000000..73d91a95a
--- /dev/null
+++ b/spacecraft/FoxTelem_1.13e/command_status.tab
@@ -0,0 +1,3 @@
+0,OFF
+1,Carrier
+2,DTMF/APRS
diff --git a/squelch_cc.py b/squelch_cc.py
new file mode 100644
index 000000000..9faa6ca85
--- /dev/null
+++ b/squelch_cc.py
@@ -0,0 +1,196 @@
+import RPi.GPIO as GPIO
+from RPi.GPIO import output
+from time import sleep
+from os import system
+import sys
+
+def command_control_check():
+
+# global command_control
+# global no_command
+ global debug_mode
+ command_count = 0
+ global squelch
+ global txLed
+
+# output(pd, 1)
+# output(ptt, 1)
+# sleep(1)
+# if (no_command == False and GPIO.input(squelch) == False):
+ if GPIO.input(squelch) == False:
+ print("carrier received!")
+ # command_tx = not command_tx
+# print(command_tx)
+
+ try:
+ file = open("/home/pi/CubeSatSim/command_count.txt", "r")
+ string = file.read()
+ file.close()
+ command_count = int(string)
+ command_count += 1
+ filec = open("/home/pi/CubeSatSim/command_count.txt", "w")
+ command_count_string = str(command_count)
+ print(command_count_string)
+ string = filec.write(command_count_string)
+ filec.close()
+ except:
+ print("Can't write command_count file!")
+ print("Command_count: ")
+ print(command_count)
+
+ increment_mode()
+
+# if (command_tx == True):
+# print("Turning on transmit")
+# system("echo > command_tx True")
+# output(txLed, txLedOn)
+# sleep(0.5)
+# output(txLed, txLedff)
+# else:
+# print("Turning off transmit")
+# system("echo > command_tx False")
+## else:
+## print("No carrier received!")
+# output(pd, 0)
+# sleep(1)
+
+def increment_mode():
+ global debug_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'
+ GPIO.output(powerPin, 0) # blink two times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+
+ elif (mode == 'f'):
+ mode = 'b'
+ GPIO.output(powerPin, 0) # blink three times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+
+ elif (mode == 'b'):
+ mode = 's'
+ GPIO.output(powerPin, 0) # blink four times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+
+ elif (mode == 's'):
+ mode = 'm'
+ GPIO.output(powerPin, 0) # blink five times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1);
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+ else:
+ mode = 'a'
+ GPIO.output(powerPin, 0) # blink one time
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(1)
+
+ try:
+ print("/home/pi/CubeSatSim/config -" + mode)
+ if (debug_mode == False):
+ GPIO.setwarnings(False)
+ GPIO.output(txLed, 0)
+ GPIO.output(powerPin, 0)
+ system("sudo systemctl stop rpitx")
+ system("sudo systemctl stop cubesatsim")
+
+ system("/home/pi/CubeSatSim/config -" + mode)
+ print("Changing mode now")
+
+
+# file = open("/home/pi/CubeSatSim/.mode", "w")
+# count_string = str(command_count)
+# file.write(mode)
+# file.close()
+# print(".mode file written")
+# print("sudo reboot -h now")
+# GPIO.setwarnings(False)
+# GPIO.setup(powerPin, GPIO.OUT)
+# GPIO.output(powerPin, 0);
+# system("reboot -h now")
+# release = True;
+# system("/home/pi/CubeSatSim/config -" + mode)
+# system("reboot -h now")
+ print(" ")
+# sleep(10);
+ except:
+ print("can't change mode")
+
+print("Squelch Command and Control active")
+debug_mode = False
+if (len(sys.argv)) > 1:
+# print("There are arguments!")
+ if ('d' == sys.argv[1]):
+ debug_mode = True
+ print("Debug mode - mode changes not made")
+
+GPIO.setmode(GPIO.BCM)
+GPIO.setwarnings(False)
+squelch = 6
+powerPin = 16
+txLed = 27
+GPIO.setup(squelch, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## pull up in case pin is not connected
+GPIO.setup(powerPin, GPIO.OUT)
+GPIO.setup(txLed, GPIO.OUT)
+
+while True:
+ command_control_check()
+ sleep(0.5)
diff --git a/stempayload/Payload_BME280_MPU6050_AIO/Payload_BME280_MPU6050_AIO.ino b/stempayload/Payload_BME280_MPU6050_AIO/Payload_BME280_MPU6050_AIO.ino
new file mode 100644
index 000000000..a1022069e
--- /dev/null
+++ b/stempayload/Payload_BME280_MPU6050_AIO/Payload_BME280_MPU6050_AIO.ino
@@ -0,0 +1,683 @@
+// code for Pico or Pro Micro or STM32 on the CubeSat Simulator STEM Payload board
+// works wih CubeSatSim software v1.3.2 or later
+// extra sensors can be added in payload_extension.cpp file
+
+#include
+#include
+#include
+#include
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040)
+#include
+#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Arduino Mbed OS RP2040 Boards is used in Arduino IDE
+#include
+TinyGPSPlus gps;
+UART Serial2(8, 9, 0, 0);
+
+#elif !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards in Arduino IDE
+#include
+TinyGPSPlus gps;
+bool check_for_wifi();
+bool wifi = false;
+int led_builtin_pin;
+float tlm[20];
+
+#else // if Sparkfun Pro Micro or STM32
+#include
+#endif
+
+#define SEALEVELPRESSURE_HPA (1013.25)
+
+Adafruit_BME280 bme;
+MPU6050 mpu6050(Wire);
+
+long timer = 0;
+int bmePresent;
+int RXLED = 17; // The RX LED has a defined Arduino pin
+int greenLED = 9;
+int blueLED = 8;
+int Sensor1 = 0;
+float Sensor2 = 0;
+float temp;
+int calibration = 0;
+
+void ee_prom_word_write(int addr, int val);
+short ee_prom_word_read(int addr);
+int first_time = true;
+int first_read = true;
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+float T2 = 24; // Temperature data point 1
+float R2 = 169; // Reading data point 1
+float T1 = 6; // Temperature data point 2
+float R1 = 181; // Reading data point 2
+#endif
+#if defined __AVR_ATmega32U4__
+float T2 = 26.3; // Temperature data point 1
+float R2 = 167; // Reading data point 1
+float T1 = 2; // Temperature data point 2
+float R1 = 179; // Reading data point 2
+#endif
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+float T2 = 25; // Temperature data point 1
+float R2 = 671; // Reading data point 1
+float T1 = 15.5; // Temperature data point 2
+float R1 = 695; // Reading data point 2
+#endif
+
+int sensorValue;
+float Temp;
+float rest;
+
+char sensor_end_flag[] = "_END_FLAG_";
+char sensor_start_flag[] = "_START_FLAG_";
+bool show_gps = true; // set to false to not see all messages
+float flon = 0.0, flat = 0.0, flalt = 0.0;
+void get_gps();
+
+extern void payload_setup(); // sensor extension setup function defined in payload_extension.cpp
+extern void payload_loop(); // sensor extension read function defined in payload_extension.cpp
+
+extern void aio_setup(); // Adafruit IO setup code defined in adafruitio_00_publish.cpp
+extern void aio_loop(float telem[]); // Adafruit IO loop code defined in adafruitio_00_publish.cpp
+
+void setup() {
+
+ Serial.begin(115200); // Serial Monitor for testing
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ Serial1.setRX(1);
+ delay(100);
+ Serial1.setTX(0);
+ delay(100);
+#endif
+
+ Serial1.begin(115200); // for communication with Pi Zero
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards in Arduino IDE
+ EEPROM.begin(512);
+#endif
+
+ delay(2000);
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) && (ARDUINO_ARCH_RP2040)
+ Serial.println("Pico with Mbed");
+#elif !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ Serial.println("Pico with RP2040");
+#elif defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ Serial.println("STM32");
+#elif defined __AVR_ATmega32U4__
+ Serial.println("Pro Micro");
+#else
+ Serial.println("Unknown board");
+#endif
+
+ Serial.println("Starting!");
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ Serial.println("Starting Serial2 for optional GPS on JP12");
+// Serial2.begin(9600); // serial from - some modules need 115200
+ Serial2.begin(9600); // serial from GPS or other serial sensor. Some GPS need 115200
+
+ // set all Pico GPIO connected pins to input
+ for (int i = 10; i < 22; i++) {
+ pinMode(i, INPUT);
+ }
+ pinMode(26, INPUT);
+ pinMode(27, INPUT);
+ pinMode(28, INPUT);
+ pinMode(15, INPUT_PULLUP); // squelch
+#endif
+
+ blink_setup();
+
+ blink(500);
+ delay(250);
+ blink(500);
+ delay(250);
+ led_set(greenLED, HIGH);
+ delay(250);
+ led_set(greenLED, LOW);
+ led_set(blueLED, HIGH);
+ delay(250);
+ led_set(blueLED, LOW);
+
+ if (bme.begin(0x76)) {
+ bmePresent = 1;
+ } else {
+ Serial.println("Could not find a valid BME280 sensor, check wiring!");
+ bmePresent = 0;
+ }
+
+ mpu6050.begin();
+
+ if (eeprom_word_read(0) == 0xA07)
+ {
+ Serial.println("Reading gyro offsets from EEPROM\n");
+
+ float xOffset = ((float)eeprom_word_read(1)) / 100.0;
+ float yOffset = ((float)eeprom_word_read(2)) / 100.0;
+ float zOffset = ((float)eeprom_word_read(3)) / 100.0;
+
+ Serial.println(xOffset, DEC);
+ Serial.println(yOffset, DEC);
+ Serial.println(zOffset, DEC);
+
+ mpu6050.setGyroOffsets(xOffset, yOffset, zOffset);
+
+ Serial.println("\nTemperature calibration data from EEPROM\n");
+
+ T1 = ((float)eeprom_word_read(4)) / 10.0;
+ R1 = ((float)eeprom_word_read(5));
+ T2 = ((float)eeprom_word_read(6)) / 10.0;
+ R2 = ((float)eeprom_word_read(7));
+
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+ Serial.println(" ");
+
+ }
+ else
+ {
+ Serial.println("Calculating gyro offsets\n");
+ mpu6050.calcGyroOffsets(true);
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ Serial.println("Storing gyro offsets in EEPROM\n");
+
+ eeprom_word_write(0, 0xA07);
+ eeprom_word_write(1, (int)(mpu6050.getGyroXoffset() * 100.0) + 0.5);
+ eeprom_word_write(2, (int)(mpu6050.getGyroYoffset() * 100.0) + 0.5);
+ eeprom_word_write(3, (int)(mpu6050.getGyroZoffset() * 100.0) + 0.5);
+
+ Serial.println(eeprom_word_read(0), HEX);
+ Serial.println(((float)eeprom_word_read(1)) / 100.0, DEC);
+ Serial.println(((float)eeprom_word_read(2)) / 100.0, DEC);
+ Serial.println(((float)eeprom_word_read(3)) / 100.0, DEC);
+
+ Serial.println("\nStoring temperature calibration data in EEPROM\n");
+
+ eeprom_word_write(4, (int)(T1 * 10.0) + 0.5);
+ eeprom_word_write(5, (int) R1);
+ eeprom_word_write(6, (int)(T2 * 10.0) + 0.5);
+ eeprom_word_write(7, (int) R2);
+
+ T1 = ((float)eeprom_word_read(4)) / 10.0;
+ R1 = ((float)eeprom_word_read(5));
+ T2 = ((float)eeprom_word_read(6)) / 10.0;
+ R2 = ((float)eeprom_word_read(7));
+
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+ Serial.println(" ");
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
+ }
+#endif
+#endif
+ }
+ payload_setup(); // sensor extension setup function defined in payload_extension.cpp
+ aio_setup(); // Adafruit IO setup code defined in adafruitio_00_publish.cpp
+
+ for (int i = 0; i++; i < 20)
+ tlm[i] = 0.0;
+// tlm[0] = 23.1; // uncomment for non-zero test values if no BME or MPU sensor is attached.
+// tlm[1] = 1000.2;
+// tlm[2] = 122;
+// tlm[3] = 56.8;
+}
+
+void loop() {
+
+ blink(50);
+
+ if (Serial1.available() > 0) {
+ Serial.print("Received serial data!!!\n");
+ delay(10);
+ while (Serial1.available() > 0) {
+ char result = Serial1.read();
+ Serial.print(result);
+ }
+ Serial.println(" ");
+ }
+ {
+// if (result == '?')
+ {
+ if (bmePresent) {
+
+ tlm[0] = bme.readTemperature();
+ tlm[1] = bme.readPressure() / 100.0F;
+ tlm[2] = bme.readAltitude(SEALEVELPRESSURE_HPA);
+ tlm[3] = bme.readHumidity();
+
+ Serial1.print(sensor_start_flag);
+ Serial1.print("OK BME280 ");
+ Serial1.print(tlm[0]);
+ Serial1.print(" ");
+ Serial1.print(tlm[1]);
+ Serial1.print(" ");
+ Serial1.print(tlm[2]);
+ Serial1.print(" ");
+ Serial1.print(tlm[3]);
+
+ Serial.print("OK BME280 ");
+ Serial.print(tlm[0]);
+ Serial.print(" ");
+ Serial.print(tlm[1]);
+ Serial.print(" ");
+ Serial.print(tlm[2]);
+ Serial.print(" ");
+ Serial.print(tlm[3]);
+ } else
+ {
+ Serial1.print(sensor_start_flag);
+ Serial1.print("OK BME280 0.0 0.0 0.0 0.0");
+
+ Serial.print("OK BME280 0.0 0.0 0.0 0.0");
+ }
+ mpu6050.update();
+
+ tlm[4] = mpu6050.getGyroX();
+ tlm[5] = mpu6050.getGyroY();
+ tlm[6] = mpu6050.getGyroZ();
+ tlm[7] = mpu6050.getAccX();
+ tlm[8] = mpu6050.getAccY();
+ tlm[9] = mpu6050.getAccZ();
+
+ Serial1.print(" MPU6050 ");
+ Serial1.print(tlm[4]);
+ Serial1.print(" ");
+ Serial1.print(tlm[5]);
+ Serial1.print(" ");
+ Serial1.print(tlm[6]);
+
+ Serial1.print(" ");
+ Serial1.print(tlm[7]);
+ Serial1.print(" ");
+ Serial1.print(tlm[8]);
+ Serial1.print(" ");
+ Serial1.print(tlm[9]);
+
+ Serial.print(" MPU6050 ");
+ Serial.print(tlm[4]);
+ Serial.print(" ");
+ Serial.print(tlm[5]);
+ Serial.print(" ");
+ Serial.print(tlm[6]);
+
+ Serial.print(" ");
+ Serial.print(tlm[7]);
+ Serial.print(" ");
+ Serial.print(tlm[8]);
+ Serial.print(" ");
+ Serial.print(tlm[9]);
+
+ sensorValue = read_analog();
+
+// Serial.println(sensorValue);
+ Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1));
+
+// Serial1.print(" GPS 0 0 0 TMP ");
+
+ Serial1.print(" GPS ");
+ Serial1.print(flat,4);
+ Serial1.print(" ");
+ Serial1.print(flon,4);
+ Serial1.print(" ");
+ Serial1.print(flalt,2);
+
+ Serial1.print(" TMP ");
+ Serial1.print(Temp);
+
+// Serial1.print(" ");
+// Serial1.println(Sensor2);
+
+ Serial.print(" GPS ");
+ Serial.print(flat,4);
+ Serial.print(" ");
+ Serial.print(flon,4);
+ Serial.print(" ");
+ Serial.print(flalt,2);
+
+// Serial.print(" GPS 0 0 0 TMP ");
+ Serial.print(" TMP ");
+ Serial.print(Temp);
+// Serial.print(" ");
+// Serial.println(Sensor2);
+
+ float rotation = sqrt(tlm[4]*tlm[4] + tlm[5]*tlm[5] + tlm[6]*tlm[6]);
+ float acceleration = sqrt(tlm[7]*tlm[7] + tlm[8]*tlm[8] + tlm[9]*tlm[9]);
+// Serial.print(rotation);
+// Serial.print(" ");
+// Serial.println(acceleration);
+
+ if (first_read == true) {
+ first_read = false;
+ rest = acceleration;
+ }
+
+ if (acceleration > 1.2 * rest)
+ led_set(greenLED, HIGH);
+ else
+ led_set(greenLED, LOW);
+
+ if (rotation > 5)
+ led_set(blueLED, HIGH);
+ else
+ led_set(blueLED, LOW);
+ }
+
+ payload_loop(); // sensor extension read function defined in payload_extension.cpp
+ aio_loop(tlm); // Adafruit IO loop code defined in adafruitio_00_publish.cpp
+
+// Serial1.println(" ");
+ Serial1.println(sensor_end_flag);
+ Serial.println(" ");
+
+ }
+
+ if (Serial.available() > 0) {
+ blink(50);
+ char result = Serial.read();
+// Serial.println(result);
+// Serial.println("OK");
+// Serial.println(counter++);
+//#if !defined (ARDUINO_ARCH_RP2040)
+ if (result == 'R' || result == 'r') {
+// Serial1.println("OK");
+// delay(100);
+ Serial.println("Resetting\n");
+ first_read = true;
+ setup();
+ }
+ else if (result == 'D' || result == 'd') {
+ Serial.println("\nCurrent temperature calibration data\n");
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+
+ Serial.println("\nCurrent raw temperature reading\n");
+ Serial.println(sensorValue, DEC);
+ Serial.println(" ");
+ }
+ else if (result == 'C' || result == 'c') {
+ Serial.println("\nClearing stored gyro offsets in EEPROM\n");
+ eeprom_word_write(0, 0x00);
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
+ }
+#endif
+ first_time = true;
+ setup();
+ }
+ else if (result == 'S' || result == 's') {
+ Serial.print("\nStoring temperature calibration data point "); // in EEPROM\n");
+ Serial.print(calibration + 1);
+ Serial.print(" in EEPROM\n");
+
+ Serial.println(temp);
+ Serial.println(sensorValue);
+ Serial.println(" ");
+
+ eeprom_word_write(calibration * 2 + 4 , (int)(temp * 10.0) + 0.5);
+ eeprom_word_write(calibration * 2 + 5, sensorValue);
+
+ if (calibration == 0) {
+ T1 = temp;
+ R1 = sensorValue;
+ calibration = 1;
+ } else {
+ T2 = temp;
+ R2 = sensorValue;
+ calibration = 0;
+ }
+
+// calibration = (calibration + 1) % 2;
+// Serial.println(calibration + 1);
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
+ }
+#endif
+
+ }
+//#endif
+ }
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ Serial.print("Squelch: ");
+ Serial.println(digitalRead(15));
+
+ get_gps();
+#else
+ delay(1000); // not needed due to gps 1 second polling delay
+
+#endif
+}
+
+void eeprom_word_write(int addr, int val)
+{
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ EEPROM.write(addr * 2, lowByte(val));
+ EEPROM.write(addr * 2 + 1, highByte(val));
+#endif
+}
+
+short eeprom_word_read(int addr)
+{
+ int result = 0;
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ result = ((EEPROM.read(addr * 2 + 1) << 8) | EEPROM.read(addr * 2));
+#endif
+ return result;
+}
+
+void blink_setup()
+{
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ // initialize digital pin PB1 as an output.
+ pinMode(PC13, OUTPUT);
+ pinMode(PB9, OUTPUT);
+ pinMode(PB8, OUTPUT);
+#endif
+
+#if defined __AVR_ATmega32U4__
+ pinMode(RXLED, OUTPUT); // Set RX LED as an output
+ // TX LED is set as an output behind the scenes
+ pinMode(greenLED, OUTPUT);
+ pinMode(blueLED,OUTPUT);
+#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ pinMode(LED_BUILTIN, OUTPUT);
+ pinMode(18, OUTPUT); // blue LED on STEM Payload Board v1.3.2
+ pinMode(19, OUTPUT); // green LED on STEM Payload Board v1.3.2
+#endif
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (check_for_wifi()) {
+ wifi = true;
+ led_builtin_pin = LED_BUILTIN; // use default GPIO for Pico W
+ pinMode(LED_BUILTIN, OUTPUT);
+// configure_wifi();
+ } else {
+ led_builtin_pin = 25; // manually set GPIO 25 for Pico board
+// pinMode(25, OUTPUT);
+ pinMode(led_builtin_pin, OUTPUT);
+ }
+ pinMode(18, OUTPUT);
+ pinMode(19, OUTPUT);
+#endif
+}
+
+void blink(int length)
+{
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ digitalWrite(PC13, LOW); // turn the LED on (HIGH is the voltage level)
+#endif
+
+#if defined __AVR_ATmega32U4__
+ digitalWrite(RXLED, LOW); // set the RX LED ON
+ TXLED0; //TX LED is not tied to a normally controlled pin so a macro is needed, turn LED OFF
+#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+#endif
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (wifi)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON
+#endif
+
+delay(length);
+
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ digitalWrite(PC13, HIGH); // turn the LED off by making the voltage LOW
+#endif
+
+#if defined __AVR_ATmega32U4__
+ digitalWrite(RXLED, HIGH); // set the RX LED OFF
+ TXLED0; //TX LED macro to turn LED ON
+#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF
+#endif
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (wifi)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, LOW); // set the built-in LED ON
+#endif
+}
+
+void led_set(int ledPin, bool state)
+{
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ if (ledPin == greenLED)
+ digitalWrite(PB9, state);
+ else if (ledPin == blueLED)
+ digitalWrite(PB8, state);
+#endif
+
+#if defined __AVR_ATmega32U4__
+ digitalWrite(ledPin, state);
+#endif
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ if (ledPin == greenLED)
+ digitalWrite(19, state);
+ else if (ledPin == blueLED)
+ digitalWrite(18, state);
+#endif
+}
+
+int read_analog()
+{
+ int sensorValue;
+ #if defined __AVR_ATmega32U4__
+ sensorValue = analogRead(A3);
+#endif
+
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ sensorValue = analogRead(PA7);
+#endif
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ sensorValue = analogRead(28);
+#endif
+ return(sensorValue);
+}
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+bool check_for_wifi() {
+
+ pinMode(29, INPUT);
+ const float conversion_factor = 3.3f / (1 << 12);
+ uint16_t result = analogRead(29);
+// Serial.printf("ADC3 value: 0x%03x, voltage: %f V\n", result, result * conversion_factor);
+
+ if (result < 0x10) {
+ Serial.println("\nPico W detected!\n");
+ return(true);
+ }
+ else {
+ Serial.println("\nPico detected!\n");
+ return(false);
+ }
+}
+#endif
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+void get_gps() {
+// Serial.println("Getting GPS data");
+ bool newData = false;
+ unsigned long start = millis();
+
+// for (unsigned long start = millis(); millis() - start < 1000;) // 5000;)
+ while ((millis() - start) < 1000) // 5000;)
+ {
+ while (Serial2.available())
+ {
+ char c = Serial2.read();
+ if (show_gps)
+ Serial.write(c); // uncomment this line if you want to see the GPS data flowing
+ if (gps.encode(c)) // Did a new valid sentence come in?
+ newData = true;
+ }
+ }
+ if (newData) {
+ Serial.print("GPS read new data in ms: ");
+ Serial.println(millis() - start);
+
+// float flon = 0.0, flat = 0.0, flalt = 0.0;
+// unsigned long age;
+// starting = millis();
+// gps.f_get_position(&flat, &flon, &age);
+
+ Serial.print(F("Location: "));
+ if (gps.location.isValid())
+ {
+ Serial.print(gps.location.lat(), 6);
+ Serial.print(F(","));
+ Serial.print(gps.location.lng(), 6);
+
+ flat = gps.location.lat();
+ flon = gps.location.lng();
+ flalt = gps.altitude.meters();
+ }
+ else
+ {
+ Serial.print(F("INVALID"));
+ }
+ Serial.print("\r\n");
+
+ } else
+// Serial.printf("GPS read no new data: %d\n", millis() - start);
+ ;
+}
+#endif
diff --git a/stempayload/Payload_BME280_MPU6050_AIO/adafruitio_00_publish_modified.cpp b/stempayload/Payload_BME280_MPU6050_AIO/adafruitio_00_publish_modified.cpp
new file mode 100644
index 000000000..27deb5faa
--- /dev/null
+++ b/stempayload/Payload_BME280_MPU6050_AIO/adafruitio_00_publish_modified.cpp
@@ -0,0 +1,142 @@
+// Mods to this file by Alan B Johnston KU2Y
+//
+// changed setup to aio_setup and loop to aio_loop
+//
+// You must put your account and WiFi info and rename config file as config.h
+//
+// Adafruit IO Publish Example
+//
+// Adafruit invests time and resources providing this open source code.
+// Please support Adafruit and open source hardware by purchasing
+// products from Adafruit!
+//
+// Written by Todd Treece for Adafruit Industries
+// Copyright (c) 2016 Adafruit Industries
+// Licensed under the MIT license.
+//
+// All text above must be included in any redistribution.
+
+/************************** Configuration ***********************************/
+
+// edit the config.h tab and enter your Adafruit IO credentials
+// and any additional configuration needed for WiFi, cellular,
+// or ethernet clients.
+#include "config.h"
+
+/************************ Example Starts Here *******************************/
+
+// this int will hold the current count for our sketch
+// int count = 0;
+bool aio_connected = false;
+unsigned long time_stamp;
+
+// should match the number of feeds define below so throttling delay is set correctly
+#define FEEDS 7
+
+// set up the 'counter' feed
+//AdafruitIO_Feed *counter = io.feed("counter");
+AdafruitIO_Feed *temperature = io.feed("temperature");
+AdafruitIO_Feed *pressure = io.feed("pressure");
+AdafruitIO_Feed *altitude = io.feed("altitude");
+AdafruitIO_Feed *humidity = io.feed("humidity");
+AdafruitIO_Feed *accel_x = io.feed("Acceleration - X Axis");
+AdafruitIO_Feed *accel_y = io.feed("Acceleration - Y Axis");
+AdafruitIO_Feed *accel_z = io.feed("Acceleration - Z Axis");
+// AdafruitIO_Feed *gyro_x = io.feed("Rotation X Axis");
+// AdafruitIO_Feed *gyro_y = io.feed("Rotation Y Axis");
+// AdafruitIO_Feed *gyro_z = io.feed("Rotation Z Axis");
+
+void aio_setup() {
+/*
+ // start the serial connection
+ Serial.begin(115200);
+
+ // wait for serial monitor to open
+ while(! Serial);
+*/
+ Serial.print("\nConnecting to Adafruit IO");
+
+ // connect to io.adafruit.com
+ io.connect();
+
+/* // wait for a connection
+ while(io.status() < AIO_CONNECTED) {
+ Serial.print(".");
+ delay(500);
+ }
+
+ // we are connected
+ Serial.println();
+ Serial.println(io.statusText());
+*/
+ time_stamp = millis();
+}
+
+void aio_loop(float tlm[]) {
+
+ if (!aio_connected) {
+ if (io.status() < AIO_CONNECTED) {
+ Serial.println("\nConnecting to Adafruit IO...");
+ } else {
+ Serial.print("\nSuccessfully connected to Adafruit IO! Status: ");
+// Serial.println();
+ Serial.println(io.statusText());
+ aio_connected = true;
+ }
+ } else {
+ // io.run(); is required for all sketches.
+ // it should always be present at the top of your loop
+ // function. it keeps the client connected to
+ // io.adafruit.com, and processes any incoming data.
+ io.run();
+
+ if ((millis() - time_stamp) < ((2000 * (FEEDS+1)) + 1000)) { // 8000) { // Only send if 8 seconds have passed
+ Serial.print("\nWaiting to send Adafruit IO\n");
+ }
+ else {
+ time_stamp = millis();
+ // save count to the 'counter' feed on Adafruit IO
+ Serial.print("\nSending to Adafruit IO -> ");
+ // Serial.println(count);
+ // counter->save(count);
+ Serial.print(tlm[0]);
+ temperature->save(tlm[0]);
+ Serial.print(" ");
+ Serial.print(tlm[1]);
+ pressure->save(tlm[1]);
+ Serial.print(" ");
+ Serial.print(tlm[2]);
+ altitude->save(tlm[2]);
+ Serial.print(" ");
+ Serial.print(tlm[3]);
+ humidity->save(tlm[3]);
+ Serial.print(" ");
+// Serial.print(tlm[4]);
+// gyro_x->save(tlm[4]);
+// Serial.print(" ");
+// Serial.print(tlm[5]);
+// gyro_y->save(tlm[5]);
+// Serial.print(" ");
+// Serial.print(tlm[6]);
+// gyro_z->save(tlm[6]);
+ Serial.print(tlm[7]);
+ accel_x->save(tlm[7]);
+ Serial.print(" ");
+ Serial.print(tlm[8]);
+ accel_y->save(tlm[8]);
+ Serial.print(" ");
+ Serial.print(tlm[9]);
+ accel_z->save(tlm[9]);
+
+ Serial.println(" ");
+
+ // increment the count by 1
+// count++;
+
+ // Adafruit IO is rate limited for publishing, so a delay is required in
+ // between feed->save events. In this example, we will wait three seconds
+ // (1000 milliseconds == 1 second) during each loop.
+ // delay(10000); // 1000
+ }
+ }
+}
diff --git a/stempayload/Payload_BME280_MPU6050_AIO/edit_this_config_and_rename.h b/stempayload/Payload_BME280_MPU6050_AIO/edit_this_config_and_rename.h
new file mode 100644
index 000000000..b6c47fa31
--- /dev/null
+++ b/stempayload/Payload_BME280_MPU6050_AIO/edit_this_config_and_rename.h
@@ -0,0 +1,74 @@
+// Edit this config file with your IO Username, Key, WiFi SSID and Password, then save as config.h
+
+/************************ Adafruit IO Config *******************************/
+
+// visit io.adafruit.com if you need to create an account,
+// or if you need your Adafruit IO key.
+#define IO_USERNAME "your_username"
+#define IO_KEY "your_key"
+
+/******************************* WIFI **************************************/
+
+// the AdafruitIO_WiFi client will work with the following boards:
+// - HUZZAH ESP8266 Breakout -> https://www.adafruit.com/products/2471
+// - Feather HUZZAH ESP8266 -> https://www.adafruit.com/products/2821
+// - Feather HUZZAH ESP32 -> https://www.adafruit.com/product/3405
+// - Feather M0 WiFi -> https://www.adafruit.com/products/3010
+// - Feather WICED -> https://www.adafruit.com/products/3056
+// - Adafruit PyPortal -> https://www.adafruit.com/product/4116
+// - Adafruit Metro M4 Express AirLift Lite ->
+// https://www.adafruit.com/product/4000
+// - Adafruit AirLift Breakout -> https://www.adafruit.com/product/4201
+// - Adafruit AirLift Shield -> https://www.adafruit.com/product/4285
+// - Adafruit AirLift FeatherWing -> https://www.adafruit.com/product/4264
+
+#define WIFI_SSID "your_ssid"
+#define WIFI_PASS "your_pass"
+
+// uncomment the following line if you are using airlift
+// #define USE_AIRLIFT
+
+// uncomment the following line if you are using winc1500
+// #define USE_WINC1500
+
+// uncomment the following line if you are using mrk1010 or nano 33 iot
+//#define ARDUINO_SAMD_MKR1010
+
+// comment out the following lines if you are using fona or ethernet
+#include "AdafruitIO_WiFi.h"
+
+#if defined(USE_AIRLIFT) || defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || \
+ defined(ADAFRUIT_PYPORTAL)
+// Configure the pins used for the ESP32 connection
+#if !defined(SPIWIFI_SS) // if the wifi definition isnt in the board variant
+// Don't change the names of these #define's! they match the variant ones
+#define SPIWIFI SPI
+#define SPIWIFI_SS 10 // Chip select pin
+#define NINA_ACK 9 // a.k.a BUSY or READY pin
+#define NINA_RESETN 6 // Reset pin
+#define NINA_GPIO0 -1 // Not connected
+#endif
+AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS, SPIWIFI_SS,
+ NINA_ACK, NINA_RESETN, NINA_GPIO0, &SPIWIFI);
+#else
+AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
+#endif
+/******************************* FONA **************************************/
+
+// the AdafruitIO_FONA client will work with the following boards:
+// - Feather 32u4 FONA -> https://www.adafruit.com/product/3027
+
+// uncomment the following two lines for 32u4 FONA,
+// and comment out the AdafruitIO_WiFi client in the WIFI section
+// #include "AdafruitIO_FONA.h"
+// AdafruitIO_FONA io(IO_USERNAME, IO_KEY);
+
+/**************************** ETHERNET ************************************/
+
+// the AdafruitIO_Ethernet client will work with the following boards:
+// - Ethernet FeatherWing -> https://www.adafruit.com/products/3201
+
+// uncomment the following two lines for ethernet,
+// and comment out the AdafruitIO_WiFi client in the WIFI section
+// #include "AdafruitIO_Ethernet.h"
+// AdafruitIO_Ethernet io(IO_USERNAME, IO_KEY);
diff --git a/stempayload/Payload_BME280_MPU6050_AIO/payload_extension.cpp b/stempayload/Payload_BME280_MPU6050_AIO/payload_extension.cpp
new file mode 100644
index 000000000..5b8dd2ec8
--- /dev/null
+++ b/stempayload/Payload_BME280_MPU6050_AIO/payload_extension.cpp
@@ -0,0 +1,25 @@
+// Use this template for adding additional sensors
+// see Payload_BME280_MPU6050_XS_Extended for an example
+
+// put your library includes here
+#include "Arduino.h"
+
+// put your globals here
+
+// put your setup code here
+void payload_setup() {
+
+// Serial.println("Starting new sensor!");
+
+}
+
+// put your loop code here
+// Very Important: only use print, not println!!
+void payload_loop() {
+
+/*
+ Serial1.print(" NEW 0.0"); // send sensor data over serial to Pi Zero
+ Serial.print(" NEW 0.0"); // send sensor data over serial monitor for testing
+*/
+
+}
diff --git a/stempayload/Payload_BME280_MPU6050_XS/Payload_BME280_MPU6050_XS.ino b/stempayload/Payload_BME280_MPU6050_XS/Payload_BME280_MPU6050_XS.ino
index f0111f9ea..748989b70 100644
--- a/stempayload/Payload_BME280_MPU6050_XS/Payload_BME280_MPU6050_XS.ino
+++ b/stempayload/Payload_BME280_MPU6050_XS/Payload_BME280_MPU6050_XS.ino
@@ -1,16 +1,36 @@
-// code for Pro Micro or STM32 on the CubeSat Simulator STEM Payload board
-// answers "OK" on the serial port Serial1 when queried by the Pi
+// code for Pico or Pro Micro or STM32 on the CubeSat Simulator STEM Payload board
+// works wih CubeSatSim software v1.3.2 or later
+// extra sensors can be added in payload_extension.cpp file
#include
#include
#include
#include
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040)
#include
+#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Arduino Mbed OS RP2040 Boards is used in Arduino IDE
+#include
+TinyGPSPlus gps;
+UART Serial2(8, 9, 0, 0);
+
+#elif !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards in Arduino IDE
+#include
+TinyGPSPlus gps;
+bool check_for_wifi();
+bool wifi = false;
+int led_builtin_pin;
+
+#else // if Sparkfun Pro Micro or STM32
+#include
+#endif
+
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;
MPU6050 mpu6050(Wire);
-
+
long timer = 0;
int bmePresent;
int RXLED = 17; // The RX LED has a defined Arduino pin
@@ -18,11 +38,20 @@ int greenLED = 9;
int blueLED = 8;
int Sensor1 = 0;
float Sensor2 = 0;
-void eeprom_word_write(int addr, int val);
-short eeprom_word_read(int addr);
+float temp;
+int calibration = 0;
+
+void ee_prom_word_write(int addr, int val);
+short ee_prom_word_read(int addr);
int first_time = true;
int first_read = true;
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+float T2 = 24; // Temperature data point 1
+float R2 = 169; // Reading data point 1
+float T1 = 6; // Temperature data point 2
+float R1 = 181; // Reading data point 2
+#endif
#if defined __AVR_ATmega32U4__
float T2 = 26.3; // Temperature data point 1
float R2 = 167; // Reading data point 1
@@ -39,15 +68,63 @@ float R1 = 695; // Reading data point 2
int sensorValue;
float Temp;
float rest;
-
+
+char sensor_end_flag[] = "_END_FLAG_";
+char sensor_start_flag[] = "_START_FLAG_";
+bool show_gps = true; // set to false to not see all messages
+float flon = 0.0, flat = 0.0, flalt = 0.0;
+void get_gps();
+
+extern void payload_setup(); // sensor extension setup function defined in payload_extension.cpp
+extern void payload_loop(); // sensor extension read function defined in payload_extension.cpp
+
void setup() {
+
+ Serial.begin(115200); // Serial Monitor for testing
- Serial.begin(9600); // Serial Monitor for testing
-
- Serial1.begin(115200); // Pi UART faster speed
-// Serial1.begin(9600); // Pi UART faster speed
-
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ Serial1.setRX(1);
+ delay(100);
+ Serial1.setTX(0);
+ delay(100);
+#endif
+
+ Serial1.begin(115200); // for communication with Pi Zero
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards in Arduino IDE
+ EEPROM.begin(512);
+#endif
+
+ delay(2000);
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) && (ARDUINO_ARCH_RP2040)
+ Serial.println("Pico with Mbed");
+#elif !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ Serial.println("Pico with RP2040");
+#elif defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ Serial.println("STM32");
+#elif defined __AVR_ATmega32U4__
+ Serial.println("Pro Micro");
+#else
+ Serial.println("Unknown board");
+#endif
+
Serial.println("Starting!");
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ Serial.println("Starting Serial2 for optional GPS on JP12");
+// Serial2.begin(9600); // serial from - some modules need 115200
+ Serial2.begin(9600); // serial from GPS or other serial sensor. Some GPS need 115200
+
+ // set all Pico GPIO connected pins to input
+ for (int i = 10; i < 22; i++) {
+ pinMode(i, INPUT);
+ }
+ pinMode(26, INPUT);
+ pinMode(27, INPUT);
+ pinMode(28, INPUT);
+ pinMode(15, INPUT_PULLUP); // squelch
+#endif
blink_setup();
@@ -70,7 +147,7 @@ void setup() {
}
mpu6050.begin();
-
+
if (eeprom_word_read(0) == 0xA07)
{
Serial.println("Reading gyro offsets from EEPROM\n");
@@ -84,37 +161,89 @@ void setup() {
Serial.println(zOffset, DEC);
mpu6050.setGyroOffsets(xOffset, yOffset, zOffset);
+
+ Serial.println("\nTemperature calibration data from EEPROM\n");
+
+ T1 = ((float)eeprom_word_read(4)) / 10.0;
+ R1 = ((float)eeprom_word_read(5));
+ T2 = ((float)eeprom_word_read(6)) / 10.0;
+ R2 = ((float)eeprom_word_read(7));
+
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+ Serial.println(" ");
+
}
else
{
- Serial.println("Calculating gyro offsets and storing in EEPROM\n");
-
+ Serial.println("Calculating gyro offsets\n");
mpu6050.calcGyroOffsets(true);
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ Serial.println("Storing gyro offsets in EEPROM\n");
eeprom_word_write(0, 0xA07);
eeprom_word_write(1, (int)(mpu6050.getGyroXoffset() * 100.0) + 0.5);
eeprom_word_write(2, (int)(mpu6050.getGyroYoffset() * 100.0) + 0.5);
- eeprom_word_write(3, (int)(mpu6050.getGyroZoffset() * 100.0) + 0.5);
+ eeprom_word_write(3, (int)(mpu6050.getGyroZoffset() * 100.0) + 0.5);
Serial.println(eeprom_word_read(0), HEX);
Serial.println(((float)eeprom_word_read(1)) / 100.0, DEC);
Serial.println(((float)eeprom_word_read(2)) / 100.0, DEC);
Serial.println(((float)eeprom_word_read(3)) / 100.0, DEC);
+
+ Serial.println("\nStoring temperature calibration data in EEPROM\n");
+
+ eeprom_word_write(4, (int)(T1 * 10.0) + 0.5);
+ eeprom_word_write(5, (int) R1);
+ eeprom_word_write(6, (int)(T2 * 10.0) + 0.5);
+ eeprom_word_write(7, (int) R2);
+
+ T1 = ((float)eeprom_word_read(4)) / 10.0;
+ R1 = ((float)eeprom_word_read(5));
+ T2 = ((float)eeprom_word_read(6)) / 10.0;
+ R2 = ((float)eeprom_word_read(7));
+
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+ Serial.println(" ");
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
+ }
+#endif
+#endif
}
-/**/
+ payload_setup(); // sensor extension setup function defined in payload_extension.cpp
}
void loop() {
-
+
+ blink(50);
+
if (Serial1.available() > 0) {
- blink(50);
- char result = Serial1.read();
-// Serial1.println(result);
-// Serial1.println("OK");
-
+ Serial.print("Received serial data!!!\n");
+ delay(10);
+ while (Serial1.available() > 0) {
+ char result = Serial1.read();
+ Serial.print(result);
+ }
+ Serial.println(" ");
+ }
+ {
// if (result == '?')
{
if (bmePresent) {
+ Serial1.print(sensor_start_flag);
Serial1.print("OK BME280 ");
Serial1.print(bme.readTemperature());
Serial1.print(" ");
@@ -123,9 +252,22 @@ void loop() {
Serial1.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial1.print(" ");
Serial1.print(bme.readHumidity());
+
+ Serial.print("OK BME280 ");
+ temp = bme.readTemperature();
+ Serial.print(temp);
+ Serial.print(" ");
+ Serial.print(bme.readPressure() / 100.0F);
+ Serial.print(" ");
+ Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
+ Serial.print(" ");
+ Serial.print(bme.readHumidity());
} else
{
+ Serial1.print(sensor_start_flag);
Serial1.print("OK BME280 0.0 0.0 0.0 0.0");
+
+ Serial.print("OK BME280 0.0 0.0 0.0 0.0");
}
mpu6050.update();
@@ -136,22 +278,59 @@ void loop() {
Serial1.print(" ");
Serial1.print(mpu6050.getGyroZ());
- Serial1.print(" ");
- Serial1.print(mpu6050.getAccX());
- Serial1.print(" ");
- Serial1.print(mpu6050.getAccY());
- Serial1.print(" ");
- Serial1.print(mpu6050.getAccZ());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccX());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccY());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccZ());
+
+ Serial.print(" MPU6050 ");
+ Serial.print(mpu6050.getGyroX());
+ Serial.print(" ");
+ Serial.print(mpu6050.getGyroY());
+ Serial.print(" ");
+ Serial.print(mpu6050.getGyroZ());
- sensorValue = read_analog();
+ Serial.print(" ");
+ Serial.print(mpu6050.getAccX());
+ Serial.print(" ");
+ Serial.print(mpu6050.getAccY());
+ Serial.print(" ");
+ Serial.print(mpu6050.getAccZ());
+
+ sensorValue = read_analog();
// Serial.println(sensorValue);
Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1));
- Serial1.print(" XS ");
- Serial1.print(Temp);
+// Serial1.print(" GPS 0 0 0 TMP ");
+
+ Serial1.print(" GPS ");
+ Serial1.print(flat,4);
+ Serial1.print(" ");
+ Serial1.print(flon,4);
Serial1.print(" ");
- Serial1.println(Sensor2);
+ Serial1.print(flalt,2);
+
+ Serial1.print(" TMP ");
+ Serial1.print(Temp);
+
+// Serial1.print(" ");
+// Serial1.println(Sensor2);
+
+ Serial.print(" GPS ");
+ Serial.print(flat,4);
+ Serial.print(" ");
+ Serial.print(flon,4);
+ Serial.print(" ");
+ Serial.print(flalt,2);
+
+// Serial.print(" GPS 0 0 0 TMP ");
+ Serial.print(" TMP ");
+ Serial.print(Temp);
+// Serial.print(" ");
+// Serial.println(Sensor2);
float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ());
float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ());
@@ -174,7 +353,13 @@ void loop() {
else
led_set(blueLED, LOW);
}
-
+
+ payload_loop(); // sensor extension read function defined in payload_extension.cpp
+
+// Serial1.println(" ");
+ Serial1.println(sensor_end_flag);
+ Serial.println(" ");
+
}
if (Serial.available() > 0) {
@@ -183,98 +368,104 @@ void loop() {
// Serial.println(result);
// Serial.println("OK");
// Serial.println(counter++);
-
- if (result == 'R') {
- Serial1.println("OK");
- delay(100);
+//#if !defined (ARDUINO_ARCH_RP2040)
+ if (result == 'R' || result == 'r') {
+// Serial1.println("OK");
+// delay(100);
+ Serial.println("Resetting\n");
first_read = true;
setup();
}
- else if (result == 'C') {
- Serial.println("Clearing stored gyro offsets in EEPROM\n");
+ else if (result == 'D' || result == 'd') {
+ Serial.println("\nCurrent temperature calibration data\n");
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+
+ Serial.println("\nCurrent raw temperature reading\n");
+ Serial.println(sensorValue, DEC);
+ Serial.println(" ");
+ }
+ else if (result == 'C' || result == 'c') {
+ Serial.println("\nClearing stored gyro offsets in EEPROM\n");
eeprom_word_write(0, 0x00);
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
+ }
+#endif
first_time = true;
setup();
- }
-
- if ((result == '?') || first_time == true)
- {
- first_time = false;
- if (bmePresent) {
- Serial.print("OK BME280 ");
- Serial.print(bme.readTemperature());
- Serial.print(" ");
- Serial.print(bme.readPressure() / 100.0F);
- Serial.print(" ");
- Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
- Serial.print(" ");
- Serial.print(bme.readHumidity());
- } else
- {
- Serial.print("OK BME280 0.0 0.0 0.0 0.0");
- }
- mpu6050.update();
-
- Serial.print(" MPU6050 ");
- Serial.print(mpu6050.getGyroX());
- Serial.print(" ");
- Serial.print(mpu6050.getGyroY());
- Serial.print(" ");
- Serial.print(mpu6050.getGyroZ());
-
- Serial.print(" ");
- Serial.print(mpu6050.getAccX());
- Serial.print(" ");
- Serial.print(mpu6050.getAccY());
- Serial.print(" ");
- Serial.print(mpu6050.getAccZ());
-
- sensorValue = read_analog();
-
- Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1));
-
- Serial.print(" XS ");
- Serial.print(Temp);
- Serial.print(" ");
- Serial.print(Sensor2);
- Serial.print(" (");
- Serial.print(sensorValue);
- Serial.println(")");
-
- float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ());
- float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ());
-// Serial.print(rotation);
-// Serial.print(" ");
-// Serial.println(acceleration);
-
- if (first_read == true) {
- first_read = false;
- rest = acceleration;
}
-
- if (acceleration > 1.2 * rest)
- led_set(greenLED, HIGH);
- else
- led_set(greenLED, LOW);
-
- if (rotation > 5)
- led_set(blueLED, HIGH);
- else
- led_set(blueLED, LOW);
+ else if (result == 'S' || result == 's') {
+ Serial.print("\nStoring temperature calibration data point "); // in EEPROM\n");
+ Serial.print(calibration + 1);
+ Serial.print(" in EEPROM\n");
+
+ Serial.println(temp);
+ Serial.println(sensorValue);
+ Serial.println(" ");
+
+ eeprom_word_write(calibration * 2 + 4 , (int)(temp * 10.0) + 0.5);
+ eeprom_word_write(calibration * 2 + 5, sensorValue);
+
+ if (calibration == 0) {
+ T1 = temp;
+ R1 = sensorValue;
+ calibration = 1;
+ } else {
+ T2 = temp;
+ R2 = sensorValue;
+ calibration = 0;
+ }
+
+// calibration = (calibration + 1) % 2;
+// Serial.println(calibration + 1);
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
}
+#endif
+
+ }
+//#endif
}
- delay(100);
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ Serial.print("Squelch: ");
+ Serial.println(digitalRead(15));
+
+ get_gps();
+#else
+ delay(1000); // not needed due to gps 1 second polling delay
+
+#endif
}
void eeprom_word_write(int addr, int val)
{
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
EEPROM.write(addr * 2, lowByte(val));
EEPROM.write(addr * 2 + 1, highByte(val));
+#endif
}
short eeprom_word_read(int addr)
{
- return ((EEPROM.read(addr * 2 + 1) << 8) | EEPROM.read(addr * 2));
+ int result = 0;
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ result = ((EEPROM.read(addr * 2 + 1) << 8) | EEPROM.read(addr * 2));
+#endif
+ return result;
}
void blink_setup()
@@ -292,6 +483,27 @@ void blink_setup()
pinMode(greenLED, OUTPUT);
pinMode(blueLED,OUTPUT);
#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ pinMode(LED_BUILTIN, OUTPUT);
+ pinMode(18, OUTPUT); // blue LED on STEM Payload Board v1.3.2
+ pinMode(19, OUTPUT); // green LED on STEM Payload Board v1.3.2
+#endif
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (check_for_wifi()) {
+ wifi = true;
+ led_builtin_pin = LED_BUILTIN; // use default GPIO for Pico W
+ pinMode(LED_BUILTIN, OUTPUT);
+// configure_wifi();
+ } else {
+ led_builtin_pin = 25; // manually set GPIO 25 for Pico board
+// pinMode(25, OUTPUT);
+ pinMode(led_builtin_pin, OUTPUT);
+ }
+ pinMode(18, OUTPUT);
+ pinMode(19, OUTPUT);
+#endif
}
void blink(int length)
@@ -304,8 +516,19 @@ void blink(int length)
digitalWrite(RXLED, LOW); // set the RX LED ON
TXLED0; //TX LED is not tied to a normally controlled pin so a macro is needed, turn LED OFF
#endif
-
- delay(length); // wait for a lenth of time
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+#endif
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (wifi)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON
+#endif
+
+delay(length);
#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
digitalWrite(PC13, HIGH); // turn the LED off by making the voltage LOW
@@ -315,6 +538,17 @@ void blink(int length)
digitalWrite(RXLED, HIGH); // set the RX LED OFF
TXLED0; //TX LED macro to turn LED ON
#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF
+#endif
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (wifi)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, LOW); // set the built-in LED ON
+#endif
}
void led_set(int ledPin, bool state)
@@ -329,6 +563,13 @@ void led_set(int ledPin, bool state)
#if defined __AVR_ATmega32U4__
digitalWrite(ledPin, state);
#endif
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ if (ledPin == greenLED)
+ digitalWrite(19, state);
+ else if (ledPin == blueLED)
+ digitalWrite(18, state);
+#endif
}
int read_analog()
@@ -337,8 +578,81 @@ int read_analog()
#if defined __AVR_ATmega32U4__
sensorValue = analogRead(A3);
#endif
+
#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
sensorValue = analogRead(PA7);
+#endif
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ sensorValue = analogRead(28);
#endif
return(sensorValue);
}
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+bool check_for_wifi() {
+
+ pinMode(29, INPUT);
+ const float conversion_factor = 3.3f / (1 << 12);
+ uint16_t result = analogRead(29);
+// Serial.printf("ADC3 value: 0x%03x, voltage: %f V\n", result, result * conversion_factor);
+
+ if (result < 0x10) {
+ Serial.println("\nPico W detected!\n");
+ return(true);
+ }
+ else {
+ Serial.println("\nPico detected!\n");
+ return(false);
+ }
+}
+#endif
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+void get_gps() {
+// Serial.println("Getting GPS data");
+ bool newData = false;
+ unsigned long start = millis();
+
+// for (unsigned long start = millis(); millis() - start < 1000;) // 5000;)
+ while ((millis() - start) < 1000) // 5000;)
+ {
+ while (Serial2.available())
+ {
+ char c = Serial2.read();
+ if (show_gps)
+ Serial.write(c); // uncomment this line if you want to see the GPS data flowing
+ if (gps.encode(c)) // Did a new valid sentence come in?
+ newData = true;
+ }
+ }
+ if (newData) {
+ Serial.print("GPS read new data in ms: ");
+ Serial.println(millis() - start);
+
+// float flon = 0.0, flat = 0.0, flalt = 0.0;
+// unsigned long age;
+// starting = millis();
+// gps.f_get_position(&flat, &flon, &age);
+
+ Serial.print(F("Location: "));
+ if (gps.location.isValid())
+ {
+ Serial.print(gps.location.lat(), 6);
+ Serial.print(F(","));
+ Serial.print(gps.location.lng(), 6);
+
+ flat = gps.location.lat();
+ flon = gps.location.lng();
+ flalt = gps.altitude.meters();
+ }
+ else
+ {
+ Serial.print(F("INVALID"));
+ }
+ Serial.print("\r\n");
+
+ } else
+// Serial.printf("GPS read no new data: %d\n", millis() - start);
+ ;
+}
+#endif
diff --git a/stempayload/Payload_BME280_MPU6050_XS/payload_extension.cpp b/stempayload/Payload_BME280_MPU6050_XS/payload_extension.cpp
new file mode 100644
index 000000000..5b8dd2ec8
--- /dev/null
+++ b/stempayload/Payload_BME280_MPU6050_XS/payload_extension.cpp
@@ -0,0 +1,25 @@
+// Use this template for adding additional sensors
+// see Payload_BME280_MPU6050_XS_Extended for an example
+
+// put your library includes here
+#include "Arduino.h"
+
+// put your globals here
+
+// put your setup code here
+void payload_setup() {
+
+// Serial.println("Starting new sensor!");
+
+}
+
+// put your loop code here
+// Very Important: only use print, not println!!
+void payload_loop() {
+
+/*
+ Serial1.print(" NEW 0.0"); // send sensor data over serial to Pi Zero
+ Serial.print(" NEW 0.0"); // send sensor data over serial monitor for testing
+*/
+
+}
diff --git a/stempayload/Payload_BME280_MPU6050_XS_Extended/Payload_BME280_MPU6050_XS_Extended.ino b/stempayload/Payload_BME280_MPU6050_XS_Extended/Payload_BME280_MPU6050_XS_Extended.ino
index f7b391b44..748989b70 100644
--- a/stempayload/Payload_BME280_MPU6050_XS_Extended/Payload_BME280_MPU6050_XS_Extended.ino
+++ b/stempayload/Payload_BME280_MPU6050_XS_Extended/Payload_BME280_MPU6050_XS_Extended.ino
@@ -1,49 +1,133 @@
+// code for Pico or Pro Micro or STM32 on the CubeSat Simulator STEM Payload board
+// works wih CubeSatSim software v1.3.2 or later
+// extra sensors can be added in payload_extension.cpp file
+
#include
#include
#include
#include
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040)
#include
-#include "Adafruit_SI1145.h"
-#include
+#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Arduino Mbed OS RP2040 Boards is used in Arduino IDE
+#include
+TinyGPSPlus gps;
+UART Serial2(8, 9, 0, 0);
+
+#elif !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards in Arduino IDE
+#include
+TinyGPSPlus gps;
+bool check_for_wifi();
+bool wifi = false;
+int led_builtin_pin;
+
+#else // if Sparkfun Pro Micro or STM32
+#include
+#endif
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;
MPU6050 mpu6050(Wire);
-Adafruit_SI1145 uv = Adafruit_SI1145();
-Adafruit_LIS3MDL lis3mdl;
long timer = 0;
int bmePresent;
-int uvPresent;
-int magPresent;
int RXLED = 17; // The RX LED has a defined Arduino pin
int greenLED = 9;
int blueLED = 8;
-void eeprom_word_write(int addr, int val);
-short eeprom_word_read(int addr);
+int Sensor1 = 0;
+float Sensor2 = 0;
+float temp;
+int calibration = 0;
+
+void ee_prom_word_write(int addr, int val);
+short ee_prom_word_read(int addr);
int first_time = true;
int first_read = true;
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+float T2 = 24; // Temperature data point 1
+float R2 = 169; // Reading data point 1
+float T1 = 6; // Temperature data point 2
+float R1 = 181; // Reading data point 2
+#endif
+#if defined __AVR_ATmega32U4__
float T2 = 26.3; // Temperature data point 1
float R2 = 167; // Reading data point 1
float T1 = 2; // Temperature data point 2
float R1 = 179; // Reading data point 2
+#endif
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+float T2 = 25; // Temperature data point 1
+float R2 = 671; // Reading data point 1
+float T1 = 15.5; // Temperature data point 2
+float R1 = 695; // Reading data point 2
+#endif
+
int sensorValue;
float Temp;
float rest;
-float magRaw = 0;
-float magRawAbs = 0;
-
-void setup() {
- Serial.begin(9600); // Serial Monitor for testing
+char sensor_end_flag[] = "_END_FLAG_";
+char sensor_start_flag[] = "_START_FLAG_";
+bool show_gps = true; // set to false to not see all messages
+float flon = 0.0, flat = 0.0, flalt = 0.0;
+void get_gps();
- Serial1.begin(115200); // Pi UART faster speed
+extern void payload_setup(); // sensor extension setup function defined in payload_extension.cpp
+extern void payload_loop(); // sensor extension read function defined in payload_extension.cpp
+void setup() {
+
+ Serial.begin(115200); // Serial Monitor for testing
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ Serial1.setRX(1);
+ delay(100);
+ Serial1.setTX(0);
+ delay(100);
+#endif
+
+ Serial1.begin(115200); // for communication with Pi Zero
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards in Arduino IDE
+ EEPROM.begin(512);
+#endif
+
+ delay(2000);
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) && (ARDUINO_ARCH_RP2040)
+ Serial.println("Pico with Mbed");
+#elif !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ Serial.println("Pico with RP2040");
+#elif defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ Serial.println("STM32");
+#elif defined __AVR_ATmega32U4__
+ Serial.println("Pro Micro");
+#else
+ Serial.println("Unknown board");
+#endif
+
Serial.println("Starting!");
- blink_setup();
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ Serial.println("Starting Serial2 for optional GPS on JP12");
+// Serial2.begin(9600); // serial from - some modules need 115200
+ Serial2.begin(9600); // serial from GPS or other serial sensor. Some GPS need 115200
+ // set all Pico GPIO connected pins to input
+ for (int i = 10; i < 22; i++) {
+ pinMode(i, INPUT);
+ }
+ pinMode(26, INPUT);
+ pinMode(27, INPUT);
+ pinMode(28, INPUT);
+ pinMode(15, INPUT_PULLUP); // squelch
+#endif
+
+ blink_setup();
+
blink(500);
delay(250);
blink(500);
@@ -58,84 +142,120 @@ void setup() {
if (bme.begin(0x76)) {
bmePresent = 1;
} else {
- Serial.println("BME280 sensor fault");
+ Serial.println("Could not find a valid BME280 sensor, check wiring!");
bmePresent = 0;
}
-
- if (! uv.begin()) {
- Serial.println("Si1145 sensor fault");
- uvPresent = 0;
- } else {
- uvPresent = 1;
- }
-
- if (! lis3mdl.begin_I2C()) {
- Serial.println("LIS3MDL sensor fault");
- magPresent = 0;
- } else {
- magPresent = 1;
- }
-
+
mpu6050.begin();
-
+
if (eeprom_word_read(0) == 0xA07)
{
Serial.println("Reading gyro offsets from EEPROM\n");
-
+
float xOffset = ((float)eeprom_word_read(1)) / 100.0;
float yOffset = ((float)eeprom_word_read(2)) / 100.0;
float zOffset = ((float)eeprom_word_read(3)) / 100.0;
-
+
Serial.println(xOffset, DEC);
Serial.println(yOffset, DEC);
Serial.println(zOffset, DEC);
-
+
mpu6050.setGyroOffsets(xOffset, yOffset, zOffset);
+
+ Serial.println("\nTemperature calibration data from EEPROM\n");
+
+ T1 = ((float)eeprom_word_read(4)) / 10.0;
+ R1 = ((float)eeprom_word_read(5));
+ T2 = ((float)eeprom_word_read(6)) / 10.0;
+ R2 = ((float)eeprom_word_read(7));
+
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+ Serial.println(" ");
+
}
else
{
- Serial.println("Calculating gyro offsets and storing in EEPROM\n");
-
+ Serial.println("Calculating gyro offsets\n");
mpu6050.calcGyroOffsets(true);
-
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ Serial.println("Storing gyro offsets in EEPROM\n");
+
eeprom_word_write(0, 0xA07);
eeprom_word_write(1, (int)(mpu6050.getGyroXoffset() * 100.0) + 0.5);
eeprom_word_write(2, (int)(mpu6050.getGyroYoffset() * 100.0) + 0.5);
- eeprom_word_write(3, (int)(mpu6050.getGyroZoffset() * 100.0) + 0.5);
-
+ eeprom_word_write(3, (int)(mpu6050.getGyroZoffset() * 100.0) + 0.5);
+
Serial.println(eeprom_word_read(0), HEX);
Serial.println(((float)eeprom_word_read(1)) / 100.0, DEC);
Serial.println(((float)eeprom_word_read(2)) / 100.0, DEC);
Serial.println(((float)eeprom_word_read(3)) / 100.0, DEC);
+
+ Serial.println("\nStoring temperature calibration data in EEPROM\n");
+
+ eeprom_word_write(4, (int)(T1 * 10.0) + 0.5);
+ eeprom_word_write(5, (int) R1);
+ eeprom_word_write(6, (int)(T2 * 10.0) + 0.5);
+ eeprom_word_write(7, (int) R2);
+
+ T1 = ((float)eeprom_word_read(4)) / 10.0;
+ R1 = ((float)eeprom_word_read(5));
+ T2 = ((float)eeprom_word_read(6)) / 10.0;
+ R2 = ((float)eeprom_word_read(7));
+
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+ Serial.println(" ");
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
+ }
+#endif
+#endif
}
- pinMode(greenLED, OUTPUT);
- pinMode(blueLED, OUTPUT);
+ payload_setup(); // sensor extension setup function defined in payload_extension.cpp
}
-
+
void loop() {
- if ((Serial.available() > 0) || first_time == true) {
- blink(50);
- char result = Serial.read();
-
- if (result == 'R') {
- Serial.println("OK");
- delay(100);
- first_time = true;
- setup();
- }
- else if (result == 'C') {
- Serial.println("Clearing stored gyro offsets in EEPROM\n");
- eeprom_word_write(0, 0x00);
- first_time = true;
- setup();
+ blink(50);
+
+ if (Serial1.available() > 0) {
+ Serial.print("Received serial data!!!\n");
+ delay(10);
+ while (Serial1.available() > 0) {
+ char result = Serial1.read();
+ Serial.print(result);
}
- if ((result == '?') || first_time == true)
+ Serial.println(" ");
+ }
+ {
+// if (result == '?')
{
- first_time = false;
if (bmePresent) {
+ Serial1.print(sensor_start_flag);
+ Serial1.print("OK BME280 ");
+ Serial1.print(bme.readTemperature());
+ Serial1.print(" ");
+ Serial1.print(bme.readPressure() / 100.0F);
+ Serial1.print(" ");
+ Serial1.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
+ Serial1.print(" ");
+ Serial1.print(bme.readHumidity());
+
Serial.print("OK BME280 ");
- Serial.print(bme.readTemperature());
+ temp = bme.readTemperature();
+ Serial.print(temp);
Serial.print(" ");
Serial.print(bme.readPressure() / 100.0F);
Serial.print(" ");
@@ -144,9 +264,26 @@ void loop() {
Serial.print(bme.readHumidity());
} else
{
+ Serial1.print(sensor_start_flag);
+ Serial1.print("OK BME280 0.0 0.0 0.0 0.0");
+
Serial.print("OK BME280 0.0 0.0 0.0 0.0");
}
mpu6050.update();
+
+ Serial1.print(" MPU6050 ");
+ Serial1.print(mpu6050.getGyroX());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getGyroY());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getGyroZ());
+
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccX());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccY());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccZ());
Serial.print(" MPU6050 ");
Serial.print(mpu6050.getGyroX());
@@ -154,206 +291,368 @@ void loop() {
Serial.print(mpu6050.getGyroY());
Serial.print(" ");
Serial.print(mpu6050.getGyroZ());
-
+
Serial.print(" ");
- Serial.print(mpu6050.getAccX());
+ Serial.print(mpu6050.getAccX());
Serial.print(" ");
- Serial.print(mpu6050.getAccY());
+ Serial.print(mpu6050.getAccY());
Serial.print(" ");
- Serial.print(mpu6050.getAccZ());
-
- sensorValue = analogRead(A3);
- Temp = T1 + (sensorValue - R1) * ((T2 - T1) / (R2 - R1));
-
- Serial.print(" XS ");
- Serial.print(Temp);
- Serial.print(" ");
- if (uvPresent) {
- Serial.print(uv.readVisible());
- Serial.print(" ");
- Serial.print(uv.readIR());
- Serial.print(" ");
- } else
- {
- Serial.print("0.0 0.0 ");
- }
- if (magPresent) {
- lis3mdl.read();
- magRaw = (((lis3mdl.x + lis3mdl.y + lis3mdl.z) / 3));
- magAbs = abs(magRaw);
- Serial.println(magAbs);
- } else
- {
- Serial.println("0.0");
- }
-
- float rotation = sqrt(mpu6050.getGyroX() * mpu6050.getGyroX() + mpu6050.getGyroY() * mpu6050.getGyroY() + mpu6050.getGyroZ() * mpu6050.getGyroZ());
- float acceleration = sqrt(mpu6050.getAccX() * mpu6050.getAccX() + mpu6050.getAccY() * mpu6050.getAccY() + mpu6050.getAccZ() * mpu6050.getAccZ());
-
- if (acceleration > 1.2)
+ Serial.print(mpu6050.getAccZ());
+
+ sensorValue = read_analog();
+
+// Serial.println(sensorValue);
+ Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1));
+
+// Serial1.print(" GPS 0 0 0 TMP ");
+
+ Serial1.print(" GPS ");
+ Serial1.print(flat,4);
+ Serial1.print(" ");
+ Serial1.print(flon,4);
+ Serial1.print(" ");
+ Serial1.print(flalt,2);
+
+ Serial1.print(" TMP ");
+ Serial1.print(Temp);
+
+// Serial1.print(" ");
+// Serial1.println(Sensor2);
+
+ Serial.print(" GPS ");
+ Serial.print(flat,4);
+ Serial.print(" ");
+ Serial.print(flon,4);
+ Serial.print(" ");
+ Serial.print(flalt,2);
+
+// Serial.print(" GPS 0 0 0 TMP ");
+ Serial.print(" TMP ");
+ Serial.print(Temp);
+// Serial.print(" ");
+// Serial.println(Sensor2);
+
+ float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ());
+ float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ());
+// Serial.print(rotation);
+// Serial.print(" ");
+// Serial.println(acceleration);
+
+ if (first_read == true) {
+ first_read = false;
+ rest = acceleration;
+ }
+
+ if (acceleration > 1.2 * rest)
led_set(greenLED, HIGH);
- else
+ else
led_set(greenLED, LOW);
-
- if (rotation > 5)
+
+ if (rotation > 5)
led_set(blueLED, HIGH);
- else
+ else
led_set(blueLED, LOW);
}
- }
- if (Serial1.available() > 0) {
+ payload_loop(); // sensor extension read function defined in payload_extension.cpp
- blink(50);
- char result = Serial1.read();
+// Serial1.println(" ");
+ Serial1.println(sensor_end_flag);
+ Serial.println(" ");
+
+ }
- if (result == 'R') {
- Serial1.println("OK");
- delay(100);
+ if (Serial.available() > 0) {
+ blink(50);
+ char result = Serial.read();
+// Serial.println(result);
+// Serial.println("OK");
+// Serial.println(counter++);
+//#if !defined (ARDUINO_ARCH_RP2040)
+ if (result == 'R' || result == 'r') {
+// Serial1.println("OK");
+// delay(100);
+ Serial.println("Resetting\n");
first_read = true;
setup();
}
-
- if (result == '?')
- {
- if (bmePresent) {
- Serial1.print("OK BME280 ");
- Serial1.print(bme.readTemperature());
- Serial1.print(" ");
- Serial1.print(bme.readPressure() / 100.0F);
- Serial1.print(" ");
- Serial1.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
- Serial1.print(" ");
- Serial1.print(bme.readHumidity());
- } else
- {
- Serial1.print("OK BME280 0.0 0.0 0.0 0.0");
- }
- mpu6050.update();
-
- Serial1.print(" MPU6050 ");
- Serial1.print(mpu6050.getGyroX());
- Serial1.print(" ");
- Serial1.print(mpu6050.getGyroY());
- Serial1.print(" ");
- Serial1.print(mpu6050.getGyroZ());
-
- Serial1.print(" ");
- Serial1.print(mpu6050.getAccX());
- Serial1.print(" ");
- Serial1.print(mpu6050.getAccY());
- Serial1.print(" ");
- Serial1.print(mpu6050.getAccZ());
-
- sensorValue = analogRead(A3);
- Temp = T1 + (sensorValue - R1) * ((T2 - T1) / (R2 - R1));
-
- Serial1.print(" XS ");
- Serial1.print(Temp);
- Serial1.print(" ");
- if (uvPresent) {
- Serial1.print(uv.readVisible());
- Serial1.print(" ");
- Serial1.print(uv.readIR());
- Serial1.print(" ");
- } else
- {
- Serial1.print("0.0 0.0 ");
- }
- if (magPresent) {
- lis3mdl.read();
- magRaw = (((lis3mdl.x + lis3mdl.y + lis3mdl.z) / 3));
- magAbs = abs(magRaw);
- Serial1.println(magAbs);
- } else
- {
- Serial1.println("0.0");
- }
-
-
- float rotation = sqrt(mpu6050.getGyroX() * mpu6050.getGyroX() + mpu6050.getGyroY() * mpu6050.getGyroY() + mpu6050.getGyroZ() * mpu6050.getGyroZ());
- float acceleration = sqrt(mpu6050.getAccX() * mpu6050.getAccX() + mpu6050.getAccY() * mpu6050.getAccY() + mpu6050.getAccZ() * mpu6050.getAccZ());
-
- if (first_read == true) {
- first_read = false;
- rest = acceleration;
- }
-
- if (acceleration > 1.2 * rest)
- led_set(greenLED, HIGH);
- else
- led_set(greenLED, LOW);
-
- if (rotation > 5)
- led_set(blueLED, HIGH);
- else
- led_set(blueLED, LOW);
- }
+ else if (result == 'D' || result == 'd') {
+ Serial.println("\nCurrent temperature calibration data\n");
+ Serial.println(T1, DEC);
+ Serial.println(R1, DEC);
+ Serial.println(" ");
+ Serial.println(T2, DEC);
+ Serial.println(R2, DEC);
+
+ Serial.println("\nCurrent raw temperature reading\n");
+ Serial.println(sensorValue, DEC);
+ Serial.println(" ");
}
+ else if (result == 'C' || result == 'c') {
+ Serial.println("\nClearing stored gyro offsets in EEPROM\n");
+ eeprom_word_write(0, 0x00);
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
+ }
+#endif
+ first_time = true;
+ setup();
+ }
+ else if (result == 'S' || result == 's') {
+ Serial.print("\nStoring temperature calibration data point "); // in EEPROM\n");
+ Serial.print(calibration + 1);
+ Serial.print(" in EEPROM\n");
+
+ Serial.println(temp);
+ Serial.println(sensorValue);
+ Serial.println(" ");
+
+ eeprom_word_write(calibration * 2 + 4 , (int)(temp * 10.0) + 0.5);
+ eeprom_word_write(calibration * 2 + 5, sensorValue);
+
+ if (calibration == 0) {
+ T1 = temp;
+ R1 = sensorValue;
+ calibration = 1;
+ } else {
+ T2 = temp;
+ R2 = sensorValue;
+ calibration = 0;
+ }
+
+// calibration = (calibration + 1) % 2;
+// Serial.println(calibration + 1);
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+
+ if (EEPROM.commit()) {
+ Serial.println("EEPROM successfully committed\n");
+ } else {
+ Serial.println("ERROR! EEPROM commit failed\n");
+ }
+#endif
+
+ }
+//#endif
+ }
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ Serial.print("Squelch: ");
+ Serial.println(digitalRead(15));
+
+ get_gps();
+#else
+ delay(1000); // not needed due to gps 1 second polling delay
+#endif
}
-
+
void eeprom_word_write(int addr, int val)
{
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
EEPROM.write(addr * 2, lowByte(val));
EEPROM.write(addr * 2 + 1, highByte(val));
+#endif
}
-
+
short eeprom_word_read(int addr)
{
- return ((EEPROM.read(addr * 2 + 1) << 8) | EEPROM.read(addr * 2));
+ int result = 0;
+#if !defined(ARDUINO_ARCH_MBED_RP2040) // && defined(ARDUINO_ARCH_RP2040) // if Raspberry Pi RP2040 Boards is used in Arduino IDE
+ result = ((EEPROM.read(addr * 2 + 1) << 8) | EEPROM.read(addr * 2));
+#endif
+ return result;
}
-
-void blink_setup()
+
+void blink_setup()
{
-#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
// initialize digital pin PB1 as an output.
pinMode(PC13, OUTPUT);
pinMode(PB9, OUTPUT);
pinMode(PB8, OUTPUT);
#endif
-
+
#if defined __AVR_ATmega32U4__
pinMode(RXLED, OUTPUT); // Set RX LED as an output
// TX LED is set as an output behind the scenes
pinMode(greenLED, OUTPUT);
- pinMode(blueLED, OUTPUT);
+ pinMode(blueLED,OUTPUT);
#endif
-}
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ pinMode(LED_BUILTIN, OUTPUT);
+ pinMode(18, OUTPUT); // blue LED on STEM Payload Board v1.3.2
+ pinMode(19, OUTPUT); // green LED on STEM Payload Board v1.3.2
+#endif
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (check_for_wifi()) {
+ wifi = true;
+ led_builtin_pin = LED_BUILTIN; // use default GPIO for Pico W
+ pinMode(LED_BUILTIN, OUTPUT);
+// configure_wifi();
+ } else {
+ led_builtin_pin = 25; // manually set GPIO 25 for Pico board
+// pinMode(25, OUTPUT);
+ pinMode(led_builtin_pin, OUTPUT);
+ }
+ pinMode(18, OUTPUT);
+ pinMode(19, OUTPUT);
+#endif
+}
+
void blink(int length)
{
#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
digitalWrite(PC13, LOW); // turn the LED on (HIGH is the voltage level)
#endif
-
+
#if defined __AVR_ATmega32U4__
digitalWrite(RXLED, LOW); // set the RX LED ON
TXLED0; //TX LED is not tied to a normally controlled pin so a macro is needed, turn LED OFF
-#endif
+#endif
- delay(length); // wait for a lenth of time
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+#endif
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (wifi)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON
+#endif
+
+delay(length);
+
#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
digitalWrite(PC13, HIGH); // turn the LED off by making the voltage LOW
#endif
-
+
#if defined __AVR_ATmega32U4__
digitalWrite(RXLED, HIGH); // set the RX LED OFF
TXLED0; //TX LED macro to turn LED ON
-#endif
-}
+#endif
+
+#if defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF
+#endif
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+ if (wifi)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, LOW); // set the built-in LED ON
+#endif
+}
+
void led_set(int ledPin, bool state)
{
#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
if (ledPin == greenLED)
digitalWrite(PB9, state);
else if (ledPin == blueLED)
- digitalWrite(PB8, state);
+ digitalWrite(PB8, state);
#endif
-
+
#if defined __AVR_ATmega32U4__
- digitalWrite(ledPin, state);
+ digitalWrite(ledPin, state);
+#endif
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ if (ledPin == greenLED)
+ digitalWrite(19, state);
+ else if (ledPin == blueLED)
+ digitalWrite(18, state);
+#endif
+}
+
+int read_analog()
+{
+ int sensorValue;
+ #if defined __AVR_ATmega32U4__
+ sensorValue = analogRead(A3);
+#endif
+
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ sensorValue = analogRead(PA7);
+#endif
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+ sensorValue = analogRead(28);
+#endif
+ return(sensorValue);
+}
+
+#if !defined(ARDUINO_ARCH_MBED_RP2040) && defined(ARDUINO_ARCH_RP2040)
+bool check_for_wifi() {
+
+ pinMode(29, INPUT);
+ const float conversion_factor = 3.3f / (1 << 12);
+ uint16_t result = analogRead(29);
+// Serial.printf("ADC3 value: 0x%03x, voltage: %f V\n", result, result * conversion_factor);
+
+ if (result < 0x10) {
+ Serial.println("\nPico W detected!\n");
+ return(true);
+ }
+ else {
+ Serial.println("\nPico detected!\n");
+ return(false);
+ }
+}
#endif
+
+#if defined (ARDUINO_ARCH_MBED_RP2040) || (ARDUINO_ARCH_RP2040)
+void get_gps() {
+// Serial.println("Getting GPS data");
+ bool newData = false;
+ unsigned long start = millis();
+
+// for (unsigned long start = millis(); millis() - start < 1000;) // 5000;)
+ while ((millis() - start) < 1000) // 5000;)
+ {
+ while (Serial2.available())
+ {
+ char c = Serial2.read();
+ if (show_gps)
+ Serial.write(c); // uncomment this line if you want to see the GPS data flowing
+ if (gps.encode(c)) // Did a new valid sentence come in?
+ newData = true;
+ }
+ }
+ if (newData) {
+ Serial.print("GPS read new data in ms: ");
+ Serial.println(millis() - start);
+
+// float flon = 0.0, flat = 0.0, flalt = 0.0;
+// unsigned long age;
+// starting = millis();
+// gps.f_get_position(&flat, &flon, &age);
+
+ Serial.print(F("Location: "));
+ if (gps.location.isValid())
+ {
+ Serial.print(gps.location.lat(), 6);
+ Serial.print(F(","));
+ Serial.print(gps.location.lng(), 6);
+
+ flat = gps.location.lat();
+ flon = gps.location.lng();
+ flalt = gps.altitude.meters();
+ }
+ else
+ {
+ Serial.print(F("INVALID"));
+ }
+ Serial.print("\r\n");
+
+ } else
+// Serial.printf("GPS read no new data: %d\n", millis() - start);
+ ;
}
+#endif
diff --git a/stempayload/Payload_BME280_MPU6050_XS_Extended/payload_extension.cpp b/stempayload/Payload_BME280_MPU6050_XS_Extended/payload_extension.cpp
new file mode 100644
index 000000000..b88dd680f
--- /dev/null
+++ b/stempayload/Payload_BME280_MPU6050_XS_Extended/payload_extension.cpp
@@ -0,0 +1,71 @@
+// Use this template for adding additional sensors
+
+// put your library includes here
+#include "Adafruit_SI1145.h"
+#include
+
+// put your globals here
+Adafruit_SI1145 uv = Adafruit_SI1145();
+Adafruit_LIS3MDL lis3mdl;
+
+int uvPresent;
+int magPresent;
+
+float magRaw = 0;
+float magRawAbs = 0;
+
+// put your setup code here
+void payload_setup() {
+
+ Serial.println("Starting Si1145 sensor!");
+
+ if (! uv.begin()) {
+ Serial.println("Si1145 sensor fault");
+ uvPresent = 0;
+ } else {
+ uvPresent = 1;
+ }
+
+ Serial.println("Starting LIS3MDL sensor!");
+
+ if (! lis3mdl.begin_I2C()) {
+ Serial.println("LIS3MDL sensor fault");
+ magPresent = 0;
+ } else {
+ magPresent = 1;
+ }
+}
+
+// put your loop code here
+// Very Important: only use print, not println!!
+void payload_loop() {
+
+ if (uvPresent) {
+ Serial1.print(" SI "); // chose a 2-3 letter hint for your sensor
+ Serial1.print(uv.readVisible()); // Serial1 sends the sensor data to the Pi Zero for transmission
+ Serial1.print(" ");
+ Serial1.print(uv.readIR());
+
+ Serial.print(" SI ");
+ Serial.print(uv.readVisible()); // Serial sends the sensor data to the Serial Monitor for debugging
+ Serial.print(" ");
+ Serial.print(uv.readIR());
+ } else {
+ Serial1.print(" SI 0.0 0.0");
+ Serial.print(" SI 0.0 0.0");
+ }
+ if (magPresent) {
+ lis3mdl.read();
+ magRaw = (((lis3mdl.x + lis3mdl.y + lis3mdl.z) / 3));
+ magRawAbs = abs(magRaw);
+
+ Serial1.print(" LI ");
+ Serial1.print(magRawAbs);
+
+ Serial1.print(" LI ");
+ Serial.print(magRawAbs);
+ } else {
+ Serial1.print(" LI 0.0");
+ Serial.print(" LI 0.0");
+ }
+}
diff --git a/stempayload/payload_pico/payload_pico.h b/stempayload/payload_pico/payload_pico.h
new file mode 100644
index 000000000..2b3dba7cf
--- /dev/null
+++ b/stempayload/payload_pico/payload_pico.h
@@ -0,0 +1,485 @@
+//#include
+#include
+#include
+//#include
+#include
+//#include "afsk/status.h"
+//#include "afsk/ax5043.h"
+//#include "afsk/ax25.h"
+//#include "ax5043/spi/ax5043spi.h"
+//#include
+//#include
+//#include
+#include
+#include
+//#include "TelemEncoding.h"
+//#include
+//#include
+//#include
+#include
+//#include
+//#include
+#include "DumbTXSWS.h"
+#include
+//#include
+#include
+#include
+#include
+#include
+//#include
+#include
+#include "pico/stdlib.h" // stdlib
+#include "hardware/irq.h" // interrupts
+#include "hardware/pwm.h" // pwm
+#include "hardware/sync.h" // wait for interrupt
+//#include "RPi_Pico_TimerInterrupt.h"
+//#include
+#include "hardware/gpio.h"
+#include "hardware/adc.h"
+#include
+
+// Pico GPIO pin assignments
+#define PI_TX 0 // Serial to Pi transmit data
+#define PI_RX 1 // Serial to Pi receive data
+#define SDA 2 // I2C 1 Data
+#define SCL 3 // I2C 1 Clock
+#define SDA2 4 // I2C 2 Data
+#define SCL2 5 // I2C 2 Clock
+#define BPSK_CONTROL_A 6 // was 16 // control for Phase A to switch
+#define BPSK_CONTROL_B 7 // was 15 // control for Phase A to switch
+
+#ifdef PICO_0V1
+#define BPF_PIN 8 // BPF is installed for v0.1 Pico
+#define PI_3V3_PIN 9 // 3.3V supply used to detect Pi Zero for v0.1 Pico
+#define TX2 12 // Serial2 to ESP32-CAM transmit data
+#define RX2 13 // Serial2 to ESP32-CAM receive data
+#else
+#define TX2 8 // Serial2 to ESP32-CAM transmit data
+#define RX2 9 // Serial2 to ESP32-CAM receive data
+#define BPF_PIN 12 // BPF is installed
+#define PI_3V3_PIN 13 // 3.3V supply used to detect Pi Zero
+#endif
+
+
+#define MAIN_PB_PIN 10 // Main board PB pushbutton pin
+#define TXC_PIN 11 // Transceiver Board is present
+
+#define BPSK_PWM_A_PIN 14 // was 6 // PWM Output Phase A to switch
+#define BPSK_PWM_B_PIN 15 // was 7 // PWM Output Phase B to switch
+#define SWTX_PIN 16 // was 14 SR_FRS_05W Transmit Pico software serial port
+#define PTT_PIN 17 // SR_FRS_05W PTT Push to Talk - transmit
+#define STEM_LED_GREEN 18 // STEM board LED1 Green
+#define STEM_LED_BLUE 19 // STEM board LED2 Blue
+#define MAIN_LED_GREEN 20 // Main board LED1
+#define MAIN_LED_BLUE 21 // Main board LED1
+#define PD_PIN 22 // SR_FRS_05W PD pin - enable
+#define AUDIO_OUT_PIN 26 // 26 // SR_FRS_05W audio out pin
+#define AUDIO_IN_PIN 27 // SR_FRS_05W audio in pin
+#define TEMPERATURE_PIN 28 // Diode temperature analog pin
+
+#define PORT 8080
+#define FREQUENCY_OFFSET 0
+#define TRUE 1
+#define FALSE 0
+
+#define A_ 1
+#define B_ 2
+#define C_ 3
+#define D_ 4
+#define PLUS_X 0
+#define PLUS_Y 1
+#define BAT 2
+#define BUS 3
+#define MINUS_X 5 // 4
+#define MINUS_Y 6 // 5
+#define PLUS_Z 4 // 6
+#define MINUS_Z 7
+#define TEMP 2
+#define PRES 3
+#define ALT 4
+#define HUMI 5
+#define GYRO_X 7
+#define GYRO_Y 8
+#define GYRO_Z 9
+#define ACCEL_X 10
+#define ACCEL_Y 11
+#define ACCEL_Z 12
+#define XS1 14
+#define XS2 15
+#define XS3 16
+
+#define RSSI_ 0
+#define IHU_TEMP 2
+#define SPIN 1
+
+#define OFF - 1
+#define ON 1
+
+#define PROMPT_CALLSIGN 1
+#define PROMPT_SIM 2
+#define PROMPT_LAT 3
+#define PROMPT_RESET 4
+#define PROMPT_QUERY 5
+#define PROMPT_HELP 6
+#define PROMPT_RESTART 7
+#define PROMPT_DEBUG 8
+#define PROMPT_VOLTAGE 9
+#define PROMPT_PAYLOAD 10
+#define PROMPT_TEMP 11
+#define PROMPT_FORMAT 12
+#define PROMPT_REBOOT 13
+#define PROMPT_I2CSCAN 14
+#define PROMPT_WIFI 15
+#define PROMPT_CAMERA 16
+
+#define PAYLOAD_QUERY 1
+#define PAYLOAD_RESET 2
+#define PAYLOAD_CLEAR 3
+
+volatile int prompt = false;
+volatile int prompting = false;
+
+char serial_string[128];
+
+float get_cpu_temp();
+
+//#define WAV_DATA_LENGTH (50000 * 8)
+
+uint32_t tx_freq_hz = 434900000 + FREQUENCY_OFFSET;
+//uint8_t data[1024];
+uint32_t tx_channel = 0;
+
+//ax5043_conf_t hax5043;
+//ax25_conf_t hax25;
+
+float xOffset;
+float yOffset;
+float zOffset;
+
+int twosToInt(int val, int len);
+float toAprsFormat(float input);
+float rnd_float(double min, double max);
+void get_tlm();
+void get_tlm_fox();
+int encodeA(short int * b, int index, int val);
+int encodeB(short int * b, int index, int val);
+void config_x25();
+void trans_x25();
+int upper_digit(int number);
+int lower_digit(int number);
+void update_rs(unsigned char parity[32], unsigned char c);
+void write_little_endian(unsigned int word, int num_bytes, FILE *wav_file);
+static int init_rf();
+void test_radio();
+void config_radio();
+void send_aprs_packet();
+void read_ina219();
+void read_sensors();
+void get_tlm_ao7();
+void print_string(char *string);
+void start_payload();
+void led_set(int ledPin, bool state);
+void blink(int length);
+void blink_setup();
+short eeprom_word_read(int addr);
+void eeprom_word_write(int addr, int val);
+void read_payload();
+void start_ina219();
+void pwm_interrupt_handler();
+void start_pwm();
+void transmit_on();
+void transmit_off();
+void config_telem();
+void config_simulated_telem();
+void generate_simulated_telem();
+void process_pushbutton();
+void blinkTimes(int blinks);
+void blink_pin(int pin, int duration);
+void config_gpio();
+void start_isr();
+void read_reset_count();
+void start_button_isr();
+void payload_OK_only();
+void client_print_string(char *string);
+bool check_for_wifi();
+void check_for_browser();
+void configure_wifi();
+void transmit_cw(int freq, float duration);
+void transmit_char(char character);
+void transmit_string(char *string);
+void transmit_callsign(char *callsign);
+void parse_payload();
+void load_files();
+void show_dir();
+void serial_input();
+void get_serial_string();
+void get_serial_char();
+void get_serial_clear_buffer();
+void set_lat_lon();
+void program_radio();
+bool read_config_file();
+void write_config_file();
+void read_mode();
+void write_mode();
+void start_clockgen();
+bool TimerHandler1(struct repeating_timer *t);
+void load_sstv_image_1_as_cam_dot_jpg();
+void load_sstv_image_2_as_cam_dot_jpg();
+void get_input();
+void transmit_led(bool status);
+void reset_min_max();
+
+#ifndef STASSID
+#define STASSID "Pico"
+#define STAPSK "picoPassword"
+#endif
+
+const char* ssid = STASSID;
+const char* password = STAPSK;
+int port = 7373;
+volatile bool wifi = false;
+
+extern int Encode_8b10b[][256];
+
+//int socket_open = 0;
+//int sock = 0;
+int loop_count = 0;
+int firstTime = ON; // 0;
+long start;
+int testCount = 0;
+long time_start;
+//char cmdbuffer[1000];
+//FILE * file1;//
+#define BUFFER_SIZE 5841 //970 // (970 * 2) // * 2)
+//short int buffer[BUFFER_SIZE]; // 50000]; //BUFFER_SIZE]; // ctr is an int // 100000]; // 50000]; // 25000]; // 10240]; // was 2336400]; // max size for 10 frames count of BPSK
+byte buffer[BUFFER_SIZE]; // 50000]; //BUFFER_SIZE]; // ctr is an int // 100000]; // 50000]; // 25000]; // 10240]; // was 2336400]; // max size for 10 frames count of BPSK
+//short int buffer[(WAV_DATA_LENGTH/8)];
+//FILE *sopen(const char *program);
+char tlm_str[1000];
+char payload_str[100];
+
+#define S_RATE (200) // (8000) //(48000) // (44100)
+
+#define AFSK 1
+#define FSK 2
+#define BPSK 3
+#define SSTV 4
+#define CW 5
+
+int rpitxStatus = -1;
+
+float amplitude; // = ; // 20000; // 32767/(10%amp+5%amp+100%amp)
+float freq_Hz = 3000; // 1200
+short int sin_samples;
+short int sin_map[16];
+int STEMBoardFailure = 1;
+
+int smaller;
+int flip_ctr = 0;
+int phase = 1;
+int ctr = 0;
+int rd = 0;
+int nrd;
+void write_to_buffer(int i, int symbol, int val);
+void write_wave(int i, byte * buffer);
+void sleep(float time);
+int uart_fd;
+
+int reset_count = 0;
+float uptime_sec = 1000;
+long int uptime = 1000;
+//char call[5];
+char sim_yes[10];
+
+int mode = BPSK; // SSTV;
+volatile int new_mode;
+int bitRate, bufLen, rsFrames, payloads, rsFrameLen, dataLen, headerLen, syncBits, syncWord, parityLen, samples, frameCnt, samplePeriod;
+float sleepTime;
+unsigned int sampleTime = 0;
+int frames_sent = 0;
+int cw_id = ON;
+int vB4 = FALSE, vB5 = FALSE, vB3 = FALSE, ax5043 = FALSE, transmit = FALSE, onLed, onLedOn, onLedOff, txLed, txLedOn, txLedOff, payload = OFF;
+float voltageThreshold = 3.5, batteryVoltage = 4.5, batteryCurrent = 0, currentThreshold = 100;
+float latitude = 39.027702f, longitude = -77.078064f;
+float lat_file, long_file;
+double cpuTemp;
+int frameTime;
+
+bool debug_camera = false;
+
+float axis[3], angle[3], volts_max[3], amps_max[3], batt, rotation_speed, period, tempS, temp_max, temp_min, eclipse;
+int i2c_bus0 = OFF, i2c_bus1 = OFF, i2c_bus3 = OFF, camera = OFF, sim_mode = FALSE, SafeMode = FALSE, rxAntennaDeployed = 0, txAntennaDeployed = 0;
+double eclipse_time;
+bool i2c_1, i2c2, i2c3,i2c4, i2c5, i2c6, i2c7, i2c8;
+
+float voltage[9], current[9], sensor[17], other[3];
+char sensor_payload[500];
+
+int test_i2c_bus(int bus);
+
+//const char pythonCmd[] = "python3 -u /home/pi/CubeSatSim/python/voltcurrent.py ";
+//const char pythonCmd[] = "python3 -u /home/pi/CubeSatSim/ina219.py ";
+//char pythonStr[100], pythonConfigStr[100], busStr[10];
+int mapping[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+char src_addr[5] = "";
+char dest_addr[6] = "APCSS";
+float voltage_min[9], current_min[9], voltage_max[9], current_max[9], sensor_max[17], sensor_min[17], other_max[3], other_min[3];
+
+// Payload OK
+
+#define SEALEVELPRESSURE_HPA (1013.25)
+
+Adafruit_BME280 bme;
+MPU6050 mpu6050(Wire);
+
+long timer = 0;
+int bmePresent, mpuPresent;
+int RXLED = 17; // The RX LED has a defined Arduino pin
+int greenLED = 19;
+int blueLED = 18;
+float Sensor1 = 0.0;
+float Sensor2 = 0.0;
+float Sensor3 = 0.0;
+bool newData = false;
+void eeprom_word_write(int addr, int val);
+short eeprom_word_read(int addr);
+int first_time = true;
+int first_time_sstv = true;
+int first_read = true;
+float T2 = 27; // Temperature data point 1
+float R2 = 170; // Reading data point 1
+float T1 = 7; // Temperature data point 2
+float R1 = 184; // Reading data point 2
+int sensorValue;
+float Temp;
+float rest;
+
+unsigned int wav_position = 0;
+/*
+int pwm_counter = 0;
+int pwm_counter_max = 420;
+int pwm_amplitude = 50; //50 //100;
+int pwm_value;
+int tx_bit = 1;
+*/
+volatile unsigned long delay_time;
+bool polarity = true;
+pwm_config config;
+int bpsk_pin_slice_A;
+int bpsk_pin_slice_B;
+int bpsk_pin_slice;
+int sample_rate;
+int buffer_size;
+long micro_timer;
+long micro_timer2;
+int ready = FALSE;
+bool cw_stop = false;
+int payload_command = false;
+bool debug_mode = false;
+bool voltage_read = false;
+bool ina219_started = false;
+bool camera_detected = false;
+bool rotate_flag = true;
+
+int led_builtin_pin;
+
+#define PRESSED 0
+#define HELD 0
+#define RELEASED 1
+int pb_state = RELEASED;
+int mode_count = 0;
+unsigned long pb_press_start;
+const char sstv1_filename[] = "/sstv_image_1_320_x_240.jpg";
+const char sstv2_filename[] = "/sstv_image_2_320_x_240.jpg";
+
+//bool TimerHandler0(struct repeating_timer *t);
+//RPI_PICO_Timer ITimer0(0);
+//RPI_PICO_Timer ITimer1(1);
+
+bool timer0_on = false;
+volatile int timer_counter;
+bool filter_present = false; // BPF installation state for transmitter
+bool sr_frs_present = false; // SR_FRS FM transmitter module state
+
+char callsign[20];
+int morse_timing = 60; // ms for a dit
+int morse_freq = 1800; // Hz
+//int morse_table[44][6] = { // 0-9, A-Z only by (ASCII - 48)
+byte morse_table[44][6] = { // 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
+};
+
+
+/*
+ * TelemEncoding.h
+ *
+ * Created on: Feb 3, 2014
+ * Author: fox
+ */
+
+#ifndef TELEMENCODING_H_
+#define TELEMENCODING_H_
+
+/*
+void update_rs(
+ unsigned char parity[32], // 32-byte encoder state; zero before each frame
+ unsigned char c // Current data byte to update
+);
+*/
+
+#define CHARACTER_BITS 10
+#define CHARACTERS_PER_LONGWORD 3
+#define CHARACTER_MASK ((1<.
+ */
+
+// This code is an Arduino sketch for the Raspberry Pi Pico
+// based on the Raspberry Pi Code
+
+//#define PICO_0V1 // define for Pico v0.1 hardware
+
+#include "payload_pico.h"
+#include "DumbTXSWS.h"
+#include
+//#include
+#include
+#include
+//#include
+#include
+//#include
+#include
+#include "pico/stdlib.h" // stdlib
+//#include "hardware/irq.h" // interrupts
+//#include "hardware/pwm.h" // pwm
+//#include "hardware/sync.h" // wait for interrupt
+//#include "RPi_Pico_ISR_Timer.h"
+//#include "RPi_Pico_TimerInterrupt.h"
+#include
+#include "hardware/gpio.h"
+#include "hardware/adc.h"
+//#include "SSTV-Arduino-Scottie1-Library.h"
+#include "LittleFS.h"
+//#include
+//#include "picosstvpp.h"
+#include "pico/bootrom.h"
+#include "hardware/watchdog.h"
+#include
+#include
+
+// jpg files to be stored in flash storage on Pico (FS 512kB setting)
+//#include "sstv1.h"
+//#include "sstv2.h"
+
+//Adafruit_INA219 ina219_1_0x40;
+//Adafruit_INA219 ina219_1_0x41(0x41);
+//Adafruit_INA219 ina219_1_0x44(0x44);
+//Adafruit_INA219 ina219_1_0x45(0x45);
+//Adafruit_INA219 ina219_2_0x40(0x40);
+//Adafruit_INA219 ina219_2_0x41(0x41);
+//Adafruit_INA219 ina219_2_0x44(0x44);
+//Adafruit_INA219 ina219_2_0x45(0x45);
+
+//Adafruit_SI5351 clockgen = Adafruit_SI5351();
+TinyGPSPlus gps;
+
+unsigned long micros3;
+bool show_gps = true; // set to false to not see all GPS messages
+volatile int skip = 0;
+
+//WiFiServer server(port);
+//WiFiClient client;
+WiFiClient net;
+MQTTClient client;
+
+#define PICO_W // define if Pico W board. Otherwise, compilation fail for Pico or runtime fail if compile as Pico W
+
+//#define APRS_VHF
+
+byte green_led_counter = 0;
+//char call[] = "AMSAT"; // put your callsign here
+
+//extern bool get_camera_image(bool debug);
+//extern bool start_camera();
+
+float rand_float(float lower, float upper) {
+
+ return (float)(random(lower*100, upper*100)/100.0);
+}
+
+void setup() {
+
+ set_sys_clock_khz(133000, true);
+
+ Serial.begin(115200);
+
+ delay(10000);
+
+ LittleFS.begin();
+// LittleFS.format(); // only format if files of size 0 keep showing up
+//#ifdef APRS_VHF
+// mode = AFSK; // force to APRS
+//#else
+// read_mode();
+//#endif
+
+// new_mode = mode;
+
+// pinMode(LED_BUILTIN, OUTPUT);
+// blinkTimes(1);
+
+/// sleep(5.0);
+
+// otherwise, run CubeSatSim Pico code
+
+ Serial.println("CubeSatSim Pico Payload v0.4 starting...\n");
+
+/**/
+ if (check_for_wifi()) {
+ wifi = true;
+ led_builtin_pin = LED_BUILTIN; // use default GPIO for Pico W
+ pinMode(LED_BUILTIN, OUTPUT);
+// configure_wifi();
+ } else {
+ led_builtin_pin = 25; // manually set GPIO 25 for Pico board
+// pinMode(25, OUTPUT);
+ pinMode(led_builtin_pin, OUTPUT);
+ }
+/**/
+
+ config_gpio();
+
+ Serial.print("Pi Zero present, so running Payload OK code.");
+ sr_frs_present = true;
+// program_radio();
+ start_payload();
+
+ pinMode(15, INPUT_PULLUP);
+ pinMode(22, OUTPUT);
+ digitalWrite(22, 1);
+ pinMode(17, OUTPUT);
+ digitalWrite(17, 1);
+
+ prompt = false;
+ prompting = false;
+
+}
+
+void loop() {
+
+ payload_OK_only();
+ sleep(1.0);
+ Serial.print("Squelch: ");
+ Serial.println(digitalRead(15));
+// Serial.println(" ");
+ prompt_for_input();
+}
+
+void config_gpio() {
+
+ pinMode(0, INPUT);
+ pinMode(1, INPUT);
+
+ // set all Pico GPIO connected pins to input
+ for (int i = 6; i < 22; i++) {
+ pinMode(i, INPUT);
+ }
+ pinMode(26, INPUT);
+ pinMode(27, INPUT);
+ pinMode(28, INPUT);
+}
+
+void program_radio() {
+ if (sr_frs_present) {
+ Serial.println("Programming SR_FRS!");
+
+ pinMode(PD_PIN, OUTPUT);
+ pinMode(PTT_PIN, OUTPUT);
+ digitalWrite(PD_PIN, HIGH); // enable SR_FRS
+ digitalWrite(PTT_PIN, HIGH); // stop transmit
+
+ DumbTXSWS mySerial(SWTX_PIN); // TX pin
+ mySerial.begin(9600);
+
+ for (int i = 0; i < 5; i++) {
+ sleep(0.5); // delay(500);
+#ifdef APRS_VHF
+ mySerial.println("AT+DMOSETGROUP=0,144.3900,144.3900,0,3,0,0\r"); // can change to 144.39 for standard APRS
+// mySerial.println("AT+DMOSETGROUP=0,145.0000,145.0000,0,3,0,0\r"); // can change to 145 for testing ASPRS
+#else
+ mySerial.println("AT+DMOSETGROUP=0,435.1000,434.9900,0,3,0,0\r"); // squelch set to 3
+#endif
+ sleep(0.5);
+ mySerial.println("AT+DMOSETMIC=8,0\r"); // was 8
+
+ }
+ }
+#ifdef APRS_VHF
+ Serial.println("Programming FM tx 144.39, rx on 144.39 MHz");
+#else
+ Serial.println("Programming FM tx 434.9, rx on 435.0 MHz");
+#endif
+// digitalWrite(PTT_PIN, LOW); // transmit carrier for 0.5 sec
+// sleep(0.5);
+// digitalWrite(PTT_PIN, HIGH);
+ digitalWrite(PD_PIN, LOW); // disable SR_FRS
+ pinMode(PD_PIN, INPUT);
+ pinMode(PTT_PIN, INPUT);
+}
+
+bool read_config_file() {
+ char buff[255];
+ // Open configuration file with callsign and reset count
+ Serial.println("Reading config file");
+ File config_file = LittleFS.open("/payload.cfg", "r");
+// FILE * config_file = fopen("/payload.cfg", "r");
+ if (!config_file) {
+ return(false);
+ }
+
+// char * cfg_buf[100];
+ config_file.read((uint8_t *)buff, 255);
+// sscanf(buff, "%d", &cnt);
+ sscanf(buff, "%f %f %f", xOffset, yOffset, zOffset);
+ config_file.close();
+// if (debug_mode)
+ Serial.printf("Config file /payload.cfg contains %f %f %f\n", xOffset, yOffset, zOffset);
+
+ config_file.close();
+
+// write_config_file();
+
+ return(true);
+}
+
+void write_config_file() {
+ Serial.println("Writing /payload.cfg file");
+ char buff[255];
+ File config_file = LittleFS.open("/payload.cfg", "w+");
+
+ sprintf(buff, "%f %f %f", xOffset, yOffset, zOffset);
+ Serial.println("Writing string ");
+// if (debug_mode)
+ print_string(buff);
+ config_file.write(buff, strlen(buff));
+
+ config_file.close();
+// Serial.println("Write complete");
+
+}
+
+void read_sensors()
+{
+
+}
+
+void print_string(char *string)
+{
+ int count = 0;
+ while ((count < 250) && (string[count] != 0))
+ {
+ Serial.print(string[count++]);
+ }
+ Serial.println(" ");
+}
+
+void start_payload() {
+
+//#ifdef APRS_VHF
+// Serial2.setRX(9);
+// Serial2.setRX(9);
+// Serial2.setRX(1);
+ delay(100);
+// Serial2.setTX(8);
+// Serial2.setTX(8);
+// Serial2.setRX(0);
+
+/*
+ delay(100);
+ Serial1.setRX(1);
+ delay(100);
+ Serial1.setTX(0);
+ delay(10);
+*/
+/*
+ Serial1.begin(115200); // serial to Pi
+
+ Serial.println("Starting Serial1 for payload");
+
+ Serial2.begin(115200); // serial from GPS
+
+ Serial.println("Starting Serial2 for GPS");
+*/
+//#else
+ Serial1.setRX(1);
+ delay(100);
+ Serial1.setTX(0);
+ delay(100);
+ Serial1.begin(115200); // Pi UART faster speed
+
+ Serial2.begin(9600); // serial from GPS - some GPS modules need 115200
+
+ Serial.println("Starting Serial2 for GPS");
+//#endif
+
+ Serial.println("Starting payload!");
+
+ blink_setup();
+/*
+ blink(500);
+ sleep(0.25); // delay(250);
+ blink(500);
+ sleep(0.25); // delay(250);
+ led_set(greenLED, HIGH);
+ sleep(0.25); // delay(250);
+ led_set(greenLED, LOW);
+ led_set(blueLED, HIGH);
+ sleep(0.25); // delay(250);
+ led_set(blueLED, LOW);
+*/
+
+ if (bme.begin()) {
+ bmePresent = 1;
+ } else {
+ Serial.println("Could not find a valid BME280 sensor, check wiring!");
+ bmePresent = 0;
+ }
+
+ Wire.begin();
+ Wire.beginTransmission(0x68);
+ if (Wire.endTransmission() != 0) {
+ Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
+ mpuPresent = 0;
+ }
+ else {
+ mpuPresent = 1;
+ mpu6050.begin();
+
+
+// if ((read_config_file()) && (payload_command != PAYLOAD_RESET))
+ if (false)
+ {
+ Serial.println("Reading gyro offsets from config file\n");
+ mpu6050.setGyroOffsets(xOffset, yOffset, zOffset);
+
+ }
+
+ else
+ {
+ payload_command = false;
+
+ Serial.println("Calculating gyro offsets and storing in EEPROM\n");
+
+ mpu6050.calcGyroOffsets(true);
+/*
+ eeprom_word_write(0, 0xA07);
+ eeprom_word_write(1, (int)(mpu6050.getGyroXoffset() * 100.0) + 0.5);
+ eeprom_word_write(2, (int)(mpu6050.getGyroYoffset() * 100.0) + 0.5);
+ eeprom_word_write(3, (int)(mpu6050.getGyroZoffset() * 100.0) + 0.5);
+*/
+// flag = 0xA07;
+ xOffset = mpu6050.getGyroXoffset();
+ yOffset = mpu6050.getGyroYoffset();
+ zOffset = mpu6050.getGyroZoffset();
+
+ write_config_file();
+ }
+ }
+
+ if (!(payload = bmePresent || mpuPresent))
+ Serial.println("No payload sensors detected");
+
+ pinMode(greenLED, OUTPUT);
+ pinMode(blueLED, OUTPUT);
+
+}
+
+void payload_OK_only()
+{
+ payload_str[0] = '\0'; // clear the payload string
+
+ if ((Serial.available() > 0)|| first_time == true) // commented back in
+ {
+ blink(50);
+ char result = Serial.read();
+ char header[] = "OK BME280 ";
+ char str[100];
+
+ strcpy(payload_str, header);
+// print_string(str);
+ if (bmePresent)
+// sprintf(str, "%4.2f %6.2f %6.2f %5.2f ",
+ sprintf(str, "%.1f %.2f %.1f %.2f ",
+ bme.readTemperature(), bme.readPressure() / 100.0, bme.readAltitude(SEALEVELPRESSURE_HPA), bme.readHumidity());
+ else
+ sprintf(str, "OK BME280 0.0 0.0 0.0 0.0 ");
+ strcat(payload_str, str);
+
+ if (mpuPresent) {
+// print_string(payload_str);
+ mpu6050.update();
+
+// sprintf(str, " MPU6050 %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f ",
+ sprintf(str, " MPU6050 %.1f %.1f %.1f %.1f %.1f %.1f ",
+ mpu6050.getGyroX(), mpu6050.getGyroY(), mpu6050.getGyroZ(), mpu6050.getAccX(), mpu6050.getAccY(), mpu6050.getAccZ());
+
+ strcat(payload_str, str);
+// print_string(payload_str);
+ }
+ if (result == 'R') {
+ Serial.println("OK");
+ delay(100);
+// first_time = true;
+ start_payload();
+// setup();
+ }
+ else if (result == 'g') {
+ show_gps = !show_gps;
+ }
+ else if (result == 'C') {
+ Serial.println("Clearing stored gyro offsets in EEPROM\n");
+ EEPROM.put(0, (float)0.0);
+// first_time = true;
+ start_payload();
+// setup();
+ }
+ if ((result == '?') || first_time == true) // commented back in
+ if (true)
+ {
+
+// first_time = false;
+ if (bmePresent) {
+ Serial.print("OK BME280 ");
+ Serial.print(bme.readTemperature());
+ Serial.print(" ");
+ Serial.print(bme.readPressure() / 100.0F);
+ Serial.print(" ");
+ Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
+ Serial.print(" ");
+ Serial.print(bme.readHumidity());
+ } else
+ {
+ Serial.print("OK BME280 0.0 0.0 0.0 0.0");
+ }
+ if (mpuPresent) {
+ mpu6050.update();
+
+ Serial.print(" MPU6050 ");
+ Serial.print(mpu6050.getGyroX());
+ Serial.print(" ");
+ Serial.print(mpu6050.getGyroY());
+ Serial.print(" ");
+ Serial.print(mpu6050.getGyroZ());
+
+ Serial.print(" ");
+ Serial.print(mpu6050.getAccX());
+ Serial.print(" ");
+ Serial.print(mpu6050.getAccY());
+ Serial.print(" ");
+ Serial.print(mpu6050.getAccZ());
+ } else
+ {
+ Serial.print(" MPU6050 0.0 0.0 0.0 0.0 0.0 0.0");
+ }
+
+ sensorValue = analogRead(TEMPERATURE_PIN);
+ //Serial.println(sensorValue);
+ Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1));
+
+
+ Serial.print(" GPS ");
+ Serial.print(Sensor1,4);
+ Serial.print(" ");
+ Serial.print(Sensor2,4);
+ Serial.print(" ");
+ Serial.print(Sensor3,2);
+ Serial.print(" AN ");
+ Serial.println(sensorValue); // ,0);
+
+ if (mpuPresent) {
+ float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ());
+ float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ());
+// Serial.print(rotation);
+// Serial.print(" ");
+// Serial.println(acceleration);
+
+ if (acceleration > 1.2)
+ led_set(greenLED, HIGH);
+ else
+ led_set(greenLED, LOW);
+
+ if (rotation > 5)
+ led_set(blueLED, HIGH);
+ else
+ led_set(blueLED, LOW);
+ }
+ }
+ }
+
+// Serial2.print("b");
+ delay(250);
+
+// if (Serial2.available() > 0) {
+ if (true) {
+/*
+ while (Serial2.available() > 0) // read GPS
+ Serial.write(Serial2.read());
+*/
+// For one second we parse GPS data and report some key values
+ newData = false;
+
+ unsigned long starting = millis();
+ for (unsigned long start = millis(); millis() - start < 1000;) // 5000;)
+ {
+ while (Serial2.available())
+ {
+ char c = Serial2.read();
+ if (show_gps)
+ Serial.write(c); // uncomment this line if you want to see the GPS data flowing
+ if (gps.encode(c)) // Did a new valid sentence come in?
+ newData = true;
+ }
+ }
+ if (newData)
+ {
+ Serial.printf("GPS read new data in ms: %d\n", millis() - start);
+ float flon = 0.0, flat = 0.0, flalt = 0.0;
+ unsigned long age;
+ starting = millis();
+// gps.f_get_position(&flat, &flon, &age);
+
+ Serial.print(F("Location: "));
+ if (gps.location.isValid())
+ {
+ Serial.print(gps.location.lat(), 6);
+ Serial.print(F(","));
+ Serial.print(gps.location.lng(), 6);
+
+ flat = gps.location.lat();
+ flon = gps.location.lng();
+ flalt = gps.altitude.meters();
+ }
+ else
+ {
+ Serial.print(F("INVALID"));
+ }
+ Serial.print("\r\n");
+
+ Sensor1 = flat;
+ Sensor2 = flon;
+ Sensor3 = flalt; // (float) gps.altitude.meters();
+// Serial.printf("New GPS data: %f %f %f ms: %d\n", Sensor1, Sensor2, Sensor3, millis() - start);
+ } else
+// Serial.printf("GPS read no new data: %d\n", millis() - start);
+ ;
+
+ blink(50);
+/*
+ if (Serial1.available()) {
+ char result = Serial1.read();
+// Serial1.println(result);
+// Serial.println(result); // don't print read result
+
+ if (result == 'R') {
+ Serial1.println("OK");
+ delay(100);
+ first_read = true;
+ start_payload();
+// setup();
+ }
+ }
+*/
+// if (result == '?')
+ if (true) // always send payload data over serial
+ {
+ if (bmePresent) {
+// Serial1.print("START_FLAGOK BME280 ");
+ Serial1.print(sensor_start_flag);
+ Serial1.print("OK BME280 ");
+ Serial1.print(bme.readTemperature());
+ Serial1.print(" ");
+ Serial1.print(bme.readPressure() / 100.0F);
+ Serial1.print(" ");
+ Serial1.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
+ Serial1.print(" ");
+ Serial1.print(bme.readHumidity());
+ } else
+ {
+// Serial1.print("START_FLAGOK BME280 0.0 0.0 0.0 0.0");
+ Serial1.print(sensor_start_flag);
+ Serial1.print("OK BME280 0.0 0.0 0.0 0.0");
+ }
+ if (mpuPresent) {
+ mpu6050.update();
+
+ Serial1.print(" MPU6050 ");
+ Serial1.print(mpu6050.getGyroX());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getGyroY());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getGyroZ());
+
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccX());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccY());
+ Serial1.print(" ");
+ Serial1.print(mpu6050.getAccZ());
+
+ } else
+ {
+ Serial1.print(" MPU6050 0.0 0.0 0.0 0.0 0.0 0.0");
+ }
+
+ sensorValue = analogRead(TEMPERATURE_PIN);
+ //Serial.println(sensorValue);
+ Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1));
+
+ Serial1.print(" GPS ");
+ Serial1.print(Sensor1,4);
+ Serial1.print(" ");
+ Serial1.print(Sensor2,4);
+ Serial1.print(" ");
+ Serial1.print(Sensor3,2);
+ Serial1.print(" AN ");
+ Serial1.print(sensorValue); //,0);
+// Serial1.println("END_FLAG");
+ Serial1.println(sensor_end_flag);
+
+ blink(50);
+ delay(50);
+ blink(50);
+
+ if (mpuPresent) {
+ float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ());
+ float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ());
+// Serial.print(rotation);
+// Serial.print(" ");
+// Serial.println(acceleration);
+
+ if (first_read == true) {
+ first_read = false;
+ rest = acceleration;
+ }
+
+ if (acceleration > 1.2 * rest)
+ led_set(greenLED, HIGH);
+ else
+ led_set(greenLED, LOW);
+
+ if (rotation > 5)
+ led_set(blueLED, HIGH);
+ else
+ led_set(blueLED, LOW);
+ }
+ }
+ }
+
+ delay(100);
+}
+
+/**/
+/*
+void eeprom_word_write(int addr, int val)
+{
+ EEPROM.write(addr * 2, lowByte(val));
+ EEPROM.write(addr * 2 + 1, highByte(val));
+}
+
+short eeprom_word_read(int addr)
+{
+ return ((EEPROM.read(addr * 2 + 1) << 8) | EEPROM.read(addr * 2));
+}
+*/
+
+void blink_setup()
+{
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ // initialize digital pin PB1 as an output.
+ pinMode(PC13, OUTPUT);
+ pinMode(PB9, OUTPUT);
+ pinMode(PB8, OUTPUT);
+#endif
+
+#if defined __AVR_ATmega32U4__ || ARDUINO_ARCH_RP2040
+ pinMode(RXLED, OUTPUT); // Set RX LED as an output
+ // TX LED is set as an output behind the scenes
+ pinMode(greenLED, OUTPUT);
+ pinMode(blueLED,OUTPUT);
+#endif
+}
+
+void blink(int length)
+{
+ if (wifi)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON
+
+ sleep(length/1000.0); // delay(length); // wait for a lenth of time
+
+ if (wifi)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF
+ else
+ digitalWrite(led_builtin_pin, LOW); // set the built-in LED OFF
+}
+
+void led_set(int ledPin, bool state)
+{
+#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4)
+ if (ledPin == greenLED)
+ digitalWrite(PB9, state);
+ else if (ledPin == blueLED)
+ digitalWrite(PB8, state);
+#endif
+
+#if defined __AVR_ATmega32U4__ || ARDUINO_ARCH_RP2040
+ digitalWrite(ledPin, state);
+#endif
+}
+
+
+void sleep(float timer) { // sleeps for intervals more than 0.01 milli seconds
+
+ unsigned long time_us = (unsigned long)(timer * 1000000.0);
+ unsigned long startSleep = micros();
+ while ((micros() - startSleep) < time_us) {
+// busy_wait_us(100);
+ delayMicroseconds(100);
+ }
+}
+
+void blinkTimes(int blinks) {
+ for (int i = 0; i < blinks; i++) {
+ digitalWrite(MAIN_LED_GREEN, LOW);
+
+ if (wifi)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF
+ else
+ digitalWrite(led_builtin_pin, LOW); // set the built-in LED OFF
+
+ sleep(0.1);
+ digitalWrite(MAIN_LED_GREEN, HIGH);
+
+ if (wifi)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON
+
+ sleep(0.1);
+ }
+}
+
+void blinkFastTimes(int blinks) {
+ for (int i = 0; i < blinks; i++) {
+ digitalWrite(MAIN_LED_GREEN, LOW);
+
+ if (wifi)
+ digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF
+ else
+ digitalWrite(led_builtin_pin, LOW); // set the built-in LED OFF
+
+ sleep(0.05);
+ digitalWrite(MAIN_LED_GREEN, HIGH);
+
+ if (wifi)
+ digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON
+ else
+ digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON
+
+ sleep(0.05);
+ }
+}
+
+void blink_pin(int pin, int duration) {
+
+ digitalWrite(pin, HIGH);
+ sleep((float)duration / 1000.00);
+ digitalWrite(pin, LOW);
+
+}
+
+
+bool check_for_wifi() {
+
+#ifndef PICO_W
+
+ Serial.println("WiFi disabled in software");
+ return(false); // skip check if not Pico W board or compilation will fail
+
+#endif
+
+// stdio_init_all();
+
+// adc_init();
+// adc_gpio_init(29);
+ pinMode(29, INPUT);
+// adc_select_input(3);
+ const float conversion_factor = 3.3f / (1 << 12);
+// uint16_t result = adc_read();
+ uint16_t result = analogRead(29);
+// Serial.printf("ADC3 value: 0x%03x, voltage: %f V\n", result, result * conversion_factor);
+
+// if (result < 0x100) {
+ if (result < 0x10) {
+ Serial.println("\nPico W detected!\n");
+ return(true);
+ }
+ else {
+ Serial.println("\nPico detected!\n");
+ return(false);
+ }
+}
+
+void show_dir() {
+ LittleFS.begin();
+ Dir dir = LittleFS.openDir("/");
+// or Dir dir = LittleFS.openDir("/data");
+ Serial.println("FS directory:");
+ while (dir.next()) {
+ Serial.print(dir.fileName());
+ if(dir.fileSize()) {
+ File f = dir.openFile("r");
+ Serial.print(" ");
+ Serial.println(f.size());
+ }
+ }
+ Serial.println(">");
+}
+
+void serial_input() {
+
+ if (prompt == false) { // only query if not in the middle of prompting
+
+ if (Serial.available() > 0) { // check for user input on serial port
+
+// blink(50);
+ char result = Serial.read();
+
+ if ((result != '\n') && (result != '\r')) {
+
+ Serial.println(result);
+
+ switch(result) {
+ case 'h':
+ case 'H':
+ // Serial.println("Help");
+ prompt = PROMPT_HELP;
+ break;
+
+ case 'a':
+ case 'A':
+ Serial.println("Change to AFSK/APRS mode");
+ new_mode = AFSK;
+ break;
+
+ case 'm':
+ case 'M':
+ Serial.println("Change to CW mode");
+ new_mode = CW;
+ break;
+
+ case 'F':
+ Serial.println("Formatting flash memory");
+ prompt = PROMPT_FORMAT;
+ break;
+ case 'f':
+ Serial.println("Change to FSK mode");
+ new_mode = FSK;
+ break;
+
+ case 'b':
+ case 'B':
+ Serial.println("Change to BPSK mode");
+ new_mode = BPSK;
+ break;
+
+ case 's':
+ Serial.println("Change to SSTV mode");
+ new_mode = SSTV;
+ break;
+
+ case 'S':
+ Serial.println("I2C scan");
+ prompt = PROMPT_I2CSCAN;
+ break;
+
+ case 'i':
+ case 'I':
+ Serial.println("Restart CubeSatsim software");
+ prompt = PROMPT_RESTART;
+ break;
+
+ case 'c':
+ Serial.println("Change the CALLSIGN");
+ prompt = PROMPT_CALLSIGN;
+ break;
+
+ case 'C':
+ Serial.println("Debug camera");
+ debug_camera = true;
+ prompt = PROMPT_CAMERA;
+ break;
+
+ case 't':
+ case 'T':
+ Serial.println("Change the Simulated Telemetry");
+ prompt = PROMPT_SIM;
+ break;
+
+ case 'p':
+ case 'P':
+ Serial.println("Reset payload EEPROM settings");
+ prompt = PROMPT_PAYLOAD;
+ break;
+
+ case 'r':
+ case 'R':
+ Serial.println("Change the Resets Count");
+ prompt = PROMPT_RESET;
+ break;
+
+ case 'o':
+ case 'O':
+ Serial.println("Read diode temperature");
+ prompt = PROMPT_TEMP;
+ break;
+
+ case 'l':
+ case 'L':
+ Serial.println("Change the Latitude and Longitude");
+ prompt = PROMPT_LAT;
+ break;
+
+ case 'v':
+ case 'V':
+ Serial.println("Read INA219 voltage and current");
+ prompt = PROMPT_VOLTAGE;
+ break;
+
+ case '?':
+ Serial.println("Query payload sensors");
+ prompt = PROMPT_QUERY;
+ break;
+
+ case 'd':
+ Serial.println("Change debug mode");
+ prompt = PROMPT_DEBUG;
+ break;
+
+ case 'w':
+ Serial.println(wifi);
+ Serial.println("Connect to WiFi");
+ prompt = PROMPT_WIFI;
+ break;
+
+ default:
+ Serial.println("Not a command\n");
+
+ break;
+ }
+ }
+ }
+ }
+}
+
+void prompt_for_input() {
+ float float_result;
+
+ if (!prompting) {
+ prompting = true;
+
+ while (Serial.available() > 0) // clear any characters in serial input buffer
+ Serial.read();
+
+ switch(prompt) {
+
+ case PROMPT_HELP:
+ Serial.println("\nChange settings by typing the letter:");
+ Serial.println("h Help info");
+ Serial.println("F Format flash memory");
+ Serial.println("S I2C scan");
+ Serial.println("i Restart");
+ Serial.println("p Reset payload and stored EEPROM values");
+ Serial.println("? Query sensors");
+ Serial.println("o Read diode temperature");
+ Serial.println("d Change debug mode");
+ Serial.println("w Connect to WiFi\n");
+
+// Serial.printf("Software version v0.39 \nConfig file /payload.cfg contains %s %d %f %f %s\n\n", callsign, reset_count, lat_file, long_file, sim_yes);
+/*
+ switch(mode) {
+
+ case(AFSK):
+ Serial.println("AFSK mode");
+ break;
+
+ case(FSK):
+ Serial.println("FSK mode");
+ break;
+
+ case(BPSK):
+ Serial.println("BPSK mode");
+ break;
+
+ case(SSTV):
+ Serial.println("SSTV mode");
+ break;
+
+ case(CW):
+ Serial.println("CW mode");
+ break;
+ }
+*/
+ break;
+
+ case PROMPT_REBOOT:
+ Serial.println("Rebooting...");
+ Serial.flush();
+ watchdog_reboot (0, SRAM_END, 500); // restart Pico
+ sleep(20.0);
+ break;
+
+ case PROMPT_FORMAT:
+ LittleFS.format();
+// Serial.println("Reboot or power cycle to restart the CubeSatSim");
+ // while (1) ; // infinite loop
+ Serial.println("Rebooting...");
+ Serial.flush();
+ watchdog_reboot (0, SRAM_END, 500); // restart Pico
+ sleep(20.0);
+ break;
+
+ case PROMPT_PAYLOAD:
+ Serial.println("Resetting the Payload");
+ payload_command = PAYLOAD_RESET;
+ start_payload();
+ break;
+
+ case PROMPT_WIFI:
+ Serial.println(wifi);
+ if (wifi) {
+ char ssid[30], pass[30];
+ Serial.println("Enter the credentials for your WiFi network");
+
+ Serial.print("Enter WiFi SSID: ");
+ get_serial_string();
+
+ print_string(serial_string);
+
+ if (strlen(serial_string) > 0) {
+ strcpy(ssid, serial_string);
+ Serial.print("Enter WiFi password: ");
+ get_serial_string();
+ if (strlen(serial_string) > 0) {
+ strcpy(pass, serial_string);
+ Serial.println("Connecting to Wifi");
+// Serial.printf("%s%s\n",ssid, pass);
+
+ WiFi.begin(ssid, pass);
+
+ unsigned int elapsed_timer = (unsigned int) millis();
+ while ((WiFi.status() != WL_CONNECTED) && ((millis() - elapsed_timer) < 10000)) {
+ Serial.print(".");
+ delay(500);
+ }
+ if (((millis() - elapsed_timer) > 10000))
+ Serial.println("Failed to connect!");
+ else
+ Serial.println("Connected to WiFi!");
+ } else
+ Serial.println("No password entered.");
+ } else
+ Serial.println("No SSID entered.");
+ } else
+ Serial.println("WiFi not available");
+
+ break;
+
+ case PROMPT_I2CSCAN:
+ Serial.print("I2C scan");
+
+// --------------------------------------
+// i2c_scanner
+//
+// Version 1
+// This program (or code that looks like it)
+// can be found in many places.
+// For example on the Arduino.cc forum.
+// The original author is not know.
+// Version 2, Juni 2012, Using Arduino 1.0.1
+// Adapted to be as simple as possible by Arduino.cc user Krodal
+// Version 3, Feb 26 2013
+// V3 by louarnold
+// Version 4, March 3, 2013, Using Arduino 1.0.3
+// by Arduino.cc user Krodal.
+// Changes by louarnold removed.
+// Scanning addresses changed from 0...127 to 1...119,
+// according to the i2c scanner by Nick Gammon
+// https://www.gammon.com.au/forum/?id=10896
+// Version 5, March 28, 2013
+// As version 4, but address scans now to 127.
+// A sensor seems to use address 120.
+// Version 6, November 27, 2015.
+// Added waiting for the Leonardo serial communication.
+//
+//
+// This sketch tests the standard 7-bit addresses
+// Devices with higher bit address might not be seen properly.
+//
+
+
+{
+ byte error, address;
+ int nDevices;
+
+ Serial.println("Scanning I2C Bus 1");
+
+ nDevices = 0;
+ for(address = 1; address < 127; address++ )
+ {
+ // The i2c_scanner uses the return value of
+ // the Write.endTransmisstion to see if
+ // a device did acknowledge to the address.
+ Wire.beginTransmission(address);
+ error = Wire.endTransmission();
+
+ if (error == 0)
+ {
+ Serial.print("I2C device found at bus 1 address 0x");
+ if (address<16)
+ Serial.print("0");
+ Serial.print(address,HEX);
+ Serial.println(" !");
+
+ nDevices++;
+ }
+ else if (error==4)
+ {
+ Serial.print("Unknown error at bus 1 address 0x");
+ if (address<16)
+ Serial.print("0");
+ Serial.println(address,HEX);
+ }
+ }
+ if (nDevices == 0)
+ Serial.println("No I2C devices found on bus 1\n");
+ else
+ Serial.println("done\n");
+
+ delay(5000); // wait 5 seconds for next scan
+
+ Serial.println("Scanning I2C Bus 2");
+
+ nDevices = 0;
+ for(address = 1; address < 127; address++ )
+ {
+ // The i2c_scanner uses the return value of
+ // the Write.endTransmisstion to see if
+ // a device did acknowledge to the address.
+
+ Wire1.beginTransmission(address);
+ error = Wire1.endTransmission();
+
+ if (error == 0)
+ {
+ Serial.print("I2C device found at bus 2 address 0x");
+ if (address<16)
+ Serial.print("0");
+ Serial.print(address,HEX);
+ Serial.println(" !");
+
+ nDevices++;
+ }
+ else if (error==4)
+ {
+ Serial.print("Unknown error at bus 2 address 0x");
+ if (address<16)
+ Serial.print("0");
+ Serial.println(address,HEX);
+ }
+ }
+ if (nDevices == 0)
+ Serial.println("No I2C devices found on bus 2\n");
+ else
+ Serial.println("done\n");
+
+}
+ Serial.println("complete");
+ break;
+
+
+
+/*
+
+ case PROMPT_SIM:
+ if (sim_mode == TRUE)
+ Serial.println("Simulted Telemetry mode is currently on");
+ else
+ Serial.println("Simulted Telemetry mode is currently off");
+ Serial.println("Do you want Simulated Telemetry on (y/n)");
+ get_serial_char();
+ if ((serial_string[0] == 'y') || (serial_string[0] == 'Y')) {
+ Serial.println("Setting Simulated telemetry to on");
+ reset_min_max();
+ config_simulated_telem();
+ write_config_file();
+ } else if ((serial_string[0] == 'n') || (serial_string[0] == 'N')) {
+ Serial.println("Setting Simulated telemetry to off");
+ reset_min_max();
+ sim_mode = false;
+ if (!ina219_started)
+ start_ina219();
+ write_config_file();
+ } else
+ Serial.println("No change to Simulated Telemetry mode");
+ break;
+
+ case PROMPT_LAT:
+
+ Serial.println("Changing the latitude and longitude - only used for APRS telemetry");
+ Serial.println("Hitting return keeps the current value.");
+
+ Serial.print("Current value of latitude is ");
+ Serial.println(latitude);
+ Serial.println("Enter latitude (decimal degrees, positive is north): ");
+ get_serial_string();
+ float_result = atof(serial_string);
+ if (float_result != 0.0) {
+ Serial.print("Latitude updated to ");
+ Serial.println(float_result);
+ latitude = float_result;
+ } else
+ Serial.println("Latitude not updated");
+
+ get_serial_clear_buffer();
+ Serial.print("Current value of longitude is ");
+ Serial.println(longitude);
+ Serial.println("Enter longitude (decimal degrees, positive is east): ");
+ get_serial_string();
+ float_result = atof(serial_string);
+ if (float_result != 0.0) {
+ Serial.print("Longitude updated to ");
+ Serial.println(float_result);
+ longitude = float_result;
+ } else
+ Serial.println("Longitude not updated");
+
+ write_config_file();
+ if (mode == AFSK)
+ set_lat_lon();
+
+ break;
+
+ case PROMPT_QUERY:
+ Serial.println("Querying payload sensors");
+ payload_command = PAYLOAD_QUERY;
+ break;
+
+ case PROMPT_CAMERA:
+ show_dir();
+ get_camera_image(debug_camera);
+ show_dir();
+ break;
+
+ case PROMPT_TEMP:
+ sensorValue = analogRead(TEMPERATURE_PIN);
+ Serial.print("Raw diode voltage: ");
+ Serial.println(sensorValue);
+ Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1));
+ Serial.print("Calculated temperature: ");
+ Serial.print(Temp);
+ Serial.println(" C");
+ break;
+
+ case PROMPT_VOLTAGE:
+ Serial.println("Querying INA219 voltage and current sensors");
+ if (!ina219_started)
+ start_ina219();
+ voltage_read = true;
+ read_ina219();
+ break;
+
+
+ case PROMPT_RESET:
+ Serial.println("Reset count is now 0");
+ reset_count = 0;
+ write_config_file();
+ break;
+
+ case PROMPT_RESTART:
+ prompt = false;
+// Serial.println("Restart not yet implemented");
+ start_payload();
+// start_ina219();
+ if ((mode != CW) || (!filter_present))
+ transmit_callsign(callsign);
+ sleep(0.5);
+ config_telem();
+ config_radio();
+ sampleTime = (unsigned int) millis();
+ break;
+
+ case PROMPT_DEBUG:
+ Serial.print("Changing Debug Mode to ");
+ debug_mode = !debug_mode;
+ if (debug_mode)
+ Serial.println("on");
+ else
+ Serial.println("off");
+ break;
+*/
+
+ }
+ prompt = false;
+ prompting = false;
+ }
+// else
+// Serial.println("Already prompting!");
+}
+
+void get_serial_string() {
+ int input = 0;
+ int i = 0;
+ unsigned int elapsed_time = (unsigned int) millis();
+ while ((input != '\n') && (input!= '\r') && (i < 128) && ((millis() - elapsed_time) < 20000)) {
+ if (Serial.available() > 0) {
+ input = Serial.read();
+ if ((input != '\n') && (input!= '\r')) {
+ serial_string[i++] = input;
+ Serial.write(input);
+ }
+ }
+ sleep(0.1);
+ }
+ serial_string[i] = 0;
+ Serial.println(" ");
+}
+
+void get_serial_char() {
+ unsigned int elapsed_time = (unsigned int) millis();
+ while (((millis() - elapsed_time) < 20000) && (Serial.available() < 1)) { }
+ if (Serial.available() > 0) {
+ serial_string[0] = Serial.read(); // get character
+ Serial.write(serial_string[0]);
+ serial_string[1] = 0;
+ Serial.println(" ");
+ } else
+ {
+ serial_string[0] = 0; // timeout - no character
+ }
+}
+
+void get_serial_clear_buffer() {
+// Serial.println("Emptying serial input buffer");
+ while (Serial.available() > 0)
+ Serial.read();
+
+}
+
+
+void read_config() {
+ LittleFS.begin();
+ Serial.println("Reading config file");
+ char buff[32];
+ File mode_file = LittleFS.open("/config.txt", "r");
+// if (!mode_file) {
+// write_mode(mode);
+// } else {
+ // if (mode_file.read((uint8_t *)buff, 31)) {
+// Serial.println("Reading mode from .mode file");
+ sscanf(buff, "%d", &mode);
+ mode_file.close();
+// Serial.print("Mode is ");
+// Serial.print(mode);
+
+// }
+ //}
+}
+
+void write_config(int save_mode) {
+
+ char buff[32];
+ Serial.println("Writing config file");
+ File mode_file = LittleFS.open("/config.txt", "w+");
+
+ sprintf(buff, "%d", save_mode);
+ if (debug_mode) {
+ Serial.println("Writing string");
+ print_string(buff);
+ }
+
+ if (mode_file.write(buff, strlen(buff)) != strlen(buff)) {
+// Serial.println(mode_file.write(buff, strlen(buff)));
+ Serial.println("*** config file write error! ***\n\n");
+ blinkFastTimes(3);
+ }
+
+ mode_file.close();
+// Serial.println("Write complete");
+}
+
+
+void get_input() {
+// if (mode != SSTV)
+// Serial.print("+");
+// if ((mode == CW) || (mode == SSTV))
+ serial_input();
+
+// check for button press
+// if (digitalRead(MAIN_PB_PIN) == PRESSED) // pushbutton is pressed
+// process_pushbutton();
+ if (BOOTSEL) // boot selector button is pressed on Pico
+// process_bootsel();
+ Serial.println("boot selector button pressed!");
+
+ if (prompt) {
+// Serial.println("Need to prompt for input!");
+ prompt_for_input();
+ prompt = false;
+ }
+/*
+ // check to see if the mode has changed
+ if (mode != new_mode) {
+ Serial.println("Changing mode");
+ cw_stop = false; // enable CW or won't hear CW ID
+/// if (mode == SSTV) {
+/// ITimer1.detachInterrupt();
+/// start_button_isr(); // restart button isr
+/// }
+ int old_mode = mode;
+ bool config_done = false;
+// mode = new_mode; // change modes if button pressed
+ write_mode(new_mode);
+
+ Serial.println("Rebooting...");
+ Serial.flush();
+ watchdog_reboot (0, SRAM_END, 500); //10); // restart Pico
+
+ sleep(20.0);
+ */
+/*
+ if (new_mode != CW)
+ transmit_callsign(callsign);
+ sleep(0.5);
+
+ if (!config_done)
+ config_telem(); // run this here for all other modes
+
+ config_radio();
+ if ((mode == FSK) || (mode == BPSK)) {
+ digitalWrite(LED_BUILTIN, HIGH);
+ digitalWrite(MAIN_LED_BLUE, HIGH);
+ }
+
+ sampleTime = (unsigned int) millis();
+*/
+// }
+
+}
diff --git a/systemd/rpitx.service b/systemd/command.service
similarity index 67%
rename from systemd/rpitx.service
rename to systemd/command.service
index 2f2feac2c..9354154fa 100644
--- a/systemd/rpitx.service
+++ b/systemd/command.service
@@ -1,9 +1,9 @@
[Unit]
-Description=CubeSatSim rpitx service
+Description=Command service
[Service]
TimeoutStopSec=5
-ExecStart=python3 -u /home/pi/CubeSatSim/rpitx.py
+ExecStart=/home/pi/CubeSatSim/command
WorkingDirectory=/home/pi/CubeSatSim
StandardOutput=inherit
StandardError=inherit
diff --git a/systemd/cubesatsim.service b/systemd/cubesatsim.service
index 11966c22b..1101dc9e4 100644
--- a/systemd/cubesatsim.service
+++ b/systemd/cubesatsim.service
@@ -10,7 +10,7 @@ StandardError=inherit
Restart=always
User=root
CPUAccounting=true
-CPUQuota=5%
+CPUQuota=7%
[Install]
WantedBy=default.target
diff --git a/systemd/transmit.service b/systemd/transmit.service
new file mode 100644
index 000000000..ab6dd815d
--- /dev/null
+++ b/systemd/transmit.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=CubeSatSim transmit service
+
+[Service]
+TimeoutStopSec=5
+ExecStart=python3 -u /home/pi/CubeSatSim/transmit.py
+WorkingDirectory=/home/pi/CubeSatSim
+StandardOutput=inherit
+StandardError=inherit
+Restart=always
+User=root
+
+[Install]
+WantedBy=default.target
diff --git a/telem.c b/telem.c
index a32746db1..7afceef28 100644
--- a/telem.c
+++ b/telem.c
@@ -15,7 +15,7 @@ int main(int argc, char *argv[]) {
}
}
- printf("CubeSatSim v1.2 INA219 Voltage and Current Telemetry\n");
+ printf("CubeSatSim v2.0 INA219 Voltage and Current Telemetry\n");
map[MINUS_X] = MINUS_Y;
map[PLUS_Z] = MINUS_X;
map[MINUS_Y] = PLUS_Z;
@@ -72,14 +72,14 @@ int main(int argc, char *argv[]) {
}
printf("\n");
- printf("+X | % 4.2f V % 5.0f mA \n", voltage[map[PLUS_X]], current[map[PLUS_X]]);
- printf("+Y | % 4.2f V % 5.0f mA \n", voltage[map[PLUS_Y]], current[map[PLUS_Y]]);
- printf("+Z | % 4.2f V % 5.0f mA \n", voltage[map[PLUS_Z]], current[map[PLUS_Z]]);
- printf("-X | % 4.2f V % 5.0f mA \n", voltage[map[MINUS_X]], current[map[MINUS_X]]);
- printf("-Y | % 4.2f V % 5.0f mA \n", voltage[map[MINUS_Y]], current[map[MINUS_Y]]);
- printf("-Z | % 4.2f V % 5.0f mA \n", voltage[map[MINUS_Z]], current[map[MINUS_Z]]);
- printf("Bat | % 4.2f V % 5.0f mA \n", voltage[map[BAT]], current[map[BAT]]);
- printf("Bus | % 4.2f V % 5.0f mA \n\n", voltage[map[BUS]], current[map[BUS]]);
+ printf("+X | % 4.2f V % 5.0f mA \n", voltage[map[PLUS_X]], current[map[PLUS_X]]);
+ printf("+Y | % 4.2f V % 5.0f mA \n", voltage[map[PLUS_Y]], current[map[PLUS_Y]]);
+ printf("+Z | % 4.2f V % 5.0f mA \n", voltage[map[PLUS_Z]], current[map[PLUS_Z]]);
+ printf("-X | % 4.2f V % 5.0f mA \n", voltage[map[MINUS_X]], current[map[MINUS_X]]);
+ printf("-Y | % 4.2f V % 5.0f mA \n", voltage[map[MINUS_Y]], current[map[MINUS_Y]]);
+ printf("-Z | % 4.2f V % 5.0f mA \n", voltage[map[MINUS_Z]], current[map[MINUS_Z]]);
+ printf("Bat | % 4.2f V % 5.0f mA \n", voltage[map[BAT]], current[map[BAT]]);
+ printf("Bat2 | % 4.2f V % 5.0f mA \n\n", voltage[map[BAT2]], current[map[BAT2]]);
fclose(file1);
return 0;
diff --git a/transmit.py b/transmit.py
new file mode 100644
index 000000000..51392f7da
--- /dev/null
+++ b/transmit.py
@@ -0,0 +1,835 @@
+#!/usr/bin/env python
+
+import RPi.GPIO as GPIO
+from RPi.GPIO import output
+#import subprocess
+#import time
+from time import sleep
+#import os
+import sys
+from os import system
+from PIL import Image, ImageDraw, ImageFont, ImageColor
+import serial
+
+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 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'
+ GPIO.output(powerPin, 0) # blink two times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(2.5)
+
+ elif (mode == 'f'):
+ mode = 'b'
+ GPIO.output(powerPin, 0) # blink three times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(2.5)
+
+ elif (mode == 'b'):
+ mode = 's'
+ GPIO.output(powerPin, 0) # blink four times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(2.5)
+
+ elif (mode == 's'):
+ mode = 'm'
+ GPIO.output(powerPin, 0) # blink five times
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1);
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(0.1)
+ GPIO.output(powerPin, 0)
+ sleep(0.1)
+ GPIO.output(powerPin, 1)
+ sleep(2.5)
+ else:
+ mode = 'a'
+ GPIO.output(powerPin, 0) # blink one time
+ sleep(0.1)
+ GPIO.output(powerPin, 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")
+
+ GPIO.setwarnings(False)
+ GPIO.output(txLed, 0)
+ GPIO.output(powerPin, 0)
+ print("sudo reboot -h now")
+ GPIO.setwarnings(False)
+ GPIO.setup(powerPin, GPIO.OUT)
+ GPIO.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")
+
+
+print("CubeSatSim v2.0 transmit.py starting...")
+
+pd = 21
+ptt = 20
+txc_pin = 7
+squelch = 6
+green = 16
+powerPin = 16
+
+command_tx = True
+
+GPIO.setmode(GPIO.BCM)
+GPIO.setwarnings(False)
+GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+GPIO.setup(txc_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+GPIO.setup(green, GPIO.OUT)
+GPIO.output(powerPin, 1)
+
+transmit = False
+txLed = 27
+txLedOn = 1
+txLedOff = 0
+if GPIO.input(12) == False:
+ print("Version is v1 with UHF LPF")
+ transmit = True
+else:
+ print("No LPF")
+
+
+# GPIO.setup(txLed, GPIO.OUT)
+# output(txLed, txLedOff)
+
+GPIO.setmode(GPIO.BCM) # Repeat to make LED work on Pi 4
+GPIO.setwarnings(False)
+GPIO.setup(txLed, GPIO.OUT)
+
+GPIO.setup(pd, GPIO.OUT)
+#output(pd, 1)
+output(pd, 0)
+GPIO.setup(ptt, GPIO.OUT)
+output (ptt, 1)
+
+txc = False
+if GPIO.input(txc_pin) == False:
+ print("TXC is present")
+ txc = True;
+else:
+ print("TXC not present")
+
+# txc = False # forcing it off
+output(txLed, txLedOn)
+sleep(1)
+output(txLed, txLedOff)
+
+battery_saver_check()
+
+# print(txLedOn)
+print(txLed)
+# GPIO.setup(27, GPIO.OUT)
+# GPIO.output(27, 0)
+
+debug_mode = 0 #no debugging transmit
+
+skip = False
+
+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)
+
+
+ try:
+ system("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 < 45):
+ print("Uptime < 45 seconds")
+ else:
+ print("Uptime > 45 seconds")
+ skip = True
+ file.close()
+ except:
+ print("Can't open /proc/uptime")
+
+ 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)
+
+ 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'
+
+ try:
+ file = open("/home/pi/CubeSatSim/sim.cfg")
+# callsign = file.readline().split(" ")[0]
+ config = file.readline().split()
+ callsign = config[0]
+ if len(config) > 5:
+ sq = config[5]
+ print(sq)
+ if len(config) > 6:
+ txf = float(config[6])
+# print(txf)
+# print( "{:.4f}".format(txf))
+ tx = "{:.4f}".format(txf)
+ print(tx)
+ if len(config) > 7:
+ rxf = float(config[7])
+# print(rxf)
+# print( "{:.4f}".format(rxf))
+ rx = "{:.4f}".format(rxf)
+ print(rx)
+ 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)
+ 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()
+
+ try:
+ f = open("/home/pi/CubeSatSim/command_control", "r")
+ f.close()
+ GPIO.setmode(GPIO.BCM)
+ GPIO.setwarnings(False)
+ GPIO.setup(squelch, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## pull up in case pin is not connected
+ if GPIO.input(squelch) == False:
+ print("squelch not set correctly, no command input!")
+ no_command = True
+ else:
+ print("command and control is activated")
+ no_command = False
+# system("/home/pi/CubeSatSim/command &")
+ system("sudo systemctl start command")
+ except:
+ print("command and control not activated")
+ no_command = True
+
+ print(callsign)
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi 4
+ print(txLed)
+ print(txLedOn)
+ GPIO.setup(txLed, GPIO.OUT)
+
+ card = "Headphones" # default using pcm audio output of Pi Zero
+# card = "Device" # using USB sound card for audio output
+
+ print("Programming FM module!\n");
+ 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:
+ print("Error in serial write")
+ output(pd, 0)
+
+# if (mode != 'x') and (skip == False):
+# sleep(10) # delay so cubesatsim code catches up
+
+ system("echo 'hi hi de " + callsign + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1")
+
+# command_control_check()
+
+# if (mode != ) and (command_tx == True):
+# if (command_tx == True):
+ if ((mode == 'a') or (mode == 'b') or (mode == 'f') or (mode == 's')) and (command_tx == True) and (skip == False):
+# battery_saver_mode
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+# if (txc):
+# output(pd, 1)
+# output (ptt, 0)
+# sleep(0.1)
+# system("aplay -D plughw:CARD=" + card + ",DEV=0 /home/pi/CubeSatSim/morse.wav")
+# sleep(0.1)
+# output (ptt, 1)
+# output(pd, 0)
+# else:
+ if (True):
+ if (debug_mode == 1):
+# system("echo 'hi hi de " + callsign + "' > 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 434.9e3")
+ system("echo 'hi hi de " + callsign + "' > 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 + "' > 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 434.9e3 > /dev/null 2>&1")
+ system("echo 'hi hi de " + callsign + "' > 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")
+
+ output(txLed, txLedOff)
+
+ sleep(1)
+ else:
+ print("Don't transmit CW ID since command_tx is False or APRS 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'):
+# command_control_check()
+ output(pd, 1)
+ output(ptt, 1)
+ if (mode == 'a'):
+ print("AFSK")
+ else:
+ GPIO.output(powerPin, 0)
+ print("Transmit APRS Commands")
+# 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):
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+# output(pd, 1)
+# output (ptt, 0)
+# sleep(.1)
+#
+# battery_saver_check()
+ if (txc):
+# 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")
+ 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, txLedOff)
+ system("sudo rm /home/pi/CubeSatSim/ready")
+ f.close()
+
+ if (debug_mode == 1):
+ print("Ready for next packet!")
+
+ sleep(0.5)
+ except:
+# 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):
+ 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):
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+
+ if (txc):
+# 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, txLedOff)
+
+# command_control_check()
+ sleep(2)
+ f.close()
+ sleep(10)
+ except:
+# command_control_check()
+ 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")
+ 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, txLedOff)
+# 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")
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+# battery_saver_check()
+
+ if (txc):
+# 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, txLedOff)
+
+ # sleep(1)
+ except:
+ print("image 2 did not load - copy from CubeSatSim/sstv directory")
+ while 1:
+# command_control_check()
+
+ system("raspistill -o /home/pi/CubeSatSim/camera_out.jpg -w 320 -h 256") # > /dev/null 2>&1")
+ print("Photo taken")
+
+ 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((122, 12), telem_string, font=font2, fill='black')
+ draw.text((120, 10), telem_string, font=font2, fill='white')
+ img.save(file)
+
+# command_control_check()
+
+ 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")
+
+# command_control_check()
+
+ if (command_tx == True):
+ print ("Sending SSTV image")
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+# battery_saver_check()
+
+ if (txc):
+# 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, txLedOff)
+# 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")
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+
+# battery_saver_check()
+
+ if (txc):
+# 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, txLedOff)
+# 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:
+
+# command_control_check()
+
+ if (command_tx == True):
+ print ("Sending SSTV image")
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+# battery_saver_check()
+
+ if (txc):
+# 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, txLedOff)
+# 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):
+# command_control_check()
+
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+
+# battery_saver_check()
+
+ if (txc):
+# 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, txLedOff)
+# output (ptt, 1)
+# output(pd, 0)
+ sleep(10)
+
+ elif (mode == 'b'):
+# command_control_check()
+ print("BPSK")
+ print("turn on FM rx")
+ output(pd, 1)
+ output(ptt, 1)
+
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+
+ 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")
+ while 1:
+ output(txLed, txLedOff)
+ sleep(0.4)
+# if (command_tx == False):
+# output(txLed, txLedOn)
+# sleep(0.03)
+# output(txLed, txLedOff)
+# command_control_check()
+
+ if (command_tx == True):
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+# print(txLed)
+# print(txLedOn)
+ sleep(4.2)
+ elif (mode == 'e'): # code based on https://zr6aic.blogspot.com/2016/11/creating-2m-fm-repeater-with-raspberry.html
+ print("Repeater")
+ print("Stopping command and control")
+ system("sudo systemctl stop command")
+ print("turn on FM rx")
+ output(pd, 1)
+ output(ptt, 1)
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ GPIO.setup(powerPin, GPIO.OUT)
+ GPIO.setup(squelch, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## pull up in case pin is not connected
+ GPIO.output(powerPin, 0)
+ while True:
+ sleep(0.5)
+ if (GPIO.input(squelch) == False):
+ print("Carrier detected, starting repeater")
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+# system("arecord -D plughw:CARD=Device,DEV=0 | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &")
+## system("arecord -D plughw:CARD=Device,DEV=0 -f S16_LE -r 48000 -c 1 | csdr convert_s16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &")
+ system("sudo nc -l 8011 | csdr convert_i16_f | csdr gain_ff 16000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &")
+ sleep(1)
+ system("sudo arecord -D plughw:1 -r48000 -fS16_LE -c1 | nc localhost 8011 &")
+ GPIO.output(powerPin, 1)
+ sleep(0.5)
+ GPIO.output(powerPin, 0)
+ while (GPIO.input(squelch) == False):
+ sleep(1)
+ print("No carrier detected, stopping repeater")
+ output(txLed, txLedOff)
+ system("sudo killall -9 arecord")
+ system("sudo killall -9 nc")
+ system("sudo killall -9 rpitx")
+
+ else:
+ print("FSK")
+ print("turn on FM rx")
+ output(pd, 1)
+ output(ptt, 1)
+
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+
+ 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, txLedOff)
+ sleep(0.4)
+# if (command_tx == False):
+# output(txLed, txLedOn)
+# sleep(0.03)
+# output(txLed, txLedOff)
+# command_control_check()
+ if (command_tx == True):
+ GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
+ GPIO.setup(txLed, GPIO.OUT)
+ output(txLed, txLedOn)
+# print(txLed)
+# print(txLedOn)
+ 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)
diff --git a/update b/update
index 53aa19cd1..b2dccbe2e 100755
--- a/update
+++ b/update
@@ -1,14 +1,25 @@
#!/bin/bash
-echo -e "\nupdate script for CubeSatSim v1.2\n"
+echo -e "\nupdate script for CubeSatSim v2.0\n"
+
+if [ "$1" = "n" ] ; then
+# if [ -z "$2" ] ; then
+ noreboot=1
+else
+ noreboot=0
+fi
+
+# echo "No reboot"
+# echo $noreboot
sudo rm /home/pi/CubeSatSim/morse.wav /home/pi/CubeSatSim/id.txt /home/pi/CubeSatSim/cw.txt > /dev/null 2>&1
if [ "$1" = "u" ]; then
- sudo apt-get update && sudo apt-get dist-upgrade -y
+# sudo apt-get update && sudo apt-get dist-upgrade -y
+ sudo apt-get update -y
- sudo apt-get install -y wiringpi git libasound2-dev i2c-tools build-essential libgd-dev libmagic-dev python3-pip minicom
+ sudo apt-get install -y git libasound2-dev i2c-tools build-essential libgd-dev libmagic-dev python3-pip minicom
fi
@@ -22,12 +33,30 @@ sudo sed -i 's/more information/more\ninformation/g' /etc/motd
sudo sed -i 's/update to/update\nto/g' /etc/motd
+sudo sed -i 's/console=tty1 r/console=tty1 maxcpus=1 r/g' /boot/cmdline.txt # single core if Pi Zero 2
+
cd /home/pi/CubeSatSim
-git pull > .updated
+git pull --no-rebase > .updated
make debug
+FILE=/home/pi/CubeSatSim/command_tx
+if [ -f "$FILE" ]; then
+ echo "$FILE exists."
+else
+ echo "creating $FILE"
+ echo "True\n" > /home/pi/CubeSatSim/command_tx
+fi
+
+FILE=/home/pi/CubeSatSim/command_count.txt
+if [ -f "$FILE" ]; then
+ echo "$FILE exists."
+else
+ echo "creating $FILE"
+ echo "0\n" > /home/pi/CubeSatSim/command_count.txt
+fi
+
FLAG=0
if [[ $(diff systemd/cubesatsim.service /etc/systemd/system/cubesatsim.service) ]]; then
@@ -38,12 +67,41 @@ else
echo "no changes to cubesatsim.service."
fi
-if [[ $(diff systemd/rpitx.service /etc/systemd/system/rpitx.service) ]]; then
- echo "changed rpitx.service."
- sudo cp /home/pi/CubeSatSim/systemd/rpitx.service /etc/systemd/system/rpitx.service
+FILE=/etc/systemd/system/rpitx.service
+if [ -f "$FILE" ]; then
+ sudo systemctl disable rpitx
+ sudo rm /etc/systemd/system/rpitx.service
+fi
+
+FILE=/etc/systemd/system/transmit.service
+if [ -f "$FILE" ]; then
+ if [[ $(diff systemd/transmit.service /etc/systemd/system/transmit.service) ]]; then
+ echo "changed transmit.service."
+ sudo cp /home/pi/CubeSatSim/systemd/transmit.service /etc/systemd/system/transmit.service
+ FLAG=1
+ else
+ echo "no change to transmit.service."
+ fi
+else
+ echo "creating transmit.service."
+ sudo cp /home/pi/CubeSatSim/systemd/transmit.service /etc/systemd/system/transmit.service
FLAG=1
+fi
+
+FILE=/etc/systemd/system/command.service
+if [ -f "$FILE" ]; then
+ if [[ $(diff systemd/command.service /etc/systemd/system/command.service) ]]; then
+ echo "changed command.service."
+ sudo cp /home/pi/CubeSatSim/systemd/command.service /etc/systemd/system/command.service
+ FLAG=1
+ else
+ echo "no change to command.service."
+ fi
else
- echo "no changes to rpitx.service."
+ echo "creating command.service."
+ sudo cp /home/pi/CubeSatSim/systemd/command.service /etc/systemd/system/command.service
+ sudo systemctl enable command
+ FLAG=1
fi
FILE=/home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg
@@ -64,23 +122,10 @@ if [[ $(grep 'update' /home/pi/CubeSatSim/.updated) ]]; then
/home/pi/CubeSatSim/update
fi
-if [ $FLAG -eq 1 ]; then
- echo "systemctl daemon-reload and restart"
- sudo systemctl daemon-reload
- sudo systemctl restart cubesatsim
-else
- grep 'changed' /home/pi/CubeSatSim/.updated
- if [[ $(grep 'changed' /home/pi/CubeSatSim/.updated) ]]; then
- echo "systemctl restart cubesatsim"
- sudo systemctl restart cubesatsim
- else
- echo "nothing to do."
- fi
-fi
-
if [ ! -d "/home/pi/PiSSTVpp" ]; then
- sudo apt-get update && sudo apt-get dist-upgrade -y
+# sudo apt-get update && sudo apt-get dist-upgrade -y
+ sudo apt-get update -y
sudo apt-get install -y python-picamera python3-picamera build-essential libgd-dev libmagic-dev
@@ -127,9 +172,66 @@ if [ ! -d "/home/pi/PiSSTVpp" ]; then
fi
+if [ ! -d "/home/pi/rpitx" ]; then
+
+ cd
+ git clone https://github.com/alanbjohnston/rpitx.git
+ cd rpitx
+ ./install.sh
+ cd
+else
+
+ if [[ $(grep 'SYNCWITHPWM' /home/pi/rpitx/src/librpitx/src/fskburst.h) ]]; then
+ echo "rpitx library already updated"
+ else
+ echo "updating rpitx"
+ cd /home/pi/rpitx
+ git pull
+ ./update.sh
+ cd
+ fi
+fi
+
+if [ ! -d "/home/pi/WiringPi" ]; then
+
+ cd
+
+ git clone https://github.com/PinkFreud/WiringPi
+ cd WiringPi
+ ./build debian
+
+ sudo dpkg -i debian-template/wiringpi-2.61-1.deb
+
+ cd
+
+ cd CubeSatSim
+ make debug
+
+ FLAG=1
+
+ cd
+
+fi
+
cd /home/pi/pi-power-button
-git pull > .updated_p
+git checkout reboot-mode-change-beta > .updated_b
+
+ grep 'error' /home/pi/pi-power-button/.updated_b
+ if [[ $(grep 'error' /home/pi/pi-power-button/.updated_b) ]]; then
+
+ echo "pi-power-button switching to beta branch"
+
+ git pull
+
+ git checkout reboot-mode-change-beta
+
+ script/install
+
+ FLAG=1
+ fi
+
+ git pull --no-rebase > .updated_p
grep 'changed' /home/pi/pi-power-button/.updated_p
if [[ $(grep 'changed' /home/pi/pi-power-button/.updated_p) ]]; then
@@ -137,23 +239,143 @@ git pull > .updated_p
echo "updating pi-power-button."
script/install
+
+ FLAG=1
- echo "You need to reboot to complete this update. Reboot now (y/n)?"
+# echo "You need to reboot to complete this update. Reboot now (y/n)?"
- read -r ANS
+# read -r ANS
- if [ "$ANS" = "y" ]; then
+ # if [ "$ANS" = "y" ]; then
- sudo reboot now
+ # sudo reboot now
- else
+ # else
- echo "The CubeSatSim software may not work correctly until you reboot."
+ # echo "The CubeSatSim software may not work correctly until you reboot."
- fi
+ # fi
else
echo "nothing to do for pi-power-button."
fi
-
- echo "CubeSatSim update complete."
+
+ if [[ $(grep 'dtparam=audio=on' /boot/config.txt) ]]; then
+ echo "dtparam=audio=on already in /boot/config.txt"
+ else
+ echo "adding dtparam=audio=on to /boot/config.txt"
+ sudo sh -c 'echo "\ndtparam=audio=on" >> /boot/config.txt'
+ FLAG=1
+ fi
+
+ if [[ $(grep 'dtoverlay=audremap,enable_jack=on' /boot/config.txt) ]]; then
+ echo "dtoverlay=audremap,enable_jack=on already in /boot/config.txt"
+ else
+ echo "adding dtoverlay=audremap,enable_jack=on to /boot/config.txt"
+ sudo sh -c 'echo "\ndtoverlay=audremap,enable_jack=on" >> /boot/config.txt'
+ FLAG=1
+ fi
+
+ if [[ $(grep 'dtoverlay=pwm,pin=18,func=2' /boot/config.txt) ]]; then
+ echo "dtoverlay=pwm,pin=18,func=2 already in /boot/config.txt"
+ else
+ echo "adding dtoverlay=pwm,pin=18,func=2 to /boot/config.txt"
+ sudo sh -c 'echo "\ndtoverlay=pwm,pin=18,func=2" >> /boot/config.txt'
+ FLAG=1
+
+ cd /home/pi/pi-power-button
+ git pull --no-rebase
+ git checkout reboot-mode-change
+ script/install
+
+# sudo apt-get update && sudo apt-get dist-upgrade -y
+ sudo apt-get update -y
+ sudo apt-get install -y libjpeg-dev zlib1g-dev libfreetype6-dev liblcms1-dev libopenjp2-7 libtiff5 python3-pil
+ sudo pip3 install adafruit-blinka RPI.GPIO adafruit-extended-bus adafruit-circuitpython-ina219 pillow
+
+ fi
+
+ if [[ $(grep 'disable_splash=1' /boot/config.txt) ]]; then
+ echo "disable_splash=1 already in /boot/config.txt"
+ else
+ echo "adding to /boot/config.txt"
+ sudo sh -c 'echo "\ndisable_splash=1" >> /boot/config.txt'
+ FLAG=1
+ fi
+
+ if [[ $(grep 'boot_delay=0' /boot/config.txt) ]]; then
+ echo "boot_delay=0 already in /boot/config.txt"
+ else
+ echo "adding to /boot/config.txt"
+ sudo sh -c 'echo "\nboot_delay=0" >> /boot/config.txt'
+ FLAG=1
+ fi
+
+ if ! grep -q force_turbo=1 /boot/config.txt ; then
+ sudo sh -c 'echo "force_turbo=1" >> /boot/config.txt'
+ FLAG=1
+ fi
+
+#if [ ! -f "/home/pi/CubeSatSim/telem_string.txt" ]; then
+
+# sudo apt-get update && sudo apt-get dist-upgrade -y
+
+# sudo apt-get install -y libjpeg-dev zlib1g-dev libfreetype6-dev liblcms1-dev libopenjp2-7 libtiff5 -y
+
+# sudo pip3 install pillow
+
+#fi
+
+changed=0
+value=`cat /home/pi/CubeSatSim/sim.cfg`
+# echo "$value"
+echo "$value" > /dev/null
+set -- $value
+
+if [ -z "$1" ] ; then n1="AMSAT" ; changed=1 ; else n1=$1 ; fi # callsign
+if [ -z "$2" ] ; then n2="0" ; changed=1 ; else n2=$2 ; fi # reset count
+if [ -z "$3" ] ; then n3="0" ; changed=1 ; else n3=$3 ; fi # lat
+if [ -z "$4" ] ; then n4="0" ; changed=1 ; else n4=$4 ; fi # lon
+if [ -z "$5" ] ; then n5="no" ; changed=1 ; else n5=$5 ; fi # sim mode
+if [ -z "$6" ] ; then n6="3" ; changed=1 ; else n6=$6 ; fi # squelch
+if [ -z "$7" ] ; then n7="434.9000" ; changed=1 ; else n7=$7 ; fi # transmit frequency
+if [ -z "$8" ] ; then n8="435.0000" ; changed=1 ; else n8=$8 ; fi # receive frequency
+if [ -z "$9" ] ; then n9="no" ; changed=1 ; else n9=$9 ; fi # hab mode
+if [ -z "${10}" ] ; then m1="0" ; changed=1 ; else m1=${10} ; fi # rx pl code
+if [ -z "${11}" ] ; then m2="0" ; changed=1 ; else m2=${11} ; fi # tx pl code
+
+if [ $changed -eq 1 ]; then
+ echo -e "Current sim.cfg configuration file:"
+ echo
+ echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
+ echo -e "\nCubeSatSim configuration sim.cfg file updated to: \n"
+ echo
+ echo $n1 $n2 $n3 $n4 $n5 $n6 $n7 $n8 $n9 $m1 $m2
+ echo $n1 $n2 $n3 $n4 $n5 $n6 $n7 $n8 $n9 $m1 $m2 > /home/pi/CubeSatSim/sim.cfg
+ echo
+fi
+
+if [ "$noreboot" = "0" ] ; then
+
+ if [ $FLAG -eq 1 ]; then
+ echo "systemctl daemon-reload and reboot"
+ sudo systemctl daemon-reload
+ sudo reboot -h now
+# sudo cubesatsim
+ else
+ grep 'changed' /home/pi/CubeSatSim/.updated
+ if [[ $(grep 'changed' /home/pi/CubeSatSim/.updated) ]]; then
+ echo "reboot due to code changes " | wall
+ sudo reboot -h now
+# sudo cubesatsim
+ else
+ echo "nothing to do."
+ fi
+ fi
+else
+ if [ $FLAG -eq 1 ]; then
+ echo "reboot needed for changes to take effect"
+ fi
+fi
+
+echo "CubeSatSim update complete."