本帖最后由 MOPPLAYER 于 2015-12-8 23:26 编辑
前言:本篇將快速指引如何建構一個以BLE收集資料和觸發家電開關的項目,因為不拆開電器,所以電器方面我以小風扇來代表
實作:
1. 創建PSoC_4_BLE_CapSense_Slider_LED範例專案,我將以這專案為基礎新增功能
2. 新建三個
元件,一個Analog,一個Digital Output,一個ADC SAR Seq,我們將讀取Analog訊號來控制Digital輸出
Fig. 1 新增三個元件
3. 其中三個元件設定值如下:
Fig. 2 Analog 元件設定
Fig. 3 Digital元件設定
Fig. 4 ADC元件設定,其中主要設定的是Vref select和Single ended nega
tive input決定ADC轉換的電壓範圍,而Clock frequency(或者使用Channel sample rate)設定採樣頻率,其他Sample averaged是採樣多少次來做平均
Fig. 5 ADC元件設定,保留一個Channel 0即可,並勾選AVG設定,以平均採樣的結果,並選擇Single方式
4. 完成設定後,接線圖如下:
Fig. 6 接線圖
5. 設定腳位如下,不一定要設定這兩個腳位,但也不是每個腳位都能正確讀取Analog值
Fig. 7 腳位設定
6. 再來開始修改程式碼,仿照CapSense元件透傳方式,新增以下程式碼
在main.c中修改程式碼如下:
- if(TRUE == deviceConnected)
- {
- /* After the connection, send new connection parameter to the Client device
- * to run the BLE communication on desired interval. This affects the data rate
- * and power consumption. High connection interval will have lower data rate but
- * lower power consumption. Low connection interval will have higher data rate at
- * expense of higher power. This function is called only once per connection. */
- UpdateConnectionParam();
-
- /* When the Client Characteristic Configuration descriptor (CCCD) is written
- * by Central device for enabling/disabling notifications, then the same
- * descriptor value has to be explicitly updated in application so that
- * it reflects the correct value when the descriptor is read */
- UpdateNotificationCCCD();
-
- /* Send CapSense Slider data when respective notification is enabled */
- if(sendCapSenseSliderNotifications & CCCD_NTF_BIT_MASK)
- {
- if(CYBLE_BLESS_STATE_ECO_STABLE ==CyBle_GetBleSsState())
- {
- /* Check for CapSense slider swipe and send data accordingly */
- HandleCapSenseSlider();
- }
- }
-
- /* Send analog data when respective notification is enabled */
- if(sendAnalogNotifications & CCCD_NTF_BIT_MASK)
- {
- if(CYBLE_BLESS_STATE_ECO_STABLE ==CyBle_GetBleSsState())
- {
- /* Check for analog reading and send data accordingly */
- HandleAnalogReading();
- }
- }
- }
- /* Start BLE component and register the CustomEventHandler function. This
- * function exposes the events from BLE component for application use */
- CyBle_Start(CustomEventHandler);
-
- ADC_SAR_Seq_1_Start();
- ADC_SAR_Seq_1_StartConvert();
- ADC_SAR_Seq_1_IsEndConversion(ADC_SAR_Seq_1_WAIT_FOR_RESULT);
- Pin_2_Write(0);
-
- /* Start the PrISM component for LED control*/
- PrISM_1_Start();
- PrISM_2_Start();
-
- /* The RGB LED on BLE Pioneer kit are active low. Drive HIGH on
- pin for OFF and drive LOW on pin for ON*/
- PrISM_1_WritePulse0(RGB_LED_OFF);
- PrISM_1_WritePulse1(RGB_LED_OFF);
- PrISM_2_WritePulse0(RGB_LED_OFF);
- void HandleAnalogReading(void)
- {
- uint16 ADCResult = ADC_SAR_Seq_1_GetResult16(0);
- uint8 AnalogData[2];
-
- AnalogData[0] = ((ADCResult >> 8) & 0xFF);
- AnalogData[1] = (ADCResult & 0xFF);
-
- if(ADCResult > OPEN_FAN)
- Pin_2_Write(1);
- else
- Pin_2_Write(0);
-
- SendDataOverAnalogNotification(AnalogData,ANALOG_DATA_LEN);
- }
其中本Handler主要控制風扇開關和Analog讀值的通知透傳
7. 在main.h加入以下定義
- #define OPEN_FAN 1500
- void HandleAnalogReading(void);
- void SendDataOverAnalogNotification(uint8 *AnalogData, uint16 len);
8. 在BLE_application增加以下程式碼
- /*This flag is set when the Central device writes to CCCD (Client Characteristic
- * Configuration Descriptor) of the CapSense slider Characteristic to enable
- * notifications */
- uint8 sendCapSenseSliderNotifications = FALSE;
- /*This flag is set when the Central device writes to CCCD (Client Characteristic
- * Configuration Descriptor) of the Analog Characteristic to enable
- * notifications */
- uint8 sendAnalogNotifications = FALSE;
- /*This flag is set when the Central device writes to CCCD of the
- * RGB LED Characteristic to enable notifications */
- uint8 rgbledNotifications = FALSE;
- /* These flags are used to let application update the respective CCCD value of the
- * custom characteristics for correct read operation by connected Central device */
- uint8 updateSliderNotificationCCCDAttribute = FALSE;
- uint8 updateRGBNotificationCCCDAttribute = FALSE;
- uint8 updateAnalogNotificationCCCDAttribute = FALSE;
- case CYBLE_EVT_GATT_DISCONNECT_IND:
- /* This event is received when device is disconnected */
-
- /* Update deviceConnected flag*/
- deviceConnected = FALSE;
-
- /* Reset CapSense notification flag to prevent further notifications
- * being sent to Central device after next connection. */
- sendCapSenseSliderNotifications = FALSE;
-
- /* Reset Analog notification flag to prevent further notifications
- * being sent to Central device after next connection. */
- sendAnalogNotifications = FALSE;
-
- Pin_2_Write(0);
-
- /* Reset RGB notification flag to prevent further notifications
- * being sent to Central device after next connection. */
- rgbledNotifications = FALSE;
-
- /* Reset the CCCD value to disable notifications */
- updateRGBNotificationCCCDAttribute = TRUE;
- updateAnalogNotificationCCCDAttribute = TRUE;
- updateSliderNotificationCCCDAttribute = TRUE;
- UpdateNotificationCCCD();
- /* When this event is triggered, the peripheral has received a write command on the custom characteristic */
- /* Check if command is for correct attribute and update the flag for sending Notifications */
- if(CYBLE_CAPSENSE_CAPSENSE_SLIDER_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE == wrReqParam->handleValPair.attrHandle)
- {
- /* Extract the Write value sent by the Client for CapSense Slider CCCD */
- sendCapSenseSliderNotifications = wrReqParam->handleValPair.value.val[CYBLE_CAPSENSE_CAPSENSE_SLIDER_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_INDEX];
-
- /* Set flag to allow CCCD to be updated for next read operation */
- updateSliderNotificationCCCDAttribute = TRUE;
- }
-
- /* When this event is triggered, the peripheral has received a write command on the custom characteristic */
- /* Check if command is for correct attribute and update the flag for sending Notifications */
- if(CYBLE_ANALOG_READ_ANALOG_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE == wrReqParam->handleValPair.attrHandle)
- {
- /* Extract the Write value sent by the Client for Analog CCCD */
- sendAnalogNotifications = wrReqParam->handleValPair.value.val[CYBLE_ANALOG_READ_ANALOG_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_INDEX];
-
- /* Set flag to allow CCCD to be updated for next read operation */
- updateAnalogNotificationCCCDAttribute = TRUE;
- }
- /*******************************************************************************
- * Function Name: SendDataOverAnalogNotification
- ********************************************************************************
- * Summary:
- * Send Analog reading data as BLE Notifications. This function updates
- * the notification handle with data and triggers the BLE component to send
- * notification
- *
- * Parameters:
- * AnalogData: Analog reading value
- *
- * Return:
- * void
- *
- *******************************************************************************/
- void SendDataOverAnalogNotification(uint8 *AnalogData, uint16 len)
- {
- /* 'CapSensenotificationHandle' stores CapSense notification data parameters */
- CYBLE_GATTS_HANDLE_VALUE_NTF_T AnalognotificationHandle;
-
- /* If stack is not busy, then send the notification */
- if(busyStatus == CYBLE_STACK_STATE_FREE)
- {
- /* Update notification handle with CapSense slider data*/
- AnalognotificationHandle.attrHandle = CYBLE_ANALOG_READ_ANALOG_CHAR_HANDLE;
- AnalognotificationHandle.value.val = AnalogData;
- AnalognotificationHandle.value.len = len;
-
- /* Send the updated handle as part of attribute for notifications */
- CyBle_GattsNotification(connectionHandle,&AnalognotificationHandle);
- }
- }
- /*******************************************************************************
- * Function Name: UpdateNotificationCCCD
- ********************************************************************************
- * Summary:
- * Update the data handle for notification status and report it to BLE
- * component so that it can be read by Central device.
- *
- * Parameters:
- * void
- *
- * Return:
- * void
- *
- *******************************************************************************/
- void UpdateNotificationCCCD(void)
- {
- /* Local variable to store the current CCCD value */
- uint8 CapSenseCCCDvalue[2];
- uint8 RGBCCCDvalue[2];
- uint8 AnalogCCCDvalue[2];
-
- /* Handle value to update the CCCD */
- CYBLE_GATT_HANDLE_VALUE_PAIR_T CapSenseNotificationCCCDhandle;
-
- /* Handle value to update the CCCD */
- CYBLE_GATT_HANDLE_VALUE_PAIR_T AnalogNotificationCCCDhandle;
-
- /* Handle value to update the CCCD */
- CYBLE_GATT_HANDLE_VALUE_PAIR_T RGBNotificationCCCDhandle;
- /* Update notification attribute only when there has been change in CapSense CCCD */
- if(updateSliderNotificationCCCDAttribute)
- {
- /* Reset the flag*/
- updateSliderNotificationCCCDAttribute = FALSE;
-
- /* Write the present CapSense notification status to the local variable */
- CapSenseCCCDvalue[0] = sendCapSenseSliderNotifications;
- CapSenseCCCDvalue[1] = 0x00;
-
- /* Update CCCD handle with notification status data*/
- CapSenseNotificationCCCDhandle.attrHandle = CYBLE_CAPSENSE_CAPSENSE_SLIDER_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE;
- CapSenseNotificationCCCDhandle.value.val = CapSenseCCCDvalue;
- CapSenseNotificationCCCDhandle.value.len = CCCD_DATA_LEN;
-
- /* Report data to BLE component for sending data when read by Central device */
- CyBle_GattsWriteAttributeValue(&CapSenseNotificationCCCDhandle, ZERO, &connectionHandle, CYBLE_GATT_DB_LOCALLY_INITIATED);
- }
-
- /* Update notification attribute only when there has been change in Analog CCCD */
- if(updateAnalogNotificationCCCDAttribute)
- {
- /* Reset the flag*/
- updateAnalogNotificationCCCDAttribute = FALSE;
-
- /* Write the present Analog notification status to the local variable */
- AnalogCCCDvalue[0] = sendAnalogNotifications;
- AnalogCCCDvalue[1] = 0x00;
-
- /* Update CCCD handle with notification status data*/
- AnalogNotificationCCCDhandle.attrHandle = CYBLE_ANALOG_READ_ANALOG_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE;
- AnalogNotificationCCCDhandle.value.val = AnalogCCCDvalue;
- AnalogNotificationCCCDhandle.value.len = CCCD_DATA_LEN;
-
- /* Report data to BLE component for sending data when read by Central device */
- CyBle_GattsWriteAttributeValue(&AnalogNotificationCCCDhandle, ZERO, &connectionHandle, CYBLE_GATT_DB_LOCALLY_INITIATED);
- }
-
- /* Update notification attribute only when there has been change in RGB LED CCCD*/
- if(updateRGBNotificationCCCDAttribute)
- {
- /* Reset the flag*/
- updateRGBNotificationCCCDAttribute = FALSE;
-
- /* Write the present RGB notification status to the local variable */
- RGBCCCDvalue[0] = rgbledNotifications;
- RGBCCCDvalue[1] = 0x00;
-
- /* Update CCCD handle with notification status data*/
- RGBNotificationCCCDhandle.attrHandle = CYBLE_RGB_LED_RGB_LED_CONTROL_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE;
- RGBNotificationCCCDhandle.value.val = RGBCCCDvalue;
- RGBNotificationCCCDhandle.value.len = CCCD_DATA_LEN;
-
- /* Report data to BLE component for sending data when read by Central device */
- CyBle_GattsWriteAttributeValue(&RGBNotificationCCCDhandle, ZERO, &connectionHandle, CYBLE_GATT_DB_LOCALLY_INITIATED);
- }
- }
9. 修改完畢後儲存,回到TopDesign原理圖的BLE元件來新增服務
Fig. 8 新增BLE自定義服務,UUID可自己喜好來設定
Fig. 9 新增特徵值,資料型態為Array,種類為通知透傳(Notification)
Fig. 10 透傳的開啟描述子
Fig. 11 服務描述子
10. 以上完成修改,按下編譯,並且燒寫至開發板上,應該是0錯誤0警告,1個通知如下
Fig. 12 編譯完成,此通知是說明受限DWR,採樣頻率會降低
11. 利用Cysmart來驗證,也可使用手機等行動裝置,電腦插入USB Dongel,在開發板上按一下SW2按鈕開始廣播,並連線,如下圖
Fig. 13 連線成功,提示動態調整組態設定,按下Yes
12. 按下Discover All Attributes,拉到最底下可看到新增的自定義服務
Fig. 14 新增的服務找尋OK
13. 將開發板接線,這裡我使用一個光敏傳感器模組,和一個繼電器模組,加上一個風扇組合成一個簡易的居家控制系統,依照讀取光敏的Analog值打開風扇,可想見情境:進入房間後打開電燈,會自動開啟風扇,離開房間時關閉電燈,風扇也會關閉
- P1.6 <=> 光敏模組OUT
- P1.7 <=> 繼電器模組IN
- 3.3V <=> 光敏模組VCC
- 5V <=> 繼電器模組VCC
- GND <=> 光敏模阻GND
- GND <=> 繼電器模組GND
- 12V電源VCC <=> 繼電器模組COM
- 繼電器模組NO <=> 風扇VCC
- 12V電源GND <=> 風扇GND
Fig. 15 實品接線圖
14. 對新建立的服務通知透傳描述子寫入1
Fig. 16 可發現特徵值開始接收到光敏模組的Analog值
15. 遮蔽光敏電阻,繼電器會關閉,放開時繼電器會觸發開啟,導通風扇
Fig. 17 風扇導通,衛生紙識別用
Fig. 18 遮蔽光敏模組,風扇關閉
16. 結束連線時,會自動關閉繼電器,注意,本設計必須建立BLE連線才能控制風扇開關,完成本篇項目設計