Low data throughput on nRF9151DK compared to nRF9160

Hi, I'm experiencing a significant performance drop when switching from the nRF9160 to the nRF9151DK.

I have a firmware that sends around 300 kBytes of data over UART in about 20 seconds using data mode with the Serial LTE Modem (SLM) on the nRF9160. However, running the same firmware (with minor adjustments) on the nRF9151DK, the same 300 kBytes take about 2 minutes to transmit.

Data is being sent over UART in SLM data mode (i.e., after AT+CFUN=1, AT+CMEE=1, AT+KTCPCNX, etc.). I'm using UART2 with HW Async mode enabled (CONFIG_UART_2_NRF_HW_ASYNC=y) and a baudrate of 921600.

I would like to ask:

  • Are there any known differences between the nRF9160 and nRF9151 that could explain this performance drop?

  • Are there specific UART, modem, or clock configurations required for the nRF9151 to achieve similar throughput?

  • Does using HW Async with TIMER2 on the nRF9151 require special considerations?

Any guidance would be greatly appreciated.
Thanks!

Conectado à porta COM13 a 921600 bps.
Enviando: AT+CFUN=0
Resposta:
ERROR
------------------------------
Enviando: AT%POWERCLASS=5
Resposta:
OK
------------------------------
Enviando: AT%XSYSTEMMODE=1,0,0,0
Resposta:
OK
------------------------------
Enviando: AT+CFUN=1
Resposta:
OK
------------------------------
Enviando: AT+CFUN?
Resposta:
+CFUN: 1
OK
------------------------------
Enviando: AT+COPS=1,2,"72405"
Resposta:
OK
------------------------------
Enviando: AT+CGDCONT=1,"IP","em"
Resposta:
OK
------------------------------
Enviando: AT+CEREG=1
Resposta:
OK
------------------------------
Enviando: AT+COPS?
Resposta:
+COPS: 1
OK
------------------------------
Enviando: AT+CEREG?
Resposta:
+CEREG: 1,4
OK
------------------------------
Aguardando registro na rede... Tentando novamente em 5 segundos.
Enviando: AT+CEREG?
Resposta:
+CEREG: 2
+CEREG: 5
+CEREG: 1,5
OK
------------------------------
Registrado na rede com sucesso.
Enviando: AT#XMQTTCFG="clientId-NdUYzNW5CM",60,1
Resposta:
OK
------------------------------
Enviando: AT#XMQTTCON=1,"","","XXXXXXXXXX",1883
Resposta:
OK
------------------------------
Aguardando evento 0,0...
Recebido: #XMQTTEVT: 0,0
Enviando: AT#XMQTTPUB="test/consumo/nrf9151","",2,0
Resposta:
OK
------------------------------
Entrando em modo de dados. Iniciando envios de payloads...

[Payload 1/74]
[18:00:24] Enviando payload 1
[18:00:25] Recebido: #XMQTTEVT: 4,0
[18:00:25] Recebido: #XMQTTEVT: 6,0

[Payload 2/74]
[18:00:25] Enviando payload 2
[18:00:26] Recebido: #XMQTTEVT: 4,0
[18:00:27] Recebido: #XMQTTEVT: 6,0

[Payload 3/74]
[18:00:27] Enviando payload 3
[18:00:28] Recebido: #XMQTTEVT: 4,0
[18:00:28] Recebido: #XMQTTEVT: 6,0

[Payload 4/74]
[18:00:28] Enviando payload 4
[18:00:29] Recebido: #XMQTTEVT: 4,0
[18:00:29] Recebido: #XMQTTEVT: 6,0

[Payload 5/74]
[18:00:29] Enviando payload 5
[18:00:30] Recebido: #XMQTTEVT: 4,0
[18:00:31] Recebido: #XMQTTEVT: 6,0

[Payload 6/74]
[18:00:31] Enviando payload 6
[18:00:31] Recebido: #XMQTTEVT: 4,0
[18:00:31] Recebido: #XMQTTEVT: 6,0

[Payload 7/74]
[18:00:31] Enviando payload 7
[18:00:32] Recebido: #XMQTTEVT: 4,0
[18:00:32] Recebido: #XMQTTEVT: 6,0

