An ordinary analog protein settled in my house. She lived in a cage, lived for herself, spun her wheel. With different speeds. In the morning, usually more energetic, in the evening, tired, slow down. And all this time one question did not give me rest. And how fast is the squirrel in the wheel? I thought long and once ... I decided to make a wheel speed counter .
The photo is a prototype. Therefore, not everything is done neatly.
')
Sortsy, video and final measurement results under the cat.
Components.
Arduino Uno.
Screen LKM-1638.
Hall sensor (any suitable).
Expansion Board.
Bonus - Temperature and humidity sensor DHT11.
In principle, all I needed was a microcontroller on the board, an LKM-1638 screen, and a simple Hall sensor, but choosing all this, I also took a DHT11 humidity and temperature sensor to immediately pump the squirrel cage into a smart one! Ordered on dx.com.
He did everything himself, with his own hands.
I chose a ready-made Arduino Uno board, so as not to waste time on wiring, pickling, programmers, etc., and immediately begin to implement the plan. The screen took the LKM-1638, because it is bright, chotke , with large and clear numbers.
Along the way, the buttons on the display were useful for displaying statistical information.
Pressing the corresponding button displays:
Total mileage in kilometers.
Maximum speed of the circle.
Average daily mileage in kilometers.
Average speed per lap.
Uptime in days
Total number of revolutions of the circle
Current humidity.
Current temperature.
It turned out almost like in Formula 1. If there were several squirrels, you could arrange your blackjack tote.
Yes, and there, under the buttons on the display, there were LEDs in an amount equal to the number of buttons. With their help, it was decided to visualize the speed. Make a semblance of a digital tachometer. By the principle: the more diodes are lit, the closer the current speed is to the maximum, the smaller, the lower the minimum speed.
I gathered everything together, connected the wires and started writing the code. The library for the screen took ready here . For temperature and humidity sensor examples and library here . For the Hall sensor, I took everything from my head.
The logic of the speed counter is very simple. The Hall sensor is attached to the cell at the point closest to the wheel. There is a small but very strong neodymium magnet on the wheel, which I pulled out of the head of an old DVD drive. When the wheel rotates, with each integer turn of the magnet for a short time changes the magnetic field in the radius of measurement of the Hall sensor, changing in the latter state from 1 to 0. With the reverse arrangement of the sensor, the value would change from 0 to 1 (which is probably more correct ), but then the sensor would be worse kept on the cell. The difference in time between the two occurrences of a magnet in the area of the sensor is recognized for a whole circle. Further, knowing the inner circumference of the wheel, you can easily calculate the speed of the circle and bring it to the display, which I did. It should be noted here that this method of measurement has nuances :
It is considered only a complete revolution of the wheel. If the squirrel scrolled, for example, 0.9 turnover and jumped out of it, then this turnover is not counted at all. Or if she turned the wheel at 1.9, 2.9, 3.9 ... n.9 revolutions and so repeated many times during the device testing process, then there is a big error in the calculation of the total mileage, and the speed of these incomplete circles is not taken into account in calculating the average speed.
When the squirrel jumps out of the still rotating wheel in the direction opposite to the rotation, then in opposite direction, if the magnet just passed by the sensor at that time, the magnet passes the sensor again in the other direction, erroneously fixing the whole full turn of the wheel.
Measurement errors in these cases can be minimized by increasing the number of sensors, for example, to 4 and placing they are on opposite sides of the circle (in? / 2 radians or 90 degrees). Then you can take into account not only every quarter turn, which will definitely increase the accuracy of measurements, but also know the direction of the wheel rotation (i.e. where the protein runs - home or from home to the neighbor).
The current wheel speed displayed in real time on the display in kilometers / hour.
Next is the code itself. I note that the code is quite working, but the version is not final. By the time available, I will optimize it.
All code
/ * sketch for counting wheel speed and output values to 8 digital screen plus output current temperature and humidity release * /
/ ************** For digital DHT11 sensor *************** / #define dht_dpin A2
byte bGlobalErr;
byte dht_dat [5]; / ************** End for digital sensor DHT11 ********** /
/ ******* variables for the digital module ****************** /
// library for 8-segment digital module #include "TM1638.h" // Pins in the data pin 5 module, clock pin 4 and strobe pin 6 TM1638 module (5, 4, 6); #define Red TM1638_COLOR_RED #define Green TM1638_COLOR_GREEN #define Red_green TM1638_COLOR_GREEN + TM1638_COLOR_RED
/ ************ end of variables for module ***************
/ ********* variables for the Hall sensor ******************** /
// wheel circumference in meters (it is necessary to clarify) static float One_round = 0.91;
// determine the port for connecting the Hall sensor #define Hall_port 2 #define Max_led_light_speed 8 // interval of 10 seconds, if the larger wheel is recognized only as stopped, // if less, then it is considered that it is cool #define Wait_interval 10000 // interval after which the screen turns off #define Do_sleeping_interval 60000 // pause in sensor polls in normal mode #define Delay_in_work 5 // pause in sensor polls in sleep mode #define Delay_in_sleep 50
// wheel spin count unsigned long Round_counter = 0; // store the previous time here to calculate speed unsigned long Prev_time = 0; // store the previous time here for continuous monitoring unsigned long Prev_time_mon = 0; // here is the data to monitor pauses for zeroing and turning off the screen, etc. unsigned long time_span_mon = 0; // previous sensor value byte PrevValue = 1; // current wheel speed cm / c double Curr_speed = 0; // maximum wheel speed m / c double Max_speed = 0; // total mileage to be counted by pressing buttons double Total_run = 0; // speed of all circles here put to calculate the average double All_speeds = 0; // how many days have passed double Day_passed = 0; // variable to store the system state // 0- system in power saving and standby mode - the wheel has not been cool for a long time - the screen is off // 1- the wheel has just ceased to spin // 2- sprint wheel byte Sys_status = 0;
/ *************** end of variables for Hall ****************** /
// turn on the display, displaying 0 module.setDisplayToString ("0.", 0, 7); delay (1000);
}
void loop () {
if (Sys_status == 0) { // If sleep mode, then less often we poll sensor delay (Delay_in_sleep); } else { // if the operating mode is more often we poll the sensor delay (Delay_in_work); } / ************** start of the buttons ********************************* ******* /
// listen to buttons byte keys = module.getButtons ();
// if the button is pressed and the time is longer than the timeout, then turn on the display if (keys! = 0 && Sys_status == 0) { module.setupDisplay (true, 7); }
switch (keys) { // if leftmost button is pressed case 0b00000001:
// we blink the corresponding diode the others we extinguish module.setLEDs (0); module.setLED (Red, 0); module.clearDisplay (); // display the total mileage in kilometers Total_run = Round_counter * (double) One_round / 1000.00;
DoubleToDisp (Total_run); //module.setDisplayToDecNumber (Total_run, 1, false); delay (1000); // if the status is zero, then turn off the screen if (Sys_status == 0) { module.setupDisplay (false, 0); }
break;
// if the 2nd is pressed from the left case 0b00000010: // we blink the corresponding diode the others we extinguish module.setLEDs (0); module.setLED (Red, 1); module.clearDisplay (); // display the maximum speed DoubleToDisp (Max_speed); //module.setDisplayToDecNumber (Max_speed, 1, false); delay (1000); if (Sys_status == 0) { module.setupDisplay (false, 0); } break;
// if left 3 is pressed case 0b00000100: // we blink the corresponding diode the others we extinguish module.setLEDs (0); module.setLED (Red, 2); module.clearDisplay (); // how many days have we passed since we started Day_passed = millis () / 86400000.00; // if the whole day passed if (Day_passed> 1) {
// count the total mileage in kilometers Total_run = Round_counter * (double) One_round / 1000.00; // print the average daily run DoubleToDisp (Total_run / Day_passed); delay (1000); module.clearDisplay (); } else // if the whole day has not passed { module.setDisplayToString ("0", 0); } if (Sys_status == 0) { module.setupDisplay (false, 0); }
break;
// if 4th left is pressed case 0b00001000: // we blink the corresponding diode the others we extinguish module.setLEDs (0); module.setLED (Red, 3); module.clearDisplay (); // count and display the average speed per lap :) DoubleToDisp (All_speeds / Round_counter);
// if 5th left is pressed case 0b00010000: // we blink the corresponding diode the others we extinguish module.setLEDs (0); module.setLED (Red, 4); module.clearDisplay (); // how many days have we passed since we started Day_passed = millis () / 86400000.00; DoubleToDisp (Day_passed);
// if 6th left is pressed case 0b00100000: // we blink the corresponding diode the others we extinguish module.setLEDs (0); module.setLED (Red, 4); module.clearDisplay (); // display the number of circles module.setDisplayToDecNumber (Round_counter, 0, false);
// if 1st is pressed on the right case 0b10000000: // we blink the corresponding diode the others we extinguish module.setLEDs (0); module.setLED (Red, 7); module.clearDisplay (); // display current humidity ReadDHT (); // read the sensor // if there are no errors if (bGlobalErr == 0) { byte humidity = dht_dat [0]; module.setDisplayToDecNumber (humidity, 0, false); // DoubleToDisp (humidity); } delay (1000); if (Sys_status == 0) { module.setupDisplay (false, 0); } break;
// if 2nd is pressed on the right case 0b01000000: // we blink the corresponding diode the others we extinguish module.setLEDs (0); module.setLED (Red, 6); module.clearDisplay (); // display the current temperature ReadDHT (); // read the sensor // if there are no errors if (bGlobalErr == 0) { byte temperature = dht_dat [2]; module.setDisplayToDecNumber (temperature, 0, false); } delay (1000); if (Sys_status == 0) { module.setupDisplay (false, 0); } break; } // end of buttons / **************** end of buttons ******************************* ******* /
/ **************** here is the whole logic of reading info ************************** /
// read data - connect the hall sensor to the 3rd digital port int sensorValue = digitalRead (Hall_port);
// if the sensor state has changed if (sensorValue! = PrevValue) { PrevValue = sensorValue; // if the sensor gives 0 i.e. magnet here if (! sensorValue) { Sys_status = 2;
// turn on the display if the pause was longer than the interval slip and it has already turned off if (time_span_mon> Do_sleeping_interval) { module.setupDisplay (true, 7); } // add the counter Round_counter ++;
// current time we take in millisecs unsigned long time_now = millis ();
// count the difference in ms in time between the current and previous unsigned long time_span = time_now - Prev_time; // current write to previous Prev_time = time_now; // if the pause is less than 10 seconds, then we recognize that the wheel is cool if (time_span <Wait_interval) { if (Curr_speed> 10.00) { module.clearDisplay (); }
Curr_speed = One_round / time_span * 1000 * 3.6; // kilometers per hour we get speed All_speeds + = Curr_speed; // to calculate the average
// check for maximum if (Curr_speed> Max_speed) Max_speed = Curr_speed;
// display current speed DoubleToDisp (Curr_speed);
} // if the pause is more than 10 seconds, then we believe that the wheel stood before // and we do not take into account the previous time data, but we start // count the difference first else { Prev_time = time_now;
// debug //Serial.print ("time_span reset"); }
}
}
else // if the state of the sensor has not changed { // current time we take unsigned long time_now = millis ();
// time difference between the current and previous for post monitoring in ms; time_span_mon = time_now - Prev_time;
// if the interval between touches is more than 10 seconds - then we assume that the wheel // stopped and output 0 (interval needs to be clarified) 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); }
// if the pause is more than 60 seconds // if the interval between touches is more than 10 seconds - then we assume that the wheel // stopped and output 0 (interval needs to be clarified) if (time_span_mon> Do_sleeping_interval && Sys_status! = 0) { Sys_status = 0; module.setupDisplay (false, 0); }
}
} /// diode illumination depending on wheel speed // function void Led_speed_light (byte led_speed) { constrain (led_speed, 0, 7);
// If the number was less than 1, then the collective farm to stop the correct fraction if (num <1) { module.setDisplayDigit (0, 5, true); module.setDisplayDigit (str [0], 6, false); module.setDisplayDigit (str [1], 7, false); }
else // if more than 1 then output { for (int i = 0; i <length; i ++) { if (i == length - 3) { module.setDisplayDigit (str [i], i + 8-length, true); } else { module.setDisplayDigit (str [i], i + 8-length, false); } } }
Next, a little video to form a general idea of the resulting design.
Results, interesting facts and conclusions
From early morning the squirrel usually runs at an average speed of ~ 5-6 km / h (apparently, in search of food and a better share).
After a mandatory daytime sleep and taking high-calorie nuts, the squirrel speed drops to 3-4 km / h (I have already found food, I have done everything important in life).
When running near the vacuum cleaner, the speed EXTREMELY increases to 12-14 km / h! Although I met somewhere on foreign resources about the maximum speed of squirrels at 30 km / h, I can responsibly declare that all this is false. Well, or my squirrel does not belong to the breed of hounds (African Olympic).
The maximum speed of the circle is 18 km / h.
The average daily mileage of a squirrel, measured in two months, is ~ 15 kilometers.
These data can be used as a feasibility study of a project to create generating facilities - mini power plants for heating a squirrel house in the winter or lighting in the dark. Or for a school project on computer science.