読者です 読者をやめる 読者になる 読者になる

アナログピンをpinModeしない

アナログピンはsetupでpinModeしないこと.
pinModeするとデジタルピン扱いになり,不都合が発生しやすい.

2015/06/06 追記: スケッチを公開.
 

目的

analogRead値(今回は半固定抵抗)を変換してLEDの明るさを調節したい.

 

環境

 

スケッチ

半固定抵抗の抵抗値でデューティー比を変化させて,LEDの明るさを調節させる.

const int LED = 9; // LEDはpinNO.D9
const int RES = A0; // 半固定抵抗はpinNO.A0


/* アナログ入力値(0~1023)をデジタルPWMで扱える値(0~255)に変換 */
int convert(int analog_in);


/* 各ピンの入出力,シリアル通信のbpsを設定 */
void setup(void)
{
  pinMode(LED, OUTPUT); // LEDは出力
  
  Serial.begin(9600); // シリアル通信は9600bps
  // pinMode(RES, INPUT); // 半固定抵抗は入力 // デジタルピンとして扱ってしまう
}

/* 繰り返す */
void loop(void)
{
  Serial.println(analogRead(RES));
  analogWrite(LED, convert(analogRead(RES)));
}


/* アナログ入力値(0~1023)をデジタルPWMで扱える値(0~255)に変換 */
/* 引数 int analog_in: アナログ入力値 */
/* 返却値 int: デジタルPWMで扱える値 */
int convert(int analog_in)
{
  double x = (double)analog_in / 1023.0 * 255.0;
  
  return (int)floor(x + 0.5);
}

 

結論

アナログピンとして扱いたいのにpinModeしてしまうとデジタルピン扱いになり,当然値は0/1になるので動くと思ったプログラムも動かない.
プログラムのバグか,回路のバグか,知識がないと判断が困難になる.

 

おまけ

上記のスケッチを検討した後に,以下のスケッチも検討していた.

#define WAVE random(0, 3) // 0->step 1->saw 2->triangle

const int LED = 9; // LEDはpinNO.D9

int getDutyCycle(int val); // デューティー比からanalogWriteで与える引数を求める
void stepwave(void); // ステップ波
void sawwave(void); // のこぎり波
void trianglewave(void); // 三角波


/* 各ピンの入出力,シリアル通信のbpsを設定 */
void setup()
{
    Serial.begin(9600); // シリアル通信は9600bps
    randomSeed(analogRead(A0)); // 未接続のアナログピンからランダム値を取得して乱数のシードとする

    pinMode(LED, OUTPUT); // LEDは出力
}

/* 繰り返す */
void loop()
{
    switch( WAVE ){
      case 0: stepwave(); break; // ステップ波
      case 1: sawwave(); break; // のこぎり波
      case 2: trianglewave(); break; // 三角波
      default: Serial.println("制御外です"); analogWrite(LED, 0); break; 
    }
}


/* デューティー比からanalogWriteで与える引数を求める */
/* int val : 平均電圧として電源電圧のval%(デューティー比)を要求*/
/* val%を0-255に変換した値を返却(四捨五入) */
int getDutyCycle(int val)
{
    double x = (double)val * 255.0 / 100.0;

    return (int)floor(x + 0.5);
}


/* ステップ波 */
void stepwave(void)
{
    Serial.println("StepWave");
    for( int val = 0, cnt = 0; ; ++cnt, val = (val + 25) % 125 ){
      /* デューティー比val%でPWM派をLEDのピンから出力 */
      analogWrite(LED, getDutyCycle(val));
      /* 一定時間その平均電圧を保つ */
      delay(1000);
    }
}

/* のこぎり波 */
void sawwave(void)
{
    Serial.println("sawWave");
    for( int val = 0, cnt = 0; ; ++cnt, val = (val + 1) % 101 ){
      /* デューティー比val%でPWM派をLEDのピンから出力 */
      analogWrite(LED, getDutyCycle(val));
      /* 一定時間その平均電圧を保つ */
      delay(1000 / 255);
    }
}

/* 三角波 */
void trianglewave(void)
{
    Serial.println("triangWave");
    for( int cnt = 0; ; ++cnt ){
      int val = 0;
      /* 上昇 */
      for( ; val < 81 ; ++val ){ /* 平均電圧4Vは80% */
        /* デューティー比val%でPWM派をLEDのピンから出力 */
        analogWrite(LED, getDutyCycle(val));
        /* 一定時間その平均電圧を保つ */
        delay(1000 / 204);
      }
      /* 下降 */
      for( ; -1 < val ; --val ){ /* 平均電圧0Vは0% */
        /* デューティー比val%でPWM派をLEDのピンから出力 */
        analogWrite(LED, getDutyCycle(val));
        /* 一定時間その平均電圧を保つ */
        delay(1000 / 204);
      }
    }
}

randomSeedの引数として 未接続の アナログピンを使用する.
しかし,「未接続の」というのをすっかり読み落としており,前の回路で使用しているA0をそのまま引数に(回路を組み直すのを面倒がって半固定抵抗を接続したままLEDの回路だけ使用していた).
ステップ波しか出力されないと思いきや,という感じ.
もちろん,半固定抵抗をぐるぐる触ってからリセットすると別の波形になる.