【2017年版】Visual Studio で Arduino 開発

Arduino と言えば、普通は開発には Arduino IDE を使うと思いますが、ここでは Visual Studio で Arduino 開発ができますよ、しかもより効率的に開発できますよというお話。

2~3年ごとに、Visual Studio での Arduino 開発の記事を書いています。本当にたまたまなんですが、今回が3回目。
やんごとなき理由 で久しぶりに Arduino を触っておこうと思い、せっかくなのでデバッグあたりも見てみました(と言っても、作ったスケッチは L チカなんですが・・・)。

Visual Studio を使っちゃうと、申し訳ないですが Arduino IDE には戻れないですね。

続きを読む

「Visual Studio で Bot Service をローカルデバッグする方法」 第4回 Cogbot 勉強会で登壇しました #cogbot #botservice #functions

2017年1月27日(金) 開催の 第4回 Cogbot 勉強会で、
Visual Studio で Bot Service をローカルデバッグする方法」というテーマでお話ししました。

https://docs.com/d/embed/D25191673-0444-5596-4310-001940935162%7eBfe5a7bff-fc39-9c7d-d35f-86e930988702

Cognitive Service とも IoT とも仲良くできそうな、Bot Service は、ご承知の方も多いと思いますが、Azure Functions 上に展開されています。

Functions は当初デバッグが大変なサービスでした。
Azure ポータル上で print 分を使ってデバッグするか、Windows アプリでロジックを作った上で Functions のコードに貼り付けるかするくらいしかできませんでした。サーバーレス、ナノサービに分類されるサービスで、小さな処理を実行することを想定したサービスなので、それでも何とかできなくはないのですが、Visual Studio に慣れた身には面倒でした。


まだ「枯れた」とは言いがたいのですが、現在はいくつかの手順を踏めば Bot Service をローカルデバッグできます。Visual Studio のデバッグ機能も利用可能です。
ローカルデバッグするための手順は https://aka.ms/bf-docs-azure-debug で説明されているのですが、いくつかのページを移動しながらデバッグ準備を進めなければなりません。

そこで必要なツールやファイルのリンクと一緒に、画面キャプチャ付きで実際にデバッグを始めるまでのステップを紹介しました。

Visual Studio でブレークしたり、変数の値をウォッチしたりしながら、Bot Service を開発できるのは、やはりうれしいですね。
なお本稿の内容は、Bot Service だけではなく Azure Functions でも使えます。IoT でも Functions は使いどころがあるので、IoT 好きな方も参考にしてみてください。

ウイルスバスター入りの環境で、Hololens, Windows Mobile などのエミュレーター起動に失敗する場合

なんだかブログ更新が久しぶりの感じですみません。
少し生活のパターンが変わったらペースがつかめなくなってました・・・。

Hololens エミュレーターも出たことだし、立ち上げるくらいやってみるか」と思い、ツールをインストールして真っ白 UWP アプリを動かそうとしたところ、私の環境では何度やっても「認証エラーが発生しました」メッセージとともにエミュレーターが終了・・・。Visual Studio を再起動しても、Windows を再起動してもダメ。
(そういえば、PCを変えてから Windows Mobile エミュレーターも起動していなかった)

調べたところ、ウイルスバスターをインストールしたマシンだとエミューレーター(仮想マシン)の作成や起動に失敗することが多いらしい。(英語サイトに行くと他のセキュリティソフトでも同様の事象があるようです)
トレンドマイクロの FAQ ページにも載っているくらい、知ってる人は知ってる事象のようです。

解決するには、Hyper-V のデータに関するフォルダーをリアルタイムスキャンの対象から外すといいようです。

2016-04-17 20-58-32

2016-04-17 21-00-26

以下の4つのフォルダーをスキャン対象から除外します。

  • C:\ProgramData\Microsoft\Windows\Hyper-V
  • C:\ProgramData\Microsoft\Windows\Hyper-V\Snapshots
  • C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks
  • C:\Users\<アカウント>\AppData\Local\Microsoft\XDE

これで Windows を再起動すれば大丈夫、ちゃんとエミュレーターが起動して、Hololens を楽しめます。
何かの拍子に起動に失敗するようになることはあるけど、その時は VS 再起動したり Windows 再起動したりすればまた動きます。

 

