MDM9206 with Pressure Detector

Skill LevelArea of FocusOperating SystemPlatform/HardwareCloud Services/Platform
IntermediateIoT, Embedded, SensorsRTOSQualcomm® MDM920x LTE for IoTGizwits Cloud Platform

This project is designed to read pressure values from the FSR402 sensor using the Qualcomm® MDM9206 LTE modem, a multimode communication chipset that supports Cat-M1/eMTC, Cat-NB1/NB-IoT, 2G/E-GPRS technologies and more than 15 RF bands, making it ideal for global IoT applications. The LED lights up when pressure values exceed the set threshold.

The main objective of this project is to connect the FSR402 sensor to the ADC interface of the Qualcomm MDM9206 LTE Modem provided by the GoKit development board and collect pressure values.

Parts used

Below are the items used in this project.

  1. Win7 PC
  2. GoKit4 development board
  3. FSR402 Sensor, used to detect pressure values
  4. LED that lights up when pressure value changes exceed the set threshold
  5. DuPont cable, used to connect other components as wires

GoKit4 development board.

DuPont cable.

FSR402 sensor to detect pressure values.

How does it work?

Below are some usage instructions to test the project.

Now let's introduce the demo-Smart-Pressure-detector’s workflow.

  gagentMain---->user_init---->led_init---->tx_timer_create---->userTimerCB

Register a callback in the interface named tx_timer_create,when time is up, call the callback called userTimerCB.

  demo-Smart-Pressure-detector/main/main.c
  
  void gagentMain( void )
  {
      getFreeHeap();
      user_init();
  }

