Help us understand the problem. What is going on with this article?

鉛筆可変抵抗でLED調光

More than 1 year has passed since last update.

鉛筆で可変抵抗を自作できると聞きテストした.
最終的には, 長さに比例して抵抗が大きくなる別の素材が欲しい.
しかし, まずは試しということで.

構成

IMG_2898.jpg

動画

https://www.youtube.com/watch?v=TCviH7VKQeI

git

https://github.com/keitasumiya/arduino/tree/master/analog-in

code

下記の段階にわけて掲載する.
1) analog-inputする
2) inputの値を履歴のリストとして一定数保持し, その平均を求める
3) inputの履歴リストの誤差二乗平均ルートをとる(自作可変抵抗器に接触しているかどうかを検出するため)
4) 自作可変抵抗器に接触している(touch)かどうかの判定をする
5) 自作可変抵抗器に接触している際に, その抵抗の値によってLEDを調光する

analog-inputする

analog_in.ino
const int pinI = 0; //input

void setup() {
  pinMode(pinI, INPUT);
  Serial.begin(9600);
}

void loop() {
  int val = analogRead(pinI);
  Serial.println(val);
}

inputの値を履歴のリストとして一定数保持し, その平均を求める

analog_in_mean_fn.ino
const int PinI = 0; //input
const int ValuesSize = 10;
int Values[ValuesSize];
int Frame;

void setup() {
  pinMode(PinI, INPUT);
  Serial.begin(9200);
  for(int i=0; i<ValuesSize; i++){
    Values[i] = 0;
  }
  Frame = 0;
}

void loop() {
  Frame++;
  int val = analogRead(PinI);

  update_values(Values, sizeof(Values)/sizeof(int), val);

  float total = calc_total(Values, sizeof(Values)/sizeof(int));
  float mean = calc_mean(Values, sizeof(Values)/sizeof(int));

  print_int("", val, " ");
  print_float("total=", total, " ");
  print_float("mean=", mean, " ");
  print_ints("values=[", Values, sizeof(Values)/sizeof(int), "] ");

  Serial.println("");
}

//######################################################################
//######################################################################
//######################################################################

void update_values(int _values[], int _valuesSize, int _val){
  if(Frame < _valuesSize){
    _values[Frame] = _val;
  } else {
    for(int i=0; i<_valuesSize-1; i++){
      _values[i] = _values[i+1];
    }
    _values[_valuesSize-1] = _val;
  }
}

//----------------------------------------------------------------------

float calc_total(int _values[], int _valuesSize){
  float _total = 0;
  for(int i=0; i<_valuesSize; i++){
    _total+=_values[i];
  }
  return _total;
}

//----------------------------------------------------------------------

float calc_mean(int _values[], int _valuesSize){
  float _total = 0;
  float _mean = 0;
  _total = calc_total(_values, _valuesSize);
  _mean = _total/float(_valuesSize);
  return _mean;
}

//----------------------------------------------------------------------

void print_int(char* _c1, int _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}

//----------------------------------------------------------------------

void print_float(char* _c1, float _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}

//----------------------------------------------------------------------

void print_ints(char* _c1, int _x[], int _xSize, char* _c2){
  Serial.print(_c1);
  for(int i=0; i<_xSize-1; i++){
    print_int("", _x[i], " ");
  }
  print_int("", _x[_xSize-1], "");
  Serial.print(_c2);
}

inputの履歴リストの誤差二乗平均ルートをとる

analog_in_rootMeanSquareError_fn.ino
const int PinI = 0; //input
const int ValuesSize = 10;
int Values[ValuesSize];
int Frame;

void setup() {
  pinMode(PinI, INPUT);
  Serial.begin(9200);
  for(int i=0; i<ValuesSize; i++){
    Values[i] = 0;
  }
  Frame = 0;
}

void loop() {
  Frame++;
  int val = analogRead(PinI);

  update_values(Values, sizeof(Values)/sizeof(int), val);

  float total = calc_total(Values, sizeof(Values)/sizeof(int));
  float mean = calc_mean(Values, sizeof(Values)/sizeof(int));
  float rootMeanSquareError = calc_rootMeanSquareError(Values, ValuesSize, mean);

  print_int("", val, " ");
  print_float("total=", total, " ");
  print_float("mean=", mean, " ");
  print_float("rootMeanSquareError=", rootMeanSquareError, " ");
  print_ints("values=[", Values, sizeof(Values)/sizeof(int), "] ");

  Serial.println("");
}

//######################################################################
//######################################################################
//######################################################################

void update_values(int _values[], int _valuesSize, int _val){
  if(Frame < _valuesSize){
    _values[Frame] = _val;
  } else {
    for(int i=0; i<_valuesSize-1; i++){
      _values[i] = _values[i+1];
    }
    _values[_valuesSize-1] = _val;
  }
}

//----------------------------------------------------------------------

float calc_total(int _values[], int _valuesSize){
  float _total = 0;
  for(int i=0; i<_valuesSize; i++){
    _total+=_values[i];
  }
  return _total;
}

//----------------------------------------------------------------------

