2013/12/29

アーム根元ヨー軸のポテンショメータ


suzutoです。

アームの回転板のポテンショメータに、今まで使っていたGreen Pot以外のポテンショメータが使えないか探してました。場所が場所なのでキー溝タイプのものを探したのですが、ほとんど見つかりませんでした。キー溝タイプのポテンショってあまりないんですね、勉強不足でした。ということで、結局同じものを使うことにしました。取り付け方もとりあえず同じにします。もう少し機体の中身ができてきたら考え直すかもしれないです。



変えたところといえば、ポテンショ周りの板を減らして回転板の手入れをしやすい(と思う)感じにしたくらいです。ちなみに、夏に作り直した俯瞰カメラの昇降部分はそのまま使います。
今後は回転板の回転方法やクローラについて考えていこうと思います。

2013/12/27

慣性モーメントの計算の改善案

既に決まったルーチンをコンピュータにやらせるのはいい考えですね! ただ、ソースコードが以下の点で保守がしづらいと思われますので、改善案を示しておきます。

1. グローバル変数が多数の関数内で参照 & 書き換えがされていて、修正が容易でないこと。
2.  同じ変数について、ifでの分岐があちこちに散在していてバグの元となること。
3. 「3.14」の精度が足りない場合がある。それ以前にプログラム中に出てくる定数はマジックナンバーと呼ばれ、修正が大変になるので事前に定義しておく。

#include <stdio.h>

#define _USE_MATH_DEFINES
#include <math.h>

double chouhoukei(double* ref_m, double ro);
double nagaibou(double* ref_m, double ro);
double enban(double* ref_m, double ro);
double enchuu(double* ref_m, double ro);
double entou(double* ref_m, double ro);
double kyuu(double* ref_m, double ro);
double kyuukaku(double* ref_m, double ro);

static const double g_ro[3] = { 2.7 / 1000000, 7.9 / 1000000, 1.19 / 1000000 };
static const double (*f[7])(double*, double) = { chouhoukei, nagaibou, enban, enchuu, entou, kyuu, kyuukaku };

int main(void) {
   int i;
   float t0 = 0;

   printf("任意の軸(機力の教科書p251の図参照)まわりの慣性モーメントJ[kgcm^2]\n");

   for(i = 1; ; i++) {
      // 使う変数の領域を考えて極量スコープを小さく
      int u, n;
      double e, m, ro, t;

      printf("部材を番号で選んでください\n0.アルミ,1.ステンレス,2.アクリル,3.その他(密度既知)\n4.その他(質量既知),5.終了\n");
      scanf("%d", &u);

      // 密度既知の場合
      if(u >= 0 && u <= 2) {
         ro = g_ro[u];
      }
      else if(u == 3) {
         ro = 0;
         printf("密度[kg/m^3]を入力してください\n");
         scanf("%lf", ro);
         ro /= 1000000000;
      }
      else if(u == 5) {
         break;
      }

      printf("部品%dの形を番号で選んでください.\n1.長方形板,2.長い棒,3.薄い円盤,4.円柱,5.円筒形\n6.球,7.球殻,8その他(慣性モーメント既知)\n", i);
      scanf("%d", &n);

      // 質量既知の場合
      if(u == 4) {
         printf("質量[g]を入力してください\n");
         scanf("%lf", &m);
         m /= 1000;
         ro = 0;
      }
      else {
         m = 0;
      }

      // 慣性モーメントが既知の場合
      if(n == 8) {
         printf("\n部品%dの慣性モーメント[kgmm^2]を入力してください\n\n", i);
         scanf("%lf", &t);
      }
      // 想定外の値が入力されたらエラーを表示
      else if(n < 0 || n > 8) {
         // printf("nは1から8の範囲で入力して下さい\n");
         continue;
      }
      // elseを使う場面
      else {
         printf("重心の回転軸からの距離[mm]を入力してください\n");
         scanf("%lf", &e);

         // 同じ処理はまとめる
         t = (*f[n - 1])(&m, ro) + e * e * m;

         printf("\n部品%dの質量=%lf[kg]\n", i, m);
         printf("部品%dのJ=%lf[kgcm^2]\n\n", i, t / 100);
      }

      t0 += t / 100;
   }

   printf("\n全体の慣性モーメント\nJ=%lf[kgcm^2]", t0);

   return 0; // 正常の場合はmain関数は0(EXIT_SUCCESS)を返す
}

