ラベル 組み込み の投稿を表示しています。 すべての投稿を表示
ラベル 組み込み の投稿を表示しています。 すべての投稿を表示

2013年6月9日日曜日

ロケット搭載品を作る

今までの数少ない経験から ロケットに自分の作った電子回路を載せる時の注意点とか書く予定です

電源について

基本的に数百メートル程度のモデルロケットなら乾電池等で問題ないはずです
Ni-CdやLi-Po等も使えるはず
扱いやすさで言えば006Pとかも使えます

しかし高高度まで飛ぶ信頼性の求められる用途や特殊な環境での打ち上げの場合は乾電池やNi系/Li系二次電池は避けたほうがいいようです
この場合リチウム電池(1次電池)を選択するべきです
2CR5などのリチウム電池は-40℃から+70℃の範囲で使用することができます
特殊な場所を除いて、寒冷地などでも使用出来ます

リチウム一次電池と他の電池の違いは電解液にあります
一般的に販売されている電池は電解液に水を使っています
そのため内部が0℃以下になると電解液としての能力を失います
しかしリチウム電池の場合は融点が-40℃の溶媒を使用しているためこの温度まで使えます

リチウム電池の容量などはPanasonicの法人向けページに記載されています
http://industrial.panasonic.com/www-ctlg/ctlgj/qAAA4000_JP.html

2CR5は電池から電極が出ているためハンダ付けが容易です
ただし長さが45mmあるので小型化が必要な用途には使えません
CR-P2は2CR5より直径が少しちいさく、高さが9mmほど短くなります
ただし少し幅が広くなっています
CR-P2は電池に直接ハンダ付けする必要が有るため
容量の大きなハンダゴテで手早くする必要があります
基本的に2CR5を使用し、どうしても狭い場所に入れる必要が有る場合はCR-P2を使うなどの使い分けがいいでしょう

また電池を使用する場合 基本的に電池ボックスは使うべきではありません
一般的な電池ボックスは簡単な衝撃で電池が外れてしまいます

操作系

基本的にロケットなど高G環境にさらされる場合スイッチを使用するべきではありません
そもそも一旦飛んでしまえば手の届かない場所に行くのに
人間が操作するための部品は必要ありません
スイッチを載せる場合は少なくとも誤動作した場合にでも問題ないソフトウェアを構築してください

ただしリセットスイッチ テメーはダメだ

リセットスイッチは確実に分離しておいてください
また電源スイッチも避けるべきです
電源スイッチはリセットスイッチと同様のリスクがあります
むしろ中途半端に電圧が低下する分リセットスイッチよりも質が悪いです
絶対に電源スイッチが必要なら耐振動性のあるスイッチを使用してください

テレメトリ

飛距離数百m程度のモデルロケットであればXBeeで十分です
XBeeモジュールは一応300hPa程度まで引いても動くのを確認しました
(1個しか試していないですが)

それ以上の数km以上になると簡単に扱えるモジュールはありません
アマチュア無線等資格が必要になります

平面に移動するだけなら3G回線等が使えますが
ロケットは垂直に移動してしまうため使えません

電装系

基本的に基盤対電線の接続でピンヘッダを使うべきではありません
ピンヘッダ/ピンソケットの組み合わせは基盤対基盤に使う程度に留めておくべきです
(十分にピン数の多い/16p以上であれば対電線にも使えますが その場合はフラットケーブルを使用し圧着ピンソケットを使ってください)
基盤対電線でピン数が2本や4本程度の場合は簡単に抜けないようなコネクタを使います
JST-EHやJST-XAがいいでしょう
前者は小さなコネクタですし 後者は大きくなりますがロック機構がついています

宇宙用になると金メッキでネジ止めできるコネクタ等になりますが
弾道飛行程度であれば必要ないと思います

防水

海上で回収するようなロケットではデータを保護するために防水ケースに入れる必要があります
しかし防水は並大抵のことではなく
大丈夫だと思っても浸水していたりします
ケースはタカチ等の防水に特化したケースを使用し、加工は最小限にとどめてください
家庭用のタッパー程度では簡単にフタが外れるので避けるべきです

基盤

