ラベル 電子工作 の投稿を表示しています。 すべての投稿を表示
ラベル 電子工作 の投稿を表示しています。 すべての投稿を表示

2015年9月6日日曜日

STM32F4 DISCOVERYことはじめ

なんとも良い時代になりました.
32bit 高速CPUの評価ボードが2,000円の時代です.

その名もSTM32F4 DISCOVERY.

STMicroelectronics社の出している組み込みデバイス用の32bit CPU,STM32F407VGT6の評価用ボードです.
主な特徴は以下.

CPUの特徴

  • 168MHz動作の高性能CPU,STM32F407VGT6(ARM Cortex-M4)を搭載.
  • flashが1MB,RAMが192kBのデータ領域.
  • 3つの12bit ADC,2つの12bit DACを搭載.
  • 浮動小数点演算装置(FPU)搭載.

ボードの特徴

  • 3軸MEMSモーションセンサー(LIS302DL)搭載.
  • 無指向性MEMSマイクロホン搭載.
  • DAコンバータ内蔵D級アンプ搭載.
  • その他,LED,プッシュスイッチ,ST-LINK用インターフェースなどなど.

ST-LINK経由で書き込みができ,統合開発環境もメーカーのページから無料でDLできるので,導入が簡単です.
特に実数の処理に非常に有利なFPUが搭載されているため,現代制御などでのフィジカルコンピューティングを目的としている時に気兼ねなく実数演算を使えます.
値域を気にして固定小数点を作る時代は終わったのだ…

タイマも簡単で,数も豊富なため,PWMが気軽に使えるところもなかなかのメリットだと感じています.

他には,ひとつのピンに対して複数のAlternate Finction(AF)が割り当てられているので,
ピン配置が思いのほか自由なところが気に入っています.

例えば,PA1とPA2にはタイマ5とADC123が割り当てられているので,
PA1をADCに,PA2をPWM(タイマ)に使用することが簡単にできるようになっています.
Pin

micro USB経由での書き込みができるようになっている(ST-Link)ので,
ボードさえ買ってしまえば即座に使用可能です.
(ピンヘッダもついてるし)

また,SysTick_Handlerという割り込みハンドラが標準で定義されていて,
周期割り込みの設定にほとんど手間取らず,わかりやすいところもよいです.

秋月で2,000円ちょうどで販売しているので,入手性も申し分ないため一度買ってみるのもアリかとおもいます.
1ランク下のSTM32F3 DISCOVERY(1,250円)もあります.

主な違いはコアの性能の違いと,周辺機器の違いです.
個人的にはF3 DISCOVERYのほうが好きなんですが(個人で購入したのはこっちだけ.安いから),
研究室の諸事情によりF4のほうを使っています.

残念ながら,F3とF4,完全互換というわけにはいかず,多少コードを書き換える必要があったように思います.
ピン割り当てはモチロンのこと,Peripherala の設定が多少違ったような…

正直FPU搭載に目が眩んで買ってしまいましたが,用途はかなり幅広いと思われます.
(雑なまとめ)

2012年11月18日日曜日

UbuntuでのAVR開発

AVRマイコンをUbuntu上で開発しよう、という試み。
といっても先駆者が結構たくさんいるので
玉虫色に染まれ!さんの手順をそのまま実行すれば問題なく動作するかも。
http://d.hatena.ne.jp/over80/20090302/1236006771

統合開発環境はありません。曰く、
"「初めに言いますが、いわゆる「統合開発環境」的なものはありません。そういったものが欲しい人は素直にWindowsで開発していた方が幸せでしょう。Linuxでやろうと思う人は「エディタは自分の好きなものを使わせろ!」とか「GUIだといちいちマウスに持ち替えなきゃあかんやろ。CUIでやらせろ!」とか言い出すような人です。"
ということみたいです。
Ubuntuに限らずLinuxを敢えて利用するってことはそれなりの信念があるのでしょう。
もちろん主にコマンドでの操作です。