The function named gagentMain was called by GAgent, the main role of GAgent is data forwarding, which is a data interaction bridge between device data, Wit Cloud, and the application. Function user_init, does some sensor initialization:

  void user_init(void)
  {
      int32 ret = -1;
      
      gizLog(LOG_INFO,"Sensor initialization ...\n"); 
  	led_init();							//led init
      txm_module_object_allocate(&userTimer, sizeof(TX_TIMER));
      ret = tx_timer_create(userTimer, "userTimer", userTimerCB, NULL, 1,
                           20, TX_AUTO_ACTIVATE);			
      if(ret != TX_SUCCESS)
      {
          gizLog(LOG_WARNING,"Failed to create UserTimer.\n");
      }
  }
  
  void led_init()
  {
  	   gizLog(LOG_INFO,"in led init...\n"); 
  	   led_gpio_config();
  	   led_on_off(false,led_green);		//init status is off
  }
  
  demo-Smart-Pressure-detector/driver/gpio.c
  
  void led_on_off(bool on, uint8_t pin_gpio)
  {
  	
  	if (on)
  	{
  	qapi_TLMM_Drive_Gpio(gpio_id_tbl[pin_gpio], gpio_map_tbl[pin_gpio].gpio_id, QAPI_GPIO_LOW_VALUE_E);
  	}
  	else
  	{
  	qapi_TLMM_Drive_Gpio(gpio_id_tbl[pin_gpio], gpio_map_tbl[pin_gpio].gpio_id, QAPI_GPIO_HIGH_VALUE_E);
  	}
  }
  
  
  void ICACHE_FLASH_ATTR userTimerCB(void)
  {
  	gizLog(LOG_INFO,"in userTimerCB.....\n"); 
  	int16_t quality;
  
  	quality = fsr402_pressure_adc_read();	  //get quality value.
  
  	if(quality >= 1000)
  	{
  		led_on_off(true,led_green);
  		qapi_Timer_Sleep(100, QAPI_TIMER_UNIT_MSEC, true);
  		led_on_off(false, led_green);
  	}
  else if(quality == -1)
  {
  		led_on_off(true,led_red);
  		qapi_Timer_Sleep(100, QAPI_TIMER_UNIT_MSEC, true);
  		led_on_off(false, led_red);
  	}
   
  }
  
  demo-Smart-Pressure-detector/driver/adc/fsr402_pressure_adc.c
  
  //used to get quality value
  
  int fsr402_pressure_adc_read(void)
  {
      int ret = -1;
      int32_t m_voltage = 0;
      int16_t quilty = 0;
      qapi_ADC_Read_Result_t result;
  	qapi_Status_t status = QAPI_ERROR;
  
      const char *channel_name_adc0 = ADC_INPUT_ADC0;
      
      qapi_Adc_Input_Properties_Type_t Properties_ADC0;
  
  
  /*get an adc handle*/
  
  status = adc_open_handle();
  
      if(status != QAPI_OK)
      {
          gizLog(LOG_ERROR,"Get ADC Handle ERROR!\n");
          return status;
      }
  
  /*get the adc channel configuration*/
  
      status = adc_get_properties(channel_name_adc0, &Properties_ADC0);
      
  if(status != QAPI_OK)
      {
          gizLog(LOG_ERROR,"Get ADC channel-%s Configuration ERROR!\n", channel_name_adc0);
          return status;
      }   
      
  /*read channel ADC0*/
  
  memset(&result, 0, sizeof(result));
  
      status = qapi_ADC_Read_Channel(adc_handle,  &Properties_ADC0, &result);
      if(QAPI_OK == status)
      {
          if(ADC_RESULT_VALID == result.eStatus)
          {  
             m_voltage = result.nMicrovolts /1000;
                  
             quilty = to_quality(m_voltage);
             if(quilty > 0)
             {
                 gizLog(LOG_INFO,"Input %s  Voltage: %d mV  about %d g\n", channel_name_adc0, m_voltage, quilty);
             }
             else if (quilty == 0)
             {
                 gizLog(LOG_INFO,"no press.\n");
             }
             else
             {
                 gizLog(LOG_INFO,"Out of range!\n");
             }  
          }
      }
  
  status = qapi_ADC_Close(adc_handle, false);
  
      if(QAPI_OK != status)
      {
          gizLog(LOG_ERROR,"Free ADC Handle ERROR!\n");
  }
  
      return quilty;
  }
  
  qapi_Status_t adc_open_handle(void)
  {
  	qapi_Status_t status = QAPI_ERROR;
  
  status = qapi_ADC_Open(&adc_handle, 0);
  
      if (QAPI_OK != status) 
      {
          gizLog(LOG_ERROR, "open adc error!\n");
  }
  
      return status;
  }
  
  qapi_Status_t adc_get_properties(const char *Channel_Name_Ptr,
  	qapi_Adc_Input_Properties_Type_t *Properties_Ptr)
  {
  qapi_Status_t status = QAPI_ERROR;
  
      uint32_t Channel_Name_Size = strlen(Channel_Name_Ptr) + 1;
  
  status = qapi_ADC_Get_Input_Properties(adc_handle, Channel_Name_Ptr, Channel_Name_Size, Properties_Ptr);
  
      if (QAPI_OK != status)
      {   
  		gizLog(LOG_ERROR, "ADC Get Channel-%s Properties ERROR!\n", Channel_Name_Ptr);
  }
  
      return status;
  }
  
  //find quality from an arry based on voltage.
  
  int16_t to_quality(int32 m_voltage)            
  {
      uint8_t i =0;
      int16_t quilty = 0;
  
      for(i = 0; i < V_TO_Q_SIZE; i++)
      {
          if(m_voltage <= voltage_to_quality[i].voltage)
          {
              quilty = voltage_to_quality[i].quality;
              return quilty;
          }  
          i++;
      }
  
      if(i >= V_TO_Q_SIZE)
          return -1;
  }

For more details regarding the FSR402 data conversion, please see the blog below:

https://blog.csdn.net/weixin_38498942/article/details/86680506

  1. Download code from GitHub repository: https://github.com/ThunderSoft-XA/demo-Smart-Pressure-detector
  2. Compile the code and flash the image to GoKit4 development kit
  3. Connect the FSR402 sensor to the ADC interface of the GoKit development board
  4. Connect one pin of the LED to the D9 pin of the development board, and the other pin is connected to the Vcc
  5. Connect the USB data cable between the PC and GoKit development board
  6. Open the serial debugging assistant
  7. Put your finger on the pressure receiving surface of the sensor, you can see that the data has changed. When pressure values change beyond the set threshold, the LED will be lit.

Parts used for the GoKit4 development kit demo-Smart-Pressure-detector.

NameEmailTitle/Company
Zhen[email protected]Thundersoft
Rong[email protected]Thundersoft
Jie[email protected]Thundersoft
Kou[email protected]Thundersoft
Eric[email protected]Thundersoft

Qualcomm MDM9206 is a product of Qualcomm Technologies, Inc. and/or its subsidiaries.