Windows のコンソールアプリで RFCOMM を利用する

Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6819

では、Windows ストアアプリを使って Bluetooth の RFCOMM を利用したわけですが、これってストアアプリとか Windows Phone からしか出来ないのか?と思っていたのですが、コンソールからもできました。ということは、Windows フォームや WPF からもできます。

デスクトップからWinRTを参照させる

デスクトップアプリからWinRT APIを使用する – 酢ろぐ!
http://blog.ch3cooh.jp/entry/20121204/1354596483
デスクトップ アプリからのWinRT API利用 | ++C++; // 未確認飛行 C ブログ
https://ufcpp.wordpress.com/2012/09/18/%e3%83%87%e3%82%b9%e3%82%af%e3%83%88%e3%83%83%e3%83%97-%e3%82%a2%e3%83%97%e3%83%aa%e3%81%8b%e3%82%89%e3%81%aewinrt-api%e5%88%a9%e7%94%a8/

そうそう、デスクトップアプリから WinRT を参照させれば RfcommDeviceService クラスが使えるかもしれない。ということで上記を参考にして設定をします。

TargetPlatformVersion を 8.1 にして挿入します。8.0 だとデバイス関係がないので「8.1」で。

  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{9B7AD65D-3475-4D63-B5AC-6AB73477AC30}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>BluetoothConsole</RootNamespace>
    <AssemblyName>BluetoothConsole</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <TargetPlatformVersion>8.1</TargetPlatformVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>

Windows.winmd を追加します。

System.Runtime.WindowsRuntime.dll を参照設定します。
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.1\System.Runtime.WindowsRuntime.dll

Windows ストアアプリ版のコードを書き換えて、コンソールアプリで呼び出せるようにします。ストアアプリではマニフェストの追加が必要ですが、デスクトップアプリの場合は必要ありません。アクセス権が自由なので、これだと作りやすいですよね(配布はしづらいですが)。

class Program
{
	static void Main(string[] args)
	{
		new Program().mainAsync().Wait();
	}

	Guid serviceGuid = Guid.Parse("00001101-0000-1000-8000-00805f9b34fb");
	RfcommDeviceService rfcommService;
	StreamSocket socket;
	DataWriter writer;
	DataReader reader;

	async Task mainAsync()
	{
		/// 接続
		string selector = RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(serviceGuid));
		DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(selector);
		if (collection.Count > 0)
		{
			try
			{
				DeviceInformation info = collection.First();
				rfcommService = await RfcommDeviceService.FromIdAsync(info.Id);
				socket = new StreamSocket();
				await socket.ConnectAsync(rfcommService.ConnectionHostName, rfcommService.ConnectionServiceName);

				writer = new DataWriter(socket.OutputStream);
				reader = new DataReader(socket.InputStream);
				Console.WriteLine("{0} 接続しました", rfcommService.ConnectionHostName );
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
		}
		else
		{
			Console.WriteLine("デバイスが見つかりませんでした");
			return;
		}
		// 試しに最初のキーを送る
		SendCommand("start");
		while (true)
		{
			// コマンド待ち受けfs
			string text = Console.ReadLine();
			if (text == "quit" || text == "end") break;
			SendCommand(text);
		}
		/// 切断する
		writer.Dispose();
		reader.Dispose();
	}

	async void SendCommand(string text)
	{
		Console.WriteLine("W:" + text);
		// 8文字にして送る
		if (text.Length < 8)
		{
			text = text.PadRight(8, '*');
		}
		else
		{
			text = text.Substring(0, 8);
		}
		writer.WriteString(text);
		await writer.StoreAsync();
		// そのまま受信待ち
		var res = await reader.LoadAsync(8);
		var text2 = reader.ReadString(8);
		Console.WriteLine("R:" + text2 );
	}
}

お次は、iPhone から…と思っていたのですが、調べていくと iPhone からは RFCOMM が使えないことが判明。正確には MFi というのを Apple から取得して作成すれば使えるようになるそうなのですが、個人アプリレベルでは無理話。そうなると Bluetooth LE を使っての接続が必要になるのです。
Arudino に BLE のシールドも無くはないのですが結構高い。2,3台作るとなると結構な値段になるし、ちょっと手が出しにくい(まあ、1個だけは RedBearLab に注文して買うんですけど)。このあたりは、コントローラー自体が iPhone である必要もないので、RFCOMM をそのまま使うか、WiFi でさっくり作ってテストするかって感じですかね。ちょっと思案中。
Xamarin.iOS で BLE はやっておきたいので、これはまた別途。iPhone からノートPCのUSB付けた Bluetooth 4.0 で実験すればよいので。

カテゴリー: Arduino, WinRT | Windows のコンソールアプリで RFCOMM を利用する はコメントを受け付けていません

Android から Bluetooth+RFCOMM を利用してモーター制御をする

Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6819

の続きです。
ストアアプリで作ると、ノートPCでちまちま(Surfaceでもいいけど)やらないちけないので、スマートフォンから動かせるようにします。と言いますか、せっかく Xamarin.Android があるんだから、それで RFCOMM してしまおうという訳です。

最近、中古で購入した Galaxy S3 は、Android 4.1.2 までしか上がらないので BLE は使えないのですが、従来の Bluetooth は使えます。まあ、接続先が Bluetooth 2.0 でシリアル通信なのでこれでok。

内容的には、以下を参考にして作っています。

Connect to a Bluetooth Serial Device with Xamarin.Android
http://brianpeek.com/post/Connect-to-a-Bluetooth-Device-with-XamarinAndroid

Android アプリの画面はこんな感じ。

Android で RFCOMM を使う

Xamarin.Forms を使うと、何故か Android.Bluetooth 名前空間が参照できないので、ノーマルな Xamarin.Forms で作っています。
BluetoothAdapter.DefaultAdapter でデフォルトの Bluetooth を取ってきて、CreateRfcommSocketToServiceRecord メソッドで RFCOMM 用のソケットを作ります。データの送受信はこれに対して、OutputStream と InputStream を使えば ok です。

