Setup your Radar

Build a privacy-first traffic radar; 1x Pi, no cameras, no cloud, just local speed data PDFs

April 15, 2026
22 min read

A weatherproof traffic logger that keeps data local, requires no cameras, and helps you make a data-informed case for safer streets.

Difficulty: Intermediate • Time: 2–4 hours • Cost: $650


On this page
  1. Introduction
  2. Before you begin
  3. Privacy considerations
  4. What you will build
  5. Parts list
  6. Step-by-step build guide
  7. Take your data to city hall
  8. Network access and security
  9. Updating the software
  10. Backup and restore
  11. Troubleshooting
  12. Maintenance
  13. Reference
  14. Links

Introduction #

Safer streets start with measured traffic speeds.

One afternoon, a Raspberry Pi, and a radar sensor. By the evening you will have a speed monitor logging every vehicle that passes, a live dashboard, and the beginnings of the dataset that goes to your next council meeting. No cameras, no licence plates, no cloud accounts: just local speed data on hardware you own.

Before you begin #

Tools needed:

  • Computer with Raspberry Pi Imager installed
  • 5/16" nut driver (steel bands)
  • Screwdriver
  • Handsaw or circular saw
  • Drill and bits
  • Pencil and tape measure
  • Optional: mitre box for 45° cuts
  • Optional: multimeter

No soldering required · No coding required · No prior radar experience needed


Privacy considerations #

What this system collects #

Collected Vehicle speed, direction, timestamp
Not collected No licence plates, no vehicle photos, no driver identity
Not transmitted All data stays on your device

Compliance #

Measuring vehicle speeds on public streets from your own property is generally legal. Mounting on public utility poles requires explicit permission. Always check your local regulations.


What you will build #

Complete assembled velocity.report unit: weatherproof enclosure mounted on a pole with cables routed

  • Doppler radar logger: captures vehicle speeds 24/7
  • Local SQLite database: all data stays on the device
  • Live web dashboard: real-time speeds, histograms, time-of-day patterns
  • Professional PDF reports: traffic engineering metrics (p50, p85, p98)
  • Weatherproof hardware: designed for permanent outdoor deployment

The velocity.report Pi image includes everything pre-configured: flash one SD card, connect one sensor, and it starts collecting.


Parts list #

Part Price Notes
Radar sensor OPS7243-A-CW-R2 $420 IP67, 100 m range, RS232
Sensor mounting bracket OPS100-BK $50 Metal bracket for OPS7243 enclosure
Sensor cable OPS700-CBL-M1-PT-1.8 $17 M12 to pigtail; connects sensor to serial HAT
Raspberry Pi 4 (2 GB) $55 Also compatible with Pi 5
Waveshare PoE HAT (F) $20 Powers the Pi + sensor over Ethernet
Waveshare RS232 HAT $16 RS232 interface for the sensor
Adafruit DE-9 serial connector $3 Connects sensor cable to serial HAT
SanDisk High Endurance 32 GB $23 High-endurance; designed for continuous writes
Core total $604
ABS pipe, 4-in × 2-ft $25 Sensor mast
Timber stud, 2×4 × 8-ft $4 Crossbar and upright
Hose clamps ×2 $6 Clamp crossbar to roof rack bars
Corner braces, 4-pack $5 Brace the T-frame
Deck screws, 67-pack $6 Frame assembly
Full total $650 Core + roof rack mount

Power is delivered over Ethernet via the PoE HAT. You will need a PoE-capable switch or injector on the network side. For mobile deployment you will also need a PoE battery pack or 12 V car outlet adapter, and a short Ethernet cable.


Step-by-step build guide #

Build overview (total time: 2–4 hours)

  1. Wire the Sensor to the Raspberry Pi: 15–30 minutes
  2. Flash the Pi Image: 10–15 minutes
  3. Access the Web Dashboard: 5 minutes
  4. Mount the Radar Sensor: 1–2 hours
  5. Configure Your Site: 10 minutes
  6. Generate Reports: after data collection

Step 1: wire the sensor to the Raspberry Pi #

Estimated time: 15–30 minutes

The OPS7243-A-CW-R2 sensor connects to the Raspberry Pi via an RS232 serial HAT. The PoE HAT stacks on top to provide power over Ethernet.

