Wi-Fi経由のオフィス照明制御。 パート3:ライトを制御する





今日、私たちは最終的に、 第1部と第2部で得られた知識とベストプラクティスを組み合わせることでこのサイクルを完了します。



前のエピソードの要約
AtmelのAtmelのWi-FiモジュールWINC1500を使用して、サードパーティのアクセスポイントに接続し、クライアントとしてTCPサーバーに接続してデータを転送することを学びました。 タッチボタンとスライダーを使用した作業もマスターされ、対応するビデオが撮影されました。



一般的な概念を思い出してください。 Atmel SAMD21マイクロコントローラーを使用したデバッグのために、Q-touch拡張カードが接続されています。このカードには、スライダーとローターの3つのボタンがあります。 1つのボタンを使用して照明をオンにし、もう1つのボタンを使用してオフにし、スライダーを使用して明るさをスムーズに調整します。 WINC1500モジュールを搭載したボードは、2番目のポートに接続されます。 私たちのデバイス(または、プロトタイプ)は、TCPクライアントとして機能します。 サーバーは、 DALIGW1 -ModBusコマンドをDALIプロトコル(Digital Addressable Lighting Interface)のコマンドに変換するModBus TCPデバイス-デジタル照明制御用の特別なプロトコルになります。 したがって、センサーの位置の値を受け取り、Modbusプロトコルに従ってリクエストを作成し、Wi-Fi経由でゲートウェイに送信します。



TCPクライアント


簡単にするために、アクセスポイントを作成し、使用可能なネットワークをスキャンして、ユーザーにそれらの1つに接続するように依頼しませんが、オフィスのローカルネットワークに必要な設定をコードで直接設定します。

作業の開始時に、以前に作成したプロジェクトの1つ(記事の前の部分)またはQtouchまたはWINC1500のサンプルプロジェクトを開き、以前の記事の1つで説明したように、ウィザードを使用して必要なモジュールを追加できます。



main.hファイルでネットワークパラメータを設定します。

#define MAIN_WLAN_SSID "Habrahabr" //   #define MAIN_WLAN_AUTH M2M_WIFI_SEC_WPA_PSK //   #define MAIN_WLAN_PSK "123456789" //    #define MAIN_WIFI_M2M_PRODUCT_NAME "Hello world!\n\r" #define MAIN_WIFI_M2M_SERVER_IP 0xc0a81490 // IP   () #define MAIN_WIFI_M2M_SERVER_PORT (502) //  .  502  ModBus TCP
      
      







main.cで、 tcpクライアントモードでwinc1500で動作するようにライブラリを構成します。

  //Initialize the BSP. nm_bsp_init(); // Initialize socket address structure. addr.sin_family = AF_INET; addr.sin_port = _htons(MAIN_WIFI_M2M_SERVER_PORT); addr.sin_addr.s_addr = _htonl(MAIN_WIFI_M2M_SERVER_IP); // Initialize Wi-Fi parameters structure. memset((uint8_t *)¶m, 0, sizeof(tstrWifiInitParam)); // Initialize Wi-Fi driver with data and status callbacks. param.pfAppWifiCb = wifi_cb; ret = m2m_wifi_init(¶m); if (M2M_SUCCESS != ret) { printf("main: m2m_wifi_init call error!(%d)\r\n", ret); while (1); } // Initialize socket module socketInit(); registerSocketCallback(socket_cb, NULL); // Connect to router. m2m_wifi_connect((char *)MAIN_WLAN_SSID, sizeof(MAIN_WLAN_SSID), MAIN_WLAN_AUTH, (char *)MAIN_WLAN_PSK, M2M_WIFI_CH_ALL);
      
      







お気に入りのコールバックを忘れないでください。 ネットワークを介したイベント処理機能を規定しています。