PS. 「なんでウイルスバスター?」という、そもそもの疑問がある人もいるかもしれません。
家族の PC やらスマホやらが増えてきて、ちゃんとセキュリティをチェックするのが楽になるかな~と思い、家中まるごと Trend Micro OKAERI というサービスを入れました。インストールしているか、マルウェアにやられてないか、ブロックした件数などを全部のデバイスをまとめて随時確認できるので便利。家族のデバイス全部、月額固定で面倒見てくれるし。メモリー食いな感じはあるけど、使ってみるとなかなかいい製品です。

【2015年版】Visual Studio で Arduino 開発

このところ、「Visual Studio で Arduino 開発」 の閲覧数が増えています。
Arduino IDE for Visual Studio が Visual Studio の拡張機能と更新プログラムの上位に表示されるようになったからでしょうね。

2015-09-18 19-59-32

Visual Studio の Community Edition があるから、という理由もあるでしょう。

Arduino は苦手な私ですが(恥)、「Arduino 持ってるか?」と言われれば「はい」と答えざるを得ません。
ということで、せっかくなので改めてごく簡単に評価してみました。

Arduino IDE の製品詳細ドキュメントの閲覧有償版へのアップグレードは、Visual Macro のサイトへどうぞ。


インストールはごく簡単ですね。拡張機能と更新プログラムからインストールするだけです。こまめにバージョンアップされているようですが、他のプラグインなどと同様に更新時には Visual Studio が教えてくれます。

インストール後は、新しいプロジェクトダイアログにテンプレートが表示されるようになります。
Visual C++ カテゴリー下に出てきます。

2015-09-18 20-24-51

Windows for IoT 下にも Arduino IoT Project というプロジェクトテンプレートもあります。Windows Remote Arduino に関係するテンプレートですかね。(すみません、ここは調べていません。いずれ、その気になったらちょっと触ってみる・・・かもしれません)

2015-09-18 20-25-07


Arduino 開発に関する設定はツールバーから行います。ライブラリの追加もツールバーで行います。

2015-09-18 20-26-522015-09-18 20-28-14

スケッチサンプルやライブラリの一覧、ボードの参照などは、Visual Micro Explorer ウィンドウを利用できます。

2015-09-18 20-47-46

作成したスケッチは F5 キーで Arduino 実機に転送して実行できます。
デバッグ機能は有償版にアップグレードするとできるようになるようです。(未評価)

Arduino IDE を使わずに Visual Studio だけで一連の作業が完結します。インテリセンスも使えますし、Arduino IDE よりも便利に使えそう。
Visual Studio との親和性も以前より高くなっているように思います。

ホビーユースの Arduino 開発ならば、Visual Studio 2015 Community が使えますし、Arduino 好きな方はインストールしておいて損はなさそう。がっつり開発したい場合は有償版にアップグレードしてデバッグ機能を利用するとさらに効率よく開発できそうです。

「はじめての Visual Studio /クラウド/ IoT」は7月19日(土) の開催です(技術ひろば.net 2014年7月) #hirobatech

2014年7月の技術ひろば.net の勉強会は「はじめての Visual Studio /クラウド/ IoT (復習希望の方の参加も歓迎)」と題して、7月19日(土) に開催します。
ブログでの告知がすっかり遅くなってすみません。

http://hiroba-tech.connpass.com/event/7101/

タイトル通り、初心者・(再)入門者、それからこれを機に復習してみたいという方のための勉強会です。
当初の予想を大幅に超えたお申し込みをいただき、参加者枠を増やしましたが、それでも満席が予想されます。参加ご希望の方はお早めにお申し込みください。

アンケート、懇親会などで「難しい勉強会が多くて、なかなか参加しづらいことがある」という声をよく聞きます。今回はそういった方の期待に応える勉強会を企画しました。
その場で話を聞いて終わりではなく、参加者の皆さんが一つでも多く自習の情報をお持ち帰りになれる会になるようにしますね。

セッションテーマとスピーカーは、

  • Visual Studio 活用方法・・・椎野磨美さん
  • はじめての IoT ・・・太田寛さん
  • はじめてのクラウド・・・森博之さん