HAT stacking: PoE HAT on Raspberry Pi 4, serial HAT stacked on top

  1. Attach the PoE HAT to the Raspberry Pi’s 40-pin GPIO header

  2. Stack the serial HAT (Waveshare RS232/485) on top of the PoE HAT. Ensure all pins are aligned and fully seated.

  3. Wire the sensor to the HAT following the wiring diagram below:

Radar wiring diagram: M12 cable from OPS7243 sensor through pigtail and DE-9 connector to Waveshare RS232 HAT


Step 2: flash the Pi image #

Estimated time: 10–15 minutes

The velocity.report image is a complete Raspberry Pi OS with everything pre-installed and pre-configured; flash it to an SD card and the system is ready to run.

This opens Raspberry Pi Imager with the velocity.report image pre-loaded:

macOS

cd "/Applications/Raspberry Pi Imager.app/Contents/MacOS/" && \
  ./rpi-imager --repo https://velocity.report/rpi.json

Linux

rpi-imager --repo https://velocity.report/rpi.json

Windows

"C:\Program Files (x86)\Raspberry Pi Imager\rpi-imager.exe" --repo https://velocity.report/rpi.json

Screenshot of the Raspberry Pi Imager

  1. Select your Pi model
  2. Select velocity.report from the OS list
  3. Choose your SD card (32 GB high-endurance recommended)
  4. Configure settings before writing:
    • Click the gear icon (⚙) or Edit Settings
    • Set hostname: velocity (or your preference)
    • Enable SSH: select Allow public-key authentication only and paste your public key (recommended). If you do not have an SSH key, select password authentication and choose a strong password.
    • Set username and password: choose a username and password (required even with key authentication, for sudo)
    • Configure Wi-Fi (optional): the Pi connects via Ethernet by default through the PoE HAT. Add Wi-Fi credentials only if you need wireless access as a fallback or for initial setup without Ethernet.
  5. Write the image

Option B: manual download #

  1. Download the latest .img.xz file from GitHub Releases
  2. Open Raspberry Pi Imager, select Choose OSUse custom, and select the file
  3. Configure settings as above, then write

After flashing #

  1. Insert the SD card into your Raspberry Pi and connect the PoE Ethernet cable
  2. Wait 1–2 minutes for first boot, then connect:
ssh velocity@velocity.local

The service starts automatically on boot and configures the sensor (JSON mode, units, magnitude). Verify it is running:

velocity-status

To watch live logs:

velocity-log

The image installs shell aliases for common operations: velocity-status, velocity-log, velocity-bounce (restart), velocity-stop, and velocity-start. See the Reference section for the full list.


Step 3: access the web dashboard #

Estimated time: 5 minutes

Open a browser on any device on the same network: https://velocity.local

The Pi generates a self-signed TLS certificate on first boot. Your browser will show a certificate warning: this is expected for a self-signed certificate. Click Advanced → Proceed to velocity.local (Chrome/Edge) or Accept the Risk and Continue (Firefox/Safari). No certificate installation is needed.

Success criteria: the dashboard loads and shows live vehicle detections or “No data yet”

Web dashboard showing live speed detections, histogram, and time-of-day chart

If the dashboard will not load:

  1. Check the service is running: velocity-status
  2. Find the Pi’s IP address: hostname -I
  3. Test from the Pi itself: curl -k https://localhost/
  4. Check logs: velocity-log

Step 4: mount the radar sensor #

Estimated time: 1–2 hours

The same hardware supports two deployment modes: a portable rig on your car roof rack, or a fixed mount at home. Pick whichever suits the situation, or build both and move the sensor to whichever street needs attention this month.

Deployment option A: car roof rack mount (mobile) #

A portable rig that clamps to a standard roof rack. Park on any street, collect data for a few hours or a few days, then drive to the next location. One sensor, many streets.

Parts are listed in the parts list above. You will also need a PoE battery pack or 12 V car outlet adapter, and a short Ethernet cable from sensor to Pi.

Engineering drawing: isometric view of the roof rack sensor mount with bill of materials

Building the roof rack mount

