forked from arduino/Arduino
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path09_example_1.ino
114 lines (91 loc) · 3.73 KB
/
09_example_1.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <Servo.h>
// Arduino pin assignment
#define PIN_LED 9 // LED active-low
#define PIN_TRIG 12 // sonar sensor TRIGGER
#define PIN_ECHO 13 // sonar sensor ECHO
#define PIN_SERVO 10 // servi motor
// configurable parameters for sonar
#define SND_VEL 346.0 // sound velocity at 24 celsius degree (unit: m/sec)
#define INTERVAL 25 // sampling interval (unit: msec)
#define PULSE_DURATION 10 // ultra-sound Pulse Duration (unit: usec)
#define _DIST_MIN 180.0 // minimum distance to be measured (unit: mm)
#define _DIST_MAX 360.0 // maximum distance to be measured (unit: mm)
#define TIMEOUT ((INTERVAL / 2) * 1000.0) // maximum echo waiting time (unit: usec)
#define SCALE (0.001 * 0.5 * SND_VEL) // coefficent to convert duration to distance
#define _EMA_ALPHA 0.5 // EMA weight of new sample (range: 0 to 1)
// Setting EMA to 1 effectively disables EMA filter.
// Target Distance
#define _TARGET_LOW 180.0
#define _TARGET_HIGH 220.0
// duty duration for myservo.writeMicroseconds()
// NEEDS TUNING (servo by servo)
#define _DUTY_MIN 1000 // servo full clockwise position (0 degree)
#define _DUTY_NEU 1500 // servo neutral position (90 degree)
#define _DUTY_MAX 2000 // servo full counterclockwise position (180 degree)
long _DUTY_MAP;
// global variables
float dist_ema, dist_prev = _DIST_MAX; // unit: mm
unsigned long last_sampling_time; // unit: ms
Servo myservo;
void setup() {
// initialize GPIO pins
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_TRIG, OUTPUT); // sonar TRIGGER
pinMode(PIN_ECHO, INPUT); // sonar ECHO
digitalWrite(PIN_TRIG, LOW); // turn-off Sonar
myservo.attach(PIN_SERVO);
myservo.writeMicroseconds(_DUTY_NEU);
// initialize USS related variables
dist_prev = _DIST_MIN; // raw distance output from USS (unit: mm)
// initialize serial port
Serial.begin(57600);
}
void loop() {
float dist_raw;
// wait until next sampling time.
if (millis() < (last_sampling_time + INTERVAL))
return;
dist_raw = USS_measure(PIN_TRIG, PIN_ECHO); // read distance
if ((dist_raw == 0.0) || (dist_raw > _DIST_MAX)) {
dist_raw = dist_prev; // Cut higher than maximum
digitalWrite(PIN_LED, 1); // LED OFF
} else if (dist_raw < _DIST_MIN) {
dist_raw = dist_prev; // cut lower than minimum
digitalWrite(PIN_LED, 1); // LED OFF
} else { // In desired Range
dist_prev = dist_raw;
digitalWrite(PIN_LED, 0); // LED ON
}
// Apply ema filter here
dist_ema = _EMA_ALPHA*dist_raw+(_EMA_ALPHA-1)*dist_ema;;
// adjust servo position according to the USS read value
if(dist_ema<=_DIST_MIN) {
myservo.writeMicroseconds(1000);
}
if(dist_ema>_DIST_MIN && dist_ema<_DIST_MAX) {
_DUTY_MAP = map(dist_ema,180,360,_DUTY_MIN,_DUTY_MAX);
Serial.print(_DUTY_MAP);
myservo.writeMicroseconds(_DUTY_MAP);
}
if (dist_ema >= _DIST_MAX) {
myservo.writeMicroseconds(2000);
}
// output the distance to the serial port
Serial.print("Min:"); Serial.print(_DIST_MIN);
Serial.print(",Low:"); Serial.print(_TARGET_LOW);
Serial.print(",dist:"); Serial.print(dist_raw);
Serial.print(",Servo:"); Serial.print(myservo.read());
Serial.print(",High:"); Serial.print(_TARGET_HIGH);
Serial.print(",Max:"); Serial.print(_DIST_MAX);
Serial.println("");
// update last sampling time
last_sampling_time += INTERVAL;
}
// get a distance reading from USS. return value is in millimeter.
float USS_measure(int TRIG, int ECHO)
{
digitalWrite(TRIG, HIGH);
delayMicroseconds(PULSE_DURATION);
digitalWrite(TRIG, LOW);
return pulseIn(ECHO, HIGH, TIMEOUT) * SCALE; // unit: mm
}