リスホイールスピードカウンター

家で定期的にアナログリスを飼っていました。

彼女はケージに住んでいて、自分のために生きていて、車輪を回しました。 異なる速度で。 朝は、通常、より精力的に、夕方は、よりゆっくりと疲れます。 そして、この間ずっと一つの質問に悩まされました。 そして、リスはどの速度で車輪の中を走りますか?

私は長い間、一度考えました...

ホイールスピードカウンターを作ることにし



写真はプロトタイプです。 したがって、すべてがきちんと行われているわけではありません。



画像



猫の下での測定結果、ビデオ、最終結果。





コンポーネント。



  1. Arduino Uno。
  2. スクリーンLKM-1638。
  3. ホールセンサー(誰でもできます)。
  4. 拡張ボード。
  5. ボーナス-DHT11温度および湿度センサー。




原則として、必要なのは、ボード上のマイクロコントローラー、LKM-1638スクリーン、および単純なホールセンサーだけでしたが、これをすべて選択して、DHT11湿度および温度センサーを使用して、リスケージをすぐに「スマート」に排気しました。 dx.comで注文しました。



私は自分の手ですべてをしました。



配線、エッチング、プログラマなどに時間を無駄にしないように、既成のArduino Unoボードを選択しましたが、すぐに計画の実装を進めました。 LKM-1638が採用されたのは、画面が明るく鮮明で 、数字が大きく理解しやすいためです。



途中で、統計情報を表示するためにディスプレイ上のボタンが役立ちました。



対応するボタンを押すと表示されます:



  1. 総走行距離。
  2. 最大ラップ速度。
  3. キロで表した1日の平均走行距離。
  4. ラップあたりの平均速度。
  5. 日単位の稼働時間
  6. 円の総回転数
  7. 現在の湿度。
  8. 現在の温度。




フォーミュラ1のようになりました。 リスが複数いる場合は、 ブラックジャックトートを手配できます。



はい、ディスプレイのボタンの下にも、ボタンの数に等しい量のLEDがありました。 彼らの助けを借りて、速度を視覚化することにしました。 デジタルタコメーターのように見せてください。 原則によれば、より多くのダイオードが点灯するほど、現在の速度が最大に近くなり、より低くなり、最小に対応します。



すべてをまとめて、ワイヤを接続し、コードの記述を開始しました。

ここでスクリーンのライブラリを用意しました

温度および湿度センサーの例とライブラリはこちらです。

ホールセンサーについては、すべてを頭から取りました。



速度カウンターのロジックは非常に単純です。

ホールセンサーは、車輪に最も近いポイントでケージに取り付けられています。 ホイールには小さいが非常に強力なネオジム磁石があり、古いDVDドライブのヘッドから引き出しました。

ホイールが全回転ごとに回転すると、磁石はホールセンサーの測定半径の磁場を短時間変化させ、後者の状態で1から0に変化します。センサーが反対の位置にあった場合、値は0から1に変化します)、しかし、その後、センサーはセル上で悪くなります。

センサーカバレッジエリア内の2つの磁石の発生の時間差は、円全体として認識されます。 さらに、ホイールの内周がわかれば、円の速度を簡単に計算してディスプレイに表示できます。

ここで、この測定方法には微妙な違いがあることに注意してください。

  1. ホイールの完全な回転のみが考慮されます。 たとえば、タンパク質が0.9回転してスクロールした場合、この回転はまったく考慮されません。 または、彼女がホイールを1.9、2.9、3.9 ... n.9回転させてデバイスのテストプロセスで何度も繰り返した場合、総走行距離の計算で大きな誤差が生じ、平均速度の計算ではこれらの不完全な円の速度は考慮されません。
  2. リスがまだ回転しているホイールから回転と反対方向に飛び出すと、向流により、その時点で磁石がちょうどセンサーを通過した場合、磁石は再びセンサーを反対方向に通過し、誤ってホイールの全回転を記録します。


これらの場合の測定誤差は、センサーの数を4つに増やして配置することで最小限に抑えることができます。

それらを円の異なる側に(貫通?/ 2ラジアンまたは90度)。 その後、回転の4分の1ごとを考慮することができます。これにより、測定の精度が確実に向上するだけでなく、車輪の回転方向(つまり、リスが走る場所-自宅または自宅から隣人まで)を知ることができます。