double chouhoukei(double* ref_m, double ro) {
   int p;
   double a, b, tt, m;

   printf("回転軸を選んでください\n0.x  1.y  2.z\n");
   scanf("%d", &p);

   printf("横の長さ[mm]を入力してください\n");
   scanf("%lf", &b);

   printf("縦の長さ[mm]を入力してくだいさい\n");
   scanf("%lf", &a);

   m = *ref_m;

   if(m == 0) {
      printf("厚さ[mm]を入力してください\n");
      scanf("%lf", &tt);

      m = ro * (a * b * tt);
      *ref_m = m;
   }

   switch(p) {
   case 0:
      return a * a * m / 12;
   case 1:
      return b * b * m / 12;
   case 2:
      return ((a * a + b * b) * m) / 12;
   }

   return 0;
}

double nagaibou(double* ref_m, double ro) {
   double l, tt, m;

   printf("長さ[mm]を入力してください\n");
   scanf("%lf", &l);

   m = *ref_m;
   if(m == 0) {
      printf("直径[mm]を入力してください\n");
      scanf("%lf", &tt);

      m = ro * (M_PI * tt * tt / 4) * l;
      *ref_m = m;
   }

   return m * l * l / 12;
}

double enban(double* ref_m, double ro) {
   double r, tt, m;
   int p;

   printf("回転軸を選んでください\n0.x  1.y  2.z\n");
   scanf("%d", &p);

   printf("半径[mm]を入力してください\n");
   scanf("%lf", &r);

   m = *ref_m;
   if(m == 0) {
      printf("厚さ[mm]を入力してください\n");
      scanf("%lf", &tt);

      *ref_m = ro * M_PI * r * r * tt;
      m = *ref_m;
   }

   switch(p) {
   case 0:
      return r * r * m / 4;
   case 1:
      return r * r * m / 4;
   case 2:
      return r * r * m / 2;
   }

   return 0;
}

double enchuu(double* ref_m, double ro) {
   int p;
   double r, l, m;
   
   printf("回転軸を選んでください\n0.x  1.y  2.z\n");
   scanf("%d", &p);

   printf("半径[mm]を入力してください\n");
   scanf("%lf", &r);

   printf("長さ[mm]を入力してくだいさい\n");
   scanf("%lf", &l);

   m = *ref_m;
   if(m == 0) {
      m = ro * M_PI * r * r * l;
      *ref_m = m;
   }

   switch(p) {
   case 0:
      return (r * r / 2 + l * l / 12) * m;
   case 1:
      return (r * r / 2 + l * l / 12) * m;
   case 2:
      return r * r * m / 2;
   }

   return 0;
}

double entou(double* ref_m, double ro) {
   int p;
   double r, l, tt, m;

   printf("回転軸を選んでください\n0.x  1.y  2.z\n");
   scanf("%d", &p);
   printf("半径[mm]を入力してください\n");
   scanf("%lf", &r);

   // これ忘れているんじゃないか?
   printf("長さ[mm]を入力してくだいさい\n");
   scanf("%lf", &l);
   // ここまで

   m = *ref_m;
   if(m == 0) {
      printf("筒の厚さ[mm]を入力してください\n");
      scanf("%lf", &tt);

      m = ro * M_PI * r * r * l - M_PI * (r - tt) * (r - tt) * l;
      *ref_m = m;
   }

   switch(p) {
   case 0:
      return (r * r / 2 + l * l / 12) * m;
   case 1:
      return (r * r / 2 + l * l / 12) * m;
   case 2:
      return r * r * m;
   }

   return 0;
}

double kyuu(double* ref_m, double ro) {
   double r, m;
   
   printf("半径[mm]を入力してください\n");
   scanf("%lf", &r);

   m = *ref_m;
   if(m == 0) {
      m = ro * 4 * M_PI * r * r * r / 3;
      *ref_m = m;
   }

   return 2 * m * r * r / 5;
}

double kyuukaku(double* ref_m, double ro) {
   double r, tt, m;

   printf("半径[mm]を入力してください\n");
   scanf("%lf", &r);

   m = *ref_m;
   if(m == 0) {
      printf("核の厚さ[mm]を入力してください\n");
      scanf("%lf", &tt);

      m = ro * 4 * M_PI * r * r * r / 3 - 4 * M_PI * (r - tt) * (r - tt) * (r - tt) / 3;
      *ref_m = m;
   }

   return 2 * r * r * m / 3;
}

