12/10/2016 まちあかり報告会前日

今日は、三限からロボ実験の補講もあるというのに、こうちゃんリーダーが、日曜日のまちあかり報告会の準備、打ち合わせを9:00からするというので、大学に向かった。こうちゃんリーダーはマジで9:00頃到着し、連絡きた。急いで行ったが、ちょっと遅れた。私はまちあかり報告会の発表で活動内容の所の発表担当だったので、こうちゃんリーダーと後で来られたキャノンちゃんに想い火フローティングキャンドルの辺りについて教えてもらいながら、原稿を考えた。2人ともやさすい。キャノンちゃんは二限があるからかえって、こうちゃんリーダーだけになり、2人で話し合いながら原稿を決めた。彼は優しいし、真摯に一緒に考えてくれた。さすがリーダー!私の原稿がちょっとぐちゃっとなっているからワードに書き直さないかという事でワード開いてくれて打つように言われた。タイピングしてたら、早いなーと言うので、早くないですよもっと早い人いますよとかいうと、おじちゃんの話でしたとか言って笑だった。私は三限から授業なので、帰ったが、こうリーダーは残るというので、私はお昼食べに行った。結構アグレッシブであるな。。



12/9/2016

昨日は某研究室の盆年会兼ねた新入生の歓迎会だった。

今日は、明日のロボ実験について考えてみた。
(まとめ)
①ペットボトルをベルトコンベアで挟む際に、力覚センサを使用。
②ペットボトルをベルトコンベアである一定の高さまで持ち上げ停止させる際に、フォトセル(cds)もしくはフォトカプラを使用する。

フォトカプラについては以下のサイト参照↓

フォトセルも、フォトカプラも外部からの光に反応して抵抗値が変わるという面から、力覚センサと基本的に同じ。
ということで、力覚センサについて復習した。

力覚センサについては以下のサイト参照

~上記のまとめに至るまで~

(実験)
家にあるフォトセルと赤外線受信モジュールが茶のペットボトルにどういう反応するか実験を行った。
(結果)
ペットボトルのないところでは抵抗値が小さく、ペットボトルを前面に存在させると抵抗値が大きくなった。
(フォトセル原理)
フォトセルは入ってくる光の強さが大きくなると、電気抵抗が小さくなる。つまり明るいと抵抗値小。暗いと抵抗値大。
(考察)
ペットボトル自体に反応はするから使えそうであるが、フォトセルは環境の明暗で決まるため、なんともいえない。

その次に赤外線を送って赤外線受信モジュールで反応さしてモーター停止させることはできないかと思った。
(結果)
ペットボトルのない所でも、ある所でも赤外線に反応した。
(赤外線受信の原理)
赤外線を送り、受信モジュールが検知した信号データに合わせて、ledを光らせたり、モーター動かしたりする。
(考察)
そもそも、赤外線を離れたところからでも多少の障害物があっても、受信モジュールは反応をする。感度よすぎ。物体検知無理。

ロボ研のライントレースの時はどういうものを使っていたのか気になり、いろいろ調べてみた。以上のサイトでは原理的にledの光をフォトトランジスタが検知するようになっているが、電流をオンオフさせてledやモーターを動かし、マイコンとかなくてもそれ単体で動くものなので、最初はフォトセルのチップ上になったものだと思い、調べていたのだが、どうもフォトカプラっぽい。

(フォトカプラの原理)
フォトカプラは内部に発光素子と受光素子が収められ、⭐︎外部からの光を遮断するパッケージに封じ込められた構造になっている⭐︎入力された電気信号を発光素子によって光に変換し、その光を受光素子に送る事により信号を伝達する。 一般的に発光素子には発光ダイオード、受光素子にはフォトトランジスタが用いられることが多い。

⭐︎内の性質により、上記の赤外線受信モジュールの実験の奴よりも上手くいくであろう‼︎‼︎
下記のサイト参照↓
上記のサイトにも書いていたが、フォトカプラのフォトトランジスタの部分では光を受信すると抵抗値が変わるらしい。これにより電圧も変わるのでその電圧をarduinoで検出する。
まだ電気についての知識は浅いが、電流と抵抗値にはそもそも相関関係があり、そういうものなのであるが、ちょっとよく考えよ笑