現在のホイール速度は、キロメートル/時間単位でディスプレイにリアルタイムで表示されます。



次はコード自体です。 コードは非常に機能していますが、バージョンは最終的なものではありません。 時間がある場合でも、それを最適化します。



全コード
/ *

ホイール速度をカウントするためのスケッチ

値を8桁の画面に表示する

プラス出力電流温度と湿度

解放する

* /



/ ************** DHT11デジタルセンサーの場合***************** /

#define dht_dpin A2



バイトbGlobalErr;



バイトdht_dat [5];

/ ************** DHT11デジタルセンサーの終了********** /



/ *******デジタルモードの変数****************** /



// 8セグメントデジタルモジュールのライブラリ

#include "TM1638.h"

//データピン5、クロックピン4、ストローブピン6モジュールのピンを定義します

TM1638モジュール(5、4、6);

#define Red TM1638_COLOR_RED

#define Green TM1638_COLOR_GREEN

#define Red_green TM1638_COLOR_GREEN + TM1638_COLOR_RED



/ ************モジュールの変数の終わり**************** /



/ *********ホールセンサーの変数******************** /



//ホイール周長(メートル単位)(指定される)

static float One_round = 0.91;



//ホールセンサーを接続するためのポートを定義します

#define Hall_port 2

#define Max_led_light_speed 8

//ホイールが停止しているとのみ認識される場合、10秒間隔

//少ない場合は、クールだと見なされます

#define Wait_interval 10000

//画面がオフになるまでの間隔

#define Do_sleeping_interval 60000

//通常モードのセンサーポーリングで一時停止

#define Delay_in_work 5

//スリープポーリングで一時停止

#define Delay_in_sleep 50



//車輪速度カウンター

unsigned long Round_counter = 0;

//ここでは、速度の計算のために前回を保存します

unsigned long Prev_time = 0;

//ここに、常時監視のための前回の時間を保存します

unsigned long Prev_time_mon = 0;

//これは、ゼロ調整や画面のオフなどの一時停止を監視するためのデータです。

符号なしlong time_span_mon = 0;

//前のセンサー値

バイトPrevValue = 1;

//現在の車輪速度cm / c

double Curr_speed = 0;

//最大ホイール速度m / s

double Max_speed = 0;

//ボタンの押下を計算するための合計マイル数

double Total_run = 0;

//ここにすべての円の速度を入れて平均を計算します

double All_speeds = 0;

//経過日数

double Day_passed = 0;

//システム状態を保存する変数

// 0-省エネおよびスタンバイモードのシステム-ホイールが長時間冷えていません-画面がオフになっています

// 1-ホイールがkrutitstsaを停止しました

// 2- krutitstsaホイール

バイトSys_status = 0;



/ ***************ホールの変数の終わり****************** /



void setup(){



Serial.begin(9600);

InitDHT(); // DHT11センサーの初期化

Serial.println( "Run!");



//ディスプレイをオンにし、0を表示します

module.setDisplayToString( "0."、0、7);

遅延(1000);



}



