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; //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);
}
動画
comments
arduinoで配列を使うのは少し癖がある
arduinoではvector(長さ可変なリスト)は作れない
自作関数内で配列の長さを調べるのは面倒. なので, 引数で長さを送るのがbetter
sizeofでint配列の長さを求める際はsizeof(int)で割る必要がある(intが2byteなため)