This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Sending I2C data over MQTT on nRF9160DK

Hello,

I am working on MQTT sample ncs\nrf\samples\nrf9160\mqtt_simple. I am sending data from UART and I2C to the mqtt server. For sending data I am using Workqueue thread. This program works properly. I am publishing data from UART and I2C on 2 different topics.

Now I added a button to send SMS on the button press in the above code. The above program works properly until the button press. On button press, UART data continues to send data to the mqtt server, but the I2C data stops.

The Code:

#define SERIAL_Q_SIZE 5

static struct work_data{    
    struct k_work work;    
    u8_t data[1024]; 
    u8_t data_len;
}w_data[SERIAL_Q_SIZE];

void uart_cb(struct device *x)
{
        

	uart_irq_update(x);
	int data_length = 0;
        static int pos, serial_in_count, tot_len = 0;

	if (uart_irq_rx_ready(x)) {
		data_length = uart_fifo_read(x, uart_buf, sizeof(uart_buf));
                tot_len = tot_len + data_length;

                memcpy(&w_data[serial_in_count].data[pos], uart_buf, data_length);
                printk("Position is: %d\n", pos);
                //Check if last char is 'LF'
                if(uart_buf[data_length-1] == 10){
                      printk("last char is 'LF', call k_work_submit(), word number %d \n", serial_in_count);
                      w_data[serial_in_count].data_len = tot_len - 1;
                      k_work_submit(&w_data[serial_in_count].work);

                      pos = 0;
                      tot_len = 0;
                      
                      if(serial_in_count < SERIAL_Q_SIZE-1){
                        serial_in_count++;
                      }else{
                          serial_in_count=0;
                      }
                }else{
                      printk("last char is: %d\n", uart_buf[data_length-1]);
                      pos = pos + data_length;
                }

	}
	//printk("%s", uart_buf);
}

void pub_uart_mqtt(struct k_work *item)
{
    struct work_data *wrk_data = CONTAINER_OF(item, struct work_data, work);
    data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, wrk_data->data, wrk_data->data_len);
}
static int try_to_connect(struct mqtt_client *c)
{
	int rc, i = 0;

	while (i++ < APP_CONNECT_TRIES && !connected) {

		client_init(c);

		rc = mqtt_connect(c);
		if (rc != 0) {
			printk("mqtt_connect %d\n", rc);
			k_sleep(APP_SLEEP_MSECS);
			continue;
		}


		rc = fds_init(c);
		if (rc != 0) {
			printk("ERROR: fds_init %d\n", rc);
			return -EINVAL;
		}

		if (poll(&fds, 1, K_SECONDS(CONFIG_MQTT_KEEPALIVE)) < 0) {
			printk("poll error: %d\n", errno);
		}
		mqtt_input(c);

		if (!connected) {
			mqtt_abort(c);
		}
	}

	if (connected) {
		return 0;
	}

	return -EINVAL;
}

static struct work_icm{    
    struct k_work work1;    
    u8_t data1[1024]; 
}w_data1;

static void mqtt_loop(void){
	int rc;
        u32_t cnt = 0;
	
	printk("attempting to connect:\n ");
	
	rc = try_to_connect(&client);
        if (rc != 0) { return; }

	while (connected) {
		rc = poll(&fds, 1, K_SECONDS(CONFIG_MQTT_KEEPALIVE));
		if (rc < 0) {
			printk("ERROR: poll %d\n", errno);
			break;
		}

		rc = mqtt_live(&client);
		if (rc != 0) {
			printk("ERROR: mqtt_live %d\n", rc);
			break;
		}

		if ((fds.revents & POLLIN) == POLLIN) {
			rc = mqtt_input(&client);
			if (rc != 0) {
				printk("ERROR: mqtt_input %d\n", rc);
				break;
			}
		}

		if ((fds.revents & POLLERR) == POLLERR) {
			printk("POLLERR\n");
			break;
		}

		if ((fds.revents & POLLNVAL) == POLLNVAL) {
			printk("POLLNVAL\n");
			break;
		}

                gpio_pin_write(dev, LED, cnt % 2);
                cnt++;

                if(button_press)
                  {  
                    app_socket_start();   // To send SMS
                    button_press = 0;
                  }

                if(i2c_read(i2c_accel, ICM, sizeof(ICM), I2C_ACCEL_READ_ADDR) != 0) {
                        printk("Error on i2c_read()\n");
                }
                printk("Value from nrf52 = %s\r\n", ICM);
                memcpy(&w_data1.data1, ICM, sizeof(ICM));
                k_work_submit(&w_data1.work1);                          // Code stops here
//                data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, ICM, strlen(ICM));  // If using this, then the code stops here.
	}
	rc = mqtt_disconnect(&client);
	if (rc) {
		printk("Could not disconnect MQTT client. Error: %d\n", rc);
	}
}

