[Python] Why does my modem send a DTMF 9 tone three times even when AT+VTS is only called once?

Discussão em 'Python' iniciado por Stack, Maio 26, 2025.

  1. Stack

    Stack Membro Participativo

    I'm working on a project where I use a StarTech USB56KEMH2 modem with Python (PySerial) on Linux to call my building's buzzer (MICROM system) and open the door by sending a DTMF 9 tone.

    The modem is set to voice mode (AT+FCLASS=8) and auto-answers after 1 ring (ATS0=1). Once the call is active, I send the following DTMF tone:

    AT+VTS={9,8}


    (I also tried AT+VTS=9 and got the same result.)

    According to the documentation, this should play a 9 tone with a duration of 80 ms. And indeed, it works — the buzzer opens the door, but there's a weird issue: the tone is heard or interpreted three times, as if I had pressed 9 three times.

    What I’ve tried

    • Verified that AT+VTS is called only once per call (using logs).
    • Reset the modem (ATZ, ATE0, etc.) between each call.
    • Changed tone durations using both classic and {digit,duration} format.
    Command Result
    AT+VTS=9 Works but repeats 3 times
    AT+VTS={9,10} Works but repeats 3 times
    AT+VTS={9,8} Works but repeats 3 times
    AT+VTS={9,7} Works but repeats 3 times
    AT+VTS={9,6} No sound / not detected
    System setup

    • StarTech USB56KEMH2 modem
    • Python 3 + PySerial
    • Linux Mint
    • MICROM buzzer (analogue)
    • No echo suppression or filtering configured
    Question


    How can I send a single, clean DTMF 9 tone without it being interpreted multiple times?
    Is there a better way to control the duration or avoid false repetitions when using AT+VTS with this type of modem and buzzer system?

    Code Snippet


    def initialize_modem(ser):
    enviar(ser, "ATZ")
    enviar(ser, "ATE0")
    enviar(ser, "AT+FCLASS=8")
    enviar(ser, "ATS0=1")
    print("[INFO] Modem ready to receive calls.")

    def main():
    ser = connect_modem()
    initialize_modem(ser)

    last_call = None
    waiting_for_tone = False

    try:
    while True:
    line = ser.readline().decode(errors='ignore').strip()
    if line:
    print(f"[MODEM] {line}")

    if any(tag in line for tag in ["RING", "R", "NMBR", "NAME", "DATE"]):
    last_call = time.time()
    waiting_for_tone = True

    if waiting_for_tone and last_call and time.time() - last_call > 5:
    print("[INFO] Assuming call is active. Sending DTMF tone 9...")
    log_event("Call detected. Sending DTMF tone 9")

    # Send exactly one tone of 70 ms
    enviar(ser, 'AT+VTS={9,7}')
    time.sleep(0.5)

    enviar(ser, "ATH")
    print("[INFO] Call ended.")
    log_event("Call hung up.")

    initialize_modem(ser)
    log_event("Modem reset for next call.")

    last_call = None
    waiting_for_tone = False
    time.sleep(2)
    print("[INFO] Waiting for the next call...\n")
    except KeyboardInterrupt:
    print("\n[INFO] Program interrupted by user.")
    finally:
    ser.close()
    print("[INFO] Serial port closed.")

    Continue reading...

Compartilhe esta Página