ラベル Arduino の投稿を表示しています。 すべての投稿を表示
ラベル Arduino の投稿を表示しています。 すべての投稿を表示

2013年6月13日木曜日

ruby gem 'arduino_firmata' の sysex を使ってMPL115A2使用の圧力モジュールから値を取得する

2013/06/14-18:11JST u2sで負の値の求め方の間違いを修正(緑色)

気圧の値も妥当なものになった(と思う).
2013/06/14-13:30JST 返り値のバイト数が要求バイト数と合っていないことがあるのでその場合スキップするように修正(青色)
2013/06/13-16:10JST ADT7410(温度)/"arduino.sysex I2C_REQUEST, [ADDRESS_ADT7410, _WRITE, 0x03, 0x00, 0x00, 0x001]"で16bit-modeで動くこともあるが, ケースによっては13bitのままだったりする.

  • 0.1度の中に複数の計測点があるので16bit modeであることがわかる.
  • 気圧/MPL115A2側はパスコン入れたら安定した
2013/06/13-15:36JST ADT7410(温度)/16bit mode指定がやっぱり正しく動いてないので削除
2013/06/13-15:06JST ADT7410(温度)/16bit mode指定の間違いを訂正
結果:

ブレッドボードをMBPの上からおろしたらみるみる温度が下がっていく図.
気圧が安定していない…やっぱりなにか間違っているのかもしれない.

これを使って,やってみた.のでメモ.
#!/usr/bin/env ruby -Ku
require 'rubygems'
require 'arduino_firmata'
$stdout.sync = true

STRING_DATA= 0x71
I2C_REQUEST= 0x76
I2C_REPLY= 0x77
I2C_CONFIG= 0x78

_WRITE= 0x00
_READ= 0x08

ADDRESS_ADT7410= 0x48
ADDRESS_MPL115A2= 0x60

#MPL115A2 coefficients
a0= b1= b2= c12= 0.0

def readData(data, shift)
  msb= data[4+4*shift]+data[5+4*shift]*128
  lsb= data[6+4*shift]+data[7+4*shift]*128
  return (msb<<8)+lsb
end

def readDataS(data, shift)
  v= readData(data, shift)
  return (v<(1<<15)) ? v : v-(1<<15)*2
end

def data2string(data)
  i=0
  msg= ''
  while i+1<data.length
    msg+= data[i].chr
    i+= 2
  end
  return msg;
end

arduino = ArduinoFirmata.connect ENV["ARDUINO"], :nonblock_io => true

arduino.on :sysex do |command, data|
  puts "command : #{command}"
  puts "data    : #{data.inspect}"
  if command == I2C_REPLY
    if data[0] == ADDRESS_ADT7410
      if data.length == 8
        tout= readDataS(data, 0)/(1<<7).to_f
        puts "気温 #{tout} ℃"
      end
    elsif data[0] == ADDRESS_MPL115A2
      if data[2] == 0x04
        if data.length == 20
          a0 = readDataS(data, 0)/(1<<3).to_f
          b1 = readDataS(data, 1)/(1<<13).to_f
          b2 = readDataS(data, 2)/(1<<14).to_f
          c12= readDataS(data, 3)/(1<<24).to_f
        end
      elsif data[2] == 0x00
        if data.length == 12
          padc= readData(data, 0)>>6
          tadc= readData(data, 1)>>6
          pcomp= a0 + ( b1 + c12 * tadc ) * padc + b2 * tadc
          pout= pcomp * 650.0/1023.0 + 500.0
          puts "気圧 #{pout} hPa"
        end
      end
    end
  else
    if command == STRING_DATA
      p data2string(data);
    end
  end
end

#i2c enable
arduino.sysex I2C_CONFIG, [0x00, 0x00]

#MPL115A2 coefficients
arduino.sysex I2C_REQUEST, [ADDRESS_MPL115A2, _READ, 0x04, 0x00, 0x08, 0x00]

loop do
  arduino.sysex I2C_REQUEST, [ADDRESS_ADT7410, _READ, 0x00, 0x00, 0x02, 0x00]

  arduino.sysex I2C_REQUEST, [ADDRESS_MPL115A2, _WRITE, 0x12, 0x00, 0x01, 0x00]
  sleep 0.02
  arduino.sysex I2C_REQUEST, [ADDRESS_MPL115A2, _READ, 0x00, 0x00, 0x04, 0x00]

  sleep 1
end
  • 前の記事の最後に書いた,「うまくいかない.」の原因は,1バイト(8ビット)の内容を送るのにも7bitの通信なので2バイト(7ビットのバイト+1ビットのバイト)送らないといけない(受信も)という点を全く理解していなかったのに挑んでいたのが原因.…だったと思っている(結局よくわかっていない).