Completed T-frame mount: 32-inch crossbar, 24-inch upright, and two 45° braces with PVC pipe

  1. Cut the 2×4 into four pieces: one 32-inch crossbar, one 24-inch upright, and two 11-inch braces (top-edge measurement, 45° mitres at both ends).

  2. Build the main T-joint first: centre the upright on the crossbar and fasten it with corner brackets and deck screws so it stands properly vertical.

  3. Fit the two 45° braces, one each side, and fasten with the remaining brackets and deck screws. These braces are what keep the structure from developing opinions in the wind.

  4. Mark two pipe fixing points where it overlaps the wooden upright: 6-inch and 12-inch up from the bottom of the pipe. Drill pilot holes through the pipe into the wood.

  5. Attach the pipe to the upright: hold the pipe vertical against the upright and drive screws through the pilot holes into the wood until the mast is locked in place.

  6. Measure roof-rack bar spacing centre-to-centre, then mark and drill matching clamp holes in the crossbar.

  7. Attach the sensor to the pipe. Use hose clamps to secure the sensor body to the pipe. Tighten evenly.

  8. Clamp the crossbar to the roof rack. Use the two 1-13/16 to 3 in galvanised clamps and tighten firmly so the mount stays stable in wind while parked.

  9. Route the cable from the sensor through a rear window seal or sunroof into the car. Connect to the Pi and power source inside.

Completed roof rack mount installed on a car

Do not drive with the mount attached!

Deployment option B: home installation (permanent) #

A permanent mount on your property, aimed at the street.

Positioning:

  • Mount 4–8 feet off the ground (reduces false detections from small objects)
  • Use two stainless steel hose clamps (top and bottom)
  • Choose a location with a clear line of sight to traffic

Weatherproofing checklist:

  • ✅ Enclosure gasket intact and clean
  • ✅ Seal tested before final mounting
  • ✅ All cable glands sealed

Success criteria: enclosure is weatherproof, sensor aims correctly, mounting is secure

Aiming the sensor #

Once the sensor is mounted, aim it before collecting data. These guidelines apply to both deployments. For the mobile mount, parking parallel to the kerb already puts you close to 0°.

Aiming reference: sensor beam direction relative to traffic flow on Sutro Street

  • Angle: as close to 0° (parallel with traffic flow) as practical, typically 15–25°. Lower angles need less cosine correction, so the speed readings are more accurate.
  • Road coverage: the beam must encompass the full lane of traffic you are measuring. Angling the sensor 15–25° widens the field-of-view triangle enough to capture vehicles across the lane while keeping cosine error small. Choose the smallest angle whose beam triangle fully covers the lane.
  • Orientation: face approaching or receding traffic (not perpendicular)

Radar beam cone angle: top-down view showing sensor angle to direction of travel

Recording your mounting angle

You will enter this in the dashboard as the cosine error angle (Step 5).

  1. Take a photo looking straight down at the road surface, perpendicular to the kerb. Include the sensor and the road in the frame.
  2. Draw one line along the kerb and a second line from the sensor along its beam direction.
  3. Measure the angle between the two lines and subtract from 90°. A phone protractor app works.

Step 5: configure your site #

Estimated time: 10 minutes

Before generating reports, configure your site in the dashboard so speed measurements are corrected for your mounting angle.

  1. Open the dashboard at https://velocity.local
  2. Navigate to Site Settings
  3. Set the site location on the interactive map
  4. Set the cosine error angle to match your radar mounting angle from Step 4. Drag the red dot on the radar field-of-view triangle to adjust the angle visually, or type the value directly. The triangle should encompass the road lanes you want to measure.
  5. Add any notes about the installation (useful for later reference)
  6. Save the configuration

The system stores this as the active site configuration period. Reports use the angle automatically to correct measured speeds. If you change the mounting angle later, create a new configuration period so historical reports remain accurate.


Step 6: generate reports #

After collecting data for a few days, generate professional reports from the dashboard.

  1. Open the dashboard at https://velocity.local
  2. Select your site and set the date range for the report period
  3. Click Generate Report
  4. Download the PDF

The report uses the cosine error angle from your site configuration (Step 5) to correct measured speeds automatically.

What the report includes:

  • p50 (median): half of vehicles go faster than this
  • p85 (traffic engineering standard): speed at which 85% of traffic travels at or below
  • p98 (top 2%): threshold where the fastest regular drivers operate
  • Speed distribution histograms and time-of-day charts