2013/12/26

慣性モーメントの計算してみた

 昨日作ったプログラムを手計算ZERO目指してあれこれ継ぎ足して下の表を片手に計算をやらせてみました。
 計算結果があってるかどうかは気にしないとして() ,いつもなら一部品計算して1時間の休憩をしてをやって最終的に「明日になったら頑張る」って投げ出していたところですが10分位でやりたい部分すべての計算を終わらせることができました!!計算があってればですけどね。
 まだおおまかな設計すら途中ですが・・・とりあえず頑張ります。
 絶対どこか計算間違えてる気がする。
 #include<stdio.h>
float chouhoukei(void);
float nagaibou(void);
float enban(void);
float enchuu(void);
float entou(void);
float kyuu(void);
float kyuukaku(void);
float sonota(void);
float situryou(void);
float a,b,l,r,m,j,d[3],ro[4]={2.7/1000000,7.9/1000000,1.19/1000000} ,v,tt;
int i,p,u;
void main(void)
{
int n,s;
float t,e,k,t0=0;
printf("任意の軸(機力の教科書p251の図参照)まわりの慣性モーメントJ[kgcm^2]\n");
i=1,u=0;
while(u!=5){
printf("部材を番号で選んでください\n0.アルミ,1.ステンレス,2.アクリル,3.その他(密度既知)\n4.その他(質量既知),5.終了\n");
scanf("%d",&u);
if(u!=5){
if(u==3){
printf("密度[kg/m^3]を入力してください\n");
scanf("%f",&ro[3]);
ro[3]=ro[3]/1000000000;
}
printf("部品%dの形を番号で選んでください.\n1.長方形板,2.長い棒,3.薄い円盤,4.円柱,5.円筒形\n6.球,7.球殻,8その他(慣性モーメント既知)\n",i);
scanf("%d",&n);
if(u==4){
printf("質量[g]を入力してください\n");
scanf("%f",&m);
m=m/1000;
}
if(n==8){
t=sonota();
}
if(n!=8){
printf("重心の回転軸からの距離[mm]を入力してください\n");
scanf("%f",&e);
if(n==1){
k=chouhoukei();
t=k+e*e*m;
printf("\n部品%dの質量=%f[kg]\n",i,m);
printf("部品%dのJ=%f[kgcm^2]\n\n",i,t/100);
}

if(n==2){
k=nagaibou();
t=k+e*e*m;
printf("\n部品%dの質量=%f[kg]\n",i,m);
printf("部品%dのJ=%f[kgcm^2]\n\n",i,t/100);
}

if(n==3){
k=enban();
t=k+e*e*m;
printf("\n部品%dの質量=%f[kg]\n",i,m);
printf("部品%dのJ=%f[kgcm^2]\n\n",i,t/100);
}

if(n==4){
k=enchuu();
t=k+e*e*m;
printf("\n部品%dの質量=%f[kg]\n",i,m);
printf("部品%dのJ=%f[kgcm^2]\n\n",i,t/100);
}

if(n==5){
k=entou();
t=k+e*e*m;
printf("\n部品%dの質量=%f[kg]\n",i,m);
printf("部品%dのJ=%f[kgcm^2]\n\n",i,t/100);
}

if(n==6){
k=kyuu();
t=k+e*e*m;
printf("\n部品%dの質量=%f[kg]\n",i,m);
printf("部品%dのJ=%f[kgcm^2]\n\n",i,t/100);
}

if(n==7){
k=kyuukaku();
t=k+e*e*m;
printf("\n部品%dの質量=%f[kg]\n",i,m);
printf("部品%dのJ=%f[kgcm^2]\n\n",i,t/100);
}
}
t0+=t/100;
i++;
}
}
printf("\n全体の慣性モーメント\nJ=%f[kgcm^2]",t0);
}

float chouhoukei(void){
printf("回転軸を選んでください\n0.x  1.y  2.z\n");
scanf("%d",&p);
printf("横の長さ[mm]を入力してください\n");
scanf("%f",&b);
printf("縦の長さ[mm]を入力してくだいさい\n");
scanf("%f",&a);
if(u!=4){
printf("厚さ[mm]を入力してください\n");
scanf("%f",&tt);
v=a*b*tt;
m=situryou();
}
d[0]=a*a*m/12;
d[1]=b*b*m/12;
d[2]=((a*a+b*b)*m)/12;
j=d[p];
return j;
}