詳細は続きから。

2012年8月30日木曜日

DCモータのPWM制御

最近のモータ制御では主流となっているPWM(Pulse Width Modulation)での制御をしてみた。

目的は
1.モータをPWMでドライブする。
2.可変抵抗(ボリューム)で回転数が変えられる。
3.正転、逆転が可能。
の3つ。
大昔の授業でマイコン制御のサンプルとして持ってきてもらったので良い実験材料かと。

で、まあ必要なのがボリュームの位置を読むAD変換と、
出力用のPWMという訳で。

PWM自体はやったことあったので2時間あれば組みきれると思ったら大間違い。
原因はプログラム特有の問題(オーバーフロー)だったりモータ特有の問題(突入電流など)だったり。


まず、手持ちでAD変換ができるチップがATMEGA88Pだったのでこれを使用。
データシートを見ると11番(PD5)と12番(PD6)がPWMの出力端子で、
23〜28番(PC0〜PC5)がAD変換用に使える。

PWM用の端子もたくさんあるみたいだけど今回はOC0xしか使わないので。

モータードライブにはTOSHIBAのTA8428K(S)を使用。
なければ自作でフルブリッジドライバを作るほかない。

ドライバはIN1がHIGH、IN2がLOWで正転、

IN1がLOW、IN2がHIGHで逆転、
両方LOWで開放、
両方HIGHでブレーキだったような気がする。
詳しくはデータシートを。


可変抵抗は今回特に何でもいいので適当。


プログラムリストは続きから。


今回、最も詰まった注意点を先に。
まず、volatile unsigned long でvalue を宣言しているけど、
途中で割り込み排除したのでvolatileは多分不要。

あと、これはint型ではオーバーフローしてしまう(最大値を超えてしまう)ので、必ずlong型に。
これに気づかずボリュームを上げてるのに、ある点で急に回転数が低くなってしまった。


もうひとつはマイコンの電源をACアダプタから取っていて、
ACアダプタが3Aまで流せるんだけど、そこにモータつないでたのも失敗だった。

やっぱりドライバには別電源が必要だと感じた。
モータの突入時(通電時)には大電流が流れるので、PWM制御でモータを動かすときには、
秒間何回も突入が起きて動作が不安定になる。

もっとACアダプタの定格電流が大きければ問題ないかもしれないけど、
今回は3Aだったので突入電流によってアダプタが落ちていたかも。
これに一番苦労させられた。

モータの通電時にアダプタが落ちて、一瞬後に復旧するわけだけど、
このときも通電時なわけでまたアダプタが落ちる。

このせいでモータが動いたと思った瞬間止まって、また動いてを繰り返す。
今回はPWM制御が目的だったから、この反応がむしろ正常に見えてデューティに問題がないかなどのプログラム上の問題を探しに行ったりもした。

また、モータドライバで2V程度電圧が落ちるらしいので、モータ用には少なくとも5V程度はほしい。
定格は30Vなのでよくある箱型の9V電池を使用した。


なので電源とオーバーフローには注意。
とくにAVRのAD変換器の出力は10bit(1024通り)なので。


プログラムの大まかな流れは、
AD変換の出力が0〜1023なので、半分の511で区切り、
0〜511が逆転、512〜1023が正転となってる。
ただし、511近傍では信号を与えない停止状態となってる。
この近傍の広さがdefineにあるBRANGEの値。

あと今回は可変抵抗の出力を電圧として読む必要が無いので、
0〜1023のままで使ってる。


では、以下リスト。

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。

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

2011年3月20日日曜日

LEDバーサライタ再評価

前回のバーサライタでは、

・一方にしか文字が表示できない
・文字をあらかじめ決めておかなければならない
・文字が小さいので遠くから読みづらい
(バーサライタは遠くからの方がよく見えると感じたので)


などの問題があると感じました。
今回はそれをできるだけ改善する方向でいきたいと思っています。