[Payload 8/74]
[18:00:32] Enviando payload 8
[18:00:33] Recebido: #XMQTTEVT: 4,0
[18:00:34] Recebido: #XMQTTEVT: 6,0

[Payload 9/74]
[18:00:34] Enviando payload 9
[18:00:34] Recebido: #XMQTTEVT: 4,0
[18:00:35] Recebido: #XMQTTEVT: 6,0

[Payload 10/74]
[18:00:35] Enviando payload 10
[18:00:35] Recebido: #XMQTTEVT: 4,0
[18:00:35] Recebido: #XMQTTEVT: 6,0

[Payload 11/74]
[18:00:35] Enviando payload 11
[18:00:36] Recebido: #XMQTTEVT: 4,0
[18:00:37] Recebido: #XMQTTEVT: 6,0

[Payload 12/74]
[18:00:37] Enviando payload 12
[18:00:38] Recebido: #XMQTTEVT: 4,0
[18:00:38] Recebido: #XMQTTEVT: 6,0

[Payload 13/74]
[18:00:38] Enviando payload 13
[18:00:39] Recebido: #XMQTTEVT: 4,0
[18:00:39] Recebido: #XMQTTEVT: 6,0

[Payload 14/74]
[18:00:39] Enviando payload 14
[18:00:40] Recebido: #XMQTTEVT: 4,0
[18:00:41] Recebido: #XMQTTEVT: 6,0

[Payload 15/74]
[18:00:41] Enviando payload 15
[18:00:42] Recebido: #XMQTTEVT: 4,0
[18:00:43] Recebido: #XMQTTEVT: 6,0

[Payload 16/74]
[18:00:43] Enviando payload 16
[18:00:43] Recebido: #XMQTTEVT: 4,0
[18:00:44] Recebido: #XMQTTEVT: 6,0

[Payload 17/74]
[18:00:44] Enviando payload 17
[18:00:45] Recebido: #XMQTTEVT: 4,0
[18:00:45] Recebido: #XMQTTEVT: 6,0

[Payload 18/74]
[18:00:45] Enviando payload 18
[18:00:46] Recebido: #XMQTTEVT: 4,0
[18:00:46] Recebido: #XMQTTEVT: 6,0

[Payload 19/74]
[18:00:46] Enviando payload 19
[18:00:47] Recebido: #XMQTTEVT: 4,0
[18:00:47] Recebido: #XMQTTEVT: 6,0

[Payload 20/74]
[18:00:47] Enviando payload 20
[18:00:48] Recebido: #XMQTTEVT: 4,0
[18:00:48] Recebido: #XMQTTEVT: 6,0

[Payload 21/74]
[18:00:48] Enviando payload 21
[18:00:49] Recebido: #XMQTTEVT: 4,0
[18:00:49] Recebido: #XMQTTEVT: 6,0

[Payload 22/74]
[18:00:49] Enviando payload 22
[18:00:50] Recebido: #XMQTTEVT: 4,0
[18:00:50] Recebido: #XMQTTEVT: 6,0

[Payload 23/74]
[18:00:50] Enviando payload 23
[18:00:51] Recebido: #XMQTTEVT: 4,0
[18:00:51] Recebido: #XMQTTEVT: 6,0

[Payload 24/74]
[18:00:51] Enviando payload 24
[18:00:52] Recebido: #XMQTTEVT: 4,0
[18:00:52] Recebido: #XMQTTEVT: 6,0

[Payload 25/74]
[18:00:52] Enviando payload 25
[18:00:53] Recebido: #XMQTTEVT: 4,0
[18:00:53] Recebido: #XMQTTEVT: 6,0

[Payload 26/74]
[18:00:53] Enviando payload 26
[18:00:54] Recebido: #XMQTTEVT: 4,0
[18:00:54] Recebido: #XMQTTEVT: 6,0

[Payload 27/74]
[18:00:54] Enviando payload 27
[18:00:55] Recebido: #XMQTTEVT: 4,0
[18:00:55] Recebido: #XMQTTEVT: 6,0