float nagaibou(void){
printf("長さ[mm]を入力してください\n");
scanf("%f",&l);
if(u!=4){
printf("直径[mm]を入力してください\n");
scanf("%f",&tt);
v=(3.14*tt*tt/4)*l;
m=situryou();
}
j=m*l*l/12;
return j;
}

float enban(void){
printf("回転軸を選んでください\n0.x  1.y  2.z\n");
scanf("%d",&p);
printf("半径[mm]を入力してください\n");
scanf("%f",&r);
if(u!=4){
printf("厚さ[mm]を入力してください\n");
scanf("%f",&tt);
v=3.14*r*r*tt;
m=situryou();
}
d[0]=r*r*m/4;
d[1]=r*r*m/4;
d[2]=r*r*m/2;
j=d[p];
return j;
}

float enchuu(void){
printf("回転軸を選んでください\n0.x  1.y  2.z\n");
scanf("%d",&p);
printf("半径[mm]を入力してください\n");
scanf("%f",&r);
printf("長さ[mm]を入力してくだいさい\n");
scanf("%f",&l);
if(u!=4){
v=3.14*r*r*l;
m=situryou();
}
d[0]=(r*r/2+l*l/12)*m;
d[1]=(r*r/2+l*l/12)*m;
d[2]=r*r*m/2;
j=d[p];
return j;
}

float entou(void){
printf("回転軸を選んでください\n0.x  1.y  2.z\n");
scanf("%d",&p);
printf("半径[mm]を入力してください\n");
scanf("%f",&r);
if(u!=4){
printf("筒の厚さ[mm]を入力してください\n");
scanf("%f",&tt);
v=3.14*r*r*l-3.14*(r-tt)*(r-tt)*l;
m=situryou();
}
d[0]=(r*r/2+l*l/12)*m;
d[1]=(r*r/2+l*l/12)*m;
d[2]=r*r*m;
j=d[p];
return j;
}

float kyuu(void){
printf("半径[mm]を入力してください\n");
scanf("%f",&r);
if(u!=4){
v=4*3.14*r*r*r/3;
m=situryou();
}
j=2*m*r*r/5;
return j;
}

float kyuukaku(void){
printf("半径[mm]を入力してください\n");
scanf("%f",&r);
if(u!=4){
printf("核の厚さ[mm]を入力してください\n");
scanf("%f",&tt);
v=4*3.14*r*r*r/3-4*3.14*(r-tt)*(r-tt)*(r-tt)/3;
m=situryou();
}
j=2*r*r*m/3;
return j;
}

float sonota(void){
printf("\n部品%dの慣性モーメント[kgmm^2]を入力してください\n\n",i);
scanf("%f",&j);
return j;
}

float situryou(void){
if(u<=3){
m=ro[u]*v;
}
return m;
}



2013/12/25

慣性モーメントを計算するプログラム作りました

慣性モーメントを計算しようとしていちいち計算するのも大変なので簡単なプログラムを作りました。

まだ使ってないので実用的かわかりませんが(回転する軸によって値が変わっちゃう)あとでどうにかします。たぶん。

というか多分ネットで検索したらフリーの計算サイトなんかが出てくるんだろうなと思ったけど努力が無駄になってしまうので検索なんてしません(絶対)。

#include<stdio.h>

float chouhoukei(void);
float nagaibou(void);
float enban(void);
float enchuu(void);
float entou(void);
float kyuu(void);
float kyuukaku(void);

float a,b,l,r,m,j; 

void main(void)
{

    int n;
    float t;

    printf("重心z軸(機力の教科書p251の図参照)まわりの慣性モーメント\n");
    printf("部品の形を番号で選んでください.\n1.長方形板,2.長い棒,3.薄い円盤,4.円柱,5.円筒形,6.球,7.球殻\n");
    scanf("%d",&n);

    if(n==1){
        t=chouhoukei();
        printf("J=%f[kgm^2]",t);
    }

    if(n==2){
        t=nagaibou();
        printf("J=%f[kgm^2]",t);
    }



    if(n==3){
        t=enban();
        printf("J=%f[kgm^2]",t);
    }

    if(n==4){
        t=enchuu();
        printf("J=%f[kgm^2]",t);
    }

    if(n==5){
        t=entou();
        printf("J=%f[kgm^2]",t);
    }

    if(n==6){
        t=kyuu();
        printf("J=%f[kgm^2]",t);
    }

    if(n==7){
        t=kyuukaku();
        printf("J=%f[kgm^2]",t);
    }
}