float calc_mean(int _values[], int _valuesSize){
  float _total = 0;
  float _mean = 0;
  _total = calc_total(_values, _valuesSize);
  _mean = _total/float(_valuesSize);
  return _mean;
}

//----------------------------------------------------------------------

float calc_rootMeanSquareError(int _values[], int _valuesSize, float _trueValue){
  float _totalSquareError = 0;
  float _meanSquareError = 0;
  float _rootMeanSquareError = 0;
  for(int i=0; i<_valuesSize; i++){
    float _error = _values[i]-_trueValue;
    _totalSquareError+=_error*_error;
  }
  _meanSquareError = _totalSquareError/float(_valuesSize);
  _rootMeanSquareError = sqrt(_meanSquareError);
  return _rootMeanSquareError;
}

//----------------------------------------------------------------------

void print_int(char* _c1, int _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}

//----------------------------------------------------------------------

void print_float(char* _c1, float _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}

//----------------------------------------------------------------------

void print_ints(char* _c1, int _x[], int _xSize, char* _c2){
  Serial.print(_c1);
  for(int i=0; i<_xSize-1; i++){
    print_int("", _x[i], " ");
  }
  print_int("", _x[_xSize-1], "");
  Serial.print(_c2);
}

自作可変抵抗器に接触している(touch)かどうかの判定をする

analog_in_touch_fn.ino
const int PinI = 0; //input
const int ValuesSize = 10;
const float ErrorThreshold = 70.0;
int Values[ValuesSize];
int Frame;

void setup() {
  pinMode(PinI, INPUT);
  Serial.begin(9200);
  for(int i=0; i<ValuesSize; i++){
    Values[i] = 0;
  }
  Frame = 0;
}

void loop() {
  Frame++;
  int val = analogRead(PinI);

  update_values(Values, sizeof(Values)/sizeof(int), val);

  float total = calc_total(Values, sizeof(Values)/sizeof(int));
  float mean = calc_mean(Values, sizeof(Values)/sizeof(int));
  float rootMeanSquareError = calc_rootMeanSquareError(Values, ValuesSize, mean);

  bool isTouch = check_touch(rootMeanSquareError, ErrorThreshold);

  print_bool("", isTouch, " ");
  print_int("", val, " ");
  print_float("total=", total, " ");
  print_float("mean=", mean, " ");
  print_float("rootMeanSquareError=", rootMeanSquareError, " ");
  print_ints("values=[", Values, sizeof(Values)/sizeof(int), "] ");  
  Serial.println("");
}

//######################################################################
//######################################################################
//######################################################################

void update_values(int _values[], int _valuesSize, int _val){
  if(Frame < _valuesSize){
    _values[Frame] = _val;
  } else {
    for(int i=0; i<_valuesSize-1; i++){
      _values[i] = _values[i+1];
    }
    _values[_valuesSize-1] = _val;
  }
}

//----------------------------------------------------------------------

float calc_total(int _values[], int _valuesSize){
  float _total = 0;
  for(int i=0; i<_valuesSize; i++){
    _total+=_values[i];
  }
  return _total;
}

//----------------------------------------------------------------------

float calc_mean(int _values[], int _valuesSize){
  float _total = 0;
  float _mean = 0;
  _total = calc_total(_values, _valuesSize);
  _mean = _total/float(_valuesSize);
  return _mean;
}

//----------------------------------------------------------------------

float calc_rootMeanSquareError(int _values[], int _valuesSize, float _trueValue){
  float _totalSquareError = 0;
  float _meanSquareError = 0;
  float _rootMeanSquareError = 0;
  for(int i=0; i<_valuesSize; i++){
    float _error = _values[i]-_trueValue;
    _totalSquareError+=_error*_error;
  }
  _meanSquareError = _totalSquareError/float(_valuesSize);
  _rootMeanSquareError = sqrt(_meanSquareError);
  return _rootMeanSquareError;
}

//----------------------------------------------------------------------

bool check_touch(float _rootMeanSquareError, float _errorThreshold){
  bool _isTouch = false;
  if (_rootMeanSquareError <= _errorThreshold){
    Serial.print("[touch!!] ");
    _isTouch = true;
  }else{
    Serial.print("[release] ");
  }
  return _isTouch;
}

//----------------------------------------------------------------------

void print_int(char* _c1, int _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}

//----------------------------------------------------------------------

void print_float(char* _c1, float _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}

//----------------------------------------------------------------------

void print_bool(char* _c1, bool _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}
//----------------------------------------------------------------------

void print_ints(char* _c1, int _x[], int _xSize, char* _c2){
  Serial.print(_c1);
  for(int i=0; i<_xSize-1; i++){
    print_int("", _x[i], " ");
  }
  print_int("", _x[_xSize-1], "");
  Serial.print(_c2);
}

自作可変抵抗器に接触している際に, その抵抗の値によってLEDを調光する

analog_in_touch_pwm-out_fn.ino
const int PinI = 0; //input
const int PinO = 3;
const int ValuesSize = 10;
const float ErrorThreshold = 5.0;
const float ValueMin = 50.0;
const float ValueMax = 900.0;
int Values[ValuesSize];
int Frame;