12/7/2016

ロボ実験について


今日はゆうき君がPS3の実験を家でやってきたので見せてもらった。家ではモーター回ったというが、今日モーター3つコントローラーのボタン押して回そうとしても2つしか動かなかったり固まったりする。あり? プログラムは以下にあり。


そこで、回路に間違いがあるのかどうか考えてみた!


いろんなサイト見てると、arduinoPWMで2つモーター制御でも限界だとか書いてるものもあるが、

Arduinoでモーターいくつか回しているサイトもある。

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10159968040

上記のサイトによると、やっぱ電源容量とPWM出力が問題で動かないこともあるとの事。


が、しかし、プログラム(制御)でどうにかしないといけないのだと思う。

それか信号ミスか?


今後どうなるんだろ〜笑


(今後ちょっとやってみたいこと)

普通のモーター3つを赤外線通信で動かす実験。


プログラム


#include <PS3BT.h>
#include <usbhub.h>
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#include <math.h>
#endif
USB Usb;
BTD Btd(&Usb);
PS3BT PS3(&Btd); 
int counter =0;
bool printTemperature, printAngle;
int MM_pluspin = {3,6,10};
int MM_minuspin = {5,9,11};
int CM_pluspin = 4;
int CM_minuspin = 7;
int UD_pluspin = 1;
int UD_minuspin = 2;
bool Catch = false;
int plus[3];
int minus[3];
int Motor_power[3];
bool Move = false;
int turn_sp = 200;
const int Motor_num = 3;
const double Motor_FR = {1,1,1};
const double Motor_rad = {PI/2.0,-PI/6.0,-PI*5.0/6.0};
double Theta;
double Speed;
void setup() {
  Serial.begin(9600);
  for(int i = 0;i < Motor_num; i++){
    pinMode(MM_pluspin[i], OUTPUT);
    pinMode(MM_minuspin[i], OUTPUT);
  }
  pinMode(CM_pluspin, OUTPUT);
  pinMode(CM_minuspin, OUTPUT);
  pinMode(UD_pluspin, OUTPUT);
  pinMode(UD_minuspin, OUTPUT);
      for(int i =0;i < Motor_num;i++){
        analogWrite(MM_pluspin[i], 0);
        analogWrite(MM_minuspin[i], 0);
      }
  
#if !defined(__MIPSEL__)
  while (!Serial); 
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1);
  }
  Serial.print(F("\r\nPS3 Bluetooth Library Started"));
}
void loop() {
  if(counter%100==0){
    Usb.Task();
    if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
      /*if *1 {
        Theta = atan2( PS3.getAnalogHat(LeftHatY)-127.5 ,PS3.getAnalogHat(LeftHatX)-127.5);
        Speed = hypot( PS3.getAnalogHat(LeftHatY)-127.5 ,PS3.getAnalogHat(LeftHatX)-127.5);
        if(Speed>128) Speed = 128;
        for(int i =0;i < Motor_num;i++){
          Motor_power[i] = (int)(Motor_FR[i]*sin(Theta-Motor_rad[i])*Speed*255.0/128.0);//power-255~128
          if(Motor_power[i] < 0){
            plus[i] = 0;
            minus[i] = abs(Motor_power[i]);
          }else if(Motor_power[i] > 0){
            plus[i] = abs(Motor_power[i]);
            minus[i] = 0;
          }
        }
        Move = true;
        //Serial.println(String(int(Motor_power[0]))+" "+String(Motor_power[1])+" "+String(Motor_power[2]));
      }else if(PS3.getButtonPress(L1)){
        for(int i =0;i < Motor_num;i++){
          plus[i] = 0;
          minus[i] = turn_sp;
        }
        Move = true;
      }else if(PS3.getButtonPress(R1)){
        for(int i =0;i < Motor_num;i++){
          plus[i] = turn_sp;
          minus[i] = 0;
        }
        Move = true;
      }else{
        Move = false;
      }
      if(Move){
        for(int i =0;i <Motor_num;i++){
          analogWrite(MM_pluspin[i], plus[i]);
          analogWrite(MM_minuspin[i], minus[i]);
        }
      }*/
      /*******************************************************************************************************************/
      if (PS3.getAnalogHat(RightHatY) > 154){
          digitalWrite(UD_pluspin,LOW);
          digitalWrite(UD_minuspin,HIGH);
      }else if(PS3.getAnalogHat(RightHatY) < 100) {
          digitalWrite(UD_pluspin,HIGH);
          digitalWrite(UD_minuspin,LOW);
      }else{
          digitalWrite(UD_pluspin,LOW);
          digitalWrite(UD_minuspin,LOW);
      }
      /*********************************************************/
      if (PS3.getButtonClick(PS)) {
        Serial.print(F("\r\nPS"));
        PS3.disconnect();
      }
      else {
        if (PS3.getButtonClick(CIRCLE)) {
          Serial.print(F("\r\nCircle"));
          Catch = true;
        }
        if (PS3.getButtonClick(CROSS)){
          Serial.print(F("\r\nCross"));
          Catch = false;
        }
        if (PS3.getButtonPress(CROSS)){
          digitalWrite(CM_pluspin,LOW);
          digitalWrite(CM_minuspin,HIGH);
        }else if(!Catch){
          digitalWrite(CM_pluspin,LOW);
          digitalWrite(CM_minuspin,LOW);
        }
        if(Catch){
          //feedback
              digitalWrite(CM_pluspin,HIGH);
              digitalWrite(CM_minuspin,LOW);
        }
  
        
        if (PS3.getButtonClick(TRIANGLE)) {
          Serial.print(F("\r\nTraingle"));
          //PS3.setRumbleOn(RumbleLow);
        }
        if (PS3.getButtonClick(SQUARE))
          Serial.print(F("\r\nSquare"));
  
        if (PS3.getButtonPress(UP)) {
          //Serial.print(F("\r\nUp"));
           //analogWrite(MM_pluspin[0],200);
           //analogWrite(MM_minuspin[0],0);
           //analogWrite(MM_pluspin[1],200);
           // analogWrite(MM_minuspin[1],0);
           analogWrite(MM_pluspin[2],0);
           analogWrite(MM_minuspin[2],200); 
          /*if (PS3.PS3Connected) {
            PS3.setLedOff();
            PS3.setLedOn(LED4);
          }*/
        }
        if (PS3.getButtonPress(RIGHT)) {
          //Serial.print(F("\r\nRight"));
           //analogWrite(MM_pluspin[0],0);
           //analogWrite(MM_minuspin[0],0);
           //analogWrite(MM_pluspin[1],0);
          // analogWrite(MM_minuspin[1],0);
           analogWrite(MM_pluspin[2],0);
           analogWrite(MM_minuspin[2],0); 
           
          /*if (PS3.PS3Connected) {
            PS3.setLedOff();
            PS3.setLedOn(LED1);
          }*/
        }
        if (PS3.getButtonClick(DOWN)) {
          Serial.print(F("\r\nDown"));
          /*if (PS3.PS3Connected) {
            PS3.setLedOff();
            PS3.setLedOn(LED2);
          }*/
        }
        if (PS3.getButtonClick(LEFT)) {
          Serial.print(F("\r\nLeft"));
          /*if (PS3.PS3Connected) {
            PS3.setLedOff();
            PS3.setLedOn(LED3);
          }*/
        }
        //ButtonPress ositerutoki
        if (PS3.getButtonClick(L1))
          Serial.print(F("\r\nL1"));
        if (PS3.getButtonClick(L3))
          Serial.print(F("\r\nL3"));
        if (PS3.getButtonClick(R1))
          Serial.print(F("\r\nR1"));
        if (PS3.getButtonClick(R3))
          Serial.print(F("\r\nR3"));
        if (PS3.getButtonClick(SELECT)) {
          Serial.print(F("\r\nSelect - "));
          PS3.printStatusString();
        }
        if (PS3.getButtonClick(START)) {
          Serial.print(F("\r\nStart"));
          printAngle = !printAngle;
        }
      }
    }
  }
  counter++;
  
}