2013年6月12日水曜日

ruby gem 'arduino_firmata' の sysex を使ってADT7410使用の温度モジュールから値を取得する

2013/06/14-18:11JST u2sで負の値を求め方の間違いを修正(緑色)
2013/06/14-13:30JST 返り値のバイト数が要求バイト数と合っていないことがあるのでその場合スキップするように修正(青色)
2013/06/13-16:34JST "arduino.sysex I2C_REQUEST, [ADDRESS_ADT7410, _WRITE, 0x03, 0x00, 0x00, 0x001]"で16bit-modeで動くこともあるが, ケースによっては13bitのままだったりする.

  • 0.1度の中に複数の計測点があるので16bit modeであることがわかる.
2013/06/13-15:36JST 16bit mode指定がやっぱり正しく動いてないので削除
2013/06/13-15:06JST 16bit mode指定の間違いを訂正
2013/06/13-01:53JST readDataの間違いを訂正(奇数バイトは128倍(8bit目?))
2013/06/12-23:27JST readDataの間違いを訂正(shiftの係数が2だった)
これを使って,やってみた.のでメモ.
#!/usr/bin/env ruby -Ku
require 'rubygems'
require 'arduino_firmata'
$stdout.sync = true

ADDRESS_ADT7410= 0x48
I2C_READ= 0x08

def readData(data, shift)
  msb= data[4+4*shift]+data[5+4*shift]*128
  lsb= data[6+4*shift]+data[7+4*shift]*128
  return (msb*256+lsb)
end

def readDataS(data, shift)
  v= readData(data, shift)
  return (v<(1<<15)) ? v : v-(1<<15)*2
end

def data2string(data)
  i=0
  msg= ''
  while i+1<data.length
    msg+= data[i].chr
    i+= 2
  end
  return msg;
end

arduino = ArduinoFirmata.connect ENV["ARDUINO"], :nonblock_io => true
puts "firmata version #{arduino.version}"

arduino.on :sysex do |command, data|
  puts "command : #{command}"
  puts "data    : #{data.inspect}"
  if command == 0x77
    if data[0] == ADDRESS_ADT7410
      if data.length == 8
        t= readDataS(data, 0) / (1<<7).to_f #デフォルトは13bit modeで下位三ビットが1固定で無効ですが割っちゃいます.
        puts "#{t} [度]"
      end
    end
  else
    if command == 0x71
      p data2string(data);
    end
  end
end

#i2c enable
arduino.sysex 0x78, [0x00, 0x00]

loop do
  arduino.sysex 0x76, [ADDRESS_ADT7410, I2C_READ, 0x00, 0x00, 0x02, 0x00]
  sleep 1
end

2012年5月21日月曜日

serialport-serverとtimbreを連携させてみた

参考というか動機
結果
やっている事:serialport-serverの例のようにCdsを接続し,Cdsの値をtimbreのfami.freqに与えている.
予想される動作:明るくなると音の高さが上がる.暗くなると音の高さが下がる.
で,結果:
コード
<html>
  <head>
    <meta charset="utf-8"/>
    <title>timbre - oscillators</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript" src="../timbre.js"></script>
  </head>
  <body>
    <selction id="body">
      <h2>Timbre</h2>
      <div>
        <button id="play0">play</button>
        <button id="pause0">pause</button>
      </div>
      
    <hr/>

      <div id="main">
        <h2>Serial Port</h2>
        <div>
          <input type="text" value="http://localhost:8783" id="addr" size="40" />
        </div>
        <h3>LED</h3>
        <div class="led">
          <input type="button" class="btn on" value="ON" />
          <input type="button" class="btn off" value="OFF" />
        </div>
        <h3>CdS</h3>
        <div class="cds">
          <input type="range" value="500" min="0" max="1024" class="slider" />
          <input type="text" id="cdsvalue" value="500" disabled="disabled" size="5" />
       </div>
     </div>
    </section>
  </body>
  <script type="text/javascript">
    $(function() {
      $('.led .on').click(function(){
        $.post($('#addr').val(), 'o', function(){
            //alert('led on');
        });
      });
      $('.led .off').click(function(){
        $.post($('#addr').val(), 'x', function(){
            //alert('led off');
        });
      });
      setInterval(function(){
        $.getJSON($('#addr').val(), {}, function(data){
            $('.cds input').val( data[0].data );
        });
      }, 100);

      function getCdsValue() {
        var value= parseInt($("#cdsvalue")[0].value);
        if (isNaN(value)) {
          value= 880;
        }
        return value;
      }
      
      dac0= T("dac", fami= T("fami", getCdsValue()));

      var timerId;
      dac0.addEventListener("on", function() {
            timerId = setInterval(function() {
                fami.freq = getCdsValue();
            }, 50);
        });

      dac0.addEventListener("on" , function() {timbre.on();});
      dac0.addEventListener("off", function() {
        if (dac0.isOff) timbre.off();
        });

      $("#play0").on("click", function() { dac0.on(); });
      $("#pause0").on("click", function() { dac0.off(); });
    });
  </script>