[Activity(Label = "AndroidBluetooth", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
	TextView text1;
	EditText edit1;
	protected override void OnCreate(Bundle bundle)
	{
		base.OnCreate(bundle);

		// Set our view from the "main" layout resource
		SetContentView(Resource.Layout.Main);

		// Get our button from the layout resource,
		// and attach an event to it
		Button button = FindViewById<Button>(Resource.Id.MyButton);
		button.Click += button_Click;
		Button btnSend = FindViewById<Button>(Resource.Id.button1);
		btnSend.Click += btnSend_Click;
		text1 = FindViewById<TextView>(Resource.Id.textView1);
		edit1 = FindViewById<EditText>(Resource.Id.editText1);
		Button btn2 = FindViewById<Button>(Resource.Id.button2);
		btn2.Click += btn2_Click;
		FindViewById<Button>(Resource.Id.button3).Click += clickMotorOn;
		FindViewById<Button>(Resource.Id.button4).Click += clickMotorOff;
	}

	BluetoothSocket _socket;
	/// <summary>
	/// 接続
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	async void button_Click(object sender, EventArgs e)
	{
		try
		{

			BluetoothAdapter adapter = BluetoothAdapter.DefaultAdapter;
			if (adapter == null)
				throw new Exception("No Bluetooth adapter found.");

			if (!adapter.IsEnabled)
				throw new Exception("Bluetooth adapter is not enabled.");

			BluetoothDevice device = (from bd in adapter.BondedDevices
										where bd.Name == "HC-05"
										select bd).FirstOrDefault();
			if (device == null)
				throw new Exception("Named device not found.");

			_socket = device.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805f9b34fb"));
			await _socket.ConnectAsync();
			text1.Text = "接続しました";
		}
		catch (Exception ex)
		{
			text1.Text = ex.Message;
		}
	}

	async void SendCommand(string text)
	{
		// 8文字にして送る
		if (text.Length < 8)
		{
			text = text.PadRight(8, '*');
		}
		else
		{
			text = text.Substring(0, 8);
		}
		var buffer = System.Text.Encoding.UTF8.GetBytes(text);
		// 送信
		await _socket.OutputStream.WriteAsync(buffer, 0, buffer.Length);
		// 受信待ち
		var buffer2 = new byte[8];
		for (int i = 0; i < buffer2.Length; i++)
		{
			int n = _socket.InputStream.ReadByte();
			buffer2[i] = (byte)n;
		}
		string str = System.Text.Encoding.UTF8.GetString(buffer2);
		text1.Text = str;
	}

	/// <summary>
	/// 送信
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	void btnSend_Click(object sender, EventArgs e)
	{
		string text = edit1.Text ;
		SendCommand(text);
	}
	void clickMotorOn(object sender, EventArgs e)
	{
		string text = edit1.Text;
		SendCommand("m1on");
	}
	void clickMotorOff(object sender, EventArgs e)
	{
		string text = edit1.Text;
		SendCommand("m1off");
	}
	/// <summary>
	/// 切断
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	void btn2_Click(object sender, EventArgs e)
	{
		_socket.Close();
		_socket = null;
		text1.Text = "切断しました";
	}
}

コマンド自体は、Arduino が受けやすいように8バイト固定にしています。
実験して分かったのですが、Arduino からは1バイトずつ送っているので、受信する Android で ReadAsync を使うと最初の1バイトだけ先に受信してしまいます。このあたりはバッファを先読みして8バイト溜まったら読み込めばいいのですが、面倒ので1バイトずつ読み込んでいます。

		// 受信待ち
		var buffer2 = new byte[8];
		for (int i = 0; i < buffer2.Length; i++)
		{
			int n = _socket.InputStream.ReadByte();
			buffer2[i] = (byte)n;
		}

あと、プロジェクトの Android Manifest を開いて BLUETOOTH にチェックを入れます。

20150217_05

 

これがうまくいくと、Android スマートフォンからモーター制御ができるようになります。

ちなみに、上の方に写っている白いボードは「Freaduino UNO Rev1.8」です。Arduino Uno にサーボ用のシールドを作るのが面倒で買ってしまいました。手元の meArm を制御している

Assembly | Adafruit 16-Channel Servo Driver with Arduino | Adafruit Learning System
https://learn.adafruit.com/16-channel-pwm-servo-driver/assembly

とは違うけどデジタルピンに1対1で対応しているので、Arudino IDE で Servo ライブラリがそのまま使えます。

カテゴリー: 開発, Android, Arduino, Xamarin | Android から Bluetooth+RFCOMM を利用してモーター制御をする はコメントを受け付けていません

Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う

本来ならば Bluetooth LE を使うところなのでしょうが、価格が高い(苦笑)なので安い方から手を入れていきます。

<b>連載</b>Bluetooth LE (5) Android 4.3 で Bluetooth LE 機器を使う (フェンリル | デベロッパーズブログ)
http://blog.fenrir-inc.com/jp/2013/10/bluetooth-le-android.html
Bluetoothでデバイスと通信するには | garicchi.com
http://garicchi.com/?p=17111

なところで、BLE を使っているのでいずれ追いつこうということで。手始めには、先に作ったモーターの駆動系を Bluetooth で制御していきます。同時に Raspberry Pi の Bluetooth シールドも買ったのですが、まあ、これは要らなかったかも。同じ HC-05 の変換モジュールだけで ok みたいです。

Bluetoothシリアル変換モジュール(マスタ/スレーブ) – Androciti Wiki
http://wiki.androciti.com/index.php?Bluetooth%A5%B7%A5%EA%A5%A2%A5%EB%CA%D1%B4%B9%A5%E2%A5%B8%A5%E5%A1%BC%A5%EB(%A5%DE%A5%B9%A5%BF%2F%A5%B9%A5%EC%A1%BC%A5%D6)

価格的には 1,500円ぐらいですね。スレーブ専用の HC-06 だと 1,000 円ちょっとなので複数使うときに良さそうです。
実は、BLE とそれ以前の Bluetooth の違いを知らなくて、去年 Xamarin のカンファレンスで SensorTag を見せてもらったときに「うーん、Bluetooth なのか」と思ってただけなんですよ。実は、グロサミで解説してもらった(英語だったけど)Rolling Spider も BLE を使っていて、それの SDK を使って Bluetooth 対応のコントローラーで動かした、ってのミソだったんですね…と今更思い直しました。SensorTag は試しに買ってみたので、到着したら試してみる予定です。あと、BLE 対応のシールドも。

シリアルポートでつなげる

とはいえ、Bluetooth に様々なプロファイルがあって、それを使えば様々なことができる、ってことは以前に Bluetooth を調べたときに分かってはいたのですが、その時には具体的な端末がなくて、オーディオ関連とかファイル転送をしてもなぁ、ってな感じでした。あまりハードウェアに詳しくなかったので、何かを制御するには WiFi ぐらいだろうと思っていたわけで、RealSense 絡みも WiFi で作っています。
が、とある人から、がりっちさんの RFCOMM 通信の記事を知って、ちょっと通信部分の制御を変えてみようかと思ったわけです。WiFi+RPi の組み合わせや、Bluetooth+RPi+PSコントローラーのみかと思っていたら、RFCOMM プロトコルでつなげれば、結構手軽に iPhone/Android から繋げられそうです。実は Windows からは Windows Windows ストアアプリから接続しないといけない(デスクトップアプリでもできるはずなんですけどね?)ので、あれこれとややこしいのですが、さっくりと繋がります。
COM ポートとして使えるので、そのまま適当なコマンドを作ってやり取りすれば自前のモーター制御/サーボ制御ぐらいはできそうです。

Bluetooth シリアル変換モジュール(HC-05)をArduinoにつなげる

HC-05 Arudino
RX — TX
TX — RX
GND — GND
VCC — 3.3V

につなげます。RX/TX が送受信でワンセットになっているのと電源用の VCC/GND を差すだけで十分です。これは Raspberry Pi の場合も同じなので、結構さっくりと認識するはずです。

ちなみに、Windows 8 から Bluetooth 機器につなげるときはペアリングが必須なんですが(Windows 10の場合は BLE に対応するので、ペアリングは必要ないらしい?)、Bluetooth 機器だけを認識させる場合は、電源の VCC/GND の間に 3.3V – 6V ぐらい流せば ok です。電波を弱くして Bluetooth 機器の近くに入ったよ、ってのは、これでで十分かもしれませんね(実際、BLE の使い方でそういうのはあると思う)。

Android 側のスケッチを作る

シリアルポートは1バイト単位で読み込むのですが、コマンドっぽく送受信したかったので8バイト単位で受信しています。このあたりはマインドストーム EV3 を制御するときも同じみたいですね。こっちもいずれやってみたいところです。

int ledPin=13;
int mPin  = 8; // モーター

void setup(){
  pinMode(ledPin,OUTPUT);
  pinMode(mPin,OUTPUT);
  Serial.begin(9600);
}
 
void loop(){
  int n = Serial.available();
  if ( n >= 8 ) {
    int ch[8];
    int i;
    // 8バイトずつ読み込む
    for ( i=0; i<8; i++) {
      ch&#91;i&#93; = Serial.read();
    }
    // コマンドを判別
    if ( ch&#91;0&#93; == 'm' ) {
      if ( ch&#91;1&#93; == '1' ) {
        if ( ch&#91;2&#93; == 'o' && ch&#91;3&#93; == 'n' ) {
          // pin8 on
          digitalWrite(mPin,HIGH);
        } else {
          // pin8 off
          digitalWrite(mPin,LOW);
        }
      }
    }
    // 通信時に光らせる
    digitalWrite(ledPin,HIGH);
    delay(300);
    digitalWrite(ledPin,LOW);
    // エコーを送信
    for ( i=0; i<8; i++) {
      Serial.write(ch&#91;i&#93;);
    }
  }
}
&#91;/code&#93;
<ul>
<li>m1on  でモータ-をON</li>
<li>m1off でモーターをOFF</li>
</ul>
<p>
な単純な仕組みです。最終的には、モーター制御とアームのサーボ制御も入れたいのと、対物センサーの受信もいれておきたいですね。ここまで来ると、素直に BLE にしたほうがいいような気もするのですが、まあ、HC-05 モジュールが安いので。
</p>
<p>
<h2>Windows ストアアプリから制御する</h2>
</p>
<p>
Windows 8 の制限から、ストアアプリから制御します。たぶん、Windows Phone からも同じ制御ができるはずです。
</p>
[code lang="csharp"]
public sealed partial class MainPage : Page
{
	public MainPage()
	{
		this.InitializeComponent();
	}
	// RFCOMM のサービスID
	Guid serviceGuid = Guid.Parse("00001101-0000-1000-8000-00805f9b34fb");
	RfcommDeviceService rfcommService;
	StreamSocket socket;
	DataWriter writer;
	DataReader reader;

	// 接続する
	private async void btn_findDevice_Click(object sender, RoutedEventArgs e)
	{
		string selector = RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(serviceGuid));
		DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(selector);
		if (collection.Count > 0)
		{
			DeviceInformation info = collection.First();
			rfcommService = await RfcommDeviceService.FromIdAsync(info.Id);

			socket = new StreamSocket();
			await socket.ConnectAsync(rfcommService.ConnectionHostName, rfcommService.ConnectionServiceName);
			writer = new DataWriter(socket.OutputStream);
			reader = new DataReader(socket.InputStream);
			textOut.Text = "接続しました";
		}
		else
		{
			MessageDialog dialog = new MessageDialog("デバイスが見つかりませんでした");
			await dialog.ShowAsync();
		}
	}
	// 切断する
	private void btn_close_Click(object sender, RoutedEventArgs e)
	{
		writer.Dispose();
		reader.Dispose();
	}

	// 送信する
	private async void btn_sendMessage_Click(object sender, RoutedEventArgs e)
	{
		// 8文字にして送る
		string text = textIn.Text;
		await SendCommand( text );
	}
	// コマンド送信
	async Task SendCommand(string text)
	{
		textIn.Text = text;
		// 8文字にして送る
		if (text.Length < 8)
		{
			text = text.PadRight(8, '*');
		}
		else
		{
			text = text.Substring(0, 8);
		}
		writer.WriteString(text);
		await writer.StoreAsync();
		// そのまま受信待ち
		var res = reader.LoadAsync(8);
		res.Completed = async delegate
		{
			await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
				string text2 = reader.ReadString(8);
				textOut.Text = text2;
			});
		};
	}

	private async void clickM1on(object sender, RoutedEventArgs e)
	{
		await SendCommand("m1on");
	}

	private async void clickM1off(object sender, RoutedEventArgs e)
	{
		await SendCommand("m1off");
	}
}

