なんでも作っちゃう、かも。

Arduino/Make/フィジカルコンピューティング/電子工作あたりで活動しています。スタバの空きカップを使ったスタバカップアンプなど製作。最近はもっぱらArduinoと3Dプリンタの自作に興味があります。

iPod shuffle充電器

Posted by arms22 on 2008年04月28日 3  0

Minty Boostを参考にiPod shuffle充電器の製作をはじめました。Minty Boostはミントの缶に入った非常にコンパクトでパワフルなUSB充電器です。MP3やカメラ、携帯電話などUSBポートで充電可能な機器なら使えるはずです。

オリジナルの回路ではVBUS用5Vを生成する為に昇圧ICのMAX755を使用しています。MAX755は入手が難しそうなので、代わりにHT7750Aを使う事にしました。

HT7750Aは入力0.9V~6.0V、出力5.0V200mAのPFM Step-up DC/DC Converterです。Aのないバージョンもあって、そちらは最大100mAしか取り出せないので、余裕がまったくありません。

データシートの回路図どおり、ブレッドボードに実装しテストしました。
ipod_shuffle_charger.jpg

USBポートにiPod shuffleに接続するとオレンジ色のLEDが点滅、、、するはずですが、点滅しませんでした(緑色のLEDが点滅)。
Appleのサポートページによると、低電力タイプまたは電力を供給しないUSBポートに接続した場合、iPod shuffleは充電されないようです。iPod shuffleのファームウェアのバージョンを1.1に戻せば充電できるようですが、1.1.5にアップデート済みのiPod shuffleを1.1にダウングレードすることはできませんでした。ざんねん。。

Minty Boost Small battery-powered USB charger
http://www.ladyada.net/make/mintyboost/index.html

スポンサーサイト

ストロー型LEDスポットライト

Posted by arms22 on 2008年04月20日 0  0

さて、今週(?)のウィークエンドプロジェクトは「ストロー型LEDスポットライト」の製作だ!仕事から帰って、夜に半田付けする人にうってつけのアイテムになるだろう。

straw_led_spot_light_cup.jpg

最初、白色LEDを点灯させる為にHT7750を使う事を考えていたが、部品点数が多く(HT7750、コイル、キャパシタ、ダイオードなど7点)、ストローの中にすべておさめるのが難しかった。
Sim's blogさんが非常にコンパクトなJoule Thiefのコイルの作り方を発見されていたので、それを使ってJoule Thiefをストローに入れることを思いついた。

ストロー型LEDスポットライトの製作に必要な部品はこれだ。
※写真上側はJoule Thiefの部品4点、下側はHT7750の部品7点。
straw_led_spot_light_parts.jpg

  • ストロー
    スターバックスかモスで只でもらえるよ。モスの首が曲がるタイプがおすすめ。
  • 白色LED
    ストローと同じ直径のLEDを用意すること。径が大き過ぎたり小さ過ぎてもダメだよ。
  • 100uHアキシャルリードマイクロインダクタ
    ストローに入るならなんでも。
  • NPNトランジスタ2SC2655
  • 抵抗1KΩ

マイクロインダクタに0.2mmのUEW線を30~40回巻く。マイクロインダクタはつるつるしている。ヤスリで削って1面を平にしておくとUEW線が巻き易くなる。トランジスタは2SC1815でも点くが、その場合、ベース抵抗を100Ωにする。ちょっと暗い。
straw_led_spot_light_brb.jpg

ビニル線で半田付けした状態(左)。ストローに入れた状態(右)。
straw_led_spot_light_wire.jpg straw_led_spot_light_in_straw.jpg

ストローの首を曲げるとON、伸ばすとOFFという機構を入れたかったが、うまい方法が見つからなかった。
それと、トランジスタが熱い。かろうじてストローは溶けていないが、燃えてしまっても困るので何らかの対策が必要だ。

革新的発明と製品情報: ストローライト
http://www.j-tokkyo.com/2008/04/10/7418.html
1.5V電池で白色LEDを点ける(3)
http://blog.goo.ne.jp/sim00/e/7434f4d51a8bcb642179eb0a3bdba48b
Weekend Projects with Bre Pettis: Make a Joule Thief
http://www.evilmadscientist.com/article.php/joulethief

