Author: Tanvir

  • How to Play Prayer Adhan Automatically on a Raspberry Pi with a Bluetooth Speaker

    I wanted the Adhan to play in my house at the right times every day without having to remember to open an app. No phone propped up against the wall, no relying on a smart speaker subscription, no touching anything. Just the call to prayer, five times a day, handled.

    A Raspberry Pi Zero 2 W turned out to be the answer. It’s an $18 computer roughly the size of a stick of gum. It runs 24/7, uses almost no power, connects to a Bluetooth speaker, and once it’s set up you genuinely forget it’s there. I’ve been running this setup for months and it has not missed a prayer time.

    Getting there took some troubleshooting. The Bluetooth audio stack on Pi OS is not plug-and-play, and I hit a few walls. This guide covers everything I did, including the parts that didn’t work and what actually fixed them.

    ๐Ÿ“… Last Updated July 2026. Tested on Raspberry Pi OS 2026-06-18, based on Debian 13 “Trixie” with Linux kernel 6.18 LTS. That’s the current stable release from the Raspberry Pi Imager.


    What You’ll Need

    • Raspberry Pi Zero 2 W (~$18 CAD)
    • MicroSD card (8GB or more)
    • Micro USB power adapter (5V 2.5A)
    • Bluetooth speaker
    • WiFi connection
    • A computer for the initial setup

    Why Pi Zero 2 W? It has built-in WiFi and Bluetooth, costs less than a fast food meal, and draws so little power you can leave it plugged in permanently without thinking about it. For a single-purpose device like this, it’s the right call.


    Step 1 โ€” Flash Raspberry Pi OS to Your SD Card

    Download the Raspberry Pi Imager on your computer and open it.

    1. Choose Raspberry Pi Zero 2 W as the device
    2. Choose Raspberry Pi OS Lite (64-bit) as the OS โ€” no desktop needed for this
    3. Choose your SD card
    4. Click Edit Settings before writing and fill in:
      • A hostname (I used nanobot)
      • A username and password โ€” write these down
      • Your WiFi name and password
      • SSH enabled, under the Services tab
    5. Click Save then Write

    Put the SD card in the Pi, plug it in, and give it about a minute to boot.

    Trixie note: The Imager now defaults to Raspberry Pi OS based on Debian 13 “Trixie.” That’s what this guide is written for.


    Step 2 โ€” Connect to Your Pi

    You don’t need a monitor. Two options:

    Option A โ€” Raspberry Pi Connect (what I use)

    Go to connect.raspberrypi.com, make a free account, and link your Pi. Then click Remote Terminal and you have a full terminal in your browser โ€” from anywhere in the world, no router port-forwarding needed.

    Option B โ€” SSH

    If you’re on the same network, open Terminal (Mac/Linux) or PuTTY (Windows) and run:

    ssh yourusername@nanobot.local

    Step 3 โ€” Update Everything First

    Before anything else, run a full update. Skip this and you’ll hit weird dependency issues later.

    sudo apt update && sudo apt upgrade -y

    It takes a few minutes. Let it finish.


    Step 4 โ€” Unblock Bluetooth (Trixie Only)

    This tripped me up. On Trixie, the Bluetooth radio can be blocked at the hardware level by default. Your speaker simply won’t show up during scanning if you skip this.

    sudo rfkill unblock bluetooth
    sudo systemctl restart bluetooth

    One-time fix. You won’t need to run it again.


    Step 5 โ€” Install Required Packages

    sudo apt install -y git python3 python3-pip bluez bluez-alsa-utils sox

    That installs Git to download PiPrayer, Python to run the prayer calculator, the Bluetooth audio stack, and Sox for audio conversion.


    Step 6 โ€” Disable PipeWire

    This is the step that took me the most time to figure out. Trixie runs PipeWire as the default audio system, and on the Pi Zero 2 W it flat-out fights with Bluetooth audio. Both systems try to grab the Bluetooth device and they cancel each other out. No PipeWire, no problem.

    systemctl --user stop pipewire.socket pipewire-pulse.socket wireplumber
    systemctl --user disable pipewire.socket pipewire-pulse.socket wireplumber
    sudo reboot

    The Pi reboots. Reconnect after 30-60 seconds.

    Don’t skip this. I spent a long time debugging why the Bluetooth speaker kept failing to produce audio. This was the reason every time.


    Step 7 โ€” Start BlueALSA

    After the reboot, enable BlueALSA as the audio backend:

    sudo systemctl enable bluealsa
    sudo systemctl start bluealsa

    Step 8 โ€” Pair Your Bluetooth Speaker

    Put the speaker in pairing mode, then:

    bluetoothctl

    Type these one at a time. Don’t paste them all together:

    power on
    agent on
    scan on

    Wait for your speaker to appear. If you see a wall of MAC addresses and don’t know which is yours, type devices to see the names alongside them.

    Once you spot it, run these (swap in your actual MAC address):

    pair B8:D3:A2:03:7A:77
    trust B8:D3:A2:03:7A:77
    connect B8:D3:A2:03:7A:77
    exit

    The trust command matters. Without it, the Pi won’t auto-reconnect to the speaker after a reboot.


    Step 9 โ€” Verify Audio is Working

    Check that BlueALSA sees the speaker:

    bluealsa-aplay -l

    Your speaker should appear. Then play a test sound (use your MAC address):

    aplay -D bluealsa:DEV=B8:D3:A2:03:7A:77,PROFILE=a2dp /usr/share/sounds/alsa/Front_Center.wav

    If you hear something, you’re past the hard part.


    Step 10 โ€” Set the Speaker as Default Audio (Optional)

    If you want every audio command to use the Bluetooth speaker automatically without specifying it each time:

    nano ~/.asoundrc

    Paste this with your MAC address:

    defaults.bluealsa.interface "hci0"
    defaults.bluealsa.device "B8:D3:A2:03:7A:77"
    defaults.bluealsa.profile "a2dp"

    Save with Ctrl+X, Y, Enter.


    Step 11 โ€” Stop the Speaker from Disconnecting

    Left alone, the Pi’s Bluetooth goes into power saving mode and drops the connection after a while. Here’s the fix.

    Part A โ€” Turn on AutoEnable

    sudo nano /etc/bluetooth/main.conf

    Find this line:

    #AutoEnable=true

    Remove the # so it reads:

    AutoEnable=true

    Save and exit.

    Part B โ€” Add a Reconnect Script

    This runs every 5 minutes and reconnects the speaker if it dropped:

    nano ~/piprayer/reconnect-bt.sh

    Paste this (your MAC address):

    #!/bin/bash
    STATUS=$(bluetoothctl info B8:D3:A2:03:7A:77 | grep "Connected: yes")
    if [ -z "$STATUS" ]; then
        bluetoothctl connect B8:D3:A2:03:7A:77
    fi

    Make it executable:

    chmod +x ~/piprayer/reconnect-bt.sh

    Part C โ€” Add it to Cron

    crontab -e

    Add this line:

    */5 * * * * /home/admin/piprayer/reconnect-bt.sh

    Save and exit. Now even if the speaker disconnects, it comes back on its own within 5 minutes.


    Step 12 โ€” Download PiPrayer

    PiPrayer is a free open-source tool that calculates prayer times from GPS coordinates and plays an Adhan recording at each one. Exactly what we need.

    cd ~
    git clone https://github.com/kamranzafar/piprayer.git
    cd piprayer
    pip3 install configparser --break-system-packages

    Step 13 โ€” Fix the Audio Quality

    The Adhan files that come with PiPrayer are recorded at 8000 Hz. Over Bluetooth, they sound rough. This converts all 15 recordings to 44100 Hz stereo in one shot:

    cd ~/piprayer/media
    for f in azaan-*.wav; do sox "$f" -r 44100 -c 2 "tmp_$f" && mv "tmp_$f" "$f"; done

    Takes about 2 minutes. The difference in sound quality is noticeable.


    Step 14 โ€” Update the Play Script

    PiPrayer’s built-in script uses PulseAudio to play sound. Since we’re using BlueALSA, we need to change one line:

    nano ~/piprayer/play-azaan.sh

    Find:

    paplay $(dirname "$0")/media/azaan-"$1".wav

    Replace with (your MAC address):

    aplay -D bluealsa:DEV=B8:D3:A2:03:7A:77,PROFILE=a2dp $(dirname "$0")/media/azaan-"$1".wav

    Save and exit.


    Step 15 โ€” Set Your Location

    Create the config file PiPrayer reads for your location and calculation method:

    nano ~/piprayer/.piprayer

    Paste this and update the coordinates and offset for your city:

    [Default]
    lat = 44.6505
    lng = -63.5977
    gmt-offset = -3
    dst = 0
    method = ISNA
    asr-time = Standard
    prayers = Fajr:0, Dhuhr:0, Asr:0, Maghrib:0, Isha:0

    Save and exit.

    Finding your coordinates: Search “your city name coordinates” on Google.

    GMT offset: Atlantic is -3 in summer and -4 in winter. Eastern: -4/-5. Central: -5/-6. Mountain: -6/-7. Pacific: -7/-8.

    Calculation method: ISNA is standard for Canada and the US. Other options: MWL, Egypt, Karachi, Makkah. Use whatever your local mosque follows.


    Step 16 โ€” Match Your Mosque’s Times (Optional)

    Calculated times don’t always line up exactly with what your mosque publishes. You can apply a minute offset to each prayer to match. First, check what the calculator gives you:

    cd ~/piprayer
    python3 piprayer.py .piprayer

    Compare that against Muslim Pro or your mosque’s schedule. If Maghrib is 8 minutes off, update the config:

    prayers = Fajr:0, Dhuhr:0, Asr:0, Maghrib:8, Isha:0

    Negative numbers subtract minutes. Re-run the command above to confirm.


    Step 17 โ€” Pick Your Adhan

    PiPrayer comes with 15 different recordings. Try a few:

    bash ~/piprayer/play-azaan.sh 1

    Change the number at the end to try others (1 through 15). Pick your favourite before moving on.


    Step 18 โ€” Set Up the Automatic Schedule

    This is the step that makes it all run itself. Replace the 1 with whichever Adhan number you chose:

    cd ~/piprayer
    export XDG_RUNTIME_DIR=/run/user/1000
    bash setup-piprayer.sh 1

    Check that the schedule looks right:

    crontab -l

    You should see five prayer entries plus a line at 1:00 AM that recalculates times for the next day. Something like:

    ## PI PRAYER ##
    55 03 * * * export XDG_RUNTIME_DIR=/run/user/1000 && /home/admin/piprayer/play-azaan.sh 1 #fajr
    11 13 * * * export XDG_RUNTIME_DIR=/run/user/1000 && /home/admin/piprayer/play-azaan.sh 1 #dhuhr
    17 17 * * * export XDG_RUNTIME_DIR=/run/user/1000 && /home/admin/piprayer/play-azaan.sh 1 #asr
    44 20 * * * export XDG_RUNTIME_DIR=/run/user/1000 && /home/admin/piprayer/play-azaan.sh 1 #maghrib
    27 22 * * * export XDG_RUNTIME_DIR=/run/user/1000 && /home/admin/piprayer/play-azaan.sh 1 #isha
    0 1 * * * export XDG_RUNTIME_DIR=/run/user/1000 && /home/admin/piprayer/setup-piprayer.sh 1
    ## PI PRAYER ##

    Step 19 โ€” Handle Daylight Saving Automatically

    Twice a year the clocks change and the GMT offset needs to update. This script does it for you every night so you never have to think about it:

    nano ~/piprayer/update-offset.sh

    Paste this (update the timezone code and offsets for your region):

    #!/bin/bash
    CONFIG=~/piprayer/.piprayer
    IS_DST=$(date +%Z)
    if [ "$IS_DST" = "ADT" ]; then
        sed -i 's/gmt-offset = .*/gmt-offset = -3/' "$CONFIG"
    else
        sed -i 's/gmt-offset = .*/gmt-offset = -4/' "$CONFIG"
    fi

    Make it executable:

    chmod +x ~/piprayer/update-offset.sh

    Add it to cron, just before the 1 AM recalculation:

    crontab -e

    Add this at the very top:

    50 0 * * * /home/admin/piprayer/update-offset.sh

    Save and exit.

    For other timezones: Change ADT to your summer abbreviation (EDT, CDT, MDT, PDT) and update the offset values.


    Step 20 โ€” Final Reboot

    Reboot and confirm everything comes back up on its own:

    sudo reboot

    Wait a minute after it boots, then test:

    bash ~/piprayer/play-azaan.sh 1

    If the Adhan plays through the speaker, you’re done.


    What the Pi Does Every Day

    • 12:50 AM โ€” Checks the timezone and updates the GMT offset if DST changed
    • 1:00 AM โ€” Recalculates tomorrow’s five prayer times based on your coordinates
    • Every 5 minutes โ€” Checks if the Bluetooth speaker is connected and reconnects if not
    • Fajr, Dhuhr, Asr, Maghrib, Isha โ€” Adhan plays at the correct local time

    No apps. No subscriptions. No touching anything. It just works.


    Troubleshooting

    Speaker not showing up during scan: Almost certainly the rfkill issue. Run sudo rfkill unblock bluetooth and sudo systemctl restart bluetooth, then try scanning again. That’s Step 4 โ€” go back and check.

    Speaker connects but no sound: Make sure PipeWire is still disabled. Run systemctl --user status pipewire and if it’s active, re-run the disable commands from Step 6.

    Speaker disconnects after a while: Check that the reconnect script from Step 11 is in your crontab (crontab -l) and that AutoEnable is set to true in /etc/bluetooth/main.conf.

    Prayer times off by an hour: Your gmt-offset is wrong. Check what timezone your Pi thinks it’s in with date, then update the offset in ~/piprayer/.piprayer to match.

    Audio sounds bad: You probably skipped Step 13. Run those sox commands now and the quality will improve immediately.

    Cron not running: Run echo $XDG_RUNTIME_DIR and confirm it returns /run/user/1000. If your user ID is different, update the cron entries to match.


    Optional Upgrades

    Switch Adhan recording: Run bash setup-piprayer.sh 5 with any number from 1 to 15. The cron schedule updates automatically.

    Use your own recording: Convert any MP3 to WAV first:

    sox your-adhan.mp3 -r 44100 -c 2 ~/piprayer/media/azaan-16.wav

    Then run bash setup-piprayer.sh 16.

    Add Pi-hole: The Pi Zero 2 W handles both the prayer clock and Pi-hole (network-wide ad blocking) without breaking a sweat. Two useful things on one $18 device. See pi-hole.net for setup.

    SSH from anywhere: Raspberry Pi Connect handles browser access already. For SSH from your phone, Tailscale is the easiest option:

    curl -fsSL https://tailscale.com/install.sh | sh
    sudo tailscale up

    Install Tailscale on your phone and your Pi shows up like it’s on your local network, from anywhere.


    If something in here saved you time, pass it along. And if you hit a problem that’s not covered, drop it in the comments and I’ll take a look.

  • Hello world!

    Welcome to WordPress. This is your first post. Edit or delete it, then start writing!