1////////////////////////////////////////////////////////////////////////////////
2// //
3// This software is supplied under the terms of a license agreement or //
4// nondisclosure agreement with Mitov Software and may not be copied //
5// or disclosed except in accordance with the terms of that agreement. //
6// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. //
7// //
8////////////////////////////////////////////////////////////////////////////////
9
10#ifndef _MITOV_ULTRASONIC_RANGE_h
11#define _MITOV_ULTRASONIC_RANGE_h
12
13#include <Mitov.h>
14
15namespace Mitov
16{
17 enum UltrasonicRangerUnits { rdTime, rdCm, rdInch };
18
19 class UltrasonicRanger : public Mitov::CommonSource, public Mitov::ClockingSupport
20 {
21 typedef Mitov::CommonSource inherited;
22
23 enum State { sStartUp, sStartDown, sListeningEdgeUp, sListeningEdgeDown, sEchoDetected, sPause };
24
25 public:
26 OpenWire::SinkPin EchoInputPin;
27 OpenWire::SourcePin PingOutputPin;
28 OpenWire::SourcePin TimeoutOutputPin;
29
30 public:
31 int Timeout = 1000;
32 int PingTime = 2;
33 int PauseTime = 100;
34 float TimeoutValue = -1;
35
36 UltrasonicRangerUnits Units : 2;
37
38 bool Enabled : 1;
39
40 protected:
41 State FState : 3;
42 bool FClocked : 1;
43
44 unsigned long FStartTime;
45 unsigned long FEchoStartTime;
46 unsigned long FEndTime;
47
48 protected:
49 void DoReceive( void *_Data )
50 {
51 if( ( FState != sListeningEdgeUp ) && ( FState != sListeningEdgeDown ) )
52 return;
53
54 bool AValue = *(bool *)_Data;
55 if( FState == sListeningEdgeDown )
56 {
57 if( AValue )
58 return;
59
60 FEndTime = micros();
61 FState = sEchoDetected;
62 }
63
64 else
65 {
66 if( ! AValue )
67 return;
68
69 FState = sListeningEdgeDown;
70 FEchoStartTime = micros();
71 }
72
73 }
74
75 protected:
76 virtual void SystemLoopBegin( unsigned long currentMicros ) override
77 {
78 if( !Enabled )
79 return;
80
81 switch ( FState )
82 {
83 case sPause:
84 {
85 if( ( currentMicros - FStartTime ) < ((unsigned long)PauseTime ) * 1000 )
86 return;
87
88 if( ClockInputPin.IsConnected() )
89 if( ! FClocked )
90 return;
91
92 FClocked = false;
93 }
94
95 case sStartUp:
96 {
97// Serial.println( "start" );
98 bool AValue = true;
99 PingOutputPin.Notify( &AValue );
100 FStartTime = currentMicros;
101 FState = sStartDown;
102 break;
103 }
104
105 case sStartDown:
106 {
107 if( ( currentMicros - FStartTime ) < PingTime )
108 return;
109
110 bool AValue = false;
111 PingOutputPin.Notify( &AValue );
112 FStartTime = currentMicros;
113 FState = sListeningEdgeUp;
114 break;
115 }
116
117 case sListeningEdgeUp:
118 case sListeningEdgeDown:
119 {
120 if( ( currentMicros - FStartTime ) < ((unsigned long)Timeout ) * 1000 )
121 return;
122
123 OutputPin.Notify( &TimeoutValue );
124 bool ABoolValue = true;
125 TimeoutOutputPin.Notify( &ABoolValue );
126 FState = sPause;
127 break;
128 }
129
130 case sEchoDetected:
131 {
132 unsigned long APeriod = FEndTime - FEchoStartTime;
133 float AValue;
134 switch( Units )
135 {
136 case rdTime:
137 AValue = APeriod;
138 break;
139
140 case rdCm:
141 AValue = ((float)APeriod) / 29 / 2; // / 58.2;
142 break;
143
144 case rdInch:
145 AValue = ((float)APeriod) / 74 / 2;
146 break;
147 }
148
149 OutputPin.Notify( &AValue );
150 bool ABoolValue = false;
151 TimeoutOutputPin.Notify( &ABoolValue );
152 FState = sPause;
153 break;
154 }
155 }
156 }
157
158 virtual void DoClockReceive( void *_Data ) override
159 {
160 FClocked = true;
161 }
162
163 public:
164 UltrasonicRanger() :
165 FState( sStartUp ),
166 Enabled( true ),
167 Units( rdCm ),
168 FClocked( false )
169 {
170 EchoInputPin.SetCallback( MAKE_CALLBACK( UltrasonicRanger::DoReceive ));
171 }
172
173 };
174}
175
176#endif