MPPT太陽電池充電器(5)

Posted by arms22 on 2008年04月20日 19  0

しばらくブレッドボードでテストしていたMPPT太陽電池充電器ですが、ユニバーサル基板に実装してみました。段ボールが少しださいですが、全体は次のようになりました。

mppt_zentai

基板の表と裏です。上に降圧回路、下にPICとPICの電源。LEDも2個追加した。
mppt_kiban_omote mppt_kiban_ura.jpg

最終回路は次のようになりました。若干、回路定数が変わっただけで、大きく変わった箇所はありません。
mppt_sch_4_19

降圧回路の効率を上げようとして色々テストしたコイルたち。サイズと効率面で220uH1Aのコイルを選びました。
mppt_many_coil.jpg


MPPT太陽電池充電器のソースコード一式です。
http://xfind.hp.infoseek.co.jp/electric/mppt/mppt080419.zip

  • 電池電圧1.45V未満で充電開始
  • 開放電圧4V以上で充電開始
  • 充電中は赤LED点滅
  • 開放電圧の66%を動作点とする
  • 2秒間はMPPT動作を継続する
  • 2秒経過後、PWMデューティが95%以上、2%未満の時、開放電圧を再チェック
  • 電池電圧1.45以上で充電終了
  • 充電完了、緑LED点灯

テスターの内部抵抗

Posted by arms22 on 2008年04月14日 0  0

トラブルシューターさんの記事をみて気になったので調べてみました。

  • アナログテスター MASTECH 1015B
    250mAレンジ 4Ω
    10mAレンジ 87.6Ω
  • アナログテスター Kaise KF-2A
    250mAレンジ 2.5Ω
    10mAレンジ 50Ω

手持ちのデジタルテスターには電流測定機能がありません、、買ってから気がつきました。。orz
250mAレンジ100mA時、1015Bで0.4V、KF-2Aで0.25Vドロップすることになります。MPPT太陽電池充電器の充電電流や太陽電池電流をこれらのテスターで計っていたのですが、思いのほか電気を消費していたようです。
これから電流を測定する時はこれらの内部抵抗の値を考慮しないと。。

トラブルシューター: テスターの内部抵抗は?
http://htanaka.blogzine.jp/namahage/2008/03/post_5f98.html

C言語でコルーチン(co-routine)(4)

Posted by arms22 on 2008年04月12日 0  0

C言語でコルーチンを実装してみる、その4。今回でコルーチンの連載(?)は最後です。最後にコルーチンを使った協調型スレッドライブラリを実装します。さっそくサンプルコードから見ていきましょう。

int thread1_count=0;
int thread1_func(coroutine_t coro)
{
co_begin(coro);
while(1){
thread1_count++;
co_yield();
}
co_end;
}

int thread2_count=0;
int thread2_func(coroutine_t coro)
{
co_begin(coro);
while(1){
thread2_count++;
co_yield();
}
co_end;
}

int thread3_count=0;
int thread3_func(coroutine_t coro)
{
co_begin(coro);
while(1){
thread3_count++;
co_yield();
}
co_end;
}

