🛰️Mini Satellite Ground Station📡
Receive Real Weather Data from Space! A Space-Age Robotics Project for Kids
🌍Welcome to Space Technology!
Imagine being able to receive real weather images directly from satellites orbiting Earth! In this incredible project, you'll build a satellite ground station that can capture weather data from NOAA (National Oceanic and Atmospheric Administration) satellites passing overhead. You'll literally be communicating with satellites in space! 🚀
⚙️How Your Ground Station Will Work:
Monitor when NOAA satellites (NOAA 15, 18, 19) will pass over your location
Catch the radio signals (137 MHz) being broadcast from the satellite
Arduino controls the antenna to follow the satellite as it passes (optional)
Software decodes the signals into weather images and data
Save beautiful weather images showing clouds, storms, and land features
🛠️Materials You'll Need
📡 RTL-SDR Dongle
Software Defined Radio receiver (~$25)
🎛️ Arduino Board
Arduino UNO or Mega (for antenna control)
🍕 Antenna Kit
DIY V-dipole or QFH antenna materials
🔌 USB Hub
For RTL-SDR and Arduino connection
📏 Coaxial Cable
RG-58 or RG-174 (~2-5 meters)
🎯 SMA Connector
To connect antenna to RTL-SDR
🔩 Aluminum Tubing
For antenna construction (if building dipole)
🖥️ Computer
Windows, Mac, or Linux with USB ports
⚡ Servo Motor
For antenna rotation (optional)
📦 PVC Pipe
For antenna mount and support
🌐 Internet
For predicting satellite passes
🔧 Tools
Soldering iron, wire cutters, tape
📋Step-by-Step Instructions
Install Required Software
Download and install these free programs:
• GQRX (radio reception software)
• WXtoImg (satellite image decoder)
• Arduino IDE (for antenna control)
These are the "eyes and ears" of your ground station!
Build Your Antenna
Option A: Simple Monopole (~30 minutes)
• Cut copper wire to 53.5 cm (1/4 wavelength)
• Solder to SMA connector
• Mount vertically on mast
Option B: V-Dipole (~1 hour)
• Build a more powerful antenna
• Better reception and directional
• Better for beginners
Connect RTL-SDR Dongle
• Connect antenna to RTL-SDR via coaxial cable and SMA connector
• Connect RTL-SDR to computer via USB
• Install RTL-SDR drivers from GitHub
• Test connection with GQRX software
Test Radio Reception
• Open GQRX software
• Tune to 137.500 MHz (NOAA 18 frequency)
• You should hear satellite signals or weather radio
• Adjust antenna position for better signal
Find Satellite Pass Times
• Visit heavens-above.com
• Enter your location (latitude/longitude)
• Find NOAA 15, 18, 19 pass predictions
• Set alerts for upcoming passes
• Best passes have high elevation angles!
Record Satellite Pass
• Open GQRX on predicted pass time
• Set recording to WAV format
• Click record as satellite passes overhead
• Follow the satellite visually or track with antenna
• Recording takes about 12-15 minutes per pass
Decode the Image
• Open WXtoImg software
• Load the WAV file you recorded
• Click "Satellite → Decode"
• Select your satellite (NOAA 18/19)
• Wait for processing (2-5 minutes)
• Beautiful weather image appears! 🎉
Set Up Arduino (Optional)
• Connect servo motor for antenna rotation
• Program Arduino to track satellite automatically
• Calculate satellite position using computer
• Send commands to Arduino via serial
• Watch antenna follow the satellite!
Save and Analyze Your Data
• Save all decoded images
• Note the date and time
• Compare images from different passes
• Look for weather patterns and storms
• Create a gallery of your images
Celebrate Your Success! 🚀
• You've received real satellite data!
• You're a space weather scientist!
• Share your images with friends
• Continue capturing passes
• Track weather patterns yourself
📡Simple Monopole Antenna Design
DIY V-Dipole Antenna (Best for Beginners)
↑ Coaxial Cable
│ to RTL-SDR
│
╱─────────┴──────────╲
╱ ╲
╱ ╲
╱ ╲
53 cm 53 cm
(21") (21")
╲ (Copper Wire) ╱ (Copper Wire)
╲ ╭─────────╱
╲ ╱ V-shape
╲───────╱
120°
Total Frequency: 137.5 MHz (NOAA Satellites)
Wavelength: 2.18 meters
Antenna Length: 53 cm per arm (1/4 wavelength)
Angle: 120 degrees (V-dipole configuration)
CONSTRUCTION:
1. Use copper wire (14 AWG or similar)
2. Cut two pieces 53 cm each
3. Solder center to SMA connector
4. Form into V-shape at 120° angle
5. Mount on PVC mast
6. Connect coax cable to SMA
7. Point antenna skyward!
💡Antenna Tips:
✓ Higher is Better: Mount antenna as high as possible (rooftop, pole, tree)
✓ Clear Sky: Needs clear view of southern sky (where satellites pass)
✓ Away from Metal: Avoid metal structures that block signals
✓ Coax Quality: Use good quality coax cable, not cheap stuff
✓ Ground Plane: Add metal ground plane beneath antenna for better reception
✓ Weatherproof: Protect connections from rain and water
📊NOAA Satellite Frequencies
| Satellite | Frequency | Orbital Altitude | Pass Duration |
|---|---|---|---|
| NOAA 15 | 137.620 MHz | 870 km | 12-15 min |
| NOAA 18 | 137.912 MHz | 870 km | 12-15 min |
| NOAA 19 | 137.100 MHz | 870 km | 12-15 min |
💻Arduino Code for Satellite Tracking
Antenna Tracking Control Code
// Satellite Ground Station Antenna Tracker // Arduino Code for NOAA Satellite Tracking // Controls servo motors for Az/El (Azimuth/Elevation) #include// Servo Objects Servo azimuthServo; // Rotate antenna left-right Servo elevationServo; // Rotate antenna up-down // Pin Definitions const int AZIMUTH_PIN = 9; const int ELEVATION_PIN = 10; const int LED_PIN = 13; // Current position int currentAzimuth = 0; int currentElevation = 0; // Satellite position data (from computer) int targetAzimuth = 0; int targetElevation = 0; void setup() { // Initialize Serial communication Serial.begin(9600); // Attach servos to pins azimuthServo.attach(AZIMUTH_PIN); elevationServo.attach(ELEVATION_PIN); // Set initial position azimuthServo.write(0); elevationServo.write(0); // Initialize LED pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); delay(2000); digitalWrite(LED_PIN, LOW); Serial.println("Satellite Tracker Ready!"); Serial.println("Send: AZ: EL: "); } void loop() { // Check for incoming data from computer if (Serial.available()) { String command = Serial.readStringUntil('\n'); parseCommand(command); } // Smoothly move to target position moveToTarget(); delay(100); // Update every 100ms } // Parse incoming commands from computer void parseCommand(String cmd) { cmd.trim(); // Expected format: "AZ:180 EL:45" int azIndex = cmd.indexOf("AZ:"); int elIndex = cmd.indexOf("EL:"); if (azIndex != -1) { String azStr = cmd.substring(azIndex + 3, cmd.indexOf(" ", azIndex)); targetAzimuth = azStr.toInt(); targetAzimuth = constrain(targetAzimuth, 0, 360); } if (elIndex != -1) { String elStr = cmd.substring(elIndex + 3); targetElevation = elStr.toInt(); targetElevation = constrain(targetElevation, 0, 90); } // Confirm receipt Serial.print("Target: AZ="); Serial.print(targetAzimuth); Serial.print(" EL="); Serial.println(targetElevation); // Blink LED to confirm digitalWrite(LED_PIN, HIGH); delay(100); digitalWrite(LED_PIN, LOW); } // Smooth movement to target position void moveToTarget() { // Move Azimuth (with backlash compensation) if (currentAzimuth < targetAzimuth) { currentAzimuth++; } else if (currentAzimuth > targetAzimuth) { currentAzimuth--; } // Move Elevation if (currentElevation < targetElevation) { currentElevation++; } else if (currentElevation > targetElevation) { currentElevation--; } // Convert to servo angles (0-180 degrees) int servoAz = map(currentAzimuth, 0, 360, 0, 180); int servoEl = map(currentElevation, 0, 90, 0, 180); // Send to servos azimuthServo.write(servoAz); elevationServo.write(servoEl); // Print current position every 10 updates static int counter = 0; if (++counter > 10) { Serial.print("Position: AZ="); Serial.print(currentAzimuth); Serial.print(" EL="); Serial.println(currentElevation); counter = 0; } } // Alternative: Kalman Filter for smooth tracking void smoothTracking(int newAz, int newEl) { const float alpha = 0.7; // Smoothing factor currentAzimuth = (alpha * newAz) + ((1 - alpha) * currentAzimuth); currentElevation = (alpha * newEl) + ((1 - alpha) * currentElevation); } // Testing function - move antenna in pattern void testPattern() { // Sweep azimuth for (int az = 0; az <= 360; az += 10) { for (int el = 0; el <= 90; el += 15) { azimuthServo.write(map(az, 0, 360, 0, 180)); elevationServo.write(map(el, 0, 90, 0, 180)); Serial.print("Test: AZ="); Serial.print(az); Serial.print(" EL="); Serial.println(el); delay(500); } } }
Python Script for Satellite Position Calculation
#!/usr/bin/env python3
# Satellite Position Calculator
# Uses PyEphem library to calculate NOAA satellite positions
# Sends commands to Arduino tracker
import ephem
import serial
import time
from datetime import datetime
# Observer location (your ground station)
# Enter your latitude/longitude/elevation
observer = ephem.Observer()
observer.lat = '13.0827' # Chennai latitude (example)
observer.lon = '80.2707' # Chennai longitude (example)
observer.elevation = 0 # Sea level
# NOAA Satellites (Two-Line Element Set format)
# Download latest TLE from https://celestrak.com/
noaa18_tle = [
'NOAA 18',
'1 28654U 05018A 24001.00000000 '
'.00000173 00000-0 15260-3 0 9990',
'2 28654 99.0529 350.6956 0014743 '
'115.7278 244.4687 14.12499846846765'
]
noaa19_tle = [
'NOAA 19',
'1 33591U 09005A 24001.00000000 '
'.00000137 00000-0 12015-3 0 9992',
'2 33591 99.0968 30.2483 0014677 '
'173.5633 186.5970 14.12390254769349'
]
# Create satellite objects
sat18 = ephem.readtle(noaa18_tle[0],
noaa18_tle[1],
noaa18_tle[2])
sat19 = ephem.readtle(noaa19_tle[0],
noaa19_tle[1],
noaa19_tle[2])
# Arduino serial connection
try:
arduino = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
time.sleep(2) # Wait for connection
print("Arduino connected!")
except:
print("Arduino not found. Check USB connection!")
arduino = None
def calculate_position(satellite):
"""Calculate azimuth and elevation of satellite"""
satellite.compute(observer)
azimuth = float(satellite.az) * 180 / 3.14159 # Convert to degrees
elevation = float(satellite.alt) * 180 / 3.14159
return azimuth, elevation
def is_visible(elevation):
"""Check if satellite is above horizon (5 degree minimum)"""
return elevation > 5
def send_to_arduino(azimuth, elevation):
"""Send tracking commands to Arduino"""
if arduino:
command = f"AZ:{int(azimuth)} EL:{int(elevation)}\n"
arduino.write(command.encode())
print(f"Sent: {command.strip()}")
def track_satellite(satellite, satellite_name):
"""Track satellite until it sets"""
print(f"\nTracking {satellite_name}...")
while True:
observer.date = ephem.now()
az, el = calculate_position(satellite)
if is_visible(el):
send_to_arduino(az, el)
current_time = datetime.now().strftime("%H:%M:%S")
print(f"{current_time} - Az: {az:.1f}° El: {el:.1f}°")
else:
print(f"{satellite_name} has set.")
break
time.sleep(1) # Update every 1 second
def find_next_pass(satellite, satellite_name):
"""Find next pass of satellite"""
observer.date = ephem.now()
try:
# Find next rise
rise_time = observer.next_pass(satellite)[0]
set_time = observer.next_pass(satellite)[4]
rise_datetime = ephem.localtime(rise_time)
set_datetime = ephem.localtime(set_time)
print(f"\n{satellite_name} Next Pass:")
print(f"Rise: {rise_datetime.strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Set: {set_datetime.strftime('%Y-%m-%d %H:%M:%S')}")
return rise_datetime
except:
print(f"No more passes for {satellite_name} today")
return None
# Main program
if __name__ == "__main__":
print("NOAA Satellite Tracker")
print("=" * 40)
# Find next passes
next_pass_18 = find_next_pass(sat18, "NOAA 18")
next_pass_19 = find_next_pass(sat19, "NOAA 19")
print("\nWaiting for satellite pass...")
print("Press Ctrl+C to stop")
try:
while True:
observer.date = ephem.now()
# Check both satellites
az18, el18 = calculate_position(sat18)
az19, el19 = calculate_position(sat19)
# Track NOAA 18 if visible
if is_visible(el18):
send_to_arduino(az18, el18)
# Track NOAA 19 if visible
if is_visible(el19):
send_to_arduino(az19, el19)
time.sleep(1)
except KeyboardInterrupt:
print("\nTracking stopped.")
if arduino:
arduino.close()
💻Python Installation:
Install PyEphem:
pip install pyephem pyserial
Download Latest TLE data: Visit celestrak.com and get current Two-Line Element data for NOAA satellites
Run the script:
python3 satellite_tracker.py
🧪Testing Your Ground Station
✅ Test 1: Software Installation (15 min)
Install GQRX, WXtoImg, and verify they open. All software should run smoothly.
✅ Test 2: RTL-SDR Detection (10 min)
Plug in RTL-SDR. Check if GQRX recognizes it. Try tuning to local FM radio station (100 MHz) to verify reception works.
✅ Test 3: Antenna Reception (15 min)
Tune to 137.5 MHz. You should hear satellite signals or static. Better signals mean better antenna!
✅ Test 4: First Recording (30 min)
Wait for first NOAA pass. Record entire pass (should be 12-15 minutes). Monitor signal strength on GQRX.
✅ Test 5: Image Decoding (5 min)
Open WXtoImg. Load WAV file. Click decode. Wait for beautiful weather image! This is the best moment! 🎉
📷What You'll See
Beautiful Weather Images:
Cloud Patterns: High and low pressure systems
Storms: Hurricane and tornado formations
Ice Coverage: Polar ice caps and sea ice
Land Features: Coastlines, mountains, deserts
Sunglint: Reflections from oceans and lakes
Aurora: Northern/Southern Lights (sometimes!)
Weather Phenomena: Dust storms, fog, snow cover
🔧Troubleshooting Guide
Common Problems & Solutions
✓ Check USB cable (try different port)
✓ Install drivers from: https://github.com/osmocom/rtl-sdr
✓ Restart computer after driver installation
✓ Try different USB port (USB 2.0 works better)
✓ Check antenna connections (should be tight)
✓ Move antenna higher and away from obstacles
✓ Try different frequency first (test with FM radio)
✓ Check coax cable for damage or shorts
✓ Reposition antenna for better sky view
✓ Check satellite pass elevation (>30° is better)
✓ Remove metal objects near antenna
✓ Use better quality coax cable
✓ Add LNA (Low Noise Amplifier) for improvement
✓ Make sure you recorded NOAA 18 or 19 (not 15)
✓ Try different satellite in decode options
✓ Ensure recording is at least 12 minutes
✓ Check if audio levels were good during recording
✓ Check COM port (Tools → Serial Monitor)
✓ Verify baud rate is 9600
✓ Make sure Python script has correct port
✓ Test servo motors independently first
🚀Advanced Upgrades!
Boost weak signals by 20+ dB. Makes huge improvement!
Upgrade to RTL-SDR v3 with better accuracy
More complex but much more powerful antenna
Even better images from Meteor-M2 satellites
Make script capture passes automatically 24/7
Contribute your images to scientific research
Decode and display images live as they receive
Control your station from anywhere via internet
⚠️Safety & Important Notes:
✓ Radio Regulations: Receiving is legal in most countries, but check your local regulations
✓ Antenna Safety: Never point antenna at sun during high power transmission (not applicable here, but good to know)
✓ Electrical Safety: Never modify RTL-SDR while powered
✓ Height Safety: Use proper safety equipment when mounting antenna on roof
✓ USB Power: RTL-SDR draws power from USB - use quality cable
🎓Amazing Skills You've Gained!
✅ How radio signals work and how to receive them
✅ How satellites communicate with Earth
✅ How to decode and process satellite data
✅ Understanding orbital mechanics and passes
✅ Weather satellite technology and meteorology
✅ Digital signal processing basics
✅ Arduino automation and control systems
✅ Real-time data capture and analysis
✅ Python programming for sensor data
✅ Contributing to actual science!
✅ Professional-level electronics skills
📚Helpful Resources & Links
🌐 Websites:
• heavens-above.com - Satellite pass predictions
• celestrak.com - TLE data and satellite tracking
• rtl-sdr.com - RTL-SDR tutorials and updates
• www.wxtoimg.com - WXtoImg official site
• gqrx.dk - GQRX radio software
📖 Forums & Communities:
• r/rtlsdr - Reddit community for RTL-SDR
• SatelliteAOM Discord - Live satellite tracking group
• Amateur Radio Relay League - Radio communities
🎓 Learning:
• Watch "NOAA Satellite Reception" tutorials on YouTube
• Read "Receiving NOAA Satellite Images" guides
• Join local radio clubs for help

Comments
Post a Comment