です。豪華スピーカーで実は私自身が当日を一番楽しみにしています。

たくさんの方のお申し込みをお待ちしています。

http://hiroba-tech.connpass.com/event/7101/

 

「SharePoint 開発ツールの比較」セッションを担当しました (2014年3月22日 MVP Community Camp) #‎MVPComCamp

3月22日(土) に開催された MVP Community Camp 東京会場のカンファレンス(オフラインイベント)東京会場で 1枠いただき、SharePoint 開発ツールについてお話ししました。

LightSwitch (クラウドビジネスアプリ)、Access、Project Siena で SharePoint / Office 365 用のアプリケーションを開発できます。これらがそれぞれ出来ること/出来ないこと、得意なこと/苦手なことを紹介しました。
SharePoint の Web パーツを作ったり CSOM でクライアントを作ったり、という内容は全く触れていません。(InfoPath にも触れていません)
Officd 365 のおかげで中小企業でも SharePoint を使いやすくなったわけですが、当然 SharePoint のカスタマイズなりアプリ開発なりまでは充分な費用をかけられないこともあると思います。そういうケースで高い生産性で社内システム、業務アプリを開発できるといいよね、LightSwitch や Access を使うとそれを実現できるよ、というメッセージをお伝えしました。

LightSwitch の認知度はまだまだですが、それでも少しずつ知られてきて、興味を持ってもらえるようになってきたかなと思っています。やはり Office 365 対応、特にクラウドビジネスアプリの発表以降は肌で感触を感じられるようになってきました。
簡単に開発ができすぎるがために、かえってビジネスになりづらいという開発ツールですが、活用できるシーンは多いと思います。
今回初めてセッションでお話しした Access も SharePoint / Office 365 開発ツールとして非常に優秀です。Project Siena もそう。
これからも LightSwitch, Access, Project Siena の高い生産性を(勝手に)訴求していきたいと思います。

技術ひろばの勉強会では Ustream 配信はしていないのですが、今回はライブ配信、収録をしていただきました。復習やちょっと興味を持ったから聞いてみようかなという方は、ぜひこちらのページで視聴してみてください。

http://www.ustream.tv/recorded/45145052

LEGO MINDSTORMS EV3 API の DirectCommand で音楽を奏でてみる

LEGO MINDSTORMS EV3 API を使うと、Windows デスクトップ、ストアアプリ、Windows Phone 8 から Mindstorms EV3 をコントロールできます。

まずはモーターを制御してトレーニングロボットを走らせるんでしょうね。

2014-01-18 12-09-19

が、せっかく音の出るオモチャです。チューリップくらい演奏してみたくなります。
ということで、やってみました。
技術的に難しいところはない上にこのままだと実用度はほぼゼロですが、EV3 操作の一つとして紹介します。別スレッドを使ってモデルを走らせながら音楽を鳴らすのも楽しそうです。

まずはソースコードを。EV3 の操作自体は簡単です。
音階の周波数の定数値定義と楽譜がソースコードの大半なのでそれらは本稿の末尾に。
プログラミングとは別のところで苦労(?)しましたが、たまにはこういうことにエネルギーを注ぐのもいいでしょう。もうちょっと楽譜作りをがんばればドレミの歌なんかもできます。


MainWindow.xaml.cs

using System.Windows;
using Lego.Ev3.Core;
using Lego.Ev3.Desktop;

namespace Ev3Music01
{
    public partial class MainWindow : Window
    {
        private Brick _brick;

        public MainWindow()
        {
            InitializeComponent();
        }

        private async void Window_Loaded(object sender, RoutedEventArgs e)
        {
            _brick = new Brick(new BluetoothCommunication("COM6"));
            await _brick.ConnectAsync();
        }

        private async void PlayMusic_Click(object sender, RoutedEventArgs e)
        {
            await Score.PlayTulip(_brick);
        }
    }
}

PC と EV3 とは Bluetooth 接続するので、あらかじめペアリングしておいてください。
私の環境では COM6 ですが、BluetoothCommunication のコンストラクターにはそれぞれの環境に応じた引数を渡してください。

