Back to All
Project

MDM9206 with Vibration Motor

 

Skill Level Area of Focus Operating System Platform/Hardware Cloud Services/Platform
Intermediate Embedded, IoT, Robotics, Sensors, Smart Cities RTOS Qualcomm® MDM920x LTE for IoT Gizwits Cloud Platform

This project is designed to use an application installed on a mobile phone to control the vibration motor provided by GoKit4 development kit to start/stop a vibration. The GoKit4 development kit is equipped with 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.

Objective

The project’s main objective is to get familiar with the GoKit4 development kit and cloud services. It is designed to use the application installed on a mobile phone to send commands to control the vibration motor provided by GoKit4 development kit to start/ stop the vibration.

Materials Required / Parts List / Tools

  • BG96 LTE Module
  • GoKit4 Development Board

Source Code / Source Examples / Application Executable

  • Source Code

Build / Assembly Instructions

Parts Used

Below are the items used in this project.

 

Parts
  1. Mobile phone with a universal application provided by Gizwits cloud installed. This application can be used to see the sensor data and control the vibration motor on the GoKit4 development kit.
  2. GoKit4 development board
  3. USB data cable, used to supply power
  4. Win7 PC

 

Deploying the Project

  1. First step is to define product named "Smart_vibrator" on the Gizwits cloud platform, including basic information, data point, hardware solution, etc.
  2. Generate code based on the SoC scheme. The Gizwits cloud does not currently support generating code based on the MDM9206 platform, so you will need to choose ESP_826632M as the hardware platform, then make some changes. Please refer to: http://club.gizwits.com/thread-9395-1-1.html for details.
  3. Add local data which will be sent to Gizwits cloud
  4. Install application apk from https://download.gizwits.com/zh-cn/p/98/99
  5. Register mobile IoT card to NB-IoT network
  6. Add driver related code
  7. Compile the code and flash the image
  8. Run the device and open the application to control it

 

How does it work?