基本は、がりっちさんの記事 http://garicchi.com/?p=17111 と変わりません。デバイスを見つけて、最初のデバイスに自動的に接続します。最初の1回だけはストアアプリから接続許可を求めるダイアログが出ます。

あと、RFCOMM を使うために Package.appxmanifest に以下のように追加しておきます。

  <Capabilities>
    <Capability Name="internetClient" />
    <m2:DeviceCapability Name="bluetooth.rfcomm">
      <m2:Device Id="any">
        <m2:Function Type="serviceId:00001101-0000-1000-8000-00805f9b34fb" />
      </m2:Device>
    </m2:DeviceCapability>
  </Capabilities>

うまくできあがると、m1on/m1off のボタンを押すことでモーターが動いたり止まったりします。ここは LED で動かしてて確認してもよいですね。ブレッドボード上でモーターが動いても何も面白くない(娘談)なので、ええ、キャタピラを付けてコントローラーで制御するところまでやりますよ。

ちなみに BLE 機器を見つけるだけならばペアリングが不要(通信には必要?)なので、忘れ物タグとかについているんですね。なるほど。これ Windows 8.1 の場合はまだ見つけるだけでもペアリングが必要で、Windows 10 ではそれに対応するらしいのですが…適当な BLE 対応のスマートフォンを媒介すれば、Windows 8.1 でもできるかなと。まあ、半年後に Windows 10 が出るのでそれ待ちってのもあるし、手元のノートPCにWindows 10 TP 版を入れて確かめてみるってのもありですね。

カテゴリー: 開発, Arduino, WinRT | Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う はコメントを受け付けていません

Netduino を壊しながら学ぶ Arduino でモーター制御をする

いや、別に壊す気はなかったのですが、モーター制御の実験をしていて壊してしまいました T_T > Netduino 。グローバルサミットの後、年末に買っていくつかサンプルを作っていたのと、例の RealSense のコンテストで妖怪ウォッチの LED を光らせているのが Netduino plus 2 だったわけで、結構な値段で、ちょっとばかし落ち込んだのですよ。ええ、「Raspberry Pi は壊しても諦められる値段」だけど、Netduino plus 2 はちょっと高いんですよね。と言いますか、仕事で使おうと思ったら予備も含めて、最低2台は必要ですね。

さて、RasPi と Netduino, Arduino を同時にやっているのは、花札認識もそうなんですが、meArm を自走式にしたいからなのです。何がいいのかよくわからないので(最終的にはハイブリットな感じにはなりそうなのですが)いくつか同時に進めています。

で、LED は自由に光らせることができたので(妖怪ウォッチのLEDをリレー電飾っぽく光らせる方法もわかったし)、自走のためのモーター制御です。ラジコンっぽく動かしてみたい。LEGOマインドストームの EV3 と Raspberry Pi + PS3コントローラー の組み合わせでいけることが分かったので、この度はモーターを直接制御しようって話です。