可能であれば基盤は外注したほうが信頼性が高く
自由度もはるかに高くなりますが
実装までやってもらうと物凄い値段になります
(1枚数万円になることも 使い捨てで使える値段ではない。。。)
ユニバーサル基板で作る場合はなるべくスズメッキ線で配線し
ジャンパワイヤは最小限に留めてください
ジャンパワイヤは曲げる力に対して多少有利だと思われますが
どの配線がどこに行くのかが掴みづらくなります
ジャンパワイヤを使う場合は種類によって色を変える等の配慮が必要です
2.54mmピッチで配線されるスズメッキ線は実装密度の点では不利ですが
簡単に目視で配線が確認できるという利点があります

部品を実装する際に
背の高い部品はなるべく寝せて基板に固定するようにしてください

キャパシタ

電解コンデンサ等は中に液体が入っているため、真空中に長時間晒されると容量抜けを起こす場合があります
電解コンデンサは基本的に使用せず、セラミックコンデンサなどを使ってください
最近のセラミックコンデンサは100uFとかも普通に売ってるので
小さめの電解コンデンサ程度の容量はあります


2012年8月16日木曜日

年月日時分秒からUNIXtimeに

年月日時分秒をUNIXtime(秒)に変換する関数です



 int YMDhms2s(int Y, int M, int D, int h, int m, int s) {
    int y = Y - 1970;
    int res = 0;
    while(y > 0) {
        if ((y % 4) == 0 && (y % 100) != 0 || (y % 400) == 0) {
            res += 31622400;
        } else {
            res += 31536000;
        }
        y--;
    }
   
    switch(M - 1)
    {
    case(12): { res += 2678400; }
    case(11): { res += 2592000; }
    case(10): { res += 2678400; }
    case( 9): { res += 2592000; }
    case( 8): { res += 2678400; }
    case( 7): { res += 2678400; }
    case( 6): { res += 2592000; }
    case( 5): { res += 2678400; }
    case( 4): { res += 2592000; }
    case( 3): { res += 2678400; }
    case( 2): {
        if ((Y % 4) == 0 && (Y % 100) != 0 || (Y % 400) == 0) {
            res += 2505600;
        } else {
            res += 2419200; }
              }
    case( 1): { res += 2678400; }
    default : { break; }
    }

    res += (D - 1) * 86400;

    res += h * 3600;
    res += m * 60;
    res += s;
   
    return(res);
}

まずは年を秒に変換します
めんどくさいのでwhileを使いましたが
すっげー遅くなるので本来は使うべきではない

次に月を秒に変換しますが
ここは
1. 1ヶ月の長さがまちまち
2. 2月は閏年を考慮する必要がある
という理由により
switchを使っています

そして日 時 分 秒をそれぞれ計算していきます
流れとしては非常に簡単
一応正常に動いてるっぽいので 大丈夫なはずです

なお閏年判定のコードはwikipediaから拝借しました

このコードはUNIXtimeに変換するものですが
定数の変更でNTPtimeも対応可能なはずです

前にUNIXtimeを文字列に変換する関数もおいてるので
それと組み合わせれば色々と遊べます
まぁ組み込みとかの内の一部用途でしか使い道無いんですが

一応32bitだと2100年くらいまで処理できるので
しばらくの間は大丈夫だと思います

2012年8月14日火曜日

strstr 関数

strstr関数です
文字列の中から文字列を検索しポインタを返却
という感じの関数です
GCCでコンパイルしたら警告出ます
const charをcharとして戻り値に入れてるからだと思いますが


標準ライブラリ

自分でちょこちょこ作ってる標準ライブラリの関数を
ここに貼り付けることにします
理由:あとで探すのめんどくさくなってきた

最低限の動作確認はしていますが
ホンモノとまったく同じ動きをするという保証はどこにもないので
あまり使わないほうが懸命です

string.h周りが多くなると思いますが

2012年8月11日土曜日

自作strtok関数

GPSのデータのデコードにstrtokを使ったら楽なんじゃないかな
とか思って 自分で作ってみました

本来のstrtokは
char *strtok(char *s1, const char *s2);
ですが
今回はそんなに高性能じゃなくてもいいので
uint8_t *StrtokB(uint8_t *s1, const char s2);
として
複数の文字を指定する機能は付けていません

以下コード

2012年7月26日木曜日

Cで度分形式を度に変換する

