# B4R TutorialCar parking position detector

Hi everyone,

This project is a parking detector. It is not my idea and it exists already in Stavros Niarchos Foundation Parking already materialized but it has been a great pleasure analyzing it, understanding it and materializing myself (in a CAD oriented materialization at least). One may wonder why do they have used two detectors and not only one over the car. I suppose they have done this for debugging each parking position sensors because if you check regularly 2000 parking positions in a 4-stores parking then you have to employ a lot of personnel but with this materialization the parking position's sensors say to you "we are ill - come and cure us").

Here is the schematic:

The parking position sensors are located almost 2,40m over the floor and have a distance between them of about 1,80m in the x-axis of the parking position and are located in the middle of the y-axis in each related position. We have something like this:

There is a timer and triggers each sensor in regular time distances and if the space distance of a sensor to the closest object is less than 120cm (in my materialization) then it sets its state to true else it sets each state to false. When the car is out S1=False and S2=False. When it is just entering then S1=True and S2=False. When it is half in the parking position S1=True and S2=True. When the car is full in the parking then S1=False and S2=True. By getting the sequence of the states we understand if the car was parked or the car was unparked. If none of this has happened (the sequence of the states do not correspond to none of "has parked" or "has unparked" statuses) and it hasn't got in a known status within two minutes then the personnel is being notified (I suppose).

Here are the states of the sensors with related meanings and the result statuses:

When the car is unparked the Green LED lights indicating an empty position and when the car is parked the Red LED lights indicating a non empty position.