手元にある「Aduino を始めよう」の 058 ページを見ながらモーターを動かそうとしていたのですが、これ Arduino じゃない外部電源を使う場合はどうするんでしょう?と思いつつ、Arduino でモータを動かす:息子と一緒に Makers:So-netブログ を参考にしつつやっていたわけですが、MOSFET がよくわからなくて詰まっておりました。Arudino のピンを使って制御する前の段階で、なんで、PIN で ON/OFF したら、モーターが動くのだろう?って疑問です。たぶん、実地でやってみればわかるだろうと思って、あれこれやってみた途中で netduino を壊してしまうというおまけがついていますが。

image

直ぐ忘れるので、写真を張っておきます。左から、ゲート、ドレイン、ソースです。

image

  • ゲートのほうに、Arduino のピン制御を差し込む(プラス極)
  • ドレインにモーターをつなぐ(プラス極)
  • ソースを GND(マイナス極)につなぐ

モーターと並列に繋いであるダイオードはサージ用なので、逆向きにしておけばok。

で、素直に Arudino に配線して、モーターのオンオフを調べればいいのですが、先の何故ってのが気になっていたので、ピン制御をする部分を電池で代用してみます。こんな感じに、ゲートのところに6Vの電池を置きます。

image

ここで、6V の線をつなぐと、モーターが回りだします。線を外してもモーターは回り続けます。モーターを止めるには、6V のプラス極の線を、GND に設置させて電圧を0Vにしないといけないんですね。ここがよく分からなかったところで、電流を流し続けて続けている間、モーターが回るのかと思ったら、一旦、6V を流しておけば MOSFET 内で接点したままになって、モーターは回り続けます。

で、ここで必要なのは、4V 以上とのことで電池2個分の3Vではスイッチは働きません。

と、ここまで書いて、モーターを回す を見ていたら、ゲートとソースの間に抵抗を挟むことで放電させることができるんですね。そうなると、いちいち電圧を0Vにするために、6Vのプラス極を動かす必要はありません。

image

こんな感じに大き目の抵抗を挟み込むと、6Vの線を抜いた後にモーターが止まるようになります。

ちなみに、Arduino から制御するときは抵抗を挟まなくてもモーターのON/OFFが働きます。

image

モーターの動作自体は、LED の Blick のサンプルをそのまま使ったので、1秒動いて1秒止まっての繰り返しだけです。これを Bluetooth から制御するのと、逆回転の仕組みを作るのが次のステップ。

カテゴリー: Arduino | Netduino を壊しながら学ぶ Arduino でモーター制御をする はコメントを受け付けていません

Windows 10 が動作する Raspberry Pi 2 Model B の考察

Raspberry Pi 2 Model B発売。4コア化&1GB RAMでWindows 10も対応、6倍高速 – Engadget Japanese
http://japanese.engadget.com/2015/02/02/raspberry-pi-2-model-b-4-and1gb-ram-windows-10-6/
マイクロソフト、Raspberry Pi 2 にWindows 10 を含む開発環境を無償提供 – Engadget Japanese
http://japanese.engadget.com/2015/02/02/raspberry-pi-2-windows-10/
Raspberry Pi 2 runs free Windows 10, costs $35 – CNET
http://www.cnet.com/uk/news/raspberry-pi-2-model-b-is-a-quad-core-upgrade-on-sale-today/

2個注文したので、ざっと備忘録的に書いておきます。ちょうど、先日 MVP Community Camp で 「Raspberry Pi で動かすロボットアーム(meArm)」を発表したばかりなので。

去年の夏ごろに、USBポートが4つある Raspberry Pi Model B+ が発表になって、どーしたものかなと思っていたのですが、ここに来て、RAspberry Pi 2 の発売です。値段的には数百円しか変わらないので上位バージョンとして買っておく訳ですが(手元にあるのが、初代の256MB の RasPi なので)、実は Windows 10 を動かすにはクリアされなければいけない(Microsoft がクリアする訳ですが、しかも6か月間のうちに)難関がいくつかあります。

ちなみに、以前のバージョンに Windows 10 は載るのか?というと載らないみたいですね。今回の RasPi 2 では SoC(System on a chip)を搭載したことで、Windows 10 なり Ubuntu なりが動くことができるとのこと。

CPU が ARM

Intel 系の CPU ならば、そのまま載せればいいのですが、RasPi 2 の CPU は ARMv7 です。つまりは、Surface RT と同じように ARM 系なわけです。Surface RT 2 が生産中止で、ARM と WinRT の組み合わせが下降線になっている(?)ときに、再び、ARM 系に合わせないといけないわけですね。Visual Studio 自体には ARM コンパイラが入っているので、それでコンパイルしてインストール。ただし、Surface RT では、ARM 実行ファイルはそのまま入れられなかったので、その制限は緩くしなければいけないわけです。とはいえ、実行許可のガードだけかかっているので、それを外すだけでいけるのか、それとも、Windows の ARM 版がそのまま移行できるかどうかは不明なところです。

GPIO を直接アクセスする

Windows 8 あたりだったか、OS から GPIO の直接アクセスがかなり制限されています。WinRTからは絶望的(?)なので、デスクトップアプリからアクセスすることになるのですが、この手のアクセスはカーネルか特権で動かさないとだめですよね。実際、Linux からは sudo 等で特権で動かないとポートアクセスができません。ここには特定のドライバーを入れるのか、デスクトップアプリ自体を特権(管理者権限)で動かすのか、ってところです。まあ、RasPi の Windows 10 を入れてマルチユーザーで動かすことは少ないでしょうから、管理者権限のユーザーを作っておけばいいだけかもしれませんが。RasPi の場合は、USB アクセスじゃなくて、GPIO アクセスができて I2O コントローラーで制御できるってのが有利な点なので、ここは外せないところです。

.NET Compact Framework になる?

ここは予想なのですが、SD メモリ内で動く Windows Embedded 的な機能とポートアクセスな機能が必要なわけで、.NET Compact Framework が搭載される感じになるのかなと思っています。

MVP Global Summit 2014 感想戦 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6603

の中でも書きましたが、

Microsoft’s fitness band: What kinds of software and services are inside? | ZDNet
http://www.zdnet.com/article/microsofts-fitness-band-what-kinds-of-software-and-services-are-inside/

にある、Windows 10 “Athens” のところには、Windows Embedded Compact があって、ここには .NET Compact Framework が載る予定なんですよね。勿論、RasPi 2 に Windows Mobile のところを割り当てるパターンも考えられるのですが、Mobile のほうだとセンサーの制御とかがしづらくと、そうなるとせっかく RasPi 2 に乗っているモジュールが全滅ってことになりかねない。ここは、ぜひ GPIO を手軽に扱える環境を提供してほしいところです。まあ、.NET CF ってことになると、それはそれで制限が多いわけですが、デスクトップアプリを動かすことは少ないだろうし(HDMIはついているけど、それを使ってタッチパネル/ストアアプリを動かすことは少ないかなと)。まあ、ディスプレイが無い=無償提供ってことで、Windows Mobile のほうを提供するパターンもあるのですが、その場合はセンサーの類を頑張って貰わないと。