void loop(){



if(Sys_status == 0)

{

//スリープモードの場合、センサーに問い合わせる頻度は少なくなります

遅延(Delay_in_sleep);

}

他に

{

//動作モードの場合、多くの場合、センサーに問い合わせます

遅延(Delay_in_work);

}

/ **************ボタンの始まり************************************* ******* /



//ボタンを聞きます

バイトキー= module.getButtons();



//ボタンが押され、時間がタイムアウトよりも長い場合、ディスプレイをオンにします

if(keys!= 0 && Sys_status == 0)

{

module.setupDisplay(true、7);

}



スイッチ(キー){

//左端が押された場合

ケース0b00000001:



//適切なダイオードで点滅し、残りを消します

module.setLEDs(0);

module.setLED(赤、0);

module.clearDisplay();

//総走行距離をキロメートルで表示します

Total_run = Round_counter *(double)One_round / 1000.00;



DoubleToDisp(Total_run);

//module.setDisplayToDecNumber(Total_run、1、false);

遅延(1000);

//ステータスがゼロの場合、画面をオフにします

if(Sys_status == 0)

{

module.setupDisplay(false、0);

}



休憩;



//左から2番目が押された場合

ケース0b00000010:

//適切なダイオードで点滅し、残りを消します

module.setLEDs(0);

module.setLED(赤、1);

module.clearDisplay();

//最大速度を表示します

DoubleToDisp(Max_speed);

//module.setDisplayToDecNumber(Max_speed、1、false);

遅延(1000);

if(Sys_status == 0)

{

module.setupDisplay(false、0);

}

休憩;



//左から3番目が押された場合

ケース0b00000100:

//適切なダイオードで点滅し、残りを消します

module.setLEDs(0);

module.setLED(赤、2);

module.clearDisplay();

//開始してから何日経ったか

Day_passed = millis()/ 86400000.00;

// 1日が経過した場合

if(Day_passed> 1)

{



//総走行距離をキロメートルで検討します

Total_run = Round_counter *(double)One_round / 1000.00;

// 1日の平均実行回数を出力します

DoubleToDisp(Total_run / Day_passed);

遅延(1000);

module.clearDisplay();

}

else // 1日がまだ過ぎていない場合

{

module.setDisplayToString( "0"、0);

}

if(Sys_status == 0)

{

module.setupDisplay(false、0);

}



休憩;



//左4番目が押された場合

ケース0b00001000:

//適切なダイオードで点滅し、残りを消します

module.setLEDs(0);

module.setLED(赤、3);

module.clearDisplay();

//ラップごとの平均速度をカウントして表示します:)

DoubleToDisp(All_speeds / Round_counter);



遅延(1000);

if(Sys_status == 0)

{

module.setupDisplay(false、0);

}

休憩;



// 5番目が左側で押された場合

ケース0b00010000:

//適切なダイオードで点滅し、残りを消します

module.setLEDs(0);

module.setLED(赤、4);

module.clearDisplay();

//開始してから何日経ったか

Day_passed = millis()/ 86400000.00;

DoubleToDisp(Day_passed);



遅延(1000);

if(Sys_status == 0)

{

module.setupDisplay(false、0);

}

休憩;



//左から6番目が押された場合

ケース0b00100000:

//適切なダイオードで点滅し、残りを消します

module.setLEDs(0);

module.setLED(赤、4);

module.clearDisplay();

//円の数を出力します

module.setDisplayToDecNumber(Round_counter、0、false);



遅延(1000);

if(Sys_status == 0)

{

module.setupDisplay(false、0);

}

休憩;



//右から1番目が押された場合

ケース0b10000000:

//適切なダイオードで点滅し、残りを消します

module.setLEDs(0);

module.setLED(赤、7);

module.clearDisplay();

//現在の湿度を表示します

ReadDHT(); //センサーを読み取ります

//エラーがない場合

if(bGlobalErr == 0)

{

バイト湿度= dht_dat [0];

module.setDisplayToDecNumber(湿度、0、false);

// DoubleToDisp(湿度);

}

遅延(1000);

if(Sys_status == 0)

{

module.setupDisplay(false、0);

}

休憩;



//右から2番目が押された場合

ケース0b01000000:

//適切なダイオードで点滅し、残りを消します

module.setLEDs(0);

module.setLED(赤、6);

module.clearDisplay();

//現在の温度を表示します

ReadDHT(); //センサーを読み取ります

//エラーがない場合

if(bGlobalErr == 0)

{

バイト温度= dht_dat [2];

module.setDisplayToDecNumber(温度、0、false);

}

遅延(1000);

if(Sys_status == 0)

{

module.setupDisplay(false、0);

}

休憩;

}

//ボタンの終わり

/ ****************ボタンの終わり*********************************** ******* /



/ ****************は、情報を読み取るためのロジック全体です****************************** /



//データを読み取ります-ホールセンサーを3つのデジタルポートに接続します

int sensorValue = digitalRead(Hall_port);



//センサーのステータスが変更された場合

if(sensorValue!= PrevValue)

{

PrevValue = sensorValue;

//センサーが0を示した場合、つまり 磁石はここにあります

if(!sensorValue)

{

Sys_status = 2;



//一時停止がスリップ間隔よりも長く、すでにオフになっている場合、ディスプレイをオンにします

if(time_span_mon> Do_sleeping_interval)

{

module.setupDisplay(true、7);

}

//カウンターを追加します

Round_counter ++;



//現在の時間をミリ秒単位で取得します

unsigned long time_now = millis();



//現在と以前の時間差をミリ秒で考慮します

unsigned long time_span = time_now-Prev_time;

//前への現在の書き込み

Prev_time = time_now;

//一時停止が10秒未満の場合、krutitstsaホイールが認識されます

if(time_span <Wait_interval)

{

if(Curr_speed> 10.00)

{

module.clearDisplay();

}



Curr_speed = One_round / time_span * 1000 * 3.6; //時速キロメートルで速度が得られます

All_speeds + = Curr_speed; //平均を計算する



//最大値を確認します

if(Curr_speed> Max_speed)

Max_speed = Curr_speed;



バイトled_speed = map(Curr_speed、0、Max_led_light_speed、0、7);

//氷のハイライトを呼び出します

Led_speed_light(led_speed);



//デバッグ

// Serial.print( "Round_counter =");

//Serial.println(Round_counter);

//Serial.print( "curr_speed(km / h)=");

//Serial.println(Curr_speed、4);



//現在の速度を表示します

DoubleToDisp(Curr_speed);



}

//一時停止が10秒を超える場合、ホイールが前にあったと仮定します

//前回のデータを考慮せずに開始

//最初に差を数えます

他に

{

Prev_time = time_now;



//デバッグ

//Serial.print( "time_span reset");

}



}



}



else //センサーの状態が変更されていない場合

{

//現在の時刻を取得します

unsigned long time_now = millis();



//考慮するモニタリング後の現在と前の時間差(ミリ秒単位)

time_span_mon = time_now-Prev_time;



//タッチの間隔が10秒を超える場合、ホイールは

//停止して0を出力(間隔を明確にする必要があります)

if(time_span_mon> Wait_interval && Sys_status!= 1)

{

Sys_status = 1;

Curr_speed = 0;

module.clearDisplay();

module.setDisplayDigit(0、7、true);

module.setLEDs(0);

}



//一時停止が60秒を超える場合、画面をオフにします

//タッチの間隔が10秒を超える場合、ホイールは

//停止して0を出力します(間隔を明確にする必要があります)

if(time_span_mon> Do_sleeping_interval && Sys_status!= 0)

{

Sys_status = 0;

module.setupDisplay(false、0);

}



}



}