まずは表示方法。
前回はLEDを縦に1列9個でしたが、今回は18個と倍に増やすつもりです。

5mmLEDを使っているので9個だと感覚1mmでも、
(5+1)*9=54mm
なのでたいした大きさではありませんでしたが、
倍に増やすことで表示サイズを108mmまで大きくすることができます。

108mmというとかなり遠くからも見えると思うので、大きいだけで暗くならないように
LEDも赤色に変えることにします。
最近手に入ったから使ってみようと思っただけなのは内緒。


大きくなったからと言って文字を書き換えるのも面倒なので出力はひとつでいきます。
つまり従来と同じ9ピンで18個を点灯させる予定です。

ここで問題になってくるのがマイコンからの出力可能電流で、
AVRの情報みてないですけどPICが±20mAらしいので同等かなーと。

今回LEDを10mA程度で使おうと思っているので、ちょっとオーバー気味かなと思い、
トランジスタを使うことにします。みんな大好き2SC1815!
まだ評価してないですけど、どうせスイッチング動作なので
あんまり気にしないでいいかなーと。(甘い?)


その次にプログラムのスケッチ(と言うと用語的には間違っているかも)。
いうなればアルゴリズムテスト用プログラムです。

今回は動的に表示するのが目標なのでそこを重点的に。

どうやら「関数ポインタ」とかいうので処理できるようです。
関数ポインタは関数に対するポインタでありアドレスを指し示し~なんて言っても
解る人には解るし、解らない人には解りません。

まあ今までのだと関数名(aとかbとか)を直接記入しないといけない
(=書き込み機で書き換えなければいけない)でしたが、関数ポインタを使うことで
関数をポインタの中に格納できます。(=プログラム中で選択できる)


たとえばA_writeという関数があったとして、
これを使用するには
A_write();
と記入する他ありませんでしたが、ポインタに入れると、
int (*pointer_name)();
pointer_name = A_write;
となり、呼び出しは
(*pointer_name)();
となります。カッコで囲んで先頭にアスタリスクです。

これだけだとあまりメリットは感じられませんが、真の使い道は配列にしてからだと思います。

同じく、関数A_writeとB_writeがあったとして、これを呼び出すならば、
A_write();
B_write();
となります。ちょっとC言語をさわったことがある人なら想像つくと思いますが、
これを例えばB_write→A_writeとしたいならば、一度プログラムを書き換えるしかありません。
実行中に選択するならばifとかforとかを使ってループさせれば実現出来ますが、
さらにCとかDとか増えてくるとifが増えてきたりともう大変なことになってきます。

上記を関数ポインタの配列として使うと、
int (*pointer_name[2])();
pointer_name[0] = A_write;
pointer_name[1] = B_write;
となります。呼び出しはもちろん、
(*pointer_name[0])();
(*pointer_name[1])();
となります。

こうするとちょっとメリットが見えてきました。
pointer_nameの配列番号を自由にいじることでfor 0 to 1やfor 1 to 0で
上からだったり下からだったり自由に選択出来ます。

こんな感じで今回はバーサライタに文字の選択を追加しようと思います。
しかしここで予想だにしない問題が!!!
続きます。

2011年3月6日日曜日

GPSロガー3

まずは前回の訂正から。

言っていた通り、前回のままではGooglemapに送信したときにエラー(フリーズ)
することが判明したので修正版をあげておきます。


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

FILE *fr,*fw;
void KMLlayout(void);
void KMLlayout2(void);

