タグ「arduino」が付けられているもの

AIR2.0のNativeProcessを使って
jQuery PluginのCOLOR PICKERで選択した色をPerl経由でArduinoに送り
LEDの色を変化させる。

[AIR2.0 ajax] NativeProcessで perl を呼び出す メモをベースにします。

1. JQUERY PLUGINを落としてきて配置
COLOR PICKER - JQUERY PLUGINからダウンロードして配置します。
今回は以下のように配置しました。
picker1

2. COLOR PICKERをHTMLに表示する
picker3
でCOLOR PICKERを読み込みます。

javascriptで以下のように記述します。
$(function(){
  $('#colorpickerHolder').ColorPicker({flat: true,
     color: '#000000',
     onChange: function (hsb, hex, rgb) {
         writeData(hex);
     }
   });
});

bodyの中に

を記載します。

picker2

3. ArduinoにFF0000などの文字列を送るとBlinkMの色が変わるプログラムを送信します
#include "Wire.h"
#include "BlinkM_funcs.h"<<<<>>>>
#define BLINKM_ARDUINO_POWERED 1

byte blinkm_addr = 0x00;  
char serInStr[30];

void setup()
{
    if( BLINKM_ARDUINO_POWERED ) {
        BlinkM_beginWithPower();
    } else {
        BlinkM_begin();
    }
 
    Serial.begin(19200);

    // stop seq
    BlinkM_stopScript( blinkm_addr );
    
    // set default color
    BlinkM_setRGB( blinkm_addr, 0xff,0xff,0xff); // white
    
    // fade time
    BlinkM_setFadeSpeed( blinkm_addr, 255);
    
    // change color
    BlinkM_fadeToRGB( blinkm_addr, 0x00,0x00,0x00); //black

}

void loop()
{
	
  int num;
  if( readSerialString() ) {
    //Serial.println(serInStr);
    char* str = serInStr;
    num = atoi(str);
    byte a = toHex( str[0],str[1] );
    byte b = toHex( str[2],str[3] );
    byte c = toHex( str[4],str[5] );
     BlinkM_fadeToRGB( blinkm_addr, a,b,c);
  }
}

#include <ctype.h>
uint8_t toHex(char hi, char lo)
{
  uint8_t b;
  hi = toupper(hi);
  if( isxdigit(hi) ) {
    if( hi > '9' ) hi -= 7;      // software offset for A-F
    hi -= 0x30;                  // subtract ASCII offset
    b = hi<<4;
    lo = toupper(lo);
    if( isxdigit(lo) ) {
      if( lo > '9' ) lo -= 7;  // software offset for A-F
      lo -= 0x30;              // subtract ASCII offset
      b = b + lo;
      return b;
    } // else error
  }  // else error
  return 0;
}

uint8_t readSerialString()
{
  if(!Serial.available()) {
    return 0;
  }
  delay(10);
  int i = 0;
  while (Serial.available()) {
    serInStr[i] = Serial.read();
    i++;
  }
  serInStr[i] = 0;
  return i;
}
4. AIRのプログラムをAjaxスタイルで書きます
air2
jQueryColorPickerで色を選択したらNativeProcess経由でAnyEventで
標準入力に色コードをFF0000を送り、 Device::SerialPortでArduinoに
色データを送信します。

index.htmlは
<html>
<head>
<title>jQuery Plugin Color Picker - Perl - Arduino - BlinkM</title>

<link rel="stylesheet" type="text/css" href="css/colorpicker.css" />
<link href="css/layout.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/colorpicker.js"></script>

<script type="text/javascript" src="AIRIntrospector.js"></script>

<script type="text/javascript" src="AIRAliases.js"></script>
<script type="text/javascript"> 
var process;
var selected_hex;

function init(){ // Introspectorを起動しない//
  air.Introspector.canInit = function () { return false };
  air.Introspector.Console.log("Hello!");

  if (air.NativeProcess.isSupported){
   // windowをクローズする時に呼ばれるイベント
    window.nativeWindow.addEventListener(air.Event.CLOSING, closingHandler);
    launchEchoTest();
  }else{
    var textReceived = document.getElementById("textReceived");
    textReceived.value = "NativeProcess not supported.";
  }
}