int main(int argc, char *argv[])
{
struct cothread_scheduler schdlr;
cothread_t thread1;
cothread_t thread2;
cothread_t thread3;
int thread1_stack[32];
int thread2_stack[32];
int thread3_stack[32];

/* 協調型スレッド作成 */
thread1 = cothread_create(thread1_func,(co_addrword_t)1,
thread1_stack,sizeof(thread1_stack));
thread2 = cothread_create(thread2_func,(co_addrword_t)2,
thread2_stack,sizeof(thread2_stack));
thread3 = cothread_create(thread3_func,(co_addrword_t)3,
thread3_stack,sizeof(thread3_stack));

/* スケジューラ作成 */
cothread_scheduler_init(&schdlr);

/* スレッドアタッチ */
cothread_scheduler_attach(&schdlr,thread1);
cothread_scheduler_attach(&schdlr,thread2);
cothread_scheduler_attach(&schdlr,thread3);

/* 実行 */
cothread_scheduler_run(&schdlr);
printf("thread1_count %d, thread2_count %d, thread3_count %d?n",
thread1_count,thread2_count,thread3_count);
cothread_scheduler_run(&schdlr);
printf("thread1_count %d, thread2_count %d, thread3_count %d?n",
thread1_count,thread2_count,thread3_count);
cothread_scheduler_run(&schdlr);
printf("thread1_count %d, thread2_count %d, thread3_count %d?n",
thread1_count,thread2_count,thread3_count);
}
実行結果は次のとおり。
% a.exe
thread1_count 1, thread2_count 1, thread3_count 1
thread1_count 2, thread2_count 2, thread3_count 2
thread1_count 3, thread2_count 3, thread3_count 3
コルーチン関数の書き方は何も変わっていない。コルーチンの作成関数が協調型スレッドの作成関数に置き換わっているのがわかる。順番に見ていこう。
  • cothread_create()
    協調型スレッドの作成関数だ。内部でco_create関数を呼び出す。引数はco_create関数と同じだ。第1引数にコルーチン関数のアドレスを渡す。戻り値としてcothread_t型にキャストしたスタックのアドレスを返す。
  • cothread_scheduler_init()
    スレッドスケジューラの初期化関数だ。スケジューラの初期化を行う。今回実装したスケジューラはアタッチされたスレッドを順番に実行するラウンドロビン方式を採用している。
  • cothread_scheduler_attach()
    スケジューラにスレッドをアタッチする関数だ。
  • cothread_scheduler_run()
    アタッチされたスレッドを1つ1つ実行する。すべてのスレッドを1度実行した後、処理を呼び出し元に返す。

協調型スレッドを含むコルーチンライブラリの全ソースコードはこちら。
http://xfind.hp.infoseek.co.jp/electric/coroutine/coroutine_20080410.zip

C言語でコルーチン(co-routine)(3)

Posted by arms22 on 2008年04月11日 0  0

C言語でコルーチンを実装してみる、その3。
前回でローカル変数の問題、状態を制御できない問題は解決した。今回はコルーチンで値を返す処理を追加した。例によって、まずはサンプルコードから。

int num_gen(coroutine_t coro)
{
co_begin_rettype(coro,int);
co_local_valiables{
int number;
};
co_local.number = 0;
while(1){
co_yield_ret(co_local.number++);
}
co_end;
}

int main(int argc, char *argv[])
{
coroutine_t gen1;
coroutine_t gen2;
int stack1[128];
int stack2[128];
int i;

gen1 = co_create(num_gen,0,stack1,sizeof(stack1));
gen2 = co_create(num_gen,0,stack2,sizeof(stack2));

for(i=0;i<10;i++){
co_call(gen1);
co_call(gen2);
printf("gen1 result %d,gen2 result %d\n",
co_get_retval(gen1,int),
co_get_retval(gen2,int));
}
}
実行結果は次の通り。
% a.exe
gen1 result 0,gen2 result 0
gen1 result 1,gen2 result 1
gen1 result 2,gen2 result 2
gen1 result 3,gen2 result 3
gen1 result 4,gen2 result 4
gen1 result 5,gen2 result 5
gen1 result 6,gen2 result 6
gen1 result 7,gen2 result 7
gen1 result 8,gen2 result 8
gen1 result 9,gen2 result 9
num_gen関数はint型の値を、呼び出し毎に1ずつ増やして返す関数だ。今回追加したマクロはco_begin_rettype,co_yield_ret,co_get_retvalだ。順番に見ていこう。
  • co_begin_rettype(coro,int);
    コルーチンの開始と戻り値の型を決める。戻り値のサイズ分、スタックに空きを作る。
  • co_yield_ret(co_local.number++);
    スタックに戻り値を積んで、処理を中断し呼び出しもとに戻る。
  • co_get_retval(gen1,int)
    コルーチンの戻り値を型を指定して取り出す。