[Payload 28/74]
[18:00:55] Enviando payload 28
[18:00:56] Recebido: #XMQTTEVT: 4,0
[18:00:56] Recebido: #XMQTTEVT: 6,0

[Payload 29/74]
[18:00:56] Enviando payload 29
[18:00:57] Recebido: #XMQTTEVT: 4,0
[18:00:57] Recebido: #XMQTTEVT: 6,0

[Payload 30/74]
[18:00:57] Enviando payload 30
[18:00:58] Recebido: #XMQTTEVT: 4,0
[18:00:59] Recebido: #XMQTTEVT: 6,0

[Payload 31/74]
[18:00:59] Enviando payload 31
[18:00:59] Recebido: #XMQTTEVT: 4,0
[18:00:59] Recebido: #XMQTTEVT: 6,0

[Payload 32/74]
[18:00:59] Enviando payload 32
[18:01:00] Recebido: #XMQTTEVT: 4,0
[18:01:01] Recebido: #XMQTTEVT: 6,0

[Payload 33/74]
[18:01:01] Enviando payload 33
[18:01:02] Recebido: #XMQTTEVT: 4,0
[18:01:02] Recebido: #XMQTTEVT: 6,0

[Payload 34/74]
[18:01:02] Enviando payload 34
[18:01:03] Recebido: #XMQTTEVT: 4,0
[18:01:03] Recebido: #XMQTTEVT: 6,0

[Payload 35/74]
[18:01:03] Enviando payload 35
[18:01:03] Recebido: #XMQTTEVT: 4,0
[18:01:04] Recebido: #XMQTTEVT: 6,0

[Payload 36/74]
[18:01:04] Enviando payload 36
[18:01:05] Recebido: #XMQTTEVT: 4,0
[18:01:05] Recebido: #XMQTTEVT: 6,0

[Payload 37/74]
[18:01:05] Enviando payload 37
[18:01:06] Recebido: #XMQTTEVT: 4,0
[18:01:06] Recebido: #XMQTTEVT: 6,0

[Payload 38/74]
[18:01:06] Enviando payload 38
[18:01:07] Recebido: #XMQTTEVT: 4,0
[18:01:08] Recebido: #XMQTTEVT: 6,0

[Payload 39/74]
[18:01:08] Enviando payload 39
[18:01:08] Recebido: #XMQTTEVT: 4,0
[18:01:09] Recebido: #XMQTTEVT: 6,0

[Payload 40/74]
[18:01:09] Enviando payload 40
[18:01:09] Recebido: #XMQTTEVT: 4,0
[18:01:10] Recebido: #XMQTTEVT: 6,0

[Payload 41/74]
[18:01:10] Enviando payload 41
[18:01:11] Recebido: #XMQTTEVT: 4,0
[18:01:11] Recebido: #XMQTTEVT: 6,0

[Payload 42/74]
[18:01:11] Enviando payload 42
[18:01:11] Recebido: #XMQTTEVT: 4,0
[18:01:12] Recebido: #XMQTTEVT: 6,0

[Payload 43/74]
[18:01:12] Enviando payload 43
[18:01:12] Recebido: #XMQTTEVT: 4,0
[18:01:13] Recebido: #XMQTTEVT: 6,0

[Payload 44/74]
[18:01:13] Enviando payload 44
[18:01:13] Recebido: #XMQTTEVT: 4,0
[18:01:14] Recebido: #XMQTTEVT: 6,0

[Payload 45/74]
[18:01:14] Enviando payload 45
[18:01:15] Recebido: #XMQTTEVT: 4,0
[18:01:15] Recebido: #XMQTTEVT: 6,0

[Payload 46/74]
[18:01:15] Enviando payload 46
[18:01:16] Recebido: #XMQTTEVT: 4,0
[18:01:16] Recebido: #XMQTTEVT: 6,0

[Payload 47/74]
[18:01:16] Enviando payload 47
[18:01:17] Recebido: #XMQTTEVT: 4,0
[18:01:18] Recebido: #XMQTTEVT: 6,0

[Payload 48/74]
[18:01:18] Enviando payload 48
[18:01:19] Recebido: #XMQTTEVT: 4,0
[18:01:19] Recebido: #XMQTTEVT: 6,0