*1:PS3.getAnalogHat(LeftHatX) > 142 || PS3.getAnalogHat(LeftHatX) < 112 ||

      PS3.getAnalogHat(LeftHatY) > 142 || PS3.getAnalogHat(LeftHatY) < 112)&&!PS3.getButtonPress(L1)&&!PS3.getButtonPress(R1

12/6/2016

ロボ実験について考える。

ロボットを手動で目的地まで連れてく。

ボタンを押すとロボットアームが動き、対象物を挟んでいく。

力覚センサで物体を検知し、アーム挟む動作停止。

停止すると同時に、両アーム運転開始。

一定の高さになったら両アーム停止。
ここで、高さを目標値に設定して、フィードバックで実現したい。

⭐︎ 落とさないようにセンサで検知し値が小さくなってきたら、モーター出力させるようにするべきか?
実際ここでフィードバックの方が現実味あったりして!

プログラム(予想)

int hlefta = 2;
int hrighta = 3;
int hleftb = 4;
int hrightb = 5;
int hleftc = 6;
int hrightc = 7;

int lefta = 8;
int righta = 9;
int leftb = 10;
int rightb = 11;
int leftc = 12;
int rightc =13;

void setup() {
Serial.begin(9600);    
pinMode(hlefta, OUTPUT);
pinMode(hrighta, OUTPUT);
pinMode(hleftb, OUTPUT);
pinMode(hrightb, OUTPUT);
pinMode(hleftc, OUTPUT);
pinMode(hrightc,OUTPUT);

pinMode(lefta, OUTPUT);
pinMode(righta, OUTPUT);
pinMode(leftb, OUTPUT);
pinMode(rightb, OUTPUT);
pinMode(leftc, OUTPUT);
pinMode(rightc,OUTPUT);



}
void loop() {
  if(Serial.available()){
  char cmd = Serial.read();
    
switch (cmd){  
case 'w':
analogWrite(righta, 200);
analogWrite(lefta, 0);
analogWrite(rightb, 200);
analogWrite(leftb, 0);
analogWrite(rightc, 200);
analogWrite(leftc, 0);
Serial.print(F("a\n"));
break;

case 's':
analogWrite(righta, 200);
analogWrite(lefta, 0);
analogWrite(rightb,200);
analogWrite(leftb, 0);
analogWrite(rightc, 200);
analogWrite(leftc, 0);
break;

case 'd':
analogWrite(righta, 200);
analogWrite(lefta, 0);
analogWrite(rightb,200);
analogWrite(leftb, 0);
analogWrite(rightc, 200);
analogWrite(leftc, 0);
break;

case 'a':
analogWrite(righta, 200);
analogWrite(lefta, 0);
analogWrite(rightb,200);
analogWrite(leftb, 0);
analogWrite(rightc, 200);
analogWrite(leftc, 0);
break;

case 'z':
analogWrite(righta, 200);
analogWrite(lefta, 0);
analogWrite(rightb,200);
analogWrite(leftb, 0);
analogWrite(rightc, 200);
analogWrite(leftc, 0);
break;

case 'u': //掴んで持ち上げ
analogWrite(hrighta, 200);
analogWrite(hlefta, 0);

if (vol_value <400){
analogWrite(hrighta, 0);
analogWrite(hlefta, 0);

analogWrite(hrightb, 200);
analogWrite(hleftb,0);
analogWrite(hrightc, 200);
analogWrite(hleftc, 0);
delay(2000);
analogWrite(hrightb, 0);
analogWrite(hleftb,0);
analogWrite(hrightc, 0);
analogWrite(hleftc, 0);
}
delay(2000);
break;//これだと持ち上げた後に、analogWrite(hrighta, 200);
analogWrite(hlefta, 0);がまた処理されて動く。

case 'p'://降ろす離す
analogWrite(hrightb,0 );
analogWrite(hleftb,200);
analogWrite(hrightc, 0);
analogWrite(hleftc, 200);
delay(2000);
analogWrite(hrightb,0 );
analogWrite(hleftb,0);
analogWrite(hrightc, 0);
analogWrite(hleftc, 0);
analogWrite(hrighta, 0);
analogWrite(hlefta, 200);

if (vol_value <400){
analogWrite(hrighta, 0);
analogWrite(hlefta, 0);
}
delay(2000);
break;

default://case'o':
analogWrite(righta, 0);
analogWrite(lefta, 0);
analogWrite(rightb, 0);
analogWrite(leftb, 0);
analogWrite(rightc,0);
analogWrite(leftc, 0);
break;
}
   }


Serial.print("righta = ");
Serial.print(digitalRead(righta));
Serial.print("   lefta = ");
Serial.println(digitalRead(lefta));
}

12/3/2016

MOSトランジスタの「MOS」は、金属(M)、酸化膜(O)、半導体(S)の3層構造を意味します。酸化膜(O)は絶縁膜ですので、金属(M)に電圧を加えると金属(M)と半導体(S)の間に電流は流れません。電圧による電界が、半導体(S)に加わります。半導体内の電荷(キャリヤ)は、電界によって移動します。この性質をMOSトランジスタでは利用しています。 


図2 
図2:MOSトランジスタMOS FET)の構造

 MOSトランジスタは厳密には、「MOS FET(モスフェット)」と呼びます。FETは電界効果トランジスタ(Field Effect Transitor)の略号です。電界を利用することに由来した呼び名となっていることが分かります。 

 MOS FETの構造は、バイポーラ・トランジスタとは大きく違います。トランジスタの中央にMOS構造を配置してあり、その両側にMOS構造とは極性の違う領域をシリコン半導体の表面付近に局所的に形成した構造となっています。例えばMOS構造ではシリコン半導体の極性がp型だとします。その両側には、n型の半導体領域を形成するのです。