float chouhoukei(void){
    printf("質量[kg]を入力してください\n");
    scanf("%f",&m);
    printf("横の長さ[m]を入力してください\n");
    scanf("%f",&b);
    printf("縦の長さ[m]を入力してくだいさい\n");
    scanf("%f",&a);
    j=(a*a+b*b)*m/12;
    return j;
} 

float nagaibou(void){
    printf("質量[kg]を入力してください\n");
    scanf("%f",&m);
    printf("長さ[m]を入力してください\n");
    scanf("%f",&l);
    j=m*l*l/12;
    return j;
} 

float enban(void){
    printf("質量[kg]を入力してください\n");
    scanf("%f",&m);
    printf("半径[m]を入力してください\n");
    scanf("%f",&r);
    j=r*r*m/2;
    return j;
} 

float enchuu(void){
    printf("質量[kg]を入力してください\n");
    scanf("%f",&m);
    printf("半径[m]を入力してください\n");
    scanf("%f",&r);
    printf("長さ[m]を入力してくだいさい\n");
    scanf("%f",&l);
    j=r*r*m/2;
    return j;
} 

float entou(void){
    printf("質量[kg]を入力してください\n");
    scanf("%f",&m);
    printf("半径[m]を入力してください\n");
    scanf("%f",&r);
    j=r*r*m;
    return j;
} 

float kyuu(void){
    printf("質量[kg]を入力してください\n");
    scanf("%f",&m);
    printf("半径[m]を入力してください\n");
    scanf("%f",&r);
    j=2*m*r*r/5;
    return j;
} 

float kyuukaku(void){
    printf("質量[kg]を入力してください\n");
    scanf("%f",&m);
    printf("半径[m]を入力してください\n");
    scanf("%f",&r);
    j=2*r*r*m/3;
    return j;
} 

2013/12/24

LM2596T-ADJで電源を作りましたよっと

りゅーしです。

降圧型電源スイッチングレギュレーターIC,LM2596T-ADJを使って電源を作りました。

サーボモータを動かすときやちょうどいい電源がないときに便利です。

サーボモーターの選定

こんにちは、suzutoです。

最近はガレキ除去アームに用いるサーボモータの選定を行っていました。
まだ、アームの形状が完全には決まっていないので選定作業は完了していませんが、
とりあえず、このサーボモータは使えそうというのをいくつか見つけました。

あとは回路・システム担当の人に消費電力やPWM周期等を確認して使えるか
どうか判断してもらい、使用するサーボモーターを決めようと思います。

2013/12/22

忘年会を開きました。

Lv_ZEROです。

今年ももう10日を切りましたね。ということで昨日、サークル内で忘年会を開きました。
ここ最近はレスコンやロボットグランプリの活動に忙しかったので、いい具合に羽目を外す事ができました。
また、大学の方は、昨日から冬季休校となり、冬休みに入りました。冬休みの間はだらだらと過ごしたいと思ってしまいますが、1月の末辺りにレスコンの書類提出やロボットグランプリ大道芸競技のビデオ審査などが控えていますので、メリハリのある活動を行い、有意義な冬休みにしたいと思います。

2013/12/19

2軸ジョイスティック

contrailです。

今日は2軸ジョイスティックモジュールを使ってみました。
これを使ってサーボモータを動かしてみようと考え、まず傾けた分だけ角度を加算していくプログラムを作ろうとしてみましたが、どうもうまくいきません。原因を調べてみると、どうやら計算の途中で数値がオーバーフローしていたようで、うまくいかなかったみたいです。これを修正したところうまく動くようになったのですが、時間が遅くなってしまったので今日はサーボモータを動かすことができませんでした。

2013/12/18

感圧センサを使ってみました

 contrailです。


昨日に引き続いて、今日はArduino互換ボードRomeoで感圧センサを使って、LEDを点灯させてみました。


簡単ですが今回の回路を載せておきます。

3軸ジャイロスコープ・3軸加速度センサーモジュール

りゅーしです。

がじぇるねと、MPU-6050を使用して加速度と角速度を取得してみました

ガレキ除去アームの姿勢表示

Lv_ZEROです。