とはいえ、インテルのミニPCよりも断然安いし、USB給電なので電気維持費もかからないので、常時接続のモデルを作るのは都合がいいボードですよね。私の場合は、

  • ディスプレイ無し(デスクトップなし・ストアアプリなし)
  • Telnet 系の接続が必須
  • GPIO, I2C, カメラモジュールの接続が可能
  • BrickPi のような拡張ボードの接続が可能
  • USB ドングルの WiFi あるいは Bluetooth 接続

が必須なわけです。Linux で Bluetooth(ゲームコントローラー)接続がちょっと面倒なので、そのあたり Windows 10 を載せると改善されたら手軽にできてよいかなと。

カテゴリー: RaspberryPi | Windows 10 が動作する Raspberry Pi 2 Model B の考察 はコメントを受け付けていません

Xamarin Android Player をきれいに削除する方法

Xamarin Android Player でデバイスを削除しようとしても、なかなか削除できないことがあります。普通は「Delete」で削除して、再ダウンロードすればいいんですが、間違って Oracle VM VirtualBox で仮想ドライブを削除すると、かなり嵌ります。

image

なぜか、Xamarin Android Player をアンインストールしても壊れた Installed Devices が復活するし、これはどうしたものだろう…と思っていたのですが、対処方法がありました。

Cannot delete Xamarin Android Player Virtual Devices – Xamarin Forums
http://forums.xamarin.com/discussion/30620/cannot-delete-xamarin-android-player-virtual-devices

上記では、installeddevices.json を修正する方法も書かれていますが、きれいさっぱりと設定を消すだけならば、C:ProgramDataXamarinAndroidPlayer フォルダを消してしまえば ok です。そして、再び Xamarin Android Player をインストールすれば、最初の状態(デバイスがインストールされていない状態)になります。

image

これで暫くぶりに Xamarin Android Player が正常に動くようになります。

こんな風に、Xamarin.Android を HTTPサーバーにしてコマンド受付と画像転送がしたかったんですよね。System.Net.HttpListener を使うのですが、Android Emulator のほうは IP アクセスができない(10.0.2.15 などが通らない)ので、実機を使うか、Xamarin Android Player を使えるか?って感じだったのです。こっちは、10.71.34.102 が割り振られていて、ホストしている PC からアクセスができます。

image

ちなみに、こんな風に Android TV アプリとして完成させる予定です。

image

image

カテゴリー: Xamarin | Xamarin Android Player をきれいに削除する方法 はコメントを受け付けていません

Rolling Spider を買って SDK で遊ぼう(出帆準備編)

娘のサンタクロースに Rolling Spider を貰ったので、ちょっと遊び&調べてみました。

http://www.parrot.com/static/images/theme/catalog/rolling_spider/details.jpg

Jumping Sumo のほうは、夏あたりに見たのを覚えていたのですが、こっちのほうもワンセットで発表されていたのです。実は、先日の MS グロサミで MVP の方がコントローラを使ってデモをやっていて、中身で何が動いているのか知りたかったのです。その後に行った MS ストアに売っていて Surface でデモをやっていたので、.NET Micro なのかと思っていたのですが、組み込み Linux だそうです。操作は、Bluetooth v4 が装備されている iOS/Android/Windows Phone があれば ok です。FreeFlight 3 のストアアプリ版もあるので、初代 Surface RT を使って動かすこともできました。ただし、Surface の場合は、Bluetooth のペアリングなかなかつながらなくて、手元の iPod のほうがスムースにつながります。

Parrot、ミニドローンRolling SpiderとJumping Sumoを国内向けに解説。SDKも公開 – Engadget Japanese
http://japanese.engadget.com/2014/07/10/parrot-rolling-spider-jumping-sumo/
パロット社のミニドローンRolling Spiderは、地上から天井まで自在に駆け巡ります!
http://www.parrot.com/jp/products/rolling-spider/
Windows ストア の Windows 用 FreeFlight 3 アプリ
http://apps.microsoft.com/windows/ja-jp/app/freeflight-3/3c827d26-a7fa-430e-9a1f-bb33670d0551

Rooling Spider 自体は、二年前に発売された AR Drone のおもちゃ版?みたいなものです。AR Drone 自体は 4万円ほどするのですが、Rooling Spider は1万円ちょっとです(私の場合、ちょっと安い時期を見つけて1万円弱で買えました…いや、サンタ的に)。たぶん、カメラが付いてないだけで、中身は一緒のものではないかなと。カメラを積む分だけ AR Drone は非常に大きいのですが、Rooling Spider は部屋で飛ばせるぐらい小さなものです。部屋用のミニヘリコプターと同じですね。

ただし、普通のラジコンと異なるのが Bluetooth で操作できる(操作しなくてはいけない)ところです。Bluetooth だと、タイムラグが必ず出る(0.1~0.2秒ぐらい遅れる)ので操作的にはどうなんだろう?と思っていたのですが、大丈夫みたいです。Parrot 社は、オーディオ機器を作っているメーカーでそのあたりのノウハウが入っているようです。

中身は組み込み Linux

Bluetooth 制御やモーター制御等をしているのは組み込み Linux です。オープンソース化されているので、機器を作れる…んですよね。手元にある CloudFlash も組み込み Linux で busybox なんかが使われているのでわかります。

OpenSource-RollingSpider – 概要 – Parrot ASTEROID Developers Zone
https://devzone.parrot.com/projects/show/oss-rolling-spider

ファームウェアアップデートは、FreeFlight アプリからか、PC から USB ケーブル経由で行えます。私の買った時点で、既にファームウェアが古くなっていたので、最初に行うのがファームウェアアップデートでした。出荷時点とアプリの日にちのずれがあるので、これは仕方がないところです…が素人にはちょっと辛いかも。アプリの Bluetooth 経由から行うと非常に時間がかかります。アップデート開始自体はアプリに組み込まれているので、難なく進むのですが、なかなか終わらないかつ最後になって失敗するという状態で。USB ケーブル経由のほうが良いかもしれません。

Rolling Spider の組み込み Linux 自体は手がでません(と思う)。SD カードとかついてないし。しかし、Bluetooth 接続する操作アプリのほうに手を出すことができます。というか、そういう仕様になっている。

アプリは ARDroneSDK3 を使う

発表では SDK を使えるようにする、となっていたもののリンクがありませんでした。Parrot 社からのリンクも見当たらないので、探すのが苦労したのですが、github 上にありました。

ARDroneSDK3
https://github.com/ARDroneSDK3
ARDroneSDK3/Samples
https://github.com/ARDroneSDK3/Samples

「MiniDroneDeviceController is used to control the RollingSpider」とあるので、Rooling Spider も動かせそうです。中身はざっとしかみていませんが、C# 版はありません。が、ストアアプリ版があるので、動作は問題ないと思われます。

iOS 版で動かしてみて、Xamarin でくるむ?

iOS 版の MiniDroneDeviceController を Xamarin でラップしてやれば、普通に C# から使えるようになるかな、と。おそらく Bluetooth 接続するための ARNetworkAL とコマンド送受信するための ARCommands が肝になるかな。ARNetworkAL 自体は、WiFi にも対応しているようです。

[AR.Drone]Droneをc#で飛ばしてみようじゃないか (1) » はにらぼ☆てっく
https://www.honeycomb-lab.co.jp/blog/tech/?p=282

