knolleary / pubsubclient

A client library for the Arduino Ethernet Shield that provides support for MQTT.
http://pubsubclient.knolleary.net/
MIT License
3.78k stars 1.46k forks source link

Anomolous performing when using along with I2S #1032

Open dacattack opened 8 months ago

dacattack commented 8 months ago

This library seems to have some kind of problem when working together with i2s driver. I've done many tests and the results are always the same. I'm sending audio files read by the inmp441 MEMS. You can get a few published messages withouth any problem, in fact, it only takes around 40 ms microseconds to publish a 14KB message but eventually it will freeze and next message will take around 800-1200 ms and that is not acceptable at all. If I disable I2S then this won't happen. Well actually the sending time its very unestable and some messages might take a few miliseconds, but always within a reasonable amount of time.

Which platform, esp8266 or esp32? I'm using ESP32 Do you use TLS or not? I do use TLS. Do you use an IDE (Arduino, Platformio...)? PlatformIO Which version of the Arduino framework? 2.0.9 Please include any debug output and/or decoded stack trace if applicable.

Expected behaviour Estable sending time. I can expect messages to vary a bit, but not this huge amount of time.

To Reproduce Steps to reproduce the behaviour: Set up the mqtt library, objects,functions and get a valid SSL/TLS certificate for your broker. Then include library "/driver/i2s.h" and configure the microphone i2s communications( SR of 16KHz, 16 bit data width) and then send the audio files with a QoS 2. Measure with the function micros() the time the library spent delivering the message to de broker.

Example code

#include "Arduino.h"
#include <driver/i2s.h>
#include "espMqttClient.h"
#include "certificados.hpp"

espMqttClientSecure mqttclient(espMqttClientTypes::UseInternalTask::NO);

const char* broker="192.168.1.xx";
const char* SSID="xxxxx";
const char* PASS="xxxxx";
const uint16_t port=8883;

static TaskHandle_t taskHandle;
bool connectFlag=false;

uint32_t SAMPLE_RATE = 16000;
#define I2SPORT I2S_NUM_0

void i2s_init(){
  i2s_config_t i2s_config={
    .mode = i2s_mode_t (I2S_MODE_MASTER |I2S_MODE_RX ),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
    .communication_format = I2S_COMM_FORMAT_STAND_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 4 ,
    .dma_buf_len = 256,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .mclk_multiple = I2S_MCLK_MULTIPLE_256,
    .bits_per_chan = I2S_BITS_PER_CHAN_32BIT
  };
  i2s_pin_config_t i2s_pinout={
    .bck_io_num = 32,
    .ws_io_num = 25,
    .data_out_num = -1,
    .data_in_num = 33,
  };
  i2s_driver_install(I2SPORT, &i2s_config,0,NULL);
  i2s_set_pin(I2SPORT,&i2s_pinout);
}
void MqttLoopTask(){
  for(;;){
  mqttclient.loop();
  }
}
void mqttOnConnect( bool sessionPresent){
  Serial.print(" Conexión con broker realizada con éxito.\n");
  mqttclient.subscribe("cnn",2);
  connectFlag=true;
}
void mqttOnDisconnect( espMqttClientTypes :: DisconnectReason reason){
  Serial.print("Desconectado del broker.\n");
  mqttclient.subscribe("cnn",2);
  connectFlag=false;
}
void mqttConnection(){
  if(mqttclient.connect()) Serial.println("Dispositivo ESP32 se ha conectado al broker.\n");
  else {
    Serial.println("Dispositivo ESP32 no logró conectarse al broker, reintentando de forma burda...");
    delay(3000);
    ESP.restart();
  }
}
void mqttinit(){
    mqttclient.setCACert(WifiCA_cert);
    mqttclient.setServer(broker,port);
    mqttclient.onConnect(mqttOnConnect);
    mqttclient.onDisconnect(mqttOnDisconnect);
    //mqttclient.setTimeout()
    mqttConnection();
    xTaskCreatePinnedToCore((TaskFunction_t)MqttLoopTask,"MqttloopTask", 8192,nullptr, 3, &taskHandle,0);
    Serial.print("Esperando conexión con el brokercito. "); 
}
void setup(){                                              
   Serial.begin(115200);
   i2s_init();
   WiFi.begin(SSID,PASS);
   Serial.print("Conectándose a red .");
   while(WiFi.status() != WL_CONNECTED){
    Serial.print(" ."); delay(500);
   }
   Serial.print(" Conexión con red realizada exitosamente.\n");
   mqttinit();
}

uint16_t samples = 7000;
uint32_t buff_size = samples* sizeof(int16_t); 
int16_t *buff= (int16_t*)malloc(samples*sizeof(int16_t));
void loop(){
  uint32_t ti=0,tf=0, tsi=0, tsf=0, bytes_read=0;

   while(!connectFlag){
    Serial.print(" .");
    delay(400);
   }
   tsi=micros();
   esp_err_t i2s_err = i2s_read(I2SPORT, buff, buff_size, &bytes_read,pdMS_TO_TICKS(100));
   if(i2s_err != ESP_OK) {
    Serial.print("\nSe ha producido un fallo desconocido durante la comunicación i2s.\n");
    delay(5000);
    return;
   }
   tsf=micros();
   ti=micros();
   mqttclient.publish("prueba",2,false,(uint8_t*)buff,buff_size);
   tf=micros();
   Serial.printf("t_i2s=%u       t_mqtt: %u\n",(tsf-tsi),(tf-ti));
   //mqttclient.clearQueue(false); Not solving anything
}

Additional context At this point is important to understand that it affects the execution time of the publish function not the i2s_read function and that this issue also happens with other mqtt libraries.