MMDVMCal step by step: calibrating an MMDVM modem
MMDVM hotspots built on MMDVM_HS (ZUMspot, HS_Hat, SkyBridge and the like) use a cheap TCXO that easily drifts hundreds of hertz off its nominal frequency. For voice this is almost unnoticeable, but for data and SMS even 100–300 Hz of offset can cause decoding errors and packet loss. MMDVMCal is the official interactive utility from the author of MMDVM (G4KLX); it lets you find the modem's exact operating frequency, measure BER and set TX/RX levels — all straight from the command line, without editing config files by hand.
What MMDVMCal is and how it works
MMDVMCal is a standalone program (repository g4klx/MMDVMCal) that talks directly to the modem over the serial port. While the utility is running, MMDVMHost must be stopped — the two cannot use the same port at the same time.
On Pi-Star and RadioStar this is handled automatically by the launch command. Control is keyboard-only: each key instantly changes a parameter or switches a mode. On exit (Q) the program prints the final offset values.
Launching the utility
On Pi-Star and compatible images (including RadioStar) you use a wrapper:
sudo pistar-mmdvmcal
It stops MMDVMHost itself, launches MMDVMCal with the right port and config, and restores the service after you exit. On a "bare" Raspberry Pi without Pi-Star, launching looks like this:
sudo systemctl stop mmdvmhost
MMDVMCal /etc/MMDVM.ini
After launch you will see a prompt like this:
MMDVMCal (20231015) by G4KLX
H/h=help, Q/q=quit ...
MMDVMCal key reference
The program is controlled by single keypresses. The main keys:
- H / h — show help right in the terminal;
- Q / q — quit, printing the final offsets;
- E / e — enter the operating frequency in Hz (for example, 434250000);
- F — increase the frequency by one step;
- f — decrease the frequency by one step;
- Z / z — set the frequency step in Hz;
- T — increase TX deviation (TXLevel);
- t — decrease TX deviation;
- R / r — increase / decrease the receive level (RXLevel);
- P / p — increase / decrease RF power;
- b — DMR Simplex BER test mode (FEC), receiving from the radio;
- B — BER test mode with a 1031 Hz test pattern (internal generator);
- D / d — DMR Deviation mode: generates a 1.2 kHz sine wave for an oscilloscope;
- C / c — Carrier Only mode, no modulation;
- K / k — D-Star BER test (FEC);
- Space — turn transmission (TX) on / off;
- W / w — turn the modem's debug messages on / off.
Step 1: set the operating frequency
Before you start, you need to tell MMDVMCal which frequency your hotspot runs on. Press E and the utility will ask you to enter a frequency in Hz. Enter your hotspot's frequency as a whole number, without dots or spaces:
E
Enter frequency (Hz): 434250000
For the 70 cm band (430–440 MHz), typical hotspot values fall in the range 430000000–440000000. For 2 m (144–146 MHz), accordingly.
Step 2: BER test and frequency tuning
This is the key stage. The goal is to find the frequency at which the modem decodes your signal with the lowest BER.
- Press b to enter DMR Simplex BER Test mode (FEC).
- Transmit a short phrase from the radio (or just press PTT and hold it for a few seconds). The utility will show the BER of the last transmission.
- Press Z and set the step, for example 25 (Hz) — handy for fine tuning.
- Press F (frequency up) several times, transmitting from the radio each time and watching the BER. Keep going until the BER starts to rise or the signal disappears.
- Note the outermost "live" frequency. Go back with f, sweep the other direction and find the second limit.
- The optimal operating point is the midpoint between the two limits. That is where the BER will be at its minimum.
BER guidelines for DMR Simplex:
- 0 % — 0.5 % — excellent, decoding is reliable;
- 0.5 % — 2 % — acceptable for voice, but data may be lost;
- above 2 % — needs calibration; SMS and packet data will be unstable;
- above 5 % — critical, voice dropouts are possible.
Step 3: record the final RXOffset
Once you have found the optimal frequency, press Q to quit. The utility will print a line like this:
Frequency: 434250275 Hz Offset: +275 Hz
TXLevel: 50 RXLevel: 50
The Offset value is your RXOffset (and usually TXOffset). It needs to be entered into the MMDVMHost configuration.
On Pi-Star: "Admin" → "Expert" → "MMDVMHost" → the [Modem] section:
[Modem]
RXOffset=275
TXOffset=275
On RadioStar (our image): the offset is entered directly through the device's web panel — the "Modem" tab → the RX Offset / TX Offset fields. You don't need to restart the service manually; the panel does it for you.
Step 4: calibrating TXLevel and RXLevel
Deviation levels affect signal quality. The correct deviation for DMR is 2.75 kHz.
TXLevel (the hotspot's transmit level to the air):
- Press D — DMR Deviation Mode; the modem generates a 1.2 kHz sine wave.
- With an oscilloscope or a frequency counter with a deviation input, measure the carrier deviation.
- Use the T / t keys to reach ~2.75 kHz of deviation.
- If you have no oscilloscope: start with TXLevel = 50 (the default), confirm that the radio receives without distortion — that is usually enough for a hotspot.
RXLevel (the modem's receive sensitivity):
- Enter BER test mode (b).
- Use the R / r keys to set the level so that the BER is at its minimum with the radio at "normal" power (not right up against the hotspot's antenna).
- Too high an RXLevel overloads the ADC and the BER rises. Too low and the signal is weak, with the same result.
How calibration works in the RadioStar image
The ready-made RadioStar image for Raspberry Pi includes a BER sweep right from the web panel: the device itself sweeps a range of frequencies around the nominal value and finds the point of minimum BER, with no manual stepping through keys. This is convenient if you have no physical access to SSH or want to re-run the calibration after changing radios.
The sweep result is written to RXOffset automatically. If needed, the value can be adjusted manually on the same "Modem" page.
Common mistakes and how to avoid them
- MMDVMHost not stopped — the port is busy, and MMDVMCal won't start or crashes immediately. On Pi-Star use only sudo pistar-mmdvmcal.
- Radio too close to the hotspot antenna — input overload, artificially high BER. Keep a distance of 0.5–1 m.
- Radio power at maximum — same problem. For calibration 1–2 W or the lowest power step is enough.
- Caps Lock on — f turns into F, and the frequency drifts the wrong way unnoticed.
- Color Code mismatch — the radio and the hotspot don't "hear" each other at all, BER = 0 because there is no signal. Check the CC in your codeplug and in the hotspot settings.
- Offset not saved in the config — after a hotspot reboot the offset is lost. MMDVMCal does not change the config by itself; it only prints the value on exit.
Calibration is the foundation of reliable operation on the network
A precisely calibrated hotspot means stable reception of SMS, data and voice on the DMRhub network. If you don't have an image yet — build a hotspot on a Raspberry Pi in half an hour: the RadioStar image includes a web panel with a BER sweep, so manually stepping the frequency over SSH isn't needed.
Sources
- MMDVMCal — official repository (G4KLX) — github.com/g4klx/MMDVMCal
- Getting the best BER from your Pi-Star MMDVM (M1GEO, George Smart) — george-smart.co.uk
- MMDVMCal DVM Calibration (VK4PK) — lyonscomputer.com.au
- Hotspot Offset Calibration (K9NPX) — k9npx.com