First of all, let's see gpio and motor init.

 

  demo-Smart-vibrator/main/main.c
  
  void gagentMain( void )
  {
      getFreeHeap();
      sensorInit();
      gizwitsInit();
  }
  
  void sensorInit(void)
  {
      int32 ret = -1;
      
  gizLog(LOG_INFO,"Sensor initialization ...\n"); 
  led_init();						
  motor_init();						
  txm_module_object_allocate(&userTimer, sizeof(TX_TIMER));
  
      ret = tx_timer_create(userTimer, "userTimer", userTimerCB, NULL, 1,
                            100, 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();
  }
  
  
  void motor_init()
  {
  	gizLog(LOG_INFO,"in motor_init ...\n"); 
  	motor_gpio_config();
  }
  
  demo-Smart-vibrator/gpio/gpio.c
  
  
   void led_gpio_config()
   {
  	    gizLog(LOG_INFO,"in led_gpio_config...\n"); 
  	   
  	    gpio_config(GPIO_BLUE, QAPI_GPIO_OUTPUT_E, QAPI_GPIO_NO_PULL_E, QAPI_GPIO_2MA_E);	
  		
  	    gpio_config(GPIO_RED, QAPI_GPIO_OUTPUT_E, QAPI_GPIO_NO_PULL_E, QAPI_GPIO_2MA_E);	
  		
  
  	    gpio_config(GPIO_GREEN, QAPI_GPIO_OUTPUT_E, QAPI_GPIO_NO_PULL_E, QAPI_GPIO_2MA_E);	
  		
   }
  
  void motor_gpio_config()
  {
  	     gizLog(LOG_INFO,"in motor_gpio_config ...\n"); 
  		 
  	     gpio_config(GPIO_MOTOR, QAPI_GPIO_OUTPUT_E, QAPI_GPIO_NO_PULL_E, QAPI_GPIO_2MA_E);	
  }

gpio_config: does some gpio initialization

void gpio_config(MODULE_PIN_ENUM m_pin,qapi_GPIO_Direction_t gpio_dir,qapi_GPIO_Pull_t gpio_pull,qapi_GPIO_Drive_t gpio_drive)
  {
  	gizLog(LOG_INFO,"in gpio config.....\n"); 
  	
  	qapi_Status_t status = QAPI_OK;
  
  	tlmm_config[m_pin].pin   = gpio_map_tbl[m_pin].gpio_id;
  	tlmm_config[m_pin].func  = gpio_map_tbl[m_pin].gpio_func;
  	tlmm_config[m_pin].dir   = gpio_dir;
  	tlmm_config[m_pin].pull  = gpio_pull;
  	tlmm_config[m_pin].drive = gpio_drive;
  
  	// the default here
  	status = qapi_TLMM_Get_Gpio_ID(&tlmm_config[m_pin], &gpio_id_tbl[m_pin]);
  	
  	gizLog(LOG_INFO,"pin_num = %d, gpio_id[%d], status = %d ...\n",gpio_map_tbl[m_pin].pin_num, gpio_map_tbl[m_pin].gpio_id, status); 
  	
  	if (status == QAPI_OK)
  	{
  		status = qapi_TLMM_Config_Gpio(gpio_id_tbl[m_pin], &tlmm_config[m_pin]);
  
  		gizLog(LOG_INFO,"after qapi_TLMM_Config_Gpio, status = %d ...\n", status); 
  		
  		if (status != QAPI_OK)
  		{
  			gizLog(LOG_INFO,"gpio config failed.....\n"); 
  		}
  		
  		status = qapi_TLMM_Drive_Gpio(gpio_id_tbl[m_pin], gpio_map_tbl[m_pin].gpio_id, QAPI_GPIO_HIGH_VALUE_E);
  	}
  }

Process

gizIssuedProcess ---> ACTION_CONTROL_DEVICE ---> gizDataPoint2Event ---> gizwitsEventProcess

gizIssuedProcess: the function is called by the gagent to receive the relevant protocol data delivered from the cloud or the app.

int32_t ICACHE_FLASH_ATTR gizIssuedProcess(uint8_t *didPtr, uint8_t *inData, uint32_t inLen,uint8_t *outData,int32_t *outLen)
  {
  	uint8_t i = 0;
  
  
      if((NULL == inData) || (NULL == outData) || (NULL == outLen)) 
      {
          gizLog(LOG_WARNING,"!!! IssuedProcess Error \n"); 
          return -1;
      }
  
      if(NULL == didPtr)
      {
          gizLog(LOG_INFO,"~~~gizIssuedProcess: did is NULL .\n");
      }
      else
      {
          gizLog(LOG_INFO,"~~~gizIssuedProcess: did %s\n", didPtr);
      }
  
      gizLog(LOG_INFO,"%s: ", "~~~issued data"); 
      //printf_bufs((uint8_t *)inData,inLen);
  
      if(NULL == didPtr) 
      { 
          switch(inData[0]) 
          {
              case ACTION_CONTROL_DEVICE:
  
                  gizDataPoint2Event((gizwitsIssued_t *)&inData[1], &gizwitsProtocol.issuedProcessEvent,&gizwitsProtocol.gizCurrentDataPoint); 
                  gizwitsEventProcess(&gizwitsProtocol.issuedProcessEvent, (uint8_t *)&gizwitsProtocol.gizCurrentDataPoint, sizeof(dataPoint_t));
                  gizMemset((uint8_t *)&gizwitsProtocol.issuedProcessEvent, 0, sizeof(eventInfo_t));          
                  *outLen = 0; 
                  break;
                  
              case ACTION_READ_DEV_STATUS:
                  gizDataPoints2ReportData(&gizwitsProtocol.gizLastDataPoint,&gizwitsProtocol.reportData.devStatus);
                  gizwitsProtocol.reportData.action = ACTION_READ_DEV_STATUS_ACK;
                  gizMemcpy(outData, (uint8_t *)&gizwitsProtocol.reportData, sizeof(gizwitsReport_t));
                  *outLen = sizeof(gizwitsReport_t);
                  
                  gizLog(LOG_INFO,"%s: ", "~~~ReadReport \n");
                  //printf_bufs((uint8_t *)outData,*outLen);
                  break;
                  
              case ACTION_W2D_TRANSPARENT_DATA: 
  
                  gizMemcpy(gizwitsProtocol.transparentBuff, &inData[1], inLen-1);
                  gizwitsProtocol.transparentLen = inLen-1;
                  
                  gizwitsProtocol.issuedProcessEvent.event[0] = TRANSPARENT_DATA;
                  gizwitsProtocol.issuedProcessEvent.num = 1;
                  gizwitsEventProcess(&gizwitsProtocol.issuedProcessEvent, (uint8_t *)gizwitsProtocol.transparentBuff, gizwitsProtocol.transparentLen);
  
                  gizMemset((uint8_t *)&gizwitsProtocol.issuedProcessEvent, 0, sizeof(eventInfo_t));
                  gizMemset((uint8_t *)gizwitsProtocol.transparentBuff, 0, BUFFER_LEN_MAX);
                  gizwitsProtocol.transparentLen = 0;
                  *outLen = 0;
  
                  break;       
       
              default:
  
                  break;
          }
      }
      else
      { 
          gizLog(LOG_WARNING," Error : didPtr  \n");
      }
  
      return 0;
  }

ACTION_CONTROL_DEVICE: Perform related processing of "controlled protocol"

gizDataPoint2Event: Generate "control events" according to the protocol and complete the conversion of the corresponding data type.

static int8_t ICACHE_FLASH_ATTR gizDataPoint2Event(gizwitsIssued_t *issuedData, eventInfo_t *info, dataPoint_t *dataPoints)
  {
      if((NULL == issuedData) || (NULL == info) ||(NULL == dataPoints))
      {
          gizLog(LOG_WARNING,"gizDataPoint2Event Error , Illegal Param\n");
          return -1;
      }
      
      /** Greater than 1 byte to do bit conversion **/
      if(sizeof(issuedData->attrFlags) > 1)
      {
          if(-1 == gizByteOrderExchange((uint8_t *)&issuedData->attrFlags,sizeof(attrFlags_t)))
          {
              gizLog(LOG_WARNING,"gizByteOrderExchange Error\n");
              return -1;
          }
  }
  
      if(0x01 == issuedData->attrFlags.flagLed_Value)
      {
          info->event[info->num] = EVENT_Led_Value;
          info->num++;
          dataPoints->valueLed_Value = gizStandardDecompressionValue(Led_Value_BYTEOFFSET,Led_Value_BITOFFSET,Led_Value_LEN,(uint8_t *)&issuedData->attrVals.wBitBuf,sizeof(issuedData->attrVals.wBitBuf));
      }
          
      if(0x01 == issuedData->attrFlags.flagMotor_Value)
      {
          info->event[info->num] = EVENT_Motor_Value;
          info->num++;
          dataPoints->valueMotor_Value = gizStandardDecompressionValue(Motor_Value_BYTEOFFSET,Motor_Value_BITOFFSET,Motor_Value_LEN,(uint8_t *)&issuedData->attrVals.wBitBuf,sizeof(issuedData->attrVals.wBitBuf));
      }   
      return 0;
  }

gizwitsEventProcess: corresponding event processing according to the generated "control event" (calling the corresponding driver function)

int8_t ICACHE_FLASH_ATTR gizwitsEventProcess(eventInfo_t *info, uint8_t *data, uint32_t len)
  {
      uint8_t i = 0;
      dataPoint_t * dataPointPtr = (dataPoint_t *)data;
      moduleStatusInfo_t * wifiData = (moduleStatusInfo_t *)data;
  
      if((NULL == info) || (NULL == data))
      {
          gizLog(LOG_WARNING,"!!! gizwitsEventProcess Error \n");
          return -1;
      }
  
      for(i = 0; i < info->num; i++)
      {
          switch(info->event[i])
          {
          case EVENT_Led_Value :
              currentDataPoint.valueLed_Value = dataPointPtr->valueLed_Value;
              gizLog(LOG_INFO, "Evt: EVENT_LedValue %d \n", currentDataPoint.valueLed_Value);
              if(0x01 == currentDataPoint.valueLed_Value)
              {
                         //on led
  		gpio_high_low(true,GPIO_GREEN);	
              }
              else
              {
                        //off led
  		gpio_high_low(false, GPIO_GREEN);	
              }
              break;
          case EVENT_Motor_Value :
              currentDataPoint.valueMotor_Value = dataPointPtr->valueMotor_Value;
              gizLog(LOG_INFO,"Evt: EVENT_MotorValue %d \n", currentDataPoint.valueMotor_Value
              );
              if(0x01 == currentDataPoint.valueMotor_Value)
              {
                         //start motor
                         gpio_high_low(true,GPIO_MOTOR);	
              }
              else
              {
                      //stop motor
                      gpio_high_low(false,GPIO_MOTOR);	
              }
              break;
          ......
              
          default:
              break;
          }
      }
      gizSendQueue(SIG_UPGRADE_DATA);
      
      return 0; 
  }

gpio_high_low: mainly to control led or motor by setting the high/low level to the corresponding pin.

 void gpio_high_low(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_GPImotor_gpio_configO_HIGH_VALUE_E);
  	}
   }

