├── scheme.jpg ├── .gitattributes ├── libraries ├── TimerOne-r11 │ ├── examples │ │ ├── ReadReciver │ │ │ ├── .svn │ │ │ │ ├── dir-prop-base │ │ │ │ ├── all-wcprops │ │ │ │ ├── entries │ │ │ │ └── text-base │ │ │ │ │ └── ReadReciver.pde.svn-base │ │ │ └── ReadReciver.pde │ │ └── ISRBlink │ │ │ └── ISRBlink.pde │ ├── keywords.txt │ ├── TimerOne.h │ └── TimerOne.cpp ├── TM74HC595-Gyver │ ├── README.md │ ├── keywords.txt │ ├── TM74HC595Display.h │ ├── examples │ │ └── TM74HC595Display │ │ │ └── TM74HC595Display.ino │ └── TM74HC595Display.cpp └── NewPing │ ├── keywords.txt │ ├── examples │ ├── NewPingExample │ │ └── NewPingExample.pde │ ├── TimerExample │ │ └── TimerExample.pde │ ├── NewPingEventTimer │ │ └── NewPingEventTimer.pde │ └── NewPing15Sensors │ │ └── NewPing15Sensors.pde │ ├── NewPing.h │ └── NewPing.cpp ├── LICENSE ├── sonar_meter └── sonar_meter.ino └── README.md /scheme.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGyver/RangeMeter/HEAD/scheme.jpg -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /libraries/TimerOne-r11/examples/ReadReciver/.svn/dir-prop-base: -------------------------------------------------------------------------------- 1 | K 14 2 | bugtraq:number 3 | V 4 4 | true 5 | END 6 | -------------------------------------------------------------------------------- /libraries/TM74HC595-Gyver/README.md: -------------------------------------------------------------------------------- 1 | # TM74HC595-4dig-display 2 | 3 | 4-Bit LED Digital Tube Module Arduino library"# TM74HC595-4dig-display" -------------------------------------------------------------------------------- /libraries/TimerOne-r11/examples/ReadReciver/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 51 4 | /svn/!svn/ver/3/trunk/Release%20Quality/ReadReciver 5 | END 6 | ReadReciver.pde 7 | K 25 8 | svn:wc:ra_dav:version-url 9 | V 67 10 | /svn/!svn/ver/7/trunk/Release%20Quality/ReadReciver/ReadReciver.pde 11 | END 12 | -------------------------------------------------------------------------------- /libraries/TM74HC595-Gyver/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For TM74HC595-display 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | TM74HC595Display KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | clear KEYWORD2 16 | set KEYWORD2 17 | digit2 KEYWORD2 18 | digit4 KEYWORD2 19 | send KEYWORD2 20 | float_dot KEYWORD2 21 | int_dot KEYWORD2 -------------------------------------------------------------------------------- /libraries/TimerOne-r11/examples/ReadReciver/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 6 5 | https://lex-arduino-sketchbook.googlecode.com/svn/trunk/Release%20Quality/ReadReciver 6 | https://lex-arduino-sketchbook.googlecode.com/svn 7 | 8 | 9 | 10 | 2011-06-24T22:05:24.141546Z 11 | 3 12 | lex.v.talionis@gmail.com 13 | has-props 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | c9f85be5-ce43-0359-81d1-43f08a9217a6 28 | 29 | ReadReciver.pde 30 | file 31 | 7 32 | 33 | 34 | 35 | 2011-06-25T03:21:57.149370Z 36 | 7554a9104cd32bca8710cff214402bb2 37 | 2011-06-25T03:22:33.720706Z 38 | 7 39 | lex.v.talionis@gmail.com 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 3527 62 | 63 | -------------------------------------------------------------------------------- /libraries/NewPing/keywords.txt: -------------------------------------------------------------------------------- 1 | ################################### 2 | # Syntax Coloring Map For NewPing 3 | ################################### 4 | 5 | ################################### 6 | # Datatypes (KEYWORD1) 7 | ################################### 8 | 9 | NewPing KEYWORD1 10 | 11 | ################################### 12 | # Methods and Functions (KEYWORD2) 13 | ################################### 14 | 15 | ping KEYWORD2 16 | ping_in KEYWORD2 17 | ping_cm KEYWORD2 18 | ping_median KEYWORD2 19 | ping_timer KEYWORD2 20 | check_timer KEYWORD2 21 | timer_us KEYWORD2 22 | timer_ms KEYWORD2 23 | timer_stop KEYWORD2 24 | convert_in KEYWORD2 25 | convert_cm KEYWORD2 26 | 27 | ################################### 28 | # Constants (LITERAL1) 29 | ################################### 30 | 31 | -------------------------------------------------------------------------------- /libraries/TimerOne-r11/examples/ISRBlink/ISRBlink.pde: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void setup() 4 | { 5 | // Initialize the digital pin as an output. 6 | // Pin 13 has an LED connected on most Arduino boards 7 | pinMode(13, OUTPUT); 8 | 9 | Timer1.initialize(100000); // set a timer of length 100000 microseconds (or 0.1 sec - or 10Hz => the led will blink 5 times, 5 cycles of on-and-off, per second) 10 | Timer1.attachInterrupt( timerIsr ); // attach the service routine here 11 | } 12 | 13 | void loop() 14 | { 15 | // Main code loop 16 | // TODO: Put your regular (non-ISR) logic here 17 | } 18 | 19 | /// -------------------------- 20 | /// Custom ISR Timer Routine 21 | /// -------------------------- 22 | void timerIsr() 23 | { 24 | // Toggle LED 25 | digitalWrite( 13, digitalRead( 13 ) ^ 1 ); 26 | } -------------------------------------------------------------------------------- /libraries/TM74HC595-Gyver/TM74HC595Display.h: -------------------------------------------------------------------------------- 1 | /* 2 | TM74HC595Display.h - Library for use 4LED display with 2 TM74HC595. 3 | Created by Kostarev V., February 23, 2016. 4 | Updated by AlexGyver 06.02.2017 (added float_dot and int_dot functions) 5 | */ 6 | #ifndef TM74HC595Display_h 7 | #define TM74HC595Display_h 8 | 9 | class TM74HC595Display 10 | { 11 | public: 12 | TM74HC595Display(int SCLK, int RCLK, int DIO); 13 | void timerIsr(); 14 | void send(unsigned char X); 15 | void send(unsigned char X, unsigned char port); 16 | void digit4(int n, bool showZero); 17 | void digit4(int n); 18 | void digit4showZero(int n); 19 | void digit2(int n, int port); 20 | void set(unsigned char X, int port ); 21 | void clear(); 22 | 23 | void float_dot(float value, int pos); // вывод числа value с точкой СПРАВА по счёту pos 24 | void int_dot(int n, int pos); // вывод числа int с точкой СПРАВА по счёту pos 25 | 26 | private: 27 | int _SCLK; 28 | int _RCLK; 29 | int _DIO; 30 | int _DATA[4]; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /libraries/TimerOne-r11/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For TimerOne 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | TimerOne KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | initialize KEYWORD2 16 | start KEYWORD2 17 | stop KEYWORD2 18 | restart KEYWORD2 19 | resume KEYWORD2 20 | read KEYWORD2 21 | pwm KEYWORD2 22 | disablePwm KEYWORD2 23 | attachInterrupt KEYWORD2 24 | detachInterrupt KEYWORD2 25 | setPeriod KEYWORD2 26 | setPwmDuty KEYWORD2 27 | 28 | ####################################### 29 | # Constants (LITERAL1) 30 | ####################################### 31 | 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 AlexGyver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /libraries/NewPing/examples/NewPingExample/NewPingExample.pde: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // Example NewPing library sketch that does a ping about 20 times per second. 3 | // --------------------------------------------------------------------------- 4 | 5 | #include 6 | 7 | #define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor. 8 | #define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor. 9 | #define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. 10 | 11 | NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. 12 | 13 | void setup() { 14 | Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. 15 | } 16 | 17 | void loop() { 18 | delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. 19 | Serial.print("Ping: "); 20 | Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range) 21 | Serial.println("cm"); 22 | } -------------------------------------------------------------------------------- /libraries/NewPing/examples/TimerExample/TimerExample.pde: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // While the NewPing library's primary goal is to interface with ultrasonic sensors, interfacing with 3 | // the Timer2 interrupt was a result of creating an interrupt-based ping method. Since these Timer2 4 | // interrupt methods were built, the library may as well provide the functionality to use these methods 5 | // in your sketches. This shows how simple it is (no ultrasonic sensor required). Keep in mind that 6 | // these methods use Timer2, as does NewPing's ping_timer method for using ultrasonic sensors. You 7 | // can't use ping_timer at the same time you're using timer_ms or timer_us as all use the same timer. 8 | // --------------------------------------------------------------------------- 9 | 10 | #include 11 | 12 | #define LED_PIN 13 // Pin with LED attached. 13 | 14 | void setup() { 15 | pinMode(LED_PIN, OUTPUT); 16 | NewPing::timer_ms(500, toggleLED); // Create a Timer2 interrupt that calls toggleLED in your sketch once every 500 milliseconds. 17 | } 18 | 19 | void loop() { 20 | // Do anything here, the Timer2 interrupt will take care of the flashing LED without your intervention. 21 | } 22 | 23 | void toggleLED() { 24 | digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle the LED. 25 | } -------------------------------------------------------------------------------- /libraries/TM74HC595-Gyver/examples/TM74HC595Display/TM74HC595Display.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int SCLK = 7; 5 | int RCLK = 6; 6 | int DIO = 5; 7 | 8 | TM74HC595Display disp(SCLK, RCLK, DIO); 9 | unsigned char LED_0F[29]; 10 | 11 | void setup() { 12 | LED_0F[0] = 0xC0; //0 13 | LED_0F[1] = 0xF9; //1 14 | LED_0F[2] = 0xA4; //2 15 | LED_0F[3] = 0xB0; //3 16 | LED_0F[4] = 0x99; //4 17 | LED_0F[5] = 0x92; //5 18 | LED_0F[6] = 0x82; //6 19 | LED_0F[7] = 0xF8; //7 20 | LED_0F[8] = 0x80; //8 21 | LED_0F[9] = 0x90; //9 22 | LED_0F[10] = 0x88; //A 23 | LED_0F[11] = 0x83; //b 24 | LED_0F[12] = 0xC6; //C 25 | LED_0F[13] = 0xA1; //d 26 | LED_0F[14] = 0x86; //E 27 | LED_0F[15] = 0x8E; //F 28 | LED_0F[16] = 0xC2; //G 29 | LED_0F[17] = 0x89; //H 30 | LED_0F[18] = 0xF9; //I 31 | LED_0F[19] = 0xF1; //J 32 | LED_0F[20] = 0xC3; //L 33 | LED_0F[21] = 0xA9; //n 34 | LED_0F[22] = 0xC0; //O 35 | LED_0F[23] = 0x8C; //P 36 | LED_0F[24] = 0x98; //q 37 | LED_0F[25] = 0x92; //S 38 | LED_0F[26] = 0xC1; //U 39 | LED_0F[27] = 0x91; //Y 40 | LED_0F[28] = 0xFE; //hight - 41 | 42 | 43 | Timer1.initialize(1500); // set a timer of length 1500 44 | Timer1.attachInterrupt(timerIsr); // attach the service routine here 45 | 46 | } 47 | 48 | void loop() { 49 | 50 | disp.set(LED_0F[0], 0); //send digital "0" to 1st indicator 51 | delay(1000); 52 | disp.set(LED_0F[3], 1); //send digital "3" to 2nd indicator 53 | delay(1000); 54 | disp.set(LED_0F[10], 2); //send simbol "A" to 3rd indicators 55 | delay(1000); 56 | disp.set(LED_0F[11], 3); //send simbol "b" to 4rd indicators 57 | delay(1000); 58 | 59 | 60 | disp.clear(); //clear display 61 | 62 | 63 | for(int i = 0; i<=99; i++){ 64 | disp.digit2(i, 0); //send counter 0-99 in 1st and 2nd view ports 65 | delay(50); 66 | } 67 | 68 | disp.clear(); 69 | 70 | for(int i = 0; i<=99; i++){ 71 | disp.digit2(i, 1); //send counter 0-99 in 3rd and 4rd view ports 72 | delay(50); 73 | } 74 | 75 | disp.clear(); 76 | 77 | for(int i = 0; i<=100; i++){ 78 | disp.digit4showZero(i); //send counter 0-100 with zero 79 | delay(50); 80 | } 81 | disp.clear(); 82 | 83 | for(int i = 0; i<=9999; i++){ 84 | disp.digit4(i); //send counter 0-9999 hide zero 85 | delay(10); 86 | } 87 | disp.clear(); 88 | 89 | } 90 | 91 | 92 | void timerIsr() 93 | { 94 | disp.timerIsr(); 95 | } 96 | 97 | 98 | -------------------------------------------------------------------------------- /libraries/NewPing/examples/NewPingEventTimer/NewPingEventTimer.pde: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // This example shows how to use NewPing's ping_timer method which uses the Timer2 interrupt to get the 3 | // ping time. The advantage of using this method over the standard ping method is that it permits a more 4 | // event-driven sketch which allows you to appear to do two things at once. An example would be to ping 5 | // an ultrasonic sensor for a possible collision while at the same time navigating. This allows a 6 | // properly developed sketch to multitask. Be aware that because the ping_timer method uses Timer2, 7 | // other features or libraries that also use Timer2 would be effected. For example, the PWM function on 8 | // pins 3 & 11 on Arduino Uno (pins 9 and 11 on Arduino Mega) and the Tone library. Note, only the PWM 9 | // functionality of the pins is lost (as they use Timer2 to do PWM), the pins are still available to use. 10 | // NOTE: For Teensy/Leonardo (ATmega32U4) the library uses Timer4 instead of Timer2. 11 | // --------------------------------------------------------------------------- 12 | #include 13 | 14 | #define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on ping sensor. 15 | #define ECHO_PIN 11 // Arduino pin tied to echo pin on ping sensor. 16 | #define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. 17 | 18 | NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. 19 | 20 | unsigned int pingSpeed = 50; // How frequently are we going to send out a ping (in milliseconds). 50ms would be 20 times a second. 21 | unsigned long pingTimer; // Holds the next ping time. 22 | 23 | void setup() { 24 | Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. 25 | pingTimer = millis(); // Start now. 26 | } 27 | 28 | void loop() { 29 | // Notice how there's no delays in this sketch to allow you to do other processing in-line while doing distance pings. 30 | if (millis() >= pingTimer) { // pingSpeed milliseconds since last ping, do another ping. 31 | pingTimer += pingSpeed; // Set the next ping time. 32 | sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status. 33 | } 34 | // Do other stuff here, really. Think of it as multi-tasking. 35 | } 36 | 37 | void echoCheck() { // Timer2 interrupt calls this function every 24uS where you can check the ping status. 38 | // Don't do anything here! 39 | if (sonar.check_timer()) { // This is how you check to see if the ping was received. 40 | // Here's where you can add code. 41 | Serial.print("Ping: "); 42 | Serial.print(sonar.ping_result / US_ROUNDTRIP_CM); // Ping returned, uS result in ping_result, convert to cm with US_ROUNDTRIP_CM. 43 | Serial.println("cm"); 44 | } 45 | // Don't do anything here! 46 | } -------------------------------------------------------------------------------- /libraries/TimerOne-r11/TimerOne.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328 3 | * Original code by Jesse Tane for http://labs.ideo.com August 2008 4 | * Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support 5 | * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop 6 | * Modified June 2011 by Lex Talionis to add a function to read the timer 7 | * Modified Oct 2011 by Andrew Richards to avoid certain problems: 8 | * - Add (long) assignments and casts to TimerOne::read() to ensure calculations involving tmp, ICR1 and TCNT1 aren't truncated 9 | * - Ensure 16 bit registers accesses are atomic - run with interrupts disabled when accessing 10 | * - Remove global enable of interrupts (sei())- could be running within an interrupt routine) 11 | * - Disable interrupts whilst TCTN1 == 0. Datasheet vague on this, but experiment shows that overflow interrupt 12 | * flag gets set whilst TCNT1 == 0, resulting in a phantom interrupt. Could just set to 1, but gets inaccurate 13 | * at very short durations 14 | * - startBottom() added to start counter at 0 and handle all interrupt enabling. 15 | * - start() amended to enable interrupts 16 | * - restart() amended to point at startBottom() 17 | * Modiied 7:26 PM Sunday, October 09, 2011 by Lex Talionis 18 | * - renamed start() to resume() to reflect it's actual role 19 | * - renamed startBottom() to start(). This breaks some old code that expects start to continue counting where it left off 20 | * 21 | * This program is free software: you can redistribute it and/or modify 22 | * it under the terms of the GNU General Public License as published by 23 | * the Free Software Foundation, either version 3 of the License, or 24 | * (at your option) any later version. 25 | * 26 | * This program is distributed in the hope that it will be useful, 27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 | * GNU General Public License for more details. 30 | * 31 | * You should have received a copy of the GNU General Public License 32 | * along with this program. If not, see . 33 | * 34 | * See Google Code project http://code.google.com/p/arduino-timerone/ for latest 35 | */ 36 | #ifndef TIMERONE_h 37 | #define TIMERONE_h 38 | 39 | #include 40 | #include 41 | 42 | #define RESOLUTION 65536 // Timer1 is 16 bit 43 | 44 | class TimerOne 45 | { 46 | public: 47 | 48 | // properties 49 | unsigned int pwmPeriod; 50 | unsigned char clockSelectBits; 51 | char oldSREG; // To hold Status Register while ints disabled 52 | 53 | // methods 54 | void initialize(long microseconds=1000000); 55 | void start(); 56 | void stop(); 57 | void restart(); 58 | void resume(); 59 | unsigned long read(); 60 | void pwm(char pin, int duty, long microseconds=-1); 61 | void disablePwm(char pin); 62 | void attachInterrupt(void (*isr)(), long microseconds=-1); 63 | void detachInterrupt(); 64 | void setPeriod(long microseconds); 65 | void setPwmDuty(char pin, int duty); 66 | void (*isrCallback)(); 67 | }; 68 | 69 | extern TimerOne Timer1; 70 | #endif -------------------------------------------------------------------------------- /libraries/TimerOne-r11/examples/ReadReciver/ReadReciver.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Lex Talionis (Lex.V.Talionis at gmail) 3 | This program is free software: you can redistribute it 4 | and/or modify it under the terms of the GNU General Public 5 | License as published by the Free Software Foundation, 6 | either version 3 of the License, or (at your option) any 7 | later version. 8 | 9 | This uses pin change interrupts and timer 1 to mesure the 10 | time between the rise and fall of 3 channels of PPM 11 | (Though often called PWM, see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1253149521/all) 12 | on a typical RC car reciver. It could be extended to as 13 | many channels as you like. 14 | 15 | */ 16 | #include // http://www.arduino.cc/playground/Main/PinChangeInt 17 | #include 18 | #include // http://www.arduino.cc/playground/Code/Timer1 19 | 20 | #define NO_PORTB_PINCHANGES //PinChangeInt setup 21 | #define NO_PORTC_PINCHANGES //only port D pinchanges (see: http://www.arduino.cc/playground/Learning/Pins) 22 | #define PIN_COUNT 3 //number of channels attached to the reciver 23 | #define MAX_PIN_CHANGE_PINS PIN_COUNT 24 | 25 | #define RC_TURN 3 //arduino pins attached to the reciver 26 | #define RC_FWD 2 27 | #define RC_FIRE 4 28 | byte pin[] = {RC_FWD, RC_TURN, RC_FIRE}; //for maximum efficency thise pins should be attached 29 | unsigned int time[] = {0,0,0}; // to the reciver's channels in the order listed here 30 | 31 | byte state=0; 32 | byte burp=0; // a counter to see how many times the int has executed 33 | byte cmd=0; // a place to put our serial data 34 | byte i=0; // global counter for tracking what pin we are on 35 | 36 | void setup() { 37 | Serial.begin(115200); 38 | Serial.print("PinChangeInt ReciverReading test"); 39 | Serial.println(); //warm up the serial port 40 | 41 | Timer1.initialize(2200); //longest pulse in PPM is usally 2.1 milliseconds, 42 | //pick a period that gives you a little headroom. 43 | Timer1.stop(); //stop the counter 44 | Timer1.restart(); //set the clock to zero 45 | 46 | for (byte i=0; i<3; i++) 47 | { 48 | pinMode(pin[i], INPUT); //set the pin to input 49 | digitalWrite(pin[i], HIGH); //use the internal pullup resistor 50 | } 51 | PCintPort::attachInterrupt(pin[i], rise,RISING); // attach a PinChange Interrupt to our first pin 52 | } 53 | 54 | void loop() { 55 | 56 | cmd=Serial.read(); //while you got some time gimme a systems report 57 | if (cmd=='p') 58 | { 59 | Serial.print("time:\t"); 60 | for (byte i=0; i // http://www.arduino.cc/playground/Main/PinChangeInt 17 | #include 18 | #include // http://www.arduino.cc/playground/Code/Timer1 19 | 20 | #define NO_PORTB_PINCHANGES //PinChangeInt setup 21 | #define NO_PORTC_PINCHANGES //only port D pinchanges (see: http://www.arduino.cc/playground/Learning/Pins) 22 | #define PIN_COUNT 3 //number of channels attached to the reciver 23 | #define MAX_PIN_CHANGE_PINS PIN_COUNT 24 | 25 | #define RC_TURN 3 //arduino pins attached to the reciver 26 | #define RC_FWD 2 27 | #define RC_FIRE 4 28 | byte pin[] = {RC_FWD, RC_TURN, RC_FIRE}; //for maximum efficency thise pins should be attached 29 | unsigned int time[] = {0,0,0}; // to the reciver's channels in the order listed here 30 | 31 | byte state=0; 32 | byte burp=0; // a counter to see how many times the int has executed 33 | byte cmd=0; // a place to put our serial data 34 | byte i=0; // global counter for tracking what pin we are on 35 | 36 | void setup() { 37 | Serial.begin(115200); 38 | Serial.print("PinChangeInt ReciverReading test"); 39 | Serial.println(); //warm up the serial port 40 | 41 | Timer1.initialize(2200); //longest pulse in PPM is usally 2.1 milliseconds, 42 | //pick a period that gives you a little headroom. 43 | Timer1.stop(); //stop the counter 44 | Timer1.restart(); //set the clock to zero 45 | 46 | for (byte i=0; i<3; i++) 47 | { 48 | pinMode(pin[i], INPUT); //set the pin to input 49 | digitalWrite(pin[i], HIGH); //use the internal pullup resistor 50 | } 51 | PCintPort::attachInterrupt(pin[i], rise,RISING); // attach a PinChange Interrupt to our first pin 52 | } 53 | 54 | void loop() { 55 | 56 | cmd=Serial.read(); //while you got some time gimme a systems report 57 | if (cmd=='p') 58 | { 59 | Serial.print("time:\t"); 60 | for (byte i=0; i 26 | #include 27 | TM74HC595Display disp(SCLK, RCLK, DIO); 28 | unsigned char SYM[47]; 29 | 30 | // крутая библиотека сонара 31 | #include 32 | NewPing sonar(TRIG, ECHO, 400); 33 | 34 | float dist_3[3] = {0.0, 0.0, 0.0}; // массив для хранения трёх последних измерений 35 | float middle, dist, dist_filtered; 36 | float k; 37 | byte i, delta; 38 | unsigned long dispIsrTimer, sensTimer; 39 | 40 | void setup() { 41 | Serial.begin(9600); 42 | symbols(); // создать символы для отображения на дисплее 43 | 44 | // настройка пинов 45 | pinMode(sensVCC, OUTPUT); 46 | pinMode(dispGND, OUTPUT); 47 | pinMode(dispVCC, OUTPUT); 48 | pinMode(buttPIN, INPUT_PULLUP); 49 | pinMode(buttGND, OUTPUT); 50 | 51 | // подаём сигналы на пины 52 | digitalWrite(sensVCC, 1); 53 | digitalWrite(dispGND, 0); 54 | digitalWrite(dispVCC, 1); 55 | digitalWrite(buttGND, 0); 56 | } 57 | 58 | void loop() { 59 | if (millis() - sensTimer > 50) { // измерение и вывод каждые 50 мс 60 | // счётчик от 0 до 2 61 | // каждую итерацию таймера i последовательно принимает значения 0, 1, 2, и так по кругу 62 | if (i > 1) i = 0; 63 | else i++; 64 | 65 | dist_3[i] = (float)sonar.ping() / 57.5; // получить расстояние в текущую ячейку массива 66 | if (!digitalRead(buttPIN)) dist_3[i] += case_offset; // если включен переключатель стороны измерения, прибавить case_offset 67 | dist = middle_of_3(dist_3[0], dist_3[1], dist_3[2]); // фильтровать медианным фильтром из 3ёх последних измерений 68 | 69 | delta = abs(dist_filtered - dist); // расчёт изменения с предыдущим 70 | if (delta > 1) k = 0.7; // если большое - резкий коэффициент 71 | else k = 0.1; // если маленькое - плавный коэффициент 72 | 73 | dist_filtered = dist * k + dist_filtered * (1 - k); // фильтр "бегущее среднее" 74 | 75 | disp.clear(); // очистить дисплей 76 | disp.float_dot(dist_filtered, 1); // вывести 77 | sensTimer = millis(); // сбросить таймер 78 | } 79 | 80 | if (micros() - dispIsrTimer > 300) { // таймер динамической индикации (по-русски: КОСТЫЛЬ!) 81 | disp.timerIsr(); // "пнуть" дисплей 82 | dispIsrTimer = micros(); // сбросить таймер 83 | } 84 | } 85 | 86 | // медианный фильтр из 3ёх значений 87 | float middle_of_3(float a, float b, float c) { 88 | if ((a <= b) && (a <= c)) { 89 | middle = (b <= c) ? b : c; 90 | } 91 | else { 92 | if ((b <= a) && (b <= c)) { 93 | middle = (a <= c) ? a : c; 94 | } 95 | else { 96 | middle = (a <= b) ? a : b; 97 | } 98 | } 99 | return middle; 100 | } 101 | 102 | // символы для дисплея 103 | void symbols() { 104 | // обычные 105 | SYM[0] = 0xC0; //0 106 | SYM[1] = 0xF9; //1 107 | SYM[2] = 0xA4; //2 108 | SYM[3] = 0xB0; //3 109 | SYM[4] = 0x99; //4 110 | SYM[5] = 0x92; //5 111 | SYM[6] = 0x82; //6 112 | SYM[7] = 0xF8; //7 113 | SYM[8] = 0x80; //8 114 | SYM[9] = 0x90; //9 115 | 116 | // с точкой 117 | SYM[10] = 0b01000000; //0. 118 | SYM[11] = 0b01111001; //1. 119 | SYM[12] = 0b00100100; //2. 120 | SYM[13] = 0b00110000; //3. 121 | SYM[14] = 0b00011001; //4. 122 | SYM[15] = 0b00010010; //5. 123 | SYM[16] = 0b00000010; //6. 124 | SYM[17] = 0b01111000; //7. 125 | SYM[18] = 0b00000000; //8. 126 | SYM[19] = 0b00010000; //9. 127 | } 128 | -------------------------------------------------------------------------------- /libraries/NewPing/examples/NewPing15Sensors/NewPing15Sensors.pde: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust 3 | // the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the 4 | // "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor 5 | // is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results 6 | // are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project 7 | // would normally process the sensor results in this function (for example, decide if a robot needs to 8 | // turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs 9 | // to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other 10 | // processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind. 11 | // --------------------------------------------------------------------------- 12 | #include 13 | 14 | #define SONAR_NUM 15 // Number of sensors. 15 | #define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. 16 | #define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). 17 | 18 | unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor. 19 | unsigned int cm[SONAR_NUM]; // Where the ping distances are stored. 20 | uint8_t currentSensor = 0; // Keeps track of which sensor is active. 21 | 22 | NewPing sonar[SONAR_NUM] = { // Sensor object array. 23 | NewPing(41, 42, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. 24 | NewPing(43, 44, MAX_DISTANCE), 25 | NewPing(45, 20, MAX_DISTANCE), 26 | NewPing(21, 22, MAX_DISTANCE), 27 | NewPing(23, 24, MAX_DISTANCE), 28 | NewPing(25, 26, MAX_DISTANCE), 29 | NewPing(27, 28, MAX_DISTANCE), 30 | NewPing(29, 30, MAX_DISTANCE), 31 | NewPing(31, 32, MAX_DISTANCE), 32 | NewPing(34, 33, MAX_DISTANCE), 33 | NewPing(35, 36, MAX_DISTANCE), 34 | NewPing(37, 38, MAX_DISTANCE), 35 | NewPing(39, 40, MAX_DISTANCE), 36 | NewPing(50, 51, MAX_DISTANCE), 37 | NewPing(52, 53, MAX_DISTANCE) 38 | }; 39 | 40 | void setup() { 41 | Serial.begin(115200); 42 | pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting. 43 | for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor. 44 | pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL; 45 | } 46 | 47 | void loop() { 48 | for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors. 49 | if (millis() >= pingTimer[i]) { // Is it this sensor's time to ping? 50 | pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Set next time this sensor will be pinged. 51 | if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results. 52 | sonar[currentSensor].timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). 53 | currentSensor = i; // Sensor being accessed. 54 | cm[currentSensor] = 0; // Make distance zero in case there's no ping echo for this sensor. 55 | sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). 56 | } 57 | } 58 | // Other code that *DOESN'T* analyze ping results can go here. 59 | } 60 | 61 | void echoCheck() { // If ping received, set the sensor distance to array. 62 | if (sonar[currentSensor].check_timer()) 63 | cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM; 64 | } 65 | 66 | void oneSensorCycle() { // Sensor ping cycle complete, do something with the results. 67 | // The following code would be replaced with your code that does something with the ping results. 68 | for (uint8_t i = 0; i < SONAR_NUM; i++) { 69 | Serial.print(i); 70 | Serial.print("="); 71 | Serial.print(cm[i]); 72 | Serial.print("cm "); 73 | } 74 | Serial.println(); 75 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![AlexGyver YouTube](http://alexgyver.ru/git_banner.jpg)](https://www.youtube.com/channel/UCgtAOyEQdAyjvm9ATCi_Aig?sub_confirmation=1) 2 | # Дальномер своими руками на Arduino 3 | * [Описание проекта](#chapter-0) 4 | * [Папки проекта](#chapter-1) 5 | * [Схемы подключения](#chapter-2) 6 | * [Материалы и компоненты](#chapter-3) 7 | * [Как скачать и прошить](#chapter-4) 8 | * [FAQ](#chapter-5) 9 | * [Полезная информация](#chapter-6) 10 | 11 | 12 | ## Описание проекта 13 | Ультразвуковой дальномер с дисплеем 14 | - Используется дисплей на драйвере TM74HC595 15 | - Показания с дальномера фильтруются, благодаря чему достигнута точность ~1 мм 16 | - Отдельный переключатель позволяет сдвигать начало отсчёта на противоположный конец корпуса 17 | - Подробности в видео: https://youtu.be/68Vz_fjo42I 18 | 19 | 20 | ## Папки 21 | **ВНИМАНИЕ! Если это твой первый опыт работы с Arduino, читай [инструкцию](#chapter-4)** 22 | - **libraries** - библиотеки 23 | - **sonar_meter** - прошивка для Arduino 24 | 25 | 26 | ## Схема 27 | ![СХЕМА](https://github.com/AlexGyver/RangeMeter/blob/master/scheme.jpg) 28 | 29 | 30 | ## Материалы и компоненты 31 | * Arduino NANO https://ali.ski/miRRf 32 | * Дисплей https://ali.ski/1Z5zs 33 | * Сонар https://ali.ski/ZV2iK9 34 | * Батарейный отсек https://ali.ski/skfXW9 35 | * Корпус https://ali.ski/PvBik 36 | * Выключатели https://ali.ski/qmicL 37 | * Монтажный провод https://ali.ski/lMvWlV 38 | * Всё для пайки http://alexgyver.ru/all-for-soldering/ 39 | 40 | ## Вам скорее всего пригодится 41 | * [Всё для пайки (паяльники и примочки)](http://alexgyver.ru/all-for-soldering/) 42 | * [Недорогие инструменты](http://alexgyver.ru/my_instruments/) 43 | * [Все существующие модули и сенсоры Arduino](http://alexgyver.ru/arduino_shop/) 44 | * [Электронные компоненты](http://alexgyver.ru/electronics/) 45 | * [Аккумуляторы и зарядные модули](http://alexgyver.ru/18650/) 46 | 47 | 48 | ## Как скачать и прошить 49 | * [Загрузка прошивки](http://alexgyver.ru/arduino-first/) - ультра подробная статья по началу работы с Ардуино, ознакомиться первым делом 50 | * Скачать архив с проектом 51 | > На главной странице проекта (где ты читаешь этот текст) вверху справа зелёная кнопка **Clone or download**, вот её жми, там будет **Download ZIP** 52 | * Установить библиотеки в 53 | `C:\Program Files (x86)\Arduino\libraries\` (Windows x64) 54 | `C:\Program Files\Arduino\libraries\` (Windows x86) 55 | * Подключить Ардуино к компьютеру 56 | * Запустить файл прошивки (который имеет расширение .ino) 57 | * Настроить IDE (COM порт, модель Arduino, как в статье выше) 58 | * Настроить что нужно по проекту 59 | * Нажать загрузить 60 | * Пользоваться 61 | 62 | ## Настройки в коде 63 | case_offset = 10.0; // длина корпуса в сантиметрах, для переноса начала отсчёта в заднюю часть корпуса 64 | 65 | 66 | 67 | ## FAQ 68 | ### Основные вопросы 69 | В: Как скачать с этого грёбаного сайта? 70 | О: На главной странице проекта (где ты читаешь этот текст) вверху справа зелёная кнопка **Clone or download**, вот её жми, там будет **Download ZIP** 71 | 72 | В: Скачался какой то файл .zip, куда его теперь? 73 | О: Это архив. Можно открыть стандартными средствами Windows, но думаю у всех на компьютере установлен WinRAR, архив нужно правой кнопкой и извлечь. 74 | 75 | В: Я совсем новичок! Что мне делать с Ардуиной, где взять все программы? 76 | О: Читай и смотри видос http://alexgyver.ru/arduino-first/ 77 | 78 | В: Компьютер никак не реагирует на подключение Ардуины! 79 | О: Возможно у тебя зарядный USB кабель, а нужен именно data-кабель, по которому можно данные передавать 80 | 81 | В: Ошибка! Скетч не компилируется! 82 | О: Путь к скетчу не должен содержать кириллицу. Положи его в корень диска. 83 | 84 | В: Сколько стоит? 85 | О: Ничего не продаю. 86 | 87 | ### Вопросы по этому проекту 88 | 89 | 90 | ## Полезная информация 91 | * [Мой сайт](http://alexgyver.ru/) 92 | * [Основной YouTube канал](https://www.youtube.com/channel/UCgtAOyEQdAyjvm9ATCi_Aig?sub_confirmation=1) 93 | * [YouTube канал про Arduino](https://www.youtube.com/channel/UC4axiS76D784-ofoTdo5zOA?sub_confirmation=1) 94 | * [Мои видеоуроки по пайке](https://www.youtube.com/playlist?list=PLOT_HeyBraBuMIwfSYu7kCKXxQGsUKcqR) 95 | * [Мои видеоуроки по Arduino](http://alexgyver.ru/arduino_lessons/) -------------------------------------------------------------------------------- /libraries/TM74HC595-Gyver/TM74HC595Display.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | TM74HC595Display.cpp - Library 3 | Updated by AlexGyver 06.02.2017 (added float_dot and int_dot functions) 4 | */ 5 | 6 | #include "TM74HC595Display.h" 7 | #include 8 | 9 | unsigned char _LED_0F[39]; 10 | 11 | TM74HC595Display::TM74HC595Display(int SCLK, int RCLK, int DIO) 12 | { 13 | pinMode(SCLK, OUTPUT); 14 | pinMode(RCLK, OUTPUT); 15 | pinMode(DIO, OUTPUT); 16 | 17 | _SCLK = SCLK; 18 | _RCLK = RCLK; 19 | _DIO = DIO; 20 | 21 | _LED_0F[0] = 0xC0; //0 22 | _LED_0F[1] = 0xF9; //1 23 | _LED_0F[2] = 0xA4; //2 24 | _LED_0F[3] = 0xB0; //3 25 | _LED_0F[4] = 0x99; //4 26 | _LED_0F[5] = 0x92; //5 27 | _LED_0F[6] = 0x82; //6 28 | _LED_0F[7] = 0xF8; //7 29 | _LED_0F[8] = 0x80; //8 30 | _LED_0F[9] = 0x90; //9 31 | 32 | _LED_0F[10] = 0b01000000; //.0 33 | _LED_0F[11] = 0b01111001; //.1 34 | _LED_0F[12] = 0b00100100; //.2 35 | _LED_0F[13] = 0b00110000; //.3 36 | _LED_0F[14] = 0b00011001; //.4 37 | _LED_0F[15] = 0b00010010; //.5 38 | _LED_0F[16] = 0b00000010; //.6 39 | _LED_0F[17] = 0b01111000; //.7 40 | _LED_0F[18] = 0b00000000; //.8 41 | _LED_0F[19] = 0b00010000; //.9 42 | 43 | _LED_0F[20] = 0x88; //A 44 | _LED_0F[21] = 0x83; //b 45 | _LED_0F[22] = 0xC6; //C 46 | _LED_0F[23] = 0xA1; //d 47 | _LED_0F[24] = 0x86; //E 48 | _LED_0F[25] = 0x8E; //F 49 | _LED_0F[26] = 0xC2; //G 50 | _LED_0F[27] = 0x89; //H 51 | _LED_0F[28] = 0xF9; //I 52 | _LED_0F[29] = 0xF1; //J 53 | _LED_0F[30] = 0xC3; //L 54 | _LED_0F[31] = 0xA9; //n 55 | _LED_0F[32] = 0xC0; //O 56 | _LED_0F[33] = 0x8C; //P 57 | _LED_0F[34] = 0x98; //q 58 | _LED_0F[35] = 0x92; //S 59 | _LED_0F[36] = 0xC1; //U 60 | _LED_0F[37] = 0x91; //Y 61 | _LED_0F[38] = 0xFE; //hight - 62 | 63 | clear(); 64 | } 65 | 66 | void TM74HC595Display::timerIsr() 67 | { 68 | send(_DATA[0]); 69 | send(0b0001); 70 | digitalWrite(_RCLK, LOW); 71 | digitalWrite(_RCLK, HIGH); 72 | send(_DATA[1]); 73 | send(0b0010); 74 | digitalWrite(_RCLK, LOW); 75 | digitalWrite(_RCLK, HIGH); 76 | send(_DATA[2]); 77 | send(0b0100); 78 | digitalWrite(_RCLK, LOW); 79 | digitalWrite(_RCLK, HIGH); 80 | send(_DATA[3]); 81 | send(0b1000); 82 | digitalWrite(_RCLK, LOW); 83 | digitalWrite(_RCLK, HIGH); 84 | } 85 | 86 | 87 | void TM74HC595Display::send(unsigned char X) 88 | { 89 | 90 | for (int i = 8; i >= 1; i--) 91 | { 92 | if (X & 0x80) 93 | { 94 | digitalWrite(_DIO, HIGH); 95 | } 96 | else 97 | { 98 | digitalWrite(_DIO, LOW); 99 | } 100 | X <<= 1; 101 | digitalWrite(_SCLK, LOW); 102 | digitalWrite(_SCLK, HIGH); 103 | } 104 | } 105 | 106 | void TM74HC595Display::send(unsigned char X, unsigned char port) 107 | { 108 | send(X); 109 | send(port); 110 | digitalWrite(_RCLK, LOW); 111 | digitalWrite(_RCLK, HIGH); 112 | } 113 | 114 | void TM74HC595Display::digit4(int n, bool showZero) 115 | { 116 | int n1, n2, n3, n4; 117 | n1 = (int) n % 10; 118 | n2 = (int) ((n % 100)-n1)/10; 119 | n3 = (int) ((n % 1000) - n2 - n1) / 100; 120 | n4 = (int) ((n % 10000) - n3 - n2 - n1) / 1000; 121 | 122 | set(_LED_0F[n1], 0); 123 | if(showZero | n>9)set(_LED_0F[n2], 1); 124 | if(showZero | n>99)set(_LED_0F[n3], 2); 125 | if(showZero | n>999)set(_LED_0F[n4], 3); 126 | } 127 | 128 | void TM74HC595Display::digit4(int n) 129 | { 130 | digit4(n,false); 131 | } 132 | 133 | void TM74HC595Display::digit4showZero(int n) 134 | { 135 | digit4(n, true); 136 | } 137 | 138 | 139 | void TM74HC595Display::digit2(int n, int port) 140 | { 141 | int n1, n2; 142 | n1 = (int) n % 10; 143 | n2 = (int) ((n % 100)-n1)/10; 144 | 145 | set(_LED_0F[n1], port); 146 | set(_LED_0F[n2], port+1); 147 | 148 | } 149 | 150 | void TM74HC595Display::set(unsigned char X, int port ){ 151 | _DATA[port] = X; 152 | } 153 | 154 | void TM74HC595Display::clear(){ 155 | _DATA[0]= 0xFF; 156 | _DATA[1]= 0xFF; 157 | _DATA[2]= 0xFF; 158 | _DATA[3]= 0xFF; 159 | } 160 | 161 | void TM74HC595Display::int_dot(int n, int pos) { 162 | int n1, n2, n3, n4; 163 | n1 = (int) n % 10; 164 | n2 = (int) ((n % 100) - n1) / 10; 165 | n3 = (int) ((n % 1000) - n2 - n1) / 100; 166 | n4 = (int) ((n % 10000) - n3 - n2 - n1) / 1000; 167 | 168 | int dot1 = 0, dot2 = 0, dot3 = 0; 169 | switch (pos) { 170 | case 1: dot1 = 10; break; 171 | case 2: dot2 = 10; break; 172 | case 3: dot3 = 10; break; 173 | } 174 | 175 | set(_LED_0F[n1], 0); //вывод 176 | if (n > 9) set(_LED_0F[n2 + dot1], 1); //вывод 177 | if (n > 99) set(_LED_0F[n3 + dot2], 2); //вывод 178 | if (n > 999) set(_LED_0F[n4 + dot3], 3); //вывод 179 | } 180 | 181 | void TM74HC595Display::float_dot(float value, int pos) { 182 | int whole = floor(value); 183 | int fract = floor(((float)value - whole) * pow(10, pos)); 184 | 185 | byte w1, w2, w3, w4; 186 | w1 = (int) whole % 10; 187 | w2 = (int) ((whole % 100) - w1) / 10; 188 | w3 = (int) ((whole % 1000) - w2 - w1) / 100; 189 | w4 = (int) ((whole % 10000) - w3 - w2 - w1) / 1000; 190 | 191 | byte f1, f2, f3, f4; 192 | f1 = (int) fract % 10; 193 | f2 = (int) ((fract % 100) - f1) / 10; 194 | f3 = (int) ((fract % 1000) - f2 - f1) / 100; 195 | f4 = (int) ((fract % 10000) - f3 - f2 - f1) / 1000; 196 | 197 | byte n0, n1, n2, n3; 198 | switch (pos) { 199 | case 0: n0 = w1; n1 = w2; n2 = w3; n3 = w4; 200 | break; 201 | case 1: n0 = f1; n1 = w1 + 10; n2 = w2; n3 = w3; 202 | break; 203 | case 2: n0 = f1; n1 = f2; n2 = w1 + 10; n3 = w2; 204 | break; 205 | case 3: n0 = f1; n1 = f2; n2 = f3; n3 = w1 + 10; 206 | break; 207 | } 208 | 209 | set(_LED_0F[n0], 0); 210 | if (!(n3 == 0 && n2 == 0 && n1 == 0)) set(_LED_0F[n1], 1); 211 | if (!(n3 == 0 && n2 == 0)) set(_LED_0F[n2], 2); 212 | if (n3 != 0) set(_LED_0F[n3], 3); 213 | } -------------------------------------------------------------------------------- /libraries/TimerOne-r11/TimerOne.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328 3 | * Original code by Jesse Tane for http://labs.ideo.com August 2008 4 | * Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support 5 | * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop 6 | * Modified June 2011 by Lex Talionis to add a function to read the timer 7 | * Modified Oct 2011 by Andrew Richards to avoid certain problems: 8 | * - Add (long) assignments and casts to TimerOne::read() to ensure calculations involving tmp, ICR1 and TCNT1 aren't truncated 9 | * - Ensure 16 bit registers accesses are atomic - run with interrupts disabled when accessing 10 | * - Remove global enable of interrupts (sei())- could be running within an interrupt routine) 11 | * - Disable interrupts whilst TCTN1 == 0. Datasheet vague on this, but experiment shows that overflow interrupt 12 | * flag gets set whilst TCNT1 == 0, resulting in a phantom interrupt. Could just set to 1, but gets inaccurate 13 | * at very short durations 14 | * - startBottom() added to start counter at 0 and handle all interrupt enabling. 15 | * - start() amended to enable interrupts 16 | * - restart() amended to point at startBottom() 17 | * Modiied 7:26 PM Sunday, October 09, 2011 by Lex Talionis 18 | * - renamed start() to resume() to reflect it's actual role 19 | * - renamed startBottom() to start(). This breaks some old code that expects start to continue counting where it left off 20 | * 21 | * This program is free software: you can redistribute it and/or modify 22 | * it under the terms of the GNU General Public License as published by 23 | * the Free Software Foundation, either version 3 of the License, or 24 | * (at your option) any later version. 25 | * 26 | * This program is distributed in the hope that it will be useful, 27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 | * GNU General Public License for more details. 30 | * 31 | * You should have received a copy of the GNU General Public License 32 | * along with this program. If not, see . 33 | * 34 | * See Google Code project http://code.google.com/p/arduino-timerone/ for latest 35 | */ 36 | #ifndef TIMERONE_cpp 37 | #define TIMERONE_cpp 38 | 39 | #include "TimerOne.h" 40 | 41 | TimerOne Timer1; // preinstatiate 42 | 43 | ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt 44 | { 45 | Timer1.isrCallback(); 46 | } 47 | 48 | 49 | void TimerOne::initialize(long microseconds) 50 | { 51 | TCCR1A = 0; // clear control register A 52 | TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer 53 | setPeriod(microseconds); 54 | } 55 | 56 | 57 | void TimerOne::setPeriod(long microseconds) // AR modified for atomic access 58 | { 59 | 60 | long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2 61 | if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal 62 | else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8 63 | else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64 64 | else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256 65 | else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024 66 | else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum 67 | 68 | oldSREG = SREG; 69 | cli(); // Disable interrupts for 16 bit register access 70 | ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode 71 | SREG = oldSREG; 72 | 73 | TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); 74 | TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock 75 | } 76 | 77 | void TimerOne::setPwmDuty(char pin, int duty) 78 | { 79 | unsigned long dutyCycle = pwmPeriod; 80 | 81 | dutyCycle *= duty; 82 | dutyCycle >>= 10; 83 | 84 | oldSREG = SREG; 85 | cli(); 86 | if(pin == 1 || pin == 9) OCR1A = dutyCycle; 87 | else if(pin == 2 || pin == 10) OCR1B = dutyCycle; 88 | SREG = oldSREG; 89 | } 90 | 91 | void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024) 92 | { 93 | if(microseconds > 0) setPeriod(microseconds); 94 | if(pin == 1 || pin == 9) { 95 | DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin 96 | TCCR1A |= _BV(COM1A1); // activates the output pin 97 | } 98 | else if(pin == 2 || pin == 10) { 99 | DDRB |= _BV(PORTB2); 100 | TCCR1A |= _BV(COM1B1); 101 | } 102 | setPwmDuty(pin, duty); 103 | resume(); // Lex - make sure the clock is running. We don't want to restart the count, in case we are starting the second WGM 104 | // and the first one is in the middle of a cycle 105 | } 106 | 107 | void TimerOne::disablePwm(char pin) 108 | { 109 | if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1 110 | else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2 111 | } 112 | 113 | void TimerOne::attachInterrupt(void (*isr)(), long microseconds) 114 | { 115 | if(microseconds > 0) setPeriod(microseconds); 116 | isrCallback = isr; // register the user's callback with the real ISR 117 | TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit 118 | // might be running with interrupts disabled (eg inside an ISR), so don't touch the global state 119 | // sei(); 120 | resume(); 121 | } 122 | 123 | void TimerOne::detachInterrupt() 124 | { 125 | TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit 126 | // timer continues to count without calling the isr 127 | } 128 | 129 | void TimerOne::resume() // AR suggested 130 | { 131 | TCCR1B |= clockSelectBits; 132 | } 133 | 134 | void TimerOne::restart() // Depricated - Public interface to start at zero - Lex 10/9/2011 135 | { 136 | start(); 137 | } 138 | 139 | void TimerOne::start() // AR addition, renamed by Lex to reflect it's actual role 140 | { 141 | unsigned int tcnt1; 142 | 143 | TIMSK1 &= ~_BV(TOIE1); // AR added 144 | GTCCR |= _BV(PSRSYNC); // AR added - reset prescaler (NB: shared with all 16 bit timers); 145 | 146 | oldSREG = SREG; // AR - save status register 147 | cli(); // AR - Disable interrupts 148 | TCNT1 = 0; 149 | SREG = oldSREG; // AR - Restore status register 150 | resume(); 151 | do { // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt 152 | oldSREG = SREG; 153 | cli(); 154 | tcnt1 = TCNT1; 155 | SREG = oldSREG; 156 | } while (tcnt1==0); 157 | 158 | // TIFR1 = 0xff; // AR - Clear interrupt flags 159 | // TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit 160 | } 161 | 162 | void TimerOne::stop() 163 | { 164 | TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits 165 | } 166 | 167 | unsigned long TimerOne::read() //returns the value of the timer in microseconds 168 | { //rember! phase and freq correct mode counts up to then down again 169 | unsigned long tmp; // AR amended to hold more than 65536 (could be nearly double this) 170 | unsigned int tcnt1; // AR added 171 | 172 | oldSREG= SREG; 173 | cli(); 174 | tmp=TCNT1; 175 | SREG = oldSREG; 176 | 177 | char scale=0; 178 | switch (clockSelectBits) 179 | { 180 | case 1:// no prescalse 181 | scale=0; 182 | break; 183 | case 2:// x8 prescale 184 | scale=3; 185 | break; 186 | case 3:// x64 187 | scale=6; 188 | break; 189 | case 4:// x256 190 | scale=8; 191 | break; 192 | case 5:// x1024 193 | scale=10; 194 | break; 195 | } 196 | 197 | do { // Nothing -- max delay here is ~1023 cycles. AR modified 198 | oldSREG = SREG; 199 | cli(); 200 | tcnt1 = TCNT1; 201 | SREG = oldSREG; 202 | } while (tcnt1==tmp); //if the timer has not ticked yet 203 | 204 | //if we are counting down add the top value to how far we have counted down 205 | tmp = ( (tcnt1>tmp) ? (tmp) : (long)(ICR1-tcnt1)+(long)ICR1 ); // AR amended to add casts and reuse previous TCNT1 206 | return ((tmp*1000L)/(F_CPU /1000L))<= 100 135 | #include 136 | #else 137 | #include 138 | #include 139 | #endif 140 | 141 | #if defined (__AVR__) 142 | #include 143 | #include 144 | #endif 145 | 146 | // Shouldn't need to change these values unless you have a specific need to do so. 147 | #define MAX_SENSOR_DISTANCE 500 // Maximum sensor distance can be as high as 500cm, no reason to wait for ping longer than sound takes to travel this distance and back. Default=500 148 | #define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. Default=57 149 | #define US_ROUNDTRIP_IN 146 // Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total), uses integer to save compiled code space. Defalult=146 150 | #define ONE_PIN_ENABLED true // Set to "false" to disable one pin mode which saves around 14-26 bytes of binary size. Default=true 151 | #define ROUNDING_ENABLED false // Set to "true" to enable distance rounding which also adds 64 bytes to binary size. Default=false 152 | #define URM37_ENABLED false // Set to "true" to enable support for the URM37 sensor in PWM mode. Default=false 153 | #define TIMER_ENABLED true // Set to "false" to disable the timer ISR (if getting "__vector_7" compile errors set this to false). Default=true 154 | 155 | // Probably shouldn't change these values unless you really know what you're doing. 156 | #define NO_ECHO 0 // Value returned if there's no ping echo within the specified MAX_SENSOR_DISTANCE or max_cm_distance. Default=0 157 | #define MAX_SENSOR_DELAY 5800 // Maximum uS it takes for sensor to start the ping. Default=5800 158 | #define ECHO_TIMER_FREQ 24 // Frequency to check for a ping echo (every 24uS is about 0.4cm accuracy). Default=24 159 | #define PING_MEDIAN_DELAY 29000 // Microsecond delay between pings in the ping_median method. Default=29000 160 | #define PING_OVERHEAD 5 // Ping overhead in microseconds (uS). Default=5 161 | #define PING_TIMER_OVERHEAD 13 // Ping timer overhead in microseconds (uS). Default=13 162 | #if URM37_ENABLED == true 163 | #undef US_ROUNDTRIP_CM 164 | #undef US_ROUNDTRIP_IN 165 | #define US_ROUNDTRIP_CM 50 // Every 50uS PWM signal is low indicates 1cm distance. Default=50 166 | #define US_ROUNDTRIP_IN 127 // If 50uS is 1cm, 1 inch would be 127uS (50 x 2.54 = 127). Default=127 167 | #endif 168 | 169 | // Conversion from uS to distance (round result to nearest cm or inch). 170 | #define NewPingConvert(echoTime, conversionFactor) (max(((unsigned int)echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0))) 171 | 172 | // Detect non-AVR microcontrollers (Teensy 3.x, Arduino DUE, etc.) and don't use port registers or timer interrupts as required. 173 | #if (defined (__arm__) && defined (TEENSYDUINO)) 174 | #undef PING_OVERHEAD 175 | #define PING_OVERHEAD 1 176 | #undef PING_TIMER_OVERHEAD 177 | #define PING_TIMER_OVERHEAD 1 178 | #define DO_BITWISE true 179 | #elif !defined (__AVR__) 180 | #undef PING_OVERHEAD 181 | #define PING_OVERHEAD 1 182 | #undef PING_TIMER_OVERHEAD 183 | #define PING_TIMER_OVERHEAD 1 184 | #undef TIMER_ENABLED 185 | #define TIMER_ENABLED false 186 | #define DO_BITWISE false 187 | #else 188 | #define DO_BITWISE true 189 | #endif 190 | 191 | // Disable the timer interrupts when using ATmega128 and all ATtiny microcontrollers. 192 | #if defined (__AVR_ATmega128__) || defined (__AVR_ATtiny24__) || defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny84__) || defined (__AVR_ATtiny25__) || defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) || defined (__AVR_ATtiny261__) || defined (__AVR_ATtiny461__) || defined (__AVR_ATtiny861__) || defined (__AVR_ATtiny43U__) 193 | #undef TIMER_ENABLED 194 | #define TIMER_ENABLED false 195 | #endif 196 | 197 | // Define timers when using ATmega8, ATmega16, ATmega32 and ATmega8535 microcontrollers. 198 | #if defined (__AVR_ATmega8__) || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega8535__) 199 | #define OCR2A OCR2 200 | #define TIMSK2 TIMSK 201 | #define OCIE2A OCIE2 202 | #endif 203 | 204 | class NewPing { 205 | public: 206 | NewPing(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance = MAX_SENSOR_DISTANCE); 207 | unsigned int ping(unsigned int max_cm_distance = 0); 208 | unsigned long ping_cm(unsigned int max_cm_distance = 0); 209 | unsigned long ping_in(unsigned int max_cm_distance = 0); 210 | unsigned long ping_median(uint8_t it = 5, unsigned int max_cm_distance = 0); 211 | static unsigned int convert_cm(unsigned int echoTime); 212 | static unsigned int convert_in(unsigned int echoTime); 213 | #if TIMER_ENABLED == true 214 | void ping_timer(void (*userFunc)(void), unsigned int max_cm_distance = 0); 215 | boolean check_timer(); 216 | unsigned long ping_result; 217 | static void timer_us(unsigned int frequency, void (*userFunc)(void)); 218 | static void timer_ms(unsigned long frequency, void (*userFunc)(void)); 219 | static void timer_stop(); 220 | #endif 221 | private: 222 | boolean ping_trigger(); 223 | void set_max_distance(unsigned int max_cm_distance); 224 | #if TIMER_ENABLED == true 225 | boolean ping_trigger_timer(unsigned int trigger_delay); 226 | boolean ping_wait_timer(); 227 | static void timer_setup(); 228 | static void timer_ms_cntdwn(); 229 | #endif 230 | #if DO_BITWISE == true 231 | uint8_t _triggerBit; 232 | uint8_t _echoBit; 233 | volatile uint8_t *_triggerOutput; 234 | volatile uint8_t *_echoInput; 235 | volatile uint8_t *_triggerMode; 236 | #else 237 | uint8_t _triggerPin; 238 | uint8_t _echoPin; 239 | #endif 240 | unsigned int _maxEchoTime; 241 | unsigned long _max_time; 242 | }; 243 | 244 | 245 | #endif 246 | -------------------------------------------------------------------------------- /libraries/NewPing/NewPing.cpp: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // Created by Tim Eckel - teckel@leethost.com 3 | // Copyright 2016 License: GNU GPL v3 http://www.gnu.org/licenses/gpl.html 4 | // 5 | // See "NewPing.h" for purpose, syntax, version history, links, and more. 6 | // --------------------------------------------------------------------------- 7 | 8 | #include "NewPing.h" 9 | 10 | 11 | // --------------------------------------------------------------------------- 12 | // NewPing constructor 13 | // --------------------------------------------------------------------------- 14 | 15 | NewPing::NewPing(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance) { 16 | #if DO_BITWISE == true 17 | _triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin. 18 | _echoBit = digitalPinToBitMask(echo_pin); // Get the port register bitmask for the echo pin. 19 | 20 | _triggerOutput = portOutputRegister(digitalPinToPort(trigger_pin)); // Get the output port register for the trigger pin. 21 | _echoInput = portInputRegister(digitalPinToPort(echo_pin)); // Get the input port register for the echo pin. 22 | 23 | _triggerMode = (uint8_t *) portModeRegister(digitalPinToPort(trigger_pin)); // Get the port mode register for the trigger pin. 24 | #else 25 | _triggerPin = trigger_pin; 26 | _echoPin = echo_pin; 27 | #endif 28 | 29 | set_max_distance(max_cm_distance); // Call function to set the max sensor distance. 30 | 31 | #if (defined (__arm__) && defined (TEENSYDUINO)) || DO_BITWISE != true 32 | pinMode(echo_pin, INPUT); // Set echo pin to input (on Teensy 3.x (ARM), pins default to disabled, at least one pinMode() is needed for GPIO mode). 33 | pinMode(trigger_pin, OUTPUT); // Set trigger pin to output (on Teensy 3.x (ARM), pins default to disabled, at least one pinMode() is needed for GPIO mode). 34 | #endif 35 | 36 | #if defined (ARDUINO_AVR_YUN) 37 | pinMode(echo_pin, INPUT); // Set echo pin to input for the Arduino Yun, not sure why it doesn't default this way. 38 | #endif 39 | 40 | #if ONE_PIN_ENABLED != true && DO_BITWISE == true 41 | *_triggerMode |= _triggerBit; // Set trigger pin to output. 42 | #endif 43 | } 44 | 45 | 46 | // --------------------------------------------------------------------------- 47 | // Standard ping methods 48 | // --------------------------------------------------------------------------- 49 | 50 | unsigned int NewPing::ping(unsigned int max_cm_distance) { 51 | if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance. 52 | 53 | if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function. 54 | 55 | #if URM37_ENABLED == true 56 | #if DO_BITWISE == true 57 | while (!(*_echoInput & _echoBit)) // Wait for the ping echo. 58 | #else 59 | while (!digitalRead(_echoPin)) // Wait for the ping echo. 60 | #endif 61 | if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. 62 | #else 63 | #if DO_BITWISE == true 64 | while (*_echoInput & _echoBit) // Wait for the ping echo. 65 | #else 66 | while (digitalRead(_echoPin)) // Wait for the ping echo. 67 | #endif 68 | if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. 69 | #endif 70 | 71 | return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead. 72 | } 73 | 74 | 75 | unsigned long NewPing::ping_cm(unsigned int max_cm_distance) { 76 | unsigned long echoTime = NewPing::ping(max_cm_distance); // Calls the ping method and returns with the ping echo distance in uS. 77 | #if ROUNDING_ENABLED == false 78 | return (echoTime / US_ROUNDTRIP_CM); // Call the ping method and returns the distance in centimeters (no rounding). 79 | #else 80 | return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters. 81 | #endif 82 | } 83 | 84 | 85 | unsigned long NewPing::ping_in(unsigned int max_cm_distance) { 86 | unsigned long echoTime = NewPing::ping(max_cm_distance); // Calls the ping method and returns with the ping echo distance in uS. 87 | #if ROUNDING_ENABLED == false 88 | return (echoTime / US_ROUNDTRIP_IN); // Call the ping method and returns the distance in inches (no rounding). 89 | #else 90 | return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches. 91 | #endif 92 | } 93 | 94 | 95 | unsigned long NewPing::ping_median(uint8_t it, unsigned int max_cm_distance) { 96 | unsigned int uS[it], last; 97 | uint8_t j, i = 0; 98 | unsigned long t; 99 | uS[0] = NO_ECHO; 100 | 101 | while (i < it) { 102 | t = micros(); // Start ping timestamp. 103 | last = ping(max_cm_distance); // Send ping. 104 | 105 | if (last != NO_ECHO) { // Ping in range, include as part of median. 106 | if (i > 0) { // Don't start sort till second ping. 107 | for (j = i; j > 0 && uS[j - 1] < last; j--) // Insertion sort loop. 108 | uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion. 109 | } else j = 0; // First ping is sort starting point. 110 | uS[j] = last; // Add last ping to array in sorted position. 111 | i++; // Move to next ping. 112 | } else it--; // Ping out of range, skip and don't include as part of median. 113 | 114 | if (i < it && micros() - t < PING_MEDIAN_DELAY) 115 | delay((PING_MEDIAN_DELAY + t - micros()) / 1000); // Millisecond delay between pings. 116 | 117 | } 118 | return (uS[it >> 1]); // Return the ping distance median. 119 | } 120 | 121 | 122 | // --------------------------------------------------------------------------- 123 | // Standard and timer interrupt ping method support functions (not called directly) 124 | // --------------------------------------------------------------------------- 125 | 126 | boolean NewPing::ping_trigger() { 127 | #if DO_BITWISE == true 128 | #if ONE_PIN_ENABLED == true 129 | *_triggerMode |= _triggerBit; // Set trigger pin to output. 130 | #endif 131 | 132 | *_triggerOutput &= ~_triggerBit; // Set the trigger pin low, should already be low, but this will make sure it is. 133 | delayMicroseconds(4); // Wait for pin to go low. 134 | *_triggerOutput |= _triggerBit; // Set trigger pin high, this tells the sensor to send out a ping. 135 | delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS. 136 | *_triggerOutput &= ~_triggerBit; // Set trigger pin back to low. 137 | 138 | #if ONE_PIN_ENABLED == true 139 | *_triggerMode &= ~_triggerBit; // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin). 140 | #endif 141 | 142 | #if URM37_ENABLED == true 143 | if (!(*_echoInput & _echoBit)) return false; // Previous ping hasn't finished, abort. 144 | _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) 145 | while (*_echoInput & _echoBit) // Wait for ping to start. 146 | if (micros() > _max_time) return false; // Took too long to start, abort. 147 | #else 148 | if (*_echoInput & _echoBit) return false; // Previous ping hasn't finished, abort. 149 | _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) 150 | while (!(*_echoInput & _echoBit)) // Wait for ping to start. 151 | if (micros() > _max_time) return false; // Took too long to start, abort. 152 | #endif 153 | #else 154 | #if ONE_PIN_ENABLED == true 155 | pinMode(_triggerPin, OUTPUT); // Set trigger pin to output. 156 | #endif 157 | 158 | digitalWrite(_triggerPin, LOW); // Set the trigger pin low, should already be low, but this will make sure it is. 159 | delayMicroseconds(4); // Wait for pin to go low. 160 | digitalWrite(_triggerPin, HIGH); // Set trigger pin high, this tells the sensor to send out a ping. 161 | delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS. 162 | digitalWrite(_triggerPin, LOW); // Set trigger pin back to low. 163 | 164 | #if ONE_PIN_ENABLED == true 165 | pinMode(_triggerPin, INPUT); // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin). 166 | #endif 167 | 168 | #if URM37_ENABLED == true 169 | if (!digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort. 170 | _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) 171 | while (digitalRead(_echoPin)) // Wait for ping to start. 172 | if (micros() > _max_time) return false; // Took too long to start, abort. 173 | #else 174 | if (digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort. 175 | _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) 176 | while (!digitalRead(_echoPin)) // Wait for ping to start. 177 | if (micros() > _max_time) return false; // Took too long to start, abort. 178 | #endif 179 | #endif 180 | 181 | _max_time = micros() + _maxEchoTime; // Ping started, set the time-out. 182 | return true; // Ping started successfully. 183 | } 184 | 185 | 186 | void NewPing::set_max_distance(unsigned int max_cm_distance) { 187 | #if ROUNDING_ENABLED == false 188 | _maxEchoTime = min(max_cm_distance + 1, (unsigned int) MAX_SENSOR_DISTANCE + 1) * US_ROUNDTRIP_CM; // Calculate the maximum distance in uS (no rounding). 189 | #else 190 | _maxEchoTime = min(max_cm_distance, (unsigned int) MAX_SENSOR_DISTANCE) * US_ROUNDTRIP_CM + (US_ROUNDTRIP_CM / 2); // Calculate the maximum distance in uS. 191 | #endif 192 | } 193 | 194 | 195 | #if TIMER_ENABLED == true && DO_BITWISE == true 196 | 197 | // --------------------------------------------------------------------------- 198 | // Timer interrupt ping methods (won't work with non-AVR, ATmega128 and all ATtiny microcontrollers) 199 | // --------------------------------------------------------------------------- 200 | 201 | void NewPing::ping_timer(void (*userFunc)(void), unsigned int max_cm_distance) { 202 | if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance. 203 | 204 | if (!ping_trigger()) return; // Trigger a ping, if it returns false, return without starting the echo timer. 205 | timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS. 206 | } 207 | 208 | 209 | boolean NewPing::check_timer() { 210 | if (micros() > _max_time) { // Outside the time-out limit. 211 | timer_stop(); // Disable timer interrupt 212 | return false; // Cancel ping timer. 213 | } 214 | 215 | #if URM37_ENABLED == false 216 | if (!(*_echoInput & _echoBit)) { // Ping echo received. 217 | #else 218 | if (*_echoInput & _echoBit) { // Ping echo received. 219 | #endif 220 | timer_stop(); // Disable timer interrupt 221 | ping_result = (micros() - (_max_time - _maxEchoTime) - PING_TIMER_OVERHEAD); // Calculate ping time including overhead. 222 | return true; // Return ping echo true. 223 | } 224 | 225 | return false; // Return false because there's no ping echo yet. 226 | } 227 | 228 | 229 | // --------------------------------------------------------------------------- 230 | // Timer2/Timer4 interrupt methods (can be used for non-ultrasonic needs) 231 | // --------------------------------------------------------------------------- 232 | 233 | // Variables used for timer functions 234 | void (*intFunc)(); 235 | void (*intFunc2)(); 236 | unsigned long _ms_cnt_reset; 237 | volatile unsigned long _ms_cnt; 238 | #if defined(__arm__) && defined(TEENSYDUINO) 239 | IntervalTimer itimer; 240 | #endif 241 | 242 | 243 | void NewPing::timer_us(unsigned int frequency, void (*userFunc)(void)) { 244 | intFunc = userFunc; // User's function to call when there's a timer event. 245 | timer_setup(); // Configure the timer interrupt. 246 | 247 | #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). 248 | OCR4C = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. 249 | TIMSK4 = (1<>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. 254 | TIMSK2 |= (1<