</html>

2010年5月27日木曜日

USBシリアルを監視するパッチ

動機
ScratchのようにArduinoでなにか信号をもらうのをQuartzComposerに出すとかやってみようかな.


参考
Re: Serial Read in Objective C under OSX? Reply #2 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1243282360/2#2
感謝



やってみた
#import <Quartz/Quartz.h>

#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

@interface USBSerialRXPlugIn : QCPlugIn
{
int fd;
NSMutableArray *lineBuffer;

BOOL isAlive;
}

@property NSUInteger inputPort;
@property(assign) NSString *outputMessage;

int USBSerialInit(const char *port);

@end


#import <OpenGL/CGLMacro.h>

#import "USBSerialRXPlugIn.h"

#define kQCPlugIn_Name @"USBSerial RX"
#define kQCPlugIn_Description @"USBSerial RX description"

@implementation USBSerialRXPlugIn

@dynamic inputPort;
@dynamic outputMessage;

+ (NSDictionary*) attributes
{
return [NSDictionary dictionaryWithObjectsAndKeys:
kQCPlugIn_Name, QCPlugInAttributeNameKey,
kQCPlugIn_Description, QCPlugInAttributeDescriptionKey,
nil];
}

static NSMutableArray *ports;
+ (NSArray *)ports
{
if (ports==nil) {
ports= [[NSMutableArray alloc] init];

NSFileManager *fileManager= [NSFileManager defaultManager];
NSError *err= nil;
NSArray *devices= [fileManager contentsOfDirectoryAtPath:@"/dev" error:&err];
if (err==nil && devices!=nil) {
int i, ic= [devices count];
for(i= 0; i<ic; i++) {
NSString *device= [devices objectAtIndex:i];
if ([device hasPrefix:@"tty.usbserial-"]) {
NSString *portStr= [NSString stringWithFormat:@"/dev/%@", device];
if (![ports containsObject:portStr]) {
[ports addObject:portStr];
}
}
}
}
}
return ports;
}

+ (NSDictionary*) attributesForPropertyPortWithKey:(NSString*)key
{
if([key isEqualToString:@"inputPort"]) {
NSArray *items= [USBSerialRXPlugIn ports];
return [NSDictionary dictionaryWithObjectsAndKeys:
@"Port", QCPortAttributeNameKey,
QCPortTypeIndex, QCPortAttributeTypeKey,
[NSNumber numberWithUnsignedInteger:[items count]-1], QCPortAttributeMaximumValueKey,
items, QCPortAttributeMenuItemsKey,
nil];
}
if([key isEqualToString:@"outputMessage"]) {
return [NSDictionary dictionaryWithObjectsAndKeys:
@"Message", QCPortAttributeNameKey,
nil];
}
return nil;
}

+ (QCPlugInExecutionMode) executionMode
{
return kQCPlugInExecutionModeProcessor;
}

+ (QCPlugInTimeMode) timeMode
{
return kQCPlugInTimeModeIdle;
}

- (id) init
{
if(self = [super init]) {
lineBuffer= [[NSMutableArray array] retain];
}

return self;
}

- (void) finalize
{
[super finalize];
}

- (void) dealloc
{
[lineBuffer release];
[super dealloc];
}
@end

@implementation USBSerialRXPlugIn (Execution)

- (BOOL) startExecution:(id<QCPlugInContext>)context
{
return YES;
}

- (void) enableExecution:(id<QCPlugInContext>)context
{
if (self.inputPort<0) {
return;
}
NSString *port= [[USBSerialRXPlugIn ports] objectAtIndex:self.inputPort];
fd = USBSerialInit([port UTF8String]);
if (fd>-1) {
isAlive= YES;
[NSThread detachNewThreadSelector:@selector(listen)
toTarget:self
withObject:nil];
}
}

