Read Uart based sensor data on nrf5340 using VsCode?

Hi,

I'am using the  Ultrasonic Oxygen Senor with the nrf5340, the output is like this "photo" I want to calculate the concentration and the purity and with this values I had wrong results, so can you help to solve this problem?

 I am using this code

4857.gasboard.zip

 and here is my result.


this technical specification for my sensor.

 https://en.gassensor.com.cn/Product_files/Specifications/Gasboard%207500H%20series%20technical%20specification.pdf?fbclid=IwAR0R1P0FlwkPzhew7jBYVzL-rvtESB1ob2HGF0OE4bngaI5jP8ktZfFMoMo 

Could you please help me to solve this problem

Parents
  • Hello!

    Did you write the code you're using yourself?

    Can you please explain what you expect your code to do and how the results differ from your expectations?

    Best regards,

    Einar

  • Hello!
    Thank you for your response
    The code found in devzone for nrf9160
    The first step, I want to read the data through the UART connection.
    The second step, I have to read the flow rate and purity of oxygen.

    There is many illogical values, "many zeros" that gives wrong results
    Meilleures salutations,

  • Hi,

    I mean I used this program for nrf5340 and I added some changes in its code.

    I'm not sure if the program respects the communication protocol because I can't find how to add the "gasboard 7500H" or "OCS-3F" sensor in the device tree or the overlay file so I find a solution that to read the sensor data from the RX

    The outcome shows the output reading of the RX.


    The sensor protocol is UART So could you help me to read the correct values from this sensor.

  • If what you are currently trying to do is simply to read data from your sensor with some basic UART sample, then I would recommend you read through the communication protocol part of the specification. It tells you in detail how you are supposed to communicate with the sensor.

    It looks like you have to send a specific command to the sensor to get data in return, are you doing this?

    -Einar

  • Hi,
    No, I am not sending anything to the sensor, please help me how to send a specific command and what is this command?

  • Looks like you're using Zephyr's uart_irq API in your code, which uses uart_irq_tx_ready() and uart_fifo_fill() to send data.

    Read about it here:

    http://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/hardware/peripherals/uart.html#uart-interrupt-api

    The communication protocol is explained in the data sheet you linked in your original question. Please read it.

  • Thank you I understand and I write an example code, but no result.

    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/uart.h>
    #include <sys/printk.h>
    uint8_t uart_buf[1024];
    uint8_t buf[] = {17, 1, 1, 237};//11 01 01 ED
    int count;
    void uart_cb(const struct device *x, void *user_data)
    {
    	uart_irq_update(x);
    	int data_length = 0;
    	if (uart_irq_tx_ready(x)) {
    	(void)uart_fifo_fill(x, buf, sizeof(buf));
    	uart_irq_tx_disable(x);
    	}
    	if (uart_irq_rx_ready(x)) {
    		data_length = uart_fifo_read(x, uart_buf, sizeof(uart_buf));
    		uart_buf[data_length] = 0;
    	}
        uart_fifo_fill(x, uart_buf, data_length);
    }
    
    void main(void)
    {
    
        printk("sensor program start!\n"); //output on UART0, which is default for logging
    		
    
    
    const struct device *uart = device_get_binding("UART_1");
    
        struct uart_config cfg ;
        cfg.baudrate = 9600 ;
        cfg.parity = UART_CFG_PARITY_NONE ;
        cfg.stop_bits = UART_CFG_STOP_BITS_1 ;
        cfg.data_bits = UART_CFG_DATA_BITS_8 ;
        cfg.flow_ctrl = UART_CFG_FLOW_CTRL_NONE ;
     	uart_configure(uart, &cfg);
    
    	uart_irq_callback_set(uart, uart_cb);
    	uart_irq_rx_enable(uart);
    	printk("main function!\n"); //output on UART0, which is default for logging
    	while (1) {
            uart_fifo_fill(uart,buf ,sizeof(buf) );//11 01 01 ED
    
            count=uart_fifo_read(uart,uart_buf,sizeof(uart_buf));
            printf("read  %i\n",count);
    
            k_cpu_idle();
            k_sleep(K_SECONDS(1));
    	}
    }

    I have a question the Arduino code of this sensor works correctly without sending a specific command, why in the code zephyr is obliged to send a specific command to obtain the data in return?