気になる(?)実装は次の通り。
#define co_begin_rettype(coro,type) \
type *__return_addr = (type*)((coro)+1); \
co_stack_t __stack_addr = (co_stack_t)(((int)(__return_addr+1)+3)&~3); \
switch((coro)->resume){ \
case CO_INITIALALIZE:;

#define co_yield_ret(value) \
do{ \
*__return_addr=value; \
return(__LINE__); \
case __LINE__:; \
}while(0)

#define co_get_retval(coro,type) \
(*((type*)((coro)+1)))
ローカル変数で使うスタックのアライメントを4バイトに調節している。

C言語でコルーチン(co-routine)(2)

Posted by arms22 on 2008年04月10日 0  0

C言語でコルーチンを実装してみる、その2。
前回のコルーチンマクロではローカル変数が使えない、外部から状態を制御できないという問題があった。今回はそれらの問題を解決してみる。まずはサンプルコードを見てほしい。

int hoge(co_routine_t coro){
co_begin(coro);
co_local_valiables{
int a;
int b;
};
co_local.a = 0;
co_local.b = 0;
printf("arg 0x%x\n",(int)co_get_addrword(coro));
while(1){
printf("a=%d b=%d\n",co_local.a++,co_local.b++);
co_yield();
}
co_end;
}

main{
co_routine_t coro;
int stack[32];
coro = co_create(hoge,0xaa,stack,sizeof(stack));
co_call(coro);
co_call(coro);
co_call(coro);
co_call(coro);
}
実行結果は次のとおり。
% a.exe
arg=0xaa
a=0 b=0
a=1 b=1
a=2 b=2
a=3 b=3
前回のコルーチンマクロから変わった所は、コルーチンの関数定義、co_beginマクロに引数を追加、co_local_variables/co_localマクロの追加、co_create/co_call関数の追加ぐらいだろうか。順番に見ていこう。
  • int hoge(co_routine_t coro)
    今回の実装ではコルーチン関数はco_routine_t型の引数とint型の値を返す必要がある。なもんで、呼び出す度に戻り値が変わる関数を作りたい場合には使えない。
  • co_begin,co_end
    毎度おなじみの"おまじない"。
  • co_local_valiables
    ローカル変数の宣言をここで行う。これらの変数はコルーチンが呼び出されている間は消えることはない。ローカル変数へのアクセスはco_localマクロを経由して行う。co_localは単純にスタックのアドレスをローカル変数用の構造体にキャストしているだけ。
  • co_yield()
    このマクロが呼ばれた時点でコルーチンは処理を中断し、関数を抜ける。次に呼ばれた時は、このマクロの次の行から処理が再開される。
  • coro = co_create(hoge,0xaa,stack,sizeof(stack))
    co_create関数を使ってコルーチンを作成する。第1引数にコルーチン関数のポインタ、第2引数にコルーチン関数に渡す引数、第3引数にスタックのアドレス、第4引数にスタックのサイズを渡す。スタックのサイズは最低、sizeof(関数ポインタ)+sizeof(コルーチン関数に渡す引数)+sizeof(int)分必要。作成に成功したらスタックのアドレスがco_routine_t型にキャストされて返される。失敗した場合は0が返る。
  • co_call(coro)
    コルーチン呼び出す。コルーチンでco_yieldマクロが呼ばれたら処理が返ってくる。
ソースコードは長いので続きに載せておくよ。

そうそう、マクロでちまちまやるのは嫌だという人にはPCL(Portable Coroutine Library)というポータブルなコルーチンライブラリがあるよ。PCLはcontext save/restoreでコルーチンを実現しているよ。setjmp、longjmpを駆使するみたい。

Portable Coroutine Library
http://www.xmailserver.org/libpcl.html

蛍光表示管(VFD)(2)

Posted by arms22 on 2008年04月07日 0  0

またまた蛍光表示管です。共立電子シリコンハウスで1つ50円で買ってきました。データシートは付いてきませんでしたが、裏に型番が書いてありました。LD8164というNECの7セグ蛍光表示管です。7セグといいつつ、10の桁は6つしか端子がありません。上と下のセグメントを1つの端子にまとめています(節約?)。
P1010521.jpg

ネットで検索してもデータシートがみつかりませんでしたが、テキトーに12V印可したら点灯したので、なんとか使えそうです。
ピン数の多い方(下側)の両端がフィラメント端子で、その1つ内側がグリッド端子です。ピン数の少ない方(上側)の両端もグリッド端子です。あとは裏返せばどの端子がどのセグメントかわかります。多分次のような配置になっていると思います。

(上) GAAAAAAAGAAAAAAG
(下)FGAAAAAAAAAAAAAAGF

P1010522.jpg

それと、マキシマム/ダラスセミコンダクタにお願いしていたMAX6920/MAX6921のサンプルが届いた。MAX6920/MAX6921はシリアルインターフェスを備えたVFD駆動ICでそれぞれ12出力、20出力が可能。

MAX6920 - 12出力、76V、シリアルインタフェースVFD管ドライバ
http://japan.maxim-ic.com/quick_view2.cfm/qv_pk/4098

C言語でコルーチン(co-routine)

Posted by arms22 on 2008年04月07日 0  0

C言語でコルーチンを実装してみる。

コルーチン(co-routine)とはプログラミングの構造の一種。サブルーチンがエントリーからリターンまでを一つの処理単位とするのに対し、コルーチンはいったん処理を中断した後、続きから処理を再開できる。接頭辞co-は協調を意味するが、複数のコルーチンが中断/継続により協調動作を行う。

組み込みシステムではよく、複数の処理を同時に行う必要がある。そのような場合、コルーチンが使えれば、処理の記述が楽に行える。switch-caseあるいは関数テーブルなどを駆使すれば、実現することは可能だが、見通しがわるくなる。

コルーチンをサポートする言語にはModula-2、Simula、Icon、Lua、C#がある。マルチスレッドで原理的には同じことができるため、現在はそちらが使われるケースが多い。

組み込みシステムにおいても上記のことは言えるが、小規模なシステムの場合、リソースの制約上、処理1つ1つにタスクを割り当てることができず、1つのタスクで複数の処理を実行するケースも存在する。

今回、紹介するコルーチンはswitch-caseを巧みに利用して実現されている。次のコードは呼び出すごとに"Hello World"がテキトーになっていくHelloWorld関数だ。
void helloworld(void){
co_begin;

printf("hello world!!\n");
co_yield();

printf("hi world!\n");
co_yield();

printf("hi again.\n");
co_yield();

printf("hi\n");
co_yield();

printf(":)\n");
co_end;
}
main(){
helloworld();
helloworld();
helloworld();
helloworld();
helloworld();
}
実行結果は次の通り。
hello world!!
hi world!
hi again.
hi
:)
見慣れないキーワードが三つ。それぞれ簡単に説明すると、
  • co_begin
    コルーチンの開始
  • co_yield()
    処理の中断
  • co_end
    コルーチンの終了
co_begin,co_endはおまじないと思ってくれ。co_yieldについて説明しよう。
co_yieldは呼び出した時点で処理を中断し関数を抜けるんだ。次にこの関数が呼ばれた時、最後にco_yieldを呼び出したところから処理が再開される。
さて、気になるco_begin,co_yield(),co_endの実装を見てみよう。

#define co_begin              \
static int __state = 0; \
switch(__state){ \
case 0:

#define co_yield() \
do { \
__state = __LINE__; \
return; \
case __LINE__: \
break; \
} while(0);

#define co_end \
__state = __LINE__; \
}
うーん。なかなか良く出来たコードだ。switch-caseを巧みに利用しているのがわかる。もちろんこのマクロは完璧ではない。ローカル変数は使えないし、外部から状態を制御できない。PICなんかだと、1度動作を開始させた後、処理を止める必要がない場合が多いので、今回のマクロで十分かもしれない。

次回は、このコルーチンマクロをもう少し使い易く、ローカル変数を使えるようにしてみる。

コルーチン - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%AB%E3%83%BC%E3%83%81%E3%83%B3

該当の記事は見つかりませんでした。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。