void setup() {
  pinMode(PinI, INPUT);
  pinMode(PinO, OUTPUT);
  Serial.begin(115200);
  for(int i=0; i<ValuesSize; i++){
    Values[i] = 0;
  }
  Frame = 0;
}

void loop() {
  Frame++;
  int val = analogRead(PinI);

  update_values(Values, sizeof(Values)/sizeof(int), val);

  float total = calc_total(Values, sizeof(Values)/sizeof(int));
  float mean = calc_mean(Values, sizeof(Values)/sizeof(int));
  float rootMeanSquareError = calc_rootMeanSquareError(Values, ValuesSize, mean);

  bool isTouch = check_touch(rootMeanSquareError, ErrorThreshold);

  int outputPWM = calc_outputPWM(isTouch, val, ValueMin, ValueMax);
  analogWrite(PinO, outputPWM);

  print_touch(isTouch);
  print_bool("", isTouch, " ");
  print_int("", outputPWM, " ");
  print_int("", val, " ");
  print_float("total=", total, " ");
  print_float("mean=", mean, " ");
  print_float("rootMeanSquareError=", rootMeanSquareError, " ");
  print_ints("values=[", Values, sizeof(Values)/sizeof(int), "] ");  
  Serial.println("");
}

//######################################################################
//######################################################################
//######################################################################

void update_values(int _values[], int _valuesSize, int _val){
  if(Frame < _valuesSize){
    _values[Frame] = _val;
  } else {
    for(int i=0; i<_valuesSize-1; i++){
      _values[i] = _values[i+1];
    }
    _values[_valuesSize-1] = _val;
  }
}

//----------------------------------------------------------------------

float calc_total(int _values[], int _valuesSize){
  float _total = 0;
  for(int i=0; i<_valuesSize; i++){
    _total+=_values[i];
  }
  return _total;
}

//----------------------------------------------------------------------

float calc_mean(int _values[], int _valuesSize){
  float _total = 0;
  float _mean = 0;
  _total = calc_total(_values, _valuesSize);
  _mean = _total/float(_valuesSize);
  return _mean;
}

//----------------------------------------------------------------------

float calc_rootMeanSquareError(int _values[], int _valuesSize, float _trueValue){
  float _totalSquareError = 0;
  float _meanSquareError = 0;
  float _rootMeanSquareError = 0;
  for(int i=0; i<_valuesSize; i++){
    float _error = _values[i]-_trueValue;
    _totalSquareError+=_error*_error;
  }
  _meanSquareError = _totalSquareError/float(_valuesSize);
  _rootMeanSquareError = sqrt(_meanSquareError);
  return _rootMeanSquareError;
}

//----------------------------------------------------------------------

bool check_touch(float _rootMeanSquareError, float _errorThreshold){
  bool _isTouch = false;
  if (_rootMeanSquareError <= _errorThreshold){
    _isTouch = true;
  }else{
  }
  return _isTouch;
}

//----------------------------------------------------------------------

float calc_outputPWM(bool _isTouch, int _val, float _valueMin, float _valueMax){
  int _outputPWM;
  if (_isTouch == true) {
    float adjustedValue = 1024.0*(_val - _valueMin)/(_valueMax - _valueMin);
    if(adjustedValue<=0){adjustedValue=1;}
    if(adjustedValue>1023){adjustedValue=1023;}
    _outputPWM = int(adjustedValue/4);
  }else{
    _outputPWM = 0;
  }
  return _outputPWM;
}

//----------------------------------------------------------------------

void print_touch(bool _isTouch){
  if (_isTouch == true){
    Serial.print("[touch!!] ");
  }else{
    Serial.print("[release] ");
  }
}

//----------------------------------------------------------------------

void print_int(char* _c1, int _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}

//----------------------------------------------------------------------

void print_float(char* _c1, float _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}

//----------------------------------------------------------------------

void print_bool(char* _c1, bool _x, char* _c2){
  Serial.print(_c1);
  Serial.print(_x);
  Serial.print(_c2);
}
//----------------------------------------------------------------------

void print_ints(char* _c1, int _x[], int _xSize, char* _c2){
  Serial.print(_c1);
  for(int i=0; i<_xSize-1; i++){
    print_int("", _x[i], " ");
  }
  print_int("", _x[_xSize-1], "");
  Serial.print(_c2);
}

動画

https://www.youtube.com/watch?v=TCviH7VKQeI

ref

手作り可変抵抗器 (工作です・2)
111.手作り抵抗器

Vectors in Arduino
配列を自由自在に作る
Arduino 日本語リファレンス 配列

Arduinoの基本プログラム(スケッチ)

Arduino 日本語リファレンス sizeof
Arduinoで配列を関数の引数として扱う

comments

  • arduinoで配列を使うのは少し癖がある
  • arduinoではvector(長さ可変なリスト)は作れない
  • 自作関数内で配列の長さを調べるのは面倒. なので, 引数で長さを送るのがbetter
  • sizeofでint配列の長さを求める際はsizeof(int)で割る必要がある(intが2byteなため)
  • > Arduinoで配列を関数の引数として扱う
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away