0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AB位相信号の取り込み(エンコーダー入力)

Posted at

  エンコーダー拡張

前回作ったパルスカウンタは低速では特に問題ないのですが、高速では取りこぼしが有るようです。

カウントの取りこぼしは無いようですが、時々出力値が乱れます(対策を考え中)

#include "driver/pcnt.h"

#define PULSE_INPUT_PIN_X 4 //パルスの入力ピン 今回はエンコーダのA相を接続
#define PULSE_CTRL_PIN_X 2 //制御ピン 今回はエンコーダのB相を接続

#define PULSE_INPUT_PIN_Y 35 //パルスの入力ピン 今回はエンコーダのA相を接続
#define PULSE_CTRL_PIN_Y 34 //制御ピン 今回はエンコーダのB相を接続

#define PULSE_INPUT_PIN_Z 36 //パルスの入力ピン 今回はエンコーダのA相を接続
#define PULSE_CTRL_PIN_Z 39 //制御ピン 今回はエンコーダのB相を接続

#define PCNT_H_LIM_VAL   30000 //カウンタの上限
#define PCNT_L_LIM_VAL  -30000 //カウンタの下限

int16_t count_x; //カウント数
int16_t count_y; //カウント数
int16_t count_z; //カウント数

int32_t prev_count_x = 0;
int32_t current_count_x = 0;
int32_t overflow_count_x = 0;


int32_t prev_count_y = 0;
int32_t current_count_y = 0;
int32_t overflow_count_y = 0;


int32_t prev_count_z = 0;
int32_t current_count_z = 0;
int32_t overflow_count_z = 0;



void ScaleInit_x() {
  pcnt_config_t pcnt_config_x;//設定用の構造体の宣言
  pcnt_config_x.pulse_gpio_num = PULSE_INPUT_PIN_X;
  pcnt_config_x.ctrl_gpio_num = PULSE_CTRL_PIN_X;
  pcnt_config_x.lctrl_mode = PCNT_MODE_REVERSE;
  pcnt_config_x.hctrl_mode = PCNT_MODE_KEEP;
  pcnt_config_x.channel = PCNT_CHANNEL_1;
  pcnt_config_x.unit = PCNT_UNIT_2;
  pcnt_config_x.pos_mode = PCNT_COUNT_INC;
  pcnt_config_x.neg_mode = PCNT_COUNT_DEC;
  pcnt_config_x.counter_h_lim = PCNT_H_LIM_VAL;
  pcnt_config_x.counter_l_lim = PCNT_L_LIM_VAL;
  pcnt_unit_config(&pcnt_config_x);//ユニット初期化
  pcnt_counter_pause(PCNT_UNIT_2);//カウンタ一時停止
  pcnt_counter_clear(PCNT_UNIT_2);//カウンタ初期化
  pcnt_counter_resume(PCNT_UNIT_2);//カウント開始

}


void ScaleInit_y() {
  pcnt_config_t pcnt_config_y;//設定用の構造体の宣言
  pcnt_config_y.pulse_gpio_num = PULSE_INPUT_PIN_Y;
  pcnt_config_y.ctrl_gpio_num = PULSE_CTRL_PIN_Y;
  pcnt_config_y.lctrl_mode = PCNT_MODE_REVERSE;
  pcnt_config_y.hctrl_mode = PCNT_MODE_KEEP;
  pcnt_config_y.channel = PCNT_CHANNEL_1;
  pcnt_config_y.unit = PCNT_UNIT_3;
  pcnt_config_y.pos_mode = PCNT_COUNT_INC;
  pcnt_config_y.neg_mode = PCNT_COUNT_DEC;
  pcnt_config_y.counter_h_lim = PCNT_H_LIM_VAL;
  pcnt_config_y.counter_l_lim = PCNT_L_LIM_VAL;
  pcnt_unit_config(&pcnt_config_y);//ユニット初期化
  pcnt_counter_pause(PCNT_UNIT_3);//カウンタ一時停止
  pcnt_counter_clear(PCNT_UNIT_3);//カウンタ初期化
  pcnt_counter_resume(PCNT_UNIT_3);//カウント開始
}