[Payload 49/74]
[18:01:19] Enviando payload 49
[18:01:20] Recebido: #XMQTTEVT: 4,0
[18:01:20] Recebido: #XMQTTEVT: 6,0

[Payload 50/74]
[18:01:20] Enviando payload 50
[18:01:21] Recebido: #XMQTTEVT: 4,0
[18:01:21] Recebido: #XMQTTEVT: 6,0

[Payload 51/74]
[18:01:21] Enviando payload 51
[18:01:22] Recebido: #XMQTTEVT: 4,0
[18:01:23] Recebido: #XMQTTEVT: 6,0

[Payload 52/74]
[18:01:23] Enviando payload 52
[18:01:24] Recebido: #XMQTTEVT: 4,0
[18:01:24] Recebido: #XMQTTEVT: 6,0

[Payload 53/74]
[18:01:24] Enviando payload 53
[18:01:25] Recebido: #XMQTTEVT: 4,0
[18:01:25] Recebido: #XMQTTEVT: 6,0

[Payload 54/74]
[18:01:25] Enviando payload 54
[18:01:26] Recebido: #XMQTTEVT: 4,0
[18:01:27] Recebido: #XMQTTEVT: 6,0

[Payload 55/74]
[18:01:27] Enviando payload 55
[18:01:27] Recebido: #XMQTTEVT: 4,0
[18:01:28] Recebido: #XMQTTEVT: 6,0

[Payload 56/74]
[18:01:28] Enviando payload 56
[18:01:29] Recebido: #XMQTTEVT: 4,0
[18:01:29] Recebido: #XMQTTEVT: 6,0

[Payload 57/74]
[18:01:29] Enviando payload 57
[18:01:29] Recebido: #XMQTTEVT: 4,0
[18:01:30] Recebido: #XMQTTEVT: 6,0

[Payload 58/74]
[18:01:30] Enviando payload 58
[18:01:31] Recebido: #XMQTTEVT: 4,0
[18:01:31] Recebido: #XMQTTEVT: 6,0

[Payload 59/74]
[18:01:31] Enviando payload 59
[18:01:32] Recebido: #XMQTTEVT: 4,0
[18:01:32] Recebido: #XMQTTEVT: 6,0

[Payload 60/74]
[18:01:32] Enviando payload 60
[18:01:33] Recebido: #XMQTTEVT: 4,0
[18:01:33] Recebido: #XMQTTEVT: 6,0

[Payload 61/74]
[18:01:33] Enviando payload 61
[18:01:34] Recebido: #XMQTTEVT: 4,0
[18:01:34] Recebido: #XMQTTEVT: 6,0

[Payload 62/74]
[18:01:34] Enviando payload 62
[18:01:35] Recebido: #XMQTTEVT: 4,0
[18:01:35] Recebido: #XMQTTEVT: 6,0

[Payload 63/74]
[18:01:35] Enviando payload 63
[18:01:36] Recebido: #XMQTTEVT: 4,0
[18:01:36] Recebido: #XMQTTEVT: 6,0

[Payload 64/74]
[18:01:36] Enviando payload 64
[18:01:37] Recebido: #XMQTTEVT: 4,0
[18:01:38] Recebido: #XMQTTEVT: 6,0

[Payload 65/74]
[18:01:38] Enviando payload 65
[18:01:39] Recebido: #XMQTTEVT: 4,0
[18:01:39] Recebido: #XMQTTEVT: 6,0

[Payload 66/74]
[18:01:39] Enviando payload 66
[18:01:40] Recebido: #XMQTTEVT: 4,0
[18:01:40] Recebido: #XMQTTEVT: 6,0

[Payload 67/74]
[18:01:40] Enviando payload 67
[18:01:41] Recebido: #XMQTTEVT: 4,0
[18:01:41] Recebido: #XMQTTEVT: 6,0

[Payload 68/74]
[18:01:41] Enviando payload 68
[18:01:42] Recebido: #XMQTTEVT: 4,0
[18:01:42] Recebido: #XMQTTEVT: 6,0