///車輪速度に応じたダイオード照明

//関数

void Led_speed_light(バイトled_speed)

{

制約(led_speed、0、7);



スイッチ(led_speed){

ケース0:

module.setLEDs(0);

module.setLED(緑、0);

遅延(100);

module.setLED(0、0);

休憩;

ケース1:

module.setLEDs(0);

module.setLED(緑、0);

module.setLED(緑、1);

遅延(100);

module.setLED(0、1);

休憩;

ケース2:

module.setLEDs(0);

module.setLED(緑、0);

module.setLED(緑、1);

module.setLED(緑、2);

遅延(100);

for(int i = 2; i> 0; i-){

module.setLED(0、i);

遅延(50);

}

休憩;

ケース3:

module.setLEDs(0);

module.setLED(緑、0);

module.setLED(緑、1);

module.setLED(緑、2);

module.setLED(緑、3);

遅延(100);

for(int i = 3; i> 0; i-){

module.setLED(0、i);

遅延(50);

}

休憩;

ケース4:

module.setLEDs(0);

module.setLED(緑、0);

module.setLED(緑、1);

module.setLED(緑、2);

module.setLED(緑、3);

module.setLED(緑、4);

遅延(100);

for(int i = 4; i> 0; i-){

module.setLED(0、i);

遅延(50);

}

休憩;

ケース5:

module.setLEDs(0);

module.setLED(緑、0);

module.setLED(緑、1);

module.setLED(緑、2);

module.setLED(緑、3);

module.setLED(緑、4);

module.setLED(赤、5);

遅延(100);

for(int i = 5; i> 0; i-){

module.setLED(0、i);

遅延(50);

}

休憩;

ケース6:

module.setLEDs(0);

module.setLED(緑、0);

module.setLED(緑、1);

module.setLED(緑、2);

module.setLED(緑、3);

module.setLED(緑、4);

module.setLED(赤、5);

module.setLED(赤、6);

遅延(100);

for(int i = 6; i> 0; i-){

module.setLED(0、i);

遅延(50);

}

休憩;

ケース7:

module.setLEDs(0);

module.setLED(緑、0);

module.setLED(緑、1);

module.setLED(緑、2);

module.setLED(緑、3);

module.setLED(緑、4);

module.setLED(赤、5);

module.setLED(赤、6);

module.setLED(赤、7);

遅延(100);

for(int i = 7; i> 0; i-){

module.setLED(0、i);

遅延(50);

}



休憩;

}



}



