2011年5月30日月曜日

課題・近似式


最近学校でもプログラミングをやり始めたのでそれについても触れてみようかなぁ、と。
前年度でもちょっとは触ってるんですが実は去年の方が難しかったり。

今回は5回目(?)だったかな、で近似式。
10*x^c(cは定数)の近似で、積分と台形公式とシンプソン公式によるものです。

一番下にリストがあるので対照するとわかりやすいかも。


数学科ではないので実は渡された公式を見てプログラムに書き換えるだけなんですけどね。
普通に積分すると

10*x^(c-1)/(c+1)

になります。これが理論値。

こんな風に不定積分できないときのために近似を使うわけです。
今回はたぶん理論値とどのくらい近似がとれているかを測るために積分可能な関数なんでしょう。

台形公式だと

h*{(y0+yn)/2+Σ(i =1 to n-1)y(i)

となり、シンプソン公式だと

h/3*{(y0+yn)+4Σ(i=1 to n/2)y(2i-1)+2Σ(i=1 to n/2-1)y(2i)}

となります。

変数の指定は以下のとおり。
始点a=0
終点b=1
分割数n=10
刻み幅h=(b-a)/n=0.1
定数c=適当な数値


これをプログラム化していくわけですけど、なぜかみんな結構躓いてたなぁ。
まず今回は理論値が出せるのでこれを利用しない手はないです。
以下簡単な手順。


1.数値目標(答え)を求める。

目標が解ってるって結構安心なんです。
答えが与えられてないときは簡単な数値で計算してみるといいかも。
1とか2とか10とか。


2.プログラム・フローを考える。

今回は式があるのでほとんど何も考えてませんね。
Σがあるからwhileよりはforかなーくらいで。

あとは計算する箇所を分けましょう。
たとえば今回ではΣがあるのでここは別計算だなぁーとか。


3.まずは式を書いてみる。

変数宣言とかどうでもいいのでまずは一番重要な式を書いてみる。
台形公式では

answer = h/2*((y0+yn)/2+SUM);


って感じですかね。
Σがあるのでこれは四則演算にないので適当な名前に置くこととします。
まだこの時点では変数とも関数とも決めていません。


4.足りない変数を宣言。

まず、a,b,c,h,nは指定があるのでとりあえず変数宣言します。
型は計算結果を入れる場合はdouble、
自分で数値を入力するだけならそれに対応する型にします。

たとえば
c=a*b
ならcはどのような値になるかわからないのでとりあえずdouble、
aとbは整数しか入れないならint、それ以外ならfloatとかdoubleとか。

今回はa,b,hはdoubleでそれ以外はintでいいんじゃないんでしょうか。
(別に全部doubleでもいい)

課題ではSUMを関数化したので変数宣言はしていませんが、
今回はいったん計算した数値をSUMにいれてから使うようにするので
SUMもdouble宣言しちゃいましょう。


5.定数を入れてみる。

入れられる定数を入れてみます。
a,b,c,h,nが決まっているので入れていきます。

入力数値という指定になっていますが、
一回ずつ打つのは面倒なので定数として宣言しておきます。
ここでは

int a=10,b=3;


などと入れるよりは、

int a,b;
a=10;
b=3;


のようにしておいた方が便利だと思います。
あとで定数宣言している部分をまとめて消す、またはコメントアウトできるので。


6.足りない部分を考える。

ここが一番のミソになりますね。Σの部分をどう作るのか。
プログラムと聞いて構えがちですけど、要は数学の考え方でいいんですよね。


台形公式の場合ではΣ(i=1 to n-1)y(i)部分になります。
これはy(i)を1からn-1まで足す、という式ですのでfor文でどうにかなりそうです。

example:y(1)+y(2)+y(3)+……+y(n-1)


ここでyというのはもともとの関数、つまり10*x^cです。
xとは今回、刻みが変化する場所です。上にあるように0から0.1ずつ1まで動きます。

y(1)というのは2個目のyということです。(y(0)がスタートなので)

そして始点が0、終点が1、分割数が10つまり刻み幅が0.1となっているので、
y(0)は

10*(0)^c


となります。そしてy(1)はそこからxが0.1だけ動くので

10*(0.1)^c


同じようにy(2)は

10*(0.2)^c


となります。
ここまでくるとどうにかfor文で書けそうです。


7.次に大きい部分を考える。

先ほど、SUMがy(1)~y(n-1)までの和だったのでまずはfor文で書いてみます。
今回も必要な部分の宣言は後です。

for(i = 1;i <= n-1;i++){
        SUM = SUM + y[i];
}


これでSUMにyのi番目を足しこむことが出来ました。
でもこのままではyは宣言されていないしyには何も入っていません。

ここで4番と同じように、y[]を宣言します。
今までy0やynのように書いてきたyを配列で管理します。

yの配列の大きさを決めなきゃいけないんですけど、
y[i]はnまで動くのでそれより大きな数値にします。

ただ、nを変更するときにわざわざ配列の大きさを変えるのも面倒なので
y[50]とかy[100]とかでもいいと思います。

このSUMは一番上のanswerの計算よりも
先に終わっていなければならないのでそれよりも前(上)に出しておきます。


8.その次に大きな部分を考える。

次に、最終としてy[]の中身を作っていきます。
基本的に大きな枠組みを作った後に必要なものを増やしていくスタンスです。

ここでy[]の中身というのは

10*x^c


でした。

y[0]はこれのxに始点(a=0)を入れて、

10*0^c


最後の項であるy[n]には終点(b=1)での値が入り、

10*1^c


となります。

始点(a=0)から終点(b=1)までは(n=10)分割され、
ひとつの項ごとのxの変化は(h=0.1)となります。

つまりxの値は0から0.1刻みで増えていき、最終的には1まで増えます。
並べてみるとこんな感じ。

第0項  0
第1項  0.1
第2項  0.2
第3項  0.3
第4項  0.4
第5項  0.5
第6項  0.6
第7項  0.7
第8項  0.8
第9項  0.9
第10項  1.0

y[]項の変化だけをfor文で書くと、
for(i = a;i <= n;i ++){
/*処理*/
}

となります。
xの変化は0.1刻みなので、

x = x + 0.1;

をfor内に入れます。

今回は項とxの変化量が比例しているので、
上記の処理は計算式内に

i*0.1

と記すことでも解決できます。

ここでさっきのy[]に数値を入れていくので、

for(i = 0;i <= n;i ++){
        y[i] = 10*pow(x,c);
        x = x + 0.1;
}

または、

for(i = 0;i <= n;i ++){
        y[i] = 10*pow(i*0.1,c);
}

となります。pow()はべき乗の関数で、pow(x,c)ではxのc乗という意味になります。
pow()関数を使う場合には<math.h>の#includeが必要となるので忘れずに書いておきます。

このy[i]の計算はSUMで和を出すより前に解っていないといけない値なので、
その計算よりは前(上)に出します。


9.実行してみる

今までの計算をリストにしてみると、

#include<stdio.h>
#include<math.h>

int main(void){
        int i,n;
        double a,b,c,h,/*x,*/SUM,answer;
        double y[50];

        a = 0;
        b = 1;
        n = 10;
        h = (b - a)/n;
        c = 1;
        /* x = 0 */;
        SUM = 0;
        answer = 0;

        for(i = 0;i  <= n;i++){
                y[i] = 10*pow(i*0.1/* x */,c);
                /* x = x + 0.1; */
        };

        for(i = 1;i <= n-1;i++){
                SUM = SUM + y[i];
        }

        answer = h*((y[0]+y[n])/2+SUM);

        printf("%f\n",answer);
}

のようになりました。
定数cは簡単のために1としています。
積分で計算してもわかるように、答えは5となっています。

コメントアウトされている部分はxの使用についてで、こんな風にもかけるよーって感じです。

10.デバッグなどの修正。

ここまででいろんなミスが発生しました。
たとえば、iの範囲がnまでになっていたり、hに1/2がかかっていたりと様々です。

そんな時にはどこがおかしいかを確かめるデバッグが必要になりますけど、
大体は、

・1か所目がすでに間違っている
・2か所目以降のループが間違っている
・使用している変数の方がおかしい

などが多い気がします。
そんな時には気になる変数をプリント(printf)してみて、
たとえばiが0から始まっていないだとか、
y[i]に思ったような数値が入っていないだとかが見つけられます。

そんなこんなでおかしいところを順次直していけば、正しい解答に辿りつけると思います。


というわけで今回はここまでにして、以下、課題提出時の関数処理でのプログラムリスト。

/*後日載せます*/


2011年5月14日土曜日

blogger不具合

今朝ニュースで見ましたが、bloggerに不具合が起こってた模様ですね。
昨日あたりに軽く見に来ようと思ったらサービスが停止中だったので……。

どうやら近日中に投稿された記事が一時的に見れないようになっているようです。
データは残っているらしいので近いうちに復旧するんだろうなぁ。

まあどっちにしろ最近投稿していないのであんまり関係ありませんが(笑)

2011年4月17日日曜日

アンプ

前回からの話は割愛し、アンプを実装してみました。

写真をミスって消してしまって撮り直すのが面倒なので今回はなしということに(ぇ


回路図はこんな感じになりました。



なんとなく解りづらくなってしまいましたが、
AC-INにはイヤフォン端子からのプラスが刺さります。
グランド(マイナス)端子はもちろんグランド(電位のマイナス)に。

イヤフォンからは2本の線が出ているのが多いと思いますが(耳につける部分が2つあるのはそう)、
マイナス端子はどちらでもなく、周りについてる銀色の「網」みたいなのです。
2本の線は両方プラス端子なので、その2つをアンプにつなげてもたぶん変な音がします。


あんまり当初との差異はないですね。
右上の5kΩが1kΩに変化しているくらいでしょうか。

図面では修正していますが右側の0.1uFのコンデンサは最初は100uFの予定でしたけど、
100uFを入れてしまうとどうやらクリップしてしまうようなので結構小さくしました。

クリップというのは波形が大きすぎて(バイアス電流があっていなくて)、
上下がトランジスタの出力できる範囲から外れてしまっている現象です。


それとスピーカに直列になっているコンデンサも最初は10uFの予定でしたが、
10uFを持っていないので100uFにしました。
こっちは0.1uF(小さくする)だと若干不具合が起こったので大きい方に差し替えました。

どちらも正直、10uFがあればちょうどよかったんですけど、
持っていないのでしょうがない、って感じですかね。

まあ製品でもないしただの実験なので関係ない関係ない。動けばいいんです(笑


実験する場合にそこそこ重要だと思うのが、自分が持っている部品に合わせるということ。
ほんとは33kΩだったりのE系列とやらが適しているようなのですが、
自分は100、1k、10k、100kしか持っていないので、それで簡単に作れる数値に合わせました。

50kは100kを2つ並列、あとは単体で作れますね。
コンデンサは直列で抵抗の並列と同じ計算(和分の積)になるんですけど、
まあそこまで厳密な静電容量はいらないのでそのままで。


そしてこれが実装した波形のシミュレーションです。




下が入力、上が出力です。
クリップもなくいい感じです。
実際に聞いてみても結構クリアな音だと思いました。

ただトランジスタが2石なのと、1次側の出力をそのまま2次側の入力に持っていってるので
もう少し上手いこと増幅することは可能だと思います。
(2回もバイアスの計算をするのが面倒だったからとかではない)


今回は電池以外は手持ちだったので、電池の価格=製作費になりました。
この電池もまだまだ使えるのでパーツがひとつ増えたって感じですね。


アンプとは無関係ですけど実はいまさらマルチバイブレータが学校で出てきたので、
これで何かできないかなーとか考えてます。
せっかくだしパルス速度上げて音でも出してみようかな?


全くアナログ回路を知らないままデジタルを触り始めたので
まだまだやることがたくさんありそうです。

もともと若干ソフト寄りだからなぁー。
メカトロニクス技術者に向けてアナログ、デジタル、メカニクスは習得しておきたい。

なんというか抱負でした。以上。

2011年4月5日火曜日

LTspice(フリーソフト)とアンプ

私の部屋(というか家)にはオーディオというものが一切なくてですね、
もちろんスピーカーの類もないわけです。

音楽聴くときはだいたいノートPCのスピーカーとかイヤフォンとか。

そんなときにふと、PCのイヤフォンジャックから手持ちの0.5Wスピーカにつなげるのではないか、
とかいうわけのわからない発想が出てきましてイヤフォンのケーブルを切ってテスタで電圧とかを測ってみたんですけど
まったくもって針が振れないという結果に終わりました。
いや、10mAのレンジでやや振れるかなー程度には観測できました。

もちろんスピーカにつなげても音など鳴るはずもなく、ならトランジスタで増幅を~(アンプ自作)と思ったものの
現在、ブレッドボードは使用中…。
そして一回ずつ回路を組み替えて測定するのは骨が折れる。
入力波形も微弱なためミスが発見し難い。

そんなときにアンプ関連のサイトでLTspiceとかいうソフトが紹介されていたわけです。
一番上の箱の「ダウンロード!LTspiceIV」を押して、
「No thanks...」とかいう下の方を押せばDL完了です。


LTspiceは回路シミュレータ(シュミレータ、ではない)で、
回路をコンピュータ上で実験してくれるソフトです。

物理系ならphunとかBlenderとかのフリーソフトがあるんですけど、
電気はなかなか見つかりませんで^^;
(といっても探す気もなかった)

あと機械系ならAutodeskかどっかが出してたなぁ。これはもちろん有料(数百万のレンジだったと思う)。
ちなみにそこに使う3DcadもAutodeskが出してるけど有料。


それでまあ電気CADもAutodeskが出していたような気がするので大体有料か、
そうでなければ機能制限もしくはロークォリティな感じかと思っていましたが、まさかのミドルレンジ。

いや、実際そうなのかは知らないけど(笑
部品点数の制限がありません。

そんな感じで波形やら電圧やら電流やら消費電力やらを解析(シミュレーション)できるソフトを手に入れたってわけです。

余談だけど(我が)龍谷大学ではPspiceというソフトらしいです。これもフリー(まさかのフリー)


見ているうちにどっかのサイト(http://gomisai.blog75.fc2.com/blog-entry-448.html)が
PspiceとLTspiceの比較をしていたので見た結果、LTspiceに。

(前置きここまで)


試しにここ(http://www005.upp.so-net.ne.jp/guitarder/other/o-07-tr-01.html)の
一石トランジスタ回路をシミュレートしてみた結果、素晴らしい感じに。




中心付近の波形が入力(スピーカー端子から)で、一番振幅の大きいのが出力電圧、
あいだにある青いのが出力電流(負荷は適当)です。


なぜかへんに嵌ってしまってインダクタとコンデンサで適当な波形を作ったりして遊んでいます。
部品数の制限がないのでバーサライタのシミュレーションもできます。
もちろん、マイコン(AVRとか)は出来ませんけど。
解放時の出力電流や、消費電力などがシミュレートできるのでお薦め。


そんな感じで支離滅裂ながらお遊び日記。

使用方法はさっきのねがてぃぶろぐさんにあります。以上。

LEDバーサライタmarkII・スケッチ


前回の最後の方で行ってたスケッチです。
見ての通り一部の文字しか対応していません(笑

これでおおよそ1500byteくらいです。
Attiny2313のフラッシュメモリが2000byteなので頑張れば移植できそうです。
ただポート番号が変わるのと、PCINTがBピンの並びにしかないので
使うならばINT割り込みになるんじゃないでしょうか。
(INT0はPD2、INT1はPD3)

LEDが9列なので少し見難い感はありますけど当初よりはスマートになったんじゃないかな?
以下。


#include<avr/io.h>
#include<avr/pgmspace.h>
#include<avr/interrupt.h>
#include<util/delay.h>


const prog_uint8_t a_line[2][6] = {{0b00000000,0b00000001,0b00000001,0b00000001,0b00000001,0b00000000},
{0b11111111,0b00001000,0b00001000,0b00001000,0b00001000,0b11111111}};
const prog_uint8_t b_line[2][6] = {{0b00000001,0b00000001,0b00000001,0b00000001,0b00000001,0b00000000},
{0b11111111,0b00010001,0b00010001,0b00010001,0b00010001,0b11101110}};
const prog_uint8_t d_line[2][6] = {{0b00000001,0b00000001,0b00000001,0b00000001,0b00000000,0b00000000},
{0b11111111,0b00000001,0b00000001,0b00000001,0b10000010,0b01111100}};
const prog_uint8_t e_line[2][6] = {{0b00000001,0b00000001,0b00000001,0b00000001,0b00000001,0b00000001},
{0b11111111,0b00010001,0b00010001,0b00010001,0b00010001,0b00000001}};
const prog_uint8_t h_line[2][6] = {{0b00000001,0b00000000,0b00000000,0b00000000,0b00000000,0b00000001},
{0b11111111,0b00010000,0b00010000,0b00010000,0b00010000,0b11111111}};
const prog_uint8_t i_line[2][6] = {{0b00000001,0b00000001,0b00000001,0b00000001,0b00000001,0b00000001},
{0b00000001,0b00000001,0b11111111,0b00000001,0b00000001,0b00000001}};
const prog_uint8_t l_line[2][6] = {{0b00000001,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000},
{0b11111111,0b00000001,0b00000001,0b00000001,0b00000001,0b00000001}};
const prog_uint8_t m_line[2][6] = {{0b00000001,0b00000000,0b00000000,0b00000000,0b00000000,0b00000001},
{0b11111111,0b11000000,0b01110000,0b01110000,0b11000000,0b11111111}};
const prog_uint8_t o_line[2][6] = {{0b00000000,0b00000001,0b00000001,0b00000001,0b00000001,0b00000000},
{0b11111110,0b00000001,0b00000001,0b00000001,0b00000001,0b11111110}};
const prog_uint8_t p_line[2][6] = {{0b00000001,0b00000001,0b00000001,0b00000001,0b00000001,0b00000000},
{0b11111111,0b00010000,0b00010000,0b00010000,0b00010000,0b11100000}};
const prog_uint8_t r_line[2][6] = {{0b00000001,0b00000001,0b00000001,0b00000001,0b00000001,0b00000000},
{0b11111111,0b00010000,0b00010000,0b00011000,0b00010100,0b11100011}};
const prog_uint8_t t_line[2][6] = {{0b00000001,0b00000001,0b00000001,0b00000001,0b00000001,0b00000001},
{0b00000000,0b00000000,0b11111111,0b00000000,0b00000000,0b00000000}};
const prog_uint8_t u_line[2][6] = {{0b00000001,0b00000000,0b00000000,0b00000000,0b00000000,0b00000001},
{0b11111110,0b00000001,0b00000001,0b00000001,0b00000001,0b11111110}};
const prog_uint8_t v_line[2][6] = {{0b00000001,0b00000000,0b00000000,0b00000000,0b00000000,0b00000001},
{0b11111000,0b00000110,0b00000001,0b00000001,0b00000110,0b11111000}};
const prog_uint8_t w_line[2][6] = {{0b00000001,0b00000000,0b00000000,0b00000000,0b00000000,0b00000001},
{0b11111100,0b00000111,0b00111100,0b00111100,0b00000111,0b11111100}};
const prog_uint8_t y_line[2][6] = {{0b00000001,0b00000000,0b00000000,0b00000000,0b00000000,0b00000001},
{0b11000000,0b00100000,0b00011111,0b00010000,0b00100000,0b11000000}};

void space(){
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(30);
}

int main(void){
cli();
DDRB = 0b11111111;
DDRD = 0b11111111;
DDRC = 0b00000000;
PORTC = 0b11111111;
PCICR = (1<<PCIE1);
PCMSK1 = (1<<PCINT8);
int i;
sei();
while(1){
for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&h_line[0][i]);
PORTD = pgm_read_byte(&h_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&a_line[0][i]);
PORTD = pgm_read_byte(&a_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&p_line[0][i]);
PORTD = pgm_read_byte(&p_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&p_line[0][i]);
PORTD = pgm_read_byte(&p_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&y_line[0][i]);
PORTD = pgm_read_byte(&y_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


space();


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&b_line[0][i]);
PORTD = pgm_read_byte(&b_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&i_line[0][i]);
PORTD = pgm_read_byte(&i_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&r_line[0][i]);
PORTD = pgm_read_byte(&r_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&t_line[0][i]);
PORTD = pgm_read_byte(&t_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&h_line[0][i]);
PORTD = pgm_read_byte(&h_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&d_line[0][i]);
PORTD = pgm_read_byte(&d_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&a_line[0][i]);
PORTD = pgm_read_byte(&a_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 6;i++){
PORTB = pgm_read_byte(&y_line[0][i]);
PORTD = pgm_read_byte(&y_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 0;i < 2;i++){
space();
}
}
}

ISR(PCINT1_vect){
if(bit_is_clear(PINC,PC0)){
_delay_ms(80);

int i;

for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&d_line[0][i]);
PORTD = pgm_read_byte(&d_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&l_line[0][i]);
PORTD = pgm_read_byte(&l_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&r_line[0][i]);
PORTD = pgm_read_byte(&r_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&o_line[0][i]);
PORTD = pgm_read_byte(&o_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&w_line[0][i]);
PORTD = pgm_read_byte(&w_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


space();


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&o_line[0][i]);
PORTD = pgm_read_byte(&o_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&l_line[0][i]);
PORTD = pgm_read_byte(&l_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&l_line[0][i]);
PORTD = pgm_read_byte(&l_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&e_line[0][i]);
PORTD = pgm_read_byte(&e_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);


for(i = 5;i >= 0;i--){
PORTB = pgm_read_byte(&h_line[0][i]);
PORTD = pgm_read_byte(&h_line[1][i]);
_delay_ms(3);
}
PORTB = 0b00000000;
PORTD = 0b00000000;
_delay_ms(3);
space();
}else{
}
}

2011年4月1日金曜日

LEDバーサライタmarkII

そこそこ完成に近いと思います。

ブレッドボードの大きさの問題でLEDは初期と同じく9個ですけど
反対向きに振ったときの文字の表示もできるようになりました。

前回は割り込みを外部割り込みINT0~1を使う予定でしたが
あまりにも文字部分を書き換える手間が発生してしまうので、
最終的にはPCINTを使うことに。

INTもPCINTもたぶん大して変わりはない(INTはまったく使用せずなので)と思います。
INTがレジスタで割り込みの発生条件を決めるのに対して、
PCINTはプログラム内で発生条件を決める、という解釈でいいんでしょうか?

まあPCINTがなんでもかんでも拾うからそれをifとかで選別しろってことですね。たぶん(ぇ


というわけで回路図。


前より少しだけ横長になりました(笑

いつものことですけどGNDとかVCCとか書かないのはだれが見てもわかるように。
今はちょっと読めるようになったけど昔は「GNDってなんだ?」状態でしたので。



その他、プログラムの方は
配列を作るとなぜかEEPROMに書き込まれる仕様
となっていたので(AVR特有らしい)、それをフラッシュメモリ(プログラムと一緒のところ)に
入れるのに四苦八苦。

別にEEPROMでもよかったんですけどこれには深いわけが…。
ということもなく(実際にはあったんですけど)。

単純に電源の質が悪かっただけなのに行き着いた結果がこれです(笑
ダイジェストで説明。

LEDの点滅速度が一定じゃない(9個バラバラなので振っても文字にならない)

もしかして割り込みが悪いんじゃないか

違ったので、もしかしたら配列がEEPROMに入っているのが悪いんじゃ(略

ここでEEPROMからフラッシュに移動させる(しかし改善されず)

どうやらライタが接続されている間はちゃんと動作するのに、
ライタを外すとダメなようだ

ライタの中で何か接続がされていてそこを繋げばいいんじゃ

ISPケーブルを一本ずつ抜いていってどれを抜くとアウトかを調べる

VCCまたはGNDでした。ということはつまり。


電源(電池)の接触が悪く、単にノイズ(というよりはもっと大きな電圧変化)の所為でした。
もともとブレッドボードは場所により接触悪いので、挿す場所を変え、
電源用の電解コンデンサをぶち込む事で解決でした。



なんという徒労…orz

上の「配列を作ると~」は全く関係なかったわけですね。
ライタを接続していれば大丈夫だった理由は、
たぶんライタ内にコンデンサでも入ってるってことなんでしょうね。
(半透明なのに見えない…( ̄⊿ ̄)ぐぬぬ…


まあ結果的に書き換え回数が10,000回のEEPROMを使わずに済んだのは良かったのかも。
今後はこれで嵌ることがないようにしないと…。数時間これと格闘してたからなぁ(遠い目

回路図のRESET10kΩもたぶんいらないです。

これを完成させるにはまずICソケットを買わないとなぁ。
物流動いてるんだろーか。
プログラムスケッチは別で貼ろう。

2011年3月23日水曜日

LEDバーサライタ続き

前回の続きです。

予想だにしない問題というのは、
「文字を選択できるようにするなら、どの文字を選択しているか解らなければならない」
ということ。

当たり前っちゃ当たり前ですね(笑)

フルLEDボードなら見ながら変更できますけど、バーサライタ(英語ではpersistence of visionと言うらしい)は
振らないと文字を表現できないので、どの文字を選択しているかは振ってみるまで解りません。

さすがにこれはダメだろ…。ということで文字選択は出来ないようにするかも。
その場合、簡単に書き換えが出きるようにICソケットか何かで着脱を簡単にしておこうかと思います。

文字選択を実装するならLCDとかで表示用のシステムを作らなければいけないし…。
ちょっと技術的にきついかなー。まだ2つ以上のマイコン同士の通信は出来ないので。
ポートが足りない…(´д`)

というわけでまずは概観から。


まだ割り込み関連を理解していないため、表示素子だけになっております。
前回バーサライタのLED増やしただけバージョンですね。

ここからたぶん4ピン(PD2)を使用しない方向で修正すると思うので
主にPORTCとPORTBで構成されることになるかと思います。
(割り込み処理がPD2を使う関係でPORTDが制限される)


割り込み処理とは、プログラムの実行中に割り込みの条件が起こることによって
一旦、そのプログラムを中断して割り込みプログラムを優先的に実行するシステムです。

AVRなどのマイコンは割り込み処理が定義されていて、
それにしたがって記述するだけで割り込み処理が実現できます。
(といってもこれがなかなか資料が無くて…^^;)

この割り込み処理でボタンを押している間はLEDの表示順序を反対にする
(双方向で表示が出来る)ようになり(し)ます。


まだプログラムも実験段階でとりあえず関数ポインタが使えるようになったくらいなので
実装は4月上旬かなー(遅い)。

それにしてもPD2を割り込みに使うとなるとプログラムの書き換えが面倒そうだな…。

そんな感じで再評価版も準備を始めています。
当たらしい物も何か作りたい…。でもアイデアが…orz。

だれかメンバー募集(ぇ
いや結構マジで