GPSから出力されるNMEAの度分形式を度に変換するコードです



  1. #include <stdio.h>
  2. void dm2d(const char *str, char *data) {
  3.     int cCnt = 0, i = 0;
  4.     int d = 0, m = 0, cm = 0, cmc = 0;
  5.     while(*(str + cCnt) != '.') { cCnt++; }
  6.     while(i < (cCnt - 2)) { d = (d * 10) + (*(str + i++) - '0'); }
  7.     while(i < (cCnt)) { m = (m * 10) + (*(str + i++) - '0'); }
  8.     i++;
  9.     while(*(str + i) != '\0')
  10.     { cm = (cm * 10) + (*(str + i++) - '0'); cmc++; }
  11.     sprintf(data, "%3d.%0*d", d, cmc + 1, (((m * 10000) + cm) * 10) / 60);
  12. }
  13. int main(void) {
  14.     char str[20];
  15.     char data[20];
  16.     scanf("%s", str);
  17.     dm2d(str, data);
  18.     printf("%s\n", data);
  19.     return(0);
  20. }

浮動小数点数を使っていないので標準的なprintf等を使わなくても簡単に出力できます

桁数が少ない等の問題はありますが
とりあえず正常に動いてるっぽいので置いておきます
気が向いたら度から度分秒に変換したり度分から度分秒に変換するコードも書くかも

2012年5月15日火曜日

ARMの変数型名

ARMは環境依存の変数型を無くすために普通のCとは違う名前で型が宣言されてます
ってことで その一覧です


通常の宣言 CMSISでの宣言
-
signed long - int32_t
- signed short - int16_t
- signed char - int18_t
- signed long const const int32_t
- signed short const const int16_t
- signed char const const int8_t
volatile signed long - __O int32_t
__IO int32_t
volatile signed short - __O int16_t
__IO int16_t
volatile signed char - __O int8_t
__IO int8_t
volatile signed long const __I int32_t
volatile signed short const __I int 16_t
volatile signed char const __I int8_t
- unsigned long - uint32_t
- unsigned short - uint16_t
- unsigned char - uint8_t
- unsigned long const const uint32_t
- unsigned short const const uint16_t
- unsigned char const const uint8_t
volatile unsigned long - __O uint32_t
__IO uint32_t
volatile unsigned short - __O uint16_t
__IO uint16_t
volatile unsigned char - __O uint8_t
__IO uint8_t
volatile unsigned long const __I uint32_t
volatile unsigned short const __I uint16_t
volatile unsigned char const __I uint8_t

↑の表のように 用途によって 色々と決まりごとがあるみたいです
(excelからコピペしただけなので見づらいですがご了承ください)

もちろん普通のCのようにintとかcharとかboolも可能ですが
この表に従ったほうが環境依存が減るので楽なんだそうです
覚えるのめんどくせーよ…

で ちょっと解説
かなり憶測を含んでるので間違ってたらごめんなさい
まず型の大きさですが
これはint+ビット数で決まります
コンパイラ依存のビットサイズじゃないので
移植が楽だけではなく 読むときにも楽なんだそうです

signed/unsignedですが まぁこれは説明しなくてもわかりますよね
符号あり/なしの区別です
符号ありはint 符号なしはuintです
constは定数か否かみたいな意味合いもありますが
組み込みの場合はRAMかROMかという違いもあります
でもまぁあまり意識することはないと思います

で 問題なのがvolatileっていう国の名前みたいなモノ
これはコンパイラの最適化を無効化するみたいな意味があります
例えば
uint8_t flag = 1;
while(flag) { ... }
というコードがあったて ブロックの中でflagを書き換えていない場合
コンパイラは
while(1) { ... }
と書き換えます

これは「どーせ値が変更されることはないんだから判定するだけムダ」という理由によるものですが
もしかしたらこのflagは割り込みで変更される可能性があるかもしれません
例えばシリアルの送信完了でRESETされる場合
本来は送信が終了されるまで待つだけのはずなのに
実際は無限ループに陥ってしまいます

これを回避するためにvolatileをつけることにより
「この変数は外部から変更されるので強い最適化はしないように」
ということになります

volatileについてはこのページがわかりやすいです

__IOだけでなく__Oも有るのは
コード中から間違って書き換えないように ということだと思います
が __Oを使う用途というのはあまり思いつかない(無いわけではない)


とりあえず こんなところですが
今まではARMでも普通にintとかcharとか使ってたけど
これから少しずつint32_tみたいな書き方に移行していこうかなぁ と 思ったり