コールバックコード
 static void socket_cb(SOCKET sock, uint8_t u8Msg, void *pvMsg) { switch (u8Msg) { // Socket connected case SOCKET_MSG_CONNECT: { tstrSocketConnectMsg *pstrConnect = (tstrSocketConnectMsg *)pvMsg; if (pstrConnect && pstrConnect->s8Error >= 0) { printf("socket_cb: connect success!\r\n"); if (button_pressed!=0) { send(tcp_client_socket, &data_to_send, 12, 0); printf("socket_number after connection: %d\r\n", tcp_client_socket); } close(tcp_client_socket); delay_ms(50); } else { printf("socket_cb: connect error!\r\n"); close(tcp_client_socket); tcp_client_socket = -1; } } break; // Message send case SOCKET_MSG_SEND: { printf("socket_cb: send success!\r\n"); recv(tcp_client_socket, gau8SocketTestBuffer, sizeof(gau8SocketTestBuffer), 0); } break; // Message receive case SOCKET_MSG_RECV: { tstrSocketRecvMsg *pstrRecv = (tstrSocketRecvMsg *)pvMsg; if (pstrRecv && pstrRecv->s16BufferSize > 0) { printf("socket_cb: recv success!\r\n"); printf("TCP Client Test Complete!\r\n"); } else { printf("socket_cb: recv error!\r\n"); close(tcp_client_socket); tcp_client_socket = -1; } } break; default: break; } } static void wifi_cb(uint8_t u8MsgType, void *pvMsg) { printf("wifi_cb: u8MsgType= %d\n",u8MsgType); switch (u8MsgType) { case M2M_WIFI_RESP_CON_STATE_CHANGED: { tstrM2mWifiStateChanged *pstrWifiState = (tstrM2mWifiStateChanged *)pvMsg; if (pstrWifiState->u8CurrState == M2M_WIFI_CONNECTED) { printf("wifi_cb: M2M_WIFI_RESP_CON_STATE_CHANGED: CONNECTED\r\n"); m2m_wifi_request_dhcp_client(); } else { if (pstrWifiState->u8CurrState == M2M_WIFI_DISCONNECTED) { printf("wifi_cb: M2M_WIFI_RESP_CON_STATE_CHANGED: DISCONNECTED\r\n"); wifi_connected = 0; m2m_wifi_connect((char *)MAIN_WLAN_SSID, sizeof(MAIN_WLAN_SSID), MAIN_WLAN_AUTH, (char *)MAIN_WLAN_PSK, M2M_WIFI_CH_ALL); } } break; } case M2M_WIFI_REQ_DHCP_CONF: { uint8_t *pu8IPAddress = (uint8_t *)pvMsg; wifi_connected = 1; printf("wifi_cb: M2M_WIFI_REQ_DHCP_CONF: IP is %u.%u.%u.%u\r\n", pu8IPAddress[0], pu8IPAddress[1], pu8IPAddress[2], pu8IPAddress[3]); printf("wifi_cb: M2M_WIFI_REQ_DHCP_CONF: getaway IP is %u.%u.%u.%u\r\n", pu8IPAddress[4], pu8IPAddress[5], pu8IPAddress[6], pu8IPAddress[7]); printf("wifi_cb: M2M_WIFI_REQ_DHCP_CONF: DNS IP is %u.%u.%u.%u\r\n", pu8IPAddress[8], pu8IPAddress[9], pu8IPAddress[10], pu8IPAddress[11]); printf("wifi_cb: M2M_WIFI_REQ_DHCP_CONF: mask is %u.%u.%u.%u\r\n", pu8IPAddress[12], pu8IPAddress[13], pu8IPAddress[14], pu8IPAddress[15]); break; } default: break; } }
      
      









実際、これはwincをtcpクライアントとして使用するために必要なすべてのコードです。



Qtouch


ボタンとスライダーを処理するための記事の2番目の部分で説明されているすべてのコードは完全に移植性があり、tcpを介してパッケージの形成と送信を追加するだけです。



すべてをまとめる


ModBusプロトコルはシンプルでオープンであり、自動化システムで非常に愛されています。インターネット上で多くの情報を見つけることができるからです。 wikiの内容は次のとおりです。 すでに述べたように、ローカルネットワークで動作するように設計されたTCPの変更を使用します。

トレーニングタスクがあるため、美しいModBusライブラリを実装しません(個別の関数、レジスタ、データなどを示します)が、対応するバイトセットを単純に作成し、オープンソケットに送信します。 この場合のModbusパケットは、レジスタに書き込まれたデータの部分でのみ変更されます(ゲートウェイとの作業プロトコルに従って)。 1つのレジスタで書き込みコマンドを使用します-コマンドコードは0x06です。

パッケージフィールド:



読者をDALIプロトコルの詳細に没頭させるために、この記事の目的は意図されていなかったため、使用するコマンドを簡単な説明とともに単純にリストします。



注:(科学者は、デバッグの役割である)ModBusマスターがスレーブと通信する方が正しいことについて議論しています-現在の通信セッションの終了後にソケットを閉じるか、開いたままにします。 この例では、ゲートウェイに接続したい他のマスターもバス上にいる可能性があるという事実に基づいて、最初の方法を使用しました。 しかし、ここでは正しいアプローチは、ほとんどの場合そうではなく、すべては開発者の世界観に依存しています。



それだけです 最後の部分は特にボリュームがありませんでしたが、主な詰め物全体は最初の2つの部分にありました。 面白かったと思います。

最終コードメイン
 int main(void) { uint8_t button1_state; uint8_t button2_state; uint8_t slider_state; uint8_t slider_position; tstrWifiInitParam param; int8_t ret; struct sockaddr_in addr; // Initialize and configure system and generic clocks. // Use conf_clocks.h to configure system and generic clocks. system_init(); // Enable global interrupts. system_interrupt_enable_global(); //Initialize delay service. delay_init(); //Initialize timer. (RTC actually) timer_init(); //Initialize QTouch library and configure touch sensors. touch_sensors_init(); // Configure port pins configure_port_pins(); // Turn off all extension board LEDs port_pin_set_output_level(LED_0_PIN, 1); port_pin_set_output_level(LED_1_PIN, 1); port_pin_set_output_level(LED_2_PIN, 1); port_pin_set_output_level(LED_3_PIN, 1); port_pin_set_output_level(LED_4_PIN, 1); port_pin_set_output_level(LED_5_PIN, 1); port_pin_set_output_level(LED_6_PIN, 1); port_pin_set_output_level(LED_7_PIN, 1); port_pin_set_output_level(LED_8_PIN, 1); port_pin_set_output_level(LED_9_PIN, 1); port_pin_set_output_level(LED_R_PIN, 1); port_pin_set_output_level(LED_G_PIN, 1); port_pin_set_output_level(LED_B_PIN, 1); PWM_Count = 0; NVMCTRL->CTRLB.bit.SLEEPPRM = 3; system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY); // Initialize the UART console. configure_console(); printf(STRING_HEADER); //Initialize the BSP. nm_bsp_init(); // Initialize socket address structure. addr.sin_family = AF_INET; addr.sin_port = _htons(MAIN_WIFI_M2M_SERVER_PORT); addr.sin_addr.s_addr = _htonl(MAIN_WIFI_M2M_SERVER_IP); // Initialize Wi-Fi parameters structure. memset((uint8_t *)¶m, 0, sizeof(tstrWifiInitParam)); // Initialize Wi-Fi driver with data and status callbacks. param.pfAppWifiCb = wifi_cb; ret = m2m_wifi_init(¶m); if (M2M_SUCCESS != ret) { printf("main: m2m_wifi_init call error!(%d)\r\n", ret); while (1); } // Initialize socket module socketInit(); registerSocketCallback(socket_cb, NULL); // Connect to router. m2m_wifi_connect((char *)MAIN_WLAN_SSID, sizeof(MAIN_WLAN_SSID), MAIN_WLAN_AUTH, (char *)MAIN_WLAN_PSK, M2M_WIFI_CH_ALL); while (1) { // Goto STANDBY sleep mode, unless woken by timer or PTC interrupt. system_sleep(); // Start touch sensor measurement, if touch_time.time_to_measure_touch flag is set by timer. touch_sensors_measure(); if (measure_tick<INACTIVITY_DELAY) { measure_tick++; } if ((p_mutlcap_measure_data->measurement_done_touch == 1u)) { p_mutlcap_measure_data->measurement_done_touch = 0u; // Get touch sensor states button1_state = GET_MUTLCAP_SENSOR_STATE(0); button2_state = GET_MUTLCAP_SENSOR_STATE(1); rotor_state = GET_MUTLCAP_SENSOR_STATE(2); slider_state = GET_MUTLCAP_SENSOR_STATE(3); if (button1_state) { if(button_pressed!=1) { port_pin_set_output_level(LED_8_PIN, 0); button_pressed=1; form_modbus_packet(0x05,DALI_OFF ); tcp_client_socket = socket(AF_INET, SOCK_STREAM, 0); ret=connect(tcp_client_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); } } else { port_pin_set_output_level(LED_8_PIN, 1); if (button_pressed==1) { button_pressed=0; } } if (button2_state) { if(button_pressed!=2) { port_pin_set_output_level(LED_9_PIN, 0); button_pressed=2; form_modbus_packet(0x05,DALI_RECALL_MAX_LEVEL); tcp_client_socket = socket(AF_INET, SOCK_STREAM, 0); ret=connect(tcp_client_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); } } else { port_pin_set_output_level(LED_9_PIN, 1); if (button_pressed==2) { button_pressed=0; } } // Clear all slider controlled LEDs port_pin_set_output_level(LED_0_PIN, 1); port_pin_set_output_level(LED_1_PIN, 1); port_pin_set_output_level(LED_2_PIN, 1); port_pin_set_output_level(LED_3_PIN, 1); port_pin_set_output_level(LED_4_PIN, 1); port_pin_set_output_level(LED_5_PIN, 1); port_pin_set_output_level(LED_6_PIN, 1); port_pin_set_output_level(LED_7_PIN, 1); // If slider is activated if(slider_state) { // Parse slider position slider_position = GET_MUTLCAP_ROTOR_SLIDER_POSITION(1); // slider_position = slider_position >> 5u; printf("slider_position= %d\n",slider_position); if (measure_tick==INACTIVITY_DELAY) { button_pressed=4; form_modbus_packet(0x05,DALI_ON_AND_STEP_UP); tcp_client_socket = socket(AF_INET, SOCK_STREAM, 0); ret=connect(tcp_client_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); delay_ms(500); } else { if (button_pressed==4) { button_pressed=0; } if ((button_pressed!=3)&&(previous_slider_position!=slider_position)) { button_pressed=3; brightness=slider_position;//<<5u; if (brightness==255) { brightness=254; } printf("brightness= %d \n",brightness); form_modbus_packet(0x04,brightness); tcp_client_socket = socket(AF_INET, SOCK_STREAM, 0); ret=connect(tcp_client_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); previous_slider_position=slider_position; } else { if (button_pressed==3) { button_pressed=0; } } } measure_tick=0; switch(slider_position) { case 0: port_pin_set_output_level(LED_0_PIN, 0); break; case 1: port_pin_set_output_level(LED_0_PIN, 0); port_pin_set_output_level(LED_1_PIN, 0); break; case 2: port_pin_set_output_level(LED_0_PIN, 0); port_pin_set_output_level(LED_1_PIN, 0); port_pin_set_output_level(LED_2_PIN, 0); break; case 3: port_pin_set_output_level(LED_0_PIN, 0); port_pin_set_output_level(LED_1_PIN, 0); port_pin_set_output_level(LED_2_PIN, 0); port_pin_set_output_level(LED_3_PIN, 0); break; case 4: port_pin_set_output_level(LED_0_PIN, 0); port_pin_set_output_level(LED_1_PIN, 0); port_pin_set_output_level(LED_2_PIN, 0); port_pin_set_output_level(LED_3_PIN, 0); port_pin_set_output_level(LED_4_PIN, 0); break; case 5: port_pin_set_output_level(LED_0_PIN, 0); port_pin_set_output_level(LED_1_PIN, 0); port_pin_set_output_level(LED_2_PIN, 0); port_pin_set_output_level(LED_3_PIN, 0); port_pin_set_output_level(LED_4_PIN, 0); port_pin_set_output_level(LED_5_PIN, 0); break; case 6: port_pin_set_output_level(LED_0_PIN, 0); port_pin_set_output_level(LED_1_PIN, 0); port_pin_set_output_level(LED_2_PIN, 0); port_pin_set_output_level(LED_3_PIN, 0); port_pin_set_output_level(LED_4_PIN, 0); port_pin_set_output_level(LED_5_PIN, 0); port_pin_set_output_level(LED_6_PIN, 0); break; case 7: port_pin_set_output_level(LED_0_PIN, 0); port_pin_set_output_level(LED_1_PIN, 0); port_pin_set_output_level(LED_2_PIN, 0); port_pin_set_output_level(LED_3_PIN, 0); port_pin_set_output_level(LED_4_PIN, 0); port_pin_set_output_level(LED_5_PIN, 0); port_pin_set_output_level(LED_6_PIN, 0); port_pin_set_output_level(LED_7_PIN, 0); break; default: port_pin_set_output_level(LED_0_PIN, 1); port_pin_set_output_level(LED_1_PIN, 1); port_pin_set_output_level(LED_2_PIN, 1); port_pin_set_output_level(LED_3_PIN, 1); port_pin_set_output_level(LED_4_PIN, 1); port_pin_set_output_level(LED_5_PIN, 1); port_pin_set_output_level(LED_6_PIN, 1); port_pin_set_output_level(LED_7_PIN, 1); break; } } }//measurement done flag m2m_wifi_handle_events(NULL); if (wifi_connected == M2M_WIFI_CONNECTED) { // Open client socket. if (tcp_client_socket < 0) { if ((tcp_client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("main: failed to create TCP client socket error!\r\n"); continue; } // Connect server printf("socket_number new connection: %d\r\n", tcp_client_socket); ret=connect(tcp_client_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); printf("ret value: %d\r\n", ret); if (ret < 0) { close(tcp_client_socket); tcp_client_socket = -1; } } } }//while(1) }//main
      
      








All Articles