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

動画
code
下記の段階にわけて掲載する.
- analog-inputする
- inputの値を履歴のリストとして一定数保持し, その平均を求める
- inputの履歴リストの誤差二乗平均ルートをとる(自作可変抵抗器に接触しているかどうかを検出するため)
- 自作可変抵抗器に接触している(touch)かどうかの判定をする
- 自作可変抵抗器に接触している際に, その抵抗の値によって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; //inputconst 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; //inputconst 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; //inputconst 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; //inputconst 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);}
動画
comments
arduinoで配列を使うのは少し癖がある
arduinoではvector(長さ可変なリスト)は作れない
自作関数内で配列の長さを調べるのは面倒. なので, 引数で長さを送るのがbetter
sizeofでint配列の長さを求める際はsizeof(int)で割る必要がある(intが2byteなため)