Raspbianでスクリーンショットを撮ろうと思ったらパッケージが入っていなかったようなのでインストールしてみました。
$ sudo apt-get install ksnapshot
左下メニューの”グラフィックス”→”KSnapshot”から起動出来ます。
Arduinoだとタイマー割り込みを使って処理したいところですが残念ながら私の調べた限りRaspberry Piでは無さそうなのでC言語とスレッドを利用し近い処理をさせることにしました。
$ vi thread_test.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *thread_function1( void *ptr );
void *thread_function2( void *ptr );
int main(void){
pthread_t thread1, thread2;
useconds_t tick1 = 200000;
useconds_t tick2 = 2000000;
pthread_create( &thread1, NULL, thread_function1, (void *) &tick1);
pthread_create( &thread2, NULL, thread_function2, (void *) &tick2);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
return 0;
}
void *thread_function1(void *ptr){
useconds_t tick = *( int * )ptr;
while(1){
printf("function1\n");
usleep(tick);
}
}
void *thread_function2(void *ptr){
useconds_t tick = *( int * )ptr;
while(1){
printf("function2\n");
usleep(tick);
}
}
コンパイルします
$ gcc thread_test.c -pthread
実行
$ ./a.out
しかし、これでは共有資源を利用したプログラムを書いた場合取り合いになり下手をするとデータが失われたりする場合があるため排他制御するようにします。
$ vi thread_test.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *thread_function1( void *ptr );
void *thread_function2( void *ptr );
pthread_mutex_t mutex;
pthread_cond_t cond;
int count = 0;
useconds_t tick1 = 200000;
useconds_t tick2 = 2000000;
int main(void){
pthread_t thread1, thread2;
pthread_mutex_init(&mutex, NULL);
pthread_create( &thread1, NULL, thread_function1, (void *) &tick1);
pthread_create( &thread2, NULL, thread_function2, (void *) &tick2);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
void *thread_function1(void *ptr){
useconds_t tick = *( int * )ptr;
while(1){
pthread_mutex_lock(&mutex);
printf("function1 %d\n",count++);
pthread_mutex_unlock(&mutex);
usleep(tick);
}
}
void *thread_function2(void *ptr){
useconds_t tick = *( int * )ptr;
while(1){
pthread_mutex_lock(&mutex);
printf("function2 %d\n",count++);
pthread_mutex_unlock(&mutex);
usleep(tick);
}
}
コンパイルします
$ gcc thread_test.c -pthread
実行
$ ./a.out
function2 0
function1 1
function1 2
function1 3
function1 4
function1 5
function1 6
function1 7
function1 8
function1 9
function1 10
function2 11
function1 12
function1 13
function1 14
function1 15
function1 16
function1 17
function1 18
Raspberry PiでAdafruit RGB Negative 16×2 LCD+Keypad Kit for Raspberry Pi – を使ったプログラムをAdafruitの公式ライブラリを使い書いてみました。
シールドの組立、ライブラリのインストールや使い方は公式の方をご覧ください。
下記のソースコードはRasbperry Piの時間とインターフェイス毎のIPアドレスをLCDに表示します。
インターフェイス毎のローカルIPアドレスを取得するために”netifaces”ライブラリを使用しております。
$ apt-get install python-netifaces
/LCDディレクトリを作成し公式ライブラリを入れておきます。
$ sudo mkdir /LCD
$ sudo vi /LCD/MENU_LCD.py
#!/usr/bin/env python
from netifaces import interfaces, ifaddresses, AF_INET
from time import sleep
from Adafruit_I2C import Adafruit_I2C
from Adafruit_MCP230xx import Adafruit_MCP230XX
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
from IPaddr_LCD import IPaddr_LCD
from DateTime_LCD import DateTime_LCD
import smbus
lcd = Adafruit_CharLCDPlate(busnum = 1)
class MENU_LCD():
def get_const_list(self):
const_list = []
ip = IPaddr_LCD()
time = DateTime_LCD()
const_list.append(ip)
const_list.append(time)
return const_list
def print_progress(self, sleep_time, message):
lcd.clear()
lcd.message(message)
sleep(sleep_time)
self.print_lcd()
def print_lcd(self):
pointer_id = 0
push_flag = 0
lcd.clear()
lcd.message("Please Push\nRite/Left Button")
const_list = self.get_const_list()
const_list_size = len(const_list) - 1
while 1:
if (lcd.buttonPressed(lcd.RIGHT) or lcd.buttonPressed(lcd.LEFT)):
if (lcd.buttonPressed(lcd.RIGHT)):
if (pointer_id < const_list_size):
pointer_id += 1
else:
pointer_id = 0
if (lcd.buttonPressed(lcd.LEFT)):
if (pointer_id > 0):
pointer_id -= 1
else:
pointer_id = const_list_size
push_flag = 1
const_list[pointer_id].title()
if (push_flag > 0 and lcd.buttonPressed(lcd.SELECT)):
const_list[pointer_id].print_lcd()
break
if (push_flag > 0 and lcd.buttonPressed(lcd.UP)):
break
if (push_flag > 0 and lcd.buttonPressed(lcd.DOWN)):
break
sleep(.2)
return self.print_progress(1, "Reinitializeing\nPlease wate....")
if __name__ == '__main__':
try:
menu = MENU_LCD()
menu.print_progress(3, "Initializeing\nPlease wate....")
menu.print_lcd()
except KeyboardInterrupt:
print("Exit\n")
$ sudo vi /LCD/DateTime_LCD.py
#!/usr/bin/env python
import datetime
import locale
from time import sleep
from Adafruit_I2C import Adafruit_I2C
from Adafruit_MCP230xx import Adafruit_MCP230XX
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
import smbus
lcd = Adafruit_CharLCDPlate(busnum = 1)
class DateTime_LCD():
def title(self):
lcd.clear()
lcd.message("Raspberry Pi\nDate Time")
return
def print_lcd(self):
while 1:
d = datetime.datetime.today()
time = d.strftime("Date %Y/%m/%d\nTime %H:%M:%S")
lcd.clear()
lcd.message(time)
if (lcd.buttonPressed(lcd.RIGHT)):
break
if (lcd.buttonPressed(lcd.LEFT)):
break
sleep(.2)
return
if __name__ == '__main__':
try:
time = DateTime_LCD()
time.print_lcd()
except KeyboardInterrupt:
print("Exit\n")
$ sudo vi /LCD/IPaddr_LCD.py
#!/usr/bin/env python
from netifaces import interfaces, ifaddresses, AF_INET
from time import sleep
from Adafruit_I2C import Adafruit_I2C
from Adafruit_MCP230xx import Adafruit_MCP230XX
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
import smbus
lcd = Adafruit_CharLCDPlate(busnum = 1)
class IPaddr_LCD():
def title(self):
lcd.clear()
lcd.message("Raspberry Pi\nIP Address")
return
def get_ip_list(self):
ipaddr_list = []
for ifaceName in interfaces():
nic_ip_list = []
addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )]
nic = '%s' % (ifaceName)
ip = '%s' % (', '.join(addresses))
nic_ip_list.append(nic)
nic_ip_list.append(ip)
ipaddr_list.append(nic_ip_list)
return ipaddr_list
def print_lcd(self):
pointer_id = 0
lcd.clear()
lcd.message("Please Push\nUp/Down Button")
while 1:
if (lcd.buttonPressed(lcd.UP) or lcd.buttonPressed(lcd.DOWN)):
ipaddr_list = self.get_ip_list()
ipaddr_list_size = len(ipaddr_list) - 1
if (lcd.buttonPressed(lcd.UP)):
if (pointer_id < ipaddr_list_size):
pointer_id += 1
else:
pointer_id = 0
if (lcd.buttonPressed(lcd.DOWN)):
if (pointer_id > 0):
pointer_id -= 1
else:
pointer_id = ipaddr_list_size
lcd.clear()
lcd.message(ipaddr_list[pointer_id][0] + "\n" + ipaddr_list[pointer_id][1])
if (lcd.buttonPressed(lcd.RIGHT)):
break
if (lcd.buttonPressed(lcd.LEFT)):
break
sleep(.2)
return
if __name__ == '__main__':
try:
ip = IPaddr_LCD()
ip.print_lcd()
except KeyboardInterrupt:
print("Exit\n")
コマンド用の実行ファイルを作成しておきます
$ sudo vi /LCD/LCD_PRINTER
#!/usr/bin/env python
from MENU_LCD import MENU_LCD
if __name__ == '__main__':
try:
menu = MENU_LCD()
menu.print_progress(3, "Initializeing\nPlease wate....")
menu.print_lcd()
except KeyboardInterrupt:
print("Exit\n")
実行権限を与えどこからでもパスが通るように”/usr/bin/”の中にシンボリックを貼っておきます。
$ sudo chmod 700 /LCD/LCD_PRINTER
$ sudo ln -s /LCD/LCD_PRINTER /usr/bin/LCD_PRINTER
せっかくなので起動スクリプトも書いてみました。
$ sudo mkdir /LCD/init.d/
$ sudo vi /LCD/init.d/lcd_printer
#!/bin/sh
### BEGIN INIT INFO
# Provides: LCD_PRINTER
# chkconfig: 2345 91 91
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: LCD_PRINTER daemon script.
### END INIT INFO
. /lib/lsb/init-functions
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/LCD_PRINTER
DAEMON_NAME=`basename $DAEMON`
PIDFILE="/var/run/lcd_printer.pid"
set -e
start() {
log_daemon_msg "Starting $DAEMON_NAME"
if ! start-stop-daemon --stop --quiet --pidfile ${PIDFILE} --signal 0; then
start-stop-daemon --start --pidfile ${PIDFILE} --make-pidfile --quiet --background --exec ${DAEMON}
log_end_msg $?
else
echo -n " already running."
log_end_msg 1
fi
}
stop() {
log_daemon_msg "Stopping $DAEMON_NAME"
start-stop-daemon --stop --pidfile ${PIDFILE}
log_end_msg $?
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status_of_proc -p $PIDFILE $DAEMON $DAEMON_NAME && exit 0 || exit $?
;;
*)
echo $"Usage: $DAEMONNAME {start|stop|restart|status}" >&2
exit 1
;;
esac
exit 0
実行権限を与え、起動スクリプトとして”/etc/init.d/”の中にシンボリックを貼っておきます。
$ sudo chmod 755 /LCD/init.d/lcd_printer
$ sudo ln -s /LCD/init.d/lcd_printer /etc/init.d/lcd_printer
起動するか確認してみます。
$ sudo service lcd_printer start
自動起動するように設定します。
$ sudo update-rc.d lcd_printer defaults
自動起動するか確認します。完全に電源を落とすためrebootではなくシャットダウンして電源を入れます。
$ sudo shutdown -h now
余談ですがRedHat系はchkconfigで設定するのですがDebian系は違うのですね・・・勉強になりました。
GPIOを使うのに標準のライブラリよりも使い勝手のよさそうなライブラリを発見したためこちらを使うことにした。
$ sudo apt-get install git python-dev python-setuptools # 必要なパッケージをインストールする
$ cd /tmp # 当然だが/tmpは再起動すると中身が削除されるため注意する
$ git clone https://github.com/WiringPi/WiringPi-Python.git
$ cd WiringPi-Python
$ git submodule update –init
$ sudo cp WiringPi/wiringPi/*.h /usr/include/ # ヘッダーファイルが無いと怒られるためコピーしておく
$ sudo python setup.py install
$ cd
サンプルコード
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import wiringpi
import time
if __name__ == '__main__':
io = wiringpi.GPIO(wiringpi.GPIO.WPI_MODE_GPIO)
io.pinMode(23,io.OUTPUT)
io.digitalWrite(23,io.HIGH)
while True:
io.digitalWrite(23,io.LOW) # on
time.sleep(1)
io.digitalWrite(23,io.HIGH) # off
time.sleep(1)
参考サイト
Raspberry Pi GPIO with Python (without root) – Sirmc.net
fatal error: wiringPi.h: No such file or directory · Issue #7 · WiringPi/WiringPi-Python · GitHub
昨日うっかりBccとCcを間違えてしまう大失態を演じてしまったため簡易ながら不特定多数にBccでメールを一斉配信してくれるスクリプトをPerlでサクッと書いてみました。
そしてどうせ書いたのならば久々に公開して有意義に使っていただこうと思い公開します。
コマンドラインベースで動けばいいかなということで機能自体には特にこだわりは無いのですが必要のある方がおりましたらご自由にコピーしてお使いください。
※ 当スクリプトを利用するにはPerlモジュールのインストールができるレベルの知識を必要とします。
実行用スクリプト
# vi infoEmail.pl
#!/usr/bin/perl
use utf8;
use strict;
use warnings;
binmode(STDOUT, ":utf8");
require "infoEmail.pm";
#
# メールマガジン配信スクリプト
#
my $mm = infoEmail->new();
my $mime = $mm->mailer();
print $mime->as_string;
print '*' x 50 . "\n";
print "上記の内容で配信してもよろしいですか? (y/N)\n";
print '*' x 50 . "\n";
print "> ";
my $input = <STDIN>;
chomp($input);
if($input eq 'y' || $input eq 'yes'){
$mm->sendmail($mime);
print "メールを配信しました\n";
}else{
print "メールの配信をキャンセルしました\n";
}
モジュール(プログラム本体)
# vi infoEmail.pm
#!/usr/bin/perl
package infoEmail;
use utf8;
use strict;
use warnings;
use Config::Simple;
use Mail::Krohn;
use Mail::Krohn::Sendmail;
use Email::MIME;
use Email::MIME::Creator;
use Encode;
sub new {
my $class = shift;
my $cfg = new Config::Simple('./infoEmail.conf') or die Config::Simple->error();
my $self = {
from => $cfg->param('From'),
to => $cfg->param('To'),
subject => $cfg->param('Subject'),
x_mailer => $cfg->param('X-Mailer'),
bccfilepath => $cfg->param('BccFilePath'),
bodyfilepath => $cfg->param('BodyFilePath')
};
return bless $self , $class;
}
sub mailer {
my $self = shift;
my $bcc = $self->read_config($self->{ bccfilepath });
my $body = $self->read_config($self->{ bodyfilepath });
my $from = $self->{ from };
my $to = $self->{ to };
my $subject = $self->{ subject };
my $x_mailer = $self->{ x_mailer };
my $mime = Email::MIME->create(
header => [
From => encode('MIME-Header-ISO_2022_JP' => decode('utf-8',$from)),
To => encode('MIME-Header-ISO_2022_JP' => decode('utf-8',$to)),
Bcc => encode('MIME-Header-ISO_2022_JP' => decode('utf-8',$bcc)),
Subject => encode('MIME-Header-ISO_2022_JP' => decode('utf-8',$subject)),
'X-Mailer' => decode('utf-8',$x_mailer),
],
attributes => {
content_type => 'text/plain',
charset => 'ISO-2022-JP',
encoding => '7bit',
},
body => encode('iso-2022-jp' => decode('utf-8',$body)),
);
return $mime;
}
sub sendmail {
my $self = shift;
my $mime = shift;
my $mailer = Mail::Krohn->new();
$mailer->send($mime);
return 0;
}
sub read_config {
my $self = shift;
my $file_path = shift;
open(my $fh, "<", $file_path) || die("Can not open file $file_path");
my $file_contents;
while( my $line = readline $fh ){
$file_contents .= $line;
}
chomp($file_contents);
return $file_contents;
}
1;
設定ファイル
# vi infoEmail.conf
############################################################ # メールマガジン設定ファイル ############################################################ # 送信元 From = "ぼっちちゃん" <めーる@あどらあ> # 送信先 To = "ぼっちちゃん" <めーる@あどらあ> # 件名 Subject = ぼっちちゃんと愉快な仲間たちめーりんぐりすと # メーラー名 X-Mailer = My Best Friends Mailing List ############################################################ # 送り先リストの記述されたファイル BccFilePath = ./infoEmail_bcc.tmp # 本文の記述されたファイル BodyFilePath = ./infoEmail_body.tmp ############################################################
配信用メール本文
# vi infoEmail_body.tmp
お友達100人できるかな? ======================================= "ぼっちちゃん" <めーる@あどらあ~> ぼっちちゃんと愉快な仲間たちめーりんぐりすと =======================================
配信対象のアドレスリスト
# vi infoEmail_bcc.tmp
おともだち1@あどらあ, めーる2@あどらあ, めーる3@あどらあ, めーる4@あどらあ, めーる5@あどらあ
久々にPerl触ったらだいぶ忘れてました(^_^;)
参考サイト
第20回 Email::Sender:メールを送信する:モダンPerlの世界へようこそ|gihyo.jp … 技術評論社
メールをEmail::Sendを利用し送信しようとしたところ下記のように色々と怒られたため調べてみたところ
スクリプト起動時にReturn::Value::NO_CLUCKに値を入れれば良いということが分かったが実にスマートではないので代わりになるモジュールを探してみた
Return::Value is deprecated at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 13
require Return/Value.pm called at /usr/lib/perl5/site_perl/5.8.8/Email/Send.pm line 11
Email::Send::BEGIN() called at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 0
eval {...} called at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 0
require Email/Send.pm called at infoEmail.pl line 6
main::BEGIN() called at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 0
eval {...} called at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 0
必要なモジュールをインストールする
# cpan install parent
# cpan install Class::Accessor::Lite
# cpan install Mail::Krohn
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Mail::Krohn;
use Mail::Krohn::Sendmail;
use Email::MIME;
use Email::MIME::Creator;
use Encode;
MAIN:{
my $mime = Email::MIME->create(
header => [
From => 'そうしんもとめーる@あどれす',
To => 'そうしんもとめーる@あどれす',
Bcc => 'そうしんさきめーる@あどれす',
Subject => Encode::encode( 'MIME-Header-ISO_2022_JP', 'テストメールです' ),
'X-Mailer' => 'TestMailer',
],
attributes => {
content_type => 'text/plain',
charset => 'iso-2022-jp',
encoding => '7bit',
},
parts => [
Encode::encode( 'iso-2022-jp', 'でばっぐおいしー!!' ),
],
);
my $mailer = Mail::Krohn->new();
$mailer->send($mime);
}
参考サイト
Email::MIME::CreatorとEmail::Sendでメール送信
[Perl]Email::SendつかったらReturn::Valueにdeprecatedだと怒られた
# cpan install Perl::OSType <- make testでエラーが起きる # yum --enablerepo=epel install perl-Perl-OSType # cpan install Module::Build # cpan install Module::Pluggable # cpan install Email::Send
$ echo “xmms -p” |sudo at 0900
warning: commands will be executed using /bin/sh
Cannot open lockfile /var/spool/cron/atjobs/.SEQ: No such file or directory
atdを再起動させても解決しなかったため手動でロックファイルを作成したところ解決しました
$ sudo touch /var/spool/cron/atjobs/.SEQ
$ sudo chown daemon:daemon /var/spool/cron/atjobs/.SEQ
MacBook Air Late 2011 のグラフィックカードはnvidiaではなくi5に組み込まれているGPUらしいのでIntel HD Graphics 3000 384 MBを使っているようです。
調べたところリポジトリを追加することで手軽にインストールできるようなのでメモしておきます。
sudo add-apt-repository ppa:glasen/intel-driver
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install linux-image-generic-lts-backport-natty linux-headers-generic-lts-backport-natty
調べたところライセンスが関係して機能を削っているようですね。
使えるようにするにはソースからビルドする時にオプションを追加する方法等あるようですがすごくめんどくさい・・・・
そんな訳で、他の方法を探してみました。
非公式リポジトリのMedibuntuには予めオプションを追加してビルドしたパッケージが用意されているようなのでそれを利用したいと思う。
リポジトリの追加
$ sudo wget http://www.medibuntu.org/sources.list.d/`lsb_release -cs`.list –output-document=/etc/apt/sources.list.d/medibuntu.list && sudo apt-get -q update && sudo apt-get –yes -q –allow-unauthenticated install medibuntu-keyring && sudo apt-get -q update
ffmpegを再インストール
$ sudo apt-get -reinstall install ffmpeg libavcodec-extra-53
※ Ubuntu11.10のffmpegはlibavcodec-extra-52ではなくlibavcodec-extra-53のようなのでこちらを指定する。
これで、Unknown encoder ‘libfaac’が出なくなると思う。
最近のコメント