n型MOSトランジスタ

 ここで、シリコン半導体だけに眼を向けましょう。p型シリコンの両側を、n型シリコンが囲む形になっています。このような構造のMOSトランジスタを「n型(えぬがた)MOSトランジスタ」あるいは「nチャンネルMOSトランジスタ」と呼びます。 

 そして右側のn型シリコン領域を「ドレイン」、左側のn型シリコン領域を「ソース」と呼びます。ドレインとソースの位置関係は、回路構成によっては逆になることもあります。ただし1個のMOSトランジスタが描かれている場合は、左がソース、右がドレインとなるように表記するのが通例ですので、覚えておくと良いでしょう。 

 中央のMOS構造で「金属(M)」の部分は「ゲート」と呼びます。ゲートに加える電圧の高低で、MOSトランジスタのドレインとソースの間を流れる電流の量を制御します。

MOSトランジスタの電極はゲート、ドレイン、ソースの三つです。ここでソースを接地(グランド)電位に接続し、ドレインにプラスの電圧を加えます。 

 ゲートの電圧をゼロボルト、すなわち接地したときは、ソースとドレインの間に電流は流れません。トランジスタとしてはオフ状態になっています。 

 ゲートにプラスの電圧を印加すると、ドレインからソースに向かって電流が流れます。この電流を「ドレイン電流」と呼びます。トランジスタとしてはオン状態に変わりました。

