アップデートしたら、皇紀の表示が西暦になった orz
単に表示部分で表示データひったくって660年足してるだけだが、アップデートにも強い改造法を編み出さねば。
I know who Iam.
アップデートしたら、皇紀の表示が西暦になった orz
単に表示部分で表示データひったくって660年足してるだけだが、アップデートにも強い改造法を編み出さねば。
会社でATCOMのIP08の設定をやった。
同僚が設定していて、転送設定ができないとの事で、わしが見る事になった。
BAPsのfirmwareアップデート済みだったが、#を押しても”Transfer”っておねいちゃんの声が聞こえず、DTMFがスルーされてる感じ。
シリアル端末で、
ipkg remove asterisk-1.4.4
ipkg install asterisk-1.4.20
ってasteriskのバージョン上げても変わらず、しまいには、Grandstreamの電話機では繋がらず、ソフトフォンなら繋がるという謎の現象になってしまったので、BAPsのファームウエアは放棄!
ATCOMのDownload centerから、ファームウエアを落っことしてアップデートすると、転送の#押下は認識するようだが、電話がブチ切られる。
asterisk -vvvr でモニタすると、pbx-transferの音声ファイルが開けませんとかいうログが出ていた。
ファイルの位置を調べると、
/persistent/asterisk/sounds
とかにあるみたいで、
/var/lib/asteriskのディレクトリで、
ln -s /persistent/asterisk/sounds .
とシンボリックリンク貼ってやったら動いた。
AsteriskNowは、asteriskを作ったdigiumが作っただけあって、非常に良くできている。
パッケージのビルドさえ完璧であれば、GUIで設定できて、簡単なのだが、そうでない場合は、Linux弄る知識が無いと、とても触れたもんじゃない。ちょっと残念な製品だな。
バリスタと言っても、コーヒーを淹れる訳ではなくて、Variable resistorの略。
会社でソレノイドバルブを動かす回路を作ったが、RBIO-2Uのリレーでカチカチ作動させていると、RBIO-2Uでリセットが掛かる。
ソレノイドバルブの給電を止めた途端にリセットするので、過電流のせいでもないから、共立電子さんにWebフォームで「初期不良っぽいですけど交換して貰えますか?」って問い合わせてしまった。
付属マニュアルをじっくり読んでいて、大容量リレーを駆動させる回路ってのを読んでたら、バリスタを入れないと、リレーのサージによってマイコンが暴走するって書いてあった。
電子工作初心者だから、バリスタを入れないといけないなんて全然知らんかった。
Wikipedia見たら、
「直流モーターやソレノイドなどといった直流の誘導性負荷は、電源を切った際に自己誘導作用による高圧の逆起電圧を生じる。」
って、ソレノイドバルブの電源を切った途端に発生してるから、まんまこの現象だよ orz
シグナルハンドラ内では、malloc()やprintf()系が使えず、thread safe な関数しか呼べないので、シグナルハンドラではキューに記録して、メインルーチン内でキューを取り出して処理する形式を考えてみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
#include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <signal.h> #include <ucontext.h> #include <string.h> #include <time.h> #include <unistd.h> #define TM_ONESHOT 1 #define TM_INTERVAL 0 #define QUEMAX 256 timer_t timerid; volatile static int head = 0,tail=0; volatile static int event_queue[QUEMAX]; static int sigint_sigevent(int signum, siginfo_t *info, void *ctx){ int ret; ret = 0; if(signum>0){ // シグナルによる呼び出し event_queue[tail++] = signum; if(tail>=QUEMAX){ tail = 0; } if(head==tail){ head++; if(head>=QUEMAX){ head = 0; } } }else{ if(head!=tail){ ret = event_queue[head++]; if(head>=QUEMAX){ head = 0; } } } return ret; } int set_signal_handler(void){ struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_SIGINFO|SA_RESTART; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask,SIGINT); sigaddset(&sa.sa_mask,SIGRTMIN+1); sa.sa_sigaction = (void *)sigint_sigevent; if(sigaction(SIGINT,&sa,(struct sigaction *)NULL)) { perror("sigaction error"); exit(1); } sa.sa_sigaction = (void *)sigint_sigevent; if(sigaction(SIGRTMIN+1,&sa,(struct sigaction *)NULL)) { perror("sigaction error"); exit(1); } return 0; } int set_timer_count(int oneshot,int sec,int nsec){ struct itimerspec ispec; if(oneshot!=TM_INTERVAL){ ispec.it_interval.tv_sec = 0; ispec.it_interval.tv_nsec = 0; }else{ ispec.it_interval.tv_sec = sec; ispec.it_interval.tv_nsec = nsec; } ispec.it_value.tv_sec = sec; ispec.it_value.tv_nsec = nsec; if(timer_settime(timerid, 0, &ispec, NULL) < 0){ perror("timer_settime error"); exit(1); } return 0; } int init_timer(void){ struct sigevent se; memset(&se, 0, sizeof(se)); se.sigev_notify = SIGEV_SIGNAL; se.sigev_signo = SIGRTMIN+1; if(timer_create(CLOCK_REALTIME, &se, &timerid) < 0){ perror("timer_create error"); exit(1); } return 0; } int main(int argc, char** argv) { init_timer(); set_timer_count(TM_INTERVAL,0,500000000); set_signal_handler(); while(1){ printf("%d:%d sigevent:%d\n",head,tail,sigint_sigevent(0,NULL,NULL)); while(usleep(50000)!=0); } return 0; } |
実際に動作させてみると、0.5秒毎にタイマーが起動してキューにシグナル番号が積まれるが、メインルーチンで、0.05秒毎にキューをチェックするので、キューに積まれるシグナル番号は殆ど増える事は無く処理される。
30:30 sigevent:0
30:30 sigevent:0
30:30 sigevent:0
30:30 sigevent:0
30:30 sigevent:0
30:30 sigevent:0
31:31 sigevent:35
31:31 sigevent:0
31:31 sigevent:0
31:31 sigevent:0
31:31 sigevent:0
31:31 sigevent:0
31:31 sigevent:0
実行すると、こんな感じ。
表示しているのは、
キュー先頭(head):キュー末尾(tail) sigevent:シグナル番号
というフォーマットになっている。
しかし、Ctrl-Cを押しっぱなしにすると、メインルーチンでは、usleep()から抜けないので、キューにSIGINTが積まれまくる。
130:130 sigevent:0
131:131 sigevent:35
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C132:42 sigevent:2
133:42 sigevent:2
134:42 sigevent:2
135:43 sigevent:2
136:43 sigevent:2
137:43 sigevent:2
138:43 sigevent:2
139:43 sigevent:2
140:43 sigevent:2
141:43 sigevent:2
142:43 sigevent:2
143:43 sigevent:2
144:44 sigevent:2
145:44 sigevent:35
ちなみにこのキューはオーバーフローすると、古いデータを捨てるようになっている。オーバフローを確認する方法は作ってない(笑)。
Ctrl-Cを離すと、メインルーチンでキューに溜まっているデータをせっせと処理し、キューの先頭のheadの数字と末尾のtailの数字がみるみる接近していくのが見て取れる。
これで、メインルーチンでシグナル割り込みを検知し、malloc()、printf()使いたい放題。
難点は、ちょっとリアルタイム性が悪くなるという点だな。
このプログラムはリアルタイムライブラリを使うので、コンパイル時には -lrt オプションがいる。
1 2 3 |
while(1){ sleep(1); } |
というC言語のプログラムだと、1秒待ってループってな感じだけど、create_timer()とかでタイマー作ってシグナル割り込みがあると、時間に関わらず、シグナルが発生した時点で、sleep()から抜けるんやな。
メイン処理で、sleep()で1秒間隔、タイマーの割り込みで0.5秒間隔でシグナルが発生するとすると、sleep()は必ず-1の戻り値で抜けてしまい、メイン処理は0.5秒間隔でループするんだな。
シグナルが来たら、メイン処理で何かするって組み方だと、sleep()がシグナルで抜けてくれた方がデッドロックが無くて良さそうだ。
先々週に上側やって、今日は下側の歯石取り。
虫歯も歯周病も細菌が原因で、口内細菌が安定しない幼児期に親から伝染され、一生、虫歯や歯周病の可能性に怯えながら生きていく事になる。
パーフェクトペリオってので治療すれば、歯周病原因菌を撲滅でき、そもそも歯周病にならなくなるから、やってみたい気がするな。
社長にRBIO-2Uを買ってもらった。
USBインターフェースだが、Ubuntu 9.04 Desktopのマシンに繋いだら、USB Serialportとしてサックリ認識。
ターミナルで”PCR01″とかコマンド送るとリレーがカチカチ作動する。
使い方は色々あるが、例えば、パソコンの温度が高い時に、外付けの強力な電動ファンのスイッチを自動で入れるとか、炭酸ガスボンベのソレノイドバルブを開閉するとか応用次第で色々楽しそうな事ができそうだ。
リレー出力10、入力4だが、入力ポートが結構おもしろい。GNDと入力の線を短絡させて、RBIOに”FB0″とコマンドを送ると”0″と返ってきて、開放状態だと、”255″という文字列がシリアルから返ってくる。
これも色々と応用が効くが、出力と入力と合わせて、電動ねずみ取り機とか作れるな(笑)
餌のチーズに触れると、入力で検知して、リレー出力で扉をガシャンと電動で閉じるってな具合。果てしなく無用の長物感がするが、まあパソコンで入力の判断と出力ができるってのが色々応用できて、おもちゃとして面白い。