// windowをクローズする時に呼ばれるイベント
function closingHandler(event){
  process.closeInput();
  window.nativeWindow.close();
}

function launchEchoTest(){	 
  var nativeProcessStartupInfo = new air.NativeProcessStartupInfo();
  nativeProcessStartupInfo.executable = new air.File(air.File.applicationDirectory.nativePath + "/perl/serial.pl");    
  process = new air.NativeProcess();
  process.addEventListener(air.ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
  process.addEventListener(air.ProgressEvent.STANDARD_INPUT_PROGRESS, inputProgressListener);
  process.start(nativeProcessStartupInfo);
}

function writeData(selected_hex){
  process.standardInput.writeUTFBytes(selected_hex + "\n");
}

function inputProgressListener(event){
  //process.closeInput();
}

function onOutputData(event){
  var bytes = process.standardOutput;
  $('#messages').prepend( bytes.readUTFBytes(bytes.bytesAvailable) );
}

$(function(){
  init();
  $('#colorpickerHolder').ColorPicker({flat: true,
                                       color: '#000000',
                                       onChange: function (hsb, hex, rgb) {
                                         writeData(hex);
                                       }
  });

});
</script>

<style>
#colorpickerHolder {
  top: 0px;
  left: 0px;
  width: 380px; 
}
#messages {
  position:absolute;
  top: 0px;
  right: 0px;
  height: 170px;
  width: 100px; 
  overflow: auto;
}

body {
  margin: 0 0;
}
</style>
</head>
<body> 
<div id="messages"></div>
<div id="colorpickerHolder"></div>
</body>
</html>
NativeProcessで起動されるPerlのスクリプトは以下のようになります。
Serial.pl
#!/usr/bin/perl
use strict;
use Device::SerialPort;
use AnyEvent;

# Arduino 
my $p = Device::SerialPort->new("/dev/tty.usbserial-A8004JhW");
$p->databits(8);
$p->baudrate(19200);
$p->parity("none");
$p->stopbits(1);
sleep(3); # For Arduino bootup wait.

use utf8;
binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";

$| = 1;
my $cv = AnyEvent->condvar;
my $w; $w = AnyEvent->io(
    fh   => \*STDIN,
    poll => 'r',
    cb   => sub {
        chomp(my $input = <STDIN>);
        $cv->send if(!$input); 
	 $p->write($input . "\n");
        print "DONE:" . $input . "\n";
    },
    );
$cv->recv;
5. AIR2のパッケージを作成する
$adt -package -storetype pkcs12 -keystore myCert.p12 -target native NativeProcessTest.dmg application.xml index.html AIRAliases.js  icons perl/serial.pl css js images
AIRのアプリをインストールし実行すると
ColorPickerを選ぶとLEDの色が変化しているのが確認できます。
AIR2.0 NativeProcess AnyEvent USB Serial Arduino BlinkM
AIR2.0 Arduino BlinkM
Arduino: Playground のCode for using the Arduino with the P*rall*x RFID readerのサンプルを利用し
Parallax brand RFID readerのデータをUSBシリアル接続されたArduinoで取得してみます。

1. 配線
Parallax RFID Reader Serialを以下のように接続します。
Arduino             RFID Reader
Arduino GND              -  GND
Arduino 5V                  -  VCC
DIGITAL2     -  ENABLE
DIGITAL8     -  SOUT

写真でみると以下のようになります。 Arduino RFID

2. Arduinoのプログラムを書く
読み込んだ値をmacにUSBシリアルで転送させたいので
0(RX),1(TX)のピンは利用できないので、
他のポートをソフトウェアでシリアル化して読み込みます。
ここでは、Arduino: Playground のCode for using the Arduino with the P*rall*x RFID readerのサンプルを利用します。
// RFID reader for Arduino 
// Wiring version by BARRAGAN  
// Modified for Arudino by djmatic
// Modified by Worapoht K.
// http://www.arduino.cc/playground/Learning/PRFID のサンプルを利用
 