void pub_icm_mqtt(struct k_work *item)
{
    struct work_icm *wrk_data = CONTAINER_OF(item, struct work_icm, work1);
    data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, wrk_data->data1, strlen(ICM));
}


void main(void)
{
        button_press=false;
        gpio_init();      // GPIO Initialization
        k_sleep(SLEEP_TIME1);
        init_uart();      // UART Initialization
        for(int i=0; i < SERIAL_Q_SIZE; i++){
            k_work_init(&w_data[i].work, pub_uart_mqtt);
        }
        init_accelerometer(); // To initialize I2C_2
        k_work_init(&w_data1.work1, pub_icm_mqtt);
        modem_configure();

	while (1) {
                  mqtt_loop();
                    k_sleep(SLEEP_TIME);
	}
}

I have added just some part of the code.

The while(connected) loop stops on the button press. The UART data is still sent on the server, it means that nRF91 is connected to the mqtt server.

But If I don't publish the I2C data, the while(connected) loop continues to work on the button press also.

I suspect that the problem is in publishing the I2C data to the mqtt server or using k_work_submit in while(connected) loop.

So how can I publish the I2C data without stopping the while(connected) loop?

Parents
  • Hi,

      

    But If I don't publish the I2C data, the while(connected) loop continues to work on the button press also.

    Are you pushing data both to the work queue function "pub_icm_mqtt" and "data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, ICM, strlen(ICM));", or is this an experiment to choose one of these? If both are called, one will overwrite the other.

    strlen() assumes that "\0" is found in the input array. Is the array zero-terminated? Could you also check the return code from data_publish() to see if there's anything that goes wrong?

     

    Kind regards,

    Håkon

  • Hi,

    Yes, I am using one function out of the two ("pub_icm_mqtt" or "data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, ICM, strlen(ICM));") at a time. I did it for testing.

    Yes the array is zero terminated. I checked the return code from data_publish(), it is working properly. It does not return error.

    But I tried few things and observed this:

    1. I disabled UART and sent the I2C data to the cloud and sending the SMS on button press. This program worked properly. Even after the button press, the I2C data was on the cloud. The while(connected) loop did not stop.

    2. Now in the above program I enabled UART and sent both the data (UART and I2C) to the cloud. This program worked properly until the button press like the original problem. On button press, while(connected) loop stopped, but the UART data was still on the cloud. I am using one LED inside while(connected) loop to check. It also stops.

    It means that the problem occurs when I use both the peripherals with button. One peripheral with button works without any problem.

    How can I solve this problem, I am not understanding.

Reply
  • Hi,

    Yes, I am using one function out of the two ("pub_icm_mqtt" or "data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, ICM, strlen(ICM));") at a time. I did it for testing.

    Yes the array is zero terminated. I checked the return code from data_publish(), it is working properly. It does not return error.

    But I tried few things and observed this:

    1. I disabled UART and sent the I2C data to the cloud and sending the SMS on button press. This program worked properly. Even after the button press, the I2C data was on the cloud. The while(connected) loop did not stop.

    2. Now in the above program I enabled UART and sent both the data (UART and I2C) to the cloud. This program worked properly until the button press like the original problem. On button press, while(connected) loop stopped, but the UART data was still on the cloud. I am using one LED inside while(connected) loop to check. It also stops.

    It means that the problem occurs when I use both the peripherals with button. One peripheral with button works without any problem.

    How can I solve this problem, I am not understanding.

Children
No Data
Related