Note: Use the WIKI for latest informationen!

A perimeter wire (or buried wire fence, BWF) is like a 'virtual fence': it stopps the robot when it reaches its boundaries. A perimeter is not always necessary for all surroundings (a lawn sensor might be an alternative).

Principle idea
You will install a perimeter loop (a wire) in your garden through which a signal is sent and this signal is detected by the robot. So, you'll need: a sender (to transmit the on the wire) and a receiver (to detect the signal in the robot).

ardumower perimeter

How is the signal detected?

The signal is detected by one (or two) receiver coils. The closer the distance between coil and perimeter loop, the higher the signal. Also, something interesting happens when the robot crosses the perimeter loop: the signal changes its polarity, that means positive and negative voltages reverse each other. So, there are two basic principles to detect the perimeter loop. We have implemented both methods (perimeter v1 and v2) which are described below.

Sender for perimeter loop (perimeter v1)

You can use the sender of a commercial lawn robot (the sender shown here is compatible with Tianchen or Rotenbach robot mowers), or you build one yourself.

So, here's the sender:

An Arduino (e.g. Nano) generates a square signal that is used to switch the direction of a motor driver (L298N) at 7.8 Khz. Thereby, the motor driver will switch the output between VCC and GND. A resonator circuit amplifies the signal spikes as it's dimensioned so that its resonation frequency is the same as the switching frequency (7.8 Khz). That way, the motor drive only needs to be operated at 5V (instead of 12V). The power supply should be able to supply 2W (400mA at 5V). One part of the signal is captured by the Arduino (ADC) through a diode and a voltage divider. This allows to detect if the perimeter loop is connected or not. A 150 mA current will flow through in the perimeter wire (wire cross section 2-3 mm^2) - the wire should not be longer than 500m.

arduino perimeter sender

Because it's sometimes difficult to find a specific coil, here are possible combinations (coil / capacitor) you can use (all will have a resonation frequency of 7.8 Khz):
Combination 1: Coil: 160µH, Capacitor: 3,3µF/50V  (tested)
Combination 2: Coil 33mH, Capacitor: 12nF (not tested)

Power supply
It is recommended to use a voltage step-down converter (e.g. module using LM2596) to generate the 5V voltage. Before connecting, set the voltage of the converter to 5V. Warning : never connect more than 5V on the Arduino 5V pins, or you will damage the Arduino. Therefore, always measure the 5V voltage before connecting it to the Arduino 5V pin!


See Downloads

Functional test
1. After uploading the code and connecting the perimeter wire, the Arduino LED should be ON. Now remove the perimeter wire -  the Arduino LED should go OFF.
2. If that doesn't work: Using a voltmeter, measure once at Arduino pin D9 and once at motor driver output pin (OUT_1) against ground - both should have a DC voltage of 2.5 Volt.
3. If you have an oscilloscope, replace the perimeter wire by the oscilloscope. The measured signal look like below:

The output signal shows a higher amplitude (high spikes) as the input signal:

perimeter signal   ardumower perimeter sender schematics     arduino perimeter sender photo

(left: signal on the sender output, using resonator circuit, right: basic principle)

4. For a simple receiver test, you can simply connect the receiver coil to an oscilloscope. The measured oscilloscope signal should look like below:

This signal can be detected easily with a coil:
coilsignal     fft     ardumower perimeter spectrum plot

(left: coil signal at receiver coil, center: signal in frequency spectrum, superposed by motor noise, right: frequency spectrum via pfodApp)


Receiver for perimeter loop

The receiver uses 2 coils mounted left and right in the robot. The signal strenght of left and right coils is evaluated to be able to compare them.

1. Amplification of alternating signal using OPAMP
2. Optional: Bandpass-filtering to filter-out noise caused by motors etc.
3. Evaluation of signal strength of left and right coil

Advantage of this version: analog controlling works great.
Disadvantage: You cannot detect, where you are (inside/outside) if your missed the perimter crossing. Also, you cannot detect if you drive clockwise or anti-clockwise on the perimeter wire.

arduino perimeter receiver

A coil receives the sender's signal. A resonator circuit (LC) amplifies the received signal at resonation frequency (7.8 kHz). Then the signal is amplified using an LM386 (here: Arduino sound sensor using coil instead of microphone). A bandpass-filter  (digital filter, FFT) on the Arduino filters the desired frequency (7.8 Khz) and outputs a PWM signal (pulse width is proportional to signal strength). A lowpass-filter converts it to a DC voltage.
Note: Wiring between Nano and Mega has been simplified - see schematics for exact wiring.

We have tested the following combinations of amplifier und coils:
soundsensor    YwRobot Sensor   YwRobot circuit    coil 85mh

(most left: Amplifying signal using LM386 - Arduino Sound Sensor using coil instead microphone
left: Arduino Sound Sensor using LM386
right: Arduino Sound Sensor schematics
most right: 85 mH coils)

lm386 amplifier      lm386 modified     lm386 circuit      coil small

(left: LM386 amplifier (200x amplification)
center: LM386 circuit
right: 104 mH coil)
Important: When using this amplifier, capacitor C3 should be bypassed (will give a VCC/2 offset required for Arduino) and the coil will be connected to "IN" and "GND".

Arduino Code
See Downloads

Functional test
1. Make sure that the sender works correctly (see further above).
2. Increase the Arduino Sound Sensor potentiometer to maximum (rotate counter-clock-wise).
3. After uploading the code, move one coil towards the perimeter wire. The Arduino LED should start to blink. Now, hold both coils at same distance over the perimeter wire. The Arduino LED should be always ON now.
4. If that doesn't work, open the serial console (19200 baud), and verify the signal values.

Choice for coil
Induction math, only approximation:

L = 1nH x n² x ((D² / mm² ) / (l / mm))
l = coil length
D = coil diameter

Example: An inductance of 85 mH, and diamter of 10 mm, and length of 40 mm require about  5830 windings.

This inductance of 85 mH results in a capacity of 4.7 nF and a resonation frequency of 7963 kHz.

Because it's sometimes difficult to find a specific coil, here are possible combinations (coil / capacitor) you can use (all will have a resonation frequency of 7.8 Khz):
Combination 1: Coil: 85mH, Capacitor: 4.7nF  (tested)
Combination 2: Coil 104mH, Capacitor: 4nF (tested) 

Arrangement of coils
The coils are arranged at the bottom of the robot, about 90 degress to each other, both turned 45 degress.

ardumower spulen

Example (Ambrogio L50):

l50 coils    l50 parcours

Measurements of signal strength
To compare measurements, the signal strength has been determined at several distances. The signal strength (i.e. the calculated ADC value) is shown in the Android pfodApp. The distance (cm) is the length calculated from the perimeter loop until the coil (coil built-in the robot).

perimeter plot

How does the signal change when rotating the coil?

ardumower coil signal

Layout of the wire
It's important that the wire layout is round and does not have corners! Let's assume that the wire has a corner, and the robots drives exactly over the corner, it will not be able to detect the wire as both wire and coils are aligned (also see section before).
schleifen blind


video  Ambrogio-Arduimower: Perimeter stop test

video  Ambrogio-Ardumower: Perimter driving test

video  Ambrogio-Ardumower: Finding perimter and driving clock-wise

video  Rotenbach-Ardumower: Finding and driving perimter


Tracking of perimeter
The tracking of the perimeter wire is performed using a (software) digital PID controller. The controller's parameters (P,I,D) can be configured via the phone (pfodApp).

ardumower perimeter pid

You can find more information about PID controllers here.


Sender/receiver principle using polarity change ("Perimeter v2")

While crossing the perimeter loop, something interesting happens: signal changes polarity, that means negative and positive voltages reverse each other. By using this principle, crossing the perimeter wire will be detected. The robot knows its current perimeter state all the time (inside/ouside). As with perimeter v1, we will again use a motor driver to generate the signal and an operation amplifier to amplify the received signal.

1. Amplify perimeter coil signal using OPAMP
2. ADC sampling using Arduino
3. Signal filterung and detection using a digital filter (Matched filter algorithmn).
4. Evaluation of filter output

ardumower perimeter2            perimeter sampling

Signal shape, filter and simulation

applet matchedfilter


The motor driver is driven by 3.2 Khz (two pulse widths 4.8 Khz and 2.4 Khz). The circuit draws max. 20W (12V, 1.7A). We use a motor driver with integrated current limiting and thermal switch-off (e.g. MC33926).

sender circuit:

motor driver M1OUT1     o---------- perimeter loop (20-450 meters)--+

motor driver M1OUT2     o---------- perimeter loop -----------------+
motor driver Vin        o-- 12V
motor driver M1IN1      o-- Arduino Nano pinIN1
motor driver M1IN2      o-- Arduino Nano pinIN2
motor driver M1PWM_nD2  o-- Arduino Nano pinPWM
motor driver M1nSF      o-- Arduino Nano pinFault
motor driver M1FB       o-- Arduino Nano pinFeedback

motor driver EN         o-- Arduino Nano pinEnable
motor driver VDD        o-- Arduino +5V
motor driver M1D1       o-- GND (via Jumper)
motor driver SLEW       o-- VDD (via Jumper)


              |---------o-- GND
Potentiometer 100k -----o-- Arduino Nano pinPot
              |---------o-- Arduino +5V


ACS712-05 OUT ------o-- Arduino Nano pinChargeCurrent    
ACS712-05 A   ------o-- charging pin (+)
ACS712-05 B   ------o-- battery charger +24V
battery charger GND-o-- charging pin (-)

Using a current sensor (ACS712-05) it can be detected if the robot has reached the charging pins - this allows to switch off the perimeter during charging.

Using a potentiometer, the max. current can be set. In the Arduino software, first set IMAX pot to zero (0), and place robot in the center of the garden. Now, slowly increase IMAX pot, until 'sig' in the pfodApp plot ("Plot->Perimeter") increases (wait 10 seconds). Where 'sig' reaches its maximum, keep IMAX pot setting.

How the signal looks when perimeter wire loop is open:

perimeter2 sender open    


ardumower one center coil
We use a coil in upright position (centered at front in robot), connected to "pinPerimeterLeft". When using the LM386 amplifier, capacitor C3 should be bypassed (will give a VCC/2 offset required for Arduino) and the coil will be connected to "IN" and "GND".

receiver circuit:

                                     LM386 IN  o------- capacitor 4,7nF ----------- coil 100 mH
Arduino pinPerimeterLeft   o------o  LM386 OUT
                                     LM386 GND o----------------------------------- coil

The signal output of LM386 should look like this. For more details, see signal "pseudonoise4_pw" in the simulator applet.

perimeter2 receiver coil     perimeter2 receiver coil pwm

(left: signal, right: signal current limited using PWM)

ADC calibration

Run the ADC calibration once ("pfodApp->ADC Calibration"), so that the received signal is symmetric around zero.

Example plots (pfodApp)

:  coil signal
mag: filter result (negative: inside, positive: outside - strengh: distance to perimeter)
smag: filter output without sign, low-passed
in:  inside (1) oder outside (0)
cnt:  number of "inside-outside" transitions (counter)
on:  perimeter active (1) or inactive (0)

perimeterV2screenshot    perimeter2 plot 12v    ardumower perimeter2 test

perimeter2 plot 5v

video  Perimeter2-Demo

More information about the Matched Filter (Blog)



Go to