Reply
  • Thank you I understand and I write an example code, but no result.

    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/uart.h>
    #include <sys/printk.h>
    uint8_t uart_buf[1024];
    uint8_t buf[] = {17, 1, 1, 237};//11 01 01 ED
    int count;
    void uart_cb(const struct device *x, void *user_data)
    {
    	uart_irq_update(x);
    	int data_length = 0;
    	if (uart_irq_tx_ready(x)) {
    	(void)uart_fifo_fill(x, buf, sizeof(buf));
    	uart_irq_tx_disable(x);
    	}
    	if (uart_irq_rx_ready(x)) {
    		data_length = uart_fifo_read(x, uart_buf, sizeof(uart_buf));
    		uart_buf[data_length] = 0;
    	}
        uart_fifo_fill(x, uart_buf, data_length);
    }
    
    void main(void)
    {
    
        printk("sensor program start!\n"); //output on UART0, which is default for logging
    		
    
    
    const struct device *uart = device_get_binding("UART_1");
    
        struct uart_config cfg ;
        cfg.baudrate = 9600 ;
        cfg.parity = UART_CFG_PARITY_NONE ;
        cfg.stop_bits = UART_CFG_STOP_BITS_1 ;
        cfg.data_bits = UART_CFG_DATA_BITS_8 ;
        cfg.flow_ctrl = UART_CFG_FLOW_CTRL_NONE ;
     	uart_configure(uart, &cfg);
    
    	uart_irq_callback_set(uart, uart_cb);
    	uart_irq_rx_enable(uart);
    	printk("main function!\n"); //output on UART0, which is default for logging
    	while (1) {
            uart_fifo_fill(uart,buf ,sizeof(buf) );//11 01 01 ED
    
            count=uart_fifo_read(uart,uart_buf,sizeof(uart_buf));
            printf("read  %i\n",count);
    
            k_cpu_idle();
            k_sleep(K_SECONDS(1));
    	}
    }

    I have a question the Arduino code of this sensor works correctly without sending a specific command, why in the code zephyr is obliged to send a specific command to obtain the data in return?

