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
Source Code / Source Examples / Application Executable
Build / Assembly Instructions
Parts Used
Below are the items used in this project.
- 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.
- GoKit4 development board
- USB data cable, used to supply power
- Win7 PC
Deploying the Project
- First step is to define product named "Smart_vibrator" on the Gizwits cloud platform, including basic information, data point, hardware solution, etc.
- 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.
- Add local data which will be sent to Gizwits cloud
- Install application apk from https://download.gizwits.com/zh-cn/p/98/99
- Register mobile IoT card to NB-IoT network
- Add driver related code
- Compile the code and flash the image
- 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 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
- Download code from GitHub according to the repository in https://github.com/ThunderSoft-XA/demo-Smart-vibrator
- Compile the code and flash the image to the GoKit4 development kit
- Connect the USB data cable between the PC and GoKit4 development board
- Open the serial debugging assistant
- Click on "Device log" in Gizwits cloud to check if the device is online
- When the device is online, you can click the "view" button, and you'll see data from local was sent to Gizwits cloud
- Download the app from https://download.gizwits.com/zh-cn/p/98/99 and install it to your phone
- Open the application apk, and you'll see "my device", and from here you can find your device by scanning the QR code
- Next, generate the QR code
- Open "gizwits debugging assistant_v2.3.9/GIZ_SerialTool.exe"
- Choose "small tools", click "QR code generation", input "product key" and "MAC/IMEI"
- Click "get QR code", wait for a moment, and you can see a QR code
- Click "my device", scan the generated QR code, and you can find your device
- Then you can control the device and view the data
Contributor Info
Name | Title/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.