な感じで、AR Drone を C# で操作している方も。

カテゴリー: 開発 | Rolling Spider を買って SDK で遊ぼう(出帆準備編) はコメントを受け付けていません

Xamarin と AllJoyn の将来を考える

Xamarin Advent Calendar 2014 の 22日目の記事です。

Xamarin Advent Calendar 2014 – Qiita
http://qiita.com/advent-calendar/2014/xamarin

もともとの予定は、Xamarin.iOS/Android に AllJoyn を乗せてみて通信させてみようかな、と思っていたのですが、ちょっと時間が取れなかったので入り口の部分だけ紹介します。私自身 AllJoyn に詳しいわけではないけれど、今後は詳しくありたいな(つーか、やらんとあかんやろう自分)ってことで書き進めます。

そもそも AllJoyn とは何か?

端的に言えば、デバイス同士を相互通信させる規格です。デバイスとは行っても、ゲームデバイスからデスクトップPCや、ルータや家電なども対象になります。ともかく、ネットワークにつながっているものが対象ですね。

Open Source IoT to advance the Internet of Everything – AllSeen Alliance
https://allseenalliance.org/

クアルコムが主導になって、各種ソースはオープンソースで配布されています。実は AllJoyn モジュール自体は Windows 7 の頃から対応になっていて、夏ごろに Microsoft が AllSeen Alliance に加入しています。

MS、IoTを推進するAllSeen Allianceに加入–クアルコムが主導 – CNET Japan
http://japan.cnet.com/news/business/35050321/

メンバーには、Panasonic、Sharp、Sony、他にも Cisco なども入っているので、ネットワーク機器を問わずということがわかります。

ネットワーク機器(電力線通信や赤外線通信、短距離通信も含む)で機器同士がデータのやり取りをするときに何の規格に則ってデータ通信をするか、ってのが問題です。古い?ところでいえば、ルータなどの機器を MIB で動作チェックしたり、簡易的な WEB サーバーを乗せて本体のデバイスを操作したりします。他にもコンソール接続してコマンド送信ってのもあれば、独自のスイッチングってのもあります。これらは、機器のメモリの問題もあり、内部で動くコード(大抵の場合は C、最近は組み込み Linux でスクリプトを動かすってのもある)の制限もあり、ばらばらでも仕方がないところなのですが、今後、LAN だけでなく、WiFi、Bee なども含めると通信形式自体も多様になれば、機器自体も多様になる(携帯ゲーム端末、冷蔵庫、オーディオ機器、インターネット対応テレビなども含めて)わけで、何かが何かを制御するときに、どう対応すればよいか?ってのは大変なのは目に見えてきています。

そこで、それらのプロトコルを XML 形式といくつかのコマンド(GET/SET)に絞って使うように統一してしまおうというのが AllJoyn の目的です。勿論、通信形式だけでなくて、Push/Pull を実現するためにネットワーク的に Hub があったりする訳ですが、そのあたりは多機能化≒肥大化とシンプルさ≒単機能で貧弱、とのせめぎあいです。ある意味で、Raspberry Pi でよく使われる webiopi に似ています。AllJoyn のほうはデータ自体が XML で流れるのでおそらく HTTP プロトコルが使われるのでしょうが、個々の機器に Web api を作ってサービスを定義するよりは、ある程度コマンドが決めてあって内部データの形式(必須データと推奨データなど)が決まっているほうが、今後の拡張がしやすいでしょう(実際、かつての MIB はそんな形で拡張されてきています)。

AllJoyn はオープンソースである

各種の機器に広くインストールされないといけないので、オープンソースになっています。対応する OS も Android, iOS, Windows そして当然 Lunux もあります。そもそも、ソースの管理自体は、前年ごろから Linux foundation に移管されて、オープンソースとしての権利関係の地盤固めをしているようです(おそらく、クアルコムも含めて将来的に特定の企業が権利を主張しないように、という縛りだと思います)。

Download – AllSeen Alliance
https://allseenalliance.org/developers/download

バージョンが ver14 になっていますが、すごく完成されている訳ではなくて、Firefox のようがんがんバージョンを上げているだけでしょう。

image

ソースをダウンロードして展開すると、java や javascript のコードもあります。ちなみに、WinRT からは C モジュールを使うようになるそうです。Core のコードは、OS 自体に組み込まれるそうで、Window 10 からは AllJoyn のモジュールが入ることが決まっています。

ちなみに Xamarin は AllJoyn に対応していないのですが、Android/iOS のモジュールがあるので、それを使えば ok とのことです。

Does AllJoyn work with Xamarin? – Allseen Q&A Forum
https://ask.allseenalliance.org/question/677/does-alljoyn-work-with-xamarin/

AllJoyn で何ができるのか?

具体的に何ができるのか?ってのは、下記の showcase から見ていくとわかりますが、今よく使われているのは、ゲームアプリの相互通信や、スマートフォンからテレビやオーディオ機器を操作するアプリです。

Showcase of Products using AllJoyn – AllSeen Alliance
https://allseenalliance.org/showcase

スマートフォンからテレビを操作する、という方法自体は決して新しいものではありません。赤外線通信をエミュレートしても良いし、適当なリモコンアプリをテレビとスマートフォンの相互に入れれば操作ができるようになるでしょう。ただし、それらのアプリは専用のアプリになります。もちろん、これらの通信をオープンで公開すればいいのでしょうが、それを呼び出すプロトコルはいちいち異なる可能性が高くなります。それは、公開されている WEB サービスのように独自な形式になるでしょう。

そこで、相互に接続する機器を一旦切り離します。テレビ側のアプリは受信アプリとして独立して、スマートフォンのアプリは操作するアプリとして独立させます。その間のプロトコルは、ごく単純な XML 形式で流して、それぞれで解釈をします。実は、この XML 形式なり公開されたプロトコルなりが一般に認知されれば、AllJoyn である必要はありません。と同時に、この通信するプロトコルが AllJoyn が定義するプロトコルというだけです。End-to-End だけ見れば、それぞれに公開された XML 形式のフォーマットは、同時に切り替えが可能というわけで、テレビの受信データ形式が同じであれば、スマートフォンのアプリは何であっても構いません。新しく作ることも可能です。同時に、スマートフォンアプリから送るデータ形式さえあわせておけば、テレビを新調することも可能です。

同じことは、相互通信のゲームアプリにも言えて、基本的なデータ形式だけ同じであれば、別なアプリで拡張することも可能です。ピアツーピアの接続自体は、AllJoyn のネットワークが賄ってくれる(ハズ)なので、そのあたりの手間も省けます…と、どこまでできるか分かりませんが(データ量的に、バイナリ通信を併用しないと無理、っていうパターンもあるでしょうし)、いくつかそういう試みがされています。実際、先のサンプルコードに Unity が入っているので、そのあたりも範疇にはいっています。

で、Xamarin と AllJoyn はどうなのか?

現在のところ、Xamarin.iOS/Android からネイティブの AllJoyn ライブラリを使う方法は用意されていませんが、iOS/Android モジュール自体があるので、そのうち使えるようになるでしょう(どちらが対応するかわかりませんが、オープンソースなのだから自分でバインドしてもよいし)。そこで、使えることを前提にして考えると、Xamarin の使いどころとしては、

  • スマートフォン/タブレットの相互通信に使う
  • スマートフォンから、AllJoyn 対応の機器を操作するために使う