Children
  • I haven't seen the Arduino code so I can't say anything about that unless you share the code. Is the Arduino code also interrupt based?

    Looking at your code, it looks like you're disabling uart irq tx in your callback without enabling it again, any reason for this? Also you are using code in your main function that is supposed to be used in callbacks. I would recommend trying to use a UART API that is not interrupt based to test that you are able to communicate with the sensor.

    -Einar

  • Here is the Arduino code.

    #include <Wire.h>
    
    void setup() {
      Serial.begin(9600);
    }
    
    void loop() {
      typedef unsigned char u8;
      typedef unsigned int u16;
      int inByte;
      u8 temp;
      u8 i, j, o2[12];
      u16 o2c, o2f, o2t; //Define oxygen concentration, flow rate and temperature
    
      //When character arrive over the serial port ..
      if (Serial.available()) {
      // wait a bit for the entire message to arrive
      delay(100);
        // read all the available characters
        while (Serial.available() > 0) {
          inByte = Serial.read();
          //---Receiving part---
          if ((o2[0] == 0x16) && (o2[1] == 0x09) && (o2[2] == 0x01)) //Determine if the first two bytes are received correctly, I is the global variable
          {
            o2[i] = inByte;       
            i++;
          }
          else           //If one of the first three bytes received is incorrect, the first two bytes will be judged
          {
            if ((o2[0] == 0x16) && (o2[1] == 0x09))
            {
              if ( inByte == 0x01)   
              {
                o2[2] =  inByte;   
                i++;
              }
              else                                
              {
                i = 0;                
                for (j = 0; j < 12; j++)          
                {
                  o2[j] = 0;
                }
              }
            }
            else     
            {
              if (o2[0] == 0x16)
              {
                if ( inByte == 0x09)
                {
                  o2[1] =  inByte; 
                  i++;
                }
                else        
                {
                  i = 0;                
                  for (j = 0; j < 12; j++)          
                  {
                    o2[j] = 0;
                  }
                }
              }
              else     
              {
                if ( inByte == 0x16) 
                {
                  o2[0] =  inByte; 
                  i++;
                }
                else         
                {
                  i = 0;                 
                  for (j = 0; j < 12; j++)         
                  {
                    o2[j] = 0;
                  }
                }
              }
            }
          }
         //---Receiving part---
    
    
    
          if (i == 12)   //Data received complete, start calibration
          {
            temp = 0;
            for (j = 0; j < 12; j++)
            {
              temp += o2[j];
            }
            if (temp == 0)     //Check passed, calculate oxygen concentration, flow, temperature value
            {
              o2c = o2[3] * 256 + o2[4];     //Oxygen concentration
              o2f = o2[5] * 256 + o2[6];     //Oxygen flow value
              o2t = o2[7] * 256 + o2[8];     //Oxygen temperature
            }
    
            
    
            i = 0;                             
            for (j = 0; j < 12; j++)           //Initialize array
            {
              o2[j] = 0;
            }
          }
        }
      }
    
    //--O2
    Serial.print("O2 : ");
    Serial.print(o2c/100);
    Serial.print(o2c/10%10);
    Serial.print(".");
    Serial.print(o2c%10);
    Serial.println("%");
    
    //--Flow
    Serial.print("Flow : ");
    Serial.print(o2f/10%10);
    Serial.print(".");
    Serial.print(o2f%10);
    Serial.println("L/min");
    
    //--Temperature
    Serial.print("Temp : ");
    Serial.print(o2t/100);
    Serial.print(o2t/10%10);
    Serial.print(".");
    Serial.print(o2t%10);
    Serial.println("Celcius");
    delay(2000);
    }

  • Hi

    I noticed now that the data sheet says "The sensor will send data actively by default and the sending interval is 0.5 seconds", so you should be able to read data the same way the Arduino code does, without sending commands to it.

    So try to look at the Arduino code you have here and do the same in your program.

    Have you done anything more to look at the values you're reading other than the prints in your original post? Any reason you print those bytes as %x %i %i and not %x %x %x ?

    -Einar

  • Yes, I did the same but the program display this value"0", I think that i have a bug or problem in the code that i sent to you in the first discussion that i can't find it. So I need a help from you because i'm a beginner in the programing of nrf with zephyr. Thank you

    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/uart.h>
    #include <sys/printk.h>
    uint8_t uart_buf[1024];
    int count;
    void uart_cb(const struct device *x, void *user_data)
    {
    	uart_update(x);
    	int data_length = 0;
    
    	if (uart_rx_ready(x)) {
    		data_length = uart_fifo_read(x, uart_buf, sizeof(uart_buf));
    		uart_buf[data_length] = 0;
    	}
        uart_fifo_fill(x, uart_buf, data_length);
    }
    
    void main(void)
    {
    
        printk("sensor program start!\n"); //output on UART0, which is default for logging
    		
    
    
    const struct device *uart = device_get_binding("UART_1");
    	uart_callback_set(uart, uart_cb,NULL);
    	uart_rx_enable(uart,uart_buf,sizeof(uart_buf),500000);
        struct uart_config cfg ;
        cfg.baudrate = 9600 ;
        cfg.parity = UART_CFG_PARITY_NONE ;
        cfg.stop_bits = UART_CFG_STOP_BITS_1 ;
        cfg.data_bits = UART_CFG_DATA_BITS_8 ;
        cfg.flow_ctrl = UART_CFG_FLOW_CTRL_NONE ;
     uart_configure(uart, &cfg);
    
    	printk("main function!\n"); //output on UART0, which is default for logging
    	while (1) {
            // uart_fifo_fill(uart, "UART loopback start!\r\n", 22);
            count=uart_fifo_read(uart,uart_buf,sizeof(uart_buf));
            printf("read  %i\n",count);
            printk("receiveing data! %x %i %i\n",uart_buf[0],uart_buf[1],uart_buf[2]); //output on UART0, which is default for logging
    	
            k_cpu_idle();
            k_sleep(K_MSEC(1000));
    	}
    }

  • As I asked in my last post, have you tried using %x instead of %i in your print? It could be that your program works but just doesn't display the data correctly.

Related