// LKM1638の小数値を表示する関数(精度-2文字)

void DoubleToDisp(double num)

{

double mult_num =(double)num * 100.00;

long int_mult_num =(long)mult_num;

文字列string_mult_num =文字列(int_mult_num);

int length = string_mult_num.length();

char str [長さ+ 1];



string_mult_num.toCharArray(str、length + 1);



//数値が1未満の場合、集団農場ギャグが正しい割合を導き出します

if(num <1)

{

module.setDisplayDigit(0、5、true);

module.setDisplayDigit(str [0]、6、false);

module.setDisplayDigit(str [1]、7、false);

}



else //複数の場合は出力

{

for(int i = 0; i <length; i ++)

{

if(i == length-3){

module.setDisplayDigit(str [i]、i + 8長さ、true);

}

他に

{

module.setDisplayDigit(str [i]、i + 8長さ、false);

}

}

}



}



/ ****** DHT11の機能*** /



void InitDHT(){



pinMode(dht_dpin、OUTPUT);



digitalWrite(dht_dpin、HIGH);



}



void ReadDHT(){



bGlobalErr = 0;



バイトdht_in;



バイトi;



digitalWrite(dht_dpin、LOW);



遅延(20);



digitalWrite(dht_dpin、HIGH);



delayMicroseconds(40);



pinMode(dht_dpin、INPUT);



// delayMicroseconds(40);



dht_in = digitalRead(dht_dpin);



if(dht_in){



bGlobalErr = 1;



帰る



}



delayMicroseconds(80);



dht_in = digitalRead(dht_dpin);



if(!dht_in){



bGlobalErr = 2;



帰る



}



delayMicroseconds(80);



for(i = 0; i <5; i ++)



dht_dat [i] = read_dht_dat();



pinMode(dht_dpin、OUTPUT);



digitalWrite(dht_dpin、HIGH);



バイトdht_check_sum =



dht_dat [0] + dht_dat [1] + dht_dat [2] + dht_dat [3];



if(dht_dat [4]!= dht_check_sum)



{

bGlobalErr = 3;

}



};



バイトread_dht_dat(){



バイトi = 0;



バイト結果= 0;



for(i = 0; i <8; i ++){



while(digitalRead(dht_dpin)== LOW);



delayMicroseconds(30);



if(digitalRead(dht_dpin)== HIGH)



結果| =(1 <<(7-i));



while(digitalRead(dht_dpin)== HIGH);



}



結果を返す;



}



/ ****** DHT11の機能の終了**** /







次に、結果のデザインの一般的なアイデアを形成するいくつかのビデオ。







結果、興味深い事実、結論





  1. 早朝から、リスは通常平均速度5〜6 km / hで走ります(明らかに、食物とより良い分け合いを求めて)。
  2. 必須の1日の睡眠と高カロリーナッツを食べると、リスの速度は3〜4 km / hに低下します(私はすでに食べ物を見つけました。人生で重要なことはすべてやりました)。
  3. 近くの掃除機を使用すると、速度が突然 12〜14 km / hに上昇します。 私は、時速30 kmでのリスの最大速度について、外国のリソースでどこかで会いましたが、これはすべて嘘であると責任を持って宣言できます。 さて、または私のリスは猟犬の種に属していません(アフリカオリンピック)。
  4. 最大ラップ速度は18 km / hです。
  5. 2か月間測定されたリスの1日の平均走行距離は、約15キロメートルです。


これらのデータは、発電能力を作成するプロジェクトの実行可能性調査として使用できます。冬のリスの家を暖めたり、暗闇の中で照明するミニ発電所です。 または、学校のコンピューターサイエンスプロジェクトの場合。



All Articles