2015年2月16日月曜日

Galileo で Windows for IoT その2

 今回のガラクタは、前回に引き続き Windows for IoT with Galileo です。Windows for IoT の良いところは、やはり、Visual Studio で Windows (のコンソール)アプリとして、開発・デバッグが出来るところではないかと思います。ただ、Realtime OS や Arduino のようなOSなしマイコン直接操作 みたいのに比べるとリアルタイム性は無いので、そういった必要性があるところには使えません。逆に言うと、じゃあ、どんなところに使えるんだ?って話で、Raspberry Pi を使うようなネットワークやら、計算・画像処理なんかの重めのところをやらせるのがいいんじゃないでしょうか?まあ、自分の中では、その手の用途は Raspberry Pi + Arduino (Micro) のコンビがデフォルトになっているわけですが、今回は、Windows for IoT で遊ぶということで、Galileo で WinSock (Socket) 通信を試してみようと思います。
 基本的には、こちらにあるサンプルの流用となりますが、Galileo側で WinSock Server プログラムを動かして、Windows PC からWinSock Client プログラムで接続して、文字を送信、Galileo 側が受信文字によってAnalogRead()の値をClient側に返すというシンプルなものです。また、ついでに、前回のLCDシールドも使って、応答文字列をLCDにも表示しています。
 今回は GroveシールドとLCDシールドをスタックしています。Grove も DigitalWrite() や DigitalRead() などで使える簡単なものは動きますが、超音波距離センサを使おうと思ったところ pulseIn()関数が使えないようでした。


 PCのクライアントソフトで接続して、x とか y とか送信すると、AnalogRead() でジョイスティックの値を読み込んで、LCDに表示しつつ、クライアント側に応答送信します。



  Galileo側の WinSock Server のソースはこちらPC側のテスト用クライアントのソースはこちら にあります。
 一応、Galileo側のコードだけ以下に掲載。


#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include "stdafx.h"
#include "arduino.h"
#include "LiquidCrystal.h"
// Ws2_32.lib のリンクが必要。
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
// LCD pin <=> Arduino pin
int RS = 12;
int ENABLE = 11;
int DB4 = 5, DB5 = 4, DB6 = 3, DB7 = 2;
LiquidCrystal lcd = LiquidCrystal(RS, ENABLE, DB4, DB5, DB6, DB7);
int __cdecl main(void)
{
WSADATA wsaData;
int iResult;
SOCKET listenSocket = INVALID_SOCKET;
SOCKET clientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char rcvBuf[DEFAULT_BUFLEN];
int rcvBufLen = DEFAULT_BUFLEN;
// LCDの初期化。16文字×2行。
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Hello,WinIoT !");
// WinSockの初期化。WinSock Ver.2.2、MAKEWORD(メジャVer, マイナVer)。
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
// 変数の初期化。
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Serverのアドレスとポートの解決。
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed with error: %d\n", iResult);
// Winsockのリソース解放。
WSACleanup();
return 1;
}
// Server接続のためのSocketの生成。
listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (listenSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
// getaddrinfo()で確保したメモリの解放。
freeaddrinfo(result);
// Winsockのリソース解放。
WSACleanup();
return 1;
}
// TCP リスナソケットの設定。ソケットをアドレス・ポートに結びつける。
iResult = bind(listenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %d\n", WSAGetLastError());
// getaddrinfo()で確保したメモリの解放。
freeaddrinfo(result);
// ソケットを閉じる。
closesocket(listenSocket);
// Winsockのリソース解放。
WSACleanup();
return 1;
}
// getaddrinfo()で確保したメモリの解放。
freeaddrinfo(result);
// ソケットリスナを接続待ちにする。
iResult = listen(listenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR)
{
printf("listen failed with error: %d\n", WSAGetLastError());
// ソケットを閉じる。
closesocket(listenSocket);
// Winsockのリソース解放。
WSACleanup();
return 1;
}
// クライアントソケット受け入れ。
clientSocket = accept(listenSocket, NULL, NULL);
if (clientSocket == INVALID_SOCKET)
{
printf("accept failed with error: %d\n", WSAGetLastError());
// ソケットを閉じる。
closesocket(listenSocket);
// Winsockのリソース解放。
WSACleanup();
return 1;
}
// 不要なソケットを閉じる。
closesocket(listenSocket);
// 相手が接続を閉じるまで、受信する。
do
{
// ソケット受信。
iResult = recv(clientSocket, rcvBuf, rcvBufLen, 0);
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
// 受信文字によって、バッファをAnalogRead()値で書き換え。
switch (rcvBuf[0])
{
case 'x':
case 'X':
{
int val = analogRead(A0);
iResult = sprintf(rcvBuf, "X: %d\n", val);
break;
}
case 'y':
case 'Y':
{
int val = analogRead(A1);
iResult = sprintf(rcvBuf, "Y: %d\n", val);
break;
}
default:
break;
}
// 送信側に受信したバッファの内容を返す。
iSendResult = send(clientSocket, rcvBuf, iResult, 0);
if (iSendResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
// ソケットを閉じる。
closesocket(clientSocket);
// Winsockのリソース解放。
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
// LCDに表示。
if (iResult <= 16)
{
rcvBuf[iResult] = '\0';
}
else
{
rcvBuf[16] = '\0';
}
lcd.setCursor(0, 1);
lcd.print(rcvBuf);
}
else if (iResult == 0)
printf("Connection closeing...\n");
else
{
printf("recv failed with error: %d\n", WSAGetLastError());
// ソケットを閉じる。
closesocket(clientSocket);
// Winsockのリソース解放。
WSACleanup();
return 1;
}
} while (iResult > 0);
// ソケット送受信の無効化。
iResult = shutdown(clientSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed with error: %d\n", WSAGetLastError());
// ソケットを閉じる。
closesocket(clientSocket);
// Winsockのリソース解放。
WSACleanup();
return 1;
}
// ソケットを閉じる。
closesocket(clientSocket);
// Winsockのリソース解放。
WSACleanup();
return 0;
}
view raw gistfile1.cpp hosted with ❤ by GitHub

0 件のコメント:

コメントを投稿