の2種類ですね。スマートフォン同士は、ゲームアプリとかチャットアプリを作って試すことができるでしょう(ハブは必要なのかな?)。Azure の Mobile Service を使う方法もあるけど、まあ、お試しとして。もちろん、普通の PC からも操作できるはずです。

別の機器を操作するものとして、AllJoyn 対応の機器を用意する…ことはできないので(販売されているものはあるのかな?)、Raspberry Pi を使うと良いかも、と思っています。C 言語ベースなので、Arduiono か netduiono で動く感じもするんですが、 Using Arduino+Alljoyn to control blinds – YouTube こんなのもあるし。ひとまず、Raspberry Pi に AllJoyn を入れて meArm を操作させたいところです。手元で作っている meArm ライブラリの .NET 版は、 REST で動かしているのですが、これを AllJoyn に対応させればいいですよね。このあたり、スマートフォン/タブレットと、IoT な機器とをつなげるのに、Xamarin+AllJoyn は結構有力かなと思ってます。

カテゴリー: AllJoyn, Xamarin | Xamarin と AllJoyn の将来を考える はコメントを受け付けていません

Let’s call Fortran DLL from F# language.

This text is 14th article in F# Advent Calendar 2014 in Japanese.

The original article’s the Japanese, but since there was a request, I am rewriting in English. So this year is also in English version, and users to access the F# Advent of English version and traced from the following.

F# Advent Calendar 2014 – connpass
http://connpass.com/event/9758/
F# Advent Calendar in English 2014 | Sergey Tihon’s Blog
http://sergeytihon.wordpress.com/2014/11/24/f-advent-calendar-in-english-2014/

Well, last year it wrote of that “before the F# and Fortran story … of” What it is sadly the setback was me…, this time agein !!! We succeeded in calling a Fortran from F#, who deals and technical information for you, but the time being, because the head is harf-joke article capital F connection :P

Make DLL by Fortarn

This DLL is made by Intel Visual Fortran 2013.

Intel Fortan can make DLL on Windows. Export Function is defined “!DEC$ ATTRIBUTES DLLEXPORT::<EXPORT-FUNCTION>”. We have a fortran fo GNU, but without that it was made only static libraries more of over there, I do not know well. However, it is possible to to create a *.so file. If you are run on linux use as it is from the C language, you’ll probably make in a manner similar from F#.

! This function has two number parameters.
integer function add1( a, b )
    !DEC$ ATTRIBUTES DLLEXPORT::ADD1
    integer, intent(in) :: a, b
    integer :: total

    total = a + b
    add1  = total
end function add1

! This function has a One-dimensional array parameter.
integer function sum1( v, count )
    !DEC$ ATTRIBUTES DLLEXPORT::SUM1
    integer, intent(in) :: v(10)
    integer, intent(in) :: count
    integer :: i, total

    total = 0
    do i=1,count
        print *, 'in sum1: ', i, v(i)
        total = total + v(i)
    end do
    sum1 = total
    end function sum1

! This function has a Two-dimensional array parameter.
integer function sum2( v, cnti, cntj )
    !DEC$ ATTRIBUTES DLLEXPORT::SUM2
    integer :: v(3,4)
    integer :: cnti, cntj
    integer :: i,j
    integer :: total

    total = 0
    do j=1,cntj
        do i=1,cnti
            print *,i,j,v(i,j)
            total = total + v(i,j)
        end do
    end do
    sum2 = total
end function sum2

Fortran of contents is too cheap, but I have tried an array numeric (int type). To after practice, We should try double, the per float.

Try to call from C++ Language

Let’s call from C++ in order to confirm the operation. The DLL function that is published from Fortran, and I call using the dllimport, but I just want to note is where we pass the value is in the pointer. because via global variables rather than via this Fortran function of passing stack. In the case of C language and pass laden with value on the stack (C# same when passing from a .NET language, etc.), when it passed to Fortran, that do not attention to this, it’s a strange feeling. Well, when you’re doing just Fortran, and so convenient to be very well done to be taken into account (like pass as it is a huge array).

#include "stdafx.h"
#include <iostream>

#define DllImport __declspec( dllimport )

extern "C" {
	DllImport int ADD1(const int *, const int *);
	DllImport int SUM1( int(*)[] , const int *);
	DllImport int SUM2(int(*)[4][3], const int *, const int *);
}

int _tmain(int argc, _TCHAR* argv [])
{
	int x = 10;
	int y = 20;
	int ans = ADD1(&x, &y);
	std::cout << "ans " << ans << std::endl;

	int  v[] = { 1, 2, 3, 4, 5 };
	int cnt = 5;
	int ans2 = SUM1((int(*)[])&v, &cnt);
	std::cout << "ans2 " << ans2 << std::endl;

	int v2[][3] = {
		{1,2,3},
		{11,22,33},
		{10,20,30},
		{100,200,300}
	};
	int cnti = 3;
	int cntj = 4;
	int ans3 = SUM2( &v2, &cnti, &cntj);
	std::cout << "ans3 " << ans3 << std::endl;

	return 0;
}

If we run this code, you will like that.

Try to Call from C# Language

Let’s rewrite in C#. And to use the DllImport is we ware found, but it does not do not pass a pointer int type, we can use the ‘ref’ keyword. Call form of the function, we need to be defined explicitly “CallingConvention = CallingConvention.Cdecl”.

class Program
{
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int SUM1([In] int[] v, [In] ref int count);
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int SUM2([In] int[,] v, [In] ref int cnti, [In] ref int cntj);
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int ADD1([In] ref int a, [In] ref int b);

	static void Main(string[] args)
	{
		int a = 10;
		int b = 20;
		int ans = ADD1(ref a, ref b);
		Console.WriteLine("ans {0}", ans);

		int[] v = { 1, 2, 3, 4, 5 };
		int cnt = v.Length;
		int ans2 = SUM1(v, ref cnt);
		Console.WriteLine("ans2 {0}", ans2);
		/*
		int[][] v2 = {
							new int[]{1,2,3,4},
							new int[]{11,22,33,44},
							new int[]{10,20,30,40},
						};
		*/
		int[,] v2 = {
						{1,2,3},
						{11,22,33},
						{10,20,30},
						{100,200,300},
					};
		int cnti = 3;
		int cntj = 4;
		int ans3 = SUM2(v2, ref cnti, ref cntj);
		Console.WriteLine("ans3 {0}", ans3);
	}

When you pass a two-dimensional array, int[][] in rather than int[,] you can use the C++ and because the int value the same as in the contiguous memory and Fortran is to be placed. When we call the ADD1 function is cumbersome put the ref to, but you can call this correctly the DLL of Fortran.

Try to call from F# !!!

Let’s rewrite more F#. This pointer which is export from dll is int& we declare as.

open System
open System.Runtime.InteropServices

type ARY2D = int[,]

[<AutoOpen>]
module FDLL =
  [<DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)>]
  extern int ADD1(int& a, int& b)
  [<DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)>]
  extern int SUM1(int[] v, int& count )
  // cannot use int[,], so we defined 'ARY2D' alias class.
  [<DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)>]
  // extern int SUM2(int[,] v, int& cnti, int& cnt2 )
  extern int SUM2(ARY2D v, int& cnti, int& cnt2 )