Possible Ideas of extra Materialization:
1. In conjunction with an arduino, a GSM shield and a MOSFET cirquit in your car you can cut off the power of the car and halt it if it exits your garage without your authorization (being stolen f.e.)
2. In conjunction with a relay light up a bulb (let's say for 4 minutes) when your car is parked in the Garage.
3. In conjunction with an ESP8266 report the result status ("Car was parked"/"Car was unparked") in an on-line database to know when your wife left the garage and got in the garage if you have suspicions that she is cheating on you (let's get the b*tch)

Here is the code:

B4X:
``````#Region Project Attributes
#AutoFlushLogs: True
#CheckArrayBounds: True
#StackBufferSize: 300
#End Region

Sub Process_Globals
'These global variables will be declared once when the application starts.
'Public variables can be accessed from all modules.
Public Serial1 As Serial

Public triggerpin1 As Pin
Public echopin1 As Pin
Public pulseduration1 As Double

Public triggerpin2 As Pin
Public echopin2 As Pin
Public pulseduration2 As Double

Dim pinRed As Pin
Dim pinGreen As Pin

Dim bCurrentState1 As Boolean
Dim bCurrentState2 As Boolean
Dim bPreviousState1 As Boolean = False
Dim bPreviousState2 As Boolean = False

Dim iPointer As Int
Dim States1Logged(4), States2Logged(4) As Boolean
Dim Parking1(4) As Boolean, UnParking1(4) As Boolean
Dim Parking2(4) As Boolean, UnParking2(4) As Boolean

Dim tm As Timer
Dim tm2 As Timer

End Sub

Private Sub AppStart
Serial1.Initialize(115200)
Log("AppStart")
iPointer = 0
tm.Initialize("tm_Tick", 500)
tm.Enabled = True
tm2.Initialize("tm2_Tick", 120000)
triggerpin1.Initialize(4, triggerpin1.MODE_OUTPUT)
triggerpin2.Initialize(6, triggerpin2.MODE_OUTPUT)
echopin1.Initialize(5, echopin1.MODE_INPUT)
echopin2.Initialize(7, echopin2.MODE_INPUT)

pinRed.Initialize(8, pinRed.MODE_OUTPUT)
pinGreen.Initialize(9, pinRed.MODE_OUTPUT)

'First sensor parking sequence
Parking1(0) = False: Parking1(1) = True: Parking1(2) = True: Parking1(3) = False
'Second sensor parking sequence
Parking2(0) = False: Parking2(1) = False: Parking2(2) = True: Parking2(3) = True

'First sensor unparking sequence
UnParking1(0) = False: UnParking1(1) = True: UnParking1(2) = True: UnParking1(3) = False
'Second sensor unparking sequence
UnParking2(0) = True: UnParking2(1) = True: UnParking2(2) = False: UnParking2(3) = False

End Sub

Private Sub tm_Tick
LogSensor1
LogSensor2
LogStateAndLightProperPIN
End Sub

Private Sub tm2_Tick
If LightUpProperLED = False Then
'Inform me that the sensors have a problem
tm.Enabled = False
End If
End Sub

Private Sub LogSensor1
Dim distance1 As Double
'Begin trigger
triggerpin1.DigitalWrite(True)

Log("Begin trigger 1")

'Trigger Off
triggerpin1.DigitalWrite(False)

'Distance proportional to pulse duration received on echo1 Pin
RunNative("pulseins1",echopin1.PinNumber)
'distance=(0.5*pulsduration)/29.1
Log("Pulse duration: ", pulseduration1)
distance1=(0.0340*0.5*pulseduration1)

bCurrentState1 = (distance1<120)
End Sub

#if C
void pulseins1 (B4R::Object* o) {
b4r_main::_pulseduration1 = pulseIn(o->toULong(),HIGH);
}
#End if

Private Sub LogSensor2
Dim distance2 As Double
'Begin trigger
triggerpin2.DigitalWrite(True)

Log("Begin trigger 2")

'Trigger Off
triggerpin2.DigitalWrite(False)

'Distance proportional to pulse duration received on echo2 Pin
RunNative("pulseins2",echopin2.PinNumber)
'distance=(0.5*pulsduration)/29.2
Log("Pulse duration: ", pulseduration2)
distance2=(0.0340*0.5*pulseduration2)

bCurrentState2 = (distance2<120)
End Sub

#if C
void pulseins2 (B4R::Object* o) {
b4r_main::_pulseduration2 = pulseIn(o->toULong(),HIGH);
}
#End if

Sub LogStateAndLightProperPIN
'If the states have not changed do not log anything
If bPreviousState1 = bCurrentState1 And bPreviousState2 = bCurrentState2 Then Return
States1Logged(iPointer) = bCurrentState1
States2Logged(iPointer) = bCurrentState2
bPreviousState1 = bCurrentState1
bPreviousState2 = bCurrentState2
iPointer = iPointer + 1
If iPointer = 4 Then iPointer = 0
LightUpProperLED
End Sub

Private Sub LightUpProperLED As Boolean
Dim iCheck1 As Int = 0
Dim iParking2 As Int = 0
Dim iUnparking2 As Int = 0
Dim bParked As Boolean = False
Dim bUnparked As Boolean = False
For ii = 0 To 3
'We do not need actually the Unparking1 as it is actually the same
If Parking1(ii) = States1Logged((iPointer + ii) Mod 4) Then
iCheck1 = iCheck1 + 1
End If
If Parking2(ii) = States2Logged((iPointer + ii) Mod 4) Then
iParking2 = iParking2 + 1
End If
If UnParking2(ii) = States2Logged((iPointer + ii) Mod 4) Then
iUnparking2 = iUnparking2 + 1
End If
Next

If iCheck1 = 4 Then
'It has pakred or unparked
If iParking2 = 4 Then bParked = True
If iUnparking2 = 4 Then bUnparked = True
Else
'Give the sensors a 2 minutes grace period and then inform me that they are malfunctioning
'The sub is triggered only on a different state logged so the timer will not be constantly enabled and restart
tm2.Enabled = True
End If

Select Case True
Case bParked = False And bUnparked = True
tm2.Enabled = False
pinGreen.DigitalWrite(True)
pinRed.DigitalWrite(False)
Case bParked = True And bUnparked = False
tm2.Enabled = False
pinGreen.DigitalWrite(False)
pinRed.DigitalWrite(True)
Case Else
'Give the sensors a 2 minutes grace period and then inform me that they are malfunctioning
'The sub is triggered only on a different state logged so the timer will not be constantly enabled and restart
tm2.Enabled = True
End Select

Return (bParked Or bUnparked)
End Sub``````

For measuring the distance of each sensor in the code I've got advantage of a code created already in the forum by inakigram who has done it himself (thanks a lot).

Have fun

#### Attachments

187.6 KB · Views: 227
Last edited:

#### JohnC

##### Expert
Longtime User
I did a project like this for an airport parking lot in New Jersey about 17 years ago.

I used only one pair of sonic sensors and used a PIC microcontroller back then to keep costs down because we had to install this for 40 parking spaces.

I was even able to find that old PIC-Basic source code!
B4X:
``````' Space Finder detection PIC code
'(c) 2002-2003 OMNISOFT

DEFINE    OSC 20

A    VAR BYTE
U    VAR WORD
D    VAR WORD       'measured distance of sound reflection
LD   VAR WORD       'last distance measured
C     VAR BYTE         'the number of distnace readings obtained
P     VAR WORD       'value of var pot resistor (used to set threshold if car detected or not)

TRISA = 0

CMCON = 7

High PORTB.3            'turn off RED led
High PORTB.4            'turn off Green led

C = 0
LD = 0

Scan:
Pot PORTA.0, 255, P     'get pot reading (this is a variable resistor used to set the "threshold" distance = car present if distance is less then this value)
P = P * 10

GoSub    Send40      'send a 40khz burst of ultrasonic signal

Low PORTB.7         'turn off receiving sensor so wont false trigger too soon
Pause 5            '5ms
High PORTB.7        'turn on receiving sensor

For D = 1 TO 2500   'start measuring how long it takes for sound reflection to be detected (D = ~ time)
A = PORTB.6     'see if reflected sound was detected
IF A > 0 Then    'if heard, then report and check distance (in value of D)
SerOut2 PORTB.2, 32, [DEC D, 10, 13]     'report to external serial terminal the measured distance
Goto Check      'no calc if car present or not based on measured distance and pot value
EndIF
Next D

Check:

If ABS(D - LD) < 100 then    'if difference between last detected distance and this detect is less then 50, then reading is stable
C = C + 1       'increment reading count

if C > 2 then   'if got 3 readings of roughly the same value, then

IF D < P Then 'if distance is less then pot value - there is a car present in spot
High PORTB.4    'turn off green leds
Low PORTB.3     'turn on red leds
SerOut2 PORTB.2, 32, ["CAR (P=",dec P,")",10,13]    'report that there is a car present

Else             'since reflection distance is greater then pot value = no car present in spot
Low PORTB.4    'turn on green leds
High PORTB.3   'turn off red leds

if D > 2500 then  'if distance overflow, then timeout (car windshield probably deflecting audio signal away from receiver)
SerOut2 PORTB.2, 32, ["TIMEOUT (P=",dec P,")",10,13]

else    'distance is greater then pot, so no car
SerOut2 PORTB.2, 32, ["NO-CAR (P=",dec P,")",10,13]
endif
EndIF
endif

else
C = 0
endif

LD = D        'last distance = current distance

Pause 500    'wait .5 seconds

GoTo scan      'retake another measurement

Send40:
'sends 40khz pulse for .5ms
'the NOP statements were inserted to produce a perfect 40khz signal at 50% duty cycle

For U = 1 TO 20
High PORTA.6
For A = 1 TO 5
@            NOP
Next A
@       NOP
@       NOP
@       NOP

Low PORTA.6
For A=1 TO 1
@                  NOP
Next A
@       NOP
@       NOP
Next U

Return``````

Last edited:

Replies
0
Views
356
Replies
1
Views
2K
Replies
7
Views
2K
Replies
3
Views
2K
B4R Question Pin 8 in Wemos D1
Replies
7
Views
3K