鉛筆可変抵抗でLED調光

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

構成

IMG_2898.jpg

動画

git

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

code

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

analog-inputする

const int pinI = 0; //input

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

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

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

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の履歴リストの誤差二乗平均ルートをとる

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)かどうかの判定をする

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を調光する

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);
}

動画

ref

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

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

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

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

comments

  • arduinoで配列を使うのは少し癖がある
  • arduinoではvector(長さ可変なリスト)は作れない
  • 自作関数内で配列の長さを調べるのは面倒. なので, 引数で長さを送るのがbetter
  • sizeofでint配列の長さを求める際はsizeof(int)で割る必要がある(intが2byteなため)
  • > Arduinoで配列を関数の引数として扱う

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です