Usage Instructions

  1. Download code from GitHub according to the repository in https://github.com/ThunderSoft-XA/demo-Smart-vibrator
  2. Compile the code and flash the image to the GoKit4 development kit
  3. Connect the USB data cable between the PC and GoKit4 development board
  4. Open the serial debugging assistant
  5. Click on "Device log" in Gizwits cloud to check if the device is online
  6. When the device is online, you can click the "view" button, and you'll see data from local was sent to Gizwits cloud
  7. Download the app from https://download.gizwits.com/zh-cn/p/98/99 and install it to your phone
  8. Open the application apk, and you'll see "my device", and from here you can find your device by scanning the QR code
  9. Next, generate the QR code
    1. Open "gizwits debugging assistant_v2.3.9/GIZ_SerialTool.exe"
    2. Choose "small tools", click "QR code generation", input "product key" and "MAC/IMEI"
    3. Click "get QR code", wait for a moment, and you can see a QR code
  10. Click "my device", scan the generated QR code, and you can find your device
  11. Then you can control the device and view the data
Showing

Contributor Info

Name Email Title/Company
Zhen sunzhen@thundersoft.com Thundersoft
Rong yangrong0925@thundersoft.com Thundersoft
Jie wangjie0508@thundersoft.com Thundersoft
Kou kouzw0723@thundersoft.com Thundersoft
Eric yansh0810@thundersoft.com Thundersoft

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

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries ("Qualcomm"). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.

Project Authors
Thunder Software Technology (Shenzhen) Co., Ltd.
Shenzhen

Sign up for the Developer Newsletter.

Get software and hardware tool resources to help optimize your development delivered to your inbox weekly.

© Qualcomm Technologies, Inc. and/or its affiliated companies.

Snapdragon and Qualcomm branded products are products of Qualcomm Technologies, Inc. and/or its subsidiaries. Qualcomm patents are licensed by Qualcomm Incorporated.

Note: Certain services and materials may require you to accept additional terms and conditions before accessing or using those items.

References to "Qualcomm" may mean Qualcomm Incorporated, or subsidiaries or business units within the Qualcomm corporate structure, as applicable.

Qualcomm Incorporated includes our licensing business, QTL, and the vast majority of our patent portfolio. Qualcomm Technologies, Inc., a subsidiary of Qualcomm Incorporated, operates, along with its subsidiaries, substantially all of our engineering, research and development functions, and substantially all of our products and services businesses, including our QCT semiconductor business.

Materials that are as of a specific date, including but not limited to press releases, presentations, blog posts and webcasts, may have been superseded by subsequent events or disclosures.

Nothing in these materials is an offer to sell or license any of the services or materials referenced herein.