- (BOOL) execute:(id<QCPlugInContext>)context
atTime:(NSTimeInterval)time
withArguments:(NSDictionary*)arguments
{
if ([lineBuffer count]>0) {
self.outputMessage= [lineBuffer objectAtIndex:0];
[lineBuffer removeObjectAtIndex:0];
}
else {
if (NO) {
self.outputMessage= [NSString stringWithString:@""];
}
}
return YES;
}

- (void) disableExecution:(id<QCPlugInContext>)context
{
isAlive= NO;
if (fd>-1) {
close(fd);
}
}

- (void) stopExecution:(id<QCPlugInContext>)context
{
[self disableExecution:context];
}

#pragma mark --
- (void)listen
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
char *buffer= (char *)malloc(256);
char *bufptr;
int nbytes;
char inchar;

while (isAlive) {
bufptr = buffer;
while ((nbytes = read(fd, &inchar, 1)) > 0)
{
if (inchar == '\r') continue;
if (inchar == '\n') break;
*bufptr = inchar;
++bufptr;
if (bufptr-buffer>254) break;
}
*bufptr = '\0';
[lineBuffer addObject:[NSString stringWithCString:buffer
encoding:NSUTF8StringEncoding]];
}

free(buffer);
[pool release];
}
int USBSerialInit(const char *port)
{
int fd;
struct termios options;

/* open the USB Serial Port */
fd = open(port, O_RDONLY | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open_port: Unable to open serial port - ");
return -1;
}
else fcntl(fd, F_SETFL, 0);
/* set the port to 9600 Baud, 8 data bits, etc. */
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~CSIZE; /* Mask the character size bits */
options.c_cflag |= CS8; /* Select 8 data bits */
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tcsetattr(fd, TCSANOW, &options);
return fd;
}
@end


できた

2010年5月20日木曜日

'Sensor Board With Motor'をやってみた.

動機
1.こちらのPOSTをみつけた.(感謝!)


やってみた
0.その前にこちら(Scratch+Arduino)を読んでおくといいかもしれません.
1.同POSTにあるSensorBoardWithMotor.zipをダウンロード
2.SensorBoardWithMotor.pdeファイルをArduinoのSDKでArduinoにUPLOAD
3.上記POST中のモータ制御についての解説ページ(Arduino 小型DCモータ/TA7291P)から,Arduinoのデジタル3番がPWMの信号とのこと
4.デジタル3番とGNDとをLEDにつなぐ
5.SensorBoardWithMotor.imageを起動
6.'Sensing'カテゴリの'[slider] sensor value'上でコンテクストメニューを出す

7.'show ScratchBaoard watcher'を選択.ArduinoのTX/RXのLEDが点滅を始める.

8.コードを用意.メニュー/'Edit'/'Show Motor Blocks'を選択. 'Motion'カテゴリにMotor制御用のBlockが現れる


9.コードを書く.(変数valは作ってください.)

10.実行 (ArduinoとLEDが映るのは1:00以降です)

2009年7月22日水曜日

rubyでシリアル受信(光電池をanalogReadしてXBeeで飛ばしてみる 2)

動機
スクリプト系がいいなぁ.


やったこと1.ruby-serialportのインストール
1.1 ruby-serialportのインストール(失敗
$ sudo gem install ruby-serialport
Password:
Bulk updating Gem source index for: http://gems.rubyforge.org
ERROR: Error installing ruby-serialport:
echoe requires RubyGems version >= 1.2
$ gem --version
1.0.1
$


1.2 gemのupdate
$ sudo gem install rubygems-update
Password:
Bulk updating Gem source index for: http://gems.rubyforge.org
Successfully installed rubygems-update-1.3.4
1 gem installed
Installing ri documentation for rubygems-update-1.3.4...
Installing RDoc documentation for rubygems-update-1.3.4...
$ sudo update_rubygems
Installing RubyGems 1.3.4
Installing RubyGems
Installing gem executable
Removing old source_cache files
Removing old RubyGems RDoc and ri
Installing rubygems-1.3.4 ri into /Library/Ruby/Gems/1.8/doc/rubygems-1.3.4/ri
Installing rubygems-1.3.4 rdoc into /Library/Ruby/Gems/1.8/doc/rubygems-1.3.4/rdoc

------------------------------------------------------------------------------

Oh-no! Unable to find release notes!

------------------------------------------------------------------------------

RubyGems installed the following executables:
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/gem

$


1.3 再度ruby-serialportのインストール
$ sudo gem install ruby-serialport
Building native extensions. This could take a while...
Successfully installed ruby-serialport-0.7.0
1 gem installed
Installing ri documentation for ruby-serialport-0.7.0...
Installing RDoc documentation for ruby-serialport-0.7.0...
$


やったこと2. コード変更(arduino)と作成(ruby)
Arduino 送信側
 int sensorPin = 0;
int sensorValue = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
sensorValue = analogRead(sensorPin);
Serial.println(sensorValue);
delay(1000);
}
 改行コードがgetsでの受信では必要なのでprintln(ってことだよなタブン).