let mutable a = 10
let mutable b = 20
let ans = ADD1( &a , &b )

Console.WriteLine( "ans {0}", ans )

let mutable v = [|1;2;3;4;5|]
let mutable cnt = v.Length
let ans2 = SUM1( v, &cnt )

Console.WriteLine( "ans2 {0}", ans2 )

// two-dimensional array is made by Array2D module.
let vv = [|
    [|1;2;3|];
    [|11;22;33|];
    [|10;20;30|];
    [|100;200;300|];
  |]
let v2 = Array2D.init 4 3 ( fun i j -> vv.[i].[j])

let mutable cnti = 3
let mutable cntj = 4
let ans3 = SUM2( v2, &cnti, &cntj )

Console.WriteLine( "ans3 {0}", ans3 )

C# is not enough … write simpler compared with F#, I do not change much. Than that, it’s worrisome is is where you must use let ‘mutable’ is to want to pass by const. This is a limitation of Fortran call, in order to pass a pointer value, the variable of a even if it is not changed content is not pass and do not ‘mutable’. Here is where I want to twist. Though it pains of immutable values, it is a place me.

C# 2-dimensional array in int [,] since the was an unclear writing is how I in F # … but, how was I understand. With Array2D int [,] you can make a considerable thing. This, what another twist necessary int when you extern [,] it can not be the type specified in, we will create the alias. Here, extern int SUM2 by creating a type alias that ARY2D and is doing. In this way, you will be passed as the same as a two-dimensional array with C++.

Oh, Order of two-dimensional array will not unlike those of C++, but this is that the charm ;)

At the end

That is why, one New Year’s Eve of projects? As, was able story article dealing with the Fortran from F#. This, or the existing Fortran library can make an app that was made from F#, Who’s the obtained technical information but, Well, it is possible to that wanted to do. Everyone, a good Christmas !!!

カテゴリー: 開発 | Let’s call Fortran DLL from F# language. はコメントを受け付けていません

XAML は Microsoft だけのモノじゃないので、動的にロードできるよという話

XAML Advent Calendar 2014 – Qiita
http://qiita.com/advent-calendar/2014/xaml

XAML アドベントカレンダーの 18 日目の記事です。サーバーから動的に XAML をロードして表示する、というネタを考えていたのですが、と、その前に XAML って何?ってのを書き残しておきます。ちょっと前に Xamarin カンファレンスで Xamarin.formsとカスタムコントロールの話 ってのを話しました。Xamarin.Forms が扱うものが XAML ならば、そもそも XAML とは何か?ってところを突き止めてみます。実は、SPEC があって、MS-XAML(PDF) からダウンロードができます。そうです。XAML の仕様って公開されている情報なのです。なので C# とか ECMAScript のように誰でも実装できる仕様なんですね。誰でも作れるということは、XAML をサポートしているのは WPF や WinStore だけでなく、Xamarin.Forms でもよいし、Linux 上の mono でもよいわけです。名前空間としては System.Xaml が割り当てられていますが、内実は諸々なアセンブリが作られています。WPF が System.Xaml を使っているように WinStore が System.Xaml を使えばよかったのでしょうが、WinRT の関係か使っていません(使えないのかもしれません)。そのあたりは Sliverlight も使っていないので、MS-XAML として仕様は公開され統一されているものの、実装はそれぞれにあるという変な状態になっています…が、「仕様」が決まっているから、その「仕様」にあわせて実装していけば、他のプラットフォーム(あるいはフレームワーク)でも似た感じで使える、という「保証」があります。

で、具体的にどういう点で XAML が XML よりも強化されているかというと(見た目は XML なのだから、XDocument だけで扱うことも可能です)、先の MS-XAML のスペックを見ていくと、

  • x:Class で特定のクラスと結びつける
  • x:Name でクラス内のフィールドと結びつける
  • 名前=”{Binding プロパティ名}” で、指定したプロパティに結び付ける
  • Grid.Row のようなドット付きのタグ名が特別扱いになっている

が規定されていることがわかります。XAML と名乗っている場合は、この仕様が実装されているわけで、逆に XAML を名乗るならば、この仕様を実装しなければいけません。また、XAML を利用する側からみれば、プラットフォームに依存せずに上記の仕組みが利用できるという訳です。つまり、WPF の XAML であっても WinStore の XAML であっても、Silverlight の XAML であっても、Xamarin.Forms の XAML であっても、上記の書き方(クラス、フィールド、プロパティへのバインド)は同じになるということです。これは、特定のクラスへのバインドが XAML 内に書かれているので、適当なアセンブリがロードされれば良いということです。つまり、テキスト形式としての XAML ファイルをそれぞれのプラットフォーム(Windows, iOS, Android, Linux の OS に限らず、あるいは、Java や Objective-C の言語を問わず)に持って行って、適当なアセンブリ(あるいはライブラリ)をロードしてやって、アセンブリ内にあるクラスやプロパティに結び付ける(普通はリフレクションを使う)ことができますよ、って話なのです。

まあ、実際のところは、XAML をデータとして扱っているのは Windows Workflow Foundation ぐらいしかなくて、そのあたりの広がりに関しては失敗しているように見えますが。

更に言えば、名前空間として System.Xaml を用意して、この中に XamlXmlReader クラスがあるのだから、WPF とか WinStore とか Xamarin.Forms とか、このクラスを使って実装すればよかったと思われるのですが、皆ばらばらの実装になっています。おそらく、PCL やら WinRT やらの制約があって、それぞれで XAML をロードする実装が組み込まれたのだと思うのですが…ちょっと SPEC があるのに混乱させ過ぎな感じが。

ちなみに Open Source になった .NET Core には System.Xaml が含まれていません。mono には System.Xaml が入っているので、これをベースにして Linux への拡張をしてもよいかもしれません。

そんなわけで、動的に XAML をロードする方法は

 var url = "http://moonmile.net/up/samplepage.xaml"; 
 var cl = new HttpClient(); 
 var xaml = await cl.GetStringAsync(new Uri(url)); 
 var doc = XamlReader.Load(xaml) as Grid; 
 this.Content = doc; 

な風に簡単に書けます。これは HttpClient でサーバーから XAML データを取ってきている例ですが、ローカルリソースに XAML ファイルを置いてロードさせることも可能です。ただし、XamlReader.Load は、x:Name が使えなかったり、クラスを探索するのが自前のアセンブリのみだったりするので、ちょっと使い勝手が悪いです。逆に、XamlXmlReader を使えばいいんじゃないかと思ったりもするのですが、実は WinRT のほうには System.Xaml がありません。このあたり、完全に View として切り替え可能な XAML と、バインディング先としてのアセンブリ(オブジェクト)は、もう少し煮詰めて考えてもいい気がしています。ちなみに、少々頓挫中の XFormsPreviewer ですが、先の System.Xaml に則ったスタイルに書き直そうかなと思案中です。ドット付きタグ名のあたりが独自処理になってしまっているので、mono の System.Xaml を参考にする感じに。

カテゴリー: XAML | XAML は Microsoft だけのモノじゃないので、動的にロードできるよという話 はコメントを受け付けていません