int main (void){
errno_t error;

if((error = fopen_s(&fr,"gpsdata.txt","r")) != 0){
printf("gpsdata File Open Error!");
getchar();
return -1;
}
if((error = fopen_s(&fw,"mapdata.kml","w")) != 0){
printf("mapdata File Open Error!");
return -1;
}

KMLlayout();

int count;
double latitude,longitude;
char c[100];
char endflag[10] ="";
char *token,*nexttoken;

while(1){
count =0;
fscanf_s(fr,"%s",c,100);//fscanfのセキュリティ版
token = strtok_s(c,",",&nexttoken);//文字列を指定した文字で区切る(string.h)

/*終了フラグ*/
if(strcmp(token,endflag) == 0){
break;//2回連続で同じ行を読み込んだら終了する
/*最後の行までいくと最後の行を連続で読み続ける*/
}
strcpy_s(endflag,10,token);

/*変換*/
if(strcmp(token,"$GPGGA") == 0){
while(token != NULL){
if (count == 2){//NMEAとgoogleの経度緯度の順が逆なので分ける
latitude = atof(token);//文字列をdoubleに(stdlib.h)
latitude = latitude/100;//googleの位置フォーマットに合わせる
}
else if(count == 4){//別々の変数に入れる
longitude = atof(token);
longitude = longitude/100;
}
token = strtok_s(NULL,",",&nexttoken);//2度目以降はNULL文字
count++;
}
fprintf(fw,"%f,%f,0.000000 ",longitude,latitude);
}
}
KMLlayout2();
fclose(fr);
fclose(fw);
}


void KMLlayout(void){
fprintf(fw,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<kml xmlns=\"http://earth.google.com/kml/2.2\">"
"<Document>"
"  <name>無題</name>"
"  <description><![CDATA[test]]></description>"
"  <Style id=\"style1\">"
"    <LineStyle>"
"      <color>73FF0000</color>"
"      <width>5</width>"
"    </LineStyle>"
"  </Style>"
"  <Placemark>"
"    <name>line</name>"
"    <Snippet></Snippet>"
"    <description><![CDATA[]]></description>"
"    <styleUrl>#style1</styleUrl>"
"    <ExtendedData>"
"          <Data name=\"_SnapToRoads\">"
"        <value>true</value>"
"      </Data>"
"    </ExtendedData>"
"    <LineString>"
"      <tessellate>1</tessellate>"
"     <coordinates>");
}
void KMLlayout2(void){
fprintf(fw,"</coordinates>"
"    </LineString>"
"  </Placemark>"
"</Document>"
"</kml>");
}



これはもう完成版で、前回ミスしていたところの修正とkmlへの対応版となっています。
まだkmlのフォーマットについて理解していない部分があるので現在は直線でしか表示できません。
(「ルートに沿う」が出来ない。これはmapの方で指定できます。)



修正の内容について。
まず、前回は$GPGGAの行の2要素(緯度)と4要素目(経度)になればファイルに書き出す、という
流れに任せたプログラムでしたがkmlでは緯度経度が逆の順に並んでいるので、kmlに書き出すと
「北緯135度,東経45度」というあり得ない数値になっていたのが原因のようです。

そこで修正版では一度緯度データをdoubleに保存しておき(この時点ではatof関数によってcharからdoubleに変換されている)、経度も同じように保存してまとめて表示するという文になりました。

経度は特にdoubleに入れる必要はありませんが、どうせなら表示は1か所の方が見やすいので、
緯度経度ともに変数に格納しました。

下の二つのKMLlayoutは、単にプログラム内にkmlのベース文を表示させるだけのプログラムです。
これとの兼ね合いで最初のFILE宣言がグローバルになっています。

あと、ファイルオープンで自動でダイアログが消えないようにgetcharを仕込みました。
まああってもなくてもいいんですけど、ないと成功したのか失敗したのかわかんないので^^;


