shit_raccoonの電子工作日記
http://w.atwiki.jp/shimizunochikara/
shit_raccoonの電子工作日記
ja
2014-03-07T03:28:35+09:00
1394130515
-
shit_raccoonの自己紹介
https://w.atwiki.jp/shimizunochikara/pages/13.html
-名前: shit_raccoon
-年齢: 24歳
-趣味: 電子工作, 買い物, 自転車, 写真
-使っているPC: Macbook Air 13(Mountaion Lion), 自作デスクトップPC(Windows 7 64bit), Let's note W7(windows 7 32bit)
-将来の夢: 素敵なものを作れるようになる事
2014-03-07T03:28:35+09:00
1394130515
-
最近思う事
https://w.atwiki.jp/shimizunochikara/pages/26.html
2014/3/7
最近思う事は、電子工作のハードルがものすごく下がっているということだ。正直、電子回路なんて殆どわからなくても、V=IRさえ考えなくても、なんとなく繋げれば動いてしまう。プログラムに関してもサンプルコードを少しいじればすぐに動いてしまう。これってすごいことだけど、ある意味怖い事だ。ものは捉え方次第だと思うが。
僕のような人間は、動けばいいと思ってしまう所があって、いったん動いてしまうと、なぜ動いているのか、これで本当に問題がないのかといったことを考えない。でも、そういった知識は応用が効きにくい。それは自分の知識として噛み砕けてないからだ。ブロックを組み合わせる事はできても、ブロックの中身がどうなっているかわからず、自分でブロックを作り出す事が出来ない。
ブラックボックス化することは悪い事ではない。初めから全て自分でやろうとすると多分挫折してしまうだろう。それに、本質的な部分だけ記述し、作成すれば動くというのはとてもいいことなのだろう。しかし、いつまでもそこに留まってしまうとあまり進歩がないと思う。もちろん、手段としてArduinoを使うのであればそれでいいのだと思うが、自分の場合はそうではないので、いつまでもそこに留まらず、基礎的な勉強をしていきたいと思う。
こんなことは、Arduinoのせいでもなんでもないし、自分の問題なのだが、根深いので少しずつ前進していきたいと思う。自由に素敵なものが作れるようになったらうれしい。
2014-03-07T03:18:06+09:00
1394129886
-
久しぶりの更新
https://w.atwiki.jp/shimizunochikara/pages/25.html
2014/3/7、久しぶりにwikiを見たら広告が上に来ていた。60日間更新しないと広告が目立つ位置に移動してしまうらしい。やっぱりこういうのは定期的に更新しないとダメだと思う。
最近まで忙しかったので、あまり電子工作が出来ていなかったが、やりたいことはいろいろあるのでリストアップして実際に作っていきたいと思う。今度はLEDを使った工作がしたいと思っている。照明が色々な色に光るだけでも大分わくわくする。明るめのLEDを購入して小さな照明を作ってみたいと思う。
後は野外用のセンサー端末をもう一度作ってみたいと思う。今まで作っていたセンサーは基盤むき出しであったが、今度はきちんとケースを使い、野外でも使えるようにしていきたいと思っている。
いまやりたいことはこんな感じだ。
2014-03-07T02:59:22+09:00
1394128762
-
メニュー
https://w.atwiki.jp/shimizunochikara/pages/9.html
*電子工作物
[[Arduino Tank2号機>http://www57.atwiki.jp/shimizunochikara/pages/20.html]]
[[ライントレースカー>http://www57.atwiki.jp/shimizunochikara/pages/18.html]]
[[Arduino Tank1号機>http://www57.atwiki.jp/shimizunochikara/pages/15.html]]
*備忘録
[[ライントレースカー1号機のプログラム>http://www57.atwiki.jp/shimizunochikara/pages/22.html]]
[[ArduinoTank1号機のプログラム>http://www57.atwiki.jp/shimizunochikara/pages/21.html]]
*雑記
*自己紹介
[[shit_raccoonの自己紹介>http://www57.atwiki.jp/shimizunochikara/pages/13.html]]
2014-03-07T02:48:11+09:00
1394128091
-
センサーデータの配信プロトコル
https://w.atwiki.jp/shimizunochikara/pages/24.html
@todo
2013-10-16T13:51:07+09:00
1381899067
-
はじめに
https://w.atwiki.jp/shimizunochikara/pages/23.html
*センサーデータの配信システムに関して
Arduino等のマイコンを用いてセンサーデータを得られるが、これらのデータをウェブブラウザにより表示するためのシステムを考えて行きたいと思う。センサーデータをブラウザに表示するだけなら、Arduino + Ethernetシールドをサーバーにすることで、実装が可能である。しかし、リアルタイムデータを表示するためには、動的なデータ配信が必要であり、Arduinoには並列処理をするための機構が搭載されていないため、Arduino単体では困難である。そのため、データの配信を行うためのサーバーを用意し、そこから配信を行う必要がある。また、大量のセンサーデータや大量のクライアントのコネクションが到着した場合にはサーバーに大きな負荷がかかると考えられる。そこで、その際のサーバー負荷や負荷を軽減する方法に関しても考察して行きたいと考えている。
*センサーデータ配信のモデル
センサーノードとクライアントはN対Nの関係となる。一つのセンサーノードからのデータを多数のクライアントが同時受信をする、また多数のセンサーノードからのデータを一つのクライアントが受信するというモデルになっている。例えば、屋外に設置された温度センサーの値を多数のクライアントが同時に閲覧する場合や、異なる位置に設置された温度センサーの値を一つのクライアントにより閲覧することが挙げられる。
#ref(スライド2.jpg)
※ここでノードの図としてArduinoの写真を用いてしまったが、Arduinoはスレッド処理が実装されていないため、多数のクライアントに同時にデータを配信することは出来ない。このモデルの場合はArduinoとクライアントの間にデータ配信用サーバーをたてる必要がある。
*センサーデータプロキシサーバーを用いたモデル
上記のセンサーデータ配信モデルでは、ノード毎にセンサーデータ配信用のサーバーをたてる必要がある。しかし、センサーデータにインターネット上からアクセするためには、グローバルIPアドレスが必要である。またネットワークの設定を行う必要、サーバーの管理を行う必要があり、非常にコストがかかる。そこで、センサーデータのプロキシサーバーを用いたモデルを提案する。
#ref(スライド1.jpg)
**プロキシサーバーを用いた場合のメリット
-個人でサーバーをたてる必要がなくなるため、サーバーの管理コストがなくなる
-グローバルIPアドレスの取得やポート解放を行う必要がなくなる
-Arduino + Ehternetシールドの構成でセンサーデータをインターネットに配信する事が可能になる
個人でセンサーデータ配信用のサーバーをたてる事は非常にコストがかかるが、プロキシサーバーを用いる事でセンサーデータ配信を簡単に行う事が出来るようになると考えられる。
2013-10-16T13:47:16+09:00
1381898836
-
トップページ
https://w.atwiki.jp/shimizunochikara/pages/6.html
#ref(_DSC0199.jpg)
#ref(a656a51d8dc76a2ff41ff27c03645809.jpeg)
#ref(ライントレースカーコース.jpeg)
*初めに
筆者は工作が好きで色々買ってきては動かしてを繰り返しているのですが、部品は使い回す事が多いので、一旦バラバラにしてしまうと、どういった過程で作ったのかを忘れてしまいます。一回一回の試作の中にいろいろな問題や工夫があるはずなので、こういった部分を記録できればと思い、本サイトを作成しました。いわば筆者のための備忘録です。初めのうちは骨組みばかりで内容がスカスカになってしまうと思いますが、段々加筆していこうと思います。
*この日記の目的
-アイディアの記録
-工作物の記録
-実験の記録
-購入した部品の記録
目的に関しては、こういった事を試してみたい、こういったものを作っていきたいという予定も含めて個人的な備忘録として利用していきたいと思います。
*主な内容(予定)
-Arduinoを用いた電子工作
-Arduinoに関する実験
-ArduinoとWebを繋げた遊び
-プログラム関連
内容に関してはとりあえず動いたというものが多くなると考えられます。その部品の本来の使い方からかけ離れてしまう場合もあると考えられ、実験としては不適切な内容があるかもしれません。本Wikiに記述してある内容を模倣した場合に如何なる損害が発生したとしても筆者は責任を負いかねます。申し訳ないのですがよろしくお願いします。
2013-08-12T23:35:41+09:00
1376318141
-
Arduinoを使ったライントレースカーの実装
https://w.atwiki.jp/shimizunochikara/pages/18.html
2013年8月1日作成
#ref(fcc85a571b8eec5fdd7b6ddb9316fa02.jpeg)
*はじめに
前回Arduinoを用いてラジコンを作成したので今回はセンサーにより自立走行するライントレースカーを作成しようと思う。また、前回のノウハウを生かして、無線によりライントレースカーのパラメーターを変更できるようにする。一機目はライントレースカーに関するノウハウが全くないので、とりあえず動くものを作る事が目標になる。ソフト側に関しては無線で操作を可能にする.
*ライントレースカーの機能
-黒のビニールテープをコースとし、コースをトレースして走行
-走行速度やトレーススタート, 停止をPCから無線で操作可能
-センサーのしきい値等のセッティングをPCから無線で変更可能
-センサーから得られるデータを無線によりリアルタイムにPCに表示可能
*実装の方針
-ビニールテープの太さの黒い線を認識できるようにする
-フォトリフレクタを用いて線を認識する
-フォトダイオードは4つ利用する
-&bold(){比例制御}により制御を行い、パラメーターを変更する事で制御量を調整する
-コマンドを設計する事で、パラメーターの変更を可能にする
-車体側からセンサーデータをPCに送信し、表示を行う
-コントローラー側はJavaにより実装を行う
*使用した部品
**マイコン部分
-Arduino Uno
-[[Arduino モーターシールド Rev3 >http://www.amazon.co.jp/gp/product/B0081XGH0A/ref=s9_simh_gw_p23_d0_i3?pf_rd_m=AN1VRQENFRJN5&pf_rd_s=center-7&pf_rd_r=0HF31E3B4PW58XH9KNSV&pf_rd_t=101&pf_rd_p=463376816&pf_rd_i=489986]]
-Arduino XBeeシールド
-XBee Series2 × 2
**センサー
-[[フォトリフレクタ(反射タイプ)LBR-127HLD>http://akizukidenshi.com/catalog/g/gP-04519/]]
-20KΩ抵抗 × 4
-200Ω抵抗 × 4
-[[ユニバーサル基盤 72×48>http://akizukidenshi.com/catalog/g/gP-03229]]
**シャーシ
-タミヤユニバーサルプラスチック基盤 × 3
-[[タミヤダブルギヤボックス>http://www.tamiya.com/japan/products/70168double_gearbox/index.htm]]
-ナロータイヤセット 58mm径 (70145)
-ボールキャスター(70144)
*ハード部分の実装
車体はArduino Tankと同様に、タミヤ工作キットを組み合わせ作成した。初めに以下の写真のように作成したが、旋回の際に車輪が空転してしまうため、後ろにボードを追加し、重心を後ろに持って行く事で対応した。なお、マイコン部分はArduino UNOとモーターシールドR3とXBeeシールドを3段重ねにして利用している。バッテリーはエネループを利用した際にもマイコンに5V以上供給できるように、今回は単3電池を6本利用している。
#ref(ライントレースカー試作1.jpeg)
これで一応、空転しなくなった。車体の重心に関しては再度調整する必要があると思う。
#ref(ライントレースカー完成版.jpeg)
**ラインセンサー
#ref(ライントレースセンサー1.jpeg)
黒いセンサーが二つのセンサーの間に入った際に、両方のセンサーがぎりぎりで反応するように、センサー位置を調整した。このあたりは、線の認識方法と合わせて検討する必要がある。
*プログラム
**黒線の位置判定
黒線の判定は、センサーの閾値を設定し、センサーの反応している個数と位置に応じて位置を出力する仕組みになっている。
**PC側プログラム
PC側のプログラムからスタート, ストップやスピード、センサーの閾値を無線で設定する事が出来る。
#ref(ライントレースカーコントローラー.png)
画面例
上記の画面のように様々な設定をPCから無線で行う事が出来る。また、車体の現在の設定やセンサーデータをリアルタイムに表示する事が出来る。
*動作確認
#ref(ライントレースカーコース.jpeg)
以上のようなコースを作成し、線上を走行できている事を確認した。スピードを上げすぎると振動が収まらなくなり脱線してしまう。また、少し急なカーブの際にオーバーシュートしてしまう場合があった。
*今回わかった事
-車体は駆動輪を中心に旋回する
--駆動輪上に重心がないと旋回の際に車輪が空転してしまう
--回転軸より前に重量物があると回転の際の抵抗につながる
*次なる目標
-現在はArduino Uno + モーターシールド + XBeeシールドの3階建てだが、これを1枚の基盤上に実装したい
-Arduinoベースの基盤を自分で作成したい(ユニバーサル基盤上)
-車体のバランスを考え高速走行を可能にしたい
-より細かく認識ができるセンサーを作りたい
2013-08-12T21:23:21+09:00
1376310201
-
ライントレースカー1号機のプログラム
https://w.atwiki.jp/shimizunochikara/pages/22.html
*プログラムリスト
**ライントレースカー側のプログラム
#highlight(linenumber,c){{
#include <TimerOne.h>
/*
2013/7/23 動作確認済み
2013/7/24 変数の受信部分を変更, D要素を削除, 動作を確認済み
2013/7/25 データ送信部分の内容を小変更, 動作を確認済み
2013/7/30 モーター回転数の変更周期を20msに変更, 動作を確認(振動の収束が遅くなった)
Arduino Motor SHILED R3
9のエリアのどこ黒い線の位置を出力するプログラム
0 ~ 9がエリアで、-1が線が検出できない状態
*/
//MOTOR SHILED用
#define PWM_A 3
#define BREAK_B 8
#define BREAK_A 9
#define PWM_B 11
#define DIR_A 12
#define DIR_B 13
/*ラインセンサーの閾値
TH1がセンサーの真下に黒線があると考えられる閾値
*/
#define TH1 100
//前進スピードの定義(MAX255)
#define TRACESPEED 120
//比例成分
#define P_VALUE 17
#define I_VALUE 12
#define D_VALUE 12
int TraceSpeed, P_Value, I_Value, D_Value, P_Threshold;
int leftPower, rightPower;
int pos_b;//一回前の線の位置
boolean traceStartFlag, sendDataFlag;
//timer1はデータ送信用
long volatile MainTimer, timer1, timer2;
void timerInterrupt(){
MainTimer += 1;
}
/*
極座標による入力を二つのモーターの出力に変換する関数.
超信地展開しないバージョン.
moterの出力は-255 ~ 255である. -は逆回転を表す
r = 0 ~ 255をとる. s = -180 ~ 180をとる.
sは前進が0, 左旋回が-90,
右旋回が90, 後退が180 or -180である
*/
void convert_pwm2(double r, double s, int *lp, int *rp){
double _lp, _rp;
if(s > 180 || s < -180)s = 180;
/*
if(-180 <= s && s < -90){
_lp = (s + 180) / 90 - 1;
_rp = (s + 180) / 45 - 1;
}*/
if(-90 <= s && s < 0){
_lp = (s + 90) / 90;
_rp = 1;
}
else if(0 <= s && s < 90){
_lp = 1;
_rp = 1 - s / 90;
}
/*
else{//90 <= r <= 180の時
_lp = 1 - (s - 90) / 45;
_rp = -1 * (s - 90) / 90;
}*/
*lp = _lp * r;
*rp = _rp * r;
if(abs(*lp) < 20)*lp = 0;
if(abs(*rp) < 20)*rp = 0;
/*デバグ用
Serial.print(_lp);
Serial.print(",");
Serial.println(_rp);
*/
}
void setup(){
Serial.begin(9600);
pinMode(PWM_A, OUTPUT);
pinMode(PWM_B, OUTPUT);
pinMode(BREAK_A, OUTPUT);
pinMode(BREAK_B, OUTPUT);
pinMode(DIR_A, OUTPUT);
pinMode(DIR_B, OUTPUT);
digitalWrite(BREAK_A, LOW);
digitalWrite(BREAK_B, LOW);
digitalWrite(DIR_A, HIGH);
digitalWrite(DIR_B, HIGH);
analogWrite(PWM_A, 0);
analogWrite(PWM_B, 0);
traceStartFlag = false;
TraceSpeed = TRACESPEED;
P_Value = P_VALUE;
I_Value = I_VALUE;
D_Value = D_VALUE;
P_Threshold = TH1;
pos_b = 4;
MainTimer = 0;timer1 = 0;timer2 = 0;
Timer1.initialize(1000); //(1ms)
Timer1.attachInterrupt(timerInterrupt);
}
void loop(){
//a[i]はセンサーの出力結果を降順にソートしたもの
//num[i]はセンサー番号を出力の降順にソートしたもの
int a[4],a_b[4],num[4] = {
0,1,2,3 }
, i, j, swap, pos, s;
byte b[3];
//シリアルによりコマンドを受け取る
/*
PC→ライントレースカー
コマンド番号, コマンドの内容, 引数
0. 全停止
1. トレーススタート, スピード(8bit)
2. 方向転換
3. トレーススピード設定, スピード(8bit)
4. P要素の設定,(8bit)
5. I要素の設定, (8bit)
6. D要素の設定,(8bit)
7. 距離センサーの動作, (10bit)… この値を超えた場合に自動ストップをする
8. 手動コントロール時のスピード, (8bit)
9. 手動コントロール時の角度, (9bit) 0 ~ 360度で送信する180度で前進
10. 設定状態の全送信の要求
11. センサーデータの送信モードのON/OFF
12. フォトダイオードの閾値, (10bit)
*/
if(Serial.available()){
b[0] = Serial.read();
if((b[0] & 0b10000000) != 0){
delay(20);
b[1] = Serial.read();
b[2] = Serial.read();
}
//0.全停止
if((b[0] & 0b01111111) == 0b00000000){
traceStartFlag = false;
}
//1.トレーススタート
else if((b[0] & 0b01111111) == 0b00000001){
traceStartFlag = true;
TraceSpeed = (b[1] << 7 | b[2]) & 0b11111111;
}
//3.トレーススピード設定
else if((b[0] & 0b01111111) == 0b00000011){
TraceSpeed = (b[1] << 7 | b[2]) & 0b11111111;
}
//4.P要素の設定,(8bit)
else if((b[0] & 0b01111111) == 0b00000100){
P_Value = (b[1] << 7 | b[2]) & 0b11111111;
}
//5.I要素の設定,(8bit)
else if((b[0] & 0b01111111) == 0b00000101){
I_Value = (b[1] << 7 | b[2]) & 0b11111111;
}
//6.D要素の設定,(8bit)
else if((b[0] & 0b01111111) == 0b00000111){
D_Value = (b[1] << 7 | b[2]) & 0b11111111;
}
//10. 設定データの全送信の要求
else if((b[0] & 0b01111111) == 0b00001010){
Serial.print("S:");
Serial.print(TraceSpeed);
Serial.print(",TH:");
Serial.print(P_Threshold);
Serial.print(",P:");
Serial.print(P_Value);
Serial.print(";");
}
//11. センサーデータの送信のON/OFF
else if((b[0] & 0b01111111) == 0b00001011){
if(b[1] != 0 || b[2] != 0)sendDataFlag = true;
else sendDataFlag = false;
}
//12. フォトダイオードの閾値, (10bit)
else if((b[0] & 0b01111111) == 0b00001100){
P_Threshold = (b[1] << 7 | b[2]) & 0b1111111111;
}
}
//センサーデータの解析を行う
a[0] = analogRead(0);
a[1] = analogRead(1);
a[2] = analogRead(2);
a[3] = analogRead(3);
for(i = 0; i < 4; i++)a_b[i] = a[i];
//値のソートを行う
for(i = 0; i < 4 -1; i++){
for(j = 1; j < 4 - i; j++){
if(a[j] > a[j-1]){
swap = a[j];
a[j] = a[j-1];
a[j-1] = swap;
swap = num[j];
num[j] = num[j-1];
num[j-1] = swap;
}
}
}
//二つのセンサーの間に黒線があると考えられる場合
if(a[0] > P_Threshold && a[1] > P_Threshold){
if(num[0] == 0 && num[1] == 1)pos = 1;
else if(num[0] == 1 && num[1] == 0)pos = 2;
else if(num[0] == 1 && num[1] == 2)pos = 4;
else if(num[0] == 2 && num[1] == 1)pos = 5;
else if(num[0] == 2 && num[1] == 3)pos = 7;
else if(num[0] == 3 && num[1] == 2)pos = 8;
else pos = -1;
}
//センサーの真下に黒線があると考えられる場合
else if(a[0] > P_Threshold){
if(num[0] == 0)pos = 0;
else if(num[0] == 1)pos = 3;
else if(num[0] == 2)pos = 6;
else if(num[0] == 3)pos = 9;
else pos = -1;
}
else{
pos = -1;
}
if(sendDataFlag == true && MainTimer >= timer1 + 200){
Serial.print("Pos:");
Serial.print(pos);
Serial.print(",p0:");
Serial.print(a_b[0]);
Serial.print(",p1:");
Serial.print(a_b[1]);
Serial.print(",p2:");
Serial.print(a_b[2]);
Serial.print(",p3:");
Serial.print(a_b[3]);
Serial.print(";");
timer1 = MainTimer;
}
//以下でモーター出力の計算を行う
if(pos >= 0 && MainTimer >= timer2 + 1){
// + (pos - pos_b) * D_Value;
s = (pos - 4.5) * P_Value;
convert_pwm2(TraceSpeed, s , &leftPower, &rightPower);
pos_b = pos;
timer2 = MainTimer;
}
if(traceStartFlag == true){
analogWrite(PWM_A, leftPower);
analogWrite(PWM_B, rightPower);
}
else{
analogWrite(PWM_A, 0);
analogWrite(PWM_B, 0);
}
}
}}
2013-08-12T19:09:25+09:00
1376302165
-
ArduinoTank 1号機プログラム
https://w.atwiki.jp/shimizunochikara/pages/21.html
*ソースコード
**車体側
#highlight(linenumber,c){{
/*キャタピラーラジコンの完成版*/
#define ROTATION1_PIN 12
#define SPEED1_PIN 3
#define ROTATION2_PIN 13
#define SPEED2_PIN 11
#define RXPIN 2
#define TXPIN 4
int left_power, right_power;
void setup(){
pinMode(ROTATION1_PIN, OUTPUT);
pinMode(ROTATION2_PIN, OUTPUT);
pinMode(SPEED1_PIN, OUTPUT);
pinMode(SPEED2_PIN, OUTPUT);
digitalWrite(ROTATION1_PIN, HIGH);
digitalWrite(ROTATION2_PIN, HIGH);
analogWrite(SPEED1_PIN, 0);
analogWrite(SPEED2_PIN, 0);
Serial.begin(9600);
left_power = 0; right_power = 0;
}
void loop(){
boolean rotation1, rotation2;
int speed1, speed2, i;
char c[4];
if(Serial.available()){
c[0] = Serial.read();
if((c[0] & 0b10000000) != 0){
delay(5);
c[1] =Serial.read();
c[2] = Serial.read();
c[3] = Serial.read();
left_power = (c[0] & 0b01111111) << 2 | (c[1] & 0b01100000) >> 5;
right_power = (c[1] & 0b00011111) << 4 | (c[2] & 0b01111000) >> 3;
left_power -= 255;
right_power -= 255;
//以下で回転数の計算
//左モーターに関して
if(left_power >= 0) //正回転の場合
rotation1 = HIGH;
else
rotation1 = LOW;
//右モーターに関して
if(right_power >= 0) //正回転の場合
rotation2 = HIGH;
else
rotation2 = LOW;
speed1 = abs(left_power);
speed2 = abs(right_power);
digitalWrite(ROTATION1_PIN, rotation1);
digitalWrite(ROTATION2_PIN, rotation2);
analogWrite(SPEED1_PIN, speed1);
analogWrite(SPEED2_PIN, speed2);
}
}
}
}}
**コントローラー側
#highlight(linenumber,cpp){{
//ソースコード: polar_stick_ver2
#include <MsTimer2.h>
#include <math.h>
#define MAX_X 1012
#define MAX_Y 998
#define MIN_X 0
#define MIN_Y 0
#define NEUTRAL_X 414
#define NEUTRAL_Y 422
#define asobi 20
#define STICK_LED 3
int timer_count;
int stick_mode;
void count_down(){
if(timer_count > 0)
timer_count--;
}
void button_interrupt(){
if(timer_count == 0){
if(stick_mode == 0){
stick_mode = 1;
analogWrite(STICK_LED, 255);
}
else{
stick_mode = 0;
analogWrite(STICK_LED, 0);
}
timer_count = 30;
}
}
void setup(){
Serial.begin(9600);
timer_count = 0;
attachInterrupt(0, button_interrupt, FALLING);
MsTimer2::set(10, count_down);
MsTimer2::start();
attachInterrupt(0, button_interrupt, FALLING);
stick_mode = 0;
digitalWrite(STICK_LED, LOW);
}
/*
rは中央からの距離, sは角度を表す. rの最大は1である.
sはスティックを前に倒すと0, 左に倒すと-90, 右に倒すと90, 後ろに倒すと180 or -180を返す
*/
void stick_read(double *r, double *s){
double stick_x, stick_y;
//スティック位置の補正
stick_x = (double)analogRead(0);
stick_y = (double)analogRead(1);
if(stick_x < NEUTRAL_X){
stick_x = (stick_x - NEUTRAL_X) / (NEUTRAL_X - MIN_X);
}
else{
stick_x = (stick_x - NEUTRAL_X) / (MAX_X - NEUTRAL_X);
}
if(stick_y < NEUTRAL_Y){
stick_y = (stick_y -NEUTRAL_Y) / (NEUTRAL_Y - MIN_Y);
}
else{
stick_y = (stick_y - NEUTRAL_Y)/ (MAX_Y - NEUTRAL_Y);
}
/* デバッグ用
Serial.print(stick_x);
Serial.print(",");
Serial.println(stick_y);
*/
*r = sqrt(pow(stick_x,2) + pow(stick_y, 2));
if(*r > 1)*r = 1;
else if(*r < -1)*r = -1;
*s = atan2(stick_x, stick_y) /3.14 * 180;
}
/*
極座標による入力を二つのモーターの出力に変換する関数.
超信地展開するバージョン.
moterの出力は-255 ~ 255である. -は逆回転を表す
*/
void convert_pwm(double r, double s, int *lp, int *rp){
double _lp, _rp;
if(-180 <= s && s < -90){
_lp = -1;
_rp = (s + 180) / 45 - 1;
}
else if(-90 <= s && s < 0){
_lp = (s + 90) / 45 - 1;
_rp = 1;
}
else if(0 <= s && s < 90){
_lp = 1;
_rp = 1 - s / 45;
}
else{//90 <= r <= 180の時
_lp = 1 - (s - 90) / 45;
_rp = -1;
}
*lp = _lp * r * 255;
*rp = _rp * r * 255;
if(abs(*lp) < 20)*lp = 0;
if(abs(*rp) < 20)*rp = 0;
/*デバグ用
Serial.print(_lp);
Serial.print(",");
Serial.println(_rp);
*/
}
/*
極座標による入力を二つのモーターの出力に変換する関数.
超信地展開しないバージョン.
moterの出力は-255 ~ 255である. -は逆回転を表す
*/
void convert_pwm2(double r, double s, int *lp, int *rp){
double _lp, _rp;
if(-180 <= s && s < -90){
_lp = (s + 180) / 90 - 1;
_rp = (s + 180) / 45 - 1;
}
else if(-90 <= s && s < 0){
_lp = (s + 90) / 90;
_rp = 1;
}
else if(0 <= s && s < 90){
_lp = 1;
_rp = 1 - s / 90;
}
else{//90 <= r <= 180の時
_lp = 1 - (s - 90) / 45;
_rp = -1 * (s - 90) / 90;
}
*lp = _lp * r * 255;
*rp = _rp * r * 255;
if(abs(*lp) < 20)*lp = 0;
if(abs(*rp) < 20)*rp = 0;
/*デバグ用
Serial.print(_lp);
Serial.print(",");
Serial.println(_rp);
*/
}
void make_command(int left_power, int right_power){
char c0, c1, c2, c3;
left_power += 255;
right_power += 255;
c0 = (left_power & 0b111111100) >> 2;
c1 = (left_power & 0b000000011) << 5;
c1 = c1 | ((right_power & 0b111110000) >> 4);
c2 = (right_power & 0b000001111) << 3;
c3 = 0;
c0 = c0 | 0b10000000;//先頭バイトの先頭ビットを1とする
c0 = c0 & 0b111111111;
Serial.print(c0);
Serial.print(c1);
Serial.print(c2);
Serial.print(c3);
}
void loop(){
double r, s;
int left_power, right_power;//-255 ~ 255でモーター出力を表現
stick_read(&r, &s);//極座標で値を返す関数
if(stick_mode == 0)
convert_pwm2(r,s,&left_power, &right_power);
else if(stick_mode == 1)
convert_pwm(r,s,&left_power, &right_power);
make_command(left_power, right_power);
/*でバグ用
Serial.print(left_power);
Serial.print(",");
Serial.println(right_power);
*/
delay(100);
}
}}
2013-08-12T18:59:00+09:00
1376301540