_brick = new Brick(new BluetoothCommunication("COM6"));
await _brick.ConnectAsync();

念のために画面(WPF) はこんな感じ。今回はこれ以上の説明は不要ですね。

2014-01-18 12-15-01


MusicPlayer.cs

using System;
using System.Threading.Tasks;
using Lego.Ev3.Core;

namespace Ev3Music01
{
    public class MusicPlayer
    {
        public static async Task PlayToneAsync(Brick brick, int volume, ushort frequency, ushort duration)
        {
            await brick.DirectCommand.PlayToneAsync(volume, frequency, duration);
            await Task.Delay(new TimeSpan(0, 0, 0, 0, duration));
        }

        public static async Task PlayToneAsync(Brick brick, int volume, Scale scale, ushort duration)
        {
            await brick.DirectCommand.PlayToneAsync(volume, (ushort)scale, duration);
            await Task.Delay(new TimeSpan(0, 0, 0, 0, duration));
        }

        public static async Task PlayRestAsync(Brick brick, ushort duration)
        {
            await Task.Delay(new TimeSpan(0, 0, 0, 0, duration));
        }
    }
}

EV3 にコマンド (DirectCommand) を送信する処理です。PlayToneAsync メソッドで非同期に音を鳴らします。
volume (音量) は 0~100、frequency (周波数) は300~10000 が指定できるようです。duration (長さ) は ミリ秒単位の指定です。ただし実際には 300 Hz より若干低い音でも出せるようです。

await brick.DirectCommand.PlayToneAsync(volume, frequency, duration);
await Task.Delay(new TimeSpan(0, 0, 0, 0, duration));

非同期なので PlayToneAsync を連続して実行すると最後の音しか鳴りません。Task.Delay で音が鳴り終わるのを待ちます。


Scale.cs

ここで音階ごとに周波数を指定します。これで PlayToneAsync の引数で毎回周波数を指定する代わりに Scale.C4 のような指定が出来ます。
frequency は ushort なので残念ながら小数値は指定できません。正しい周波数ではありませんが、ここは制限事項ですね。

namespace Ev3Music01
{
    public enum Scale : ushort
    {
        C4 = 262,
        Cs4 = 277,
        D4 = 294,
        Ds4 = 311,
        E4 = 330,
        F4 = 349,
        Fs4 = 370,
        G4 = 392,
        Gs4 = 415,
        A4 = 440,
        As4 = 466,
        B4 = 494,
        C5 = 523,
        Cs5 = 554,
        D5 = 587,
        Ds5 = 622,
        E5 = 659,
        F5 = 698,
        Fs5 = 740,
        G5 = 784,
        Gs5 = 831,
        A5 = 880,
        As5 = 932,
        B5 = 988,
        C6 = 1047,
        Cs6 = 1109,
        D6 = 1175,
        Ds6 = 1245,
        E6 = 1319,
        F6 = 1397,
        Fs6 = 1480,
        G6 = 1568,
        Gs6 = 1661,
        A6 = 1760,
        As6 = 1865,
        B6 = 1976,
    }
}

Score.cs

楽譜はこんな感じで記述してみました。

using System.Threading.Tasks;
using Lego.Ev3.Core;

namespace Ev3Music01
{
    public class Score
    {
        private const int Volume = 10;
        private const int BeatLength = 500;

        public static async Task PlayTulip(Brick brick)
        {
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.C4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayRestAsync(brick, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.C4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayRestAsync(brick, BeatLength);

            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.G4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.C4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayRestAsync(brick, BeatLength);

            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.C4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayRestAsync(brick, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.C4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayRestAsync(brick, BeatLength);

            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.G4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.C4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.C4, BeatLength);
            await MusicPlayer.PlayRestAsync(brick, BeatLength);

            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.G4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.G4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.G4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.A4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.A4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.G4, BeatLength);
            await MusicPlayer.PlayRestAsync(brick, BeatLength);

            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.E4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.D4, BeatLength);
            await MusicPlayer.PlayToneAsync(brick, Volume, Scale.C4, BeatLength * 3);
            await MusicPlayer.PlayRestAsync(brick, BeatLength);
        }
    }
}