RaspberryPi - 小ネタ Mar 12th, 2013 CPU温度 $ /opt/vc/bin/vcgencmd measure_temp $ cat /sys/class/thermal/thermal_zone0/temp CPU情報 $ cat /proc/cpuinfo CPUクロック $ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq $ /opt/vc/bin/vcgencmd measure_clock arm メモリー情報 $ cat /proc/meminfo 電圧 /opt/vc/bin/vcgencmd measure_volts core vcgencmd使い方 RPI vcgencmd usage
RaspberryPi - 無線LAN設定 Feb 4th, 2013 USB無線LAN子機の設定 RaspberryPiにUSB無線LAN子機(NEC Aterm WL300NU-G)を接続した。 そのときの手順。 電源 RaspberryPi起動中に、USB機器を差すと物によっては電力不足でリセットがかかり再起動するらしい。 試しに、起動中にWL300NU-GをUSBに差してみたら、やはり再起動した。 USB機器を使用する場合は、電源投入前に差しておくのが良いかもしれない。 起動後の関連コマンドログ pi@raspberrypi ~ $ dmesg (省略) [ 3.143217] usb 1-1.3: new high-speed USB device number 4 using dwc_otg [ 3.302245] usb 1-1.3: New USB device found, idVendor=0409, idProduct=0249 [ 3.321389] usb 1-1.3: New USB device strings: Mfr=16, Product=32, SerialNumber=48 [ 3.336501] usb 1-1.3: Product: AtermWL300NU-G [ 3.343530] usb 1-1.3: Manufacturer: NEC [ 3.349906] usb 1-1.3: SerialNumber: 12345 [ 4.155439] udevd[137]: starting version 175 [ 5.671058] cfg80211: Calling CRDA to update world regulatory domain [ 6.493240] usb 1-1.3: reset high-speed USB device number 4 using dwc_otg [ 6.693746] usbcore: registered new interface driver carl9170 [ 6.863646] usb 1-1.3: firmware not found. (省略) pi@raspberrypi ~ $ lsmod Module Size Used by snd_bcm2835 12808 0 snd_pcm 74834 1 snd_bcm2835 snd_seq 52536 0 snd_timer 19698 2 snd_seq,snd_pcm snd_seq_device 6300 1 snd_seq snd 52489 5 snd_seq_device,snd_timer,snd_seq,snd_pcm,snd_bcm2835 snd_page_alloc 4951 1 snd_pcm carl9170 74651 0 mac80211 236178 1 carl9170 ath 16648 1 carl9170 cfg80211 171957 3 ath,mac80211,carl9170 pi@raspberrypi ~ $ lsusb Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 0409:0249 NEC Corp. Aterm WL300NU-G pi@raspberrypi ~ $ modinfo carl9170 | head filename: /lib/modules/3.2.27+/kernel/drivers/net/wireless/ath/carl9170/carl9170.ko alias: arusb_lnx alias: ar9170usb firmware: carl9170-1.fw description: Atheros AR9170 802.11n USB wireless license: GPL author: Christian Lamparter <chunkeey@googlemail.com> author: Johannes Berg <johannes@sipsolutions.net> version: 1:1.9.4 srcversion: D2411637BD7256187C65770 デバイスを認識させる USB機器としては認識しているが、ifconfigで、該当するIFが表示されない。 原因は、dmesg の [ 6.863646] usb 1-1.3: firmware not found. これ。 無線LANデバイスは、.koファイルだけでなく、対応するファームウェアファイルが必要となる。 必要なファイルは、dmesgで表示される、 firmware: carl9170-1.fw ← コイツ LinuxWirelessから、carl9170-1.fw をダウンロード /lib/firmwareにおく。パーミッションは、644。 設定 /etc/network/interfaces を編集する。 オリジナルとの差分 pi@raspberrypi /etc/network $ diff interfaces interfaces.org 6d5 < auto wlan0 8,17c7,8 < iface wlan0 inet dhcp < wpa-ap-scan 1 < wpa-scan-ssid 1 < wpa-key-mgmt WPA-PSK < wpa-proto WPA2 < wpa-pariwise CCMP < wpa-group CCMP < wpa-ssid アクセスポイントのSSID < wpa-psk アクセスポイントのキー < #wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf --- > iface wlan0 inet manual > wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf 編集後 $ sudo ifup wlan0 として有効化する。 参考サイト Raspberry Piを無線LAN化
RaspberryPi - C言語でPWM制御。からの、Ruby用ライブラリ作成(つづき) Jan 29th, 2013 前回のつづき。 Rubyライブラリの作成 前回のプログラムの関数をRubyで使用できるようにライブラリ化 Swigのインストール $ sudo apt-get install swig 定義ファイルを書く ライブラリに登録する関数をpwm.iというファイルに記述する 登録する関数 set_range set_duty hw_initialize pwm.iの内容 %module pwmlib %{ extern volatile unsigned * io_mapping(int base_addr); extern void hw_initialize(); extern void set_range(int range); extern void set_duty(int duty); %} %init %{ hw_initialize(); %} extern void set_range(int range); extern void set_duty(int duty); ラッパー関数作成 siwgを使用し、ruby用のラッパー関数を作成する。 $ swig -ruby pwm.i pwm_wrap.cが生成される Makefileの生成 extconf.rbを作成して実行する extconf.rbの内容 require 'mkmf' create_makefile('pwmlib') 実行 $ ruby extconf.rb Makefileが生成される ビルドとインストール $ make $ sudo make install ← 生成された.soファイルをRubyのライブラリディレクトリへコピー Rubyからの利用 C言語版と同様、Rangeを1000固定で、Dutyを0~1000まで100単位で変化させるサンプル。 require 'pwmlib' pwm = Pwmlib pwm.set_range(1000) 0.step(1000, 100) do |i| sleep(1) puts "d=#{i}" pwm.set_duty(i) end 実行 $ sudo ruby pwm.rb
RaspberryPi - C言語でPWM制御。からの、Ruby用ライブラリ作成 Jan 29th, 2013 雑誌インターフェースのサンプルや、 wiringPiのコードを参考にpwmのレジスタにアクセスする。 RaspberryPiのPWM PWM0(GPIO18)がピンヘッダ(12pin)へ接続されている PWM_RNGxレジスタで、Rangeを設定 PWM_DATxレジスタで、Duty(Highの期間)を設定 |<---duty-->| ___________ / \____________/ |<-------range---------->| CM_GPxCTLレジスタ(※)で、Rangeのベースクロックを設定する。 OSCに19.2MHzの発信器が接続されている。(回路図参照) CM_GPxCTLレジスタのSRCフィールドを1(oscillator)にすれば、OSC(19.2MHz)が使用可。 CM_GPxDIVレジスタで、OSCクロックを分周。WiringPiでは32分周して600KHzをRangeのベースクロックとしている。 ※CM_GPxCTLレジスタのアドレスが、BCM2835のデータシートでは、0x20101070(0x7E101070)となっているが、 WiringPiのコード上では、0x201010A0にアクセスしている。 プログラム Rangeを1000固定で、Dutyを0~1000まで100単位で変化させるサンプル。 ※ただし、動作はLED(暗→明)で確認しただけで、オシロスコープなどでは確認していないので 正確なクロックが出力されているか不明。 // // BCM2835 pwm lib // #include <stdio.h> #include <string.h> #include <stdlib.h> #include <dirent.h> #include <fcntl.h> #include <assert.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #define BCM2708_PERI_BASE 0x20000000 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ #define PWM_BASE (BCM2708_PERI_BASE + 0x20C000) /* PWM controller */ #define CLOCK_BASE (BCM2708_PERI_BASE + 0x101000) // PWM controller offset #define PWM_CONTROL 0 #define PWM_STATUS 1 #define PWM0_RANGE 4 #define PWM0_DATA 5 #define PWM1_RANGE 8 #define PWM1_DATA 9 // GPIO clock reg offset #define PWMCLK_CNTL 40 #define PWMCLK_DIV 41 // BCM Magic #define BCM_PASSWORD 0x5A000000 #define PWM1_MS_MODE 0x8000 // Run in MS mode #define PWM1_USEFIFO 0x2000 // Data from FIFO #define PWM1_REVPOLAR 0x1000 // Reverse polarity #define PWM1_OFFSTATE 0x0800 // Ouput Off state #define PWM1_REPEATFF 0x0400 // Repeat last value if FIFO empty #define PWM1_SERIAL 0x0200 // Run in serial mode #define PWM1_ENABLE 0x0100 // Channel Enable #define PWM0_MS_MODE 0x0080 // Run in MS mode #define PWM0_USEFIFO 0x0020 // Data from FIFO #define PWM0_REVPOLAR 0x0010 // Reverse polarity #define PWM0_OFFSTATE 0x0008 // Ouput Off state #define PWM0_REPEATFF 0x0004 // Repeat last value if FIFO empty #define PWM0_SERIAL 0x0002 // Run in serial mode #define PWM0_ENABLE 0x0001 // Channel Enable #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y) #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) #define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) #define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0 #define GPIO_GET *(gpio+13) // read bits // I/O access volatile unsigned *gpio; volatile unsigned *pwm; volatile unsigned *clk; static int mem_fd = 0; // // Set up a memory regions to access GPIO // volatile unsigned * io_mapping(int base_addr) { char *gpio_mem, *gpio_map; /* open /dev/mem */ if (!mem_fd) { if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { printf("can't open /dev/mem \n"); exit (-1); } } /* mmap GPIO */ // Allocate MAP block if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) { printf("allocation error \n"); exit (-1); } // Make sure pointer is on 4K boundary if ((unsigned long)gpio_mem % PAGE_SIZE) gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE); // Now map it gpio_map = (char *)mmap( (caddr_t)gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, base_addr ); if ((long)gpio_map < 0) { printf("mmap error %d\n", (int)gpio_map); exit (-1); } // Always use volatile pointer! return (volatile unsigned *)gpio_map; } // void hw_initialize() { gpio = io_mapping(GPIO_BASE); pwm = io_mapping(PWM_BASE); clk = io_mapping(CLOCK_BASE); // GPIO18をPWMに SET_GPIO_ALT(18, 5); *(pwm + PWM_CONTROL) = 0; // Stop PWM *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01; // Stop PWM Clock usleep(110000); // See comments in pwmSetClockWPi while ((*(clk + PWMCLK_CNTL) & 0x80) != 0) // Wait for clock to be !BUSY usleep(1000) ; *(clk + PWMCLK_DIV) = BCM_PASSWORD | (32 << 12); // set pwm div to 32 (19.2/32 = 600KHz) *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11; // enable clk usleep(110000); // Default range register of 1024 *(pwm + PWM0_RANGE) = 1024; usleep(10000); *(pwm + PWM1_RANGE) = 1024; usleep(10000); *(pwm + PWM0_DATA) = 0; usleep(10000); *(pwm + PWM1_DATA) = 0; usleep(10000); // Enable PWMs in balanced mode (default) *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE; usleep(100000); } // Range設定 void set_range(int range) { *(pwm + PWM0_RANGE) = range; usleep(1000); } // Duty設定 void set_duty(int duty) { *(pwm + PWM0_DATA) = duty; usleep(1000); } int main(void) { int i; hw_initialize(); set_range(1000); for(i = 0; i <= 1000; i += 100) { usleep(1000000); set_duty(i); printf("d=%d\n", i); } return 0; } コンパイルと実行 $ gcc pwm.c $ sudo ./a.out つづく…
RaspberryPi - WiringPiライブラリのインストール Jan 28th, 2013 WiringPiライブラリ Raspberry Piの低レベル周辺回路を制御するライブラリ、 WiringPiをインストールする。 C言語用ライブラリをベースに各言語のラッパーも公開されている。 (元々Arduino向けのライブラリ?をRaspberry Piに移植した?よくわからん) また、コマンドラインからGPIOを制御できるユーティリティも付属している。 $ git clone git://github.com/WiringPi/WiringPi.git $ cd WiringPi $ ./build ユーティリティの使い方 GPIOの番号指定がArduinoライクになっているらしい。 BCMの番号指定もできる。 wiringPi番号での指定 $ gpio mode 7 out ← Pin7(GPIO4)を出力モードに $ gpio write 7 1 ← Pin7(GPIO4) High $ gpio write 7 0 ← Pin7(GPIO4) Low BCM番号での指定 $ gpio -g mode 4 out ← GPIO4を出力モードに $ gpio -g write 4 1 ← GPIO4 High $ gpio -g write 4 0 ← GPIO4 Low ピンヘッダとwiringPi番号とBCM番号の対応はこちら
RaspberryPi - C言語でLチカ(レジスタ直接制御) Jan 27th, 2013 雑誌インターフェース 2012年12月号の サンプルプログラム (おそらくオリジナルはここ)を、 Rev2基板用にすこし修正して動作させた。(48行目~) それと、サンプルプログラムのGPIO4が無効になっていた(何故?)ので使えるように。 ※下記のコードもGPIO4を10回トグルさせるようにしている。 Rev2のピンヘッダのGPIO情報はこちらの少し下あたり。 $ gcc gpio_c.c $ sudo ./a.out レジスタへ直接アクセス出来るようにする手順 malloc()で、仮想メモリ空間のメモリ領域を確保 確保したメモリ領域内から、4Kバウンダリのアドレスを求める /dev/mem と mmap()で、確保したメモリ領域をレジスタ領域にマッピング mmap()からマッピングされたレジスタのアドレスが返る mmap()が返したアドレス+オフセットで各レジスタにアクセスする // // How to access GPIO registers from C-code on the Raspberry-Pi // Example program // 15-January-2012 // Dom and Gert // // Access from ARM Running Linux #define BCM2708_PERI_BASE 0x20000000 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <dirent.h> #include <fcntl.h> #include <assert.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) int mem_fd; char *gpio_mem, *gpio_map; char *spi0_mem, *spi0_map; // I/O access volatile unsigned *gpio; // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y) #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) #define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) #define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0 #define GPIO_GET *(gpio+13) // read bits #define REV2 // for rev2 board #ifdef REV2 #define MAX_PORTNUM 27 char valid_port[] = { 0,0,1,1, // 0..3 1,0,0,1, // 4..7 1,1,1,1, // 8..11 0,0,1,1, // 12..15 0,1,1,0, // 16..19 0,0,1,1, // 20..23 1,1,0,1, // 24..27 }; #else #define MAX_PORTNUM 25 char valid_port[] = { 1,1,0,0, 0,0,0,1, 1,1,1,1, 0,0,1,1, 0,1,1,0, 0,1,1,1, 1,1 }; #endif void setup_io(); int port_avail(int port) { if ((port < 0) || (port > MAX_PORTNUM)) return (0); return ((int)valid_port[port]); } int gpio_read(int port) { if (!port_avail(port)) return(0); return( (GPIO_GET & (1<<port)) ? 1 : 0); } void gpio_write(int port, int data) { if (!port_avail(port)) { printf("illigal port:%d\n", port); return; } if (data == 0) GPIO_CLR = 1<<port; else GPIO_SET = 1<<port; } // // Set up a memory regions to access GPIO // int initcount= 0; void setup_io() { initcount++; /* open /dev/mem */ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { printf("can't open /dev/mem \n"); exit (-1); } /* mmap GPIO */ // Allocate MAP block if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) { printf("allocation error \n"); exit (-1); } // Make sure pointer is on 4K boundary if ((unsigned long)gpio_mem % PAGE_SIZE) gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE); // Now map it gpio_map = (char *)mmap( (caddr_t)gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, GPIO_BASE ); if ((long)gpio_map < 0) { printf("mmap error %d\n", (int)gpio_map); exit (-1); } // Always use volatile pointer! gpio = (volatile unsigned *)gpio_map; } // setup_io void gpio_init() { int i; setup_io(); #if 1 // modify. test gpio4 INP_GPIO(4); // must use INP_GPIO before we can use OUT_GPIO OUT_GPIO(4); #else for (i=0; i<1; i++) { INP_GPIO(i); } for (i=7; i<=11; i++) { INP_GPIO(i); // must use INP_GPIO before we can use OUT_GPIO OUT_GPIO(i); } #endif } void testmain() { #if 1 // modify. test gpio4 int i; for(i = 0; i < 10; i++) { gpio_write(4, 1); sleep(1); gpio_write(4, 0); sleep(1); } #else int p; for (p=7; p<=11; p++) { gpio_write(p,1); sleep(1); } for (p=0; p<2; p++) { printf("%d:",gpio_read(p)); } printf("\n"); for (p=7; p<=11; p++) { gpio_write(p,0); sleep(1); } for (p=0; p<2; p++) { printf("%d:",gpio_read(p)); } printf("\n"); #endif } int main(int argc, char **argv) { gpio_init(); testmain(); return 0; } // main ※ そういえば、あまり見かけないけど型修飾子のintは省略できる。 volatile unsigned *gpio;
RaspberryPi - CRubyでLチカ Jan 26th, 2013 デバイスファイルを使用した、GPIO制御。 system('echo "4" > /sys/class/gpio/export') system('echo "out" > /sys/class/gpio/gpio4/direction') [0, 1].cycle do |sw| system("echo #{sw} > /sys/class/gpio/gpio4/value") sleep(0.5) end $ sudo ruby gpio4.rb
RaspberryPi - CRubyとmrubyのインストール Jan 26th, 2013 環境 Raspbian “wheezy’ 2012-12-16版 事前に $ sudo apt-get update $ sudo apt-get upgrade を実施済み gitのインストール $ sudo apt-get install git-core CRubyのインストール $ sudo apt-get install ruby mrubyのインストール・ビルド $ git clone git://github.com/mruby/mruby.git $ sudo apt-get install build-essential bison mrubyディレクトリ下で $ make ※先にCRubyを入れていないと途中でエラーになる 環境変数 $ export MRUBY_HOME=(makeしたディレクトリ) $ export PATH=$PATH:$MRUBY_HOME/bin ※.bashrcにも 参考サイト Building mruby on the Raspberry Pi
Github+Octopressデプロイ Jan 24th, 2013 デプロイ前の環境 Windows7 Ruby Installerの Ruby 1.9.2-p290 インストール済み msysgit 1.7.10 インストール済み GitHubアカウント登録済み 大まかな流れ Ruby DevKitのインストール GitHub-Pageのリポジトリをつくる Octopressをインストール ブログの設定 記事の投稿 手順 Ruby DevKitのインストール 上記のRuby Installerのサイトから、DevKitをダウンロード→実行(解凍) ※ダウンロードしたファイルを実行すると、わらわらと沢山のファイルが展開されるので、専用のディレクトリ(C:\DevKitとか)を作成して、そこで実行(解凍)するのがよい。 解凍したディレクトリに移動し下記コマンドを入力 ruby dk.rb init ruby dk.rb review ruby dk.rb install GitHub-Pagesのリポジトリをつくる リポジトリ作成画面のRepository nameの項目に アカウント名.github.com と、いうリポジトリを作成する Octopressをインストール git clone git://github.com/imathis/octopress.git octopress cd octopress sudo gem install bundler ← DevKitが無いとエラー sudo bundle install rake install ブログの設定 _config.ymlを編集 とりあえず、title: と subtitle:くらい? 記事の投稿 rake generate rake deploy rake gen_deploy ← generate と deploy を同時に行う rake preview ← localhost:4000でWebサーバ起動 関連情報 Windows環境で _config.ymlファイルや記事ファイルに日本語が含まれていて rake gen_deploy コマンドで invalid byte sequence in Windows-31J とエラーになる場合、環境変数 LANGを設定する。 c:\>set LANG=ja_JP.utf8 みたいに。 参考サイト Githubを使って独自ブログをはじめる方法メモ githubとjekyllとoctopressで作る簡単でモダンなブログ Octopress + Github Pages + Dropbox でブログを構築 Octopressの使い方 DevKitを使わないとgemが入らない場合(pikを使っていてもだいじょうぶ)