The dashboard also supports comparison reports for measuring the effect of traffic calming interventions: select two date ranges and the report shows side-by-side metrics with percentage changes.


Take your data to city hall #

Print the report. Bring it to the meeting. The data does the persuading.

Whether you are at a city council session, a town board hearing, or submitting written comments to a transport committee, the approach is the same: state the measured speed, explain what it means, and make clear that you intend to keep measuring.

What to bring #

Sample PDF report page showing speed histogram, p85 metric, and site map

  • Printed PDF report: a physical document can be held, marked up, and filed into the public record. Screen shares cannot.
  • Site photos: the street, the school, the park, the crossing. Data tells the story; photos make it concrete.
  • Before-and-after comparison: if the council has already approved changes, bring the comparison report. Did p85 drop? Did it stay down?

What to say #

Lead with the metric traffic engineers already use:

“The 85th-percentile speed on [street name] is [X] mph. The posted limit is [Y] mph.”

The p85 is the standard threshold in US federal speed surveys and UK Department for Transport assessments. Using it means your data speaks the same language as a professional traffic study.

Then adapt to the situation:

  • If the intervention worked: “After the [speed hump / signage / enforcement], p85 dropped from [X] to [Y] mph.”
  • If it worked and then wore off: “p85 dropped initially. [N] months later it has returned to [W] mph.”
  • If nothing has changed: “We have [N] weeks of continuous data. The p85 is [X] mph, consistently [Z] mph above the posted limit. This is the normal condition of this street.”

In January 2026, a velocity.report user took 6,000 transits from Clarendon Avenue (a 25 mph school zone on San Francisco’s high-injury network) to the SFMTA board. After repaving, median speed was up 8% to 33 mph and p85 up 5% to 39 mph. The ask: publish a before-and-after scoreboard for every project, and keep iterating until the speeds actually drop.

What to suggest #

Present the problem first, then name what might help:

  • Speed humps or raised crossings: reduce p85 by 5–15 mph in most studies
  • Kerb extensions: narrow the crossing distance
  • Chicanes or lane narrowing: remove the straight-line path
  • 20 mph zones: lower posted limits near schools and parks
  • Radar speed signs: real-time driver feedback
  • Targeted enforcement: your time-of-day data shows peak hours

You do not need to prescribe the answer. Present the evidence, name the options, and ask what the council can commit to and when.

Keep measuring #

Attend regularly. Each presentation enters the public record. Share the report with neighbours, the local press, and your elected representative.

  • Baseline before any intervention
  • Initial effect in the first weeks after a change
  • Long-term compliance in the months that follow
  • Regression: whether speeds drift back once the novelty wears off

A week of data shows patterns. A month is compelling. Three months across seasons is the kind of evidence that holds up in a budget discussion. The community that keeps measuring is the one that gets heard.


Network access and security #

The dashboard runs on HTTPS (port 443) and is accessible to any device on your local network. The Pi generates a self-signed TLS certificate on first boot; HTTP requests on port 80 redirect to HTTPS automatically. Your router firewall blocks external access by default, and no data leaves the network.

Best practices:

  • Use SSH key authentication (configured during flashing)
  • Use a strong Wi-Fi password (WPA3 if supported) if Wi-Fi is enabled
  • Keep the OS updated: sudo apt update && sudo apt upgrade

Tailscale provides secure remote access without exposing your Pi to the public internet. Free for personal use. It is also the cleanest way to access the dashboard: Tailscale assigns your device a *.ts.net hostname with a valid Let’s Encrypt certificate, which means no browser warnings and no certificate exceptions required.

# Install Tailscale on your Pi
curl -fsSL https://tailscale.com/install.sh | sh

# Start Tailscale and authenticate
sudo tailscale up

Follow the authentication URL, install Tailscale on your phone or laptop, then access the dashboard at https://<hostname>.<tailnet>.ts.net — this URL has a valid certificate and works without any exception.

See the Tailscale documentation for details.

Shared and untrusted networks #

If the Pi is connected to a shared network (school, workplace, library, or multi-tenant building), other devices on that network can reach the dashboard. The dashboard has no user authentication: anyone who can reach port 443 can view your data.

