[Beagleboard] A 36km High Altitude Payload with Live Images

The ‘Space Camera Live 1’ project itself This article is about the Main Payload used in this project. I advise you first to checkout what this project was about, by clicking on the Space Camera Live 1 link.

[caption id="attachment_2118" align="aligncenter" width="300" caption="me with the Flight computer"][/caption]

Beagleboard and its parts

To power the beagleboard, i made a proper “Beagle Battery” module. How i made that or make it youself you can read that here. To use the GPS/GPRS system on the beagleboard, i made a proper module that you can read about and make yourself here.

Overview of the internals

[caption id="attachment_1863" align="aligncenter" width="300" caption="Insides of the main payload"][/caption]

The outsides

[caption id="attachment_1862" align="aligncenter" width="300" caption="An overview (after launch)"][/caption]

Some other parts i have written about seperately:

Making a proper antenna. Making a ‘hot-wire’ cutdown mechanism. Cutting your styrofoam.

Downloads & Scripts

For all the scripts i have used, there is only one really important external one. SSDV Script [external, github].
[caption id="attachment_1953" align="aligncenter" width="440" caption="Script structure"][/caption]

loopall.sh

This script was invoked at startup by cron.
  1. #!/bin/bash
  2. #(C) Tim Zaman 2011
  3. cd /home/ubuntu
  4. bash catloop.sh & bash snaploop.sh & bash sendloop.sh

catloop.sh

