
Vic2020mainboard
danwerner21/vic2020
A Vic-20 clone created with [almost] all readily available parts

無線GSEのコードとか
GSEver2 is an open-source printed circuit board by tetsu26, from the tetsu26/WirelessGSE repository on GitHub. It is a 2-layer board with 29 parts on 62 nets, routed with 233 tracks and 6 vias.
It is built around the 2SC1815 and 946H-1C-5D. Its parts include 6 connectors, 5 resistors, 4 transistors, 4 switches and 1 diode.
東北大学FROM THE EARTH用のGSE制御システムVer.2の解説です.
質問等は tetsushi_m[at]outlook.jp まで.
FTEのGSEを無線化した経緯について書いておきます.
時は遡ること2017年,この年の能代で突然,点火点と射点の位置が20mくらい伸びたため,今まで使っていたGSEのケーブルの長さが足りなくなってしまったのです.そこで燃焼班の皆様はLANケーブルを調達し,なんか頑張ってどうにかなった(詳しくはよく知らん)のですが,そのときの燃焼班のケーブル半田付けなどがまぁそれはそれは残念だったので,電子班でどうにかしようということになりました.んで,当時流行だった無線GSEに憧れた7期はどうせならFTEのGSEも無線化しちまおうとなったわけです.自然な流れですね.そして当時電子班班長だった私は電子班の誰かに無線GSE開発を押しつけようと声をかけ続けた訳ですが,何かと理由をつけて全員に断られてしまったので仕方なく自分でやることにしたわけです.
そうして無線GSEを作ることになってしまった私ですが,当初はロケットの電装に比べれば,スイッチの状態を送信するだけなんで簡単だろうと高をくくっていた訳です.まぁ"スイッチの状態を送るだけなら"実際簡単な訳ですが.実際作ってみるといろいろな障壁がありました.
送信レートの問題
IM920で使ってる920MHz帯は送信時間の制限が厳しくて,データを連続送信できないため,5Hz位でしかスイッチの状態を反映できない.
IM920 の通信距離
7km飛ぶとかいっときながら見通しでも300m位しか通信できない.ちょっと怖い.
打ち上げシーケンス中に通信途切れた時の対処
ダンプするしかない.悲しい.
卍伊豆大島卍
活火山なだけあって何かが島から出ている.無線が飛ばない.見通しで100mがやっと.
責任
無線GSEがしくじるとロケットが飛ばない訳でみんなの努力が報われない.打ち上げ前は気が気じゃない.
そのたもろもろ.思ったより大変だった.
そんなこんなで無線GSEを作っていると思うわけです.点火点と射点,ケーブルでつなげばよくね? 俗に言う原点回帰って奴です.有線なら通信の安定性とか考えなくていいし,ケーブルの断線だけ気をつけていればいいよね.そこで電子班何人かで有線GSEを総点検し,やばそうな半田付けは直し,ケーブルも完璧に作り直しました.
つまり,このくそ長いはじめにで何が言いたいかというと,「無線使うな有線を使え」 ということです.きっとこれを読んでいるあなたは不幸にも無線GSEを押しつけられてしまったしがない電子班員でしょう.ご愁傷さま.燃焼班員にあったら是非伝えてください. 「無線使うな有線を使え」 と.あいつらはこの無線GSEのやばさを知りません.健闘を祈ります.
無線のチャンネルは?
プログラムコードからは変更できない.IM920の設定から変更する.ググれば出てくるし,この辺のサイトを参考にすべし.
安全対策は?
万が一Fill中に通信が途絶えてもFillが止まるように,Fillには時間制限がかかっている.時間制限はロケット側のGSEのプログラムを書き換えることで変更できる.デフォルトでは60秒以上Fillが続くと強制的に30秒ダンプする.
同様に,Oxyも60秒以上入らないようになっている.このときはダンプせず,システムを再起動する.
\SourceCode にあります.mbedオンラインコンパイラにコピペして使ってください. ロケット側と点火点側でソースコードが分かれてるんで気をつけてください.
ソースコードはc++(ほぼC)で書いてあります.一応頭から説明しておきます.
#include<mbed.h>
#include<IM920.h>
#include<cstring>ライブラリのインポートです(それはそう).
#define IM920_TX p13
#define IM920_RX p14
#define IM920_BUSY p11
#define IM920_RESET p12
#define IM920_SERIAL_BANDRATE 19200//im920の通信レートIM920関係のピン設定ですね.
DigitalOut myled(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
DigitalOut led_fill(p16);
DigitalOut led_dump(p18);
DigitalOut led_oxy(p20);
DigitalOut led_fire(p21);
DigitalOut led_1(p24);
DigitalOut led_2(p23);
PwmOut buzzer(p26);
DigitalIn fill(p15);
DigitalIn dump(p17);
DigitalIn oxy(p19);
DigitalIn fire(p22);
IM920 im920(p13, p14, p11, p12,19200);//無線通信用のserialクラス
Serial pc(USBTX, USBRX);そのたもろもろのピン設定です.基板自作したときは適宜変えてください.
// グローバルな奴ら
char send_data[8]; //送信するデータを格納する変数
char recv_data[8]; //受信すry)
int cb_count = 0; //割り込み回数を数えるやつ
int i = 0; //一秒間隔で赤いLEDを点滅させるのに使うグローバル変数です.
int fire_buzzer(int i)
{
if(i == 1)
{
buzzer.period(1.0/440.0); //多分"ラ"
buzzer.write(0.5f);
wait(0.5f);
buzzer.write(0.0f);
}
return 0;
}これは fire をオンにしたときにブザーから音を出すための関数です.音程が気に入らない人は変えてください.
void callback () { //受信時の割り込み関数(受信したときに送信するコード)
int i;
cb_count++; //割り込みの回数を数える変数
i = im920.recv(recv_data, 8);
recv_data[i] = 0;
pc.printf("recv: '%s' (%d)\r\n", recv_data, i);
if (recv_data[0] == '5' || recv_data[7] == '5') //きちんとデータを受け取れたか確認
{
led_fill = recv_data[1] - '0';
led_dump = recv_data[2] - '0';
led_oxy = recv_data[3] - '0';
led_fire = recv_data[4] - '0';
fire_buzzer(led_fire);
}
//8文字1セットで送ることにする
send_data[0] = '5'; //データ始まりの合図
send_data[1] = '0'+(fill.read()^ 1); //プルアップしてるからHiとLoを反転
send_data[2] = '0'+(dump.read()^ 1);
send_data[3] = '0'+(oxy.read()^ 1);
send_data[4] = '0'+(fire.read()^ 1);
// 5~6はとりあえず未使用これはim920が受信したときに実行される予定の関数です.グローバル関数にiがあるのにローカルでもiを宣言して使うくそコードになってますね,今気づきました.ここからわかりにくいと思うので詳しく書いておきます.
i = im920.recv(recv_data, 8);
recv_data[i] = 0;
pc.printf("recv: '%s' (%d)\r\n", recv_data, i);この辺はおまじないです.書いておいてください.
if (recv_data[0] == '5' || recv_data[7] == '5') //きちんとデータを受け取れたか確認
{
led_fill = recv_data[1] - '0';
led_dump = recv_data[2] - '0';
led_oxy = recv_data[3] - '0';
led_fire = recv_data[4] - '0';
fire_buzzer(led_fire);
}これは効果あるかは謎ですが,受信したデータの整合性を確認しているつもりです.受信データ(8桁)の最初と最後の数字は5なのでそれだけ確認しています.
その後のled_fill = recv_data[1] - '0';ですが,これは受信した8桁の2文字目がfillの状態を示しているのでそれをスイッチについたLEDに反映しています.受信したデータはrecv_dataに格納されているのですが,ASCIIコードなので0のASCIIコードを引くことで元の送信した数字に戻しています.ほかも同じです.
//8文字1セットで送ることにする
send_data[0] = '5'; //データ始まりの合図
send_data[1] = '0'+(fill.read()^ 1); //プルアップしてるからHiとLoを反転
send_data[2] = '0'+(dump.read()^ 1);
send_data[3] = '0'+(oxy.read()^ 1);
send_data[4] = '0'+(fire.read()^ 1);
// 5~6はとりあえず未使用
send_data[5] = '0';
send_data[6] = '0';
send_data[7] = '5'; //データ終わりの合図この辺はスイッチの状態を読み取って送信するデータを作っています.send_data配列の5と6は将来のために未使用です.送る文字数を8文字にしたのはなんとなくきりがいいからです.
im920.sendData(send_data,8); //8文字送りますよーってやつそしてここで上で作った文字列を送信しています.
void callback2() //受信割り込みの回数を数える関数
{
if(cb_count == 0)
{
pc.printf("yabame\r\n");
NVIC_SystemReset(); //一秒間に一回も通信しなかったらリセットする
}
else
{
cb_count = 0;
if(i == 0)
{
led_2 = 1;
i++;
}else{
led_2 = 0;
i = 0;
}
}
}これは接続が切れたときの対処です.コードをざっくり見てもらうと気づくと思うのですが,このコードには「受信したら割り込み処理で送信する」機能しかないので,一度接続が切れる(というかデータのやりとりが途絶える)と復帰できなくなる問題があります.なのでcallback2()関数を1秒ごとに起動してもしその前1秒間に一度も通信していなかったらこのmbedをリセットしてmain()関数をもう一度頭から実行します.NVIC_SystemReset()ってのはmbedのリセットボタンを押した状態をコードから作れる魔法の言葉です.
int main()
{
//各スイッチをプルアップする
fill.mode(PullUp);
dump.mode(PullUp);
oxy.mode(PullUp);
fire.mode(PullUp);
im920.init();
//Im920受信の割り込みを設定
im920.attach(callback);
pc.baud(115200);
pc.printf("Wireless GSE controll system started!!\r\n");
Ticker timeout;
timeout.attach(&callback2,1);
myled = 1; //設定完了の合図
led_1 = 1;
im920.poll();
im920.sendData(send_data,8);
while(1){ ここは特に説明することもない気がします.セットアップの時に1度データを送信します.
同じように解説書いておきます.
#include<mbed.h>
#include<IM920.h>
#define IM920_TX p13
#define IM920_RX p14
#define IM920_BUSY p11
#define IM920_RESET p12
#define IM920_SERIAL_BANDRATE 19200//im920の通信レート
//LED&SWITCHたち
DigitalOut myled(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
DigitalOut fill(p21);
DigitalOut dump(p22);
DigitalOut oxy(p23);
DigitalOut fire(p24);
IM920 im920(p13, p14, p11, p12,19200);//無線通信用のserialクラス
Serial pc(USBTX, USBRX);まぁこの辺は説明するまでもないでしょ.
char send_data[8]; //送信するデータを格納する変数
char recv_data[8]; //受信すry)
int fill_count = 0; //fillの割り込みの回数を数えるやつ
int oxy_count = 0; //oxyの割り込みの回数を数えるやつグローバル変数の定義.
void callback () {
int i;
int fire_count = 0;
i = im920.recv(recv_data, 8);
recv_data[i] = 0;
printf("recv: '%s' (%d)\r\n", recv_data, i);
if (recv_data[0] == '5' || recv_data[7] == '5') //きちんとデータを受け取れたか確認
{
fill = recv_data[1] - '0';
dump = recv_data[2] - '0';
oxy = recv_data[3] - '0';
fire_count = recv_data[4] - '0';
if(fire_count == 1 && oxy == 1){
fire = 1;
}else{
fire = 0;
}
}
/*
for(int i = 0; i < 8; i++)点火点側のcallback関数とほとんど同じです.ただ,oxyが入ってないとfireがオンにならないようにしてあります.
void fillcount() //受信割り込みの回数を数える関数
{
if(fill == 1)
{
fill_count += 1;
}else{
fill_count = 0;
}
if(oxy == 1)
{
oxy_count += 1;
}else{
oxy_count = 0;
}
printf("fill_count: %d\r\n",fill_count);
printf("oxy_count: %d\r\n",oxy_count);
if(fill_count >= 60)
{
fill = 0;
dump = 1;
printf("recovery mode!!! Dump 30second\r\n");
wait(30);この関数を1秒に一回割り込みさせることで,fillがオンになってる秒数などを数えています.
if(fill_count >= 60)の60をいじるとFill時間に制限をかけられます.60の時は一分以上はFillできないという具合です.
int main()
{
pc.baud(115200);
pc.printf("*** IM920\r\n");
/* 受信側との接続を確立する */
im920.init();
im920.attach(callback);
myled = 1; //設定完了の合図
Ticker fill_limit;
fill_limit.attach(&fillcount,1);
im920.poll();
while(1){
im920.poll();
//wait_ms(1);
}
}特にいうことはないです.
Ticker fill_limit;
fill_limit.attach(&fillcount,1);でfillcount関数に1秒おきの割り込みを設定しています.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 4 | 2SC1815 | Package_TO_SOT_THT:TO-92_Inline | Q1, Q2, Q3, Q4 |
| 4 | 8.2k | Resistors_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal | R1, R2, R3, R4 |
| 4 | 946H-1C-5D | 946H1C5D | K1, K2, K3, K4 |
| 1 | 1k | Resistors_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal | R5 |
| 1 | BP5293-50 | TO254P570X1690X1800-3P | PS1 |
| 1 | DC_IN | Connectors_JST:JST_XH_B02B-XH-A_02x2.50mm_Straight | J7 |
| 1 | Dump | Connectors_JST:JST_XH_B02B-XH-A_02x2.50mm_Straight | J2 |
| 1 | Fill | Connectors_JST:JST_XH_B02B-XH-A_02x2.50mm_Straight | J1 |
| 1 | Fire | Connectors_JST:JST_XH_B02B-XH-A_02x2.50mm_Straight | J4 |
| 1 | IM920 | fte-denshi:IM920 | IM1 |
| 1 | LED | LEDs:LED_D3.0mm | D1 |
| 1 | LEDs | Connectors_JST:JST_XH_B05B-XH-A_05x2.50mm_Straight | LEDs |
| 1 | LOGO | fte-denshi:LOGO | G*** |
| 1 | MBED-LPC1768 | DIPS2286W63P254L5370H300Q40N | MBED LPC1768 |
| 1 | MountingHole_3.2mm_M3_ISO14580 | Mounting_Holes:MountingHole_3.2mm_M3_ISO14580 | M3 |
| 1 | Oxy | Connectors_JST:JST_XH_B02B-XH-A_02x2.50mm_Straight | J3 |
| 1 | Switches | Connectors_JST:JST_XH_B06B-XH-A_06x2.50mm_Straight | J6 |
The 26 most common of 29 parts.
29 parts, built around the 2SC1815 and 946H-1C-5D. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the tetsu26/WirelessGSE repository on GitHub, at the commit this page was made from: the board is PCB/GSEver2.kicad_pcb. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask tetsu26 before reusing the design.

danwerner21/vic2020
A Vic-20 clone created with [almost] all readily available parts

GuitarML/GuitarPedalPCBs
Collection of KiCad circuit board designs for guitar pedals you can build yourself.



IdahoLabResearch/AcCCS
A collection of tools and scripts used to communicate and emulate Electric Vehicle Communication Controllers (EVCC) and Supply Equipment Communication Controllers (SECC).

StudioKAT/Toolbox
主な機能: - オーディオ/CVミキサー(加算・減算) - CVへのオフセット追加(5V/10V)・極性反転 - 1:3 バッファード・マルチプル - 2:2 ユニティミキサー - 3:1 アベレージミキサー(各チャンネルのゲイン = 1/3) - SIGNセクション:インバーター / 半波整流 / 全波整流 - LOGICセクション:アナログOR / アナログAND - S&Hセクション:サンプル&ホールド / ホワイトノイズ出力…