1号機のガレキ除去アームはパラレルリンクによる平行リンク機構となっており、作業範囲が直感的には分かり難かったため、Mathmaticaを使ってアームの姿勢を表示してみました。
各関節について順運動学を解き、その点を繋いで表示しています。また、Manipulateを用いて各関節角をスライダーで変更できるようにしました。
これで必要な作業範囲を満たすリンクの長さを決定するのに役立ちそうです。

2013/12/17

ガレキ除去アーム構想

suzutoです。
ガレキ除去機のアームの形状が決まりました。


記号を正しく使えているか不安です…


グランプリ試作

HIROSHIです。
日曜日に製作したグランプリ大道芸部門のロボットの機構の試作の動作確認(手動)をしました

ネジやギヤとの干渉,ラックランドピニオン機構の可動範囲,機構内の余分な隙間,実際の演技の仕様をどうするかなどいろいろと考えるべき部分が試作を作ることにより明らかになりました

Arduinoを使ってみました

contrailです。
サークルで購入したArduino互換ボード
http://akizukidenshi.com/catalog/g/gM-07045/
を使ってみました。

まずはサーボモータを動かしてみました。Arduino Unoと比べると3pinヘッダが標準で付いているので使いやすかったです。

次にフォトリフレクタを使ってLEDを点灯させてみました。

 正常に動作したようで何よりです。

TPIP開発

Dです。
TPIP開発のため、udpでの非同期通信のテストを行いました。
受信用のスレッドで文字を受信することができ、安心しました。

メカナムホイール

おはこんにちばんわ、イトゥーです。
メカナムホイールを使ってみました。
挙動が面白いのでいろいろな用途に使っていけたらと思います。
詳しい機構等はググって下さい。

2013/12/16

ガレキ除去機構想

ガレキ除去機担当のsuzutoです。

レスキューやらまいかは今年もガレキ除去機を出場させます。
そこで、新たなガレキ除去用アームについて検討したところ、アームの根元の構造は
第12回大会で使用したリンク機構を参考に作ることになりました。ということで、先輩か
ら頂いた12回大会のガレキ除去機のCADデータの中で参考になりそうなものを探した
ところ、アーム根元のギアボックスが見つかりました。





このギアボックスは回転角度を検出するために、ポテンショメータを取り付けています。
このように、アームの操作がしやすくなるようなセンサを使っていきたいと思います。

2013/12/14

これぞC++の真骨頂! タプルを実装してみた

今のVC++2013には標準ライブラリとしてtupleがあります。

std::tuple<int, double> t(100, 10.5);
std::cout << std::get<0>(t) << std::endl;
std::cout << std::get<1>(t) << std::endl;

こんな感じでstd::tuple<型リスト>という複数の型を持ったインスタンスを生成できます。
これは構造体と同じなのですが、構造体の場合は宣言しなければアクセスできませんでした。

ミーティング12/13

Lv_ZEROです。

今日というよりはもう昨日ですが、第14回レスキューロボットコンテストでのコンセプトを決定しました。
これからは決めたコンセプトに沿うように機体・システムを製作していこうと思います。

2013/12/12

定例会12/12

Lv_ZEROです。

本日の定例会では第14回レスキューロボットコンテストについてのミーティングを行いました。
フィロソフィーや規定などの再確認を行い、チームのコンセプトをどうするか話し合いました。
実際のレスキュー活動においては要救助者や操縦者に対しての配慮が非常に大切です。そのような配慮を元に、コンセプトを考え、案出しをしましたが、決定するまでは出来ませんでした。
なので、明日もう一度ミーティングを行い、コンセプトを決定し、活動方針を固めたいと思います。

話は変わりますが、明日12月13日(金)の19:00からロボット日本一決定戦!!「リアルロボットバトル」という番組が放送されます。各チームが1年近くかけて製作したリアルスケールの人型ロボット同士を戦わせるという企画です。各チームが創意工夫をしてロボット製作を行っており、非常に見応えがありそうです。興味のある方は見逃さないようにしましょう。

ロボット日本一決定戦!!「リアルロボットバトル」:http://www.ntv.co.jp/robot/outline.html

2013/12/11

今日の活動報告

Kです。今日は、いろいろテストしてみました。

 1. 手持ちのフォトカプラTLP521の周波数特性を実測。5kHzくらいから使い物にならなかった。回路を工夫すれば解消されると思われる。