図3 
図3:オン状態のn型MOSトランジスタ

 ゲートに加えるプラスの電圧を大きくすると、ドレイン電流が増加します。つまり、MOSトランジスタではゲート電圧を入力、ドレイン電流を出力としています。ゲート電圧の小さな変化を、ドレイン電流の大きな変化に変換することで、増幅作用を実現しているのです。

n型MOSトランジスタでは、電子がキャリヤです。ソースからドレインへと電子が移動することによって、ドレインからソースに向かって電流が流れます。電子が移動する領域は、トランジスタがオン状態になると一時的にn型半導体に変化します。この領域を「チャンネル」または「チャネル」と呼びます。

p型MOSトランジスタ

 n型MOSトランジスタと極性を逆にしたトランジスタは、p型MOSトランジスタとなります。n型MOSトランジスタでn型シリコン領域だったソースとドレインが、p型MOSトランジスタではp型シリコン領域に変わります。MOS構造の半導体はn型半導体です。キャリヤは電子ではなく、正孔となります。 

 p型MOSトランジスタを動かすための印加電圧は、n型MOSトランジスタと極性が逆になります。正孔がソースからドレインに向かって移動し、チャンネルを形成します。

上記に挙げたのは、サイト引用。

NMOS,PMOSトランジスタの動作について大体理解した。NMOSトランジスタによるNAND回路、CMOSインバータ回路についても大体理解。