#include 

int  val = 0; 
char code[10]; 
int bytesread = 0; 

#define rxPin 8
#define txPin 9
// RFID reader SOUT pin connected to Serial RX pin at 2400bps to pin8

void setup()
{ 
  Serial.begin(9600);  // Hardware serial for Monitor 9600bps

  pinMode(2,OUTPUT);       // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin 
  digitalWrite(2, LOW);    // Activate the RFID reader 
}


void loop()
{ 
  SoftwareSerial RFID = SoftwareSerial(rxPin,txPin); 
  RFID.begin(2400);

  if((val = RFID.read()) == 10)
  {   // check for header 
    bytesread = 0; 
    while(bytesread<10)
    {  // read 10 digit code 
      val = RFID.read(); 
      if((val == 10)||(val == 13))
      {  // if header or stop bytes before the 10 digit reading 
        break;                       // stop reading 
      } 
      code[bytesread] = val;         // add the digit           
      bytesread++;                   // ready to read next digit  
    } 

    if(bytesread == 10)
    {  // if 10 digit read is complete 
      Serial.print(code);            // print the TAG code 
    }
    bytesread = 0; 
    delay(500);                       // wait for a second
  } 
} 

Arduinoにスケッチを転送して、シリアルモニタで確認すると
以下のようにRFIDをリーダにかざした時に値が取得できる事が確認できます。
serial rfid

3. Device::SerialPortを利用してRFIDの値を読み込みます。
Quick & Easy Temperature Logging with the Arduinoのサンプルを参考に以下のように書いてみます。
#!/usr/bin/perl                                                                     
use strict;
use warnings;
use Device::SerialPort;

my $dev = tie (*FH, 'Device::SerialPort', "/dev/tty.usbserial-A8004JhW")
    || die "Can't tie: $!";

$dev->baudrate(9600);
$dev->databits(8);
$dev->parity("none");
$dev->stopbits(1);

# wait for arduino to boot                                                          
while (1) {
    my $val = <FH>;
    last if $val;
}

while (1) {
    my $val = <FH>;
    next unless $val;
    chomp $val;
    print $val . "\n";
    #sleep 1;                                                                       
}

実行すると以下のように値を受け取ります。
arduino RFID

値が読み込める事が確認できました。
ただしwhileで回していてCPUの負荷が高いようです。

試しにAnyEventを利用してみます。
AnyEventでtail -fを参考にし、AnyEvent::Handleを利用して書き直しました。
serialからの入力の読み込み方法がよく理解できてないので
無理矢理 IO::Handle Object を取り出してます。
ソースが正しいか分かはわからないですが、
以下のようにRFIDの値が読み込める事は確認できました。
perl serial anyevent
ソースはこちら、
#!/usr/bin/perl                                                                            
use strict;
use warnings;
use Device::SerialPort;

use AnyEvent;
use AnyEvent::Handle;

my $dev = tie (*FH, 'Device::SerialPort', "/dev/tty.usbserial-A8004JhW")
    || die "Can't tie: $!";

$dev->baudrate(9600);
$dev->databits(8);
$dev->parity("none");
$dev->stopbits(1);

# wait for arduino to boot                                                                 
while (1) {
    my $val = <FH>;
    last if $val;
}

# make anyevent loop                                                                       
my $fh = $dev->{'HANDLE'}; #IO::Handle Object                                              
$| = 1;

my $cv = AE::cv;
my $handle = create_handle();

sub create_handle {
    new AnyEvent::Handle
        fh => $fh,
        on_error => sub {
            my ($handle, $fatal, $message) = @_;
            $handle->destroy;
            undef $handle;
            $cv->send("$fatal: $message");
    },
    on_read => sub {
        my $handle = shift;
        $handle->push_read(line => sub {
            my ($handle, $line) = @_;
            print "$line\n";
                           })
    };
}

$cv->recv;

selectで待ち受けしてるみたいですが、
RFIDカードを読み取るとなんかエラーでてるような。
時間があるときに追ってみます。。。
anyevent