[Payload 69/74]
[18:01:42] Enviando payload 69
[18:01:43] Recebido: #XMQTTEVT: 4,0
[18:01:43] Recebido: #XMQTTEVT: 6,0

[Payload 70/74]
[18:01:43] Enviando payload 70
[18:01:44] Recebido: #XMQTTEVT: 4,0
[18:01:45] Recebido: #XMQTTEVT: 6,0

[Payload 71/74]
[18:01:45] Enviando payload 71
[18:01:46] Recebido: #XMQTTEVT: 4,0
[18:01:46] Recebido: #XMQTTEVT: 6,0

[Payload 72/74]
[18:01:46] Enviando payload 72
[18:01:47] Recebido: #XMQTTEVT: 4,0
[18:01:47] Recebido: #XMQTTEVT: 6,0

[Payload 73/74]
[18:01:47] Enviando payload 73
[18:01:48] Recebido: #XMQTTEVT: 4,0
[18:01:49] Recebido: #XMQTTEVT: 6,0

[Payload 74/74]
[18:01:49] Enviando payload 74
[18:01:49] Recebido: #XMQTTEVT: 4,0
[18:01:50] Recebido: #XMQTTEVT: 6,0
Envio finalizado. Saindo do modo de dados.


import serial
import time
import hexdump

# Configurações
PORT = 'COM13'
BAUDRATE = 921600
TIMEOUT = 0.5

at_commands = [
    'AT+CFUN=0',
    'AT%POWERCLASS=5',
    'AT%XSYSTEMMODE=1,0,0,0',
    'AT+CFUN=1',
    'AT+CFUN?',
    'AT+COPS=1,2,"72405"',
    'AT+CGDCONT=1,"IP","em"',
    #'AT+CGDCONT=1,"IP","waterlog.claro.com.br"',
    'AT+CEREG=1',
    'AT+COPS?',
    'AT+CEREG?',
    'AT#XMQTTCFG="clientId-NdUYzNW5CM",60,1',
    'AT#XMQTTCON=1,"","","XXXXXXXXX",1883',
    'AT#XMQTTPUB="test/consumo/nrf9151","",2,0',
]

def generate_payload(bytes=4000):
    #return ''.join([str(v) for v in range(0,4096)])
    payload = ['0'] * bytes
    cont = 0
    for i in range(0, bytes):
        payload[i] = str(cont)
        cont += 1
        if cont > 9:
            cont = 0
    return ''.join(payload)

def send_at_command(ser, command):
    print(f"Enviando: {command}")
    ser.write((command + '\r\n').encode())
    ser.flush()

    response = []
    while True:
        line = ser.readline().decode(errors='ignore')
        if not line:
            break
        stripped_line = line.strip()
        if stripped_line:
            response.append(stripped_line)
            if stripped_line in ('OK', 'ERROR'):
                break

    print("Resposta:")
    print('\n'.join(response))
    print("-" * 30)
    return response

def wait_for_mqtt_event(ser, expected_evt_type, expected_result=0, timeout=10):
    print(f"Aguardando evento {expected_evt_type},{expected_result}...")
    start_time = time.time()
    while (time.time() - start_time) < timeout:
        line = ser.readline().decode(errors='ignore').strip()
        if line:
            print(f"Recebido: {line}")
            if line.startswith('#XMQTTEVT:'):
                try:
                    parts = line.split(':')[1].split(',')
                    evt_type = int(parts[0].strip())
                    result = int(parts[1].strip())
                    if evt_type == expected_evt_type and result == expected_result:
                        return True
                except:
                    pass
        else:
            time.sleep(0.1)
    print(f"Timeout aguardando evento {expected_evt_type},{expected_result}")
    return False

