senda
ものづくり†
11月のものづくり教室にむけて、教育的視点から魅力的な電子工作キットをつくるプロジェクトです。
コメント†
- おお。はじまっとる。 -- akita
- ↓Zのときに一列が光るのは、もしかしたら、光電流によるものかもしれませんね。あ、でも電圧はあがるにしても電流はLEDが光るほどは流れないはずか・・・・ -- akita
- 各列のLEDとジャンパピンの間に1個ダイオードを入れれば、8/6の問題は解決できそうですね。列の数(=5)だけなので、入れてしまってはどうでしょう? -- akita
- ADCの割り込みのところはなやましいですね。CPU_CLOCKを、SYSCLK/1(=24MHz)にしてみると、プログラムの実行速度が、SYSCLK/8の場合の8倍になるので、けっこうよくなるのでは? -- akita
- ありがとうございます。CPU_CLOCKは、SYSCLK/1にすると怒られたので(Warningですが)、SYSCLK/2にしてみました。当初の予定通り5kHzで動くようになりました。 -- senda
- ダイオードは…配線が大変そうな予感。今度試してみます。 -- senda
- ああ、3.3VではCPU動作速度が12MHzまでなので、SYSCLK/2が上限ですね。 -- akita
- そろそろ基板設計開始ですかね? -- akita
- そうですね。なにはともあれ、まずはPCBEの操作に慣れることからはじめたいと思います…。 -- senda
- ↓本番で注意ですね・・・>LED逆挿し -- akita
記事一覧†
コンセプト†
- つくった後も遊べる
- 直感的に遊べる
- 自分でアレンジして遊べる
ということをコンセプトに掲げ、何か電子おもちゃを作れないかと考えました。
モリワキット「水盤キット」、バンダイ「超撥水GAME aqua drop」にヒントを得て、
- LEDのアレイ上を、
- 加速度センサから得た、筐体の傾き情報をもとに
- 光が水滴のように動き回る
ようなおもちゃを考えました。
さらに、迷路状に壁を置き、スタートとゴールを設けることで、いわゆる銀玉転がしのように遊べるようにしました。
08.10.27 (Mon.)†
./壁
08.10.15 (Wed.)†
長らく更新をサボってましたが…
やってきたこと†
- 組み立てマニュアルづくり(未完)
- 小分けされた袋を開けて、部品ごとにまとめた
- 『壁』づくり(未完)
- 加速度センサの変換基板とりつけ
- ピンヘッダを、3pinづつカットする作業(疲れた…)
やること†
- 『壁』をせっせとつくる
- 部品を1人分づつ袋につめる
- マニュアルを完成させる
- プログラムの調整&スタート・ゴールの設定
- アンケートをつくる
08.09.21 (Sun.)†
部品到着†
組み立てマニュアルを作成するために、写真を撮りながらの本組み。
慣れたもので、1時間そこそこで組みあがる。
…が、まさかのLED25個全部逆挿し
orz
08.09.11 (Thu.)†
基板到着†
早速1枚実作してみる。
部品が到着してないので電池ボックスが無いですが…。
動作は問題なさそうだ。
が、切ないミスが1点。
やること†
- 配線の都合上、LEDのY方向の配列を逆にしたのを修正する
- 2ボタンになったので、難易度選択などを実装する
- その他、それらしい機能を実装する
08.08.23 (Sat.)†
基板作成†
秋田先生の、PCBEによる基板設計の手引きをもとに、PCBEをインストールし、とりあえず慣れるためにいろいろ触る。
去年の、「ふるディスプレイをつくろう」をつくろうのページから、PCBEデータを拝借し、基板と見比べてにらめっこ。
さらに、こんちさんからもデータと基板をいただく。
パッドを並べて、ラインで接続していく作業は、なんとなくつかめてきた。
08.08.21 (Thu.)†
ジャンパピン†
まぁやってみよう、ということで、「ジャンパブロックにダイオードを埋め込む」作戦で行くことにする。
試作基板の変更はなし。
ただし、実作のときは、試作基板では2pinのピンヘッダを、3pinに変更する。
傾きに応じて動くLEDと、壁の動作を実現完了!
調整は必要だが、最低限動く。
08.08.20 (Wed.)†
ジャンパピン†
ダイオードを挿入し、無関係なLEDが光る問題は解決した。
しかし、再び問題発生。
緑の丸で囲ったようにピンをショートしたとき、同電位("H")になるところを赤で塗ってみた。
青の矢印で示したピンはオープン状態なのだが、この状態に関わらず、PSoCのI/Oピンには"H"が入力される。
これでは、ショートされていると誤って読み取ってしまうことになる。
任意の向きの「L字」に反応して発生するので、ゴールできないなどのバグに簡単に陥る。
これも現状では不可避な気が…。
もっとも単純には、全ジャンパピンに対して1つのダイオードを挿入するという解決法があるが、さすがに現実的ではない。
遊ぶ前に、ピンを1列ずつ読み取らせてから、スタートする、という方法。
これもスマートじゃないし、気軽に遊べなくなってしまう。
というか、1列ずついちいち抜き差しするのはありえないだろう…。
以前の問題が発生したときに、戯れで考えた解決法に、
「ジャンパブロックにダイオードを埋め込む」
というのがあったが…
<メリット>
- ダイオードをはんだづけする必要が無いので、製作の手間にはならない。
- 当然、ダイオードを埋め込んだブロックを作る必要はあるのだが。
- ダイオードを埋め込むついでに、それこそ『壁』を模したようなデザイン性を持たせることもできる。抜き差ししやすくもなるかも。
- ピン全部に対してダイオードをつけるよりは素子数が少なくて済む。
<デメリット>
- ジャンパブロックに向きができてしまい、遊ぶときの手間が少し増える。
- ダイオードに極性があるので、逆向きに挿されると用を成さない。
- 「直感的」がキーワードだけに、なかなかやっかい。
- 市販のジャンパブロックが流用できない。
- ジャンパブロックは小さくて失くす可能性があるが、比較的簡単に入手できる、というのも1つの売りだったのだが。
- 埋め込む手間と、相当数のダイオードが必要。
うーん…
メリットに対してデメリットのほうが目立つかなぁ。
アイディアメモ†
もう少しアイディアを膨らませてみる。
任意の向きに挿されると困るなら、ジャンパブロックを一定の向きにしか挿せなくしてしまえばよい。
どうせ『壁』なので、いくつかつなげて使うのが普通だろう。
ならば、最初からつながった状態で用意されていても、別段問題はないはず。
例えば、4つ分。
某テ○リスのブロック型に、7種類の「壁ブロック」を用意してしまってもおもしろいかもしれない。
現状、ジャンパピンはLEDに対して全方向に対称に、きれいに並んでいる。
これを、例えば右下方向に少しずらす。
または、少し角度をつけて、斜めに配置する。
そうすれば、「壁ブロック」はLEDと干渉したり、ピンと合わなかったりして、一定の向きでしか挿せなくなるんじゃないか。
あ、回転できないんじゃテト○スとは別物か…(謎)
08.08.18 (Mon.)†
次のグローバル変数を用意
- acc_x, acc_y
- 加速度センサから得られる、x方向、y方向の加速度
- vel_x, vel_y
- 一定時間(100ms)ごとに、加速度を足し込むことで得られる、x,y方向の速度
- pos_x, pos_y
- 一定時間ごとに速度を足し込むことで得られる、x,y方向の位置
タイマ割り込みは10Hzなので、100msごとに加速度を読み込む。
加速度は、-2g〜+2gを8ビット(256等分)。
よって、得られるacc_x, acc_yの単位は、
[(9.8/64)m/(0.1)s^2] ~= [(0.153)m/(0.1)s^2] = [(153)mm/(0.1)s^2]
と計算して、実サイズに沿った係数で動かしてみたものの、加速度センサの感度はいいわ、摩擦はないわで、すぐに枠の外に行ってしまう。
ということで、トライ&エラーで適当な係数を決めることにする。
08.08.17 (Sun.)†
ダイオード†
コメントで、ダイオードの挿入にゴーサインをいただいたので、やってみる。
しかし、LEDの数(25個)だけ必要だと思っていたのに、列の数(5個)で済むらしい。
どうすればいいだろうか…。
現状で問題なのは、ショートしたジャンパピンから流れてくる電流。
ということで、ジャンパピンと縦バスとの間にダイオードをはさんでやればよい。
縦バスとLEDは直結で問題なし。
ということは…こうか!
縦にもう1本バスを通してやり、PSoCのピンからダイオードを通してそのバスに流れるようにする。
そのバスからジャンパピンに流す、という仕様に。
#文字だと説明しづらいな…。
08.08.16 (Sat.)†
動作モード†
A/D変換もなんとかなりそうなので、動作部分に取り掛かる。
- main()内部
動作モード変数 mode を定義し、while(1)ループ内部で、modeの値によってswitch-case文で分岐させる。
modeの値は、とりあえず次のようにした。
- CONF ・・・CONFIGモード;初期設定を行う
- PLAY ・・・PLAYモード;実際に動作させる
- OVER ・・・GAME OVER状態;タクトスイッチ押下でCONFに移行
- Timer8_1_ISR()関数
1kHzでタイマ割り込みをかけて動作する関数。
タクトスイッチの状態読み取り、LEDのダイナミック駆動の制御を行う。
#ホントはジャンパピンの読み取りもここでやりたいが、保留中。
- Timer8_2_ISR()関数
10Hzで割り込み。
加速度センサから読み取ったx,y方向の加速度値(acc_x, acc_y)を、現在の速度(vel_x, vel_y)に加算し、現在の位置(pos_x, pos_y)を求める演算を行う。
予定。
08.08.14 (Thu.)†
ADC†
加速度センサは動いてるし、配線も間違ってはいない(と思う)ので、問題はソフト側だろう。
ということで、とりあえずできることをいろいろ試してみる。
- Global Resourcesをいろいろ変えてみる
- Ref Mux : (Vdd/2)+/-(Vdd/2) に
- Analog Power : SC On/Rf Highに
- Op-Amp Bias : Highに
- A_Buff_Power : Highに
- Trip Voltage[LVD (SMP)] : 3.13V (3.25V)に
- PGAの設定を見直す
- PGAとTRIADCのStartする順序を変えてみる
どこだ…
- Timer8(2つ)のClockを落としてみる(VC3に)
- 割り込みが頻繁に起こるとADCのデータ取得が追いつかないかなぁ…なんて
ADCのClockはVC2(125kHz)、Timer8のClockもVC2で、Periodは9(動作は12.5kHz)。
10クロックで割り込まれたらA/D変換はできないか…。
モジュールを増やしたりデバッグしたりするたびに、VC1、VC2の値をコロコロ変えていて、自分でもあまり把握していなかったのが原因。
現状をとりあえずメモ。
- SysClk : 24MHz
- CPU_Clock : SysClk/8 = 3MHz
- VC1 : N=12, VC1 = 24MHz/12 = 2MHz
- これもこんなもんでいいか。N=16が最大で、1.5MHzまで落とせる。
- TRIADC8のClockに使う。
- VC2 : N=10, VC2 = 2MHz/10 = 200kHz
- N=16が最大。キリのいいところでこんなもんで。
- Timer8_1のClockに使う。
- ダイナミック駆動のラインカウント(ライン変更)用に、5kHz程度の割り込みをかけたい。
- Preiod=39で、200kHz/40 = 5kHz。
- VC3 : Source=VC2, Devider=200, VC3 = 200kHz/200 = 1kHz
- Timer8_2のClockに使う。
- 加速度をもとに、LEDの光が動く速度を演算するために、適当な時間ごとに割り込みをかけたい。
- とりあえず、Period=99で、1kHz/100 = 10Hz
としてみたら、またしても同じような症状で動かなくなった。
Timer8_1のPeriodを39->199とし、1kHzで割り込みをかけるように。
1列につき200Hzだが、まぁ目視できるほどではないからいいか…。
08.08.11 (Mon.)†
ADC†
さしあたり、ピンはオープンにしておけば動作に問題はないのでとりあえず保留して、先に加速度センサ周りの処理をやることにする。
同じ秋月の加速度センサを使っているサイトを参考に、TRIADC8というモジュールを使うことにする。
3入力で、分解能は8bit。
TRIADC8のInputには、直接I/Oピンを指定できないので、それぞれにGainが1.0のPGAをはさむ。
データシートを見ると、Clockには8MHz〜125kHzを入れるようにとあるので、(SysClk)24MHz / (VC1)12 / (VC2)16 でVC2を125kHzとした。
プログラムも、ほとんどデータシート通り。
while(1)
{
// Read ADC
while(TRIADC8_1_fIsDataAvailable() == 0); // Wait for data to be ready
acc_x = TRIADC8_1_cGetData1(); // Get Data from ADC Input1
acc_y = TRIADC8_1_cGetData2(); // Get Data from ADC Input2
acc_z = TRIADC8_1_cGetData3ClearFlag(); // Get Data from ADC Input3
・・・
}
その他適宜設定して、書き込み。
が、思ったように動作しない。
- テスタで測ってみると、加速度センサの出力ピンは、所望のアナログ電圧を出しているようだ。
- TRIADC8_1, PGA_1, PGA_2, PGA_3はちゃんとStartしている。
- いろいろ試してみると、どうやらwhileループの中の、while(TRIADC8_1_fIsDataAvailable() == 0);から先に進んでいないようだ。
- ADCがready状態にならない(?)
- 割り込み関係だろうか。でもM8C_EnableGInt;はちゃんと入れてるし…
08.08.09 (Sat.)†
ジャンパピン†
現状のH/W構成では、先の問題を根本的に解決できないような気がする。
H/W構成の変更も視野に入れた解決法としては、次のようなことが考えられる。
- 現状LEDとジャンパピンで共用しているダイナミック駆動用の縦バスを、別に用意する
- こうすることで、ジャンパピンによる意図しない電流は、少なくともLEDには影響を及ぼさなくなる
- が、29466のピン数上、5x5は不可能になる
- 各ジャンパピンの根元にダイオードを挿入する
- こうすれば、横バスから縦バスに電流が流れなくなるのでは?
- ただし、さらに素子が増えるので、材料費と半田付けの手間が嵩む。
他にもあるだろうか…
08.08.06 (Wed.)†
GPIO†
昨日の続き。
縦バスの駆動がStrongだと、同列のジャンパピンをショートするとまずい。
そこで、駆動をOpen Drain Highにしてみる。
が、今度は横1列すべてのLEDが光ってしまうようになった。
縦バスをハイインピーダンスにすると、電圧が不定になり、LEDの横バスの分圧で出てくるようになるので、光ってしまうようだ。
不定ではまずいので、縦バスに"L"を出すべきタイミングでは、プルダウン抵抗を入れてやればよいというアドバイスをいただく。
実際に抵抗をかませると、所望の動作をしているように見える。
ん、そもそも駆動をPull Downにすればいいんじゃないか?
ということで、縦バスの駆動をPull Downにする。
どうやらこれで思い通りの動きをしてくれそうだ。
ジャンパピン†
ダイナミック駆動はなんとかうまくいった。
が、やはり光らなくていいLEDが光る。
青で囲ったLEDだけが光ってほしいのだが、横のピンをショートすると黄色も光る…。
08.08.05 (Tue.)†
ジャンパピン†
ダイナミック駆動がうまくできているので、ジャンパピンの値を読んで、ショートしている隣のLEDを光らせて動作を確認してみる。
が、どうもうまくいってない様子。
同じ列のピンを複数ショートすると、LEDが光らなくなる。
よくよく考えてみると、ピンを通して変な方向に電流が流れるような気がする。
どうすればいいだろうか…。
08.08.03 (Sun.)†
スイッチ†
タクトスイッチの動作確認をしてみるも、思ったように動かない。
テスタで測ってみると、常にONになっている様子。
スイッチが壊れたか、、、と思ってよく見たら、90度回転してつけてしまっていた。
初歩的なミスが続くナァ…。
しばらくやりたくないとか言いつつ、3日間のインターバルではんだづけ。
まぁ、しょうがない。
修正して、スイッチの動作を確認した。
ソフトボール大会†
2日目。
朝9時過ぎに来たのに、朝の試合は不戦勝とのこと。
なんだかなぁ…。
準決勝に敗れた後の3位決定戦。
8点差をひっくり返しての逆転勝ち。
すげぇ。
08.08.02 (Sat.)†
ダイナミック駆動†
昨日の箇所を修正。
無事、所望のLEDだけが光るようになった。
<教訓>
1命令サイクルも馬鹿にできない。
ソフトボール大会ですね†
今日は2試合出場で、5打数3安打、1四球。
08.08.01 (Fri.)†
ダイナミック駆動†
ダイナミック駆動に必要な処理をひと通り書いて、実行。
が、光らせたいLED以外も(控えめに言って)薄っすら光る。
秋田先生のアドバイスに従い、
- 駆動電圧を3.3Vに
- ダイナミック駆動の切り替えを目で見えるほどゆっくりに
してみると、どうも切り替えのタイミングに一瞬だけ光っているようだ。
// Row line
PRT0DR &= 0xE0;
PRT0DR |= (0x01<<line);
// Column line
PRT1DR &= 0xE0;
PRT1DR |= (~led_table[line] & ~0xE0);
Column lineの最初の行で、当該ラインを全部いったん"0"にしているため、次の行にいくまでの時間(1命令サイクル)は全部光るようになるので正しい。
確かに。
ということで、Row lineは全部をいったん"0"に、Column lineは全部をいったん"1"にすれば解決する…のかな?
きょうは、ここまで。
08.07.30 (Wed.)†
はんだづけ†
ひと通り終了。
総工程約15時間。
しばらくはんだづけやりたくないです…。
GPIOについて†
PSoCのI/Oポートでは、8種類の駆動方式から選択できる。
StrongとPull Upくらいしか理解してなかったので、ダイナミック駆動のためにちょっと勉強。
簡単にまとめる。
- High Z
- 一般的なディジタル入力用。ハイインピーダンス。
- High Z Analog
- アナログ出力用。デフォルトはこれ。Driveが何に設定されていてもアナログ入力としては使えるらしい。
- Open Drain High
- '0':ハイインピーダンス, '1':"H"出力。いわゆるオープンソース。
- Open Drain Low
- '0':"L"出力, '1':ハイインピーダンス。いわゆるオープンドレイン。
- Pull Down
- '0':抵抗プルダウン, '1':"H"出力。プルダウン抵抗つきオープンドレイン。いったん'0'を入れてプルダウンしてから値を読む。スイッチの入力で使った。
- Pull Up
- '0':"L"出力, '1':抵抗プルアップ。プルアップ抵抗つきオープンソース。上の逆。
- Strong
- '0';"L"出力, '1':"H"出力。一般的なディジタル出力。トーテムポール。
- Strong Slow
- 上の立ち上がり/立下りを穏やかにしたもの。
参考:
桑野雅彦著「はじめてのPSoCマイコン」
Dr.Matrix.jp - PSoC関連 - I/Oポートの使い方
ダイナミック駆動†
ということで、LEDの駆動は、
LEDに流すバス(Row_bus)・・・Open Drain High
LEDから流れ出るバス(Col_LED)・・・Open Drain Low
にすると、該当しないラインはオープンになるからいい…のかな?
Row_busは共通なので、ジャンパピンには駆動している列のみ"H"がくる。
よって、
ジャンパピンの値(ショート/オープン)を読むためのバス・・・Pull Down
にして、いったん'0'を書き込んでから値を読むと、ショートされているときのみ'1'になるからうまく読めそうだ。他の行のジャンパがショートされていようと、Row_busがハイインピーダンスを出しているので、書き込んだ'0'の値は変わらないはず。
ピン対応表†
Port | Pin No. | Connect to | Type | Drive |
P0[0] | 24 | Row_bus[0] | Digital_Out | Open Drain Low |
P0[1] | 4 | Row_bus[1] | Digital_Out | Open Drain Low |
P0[2] | 25 | Row_bus[2] | Digital_Out | Open Drain Low |
P0[3] | 3 | Row_bus[3] | Digital_Out | Open Drain Low |
P0[4] | 26 | Row_bus[4] | Digital_Out | Open Drain Low |
P0[5] | 2 | KXM52 OutZ | Analog_In | High Z Analog |
P0[6] | 27 | KXM52 OutY | Analog_In | High Z Analog |
P0[7] | 1 | KXM52 OutX | Analog_In | High Z Analog |
P1[0] | 15 | Col_LED[0] | Digital_Out | Open Drain High |
P1[1] | 13 | Col_LED[1] | Digital_Out | Open Drain High |
P1[2] | 16 | Col_LED[2] | Digital_Out | Open Drain High |
P1[3] | 12 | Col_LED[3] | Digital_Out | Open Drain High |
P1[4] | 17 | Col_LED[4] | Digital_Out | Open Drain High |
P1[5] | 11 | Col_CJP[0] | Digital_In | Pull Down |
P1[6] | 18 | Col_CJP[1] | Digital_In | Pull Down |
P1[7] | 10 | Col_CJP[2] | Digital_In | Pull Down |
P2[0] | 20 | Col_CJP[3] | Digital_In | Pull Down |
P2[1] | 8 | Col_RJP[0] | Digital_In | Pull Down |
P2[2] | 21 | Col_RJP[1] | Digital_In | Pull Down |
P2[3] | 7 | Col_RJP[2] | Digital_In | Pull Down |
P2[4] | 22 | Col_RJP[3] | Digital_In | Pull Down |
P2[5] | 6 | Col_RJP[4] | Digital_In | Pull Down |
P2[6] | 23 | | | |
P2[7] | 5 | SW_0 | Digital_in | Pull down |
08.07.27 (San.)†
PSoCのI/Oピンは融通が利くしー、と思って、深く考えずに適当なI/Oポート(P1)を加速度センサの出力ピンと接続したら、P1はアナログ入力に対応してなかった…。
あわててDesignerでアナログブロックにADCを設置し、入力に使えそうなポートを選んだら、P0以外はめんどくさそう。
ということで、P0[5]〜P0[7]につなぎなおす。素子の配置をミスったなぁ…。
08.07.25 (Fri.)†
きょうは、ここまで。
08.07.24 (Thu.)†
始動。†
使用部品
- PSoCマイコン (CY8C29466-24PXI)
- 加速度センサモジュール(KXM52-1050)
- LED(白色5φ ×25ヶ)
- ヘッダピン(2x1pin ×40ヶ)
- タクトスイッチ
- MeRL標準DCジャック
- ユニバーサル基板
- 抵抗、他