参考にさせていただいたサイト
Code for using the Arduino with the Parallax RFID reader
Quick & Easy Temperature Logging with the Arduino
[Arduino XBee Processing] RFIDタグを無線でPCに取り込む
AnyEventでtail -f
perl Device::SerialPortを使ってArduinoに信号を送りBlinkMの色を変更してみる メモ

1. 写真のようにBlinkMをArduinoにつなぎます
IMG_0489


2. macに接続して、デバイスの位置を確認します
mac arduino usb
$  ls /dev/*usbserial*

3. ArduinoでBlinkMの色を変更するプログラムを書きます
BlinkMのサイトからEXAMPLE CODEをダウンロードします。
ここでは、BlinkMのデータシートを読んでI2C通信をwireで実装するのは大変なのですが、
サンプルにあるBlinkM_funcs.hを利用するとその辺の事は何も考えず操作が可能です。
例えば、色を変更したいならアドレスと色番号を指定するだけで色を変更する事が可能です。
BlinkM_getRGBColor( blinkm_addr, &r,&g,&b);
(*BlinkM_funcs.hのラインセンスには注意)
サンプルのBlinkMTesterを参考にして、
RGBの6桁をserialで送信すると色を変更するプログラムを書いてみます。
#include "Wire.h"
#include "BlinkM_funcs.h"

#define BLINKM_ARDUINO_POWERED 1

byte blinkm_addr = 0x00;  
char serInStr[30];

void setup()
{
    if( BLINKM_ARDUINO_POWERED ) {
        BlinkM_beginWithPower();
    } else {
        BlinkM_begin();
    }
 
    Serial.begin(19200);

    // stop seq
    BlinkM_stopScript( blinkm_addr );
    
    // set default color
    BlinkM_setRGB( blinkm_addr, 0xff,0xff,0xff); // white
    
    // fade time
    BlinkM_setFadeSpeed( blinkm_addr, 255);
    
    // change color
    BlinkM_fadeToRGB( blinkm_addr, 0xff,0x00,0x00); //red

}

void loop()
{
	
  int num;
  if( readSerialString() ) {
    //Serial.println(serInStr);
    char* str = serInStr;
    num = atoi(str);
    byte a = toHex( str[0],str[1] );
    byte b = toHex( str[2],str[3] );
    byte c = toHex( str[4],str[5] );
     BlinkM_fadeToRGB( blinkm_addr, a,b,c);
  }
}

#include <ctype.h>
uint8_t toHex(char hi, char lo)
{
  uint8_t b;
  hi = toupper(hi);
  if( isxdigit(hi) ) {
    if( hi > '9' ) hi -= 7;      // software offset for A-F
    hi -= 0x30;                  // subtract ASCII offset
    b = hi<<4;
    lo = toupper(lo);
    if( isxdigit(lo) ) {
      if( lo > '9' ) lo -= 7;  // software offset for A-F
      lo -= 0x30;              // subtract ASCII offset
      b = b + lo;
      return b;
    } // else error
  }  // else error
  return 0;
}

uint8_t readSerialString()
{
  if(!Serial.available()) {
    return 0;
  }
  delay(10);
  int i = 0;
  while (Serial.available()) {
    serInStr[i] = Serial.read();
    i++;
  }
  serInStr[i] = 0;
  return i;
}
スケッチをArduinoに送信してserial monitorで
"ff0000"を送信してテストします
arduino blinkm

4. perlからRGBを指定して色を変えてみます
Device::SerialPortを利用します。
これを使うと以下のような短いコードでシリアル接続が可能です。
#!/usr/bin/perl                                                                                                       
use strict;
use Device::SerialPort;

my $p = Device::SerialPort->new("/dev/tty.usbserial-A8004JhW");
$p->baudrate(19200);
$p->databits(8);
$p->parity("none");
# $p->stopbits(1);
$p->write("ff0000");
色が変わることが確認できました。

参考サイト
ArduinoとAnyEventを使って,モールス信号でSOS !
Arduino BlinkM I2C通信テスト part1
thingm :: an electronic product studio: BlinkM