出力部分を抜けばかなり短い文になった感じですね。
Excelでオセロ作った時は知識もないしすごい長かった記憶が…(笑
たしか1500行くらい使ったような。

こんな感じでたぶんGPSデータをgooglekmlに変換することができたんじゃないかな?
それにしても標準の関数だけでここまで出来るんだなぁー。なんて。

文字比較と文字→数値、文字分割あたりはすごく便利に感じました。
文字系統が全然理解できていないので簡単に使えるといいですよね。
まあバグなんて個人プログラムだから気にしなくていいし。(その割に_s文ばっかり)


あとはハード的な解決とマイコンの方のプログラムかなー。


2011年3月5日土曜日

GPSロガー2

今回は前回の続き。

前に言ってた通り、kmlのフォーマットをはじめに。
kmlはどうやらGooglemapやGoogleEarthの形式らしくて位置情報を持っています。

ベースはたぶんXML(自分は書けませんが…)です。
XMLベースなので(ということにしておいて)、テキストエディタで開けます。

前回書いた、
「一度DLしたファイルをブラウザで開いてそのリンクからもう一度DLする方法」

で落としてきたファイルをWin標準のメモ帳で開いてみると…。


<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
  <name>無題</name>
  <description><![CDATA[test]]></description>
  <Style id="style1">
    <LineStyle>
      <color>73FF0000</color>
      <width>5</width>
    </LineStyle>
  </Style>
  <Placemark>
    <name>line</name>
    <Snippet></Snippet>
    <description><![CDATA[]]></description>
    <styleUrl>#style1</styleUrl>
    <ExtendedData>
      <Data name="_SnapToRoads">
        <value>true</value>
      </Data>
      <Data name="_SnapToRoads">
        <value>true</value>
      </Data>
    </ExtendedData>
    <LineString>
      <tessellate>1</tessellate>
      <coordinates>
        135.314151,35.215426,0.000000 135.235266,35.367473,0.000000
      </coordinates>
    </LineString>
  </Placemark>
</Document>
</kml>


<Data name ="_SnapToRoads">
 <value>true</value>
</Data>


が二つほど入っているのが気にかかるところではありますが、
ちゃんと動くのでスルーという方向で。


ここでヒントを出しますと、これはGooglemapで表示させると1本の直線です。
お察しの通り

<coordinates>
135.314151,35.215426,0.000000 135.235266,35.367473,0.000000
</coordinates>

がその直線部分になります。
たしか京都付近だったかなー?

その付近なので、座標は日本の[135,35]付近になりますね。
これは東経135度、北緯35度ということです。

今のところ北半球東半分(というか日本)でしか使う予定がないので、
南半球西半分では数値がどのような値になるかは解りません。
(たぶんマイナス表記になると思うんだけどなぁ。)


まだハード(GPS本体)を入手していないので、
先にNMEAデータからKMLデータに変換するプログラムを書いていきます。
扱うのは単にテキストファイルで、ネットに接続する予定でもないので
普通に知っているC言語でやっていきたいと思います。


機械の人間でフローチャート書くのに慣れていないので、脳内構想です。

テキストファイル(読み出しと書き出し2つ)を開く

KML形式のフォーマット(ここでいう<coordinates>以外の部分)を書き出す。
(ここはたぶん不変なので)

読み出しファイルから$GPGGAの行を探す

その行の位置データだけを取得して書き出したファイルに追加する

終わり


すごく簡単に書くとこんな感じです。
KMLフォーマット抜きにするとこんな感じになりました。


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (void){
FILE *fr,*fw;
errno_t error;

if((error = fopen_s(&fr,"gpsdata.txt","r")) != 0){
printf("gpsdata File Open Error!");
return -1;
}
if((error = fopen_s(&fw,"mapdata.kml","w")) != 0){
printf("mapdata File Open Error!");
return -1;
}

int count;
double num;
char c[100];
char endflag[10] ="";
char *token,*nexttoken;

while(1){
count =0;
fscanf_s(fr,"%s",c,100);//fscanfのセキュリティ版
token = strtok_s(c,",",&nexttoken);//文字列を指定した文字で区切る(string.h)

/*終了フラグ*/
if(strcmp(token,endflag) == 0){
break;//2回連続で同じ行を読み込んだら終了する
/*最後の行までいくと最後の行を連続で読み続ける*/
}
strcpy_s(endflag,10,token);

/*変換*/
if(strcmp(token,"$GPGGA") == 0){
while(token != NULL){
if (count == 2 || count == 4){//GPGGA行の2と4要素だけが必要なので
num = atof(token);//文字列をdoubleに(stdlib.h)
num = num/100;//googleの位置フォーマットに合わせる
fprintf(fw,"%f ",num);
}
token = strtok_s(NULL,",",&nexttoken);//2度目以降はNULL文字
count++;
}
}
}
fclose(fr);
fclose(fw);
}


これであとは先頭行に適当に書きつければOK(だと思う)。
重大なミスを発見したので次回、修正します。
googlemapが経度,緯度なのに対してNMEAが緯度,経度だったのが問題。
誰かNMEAのサンプルデータをくれるとすごくうれしいんだけど
なかなか持ってる人っていないよねー。


早く完成させて車載したいなぁ。
じゃあ終わり。

2011年3月4日金曜日

GPSロガー

GPSロガーとは?
3次元位置計測情報を取得し、記録する装置。
取得した情報は地図上に表示されたりする。

製作理由はですね、
・第一種普通免許の取得
・春休み(暇)
・技術の向上
こんなところです。

物作るのに理由なんてありません。アマは。


とどのつまりクルマで走った場所をgooglemap上に記録したかった。
そんな理由なんです。
余談ですけどトド肉を今日食べました。


そんなこんなでプロジェクトスタート。

まずはじめにするべきはフォーマットの確認。
どうやらGPSの位置情報はNMEA-0183で表現されるようです。
$GPGGA,104549.04,2447.2038,N,12100.4990,E,1,06,01.7,00078.8,M,0016.3,M,,*5C
$GPGLL,2447.2073,N,12100.5022,E,104548.04,A,A*65
$GPGSA,A,3,26,21,,,09,17,,,,,,,10.8,02.1,10.6*07
$GPGSV,2,1,08,26,50,016,40,09,50,173,39,21,43,316,38,17,41,144,42*7C
$GPGSV,2,2,08,29,38,029,37,10,27,082,32,18,22,309,24,24,09,145,*7B
$GPRMC,104549.04,A,2447.2038,N,12100.4990,E,016.0,221.0,250304,003.3,W,A*22
$GPVTG,221.0,T,224.3,M,016.0,N,0029.6,K,A*1F
$GPZDA,104548.04,25,03,2004,,*6C

こんな感じのデータ内容らしいです。
実機持ってないのが痛いところですけど
これをベースにプログラム組んでいきたいと思います。

まず、あまりマイコンに負担をかけたくないので2ステップでの予定です。
データの取得と記録→
NMEA-0183形式をGooglemapのXML(KML)形式へ→
Googlemapに位置情報を投稿
こんな感じの2ステップです。


現在2011年3月4日では、
・C言語ベース
・AVRマイコン(atmega88p)を使って情報をSDカードに記録してPCでKMLに
・GPSデータからKMLまでは自動生成であること
・シガーソケットからの給電
を目標にしています。


現在、フォーマットの確認を終えてそこからKMLへのプログラム作りです。
接続方式などは現物を入手してから考えるのでここではスルー。


上記NMEAの形式ではどうやら最上段の$GPGGA行の2要素目、
2447.2038
と、4要素目
12100.4990
が位置情報みたいです。

たぶん、付近にあるNとかEとかは
North(北緯)とEast(東経)の頭文字だと思われます。
これを取得して利用していきます。

そしてこの形式では小数点が2ケタほど右に行っているようなので、
そこを100倍か何かして
24.472038
121.004990
のような感じに変えていきます。

親切に行ごとにGPなんとか~が書かれているのでそれを利用して、

$マークが来たらその先頭の文字列はGPGGAであるかを比較する。

GPGGAだったらその行を取得(要素ごとにスペースが入っているかによって若干変わる)。

行の2要素目と4要素目を取得してKML形式に書き出し。(正確には3と5要素)


こんな感じの流れを想定しました。
KMLのフォーマットなどは次回で。


ちなみにGooglemapでマイマップを作製し、右上のバー(印刷、送信、リンクとかがあるところ)の
「GoogleEarthで表示」ってのをクリックするとKMLファイルがダウンロードできます。
当たり前ですが、このときにちゃんと線を引くなりなんなりしていないと中身を見てもすっからかんです。


そしてここからがミソ、というかそんな感じなんですけど
ここでダウンロードしたKMLは情報ファイルにリンクが張ってあるだけで、
それだけでは意味を持ちません。
なのでそのリンクを辿っていきます。

DLしたKMLをブラウザで開くとURLが見えると思うので、
それをアドレスバーにぶっこんじゃってください。
そうするともう一度KMLのダウンロードが開始されます。

ミソ、といってもやることはこれだけなんですけど
これが出来ないと位置データ自作は難しいなぁ。

やっぱり完成したものを一回見てそれをいじってみないと
どこが必要な部分かが分かんないんだよなー。

そんな感じで製作(してないけど)1日目終了。
(^-^)/~

2011年1月21日金曜日

LEDバーサライタの制作


試験前の少しの空き時間を利用してAVRマイコンでLEDバーサライタを作ってみました。
バーサライタとは残像を利用して文字列(に限らないが)を表示するシステムです。
(写真はMASAKと表示されています)
製作費は180(マイコン)+5x9(LED9個)+1(カーボン抵抗1個)で、250円程度です。

マイコンは知ってる方も多いと思いますがマイクロコントローラ、
またはマイクロコンピュータと呼ばれる小さなコンピュータで
内部に記憶装置、メモリ、CPUなどが内蔵されています。


構造はLEDを直列に並べ、その点滅で象るものです。
(写真はブレッドボードに置いた状態。撮影の都合上横に並んでます。)


「T」と表示したいなら、
○→●●●●●→
○→○○●○○→
○→○○●○○→
○→○○●○○→
○→○○●○○→

縦にLEDが5つ並んでいて、それを5回点滅させながら右にスライドさせます。
白丸は消灯、黒丸は点灯です。
矢印の方向にスライドすると図のような感じになります。


点滅の速度は一眼カメラなどのシャッターを開きっぱなしにするなら
どれだけの時間でもいいんですけど、人間の目であればコンマ数秒で残像は消えてしまうので
「出来るだけ短い時間で点滅させる」ことが重要になってきます。
(あまり遅すぎると、2つ目の縦のラインが点滅したときに1つ目のラインは消えてしまう)

けどあまりにも早すぎると、スライドさせる速度が間に合わなくなってしまって
ライトが重なり、文字が判別できなくなります。

いろいろ試してみたところ1回の点滅は5ms(ミリ秒・0.005秒)
くらいがちょうどいいという結果になりました。
もっともこれはスライドさせる速度などによって上下します。

そしてマイコンなどの応答速度によって、あまり速い速度だと点滅が上手くいかないかもしれません。


以下制作の手順をまとめてみました。

1、マイコン本体やライタ、LED、カーボン抵抗、電池などを準備。
マイコンはatmel社のAVRマイコンatmega88pを使用。
atmega88pの仕様書は以下に。(直リンク失礼)
http://www.atmel.com/dyn/resources/prod_documents/8025s.pdf

ライタは純正品を使っています。
書き込み方などは省略します。


2、プログラムを考える。
といってもLEDの点灯はHighかLowしかない(操作上は)ので、2進で制御しました。

大きさをある程度確保したかったので縦9列になっていますが、
ちょうどいいフォントがなかったので全て手打ちです。(これが一番きつかったかも)

そしてひと固まりのポート(PORTDなど)は8個ひと組なので
一番上のLEDだけはPORTBで動かしています。

マイコン自体の操作はニコニコの方がわかりやすい解説をされているので省略。
「電子工作のススメ」で検索すればHITするかと思います。

プログラムは下部に乗っけときます。


3、回路を考える。
省略します…と言いたいくらい簡単です。
PORTD0~7、PORTB0のみの使用で、あとは電源への4本くらいです。
PORTには簡略化のためすべてLED直付けなので迷うことはありません。
ブスっといっちゃいましょう。極性には気をつけてね(´・ω・`)

プルアップ?そんなの分かんない




そして初めて回路図書いてみました。


ちょっと書き方が気持ち悪いですけど、間違ってはいないはず…。
自分がわからなかったところを考慮してVCCとかGND(接地)とかいう記号は使ってません。
ちなみに上側が半円の切欠のある方です。

これでボードからライタを取り外せば(ここ重要)めでたく完成となります。
USBにライタをつながずにライタからボードにつながっていた場合、動作しません。
自分もはじめのころここで迷ったんだよなー。
だってライタ外すと再接続しなきゃいけないじゃない
ISPケーブルをライタから抜けばそれで大丈夫です。(説明がわかりづらい)

基本的なところはこれくらいにして以下プログラム。
お好きにspace分のdelayとかいれればいいとおもいます。

お疲れ様でした。

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

void A_line();
void B_line();
void C_line();
void D_line();
void E_line();
void F_line();
void G_line();
void H_line();
void I_line();
void J_line();
void K_line();
void L_line();
void M_line();
void N_line();
void O_line();
void P_line();
void Q_line();
void R_line();
void S_line();
void T_line();
void U_line();
void V_line();
void W_line();
void X_line();
void Y_line();
void Z_line();

int main(void){

DDRB = 0b11111111;
DDRD = 0b11111111;

while(1){

H_line();
E_line();
L_line();
L_line();
O_line();

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}
}

void A_line(){
PORTB = 0b00000000;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00001000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00001000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00001000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00001000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11111111;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void B_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11101110;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void C_line(){
PORTB = 0b00000000;
PORTD = 0b11111110;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b10000010;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void D_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b10000010;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b01000100;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void E_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void F_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000000;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void G_line(){
PORTB = 0b00000000;
PORTD = 0b11111110;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00001001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b10001110;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void H_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void I_line(){
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void J_line(){
PORTB = 0b00000000;
PORTD = 0b00000110;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111110;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void K_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00101000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b01000100;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b10000010;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void L_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void M_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11000000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b01110000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b01110000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11000000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void N_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11000000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b01110000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00011100;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000110;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void O_line(){
PORTB = 0b00000000;
PORTD = 0b11111110;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11111110;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void P_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11100000;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void Q_line(){
PORTB = 0b00000000;
PORTD = 0b11111110;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000101;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000011;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11111111;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void R_line(){
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00011000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010100;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b11100011;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void S_line(){
PORTB = 0b00000000;
PORTD = 0b11100010;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00010001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b01001110;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void T_line(){
PORTB = 0b00000001;
PORTD = 0b00000000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00000000;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void U_line(){
PORTB = 0b00000001;
PORTD = 0b11111110;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111110;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void V_line(){
PORTB = 0b00000001;
PORTD = 0b11111000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000110;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000001;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000110;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111000;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void W_line(){
PORTB = 0b00000001;
PORTD = 0b11111100;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000111;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00111100;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00111100;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00000111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11111100;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void X_line(){
PORTB = 0b00000001;
PORTD = 0b10000011;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b01000100;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00111000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00111000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b01000100;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b10000011;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void Y_line(){
PORTB = 0b00000001;
PORTD = 0b11000000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00100000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00011111;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00010000;
_delay_ms(5);
PORTB = 0b00000000;
PORTD = 0b00100000;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11000000;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}

void Z_line(){
PORTB = 0b00000001;
PORTD = 0b00000111;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00001101;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00011001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b00110001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b01100001;
_delay_ms(5);
PORTB = 0b00000001;
PORTD = 0b11000001;
_delay_ms(5);

PORTB = 0b00000000;
PORTD = 0b00000000;//space
_delay_ms(5);
}