Recommended isolation:

  • VLAN: place the Pi on a dedicated VLAN or network segment so only your devices can reach it. Most managed switches and many consumer routers support VLAN configuration.
  • Firewall rules: if VLAN isolation is not available, configure the router or switch to restrict access to the Pi’s IP address to specific client devices.
  • Dedicated network: for permanent installations, a small dedicated switch or router (connected to the PoE injector) keeps the Pi off the shared network entirely.

If you cannot isolate the device, use Tailscale (above) and disable the Pi’s local network listener.

Public internet #

Do not expose this service to the public internet. The TLS certificate is self-signed and the dashboard has no user authentication. Use Tailscale for remote access.


Updating the software #

The image makes zero unsolicited network requests. Updates happen when you decide.

# Check whether a newer version is available
sudo velocity-ctl upgrade --check

# Download and apply the latest release
sudo velocity-ctl upgrade

# If something goes wrong, roll back
sudo velocity-ctl rollback

Updates replace the server binary and run any database migrations. Your data and configuration are preserved. For air-gapped deployments:

sudo velocity-ctl upgrade --binary /path/to/velocity-report

Backup and restore #

Back up before re-flashing. Your sensor data took weeks to collect; the software can be re-flashed in ten minutes.

Back up your data #

The database lives at /var/lib/velocity-report/sensor_data.db.

sudo velocity-ctl backup

This creates a timestamped copy in /var/lib/velocity-report/backups/. If you are about to re-flash the SD card, copy the backup off the Pi first:

# From your laptop
scp velocity@velocity.local:/var/lib/velocity-report/sensor_data.db \
  ~/sensor_data_backup_$(date +%Y%m%d).db

Re-flash and restore #

  1. Re-flash the SD card using Step 2
  2. Boot the Pi and verify the service runs (velocity-status)
  3. Stop the service: velocity-stop
  4. Copy the backup into place:
# From your laptop
scp ~/sensor_data_backup_20260326.db \
  velocity@velocity.local:/tmp/sensor_data.db

# On the Pi
sudo cp /tmp/sensor_data.db /var/lib/velocity-report/sensor_data.db
sudo chown velocity:velocity /var/lib/velocity-report/sensor_data.db
  1. Start the service: it detects the existing database and runs any pending migrations automatically.
velocity-start

Troubleshooting #

Problem Fix
No sensor data ls /dev/serial0 or ls /dev/velocity-radar to check the device
Service will not start velocity-log to check logs
Dashboard will not load velocity-status to verify the service
Certificate warning Click Advanced → Proceed (Chrome/Edge) or Accept the Risk and Continue (Firefox/Safari)
Garbled or CSV output Connect via screen /dev/serial0 19200 and send OJ then A!
Permission denied sudo usermod -a -G dialout $USER then log out and back in

USB-serial adapters get a /dev/velocity-radar symlink automatically.


Maintenance #

  • Check the enclosure monthly for condensation
  • Clean the sensor window seasonally
  • Run sudo velocity-ctl upgrade --check periodically

Reference #

What the image includes #

Component Location Purpose
velocity-report server /usr/local/bin/velocity-report Radar data collection and web dashboard
velocity-ctl /usr/local/bin/velocity-ctl Device management and updates
PDF generator /opt/velocity-report/tools/pdf-generator/ Professional traffic reports
Systemd service /etc/systemd/system/velocity-report.service Starts automatically on boot
Nginx reverse proxy /etc/nginx/sites-enabled/velocity TLS termination, HTTPS on port 443
TLS certificates /var/lib/velocity-report/tls/ Self-signed CA and server certificate

The image also pre-configures serial port settings, UART overlays, sensor initialisation (JSON mode, units, magnitude reporting), and the service user.

Commands #

Command Purpose
velocity-status systemctl status velocity-report.service
velocity-log journalctl -u velocity-report.service -u nginx.service -f
velocity-bounce sudo systemctl restart velocity-report.service
velocity-stop sudo systemctl stop velocity-report.service
velocity-start sudo systemctl start velocity-report.service
velocity-report version Print the installed server version
sudo velocity-ctl upgrade --check Check whether a newer release is available
sudo velocity-ctl upgrade Download and apply the latest release
sudo velocity-ctl rollback Restore the previous version
sudo velocity-ctl backup Create a timestamped snapshot of binary and database


Back to top

Need Help?

Found something unclear? Have questions or suggestions?