MacBook 受信側 (rx.rb)
require 'rubygems'
require 'serialport'
port = "/dev/tty.usbserial-A6005t2E"
sp = SerialPort.new(port, 9600, 8, 1, SerialPort::NONE)
while (sp.gets) do
puts sp.gets
end
sp.close


結果
時間も出してみた.すげーバラバラ.


参考
Rails Agile Cooking - rubyでシリアル通信のテスト
gemが1.3.xにバージョンアップできない件 - func09

2009年7月21日火曜日

光電池をanalogReadしてXBeeで飛ばしてみる

追記(2009/07/22 9:18):2秒ごとのログ,1分ごとにその前10回の平均をログ,5分ごとに平均ログの最終行をtwitterにpost

訂正(2009/07/22):analogReadは0-1023の戻り値なので一バイト送信のSerial.writeの場合,4で割って0-255に納めてあげる必要があった.次の記事のprintlnの場合複数バイト送信できているようなので問題はないようだ.



動機
光量の変化を記録できないかしら?

ハード
送信:(光電池 -> Arduino(analog(0)) -> XBee)

(開放電圧1.7V)
受信:(XBee -> XBee Explorer USB -> MacBook)


ソフト
送信側(Arduino 0016)
 int sensorPin = 0;
int sensorValue = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
sensorValue = analogRead(sensorPin);
Serial.write(sensorValue/4);
delay(1000);
}

受信側(Processing 1.0.5)
import processing.serial.*;
Serial port;
int val;

void setup(){
port=new Serial(this,"/dev/tty.usbserial-A6005t2E",9600);
}
void draw(){
}
void serialEvent(Serial port) {
val = port.read();
println( "Raw Input:" + val);
}


あんまり色々考えてない.まずはこんなところ.

2008年12月14日日曜日

リレーを動かしてみた.

MacBookPro -> USB -> XBee -> (802.15.4 無線) -> XBee -> Arduino -> 信号 -> リレー




って感じのものを久しぶりに作ってみてた.
で気がついた. リレーってこんなにうるさかったけw.

動作の様子はまた後日.

2008年12月6日土曜日

USBから給電してみた.

追記(2008/12/10): 充電試しました.GOING MY WAYさんの記事にあるように赤ランプ状態では完全にだめ(開始するも数秒でやめちゃう)ですが,緑ランプでもギリギリではやはり問題はあるようで継続しません….ある程度余裕があればOKなので先に外部パックからってことになるのでしょうか?使い方が微妙.結局iPhone3G用にはKBC-L2Sが必要なようですね.買っちゃうか?



外出時,iPhone3Gで遊んでると遊び過ぎなのかバッテリーが心もとなくなることが何回かあり,予備電源が欲しいとおもっていました.
そこでGOING MY WAYのkengoさんが書かれているようなUSB給電可能なeneloopを購入を思い立ったて買いました.こいつ

で,購入決定時から頭をよぎってたのがこれの可能性.


できたよ.うごいたよ!
(eneloop二本で動作ってことは昇圧回路があるわけだよな.)

まぁ,というお話.
(ちなみにUSBケーブル(A<->B)は100円ショップで売ってたw.)

2008年12月1日月曜日

はじめてのXBee(というかArduinoもだけどw)

追記(2008/12/4):ちなみに環境は
MBP(Intel)+MacOSX10.5.5+Intel用ドライバ(FTDIUSBSerialDriver_v2_2_9_Intel)+Arduino 12(aruduino-0012)
です.



ちょっと機材が使えたのでこちらの例(?)をやってみた.
(こういう記事は本当に感謝♪プログラムアップロード時のXBee Shiled上にある二つのジャンパピンの変更の注意が既にあるのとないのでは大きな違い.)
(本来ならArduinoのA/Dあたりで遊ぶことが先だろうけどw.)

(MacBook Pro -> (USB) -> XBee Explorer USB(中央の赤い基盤) -> (無線) -> XBee Shield(右上側) -> Arduino (右下側))

こいつらどうやって通信を確立したのか,まったくこちらは意識していないんだけど
(一応断っておくが,Arduino側のUSBは電源供給のみだからねw)

ということで次はZTermを入れてその辺りのを調べたりして遊びますかね.ワクワク.