void ScaleInit_z() {
  pcnt_config_t pcnt_config_z;//設定用の構造体の宣言
  pcnt_config_z.pulse_gpio_num = PULSE_INPUT_PIN_Z;
  pcnt_config_z.ctrl_gpio_num = PULSE_CTRL_PIN_Z;
  pcnt_config_z.lctrl_mode = PCNT_MODE_REVERSE;
  pcnt_config_z.hctrl_mode = PCNT_MODE_KEEP;
  pcnt_config_z.channel = PCNT_CHANNEL_1;
  pcnt_config_z.unit = PCNT_UNIT_4;
  pcnt_config_z.pos_mode = PCNT_COUNT_INC;
  pcnt_config_z.neg_mode = PCNT_COUNT_DEC;
  pcnt_config_z.counter_h_lim = PCNT_H_LIM_VAL;
  pcnt_config_z.counter_l_lim = PCNT_L_LIM_VAL;
  pcnt_unit_config(&pcnt_config_z);//ユニット初期化
  pcnt_counter_pause(PCNT_UNIT_4);//カウンタ一時停止
  pcnt_counter_clear(PCNT_UNIT_4);//カウンタ初期化
  pcnt_counter_resume(PCNT_UNIT_4);//カウント開始

}


void CountReset_x(void) {
  ScaleInit_x();
  overflow_count_x = 0;
  prev_count_x = 0;

}


void CountReset_y(void) {
  ScaleInit_y();
  overflow_count_y = 0;
  prev_count_y = 0;

}



void CountReset_z(void) {
  ScaleInit_z();
  overflow_count_z = 0;
  prev_count_z = 0;

}


int ret_count_x(void) {
  char i;

  pcnt_get_counter_value(PCNT_UNIT_2, &count_x);

  current_count_x = (int32_t)count_x;


  if ((abs(prev_count_x) - abs(current_count_x)) > PCNT_H_LIM_VAL / 2 ) {

    if (current_count_x < prev_count_x) {
      overflow_count_x++;
      i = 1;
    } else {
      overflow_count_x--;
      i = -1;
    }
  }

  prev_count_x = current_count_x;


  return int32_t((current_count_x + overflow_count_x * (int32_t(PCNT_H_LIM_VAL + i))) * (int32_t)2);
}



int32_t ret_count_y(void) {
  char i;

  pcnt_get_counter_value(PCNT_UNIT_3, &count_y);

  current_count_y = (int32_t)count_y;


  if ((abs(prev_count_y) - abs(current_count_y)) > PCNT_H_LIM_VAL / 2 ) {

    if (current_count_y < prev_count_y) {
      overflow_count_y++;
      i = 1;
    } else {
      overflow_count_y--;
      i = -1;
    }
  }

  prev_count_y = current_count_y;

  return int32_t((current_count_y + overflow_count_y * (int32_t(PCNT_H_LIM_VAL + i))) * (int32_t)2);
}



int ret_count_z(void) {

  char i;

  pcnt_get_counter_value(PCNT_UNIT_4, &count_z);

  current_count_z = (int32_t)count_z;


  if ((abs(prev_count_z) - abs(current_count_z)) > PCNT_H_LIM_VAL / 2 ) {

    if (current_count_z < prev_count_z) {
      overflow_count_z++;
      i = 1;
    } else {
      overflow_count_z--;
      i = -1;
    }
  }

  prev_count_z = current_count_z;

  return int32_t((current_count_z + overflow_count_z * (int32_t(PCNT_H_LIM_VAL + i))) * (int32_t)2);
}





void setup() {
  //エンコーダー初期化
  ScaleInit_x();
  ScaleInit_y();
  ScaleInit_z();

  Serial.begin(115200);


}

  //エンコーダーカウント値を出力    
  Serial.printf("S:%10d:%10d:%10d:\n", (int)ret_count_x(),(int)ret_count_y(), (int)ret_count_z() / 5);
  



  //エンコーダーカウントリセット
  if (###) {//ボタンやシリアル通信からのリセット条件
    CountReset_x();
  }
  if (###) {
    CountReset_y();
  }
  if (####) {
    CountReset_z();

  }

}

こちらの記事を参考にほぼコピーしています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?