def main():
    try:
        payload_total = generate_payload(4096)

        with serial.Serial(PORT, BAUDRATE, timeout=TIMEOUT) as ser:
            print(f"Conectado à porta {PORT} a {BAUDRATE} bps.")
            time.sleep(2)

            ser.write(b'+++')
            ser.write(b'AT')


            for cmd in at_commands:
                if cmd == 'AT+CEREG?':
                    while True:
                        response = send_at_command(ser, cmd)
                        cereg_ok = any(line.startswith('+CEREG: ') and (('1,5' in line) or ('1,1' in line)) for line in response)
                        if cereg_ok:
                            print("Registrado na rede com sucesso.")
                            break
                        else:
                            print("Aguardando registro na rede... Tentando novamente em 5 segundos.")
                            time.sleep(5)
                elif cmd.startswith('AT#XMQTTCON'):
                    send_at_command(ser, cmd)
                    wait_for_mqtt_event(ser, expected_evt_type=0)
                elif cmd.startswith('AT#XMQTTPUB') and '""' in cmd:
                    send_at_command(ser, cmd)
                    print("Entrando em modo de dados. Iniciando envios de payloads...")

                    for i in range(74):
                        print(f"\n[Payload {i+1}/74]")

                        # Horário real de envio
                        t_envio = time.strftime("%H:%M:%S")
                        print(f"[{t_envio}] Enviando payload {i+1}")
                        ser.write(payload_total.encode())
                        ser.flush()

                        # Esperar evento e registrar horário real de recepção
                        t_ini_espera = time.time()
                        while (time.time() - t_ini_espera) < 10:
                            line = ser.readline()
                            #hexdump.hexdump(line,result='print')                            
                            line = line.decode(errors='ignore').strip()
                            if line:
                                t_recebido = time.strftime("%H:%M:%S")
                                print(f"[{t_recebido}] Recebido: {line}")
                                if line.startswith('#XMQTTEVT:'):
                                    try:
                                        parts = line.split(':')[1].split(',')
                                        evt_type = int(parts[0].strip())
                                        result = int(parts[1].strip())
                                        if evt_type == 6 and result == 0:
                                            break  # Evento correto recebido
                                    except:
                                        pass
                            else:
                                time.sleep(0.1)

                        else:
                            print(f"[{time.strftime('%H:%M:%S')}] Timeout aguardando evento 6,0. Abortando.")
                            break

                    ser.write(b'+++')
                    print("Envio finalizado. Saindo do modo de dados.")
                else:
                    send_at_command(ser, cmd)

    except serial.SerialException as e:
        print(f"Erro na serial: {e}")
    except Exception as e:
        print(f"Erro inesperado: {e}")

if __name__ == '__main__':
    main()

  • Hello Øyvind,

    Thank you for the follow-up. Here are the answers to your questions:

    • nRF9160 Modem Trace: We do have an existing product that uses the nRF9160, but I do not have a sample in my lab at the moment. I have contacted our client to request a unit for testing and will provide the modem trace as soon as I receive it.

    • Other SIM Cards: Currently, we only have access to Claro SIM cards. However, we are in the process of sourcing LTE-M SIMs from other local operators to expand our testing capabilities.

    • Testing Location: All tests are being performed at our facility in Uberlândia, Minas Gerais, Brazil.

    I will keep you updated on my progress with obtaining the nRF9160 sample.

    Kind regards,

    Lucas

  • l0cszp said:
    While your team is analyzing the modem trace

    Finanlly got some more feedback. There seems to be an issue with the SIM but the modem trace was not sufficient. They need to see modem traces from start-up which means that when you start modem trace you need to press reset button on the nRF9151DK. Could you please capture a new trace and assure that reset is pressed after starting modem trace in Cellular Monitor?

    Thanks

    Kind regards,
    Øyvind

  • Hello Øyvind,

    I have captured a new modem trace, making sure to press the reset button on the DK right after starting the trace in the Cellular Monitor to include the full start-up sequence. The trace was run for 30 minutes.

    On a positive note, it seems the issue with the SIM card has been resolved. I was able to verify its connectivity and status on our carrier's dashboard before this test.

    The new trace file is attached. Please let me know if this provides the necessary information from the start-up.

    Kind regards,

    Lucas

    trace-2025-08-22T13-04-49.595Z.mtrace

  • Thanks for sharing a new modem trace. Glad to hear that SIM issue is resolved. I assume that you are still using the same SIM?

  • Yes, that's correct. This trace was captured using one of the original Claro SIM cards.

    My initial thought was that the SIM itself wasn't the root cause, as I had tested with two different cards and both were functioning correctly.

    Let me know what you find in the new trace.

Related