2. 先輩の作ったモータードライバーの解析。Hブリッジの電源部分をFETでPWM駆動していて、その部分にふぉとかぷらが1つ、またゲートにフォトカプラ2つが使われていた。PWMの入力部分と制御しているマイコンは同電位だった。
3. 同調回路の実験。手持ちのマイクロインダクターで同調回路を作った。555で矩形波を作って同調させたところ、15kHz (1mH, 1μF)では同調された。ただし、500Hzではできなかった。
4. ステッピングモーターを2相励磁式で動かしてみました。PICから4ポートで制御します。各端子を2SC1825(小信号用だけど使ってしまった)
のベースに1kΩを介して接続。エミッタはGNDにして、コレクタとステッピングモーターのφ1, 2, _1, _2と接続。φ1, φ2, φ_1, φ_2の順番で動かす1相励磁式及びφ1φ2, φ2φ_1, φ_1φ_2, φ_2φ1と動かす2相励磁式を試した。以下ソースだがただタイマで回しているだけ。

初めPR2 = 128でやってみたら、1.35Hzだったので、PR2 * 1.35して172にしたところ1Hz=60rpmで回転するようになった。実験したところPR2 = 64では回転できなかった。
トランジスタに小信号用を使っていたり、電源はMAX1Aのレギュレータだったりとひどいので実用を考えると改良が必要。オシロスコープでトランジスタのベースを調べると、-26Vくらいの瞬間的な電圧がかかっていた。(コイルだからな……)当然、逆起電力を短絡するためのダイオードで除去できた。

#include <xc.h>

#define _XTAL_FREQ 16000000

#pragma config WDTE = OFF
#pragma config FOSC = 4
#pragma config MCLRE = 1
#pragma config LVP = OFF
#pragma config PLLEN = OFF

void main(void){
    OSCCON = 0b01101000;

    PORTA = 0x00;
    LATA = 0x00;
    TRISA = 0b00000000;
    ANSELA = 0b00000000;

    PORTB = 0x00;
    LATB = 0x00;
    TRISB = 0b00000000;
    ANSELB = 0b00000000;

    T2CON = 0b00000110;
    PR2 = 172;
    TMR2IE = 1;
   
    PEIE = 1;
    GIE = 1;
   
    while(1){
        __delay_ms(1000);
        LATA7 ^= 1;
    }
}

void interrupt INTERRUPT(){
    static char n1 = 0, n2 = 1, bn1, bn2;

    if(TMR2IF){
        LATA &= ~(0x01 << bn1); // bn1ビット目をクリア
        LATA &= ~(0x01 << bn2); // bn2ビット目をクリア
        LATA |= 0x01 << n1; // n1ビット目をセット
        LATA |= 0x01 << n2; // n2ビット目をセット
        bn1 = n1;
        bn2 = n2;
        n1++;
        n2++;
        if(n1 >= 4) {
            n1 = 0;
        }
        if(n2 >= 4) {
            n2 = 0;
        }
        TMR2IF = 0;
    }
}

5. 初代ポケモンの「じてんしゃ」の曲が完成した。PICで作った矩形波によって再生される。

C言語Tips5 おしまい!

C言語は言語仕様が大きくないので、また、このサークルではマイコン用途にしか使わないので
余り書くことがありません。
ただし、一通り入門が終わったらガシガシコードを書いていって下さい。
入門書に書いてなさそうなことは、例えば、
・グローバル変数とextern, static
・ファイルの分割と隠蔽
・typedef
・マクロ・インライン関数、インクルードガード
・オブジェクト指向
などがあります。これらも勉強しておくといいかもしれません。

さてC言語Tipsの最後にC言語理解度テストを掲載しておきますね!

0~5問正解 : 初心者でしょう……
6~9問正解 : そろそろ初心者ではないでしょう?

問世界 : もう初心者ではないでしょう!

1. 次の宣言a, b, cについて正しい説明をA~Dのなかから全て選んで下さい。
char a[] = "strings";
char* b = "strings";
char c[] = { 's', 't', 'r', 'i', 'n', 'g', 's', '\0' };

A. aは要素数7の配列である。
B. aとbはともにスタックに格納される。
C. aとcはともにスタックに格納される。
D. 変数aは書き換えられないが、変数bは書き換えられる。

2. 構造体Sが次のように宣言されているとき、s->m->mと等価な表現をA~Dのなかから1つ選んで下さい。
struct S {
    struct S* m;
};

struct S* a;