This script syphoned off the GPS info and the Battery status.
  1. #!/bin/bash
  2. #Project Space Camera Live
  3. #(c) Tim Zaman 2011
  4. # catloop.sh
  5. OLDIFS=${IFS}
  6. BATDEV="/dev/BAT"
  7. GPSDEV="/dev/GPRS"
  8. GPSLOG="/dev/shm/gps.log" #Logs to RAM
  9. GPSLOGRAW="/home/ubuntu/gpsraw.log"
  10. #BATLOGRAW="/home/ubuntu/batraw.log"
  11. typeset -u CHECKSUM #Anything stored in Checksum var will be uppercase
  12. stty -F $GPSDEV 115200 raw crtscts
  13. stty -F $BATDEV 9600 raw
  14. echo "AT#STARTMODESCR=1,10" > $GPSDEV
  15. sleep 1s
  16. echo "AT#EXESCR" > $GPSDEV
  17. NR=1
  18. ONE=1
  19. COM=","
  20. VAVG=0 #preallocate average mV
  21. while [ 1 ]
  22. do
  23. 	let NR=$NR+$ONE
  24. 	GPSSTR=""
  25. 	BATSTR=""
  26. 	#Battery...
  27. 	#timeout 10s cat $BATDEV | tee -a $BATLOGRAW | head -n1 > "/dev/shm/bat.str"
  28. 	timeout 10s cat $BATDEV | head -n1 > "/dev/shm/bat.str"
  29. 	BATSTR=`cat "/dev/shm/bat.str" | tr -d 'n' | tr -d 'r'`${COM}
  30. 	echo " raw bat: "$BATSTR
  31. 	if [ ${#BATSTR} -gt 10 ]
  32. 	then
  33. 		IFS=","
  34. 		set -- $BATSTR
  35. 		IFS=${OLDIFS}
  36. 		TIMEBAT=$1
  37. 		VBAT1=$2
  38. 		VBAT2=$3
  39. 		VBAT3=$4
  40. 		VBAT4=$5
  41. 		TEMPB=$6 #deoesnt get filled in?
  42. 		let VAVG=($VBAT3+$VBAT4)/2
  43. 		if [ "$TEMPB" -ge "90" ]
  44. 		then	#Incorrect measurement so 0
  45. 			TEMPB="0"
  46. 		fi
  47. 	fi
  48. 	#GPS...
  49. 	#timeout 10s cat $GPSDEV | tee -a $GPSLOGRAW | grep --text --line-buffered "GPSACP" | head -n1 > "/dev/shm/gps.str"
  50. 	timeout 10s cat $GPSDEV | grep --text --line-buffered "GPSACP" | head -n1 > "/dev/shm/gps.str"
  51. 	GPSSTR=`cat "/dev/shm/gps.str" | tr -d 'n' | tr -d 'r'`${COM}
  52. 	GPSSTR=$(echo $GPSSTR|sed 's/ /,/g') #replace " " with ","
  53. 	echo " raw gps: "$GPSSTR
  54. 	if [ ${#GPSSTR} -gt 50 ]
  55. 	then
  56. 		IFS=","
  57. 		set -- $GPSSTR
  58. 		IFS=${OLDIFS}
  59. 		TIME=$2
  60. 		LAT=$3
  61. 		LON=$4
  62. 		ALT=$5
  63. 		FIX=$6
  64. 		COURSE=$8
  65. 		SPD=$9
  66. 		DATE=${11}
  67. 		SAT=${12}
  68. 		SAT=`echo ${SAT#0}` #remove leading zeros
  69. 		#Convert time and altitude
  70. 		TIME1=${TIME:0:2}
  71. 		if [ $TIME1 -lt "22" ]
  72. 		then
  73. 			TIME1=$((TIME1+2))
  74. 		else #Later than 22hr
  75. 			TIME1="0"$((TIME1-22))
  76. 		fi
  77. 		TIME=$TIME1":"${TIME:2:2}":"${TIME:4:2}
  78. 		ALT=`echo $ALT | cut -d '.' -f1` #Round off altitude
  79. 		#Convert Latitude
  80. 		LAT1=${LAT:0:2}
  81. 		LAT1=`echo $((LAT1))`
  82. 		LAT2=`echo "scale=4 ; ${LAT:2:7} / 60" | bc`
  83. 		LAT2=`echo $LAT2`
  84. 		LAT2=${LAT2:1:6}
  85. 		LATCHAR=${LAT:9:1}
  86. 		LAT=$LAT1"."$LAT2
  87. 		if [ $LATCHAR = 'S' ]
  88. 		then #South is negative
  89. 			LAT="-"$LAT
  90. 		fi
  91. 		#Convert Longitude
  92. 		LON1=${LON:0:3}
  93. 		LON1=`echo $((LON1))`
  94. 		LON2=`echo "scale=4 ; ${LON:3:7} / 60" | bc`
  95. 		LON2=`echo $LON2`
  96. 		LON2=${LON2:1:6}
  97. 		LONCHAR=${LON:10:1}
  98. 		LON=$LON1"."$LON2
  99. 		if [ $LONCHAR = 'W' ]
  100. 		then #West is negative
  101. 			LON="-"$LON
  102. 		fi
  103. 		SENTENCE="PD4TA,"$NR$COM$TIME$COM$LAT$COM$LON$COM$ALT$COM$SAT$COM$TEMPB$COM$VAVG
  104. 		CHECKSUM=`java CRC16CCITT $SENTENCE`
  105. 		CHECKSUM=`printf "%04X" 0x$CHECKSUM`
  106. 		SENTENCE="$$"$SENTENCE"*"$CHECKSUM
  107. 		echo $SENTENCE > $GPSLOG #Write to RAM
  108. 		echo $SENTENCE >> $GPSLOGRAW #Write to file as well
  109. 		echo $SENTENCE
  110. 	fi
  111. done

snaploop.sh

This script made the webcam snap images and giving them a rating (score).
  1. #!/bin/bash
  2. #Project Space Camera Live
  3. #(c) Tim Zaman 2011
  4. # snaploop.sh
  5. # run as sudo!
  6. SWIT=1
  7. FIVE=5
  8. CAPTX=800
  9. CAPTY=600
  10. ##SENDX=240
  11. ##SENDY=176
  12. VIDDEV="/dev/video0"
  13. DIRIMGRAM="/dev/shm/snaps/raw/"
  14. DIRIMGMMC="/home/ubuntu/snaps/raw/"
  15. #DIRIMGSM="/home/ubuntu/snaps/small/"
  16. DIRIMGNEW="/dev/shm/snaps/new/"
  17. #DIRREJECT="/home/ubuntu/snaps/rejected/"
  18. mkdir "/dev/shm/snaps/"
  19. mkdir $DIRIMGRAM
  20. mkdir $DIRIMGNEW
  21. uvcdynctrl --d /dev/video0 --set="Exposure, Auto Priority" 0
  22. while [ 1 ]
  23. do
  24. 	#if [ $SWIT = $FIVE ] #Once in 5 snaps its a large capture
  25. 	#then
  26. 	#	#CAPTX=1600;CAPTY=1200 #huge problems with the webcam mangling the image
  27. 	#	SWIT=1 #Set back to 1
  28. 	#else
  29. 	#	CAPTX=800; CAPTY=600
  30. 	#	let "SWIT = SWIT + 1" #Iterate..
  31. 	#fi
  32. 	filename=`date +"%H%M%S"`".jpg"
  33. 	FILEIMG=$DIRIMGRAM$filename
  34. 	##FILEIMGSM=$DIRIMGSM$filename
  35. 	echo "Snap[x,y]=["$CAPTX","$CAPTY"]"
  36. 	##echo "Send[x,y]=["$SENDX","$SENDY"]"
  37. 	#Resize captured image and move to small folder
  38. 	uvccapture -o$FILEIMG -d$VIDDEV -x$CAPTX -y$CAPTY -m #-w #-w doesnt help with the wrong images
  39. 	##convert $FILEIMG -resize "$SENDX"x"$SENDY"^
  40.         ##  -gravity center -extent "$SENDX"x"$SENDY" $FILEIMGSM
  41. 	SCORE=`bash imgscore.sh $FILEIMG`
  42. 	SCORE=`printf "%03i" $SCORE`
  43. 	echo "Score = "$SCORE
  44. 	#FILESDIRNEW=`ls $DIRIMGNEW | wc -l`
  45. 	#if [ ${FILESDIRNEW} -gt 4 ] #this was used in the "best of 5 latest" method. unused.
  46. 	#then #Too many files, remove one then copy
  47. 	#	echo "Too many images in new folder, deleting oldest.."
  48. 		#Now remove the oldest:
  49. 	#	mv $DIRIMGNEW`ls -tr $DIRIMGNEW | head -1 | tr -d "nr"` $DIRREJECT
  50. 	#fi
  51. 	#Then copy from small folder to new fo lder and prepend score
  52. 	##cp $FILEIMGSM $DIRIMGNEW$SCORE"-"$filename
  53. 	cp $FILEIMG $DIRIMGNEW$SCORE"-"$filename #Copy image to "new" folder
  54. 	cp $FILEIMG $DIRIMGMMC$SCORE"-"$filename #Also copy to MMC
  55. 	rm $FILEIMG #Then remove the image to make some file in the RAM
  56. 	echo "*****"
  57. 	sleep 1s
  58. done

sendloop.sh

This script took care of choosing the image, decoding it, splitting it, and sending it out to the radio.
  1. #!/bin/bash
  2. #Project Space Camera Live
  3. #(c) Tim Zaman 2011
  4. # sendloop.sh
  5. USBDEV="/dev/FTDI5V"
  6. VIDDEV="/dev/video0"
  7. DIRIMG="/dev/shm/snaps/new/"
  8. DIRSENT="/dev/shm/snaps/sent/"
  9. DIRREJECTED="/dev/shm/snaps/rejected/"
  10. DIRSPLITS="/dev/shm/splits/"
  11. mkdir "/dev/shm/snaps/"
  12. mkdir $DIRSPLITS
  13. mkdir $DIRSENT
  14. mkdir $DIRIMG
  15. mkdir $DIRREJECTED
  16. sleep 5 #wait for images to be taken
  17. NR=0
  18. ONE=1
  19. FIVE=5
  20. TEN=10
  21. SWIT=1
  22. SENDX=320
  23. SENDY=240
  24. BAUDRATE=600
  25. stty -F $USBDEV $BAUDRATE raw cstopb
  26. while [ 1 ]
  27. do
  28. 	IMGAMOUNT=`ls $DIRIMG | wc -l`
  29.  	if [ "$IMGAMOUNT" -eq "0" ] #If there is no image in new folder so sent the latest..
  30. 	then
  31. 		echo "No images detected. Choosing most recent reject.."
  32. 		filename=`ls -t $DIRREJECTED | head -1 | tr -d "nr"`
  33. 		FILEIMG=$DIRREJECTED$filename
  34. 		echo "Recent folder empty, possible camera error :(" >> $USBDEV
  35. 	else #There are sufficient current (new) images so sent the best
  36. 		echo "Choosing from "$IMGAMOUNT" images.."
  37. 		filename=`ls $DIRIMG | head -1 | tr -d "nr"`
  38. 		FILEIMG=$DIRIMG$filename
  39. 	fi
  40. 	if [ $SWIT = $TEN ] #send a big one every 10 images at 1200bd
  41. 	then
  42. 		sleep 3
  43. 		BAUDRATE=1200
  44. 		SENDX=800; SENDY=576
  45. 		SWIT=1 #Set back to 1
  46. 		sleep 3
  47. 	else
  48. 		BAUDRATE=600
  49. 		SENDX=320; SENDY=240
  50. 		let "SWIT = SWIT + 1" #Iterate..
  51. 	fi
  52. 		echo "!!! NEXT ONE @ "$BAUDRATE"BAUD, CYCLE "$SWIT"/"$TEN" !!!" >> $USBDEV
  53. 	#Now convert image size
  54. 	convert $FILEIMG -resize "$SENDX"x"$SENDY"^
  55.           -gravity center -extent "$SENDX"x"$SENDY" $FILEIMG
  56. 	echo "Baudrate="$BAUDRATE
  57. 	echo "Image Nr: "$NR
  58. 	echo "Sending image:"$FILEIMG
  59. 	echo "Sendsize [x,y]=["$SENDX","$SENDY"]"
  60.  	if [[ $FILEIMG == *.jpg ]]
  61. 	then
  62. 		stty -F $USBDEV $BAUDRATE raw cstopb #Set USB baudrate settings appropriate
  63. 		sleep 1
  64. 		echo "NOW SENDING AT "$BAUDRATE" BAUD !" >> $USBDEV
  65. 		ssdv -e $FILEIMG -i $NR > "/dev/shm/img.ssdv"
  66. 		cat /dev/shm/gps.log >> "/dev/shm/img.ssdv"
  67. 		mv $FILEIMG $DIRSENT #Move used image to sent..
  68. 		find $DIRIMG -type f -name "*.jpg" -exec mv {} $DIRREJECTED ;
  69. 		rm /dev/shm/splits/* #make sure folder is empty
  70. 		if [ $SWIT = $ONE ] #Only for 120baud party
  71. 		then
  72. 			sleep 1
  73. 			cat "/dev/shm/img.ssdv" >> $USBDEV #And send it out
  74. 			sleep 3
  75. 		else #If not 1200 baud, split it up and send GPS stuff
  76. 			#Now for the splitting
  77. 			split --bytes=256 "/dev/shm/img.ssdv" /dev/shm/splits/
  78. 			for f in /dev/shm/splits/*
  79. 			do
  80. 				echo "Now at splitpart: $f"
  81. 				cat /dev/shm/gps.log >> $f #Append rtty string
  82. 				cat $f >> $USBDEV #And send it out
  83. 				sleep 3
  84. 			done
  85. 		fi
  86. 		rm /dev/shm/splits/*
  87. 		#cat "/dev/shm/img.ssdv" > $USBDEV #Send entire file out
  88. 		let NR=$NR+$ONE #Sent Image Iteration as last
  89. 		echo "DONE SENDING AT "$BAUDRATE" BAUD !" >> $USBDEV
  90. 	else
  91. 		echo "No image sent.."
  92. 		echo "No jpegs left.." >> $USBDEV
  93. 	fi
  94. 	echo "*****"
  95. done

imgscore.sh

  1. #!/bin/bash
  2. #(c) Tim Zaman 2011
  3. # imgscore.sh
  4. # Example usage: "bash imgscore.sh <image.jpg>"
  5. # Returns the score (lower=better)
  6. # THIS FUNCTION SHOULDNT ECHO ANYTHING BUT THE RESULT!
  7. f=$1
  8. STDSTR=`identify -verbose $f | grep "standard deviation:" | tr -d "nr:"`
  9. MEANSTR=`identify -verbose $f | grep "mean:" | tr -d "nr:"`
  10. stdarr=($STDSTR)
  11. meanarr=($MEANSTR)
  12. fsize=`stat -c %s $f`
  13. STDR=`printf "%.0fn" ${stdarr[2]}`
  14. STDG=`printf "%.0fn" ${stdarr[6]}`
  15. STDB=`printf "%.0fn" ${stdarr[10]}`
  16. STDAVG=$(echo "($STDR + $STDG + $STDB)/3" | bc -l)
  17. STDAVG=`printf "%.0fn" ${STDAVG}`
  18. #MEANR=`printf "%.0fn" ${meanarr[1]}`
  19. #MEANG=`printf "%.0fn" ${meanarr[4]}`
  20. MEANB=`printf "%.0fn" ${meanarr[7]}`
  21. #MEANAVG=$(echo "($MEANR + $MEANG + $MEANB)/3" | bc -l)
  22. #MEANAVG=`printf "%.0fn" ${MEANAVG}`
  23. SCORE=$(echo "sqrt ( (50-$STDAVG)^2 *2 + (160-$MEANB)^2 )" | bc -l)
  24. if [[ $fsize -ge 200000 ]]
  25. then
  26. 	penalty=100
  27. 	SCORE=$(echo "$SCORE + $penalty" | bc -l)
  28. 	#echo "[imgscore: large size detected]"
  29. fi
  30. SCORE=`printf "%.0fn" ${SCORE}`
  31. #The lower the score, the better the image
  32. echo $SCORE
  33. #echo "$f,$STDR,$STDG,$STDB,$MEANR,$MEANG,$MEANB"
  34. #Apply to image:
  35. #SCORERAP=$(echo "(50-$SCORE)/5" | bc -l)
  36. #SCORERAP=`printf "%.0fn" ${SCORERAP}`
  37. #convert $f -pointsize 40 -stroke black -fill white -draw "text 6,42 '$SCORERAP'" "c_"$f
]]>

You may also like...

3 Responses

  1. Costyn says:

    Hi Tim,
    I was wondering about the legality of transmitters other than the NTX2 unit here in NL? I was looking at the TX2H-433-64, which is cheaper and more powerful. Is that an option or will that get me into trouble?
    Thanks!
    Cheers,
    Costyn

    • Tim Zaman says:

      Well, that’s not officially clear. What is true, is that Everyone can use the NTX2 modules in holland. What is also true, is if you do not have a radio licence, you can not use any of the other modules outside the NTX2’s frequency and power.
      If you do have a radio licence, its more of a question of how you see things. In 2008, the law states that you HAVE to be at your radiotransmitter that time of operation. In a sattelite ofcourse, this is not possible, so no amateur radio law applies.
      BUT, in 2010, the law states, that you CAN use your amateur radio licence in a sattelite, *if* you are able to turn it off. So that might mean you are going to have to implement a receiver on the HAB itself. Otherwise, you could state that its going to turn off anyway after an hour after liftoff. Or, you could get yourself a pretty large sniper rifle and shoot it from the skies.
      Another question kind of over-rules all of this: why would you want to use a more powerful module? i mean, i have sent at 1200baud on 10mw, with ranges up to 460km to schotland with good extracted sentences. Why would you want anything stronger? Also the bandwidth ot the TX2 is way too large, you can tune it though, i have one too. And, the TX2 isnt made for long range, its really tiny.

  2. stefan Taylor says:

    Hi Tim,
    I’m looking at starting my own space project with my kids. What is the board in front of the camera in the picture “Overview of the internals” – red one.
    Where can i get one of these?
    also do you have any of your boards still left that you over ordered.
    Regards,
    Stefan.
    P.S. Nice work on all of it by the way.