A. (*a).(*m).(*m)
B. (*a).(*m).m
C. (*(*(*a).m)).m
D. (*(*a).m).m

3. 次の演算の中で1つだけ値が異なるものをA~Dの中から1つ選んで下さい。

A. ~(-0x01)
B. 2 ^ 3
C. 1 && -1
D. -0x03 & 0x03

4. 次のように宣言された配列aにたいして、各要素のポインタを格納する配列bがある。
ある関数fは配列bのある位置(配列bの先頭の位置を0とする)xからある位置yまで探索し、最大値を返す。
関数fの引数として妥当なものを次のA~Dの中から1つ選んで下さい。

int a[8];
int* b[8];

A. int f(int* b, int x, int y);
B. int f(int* b, int* x, int* y);
C. int f(int** b, int x, int y);
D. int f(int** b, int* x, int* y);

5. 次のプログラムを実行した結果の変数xの値をA~Fの中から1つ選んで下さい。
int f(int* x) {
    return (*x)++;
}

int main(void) {
    int x = 0;
    x += f(&x) || f(&x) || f(&x);
 return 0;
}

A. 0
B. 1
C. 2
D. 3
E. 4
F. 5

6. 次の宣言の意味をA~Dの中から1つ選んで下さい。
また、この変数xを使った文として正しいものをX~Zの中から1つ選んで下さい。(ただしN, Mは十分大きいものとします。)
int *(*(*x)[N][M])(void);

A. 変数xはN×Mの2次元配列で、各要素は整数型intのポインタを返す引数なしの関数ポインタである。
B. 変数xは各要素が整数型intのN×Mの2次元配列を返す引数なしの関数ポインタである。
C. 変数xはN×Mの2次元配列のポインタで、各要素は整数型intのポインタを返す引数なしの関数ポインタである。
D. 変数xは各要素が整数型intのN×Mの2次元配列のポインタを返す引数なしの関数ポインタである。

X. *x[1][1] = (int* (*(*)[N][M])())v;
Y. (*x)[1][1] = (int* (*)())v;
Z. ((int* (*)())(*x))[1] = (int* (*)())v;

7. 次のプログラムを実行した結果のf(&x)の値をA~Fの中から1つ選んで下さい。
struct S {
    struct S* s;
};

int f(struct S* s) {
    static int x;
    x++;

    if(s->s == NULL) {
        return x;
    }
    else {
        return f(s->s);
    }
}

int main(void) {
    struct S x;
    struct S s[3];
    int i;

    x.s = &s[0];
    x.s->s = &s[1];
    x.s->s->s = &s[2];
    x.s->s->s->s = NULL;
   
    f(&x); // いくつ?
    return 0;
}

A. 0
B. 1
C. 2
D. 3
E. 4
F. 5

8. a[i][j]と等価なものを次のA~Dの中から全て選んで下さい。

A. i[a][j]
B. i[j][a]
C. i[a[j]]
D. j[i[a]]

9. (++a)++;について正しいものを次のA~Dの中から1つ選んで下さい。

A. a += 2;と等価である。
B. ++aは左辺値でないからコンパイルエラーとなる。
C. ++aは変更不能な左辺値であるからコンパイルエラーとなる。
D. ++が後置式であるからコンパイルエラーである。

10. 型int [][N]と互換性のある型を次のA~Eの中から1つ選んで下さい。

A. int *[N]
B. int (*)[N]
C. int *[]
D. int **
E. int *

正解は……

C言語Tips4 無名構造体と共用体

共用体ってあるじゃないですか。

union Data {
    unsigned int value;
    unsigned char byte;
};

これ。

C言語Tips3 ポインタを引数にとる関数にはconstを付けよう

元々C言語にはconstがありませんでしたが、C++から逆輸入されて、多くのCコンパイラに実装されています。XC8にもあります。

C言語Tips2 enum使え!

開始モード、実行中モード、終了モードとかあって、それぞれ
int mode;

mode = 0;

mode = 1;

if(mode == 1) {
    なんちゃら
}

とかしてませんか?

2013/12/07

C言語Tips1 ポインタの問題!

C言語のポインタで躓く人が多いそうです。今回は問題を出します!

問題 : 「void (*(*p)[3])(void* (*[])(void));」をmain関数の中で宣言しました。

int main(void) {
    void (*(*p)[3])(void* (*[])(void));
    return 0;
}

このpを使ってサンプルプログラムを作りなさい。回答例は続きを読むで!