High speed detecting and identification for car charging

High speed detecting and identification for car charging
High speed detecting and identification
for car charging on electric roads
IULIANA STOICA AND VIKTOR NYBOM
MASTER´S THESIS
DEPARTMENT OF ELECTRICAL AND INFORMATION TECHNOLOGY |
FACULTY OF ENGINEERING | LTH | LUND UNIVERSITY
High speed detecting and identification for car
charging on electric roads
Iuliana Stoica And Viktor Nybom
Division of Industrial Electrical Engineering and Automation
Faculty of Engineering (IEA), Lund University
Department of Electrical and Information Technology (EIT)
Lund University
Supervisors:
Lars Lindgren (IEA)
Fredrik Tufvesson (EIT)
Examiners:
Mats Alaküla (IEA)
Mats Gustafsson (EIT)
March 2, 2017
c 2017
Printed in Sweden
Tryckeriet i E-huset, Lund
Abstract
The constantly increasing awareness of protecting the environment has put electrical roads in the spotlight as an alternative solution to fossil driven means of transport. Dan Zethraeus has developed an innovative idea for a prototype electrical
road which conductively supplies power to the cars whilst driving. The concept is
to place a line of short rail segments in the middle of the drive lanes where each
rail can have either grounded or positive polarity. The aim of this thesis work is
to find solutions for the timing, detection and identification of cars so that the
positive conductive rails are switched on correctly. The possible electromagnetic
interference from the road is to be investigated and the communication methods
adjusted accordingly. Finally, a demonstrator is built as a proof of concept for
illustrating and testing the presented solution.
This report starts by presenting possible theoretical solutions for the detection and
identification. Experiments that are set up to further analyse the most promising
methods, and also the construction of the electronics for the detection and identification modules of the demonstrator follow. Furthermore, a simulation setup
for analysis of the electromagnetic interference is tested. The complete solution
and the whole setup of the demonstrator is presented in the last part. Results
are presented for the performance of the demonstrator when tested on a real car
driving at 30 km/h.
i
Terminology
EMI - electromagnetic interference
RFID - radio frequency identification
RSU - radio station unit
TSS - Traffic Supervisions Systems
ii
Contents
1
.
.
.
.
1
1
1
3
3
2
Approach
2.1 Approach and dividing the problem . . . . . . . . . . . . . . . . . .
2.2 Finding information . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
5
3
Theoretical solutions
3.1 Solutions for car identification . . . . . .
3.1.1
RFID technology . . . . . . . . . .
3.2 Solutions for car positioning . . . . . . .
3.2.1
Identifying antenna signal strength . .
3.2.2
Doppler effect . . . . . . . . . . .
3.2.3
Inductive detection . . . . . . . . .
3.2.4
Conductive pickup signaling . . . . .
3.2.5
Short circuit detectors on rail . . . .
3.2.6
Hall effect sensors . . . . . . . . .
3.2.7
Sound and vibration . . . . . . . .
3.3 Different communication schemes . . . .
3.3.1
Scenario one . . . . . . . . . . . .
3.3.2
Scenario two . . . . . . . . . . . .
3.3.3
Scenario three . . . . . . . . . . .
7
7
4
Introduction
1.1 Background . . .
1.2 Related work . .
1.3 Aim of this thesis
1.4 Limitations . . .
. . .
. . .
work
. . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Analysis and testing
4.1 Car positioning . . . . . . . . . . . . . . . . . . . .
4.1.1
Pendulum as experimental setup . . . . . . . . .
4.1.2
Inductive system from the previous thesis work . .
4.1.3
Experimenting with different near field antennas . .
4.1.4
Simulating, testing and building . . . . . . . . .
4.1.5
Testing the detection on a road with a car . . . .
4.2 Car identification . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
iii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8
13
14
14
16
19
20
21
21
22
22
23
23
25
25
25
26
29
31
39
42
4.3
4.4
5
EMI . . . . . . . . . . . . .
4.3.1
EMI from electric car .
The Complete system . . .
4.4.1
Building . . . . . . .
4.4.2
Programming . . . .
4.4.3
Final test . . . . . .
4.4.4
Result . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
43
47
47
48
49
50
51
57
Discussion and future work
A Program Code
A.1 Receiver Arduino Due: The rail road computer
A.2 RSU . . . . . . . . . . . . . . . . . . . . . . .
A.2.1
StartServerUDP.java . . . . . . . . . . .
A.2.2
Monitor.java . . . . . . . . . . . . . . .
A.2.3
RoadConnectionUDP.java . . . . . . . . .
A.2.4
CarServerThread.java . . . . . . . . . . .
A.2.5
RecThread.java . . . . . . . . . . . . . .
A.2.6
RSU2Road.java . . . . . . . . . . . . . .
A.3 Car code . . . . . . . . . . . . . . . . . . . .
A.3.1
serial.c . . . . . . . . . . . . . . . . . .
A.3.2
testSync.cc . . . . . . . . . . . . . . . .
A.3.3
monitor.h . . . . . . . . . . . . . . . .
A.3.4
monitor.cc . . . . . . . . . . . . . . . .
A.3.5
connection.h . . . . . . . . . . . . . . .
A.3.6
connection.cc . . . . . . . . . . . . . .
iv
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
59
59
81
81
84
86
93
93
97
98
98
100
104
104
106
108
Chapter
1
Introduction
1.1 Background
There is a consensus that greenhouse gas emissions must be reduced in order to
keep the planet in the stable state which we are used to Oreskes [2004]. One way to
reduce emissions is by working towards using renewable energy. About a quarter
of the energy usage in Sweden comes from the transport sector and road traffic
stands for 94% of this energy consumption [Ene, 2013, p.32]. Most of this traffic
is still in need of fossil fuel and the swedish government has the goal of a ’fossilfree vehicle fleet’ as of year 2030. [fos, 2013, p.35]. The inventor Dan Zethraeus
is working on an idea for a prototype electric road, called ElOnRoad, with the
aim of lowering the need of batteries and the need to stop and recharge electric
vehicles. If the whole vehicle fleet can be driven by electricity then the problem
has been minimized to that of making fossil-free electricity in the power-grid. Dan
Zethraeus’ idea is to place a line of short rail segments in the middle of the traffic
lanes and have conductive sliding contacts mounted underneath the vehicles. The
rail segments are placed so that every second segment is connected to ground as a
negative polarity terminal and every other segment can be switched between the
grounded negative polarity and a positive polarity. In this way a car with three
sliding contacts and rectifiers can get constant DC power as shown in figure 1.1.
The rail segments are thought to be one meter in length and have a short isolated
area between each other. This master thesis aims to solve the timing, detection
and identification of cars so that the switching of the positive conductive rails is
done correctly. A demand on the system is that there should only be rails turned
on underneath a correctly equipped electric car.
1.2 Related work
There have been several master theses involved in the ElOnRoad project prior to
this one.
1
2
Introduction
Figure 1.1: Electric road giving constant DC power to a car with
three sliding contacts passing over it.
Philip Abrahamsson Completed his master thesis [Abrahamsson, 2015] on a
first overall design. Part of the focus was on simulating the magnetic properties and design of over-voltage protection using LT-spice, Matlab and
FEMM. Abrahamsson also did simulations on lightning strikes hitting the
road and what effects this would give. Abrahamsson’s results on magnetic
properties have been background knowledge in our work, although the geometry doesn’t fully align.
Marcus Andersson Completed his master thesis [Andersson, 2014] with focus
on the switching circuit in the rails. Andersson was also part of building
and fitting all the electronics in a full-scale proof of concept.
Henrik Fritzon Sund Completed his master thesis [Sund, 2014] with focus on
detecting a vehicle and creating a control system for activating the switching
of an individual rail. Sund’s work has been of great help to us and a great
part of our master thesis is a further development of his work and thoughts.
Filip Lillevars had not fully completed his master thesis before we wrote ours
but given support in first hand on our work.
Emil Landqvist & Theodor Hallerby Completed their master thesis [Landqvist
and Hallerby, 2015] with focus on developing a more comprehensive model
of the road. The main focus has been on the thermal aspects and analysing
overheating in different environments.
There are a couple of other electric road projects emerging in Sweden. The two
biggest are shortly mentioned here.
Elways [elw, 2015] Is a system that allows both heavy and light electric vehicles
to charge while driving. The system consist of a rail in the road, with sliding
slots. An arm on the vehicle can grab on to the rail and have a conductive
transmission of power.
Introduction
3
eHighway [sie, 2016] Is a system that lets trucks and high vehicles to charge
while driving. In this system there are power lines hanging over the road
and the trucks have pickups mounted on the roof. Quite similar to a the
electric train network.
Other work found to be related to this master thesis is the use of RFID in train
systems and car positioning described in section 3.2.1.
1.3 Aim of this thesis work
The aim of this thesis work is:
1. To come up with a theoretic solution to uniquely identify a correctly equipped
car, traveling at speeds between 20 km/h and 200 km/h and to determine
when to activate and deactivate the positive one meter rail segments in the
electrical road ElOnRoad. This should have enough accuracy so that a rail
is only active when it absolutely needs to be and no high potential parts
point out from under the passing car.
2. To identify and determine the possible electromagnetic interference from the
road and compensate the communication for this.
3. To build a demonstrator as proof of concept capable of identifying, positioning and correctly activating something at a speed of around 50 km/h.
1.4 Limitations
Some parts of the combined and full solution as well as some minor parts of
our work have been left out since it could hinder Dan Zethraeus from protecting
sensitive parts of his invention.
Identification methods using cameras or lasers are not considered in this report
since the environment around a road can get wet and dirty and components
mounted on a car are subject to high tear.
This master thesis aims at designing a proof of concept turning on LED lights
instead of a power giving rail. This thesis does not aim at finding or using
components or optimizing code for use in a real prototype with demands on
heat and durability.
It is in this report expected to be sufficient length between the ends of the car
and the sliding pickup contacts relative to the length of a rail to make sure
it is possible to have no active parts peek out from under the car.
In between standstill and 10 km/h are considered special conditions and will not
be the focus of this thesis work.
4
Introduction
Chapter
2
Approach
2.1 Approach and dividing the problem
The aim of this master thesis is to both identify a specific car and to accurately
determine a defined position of the car in order to switch the rail on and off with
the correct timing. As a first approach, the idea of using RFID (radio frequency
identification) and the inductive detection circuit built by Fritzon were further
examined, [Sund, 2014, p.5-17]. After gaining some understanding of how RFID
systems work (see section 3.1.1), it was decided to handle the theoretical solution
for the identification and precise positioning separately. Different possible ways
to determine the position of the car are presented in section 3.2. After this an
analysis of possible ways to combine the solutions with RFID are discussed in
section 3.3. The chosen solution is then tested and analyzed in chapter 4 where
finally a complete test of the proof of concept is carried out and described in
section 4.4.
2.2 Finding information
A lot of knowledge and know-how from courses attended at LTH have been of use to
us working with this thesis project. Most of the knowledge and information about
radio transmission and RFID are gathered from the RFID Handbook [Finkenzeller,
2010] and from various research articles found on the Internet. Our supervisor
Lars Lindgren has been a great help to most of our other needs of finding and
gaining information and knowledge about everything from EMI (electromagnetic
interference) to design and measurements.
5
6
Approach
Chapter
3
Theoretical solutions
The overall idea for the system, shown in Figure 3.1, is to use a two-way communication link between each car and a Radio Station Unit (RSU) marked as A.
Between each charging rail there is a possibility to place a radio detector or receiver, marked as C in the picture. This since the material in the isolation part
is not blocking radio waves and magnetic fields as the material in the conductive
rails does.
Figure 3.1: Sketch of the overall idea of the system.
3.1 Solutions for car identification
Methods presented in this chapter are based on RFID (radio frequency identification) technology which is more suitable for this application.
7
8
Theoretical solutions
3.1.1 RFID technology
A RFID system consists of two main parts, the interrogator, or the reader, and
the transponder which is located on the object to be identified [Finkenzeller, 2010,
p. 6]. The reader generates a radio signal and when a transponder is located
within the reader’s range and can pick up the signal it gets activated and starts
data exchange. The transponder consists of a coupling element and a microchip
where data is stored and modulation is done. A transponder can be passive if it
gets power supplied by the field generated by the reader or active if it has its own
power source.
Communicating data can be done in full-, half-duplex or sequential mode. In fullduplex mode both sides are sending and receiving data simultaneously, whereas in
half-duplex and sequential mode reader and transponder are taking turns on sending data. Transfer of energy from reader to transponder is continuous in duplex
mode but it occurs only in between the messages in sequential mode [Finkenzeller,
2010, p. 39]. All digital modulation techniques can be used to transmit data but
amplitude shift keying is the one most commonly used. There are a few coupling
methods,i.e ways of energy transfer between reader and transponder. Based on
reasonable distance ranges for this applications and availability of products on the
market this report will only review inductive and backscatter coupling [Finkenzeller, 2010, p. 22, 45].
A quick review of radio waves and the different kind of fields that can be found
around an antenna is given for a better understanding of the coupling methods.
The regions surrounding an antenna are usually divided into three zones: reactive
near-field, radiating near-field (Fresnel) and far-field (Fraunhofer) [Balanis, 2005,
p. 34]. The transition boundaries between these regions are gradual but there
are general approximations that work for most antennas. The transition from
reactive near field to radiating near field and far field is usually approximated by
the transition distances r1 and r2 [Balanis, 2005, p. 34]:
r1 = 0.62 ·
p
D3 /λ
r2 = 2D2 /λ,
where D is the largest dimension of the antenna and λ is the wavelength, see figure
3.2. Note that D must be much larger than the wavelength for these boundaries
to be valid. For very short dipole antennas, where the largest dimension of the
antenna is less than the wavelength, the transition out of the reactive near-field is
according to Balanis often approximated by:
r1 = λ/2π,
(3.1)
Radio waves are electromagnetic radiation created by accelerating charges. This
movement of charges generates electric and magnetic fields which together form
electromagnetic fields. In the reactive near-field, which is the region closest to
Theoretical solutions
9
Figure 3.2: Field regions of an antenna, where r1 and r2 indicate
the transitions into the reactive near-field and the far-field respectively.
the antenna, the electric and magnetic fields have greater magnitudes and varying
phases. Also the pattern of the electromagnetic wave is not fully formed yet and
the electric and magnetic fields decay with the square and cube of the distance
to the antenna respectively [Rudge et al., 1982, p.13]. In the radiating near-field
region, the radiating fields dominate but the pattern still varies with the distance.
And finally in the far-field the electric and magnetic fields are orthogonal to each
other and the radiation pattern of the electromagnetic waves decays linearly with
the distance which means it does not significantly vary with distance anymore
[Rudge et al., 1982, p.13].
3.1.1.1 Inductive coupling
Inductively coupled RFID systems usually have a passive transponder which is
energized by magnetic fields in the near-field of the antenna [Evdokimov et al.,
2010, p.7]. On the transponder side there is an LC circuit that resonates at a
specified frequency, the coil is the coupling element and works as an antenna.
The reader generates an alternating magnetic field which induces a voltage in the
transponder’s antenna. This voltage is rectified and will be the power supply to
the microchip, see figure 3.3.
The induced current will have opposite sign and act against the generating magnetic field according to Faraday’s induction law. This means the induced current
creates a magnetic field of its own which induces a voltage in the generator coil
on the reader side causing a voltage drop and thus a weakening of the magnetic
field strength on the reader side. By switching a load resistor on and off the
transponder can change the magnitude of this voltage drop and let the switch
10
Theoretical solutions
Figure 3.3: Sketch showing the principle of inductive coupling
timing be controlled by the data to be sent. Transmitting data this way is called
load modulation, [Finkenzeller, 2010, p.40-43]. Inductively coupled systems can
operate in the LF (low frequency) range usually around 125 kHz with a range of
up to 0.5 m and HF (high frequency), usually 13.56 MHz with a range of up to 1
m, [Evdokimov et al., 2010, p.7]. The near field at 13.56 MHz is roughly limited to
3.5 m according to 3.1 mentioned earlier. Practical limitations do however reduce
the range to about 1 m. Range is thus one of the main factors that affect the
frequency choice and antenna dimensions for an RFID system. One disadvantage
with inductive coupling is susceptibility to electromagnetic disturbances such as
those generated by welding robots or strong electric motors [Finkenzeller, 2010,
p.26].
3.1.1.2 Backscatter coupling
In backscatter coupling the reader’s antenna sends electromagnetic waves that are
reflected back by the transponder antenna. The way in which the electromagnetic
waves are reflected back depends on the properties of the transponder such as
cross sectional area and antenna characteristics. The reflection cross-section can
be altered by a load connected to the transponder’s antenna and thus data can be
sent by modulating the reflected amplitude.
Since backscatter systems operate in the far-field of an antenna they usually have
a range of more than 1 meter and the most common operating frequencies for
backscatter coupling are 868 MHz (Europe) and 915 MHz (USA) or the microwaves
band. [Finkenzeller, 2010, p.156]. Because of the long range the radiated power
is low so the transponder usually is of active type. Data transmission still relies
exclusively on the power in the electromagnetic field emitted by the reader but is
according to Finkenzeller more robust against electromagnetic disturbances than
inductive coupled systems, [Finkenzeller, 2010, p.45-48].
3.1.1.3 Applications
RFID technology has been widely used in the transport sector for speed measurements, vehicle counting, wagon tracking, updating time tables for bus and train
arrivals, electronic toll collection (ETC) and more [Xiaoqiang and Manos, 2011].
Theoretical solutions
11
This section will present a few examples of relevant high-speed RFID applications
and experiments.
LF spectrum
Most of the RFID applications in the LF (low frequency) spectrum have an operating frequency of 125 kHz. TSS (Traffic Supervisions Systems) is a company
which has developed solutions for several ITS (Intelligent Transportation System)
applications for roads and railways. Their systems can be structured into two
categories: AVI (Automatic Vehicle Identification) and AVL (Automatic Vehicle
Location). In AVI systems the tags are placed on the vehicle and readers in the
infrastructure. In AVL systems the reader is mounted on the vehicle and tags are
placed at specific positions in roads/railways, each tag corresponding to a location
registered in a database. The read tag ID can for example be sent to a central
information system via radio or just used by the car processing unit for different
purposes.
One of the company’s AVL systems, called TPL (train position locator), has interesting specifications. It has a speed range of 0-300 km/h with a position accuracy
of ± 1 cm at low speeds and ± 50 cm at the maximum speed, [TSS, 2015]. The
antenna dimensions are 108x335x59 mm and the tag housing has a diameter of
40 mm and a length of 330 mm. The EMI environment under a train should have
similarities to the one under a car getting power supplied conductively driving on
an electrical road. The specifications of this system makes it very interesting for
the project.
HF spectrum
RFID systems with an operating frequency of 13.56 MHz are said to be working
in the HF (high frequency) spectrum. Optys Corporation, an RFID design and
developing company has done high-speed reading tests with a 19.5 cm long tag
and 30x10 cm antenna at an operating frequency of 13.56 MHz. The tag was
attached on top of a H0 scale model train and the antenna was suspended above
the rails. When moving at the speed of 113 km/h the tag was successfully read
once. Unfortunately a documentation report could not be found but a video of the
experiment can be watched at [Optys Corporation, 2011]. The distance between
the reader and the tag is not specified but judging from the video it may be
roughly 10-15 cm. The standard used in this system is ISO 15693 which includes
basic communication protocols and anticollision algorithms which allow tags to
take turns in communicating with the reader.
UHF spectrum
The standard called EPC Global Gen2 specifies RFID systems with a range of 2.5
cm - 10 m and operating frequencies in the UHF (ultra high frequency) spectrum
12
Theoretical solutions
(858 - 930 MHz). Each RFID tag, active or passive, contains an universal identifier
in the form of an EPC code (electronic product code) saved on the memory chip.
This protocol is built to suit inventories in warehouses where many products have
to be identified fast and information such as shelf life, shipping date have to be
read/written to a tag. Therefore the reader has to go through these three states:
select (where a population of tags are selected for inventory), inventory (where
each tag is identified by its EPC) and access (where the reader can read/write
to the tag’s memory chip). The tag goes through the following states for communication: ready (waiting to be selected for an inventory), arbitrate (has been
selected but waits for its turn to identify itself), reply(identifies itself), acknowledged (identification succeeded), open and secured (access to the tag’s memory),
[epc, 2008, p.45-48].
Harting Technology Group (HTG) has done high-speed tests using their SL89
RFID tag, RF-R500-p-EU reader and WR80-30 antenna. The antenna’s operating
frequency is specified to 902-928 MHz and the tag uses the standard EPC Gen2.
The tag was mounted on the car facing the side of the road where the reader
was placed at a distance of 2.5 m at the passing point. When driving past the
antenna at 200 km/h HTG got 9 correct readings of the 96 bit EPC identifier.
Using their smaller Ha-VIS RF-ANT-WR30-EU antenna and Ha-VIS RF-R500c-EU reader HTG still got 1 correct reading at 200km/h. Further specifications
of the experiment and a video can be found at [Wermke et al., 2014a], [Wermke
et al., 2014b].
Another highly interesting application is ATIS (Automatic Train Identification
System) which is primarily used in identifying cargo trains usually traveling at
speeds less than 100 km/h, [Xiaoqiang and Manos, 2011]. This system has been in
use in China since 2007. A UHF reader is placed between the rails and a passive
tag is mounted on the train and its reading distance is specified to about 1.4 m.
Since it would be unnecessary for the reader to constantly be turned on, magnetic
steel detection systems are placed at distances of 40-50 m from the reader to send
turn-on and turn-off signals to the reader when trains are approaching or leaving
the area. When a train is approaching, the reader gets turned on and the read tag
ID is sent further to a central information system which can update time tables
for example. The reader is then turned off when the train has activated the other
magnetic steel detection system. The system also includes a module which can
write information to tags.
It seems like there is a large focus on research regarding the adjusting of such
a system to modern high-speed and ultra high-speed trains which can reach a
velocity of up to 500 km/h. The biggest challenges are the tag latency and the
fact that the tag is within the reading range for a very short period of time for
very high speeds, [Xiaoqiang and Manos, 2011].
Theoretical solutions
13
Choosing frequency and protocol
The reading distance needed between reader and transponder will decide the appropriate coupling method to be used. Power losses in the environment in which
the system is meant to be used, the regulations for the allowable radiated power
specified for each frequency range and limitations on antenna sizes give further
constraints.
As mentioned before the power of the magnetic field decays with the cube of the
distance in the near-field which corresponds to 60 dB/decade. Thereafter the
power of the electromagnetic field decays linearly with distance in the far-field
which corresponds to 20 dB/decade. The specifications for the maximum allowed
transmit power is usually given as the field strength at a distance of 10 m from
the reader. Lower frequencies have a larger near-field region according to equation
3.1 which means a higher initial transmit power will decay to the same strength
at 10 m as a lower initial power transmitted at a higher frequency, [Finkenzeller,
2010, p.162] This is an interesting optimization aspect when choosing to work with
inductively coupled systems. A lower frequency means a slower reading speed
though since there are fewer wave periods per unit of time to process. The reading
range could instead be increased by using larger tags, and thereby get a longer
time window and more time for the reading to take place.
The environment of an RFID system can cause problems. Metallic surroundings
can affect the strength of the field between reader and transponder and thus reduce
the reading area. This is due to eddy currents induced in the metal which oppose
the initial field according to Lenz’s law. There are many solutions to this problem,
one of them being ferrite shielding where a piece of ferrite with high magnetic
permeability is placed between the antenna and the metal. This will prevent eddy
currents but the field strength may get higher so adjustments have to be made,
[Finkenzeller, 2010, p.107-108].
An issue with using UHF RFID is that the operating frequency allowed varies and
there exists one standard in the US and one standard in EU. To maximize the
efficiency of the antennas of the reader these are often tuned to either the EU
standard or the US standard and not both. So to use the UHF system in the
whole world both antenna standards would need to be installed.
In an application such as identifying objects moving at high speeds a simple protocol would be the best suited. The extra functionality that EPC gen2 has is not
needed in this case and would contribute to longer read latency, mostly because
of the anti collision algorithms.
3.2 Solutions for car positioning
In this section the different methods that were considered for the the positioning
are described. Since no electric active parts are allowed to be exposed in front or
back of the car the positioning needs to be accurate to within centimeters, even at
14
Theoretical solutions
higher speeds. As the environment can get dirty and the electrical road is subject
to wear and tear some methods as for example methods using photodetectors are
not suitable for this system and will not be further discussed in this report.
3.2.1 Identifying antenna signal strength
This method requires two transmitter antennas on the car and one after each
power delivering rail.
Figure 3.4: Car positioning using two antennas that send synchronized as seen in A. The third antenna (placed in the road)
detects when the two signals have the same strength as seen in
B.
The car’s position is identified when the receiver antenna registers the same signal
strength from both transmitter antennas, see figure 3.4. Trying to compare two
signal strengths is problematic since the signals can get affected differently by the
surroundings. Electromagnetic interference from the road can for instance affect
the reception. Thus the amplitude of the received signals does not only depend on
the distance from the car. This makes it difficult to determine when the two signals
have the same amplitude. Since the positioning also has high time constraints there
is a very short time window for processing the data more thoroughly in order to get
higher accuracy. This idea is decided to be to problematic and not to be analyzed
any further.
3.2.2 Doppler effect
The components required are one receiver antenna after each power delivering rail
and one/two sending antennas on the car.
Theoretical solutions
15
Having a radio transmitter on a moving car, the intercepted frequency will be
higher than the source frequency when the car is approaching the receiver and
lower when the car is moving further away due to the Doppler effect. Therefore the
difference between the observed and emitted frequency will have a step form going
from positive to negative if the transmitter is approaching the receiver directly.
Using this method the position of the car is detected by identifying this frequency
hop, see figure 3.5.
Figure 3.5: Car positioning by detecting the frequency hop caused
by the Doppler effect. The car (marked as the red square) is
moving from left to right with constant speed as indicated by
the velocity vector vs . At the time instances t1, t2 and t3 the
received frequency will be higher, equal and lower than the sent
frequency respectively.
The formula describing the relationship between the emitted frequency, fs and the
received frequency fr for a stationary receiver is:
fr =
c
c
=
· fs ,
λ
c ± vs
where λ is the wavelength, c is the speed of light and vs is the radial component
of the speed of the transmitter, i.e the velocity component along a straight line
between the transmitter and receiver, [Tipler and Gene, 2008, p.518-519]. Since the
received frequency is higher when the transmitter is approaching, the wavelength
will be shorter and that is when the velocity gets a negative sign as indicated by
the formula.
In this case the receiver is approached at an angle because the transmitter is placed
on the car at a height h from the road. The radial component of the velocity
will thus not switch signs directly when passing the receiver but rather make a
slower transition depending on the angle, see figure 3.5. This is the reason why
the frequency hop does not change like a perfect step curve but it monotonically
decreases instead. The effect of the height on the change in frequency can be seen
in figure 3.6a for relevant heights between 10-30 cm, which is a reasonable range
16
Theoretical solutions
(a)
(b)
Figure 3.6: Doppler shift at 1 GHz and 100 km/h passing speed
with detector placed after 1 m for a) different heights h of car
ground clearance and b) different sideway positions s. The blue
line corresponds here to the car being in the other lane.
for the ground clearance of a car. The figure also shows that the Doppler shift is
about 200 Hz in total for a 1 GHz wave, if the car travels at 100 km/h. Moving
laterally relative to the receiver will give less change in frequency, see figure 3.6b,
where a movement of 3.25 m means that the car has switched lanes, considering
that a typical bidirectional road has a width of 6.5 m, [VGU, 2004].
In the scenario with one transmitter antenna, this should be placed on the front
part of the car in such a way that when the position has been detected the on-signal
to next rail should be sent. The off-signal to the rail about to be left behind can
then be calculated with the help of the speed and the distance between the antenna
and the last pickup (assuming this is some standard or that it is communicated
to the system by the car) and adding some time margin. In the scenario with
two antennas, the additional antenna would be placed on the back of the car and
would signal when a rail should be turned off. The latter scenario is more accurate
in case the car is accelerating but also safer in case something goes wrong, like an
accident, corrupt speed data or other errors in the system.
The problem with this method is once again the accuracy. The method first
demands very stable frequency references for the signals of the transmitter and
receiver antennas. Secondly as seen in picture 3.6a the accuracy of the frequency
shift is very dependent on the height difference between transmitter and detector,
making the method harder to realize for a fast and high accuracy detection.
3.2.3 Inductive detection
The principle of magnetic induction is a common way of detecting cars approaching
drive-throughs and traffic lights. These detectors are usually called inductive-loop
traffic detectors and consist of wire loops installed in the roadways and a processing
Theoretical solutions
17
unit. The loop is oscillating with a certain frequency which increases as a car passes
over it because the large amount of metal on the car lowers the inductance of the
loop. Changes in frequency are processed and give the detection signal.
Using magnetic induction in traffic applications has many advantages. It is a
simple solution. It is very resistant to wear, tear and dirty environments. This
method does not have enough accuracy to be used for identifying the position
of a car on an electric road though. The idea of using magnetic induction and
two resonant circuits has however been analysed and tested with good results
in a previous master thesis [Sund, 2014] where a proof of concept was built to
detect a car. The system, shown in figure 3.7, consists of a series LC circuit as
a transmitter and a parallel LC circuit as a receiver. Both tuned at the same
resonant frequency. The working principle is relying on the fact that alternating
current flowing through the transmitter circuit generates an alternating magnetic
field, which can induce a voltage in the receiver circuit. In a way, simplified, this
is the same way that the RFID systems work. A parallel LC circuit is used on
the receiver side because it has a high impedance at resonance while a series LC
circuit has a low impedance which enables high current through it which is needed
to create a strong magnetic field.
Figure 3.7: Illustration from earlier master thesis [Sund, 2014, fig
3, p.7] showing the differences of the resonance circuits at the
transmitter and receiver.
At the resonant frequency an LC circuit is purely resistive which means the reactances of the inductor and the capacitor cancel each other out. The resonance
frequency in an LC circuit is then given by:
2πf0 L =
1
1
√
⇔ f0 =
,
2πf0 C
2π LC
(3.2)
where L and C are the inductance and the capacitance.
As a measure of efficiency in a resonant circuit, the quality factor Q is defined as
the ratio between the energy stored in the circuit and the average power dissipated.
18
Theoretical solutions
For a resonant circuit with an sinusoidal input signal with the angular resonant
frequency ω, the expression is:
Q=ω
energy stored
.
average power dissipated
The total energy in a resonant circuit is constant at resonance and oscillates back
and forth between the inductor and capacitor. This means that the total energy
stored in the system at any time is equal to the maximum energy stored in either
the inductor or the capacitor. Since the system is purely resistive at resonance
2
the average power loss is simply Pavg = Ipk
R/2, where Ipk is the peak current,
[Thomas, 2004, p.87-92]. The Q factor in a series RLC circuit at resonance can
then be derived as follows:
1
2
LIpk
L
Etot
= ω0 12 2
=
= ω0
Q = ω0
Pavg
Rs
2 Ipk Rs
p
L/C
,
Rs
(3.3)
The formula for the Q factor in a parallel RLC circuit can be derived in a similar
way to:
Rp
Q = ω0 Rp C = p
,
(3.4)
L/C
The Q factor is not only an indicator of efficiency but since it is a function of
power losses it relates to the
√ bandwidth and ringing in the circuit as well. Solving
the equation |H(ω)| = 1/ 2 for ω gives two solutions, ω1 and ω2 which are the
frequencies at which half power occurs. This gives the following bandwidth for the
series and parallel circuits:
(
∆ω = ω1 − ω2 =
R/L,
(series)
1/RC, (parallel)
,
(3.5)
By putting eq. 3.3, 3.4 and 3.5 together it can be showed that the bandwidth in
a resonant circuit is:
Q=
ω0
,
∆ω
(3.6)
Factorising the transfer function and inverse transforming to get the impulse response in the time plane, gives an expression for the time constants for a parallel
and series RLC circuit. The time constants are 2RC and 2L/R. Using this together with eq. 3.3 and 3.4 gives the following relationship between the Q factor
and the time constant in a resonant RLC circuit:
Q=
τ ω0
2
(3.7)
Theoretical solutions
19
Thus the Q factor is a useful parameter when designing a resonant circuit not only
as a measure of efficiency but also bandwidth and time constant. A higher Q value
means a smaller bandwidth but a higher time constant which means the ringings
in the oscillations will die out slower.
Sund’s idea and ground work shows good potential and should be analyzed further.
There is for instance a lack of experimentation and analyses of how accurate or fast
the system is or could be. In his system a simple amplitude comparative method
is used to detect the car [Sund, 2014, p.51-58] which leaves much to wish for in
accuracy.
3.2.4 Conductive pickup signaling
Using the fact that the pickups have conductive contact with the rails and the
power is transmitted as direct current it would be feasible to send a sinusoidal
signal down from a pickup to a rail. If two pickups send two different sinusoidal
Figure 3.8: Positioning using pickup two (p2) and three (p3), each
sending a sinusoidal signal with a specific frequency down to the
rails. When p2 makes a jump from rail C to rail B the control
unit turns on rail A. When (p3) makes a jump from rail C to
rail B the control unit turns off rail C. In the figure there are
also antennas to show the use of wireless positioning.
signals it would be possible to distinguish the pickups from each other as seen in
figure 3.8. If one signal is detected at one of the rails by the control unit and then
detected at the adjacent rail by the next control unit, it is said that a jump has
occurred. The more accurately this jump is detected, the more accurately can the
position be decided. At low speeds this jump would probably be detected directly
as it occurs. As the pickups might bounce off the road it could get difficult to
accurately detect the signal at high speeds. Challenging parts of this method are
high pass filtering the signal from the power rails, and the need for the power rails
and pickups to be high frequency isolated from neighboring pickups and rails.
20
Theoretical solutions
3.2.5 Short circuit detectors on rail
Instead of sending and detecting a signal sent through the pickups it could be
possible to design the rails so that a passing pickup could trigger short circuits
placed at specific positions on the rail as seen in figure 3.9. In order to make the
detection more robust against false positives, detection when no detection should
occur, two short circuits at two different positions on the rail can be designed to
occur at the same time. To make double detections occur when it is time to turn
a rail on or off, four short circuit gaps have to be placed on the rail. As shown in
figure 3.9, equidistantly placed pickups cause the short circuit detection pattern to
include two double detections of each of the double detection gap pairs. This can
be seen in figure 3.9 where for instance the times t1 and t4 have the same short
circuit gap pairs. One way to make sure that the switching of a rail takes place
Figure 3.9: The case where the cars have equally spread pickups
p1-p3. The rail is equipped with four gaps along z-axis with
potential difference to the rail that the pickups short circuit
when they move over them. The gaps are placed so that two
pickups short circuit gaps at the same time when a rail should
be turned on (t3) or turned off (t4).
at the correct detection is to have a state machine in the control unit code. This
state machine goes through the states resembling the timelines in the graph shown
in the lower left of figure 3.9 and therefore knows when the correct detection pair
occurs.
Another way to distinguish between correct and false detection pairs is to move
the middle pickup on the car a little to the side. This has been done in figure 3.10
where the middle pickup (p2) has been moved backwards and the positioning of
the short circuit detectors on the rails has been moved. This gives rise to a new
detection pattern as shown in the lower left of figure 3.10 that don’t have doublets
of the detection pairs as the previous method had.
These conductive short circuit methods might work using hall detectors instead
and in that way eliminating the need for isolated conductive parts and the risk
Theoretical solutions
21
Figure 3.10: The case where the cars have equally spread pickups
p1-p3. The rail is equipped with four gaps along z-axis with
potential difference to the rail that the pickups short circuit
when they move over them. The gaps are placed so that two
pickups short circuit gaps at the same time when a rail should
be turned on (t3) or turned off (t4).
of the pickup jumping over the detection area as well as easier rail design. This
could be further investigated later.
3.2.6 Hall effect sensors
The concept is the same as in the short circuit method in 3.2.5, but with Hall
effect sensors instead of short circuit sensors. By placing electromagnets on each
side of pickup 3 and Hall effect sensors before each ground rail it should be possible
to make an accurate detection.
The Hall effect is the phenomenon arising when an electric current passes through
a metal located in a magnetic field. A potential proportional to the current and
the magnetic field arises perpendicular oriented to them both. [Hall, 1879]. Hall
effect sensors are commonly used for measuring rotational speed of motors. Often
the sensors are of either a linear version or an on-off switch version. The analog
sensors give an output proportional to the strength of the magnetic field whilst
the switching version acts as a saturated transistor. For the sensors to work in the
setup presented in 3.2.5 there can’t be any ferromagnetic material placed between
the magnet and the sensor which might be hard to achieve in the final design.
3.2.7 Sound and vibration
The frequency content in the sound wave that arises when the pickup has contact
with the conductive material of the rail should be very distinct and different from
22
Theoretical solutions
that when the pickup has contact with the isolation material between the rails.
It should be possible to determine when a pickup leaves and enters a rail using
one or more vibration sensors in the area around the isolator parts. It might
also be possible to analyze the sound and see distinctive changes in the vibrations
depending on how many pickups that are on the same rail. If the hardware and
the algorithm doing this can be made fast and cheap enough it is a possible way
for precise detection. The method is however somewhat difficult to realize since
no pickups have been designed or built yet to test this out on.
3.3 Different communication schemes
Different scenarios for the communication in the overall system have been briefly
analyzed. Figure 3.11 is meant to help visualizing them all. The possible communication channels considered are a two-way communication link between each
car and the Radio Station Unit (RSU) placed on the side of a road at appropriate intervals. The RSU uses some sort of radio communication, wifi or 3/4G, to
communicate with each car, marked by A in the picture. Wired communication
medium is used to communicate with the electronics in the road, marked by B in
the picture. Between each charging rail there is a possibility for a radio detector
or receiver, marked as C in the picture. There should also be a possibility for each
control unit to communicate with its neighbor directly, marked as D in the figure.
Figure 3.11: Illustrative sketch of the communication system to aid
the understanding of the scenarios.
3.3.1 Scenario one
Using RFID tags between each road section and a RFID reader on the car, the
car can read a tag on the road that corresponds to the next rail. The car can then
communicate this tag ID together with its unique car ID to the RSU via channel
Theoretical solutions
23
A. The RSU now has an uniquely identified car with a roughly accurate physical
position. The RSU sends a signal to the corresponding rail control unit making it
ready to switch the rail on and off. The switching occurs when a detection, using
the possible ways described in solutions for car positioning 3.2, is triggered. In
this scenario the intelligence is centralized to the RSU and the control units are
only triggers controlling the switching of one rail. The RFID system is designed
for use of many tags and few readers.
The scenario needs a fast working RFID system and a fast working long range
communication so that the time from reading the RFID tag to switching the rail
is not exceeded. If a car is traveling at a speed of 200 km/h and the RFID tag
is read one meter before the switch is triggered, that gives a total time of 18 ms.
Since the detection occurs at the rail control unit the communication between the
car, RSU and rail control unit in this scenario doesn’t have to be deterministic, just
performed fast and reliably enough. Detection solutions thought of as appropriate
for this scenario, out of the brief analyzing done in solutions for car positioning
3.2 are Hall effect sensors and inductive detection.
3.3.2 Scenario two
This scenario is very similar to the previous scenario, except the RFID readers
are placed in the road and a tag is placed on the car. In other words, this one
way communication setup is the other way around from that in scenario one. The
approaching car sends its own tag ID and a GPS position to the RSU. The RSU
sends information about which tags are clear and accepted for use to all the rail
control units in the vicinity of the GPS position. When the car tag ID is read by
the rail control unit the position is roughly confirmed and the upcoming rail can
be informed to get ready to be switched on, through communication link D. The
accurate switching is again performed by one of the solutions from solutions for
car positioning 3.2.
In this scenario the key corresponding to a car is the RFID tag which is constant
and hard to keep secret. This makes it hard to identify which car is activating
which rail in a satisfying manner. The RFID tags are also much cheaper than the
readers, this scenario resulting in a more expensive road. On the other side this
scenario doesn’t have the same constraints on the communication speed for either
channel A or B.
3.3.3 Scenario three
In this scenario the intelligence is distributed to the control units of each individual
rail and there needs to be a two way communication link between car and control
unit at each individual rail. The rail identifies itself with a RFID tag and the car
sends a rail unique code that the rail uses to both identify and position the car.
The long range channel A is used to negotiate the unique codes and other essential
information. This scenario demands that the car is able to send a key and the
24
Theoretical solutions
speed, possibly around 32 + 8 bit, to a control unit at least 150 times per second
for a radio range of around 0.5 m. This constraint is set by the maximum speed
of 200 km/h and that a message should be sent at least three times to be received
correctly.
There is no perfect way thought of in solutions for car positioning 3.2 to send so
much information from the car to the rail control unit and at the same time find
a very accurate position at high speeds. Techniques that could be possible with
more analyzing and investigation could be Conductive pickup signaling, Identifying
antenna signal strength, inductive detection or Doppler effect. All of them might
be hard to get to send enough information and at the same time accurately acquire
the position.
Chapter
4
Analysis and testing
4.1 Car positioning
One of the most promising methods in solutions for car positioning: 3.2 and
also the one which could be tested immediately was the inductive method. An
experimental setup to do comparing experiments was built and calibrated, then
different antennas and frequencies were analyzed. Finally a detection system was
built, implemented and tested outdoors.
4.1.1 Pendulum as experimental setup
In order to perform repeatable low speed tests in the laboratory a swing was built
consisting of a rectangular wood plank suspended at the short ends as a swing.
The length of the swinging pendulum measured from the pivot point to the center
of mass of the plank was 258 cm and the plank itself had a length and width of
45 cm and 9.5 cm respectively. The height from the plank to the floor was about
10 cm as seen in figure 4.1a. The energy of a swing at any point is the sum of the
potential and kinetic energy and this energy is conserved if the friction is neglected.
Approximating the swing as a simple pendulum and setting up the energy balance
equations gives the following expression for the pendulum’s velocity at a height h:
Etot = mghstart = mgh +
p
mv 2
⇔ v = 2g(hstart − h)
2
where m is the mass the of the pendulum, g is the gravitational acceleration,
hstart is the height from which the pendulum is released and v is the velocity
at the height h. According to this equation the velocity of the pendulum at the
equilibrium point is 4.43 m/s (15.95 km/h) when released from a height of 1 m
(from the floor). This was approximately the highest speed tested with since it
was hard to manually release the pendulum from a higher height than this without
it swinging sideways. For a more accurate velocity measurement and to get an
25
26
Analysis and testing
accurate position reference a photodiode was placed underneath the swing and a
strong light source was pointed from above. By measuring the time during which
the swing shadowed the sensor the speed could be calculated, since the width of
the wood plank shadow could be measured. The measurement circuit is shown in
figure 4.1b.
(a)
(b)
Figure 4.1: 4.1a The setup with the swing without the strong light
source lit. To the right in the picture an Arduino Uno and photo
detection circuit can be seen and under the swing there is room
place the system to be tested. 4.1b Measurement circuit for the
photodiode with R1 = 10 kΩ.
4.1.2 Inductive system from the previous thesis work
First off the circuit from the previous master thesis work [Sund, 2014] was tested,
which has a resonance frequency of 29 kHz. The detection circuit sent out a 5 V
high car detect signal when the voltage over the receiver coil was above a calibratable threshold, implemented using a single comparator. This means that the
detection circuit sent out a high signal once every period and that the high signal
lasted for the time the voltage over the coil was positive and above this threshold.
For testing purposes the threshold was tuned to 2.6 V and the swing was mounted
5.5 cm over the detector. In the original master thesis the detection was made
by receiving the signal as an interrupt and once an interrupt had occurred the
interrupt handling was turned off for a fixed amount of time, corresponding to the
estimated speed the car should have on the road the system was implemented on.
One disadvantage with this way of doing a detection is the lack of precision since
it is only relying on a correct tuning of a threshold for the field’s amplitude. Furthermore the detection has little protection against interference or altering of the
received frequency and amplitude. In the tests performed in this work advantage
was taken of the fact that the transmitter coil is made in a horizontal loop and the
Analysis and testing
27
receiver is made in a vertical loop. The envelope of the transmitted magnetic field
therefore has the shape of two lobes with a zero point in between. This zero point
corresponds to the point straight underneath the transmitter coil, shown as the
dotted lines in figure 4.2. Using an Arduino Uno1 the 30 kHz changes were filtered
Figure 4.2: The magnetic field sent out from the horizontal coil and
picked up by the vertical receiver coil.
out and time stamps for the detected rise and fall of the first and second lobe were
gathered. A very precise measurement of the detection distance was made using
the speed information and reference time stamps of the photo diode, see figure
4.3. This shows that the low point between the lobes can easily be detected with a
Figure 4.3: Plot of time stamps for rise and fall detection in reference
to the photo diode
very high degree of accuracy. In this first experiment the position error was below
1
open-source prototyping platform, https://www.arduino.cc/
28
Analysis and testing
1 cm. The maximum theoretical speed of this method is limited by the rise time
of the magnetic field since the magnetic field strength has to rise high enough for
a change to be detectable. The point between the two lobes should always exist
since the two lobes have a half period phase shift to each other and therefore the
signal always has to pass a point with zero magnetic field.
To test the consequences of a phase shift and other possible frequencies, a digital
square wave oscillator was programmed on an Arduino Uno. By using the internal
clock and timers, a pin toggle of 29.9 kHz with the possibility to turn the signal on
and off fast was created. A push-pull transistor output stage was built following
the later stage in the schematics for the transmitter in the previous master thesis
[Sund, 2014, p10]. The transmitter coil was then powered by this output stage
and driven by the Arduino pin toggle signal. Since the transmitter coil acts as
a resonance circuit the square wave gets filtered into a sinusoidal magnetic field.
A stationary simulation setup was made by placing the transmitter and receiver
coil still at the optimal lateral transfer position but keeping the desired height
constant, see fig 4.4.
Figure 4.4: The stationary simulation setup. A Oscilloscope measured the magnetic field from transmitter coil, voltage over receiver coil and driving signal from Arduino
A passing car could roughly be simulated by turning the square wave signal to the
new output stage on and off for the time corresponding to a distance at a specific
speed. Moving the transmitter laterally at a height of 10 cm over the receiver in
the movement axis gave an approximation of the strength of the inductive field at
different distances from the receiver. The distance from the midpoint where the
induced voltage in the receiver was under 10% of the maximum value was around
0.5 cm. This gave a 1 cm long vertical distance, 10 cm under the transmitter, where
the magnetic field was almost zero.
4.1.2.1 Simulating high speeds at 29.9 kHz
To simulate a car passing the system at 100km/h, the Arduino was programmed to
turn on the signal for 4 ms, turn off the signal for 400 µs, corresponding to 1.1 cm,
Analysis and testing
29
and then turn on the system again for 4 ms. This resulted in figure 4.5.
Figure 4.5: A simulated car passing using the 30 kHz receiver and
transmitter placed at optimal reading range and then turning
off the 30 kHz square wave for 400 µs to simulate a 1.1 cm low
magnetic low point that passes in 100 km/h. Blue is the magnetic field radiated from the transmitter. Yellow is the voltage
over the receiver. Turquoise is the 5 V square wave generated
by the Arduino feed into the transmitter coil.
To simulate the phase shift the off time had to be a factor of the period time. For
29 kHz the period time is 33 µs so an off time (the signal can be high or low) of
33 µs should make a phase shift and force the receiver to pass through a low-point.
By experimenting, a delay of 11 µs made the Arduino pause its clock for 15 µs
making a 30 µs off time and phase shift shown in figure 4.6.
This shows that it is possible to detect the passing inductive coil at very high
speeds by using the fact that the signal makes a phase shift and the magnetic field
passes through a low-point. But it should be better to use a higher frequency so
there is a longer low-point in relation to the period time to detect. Increasing the
frequency gives lower rise times and longer low point for the coils which in turn
would give a faster and more distinct detection so the receiver coil and the receiver
circuit were remade.
4.1.3 Experimenting with different near field antennas
The transmitter and receiver are both resonating coils acting as near field antennas.
The word antennas is used here in a wider sense than the common definition,
since we are calling them coil antennas. Equation 3.2 was used to adjust the
resonance frequency of the LC circuit. The inductance was chosen such that
30
Analysis and testing
Figure 4.6: A Simulated phase shift using the 30 kHz receiver and
transmitter placed at optimal reading range and then pausing
the 30 kHz square wave for 15 µs. Blue is the magnetic field
radiated from the transmitter. Yellow is the voltage over the
receiver. Turquoise is the 5 V square wave generated by the
Arduino feed in to the transmitter coil. The phase shift takes
place at the time Ax (solid line) and is seen in the receiver coil
185 µs later (dotted line).
simulations of the circuit showed a good rise time and relatively low transients
and the capacitance was adjusted according to eq. 3.2. A rough approximation of
how many windings and what cross section area a coil should have to get a certain
inductance was empirically found.
Copper thread with a diameter of 0.6 mm was used in order to lower the power
losses. The inductance of the coil was measured by connecting a known capacitor in parallel with the unknown coil, doing a frequency sweep and looking for
the frequency where the voltage over the coil had a peak. The inductance was
then calculated using eq. 3.2. The resonance frequency was easier to observe by
connecting a big resistor in series with the parallel LC circuit because it lowered
the voltage span over the LC circuit making it easier to observe the peak (10 and
100 kΩ were used in the experiments).
In the experiments presented in this report, the dimensions of the transmitter coil
antenna tested with were kept roughly the same as in Sund’s work but the receiver
coil antenna had smaller diameter and a ferrite core. First the new antennas were
tuned to 300 kHz for a higher position accuracy since more periods per unit of time
would be available for processing. Later on the antennas were retuned to 140 kHz
because the maximum allowed field strength at 300 kHz is very low compared to
Analysis and testing
31
around 9 −148 kHz [PTSFS, 2015, p.13]. And since the chosen RFID system runs
on 125 kHz, 140 kHz seemed like a good frequency to aim for. The maximum
allowed field strength at 140 kHz and a distance of 10 m from the antenna is 42
dB uA/m [PTSFS, 2015, p.13]. This corresponds to 0.158 nT:
42 dB µA/m = 20 · log(
H
)
1 µA/m
⇔ H = 125.892 µA/m
⇔ B = µ0 µr H = 0.158 nT.
4.1.4 Simulating, testing and building
The 140 kHz system consists of a transmitter stage and a receiver stage. As the
transmitter stage an Arduino Uno acts as a signal generator and together with a
transmitter antenna the sending stage is to be mounted underneath a car. The
receiving stage consists of a receiver antenna, rectifier electronics and an Arduino
Due2 with an Ethernet and SD-card reader shield3 . The receiver antenna, electronics and Arduino are to be put inside a road segment mock-up with LED lights
on it. Instead of delivering power to a passing car, the segment lights up its LED
lights when the car passes.
4.1.4.1 Receiver and transmitter antennas
The transmitter coil or antenna was finally constructed by 33 turns of 0.6 mm
copper wire in the shape of an rectangle with a length of 375 mm and width
of 70 mm. This gave an inductance of 554 µH. The resonance frequency of the
transmitter was tuned to 140 kHz with a series capacitance of 2.470 nF. The
receiver antenna was constructed by 49 turns of 0.6 mm copper wire wound around
a ferrite core from an old AM radio. The inductance of the receiver antenna then
became 128.9 µH and got the resonance frequency 140 kHz with 10 nF. The two
antennas are shown in figure 4.7. The skin effect had to be considered when
measuring the impedance of the transmitter and receiver LC circuits. Therefore
the measurements were made with an LCR meter instead of the usual four-point
measurements with the multimeter. The skin effect is the tendency of the current
density to be distributed in the area close to the surface of the conductor and not
in the middle. Higher skin effect means that the current flows through an area
smaller than the cross section area of the conductor, thus the resistance is higher.
This is due to the eddy currents generated inside the conductor which counteract
2
Arduino Due is a more powerful developing board based on a 32-bit ARM core microcontroller. More information on https://www.arduino.cc/en/Main/ArduinoBoardDue
3
Arduino ethernet shield is an extention to the Arduino giving it an ethernet jack and
a micro SD-card reader. This effectivly giving the Arduino the means to communicate
through network and save information on an micro SD-card. More information can be
found on https://www.arduino.cc/en/Main/ArduinoEthernetShield
32
Analysis and testing
Figure 4.7: The transmitter (top one in picture) and receiver antenna, at an earlier resonance tuning. The dimensions and
shape are the same as in the chosen 140 kHz setup. Only the
number of windings and the tuning capacitance value differ.
the current in the middle of the conductor. The skin depth in a copper wire can
be calculated according to:
r
δ=
2
ωµr µ0 σ
where µ0 is the magnetic permeability of free space µ0 = 4π · 10−7 T · m/A, µr
is the relative magnetic permeability (it has the value 1 for air), ω is the angular
frequency and σ is a parameter specific to copper. The formula shows that the skin
effect is higher for higher frequencies and it can be calculated that the skin effect
starts affecting the resistance first after 49 kHz where δ is 0.3 mm, i.e equal to the
radius of the wire which means the current flows through the whole cross section
area. At the frequency of 140 kHz δ is approximately 0.178 mm which means that
a little over half of the cross section area of the conductor is used. Since the radius
and the skin depth are so close to each other there is no equation to calculate the
resistance of the conductor. Another factor probably affecting the resistance in
the coil more strongly is the proximity effect, i.e losses in the conductor due to
eddy currents induced by magnetic fields that are close by. The series resistance
in the transmitter circuit was measured to 14.51 Ω and to 2490 Ω in the parallel
circuit at the exact resonance frequency of 140.660 kHz. The quality factors for
the transmitter and receiver circuits are 32.64 and 21.98 respectively. The time
constants are 73.77 µs for the transmitter and 49.74 µs for the receiver according
to eq. 3.7. Impedance measurements for the transmitter antenna and receiver
antenna can be seen in figures 4.8 and 4.9.
The reason behind winding the receiver around a ferrite core was to lower the
number of turns and the radius while keeping the inductance value high. The
reason to want a high inductance value is to get a stronger signal. A side effect of
using a ferrite core is that the core might be saturated by static magnetic fields
Analysis and testing
(a)
33
(b)
Figure 4.8: Bandwidth of the tuned transmitter antenna. The bandwidth is approximately 4 kHz
(a)
(b)
Figure 4.9: Bandwidth of the tuned receiver antenna. The bandwidth is approximately 6.5 kHz
from the electrical road. To test the affect the current of the road will have on
the signal strength in the inductive detection an experiment was made. The aim
of the experiment is to see how a neodymium magnet at different distances affects
the amplitude of the induced voltage in the receiver antenna.
4.1.4.2 Test of static magnetic impact on ferrite core
To test the effect a strong magnetic field would have on the 140 kHz induced voltage
in the receiver antenna, a neodymium magnet was used and placed at different
distances from the receiver. The receiver was placed at optimal reading range from
the transmitter. A square wave generated by an Arduino Uno was sent as input
to the transmitter and the induced amplitude was measured while the magnet was
placed at different heights from the receiver, see figure 4.10.
34
Analysis and testing
(a)
(b)
Figure 4.10: A piece of neodymium magnet was fastened with tape
on slices of hard plastic and placed above the magnetic receiver,
the number of slices used gave a measurement of the height
between them which was hard to measure otherwise because of
the attraction force. Each slice had a thickness of 1.5 mm.
Figure 4.11 shows the results. The peak around the height of 4.5 mm is probably
a result of the resonance in the transmitter coil and receiver coil are not fully
aligned. When the magnet saturates the ferrite core slightly the permeability is
lowered, inductance raised and the resonance frequency lowered in the receiver
resonance circuit. This probably result in the receiver and transmitter circuits
aligning better and therefore a peak arises. As it can be seen in the figure the
receiver is not affected at all if the magnet is placed at a distance higher than
approximately 7 mm.
The exact characteristics of the neodymium magnet were not known, but an usual
neodymium magnet of grad N50 has a residual flux density, Br, of 1.4 T [NdFeB
Specialists E-magnets UK, 2016]. The magnet used is roughly 5 mm in diameter
and 2 mm thick. An expression [Magnetics, 2016] describing the magnetic field
strength along the central axis of a round neodymium magnet is:
B=
Br
t+x
x
· 2
−√
,
2
2
2 r + (t + x)
r + x2
where r is the radius of a cylinder magnet, t the thickness of the magnet and x the
distance from the face of the magnet to the measured point. The magnetic field
of the magnet at the distance 7 mm using this formula results in roughly 56 mT.
According to our experiments in figure 4.11 this is the lower bound that affects the
receiver. The static magnetic field at a distance r from a wire carrying a current
I is given by:
B=
µ0 I
,
2πr
Analysis and testing
35
Figure 4.11: How the amplitude of the induced voltage over the
receiver varies with a neodymium magnet placed at different
heights from it.
where µ0 is the magnetic permeability of free space µ0 = 4π · 10−7 T · m/A. Assuming that 10 mm is the nearest distance from the receiver the pickups will drain
current and that the maximum flowing current will be 400 A. This results in a
maximum induced magnetic field of 8 mT at the receiver ferrite core.
The probable magnetic field induced by the wires and pickup is lower then a fifth of
the field strength that made an impact on the ferrite core. Therefore the induced
field from the high current in the system should not affect the inductive detector.
4.1.4.3 Rectifier and receiver Arduino
Once the resonance frequency was decided upon and antennas built a receiver
circuit was made. Due to previous experience with Arduino it was easy to keep
using it. The Arduino Due is used as a receiver since it has higher performance
than the Uno board with a faster processor, more memory and faster ADC (analog
to digital converter).
As seen in previous tests, using hardware to send a digital signal on the rise of the
wave and hence detect the frequency is one way to detect the signal. A second
way is to convert the signal to an analog value corresponding to the amplitude
of the waves and then sample it. A third way would be to just sample the raw
wave and do all analysis in software. As a first step it was decided to try to do
the detection on the signal amplitude and check that the signal had the correct
frequency by frequency detection. A sketch of the detection circuit for the receiver
is shown in figure 4.12a. This circuit converts the frequency to a digital square
36
Analysis and testing
wave and the amplitude to an analog value which could be read using the ADC.
The Arduino Due can only handle voltages up to 3.3V so both circuits are built
to have an output in the 0-3.3V range. The frequency analyzing was however
never implemented in code since the bandwidth of the antennas was so narrow
and the detection algorithm works satisfactory using only amplitude information.
The inductance in the transmitter antenna was near the lower acceptable limit,
(a)
(b)
Figure 4.12: 4.12a) Schematic of the receiver antenna electronics
with a rectifier in the lower half and in the half above is a
comparator converting the sine wave to a square wave signal.
4.12b) The PCB of the receiver electronics
leading to a suboptimal filtering of the square wave to sine wave shown in figure
4.13. The ripple in the driving square wave was caused by the antenna load. In this
figure it is also possible to read out that the resonance frequency of the antenna
is not exactly 140 kHz but slightly lower as the sine period is slightly longer than
the driving 140 kHz.
(a)
(b)
Figure 4.13: A none perfect filtering of the square wave to sine wave
in the sending antenna. The blue curve is the driving square
wave signal. The yellow curve is the field out from the antenna
measured with a magnetic-field probe
Doing the same experiment as with the antennas in section 4.1.2.1 a much faster
rise time could be seen. In figure 4.14 the reading from the oscilloscope during a
Analysis and testing
37
stationary test with the signal generating Arduino pausing the signal for 400 µs is
seen as a faster result than that of the 30 kHz in figure 4.5.
Figure 4.14: Simulated response of the receiver and transmitter
(tuned to 140 kHz) at a speed of 100 km/h, i.e the square wave
is paused for 400 µs. The transmitter and receiver are placed
at optimal reading positions. The pink signal is magnetic field
from transmitter coil. The yellow is the voltage over the receiver
coil. Blue is the driving square wave signal from the Arduino.
4.1.4.4 Building a mock-up segment
To test the system a mock-up of a road segment was built. The mock-up was
equipped with LED strips and lights, instead of power giving rails, so that a visual
observation could take place. The driving electronics built for the LED lights are
shown as schematics in figure 4.16. The mock-up was constructed by bending a
metal plate to a shape resembling the shape of the rail segments. The aim was
to make a mock-up resembling the magnetic features of the real theoretic rail
segments to make an as close as possible proof of concept test. The mock-up rail
was also used to analyze the EMI impact on the rail as further described in section
4.3. The interior of the mock-up consists of batteries to power the LED strips and
receiving electronics. To hold everything in place styrofoam, tape and hot-glue
were used. The final result of this first mock-up can be seen in the figure 4.15
together with the transmitter antenna in a box to the left.
The driver circuit for the power LED is shown in figure 4.16a. The two transistors
work together in regulating the current to the LED in such a way that when the
current through M1 is too big the npn transistor is triggered thus reducing the
38
Analysis and testing
Figure 4.15
(a)
(b)
Figure 4.16: a) Driver circuit for the power LED, D1 is the power
LED, M1 - MOSFET(P80NF10), C1- 1000uF, D2 - 3.3V. b)
Driver circuit for the LED strips, D1 is the LED strip, C11000uF, D2 - 3.3V, M1 - MOSFET(P80NF10)
current. The driver circuit for the LED strips is a simple switch configuration, i.e
when the Arduino pin is high the transistor starts leading current and the strip
is turned on, see figure 4.16b. The Zener diodes have the purpose to protect the
Arduino in case something goes wrong and the voltage gets too high but it would
have been safer to use a optocoupler instead.
4.1.4.5 Detection algorithm and code
In figure 4.17 an eight states algorithm is shown. In the Arduino code of the road
segment the detection algorithm is implemented as function ampCalcFix(), see
line 764 in apendix A.1. In the algorithm three tests and one timing are made
Analysis and testing
39
Figure 4.17: Help sketch for eight state detection algorithm
to ensure a correct detection. First the time between s0 and s3 has to be longer
than 100 µs (sorting out short spikes). Then the time between s0 and s1 has to
be longer than the time between s3 and s4 (steeper slope at zero point between
slopes). And finally the time between s0 and s3 has to be longer than the time
between s3 and s5 (to not waiting too long for the second lobe). If too much time
passes since s0 was passed, then the state machine is restarted. If none of the
tests failed, the detection is considered correct and a signal is sent at s6 to turn
on the next power rail. In figure 4.18b signals from an indoor test with the swing
/pendulum setup are showing that the detection works. The signal used to turn
on the LED strips is the pink one shown in figure 4.18b.
(a)
(b)
Figure 4.18: 4.18a Swing dropped from 1 m Giving a passing speed
of around 4 m/s (almost 15 km/h).The Arduino Due is using
a state machine with eight states 4.18b. Each state transition
makes a change in the light blue (signal 2) curve. And as the
state has transitioned in the right way the turn on flag, here
seen as pink (signal 3), is turned on and off.
4.1.5 Testing the detection on a road with a car
As the indoor tests showed that the detection worked and stable results were
collected it was decided to do a test outdoors with a real car passing over the
rail mock-up with the implemented receiver. The described detection algorithm,
oscilloscope readings and data dumps of the sampled amplitude values were tested
40
Analysis and testing
with a real car passing. The test took place in the fuel yard of the combined
heat and power plant in Örtofta, where a car could safely accelerate and pass the
mock-up segment at high speed. The transmitter antenna and driving Arduino
were placed in a box mounted behind a Volvo V70 shown in picture 4.19. The road
rail mock-up was placed and filmed from multiple angles with high speed footage
filming the LED lights from the side shown in picture 4.20. Multiple passes over
Figure 4.19: The sending circuit mounted on the car
Figure 4.20: The rail mock-up at the Örtofta test location. A high
speed camera can be seen rigged in the far left of the picture.
the mock-up were performed and all the passes were correctly detected. Figure
4.21 shows footage from the high speed camera where it can be seen how the LED
lights turn on when the car passes over the mock-up at 100 km/h. The transmitter
Analysis and testing
41
lies in the front of the box and the LED lights are supposed to turn on when the
rise of the second lobe is detected at s6 and turn off at the fall of the second lobe
shown in the earlier figure 4.18b.
Figure 4.21: Detection of car passing in 100km/h from the left.
Screen-shots from a high speed camera to the left and zoomed
in on the right. The LED stripe is turned on in the middle two
frames.
The sampled amplitude values were also dumped to an SD card by the Arduino.
In figure 4.22 two over passes are presented. One when the car passed a little
to the side of the mock-up rail and one when the car passed straight over. The
amplitude damping of the receiver was not properly tuned and as a result a high
ringing is observed at the higher values. This ringings are a weakness in the
receiver electronics construction whose exact cause was not fully investigated.
42
Analysis and testing
(a)
(b)
Figure 4.22: Saved values from two different passes by the car. In
4.22a the car passed in an angle to the side of the mock-up. In
4.22b a perfect passing is shown. High ringings are observed at
higher amplitudes, caused by a fault in the receiver electronics
or the arduino sampling.
4.2 Car identification
The initial ideas for the identification of a car were to test HF or UHF RFID
modules since they had successfully been used in similar applications, see section 3.1.1.3. There were also some ideas about building a radio transceiver from
scratch but that idea was quickly discarded since none of the authors had sufficient radio knowledge and the extensive work wouldn’t have permitted meeting
the deadline for the project. Before deciding which path to continue on, the TSS
company was found. Since their products are adapted to traffic environments and
they have impressive results the company was contacted in order to borrow their
products for testing. Three tags and and one antenna were used in testing, see
figure 4.23a and 4.23b.
The recommended distance between the antenna and the tag is 45 cm in order
to get good results at high speeds. But tests were made at low speed with a
cart, which the antenna is mounted on, driving over the tags in the lab. The tests
showed that the tag was successfully read at lower distances at low speed. In order
for the tags to not interfere with each other the distance between them should be
at least 40 cm.
The antenna communicates with the computer through a serial RS232 connection
written in C. The main code on the car side, found in appendix A.2.6, is written in
C++ and consists of four threads: one for communication between car and antenna,
two threads handling incoming and outgoing messages and one tread that lets the
user manually insert the speed.
Analysis and testing
(a)
43
(b)
Figure 4.23: a) Picture showing the TSS products used, the antenna
and a tag. The antenna and the processing unit are enclosed in
the box. The box has a length, width and height of 36x16x9 cm
b) The antenna is a coil wound around a core. The processing
unit and a small tag for testing purposes are also shown.
4.3 EMI
It is important to investigate the electromagnetic interference under an electrical
car driving on a conductive electrical road so that the position and identification
electronics can be adjusted accordingly.
Firstly, the behavior of electrical sparks between the road and the pickups was
analyzed by using a setup made by one of the project’s supervisors, Lars Lindgren.
These sparks are generated if the pickups bounce off the road a bit and lose contact
with it for a short amount of time which can happen if the car is driving at high
speeds. Information about the EMI under a train would have been interesting
to compare to, but no solid data could be found. Secondly, tests were made to
investigate if the car motors could cause any electromagnetic interference. To test
the interference from an electric car the positioning coil antenna was placed on the
ground and an electric car was droven over it. The signal from the receiver coil
was measured and analyzed.
The test rigg built by Lindgren has been very useful in simulating the behavior of
the sparks. The part simulating the road and the pickups consists of two circular
metallic tracks with a small sleigh fastened between them. The sleigh has four
contacts, two on each track and it is free to rotate, see figure 4.24.
The grey rectangles represent the conducting parts of the rails and the receiver
antenna is located in between them. The red loop antenna simulates the path the
current takes from the rail and up to the car battery through the pickup. Stray
inductances are not shown in the circuit. The capacitor between the loop antenna
and ground is added to counteract the effect of all the stray inductances and thus
make the induced voltage in the receiver clearer to see.
In the real setup the sleigh is surrounded by a metal case as a safety precaution,
44
Analysis and testing
Figure 4.24: The setup for simulating the effect of electrical sparks
between the road and the pickups.
see figure 4.25. The whole setup can be seen in figure 4.26. The DC voltage input
Figure 4.25: Picture of the circular metallic tracks and the sleigh.
On the sleigh the four mentioned contact points and short circuiting wires can be seen.
goes to the loop antenna and the sleigh contacts through a load in series with a
capacitor, the loop antenna can be seen closer in figure 4.27a.
Two sets of experiments were made. In the first one, the pickup was perfectly
aligned above the rail and since the magnetic field in this position is perpendicular
to the field in the receiver antenna no disturbances should be registered. In the
second one, the pickup was positioned at a 45 degree angle with the rail, shown in
figure 4.27b, simulating the situation when the pickup is not centered around the
rail but still has contact through the contact shoe. In this case the magnetic field
Analysis and testing
45
Figure 4.26: The whole setup: in the lower left corner is a wooden
box containing transformers and rectifiers with a parallelly connected capacitor to give a stable DC input. On the top shelf is
the set of capacitors which have the task of making the ringings
sharper and on the leftmost bench is the prototype road.
(a)
(b)
Figure 4.27: On the rail of the prototype there is a loop antenna
simulating a pickup. a) In this particular position the pickup is
perfectly centered above the rail.b) The pickup has a 45 degrees
angle with the rail
in the loop will affect the signal in the receiver antenna. Each experiment was run
with both 40 A and 80 A as the input to see how the current difference will affect
the receiver. The different signals measured during the experiments can be seen
in figure 4.28.
Figure 4.29 and 4.30 show the results when the pickup was placed at 90 and 45
degrees with respect to the road. The amplitude of the ringings doesn’t exceed
2 V peak to peak which shouldn’t be a problem since our transmitter circuit generates a voltage of approximately 7 V peak to peak in the receiver circuit and the
transmitter’s magnetic field could be made up to twenty times stronger without
exceeding the restrictions that are mentioned in section 4.1.3. The current difference didn’t lead to a significant difference in amplitude in the ringings. This is a
good result because the relationship between the current increase and amplitude
46
Analysis and testing
Figure 4.28: The signals that were measured on the oscilloscope.
Yellow is the voltage over the receiver antenna located in between the rails, turquoise and magenta are the voltage and the
current through the circular tracks and blue is a signal indicating
the rotation speed of the sleigh.
(a)
(b)
Figure 4.29: The ringings in the receiver antenna when the loop
antenna was placed at a 90 degree angle with the rail and the
current was 80 A in left picture and 40 A in right picture
of the ringings is not linear. Since the relationship seems to be less than linear it
is reasonable to think that the amplitude of the ringings at 400 A will be lower
than the voltage our transmitter coil could induce in the receiver antenna.
The reason for the ringings picked up when the antenna was placed at a 90 degree
angle can be that the antenna wasn’t perfectly aligned. The source of the high
voltage spikes was not closely investigated but it is probably related to capacitive and inductive stray fields which can come from cable loops in the circuit or
interference from the motor.
Analysis and testing
47
(a)
(b)
Figure 4.30: The ringings in the receiver antenna when the loop
antenna was placed at a 45 degree angle with the rail and the
current was 80 A in left picture and 40 A in right picture
4.3.1 EMI from electric car
Some small experiments were carried out by taping the transmitter under a Nissan
Leaf, a fully electric car, and analyzing the response when it passed over the mockup rail. The Arduino detection algorithms showed no problems with detecting the
transmitter coil passing by. By connecting the receiver antenna directly to an
oscilloscope, the possible EMI was intended to be further measured and analyzed.
As shown by the two seconds long sample in figure 4.31a, where the car passed
the transmitter at low speed, no significant interference was registered around
the detection signal. However, an interesting spike could be observed in figure
4.31b. In this passing, a spike could be observed before the transmitter passed
the receiver. The transmitter was in this experiment mounted on the rearmost
part of the car and the car was driving forward at a speed of about 20 km/h
over the mock-up rail. The spike had the same frequency as the transmitter
antenna and must have been caused by some part of the car frame forming a loop,
that the transmitter induced the frequency in. This car frame loop then acted
as an antenna. The amplitude is about a tenth of the amplitude received from
the transmitter itself. This experiment shows that no obvious electromagnetic
interference seemed to have been caused by the car’s power electronics or motors.
4.4 The Complete system
With a working system for detection, a working system for identifying and experiments showing that the EMI would not be a big problem it was decided to
put it all together in a complete system to prove the concept. Out of the three
communication schemes discussed in section 3.3, scheme one would be easiest to
implement. This since the RFID reader is expensive and big but the tags are
smaller and easier to mount on the road. Furthermore the communication paths
do not have to be deterministic since the timing critical detection is done solely in
48
Analysis and testing
(a)
(b)
Figure 4.31: 4.31a A two second long sample of the induced voltage in the receiver when the car was passing over it with the
transmitter turned on. The transmitter signal is clearly seen by
the receiver. 4.31b The same experiment as in a) but here an
extra spike can be seen in the middle of the picture
the Arduino.
As such the idea is that the car reads the RFID tag and sends the read RFID
tag ID, an unique car ID and the car speed to the road side unit. The road side
unit (RSU) then sends a message to the corresponding rail telling it to be ready
to detect an inductive coil passing. From the speed information the RSU also tells
the rail how long it should be turned on. Using the inductive detector the rail
computer activates the "rail" at the correct time. With the help of a timer the
Arduino then turns the rail off again as the time corresponding to the distance
and speed have passed. In the complete system, the "rail" is still implemented
with LED strips for visualization.
4.4.1 Building
To test the system, one more detection circuit - an antenna for the inductive
detector and one Arduino Due, were put together with the same characteristics
as the one described in section 4.1.4.3. One more mock-up rail was also built but
with a simpler construction. A one meter wooden stud was used as the frame
with the antenna and LED strips taped to it. Figure 4.32 shows the complete rail
segment with the tags and the LED strips mounted, where the distance between
a tag and a receiver coil antenna is 1.15 m. Furthest left in the figure is a tag
followed by a one meter negative rail, a receiver antenna and an one meter active,
switchable rail simulated by a LED strip. Then again a tag, an one meter negative
rail, a receiver antenna and finally a one meter active, switchable rail simulated
by a LED strip. Both Arduino rail computers were, as described earlier, equipped
with Ethernet shields and connected together with a router and a laptop computer
at the side of the road. The laptop computer acted as the road side unit (RSU)
in the experiment.
From the time it takes for a car to read an RFID tag and then reach the next in-
Analysis and testing
49
Figure 4.32: The complete rail segment seen from above. LED strips
are mounted on the side, shining downwards in the picture. The
distance between the center points of a tag and an antenna is
1.15 m. The orange and the white cable in the picture are
the Ethernet cables that connect the Arduino computers to the
router.
ductive detection point, the tag ID, speed and car identification must have reached
the road side computer and activated the upcoming Arduino rail computer. The
distance between an RFID tag and the inductive detector is thought to be roughly
one meter giving a maximum time of 18 ms if the car is traveling at 200 km h−1 .
Some quick tests of round-trip time for 3G and 4G mobile networks showed way
higher latencies. The same tests done on a private, ordinary, 2.4 Ghz wifi showed
better results with latencies around 1 ms but with occasional spikes. As such it
was decided to use a wifi router to connect the car to the RSU computer for the
test. In the car an ordinary laptop was used to communicate with the RFID reader
and, using a usb wifi dongle, the RSU.
4.4.2 Programming
The complete program overview showed in figure 4.33 consists of a server with
multiple classes written in java. The server can be broken down into three pieces.
One part handles the rails (RSURoad.java and RoadConnection- UDP.java), one
part handles the cars (CarServerThread.java and RecThread- .java) and the
last part is a single class implementation which acts as a monitor and makes the
communication between the threads ’thread safe’ (Monitor.java). The flow of
the program goes as follows:
1. The car connects to the wifi and the RSU server with an identification of
itself through the CarServerThread.java .
2. The car reads an RFID tag on the road.
3. The car sends the read tag ID together with the speed to the RSU through
the RecThread.java.
4. The RSU calculates the corresponding on-time for the received speed in
RSURoad.java and sends this to the rail computer linked to the tag ID
through the RoadConnectionUDP.java thread.
50
Analysis and testing
5. The rail computer activates the function ampCalcFix() and waits for a
detection to occur within a time determined by the on-time received. A
timer to send a backup message turning off the previous rail is also started.
6. A backup message turning off the previous rail is sent from this rail computer.
7. If a correct detection occurs the LED strip gets turned on by this rail computer. Otherwise if too much time passes, nothing happens.
8. The LED strip gets turned off. Either by this rail computer’s turn off timer
or by the backup signal sent by the next rail.
Figure 4.33: The complete program overview. All the classes shown
in the RSU except the monitor are threads
4.4.3 Final test
A way to mount the RFID reader and the inductive transmitter antenna on a car
was needed in order to perform the final test where the car was supposed to drive
over the complete rail segment mock-up at 50 km/h. After some discussion the
decision arrived at using a trailer on which to mount the equipment. A trailer
was bought to the project and the equipment was mounted as shown in figure
4.34. The equipment was powered using the 12 V outlet in the car. A parking
house which was often empty was chosen to be the test place. The equipment
was mounted and the complete mock-up was laid out. The test setup is shown in
Analysis and testing
51
figure 4.35. As described earlier the car needs to send its speed to the RSU when
a tag is read for the correct timing to take place. A way to transfer the speed
from the car to the laptop used in our system was never implemented. So a speed
was instead manually typed into the system and then the driver aimed to pass the
road at that speed.
Figure 4.34: In the upper left corner is a picture of the built frame
for mounting the reader and transmitter. In the lower left the
frame can be seen from the side. To the right is the trailer with
the frame, reader and transmitter installed
Figure 4.35: The final test setup is being arranged. The car is going
to drive over the mock-up from the left in the picture and the
LED strips can be seen pointing towards the camera of this
picture as the white stripe on the black tape on the mock-up
4.4.4 Result
A passing of the car driving at the real speed of around 35 km/h and with the
system speed set to 33 km/h is shown in figure 4.36 to 4.39. The first picture
52
Analysis and testing
4.36 shows the first rail and the LED strip getting activated. Figure 4.37 shows
the second rail and LED strip getting activated. In figure 4.38 the first rail and
LED strip get turned off again. Finally in figure 4.39 the second rail and LED
strip get turned off. Multiple passes were performed, and the system read the tag
ID, transferred this information over wifi to the laptop at the side of the road,
and activated the detection system in the road segments correctly every time. But
since the timing relied on the driver passing the mock-up at the same speed that
had been typed into the system, some of the passes did not have the correct turn
off timing.
Figure 4.36: The detection and turning on of the first rail segment
represented by the LED strip in front of the trailer tires.
Analysis and testing
Figure 4.37: The detection and turning on of the second rail segment represented by the LED strip in front of the trailer tires.
53
54
Analysis and testing
Figure 4.38: The timing of the first rail-computer (Arduino) turning
off the first rail segment represented by the LED strip behind
the trailer.
Analysis and testing
Figure 4.39: The timing of the second rail-computer (Arduino) turning off the second rail segment represented by the LED strip
behind the trailer.
55
56
Analysis and testing
Chapter
5
Discussion and future work
The final experiment shows that the software and hardware designed in this thesis
works for detecting and identifying a moving vehicle with a little help. By help, it
is meant here that the speed has to be manually given to the computer in the car.
A possible way to get the speed information from the car into the laptop running
our program would be to use an open OBD reader1 with a suitable API. This
was however not investigated due to the limited time frame for the project. The
problem of inputting the speed manually, as well as the too small test area and
the safety issues, since it was a place open to the public, restricted the posibility
of testing the complete setup at full speed. The fact that the RFID system is
specified to work at higher speeds, and that the earlier high speed test in section
4.2 went well, still gives some confidence that the complete system would work at
higher speeds as well. The final solution built is only a demonstrator for showing
a proof of concept of our idea. As such the components and code are not in any
way optimized. Software and hardware optimization gives even greater confidence
that the system would be robust in tests at higher speeds.
A drawback of the design chosen to work with is the use of an RFID system
developed by an external company. This system is built for trains and costs tens
of thousands of euros each, making it a very expensive solution. What the price
would be at the mass production of the scale road is not known and this could be
further investigated in the future.
The EMI experiments in section 4.3 point in the direction that the interference
should be possible to overcome and handle. But these experiments are made in a
model of how the real system might behave. How the real EMI environment will
be, with a 400 Ampere current flowing through the pickups, whose shape, behavior
and performance is unknown, is hard to model. It would be good to make further
experiments on the model with higher current values to see if the relation between
current and interference can be better determined.
1
OBD stands for "On-board diagnostics" and is a interface connection to a vehicle’s
self-diagnostic and reporting capability that now is standardized in most cars and often
can give real time information
57
58
Discussion and future work
To conclude it is deemed that all of the goals and aims set up for this thesis project
were met with a satisfying outcome.
Appendix
A
Program Code
A.1 Receiver Arduino Due: The rail road computer
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
# include < SPI .h >
# include < SD .h >
# include < Ethernet .h >
# define DEBUG 1
// metal
// # define RAIL6 1
// tree
# define RAIL7 1
// Ethernet
# ifdef RAIL7
byte mac [] = {
0 xDE , 0 xAD , 0 xBE , 0 xEF , 0 xFE , 0 x07
};
IPAddress ip (192 , 168 , 1 , 167) ;
# endif
# ifdef RAIL6
byte mac [] = {
0 xDE , 0 xAD , 0 xBE , 0 xEF , 0 xFE , 0 x06
};
IPAddress ip (192 , 168 , 1 , 166) ;
# endif
int port = 5217;
IPAddress server (192 , 168 , 1 , 33) ;
IPAddress preRail (192 , 168 , 1 , 166) ;
unsigned int localPort = 8888;
59
60
Program Code
33 // An EthernetUDP instance to let us send and receive packets
over UDP
34 EthernetUDP Udp ;
35
36 # define UDP_TX_PACKET 255
37 # define PRIME 0 X0F
38 # define SETID 0 X0A
39 # define GETID 0 x0B
40 # define TURNON 0 X0C
41 # define TURNOFF 0 x0D
42 # define ACKPRIME 0 x06
43 # define ACKSETID 0 X05
44 # define ACKGETID 0 x04
45 # define ACKTURNON 0 X03
46 # define ACKTURNOFF 0 x02
47 # define PING 0 x01
48
49 char turnOffMsg []={ ’? ’ , ’0 ’ , ’D ’ , ’0 ’ , ’1 ’ , ’0 ’ , ’1 ’ , ’K ’ };
50
51 byte lastMsgNbr ;
52 byte tagId [] = {0 x00 ,0 x00 ,0 x00 ,0 x00 };
53 byte data [257];
54 byte dataOut [257];
55 byte dataLength =0;
56 byte stage = 0;
57 byte hexStage =0;
58 unsigned long etherPreTime =0;
59 volatile boolean primed =0;
60
61 # define LED1 53
62 # define LED2 51
63 # define LED3 49
64 # define LED4 47
65 # define LED_CAR_PIN 7
66 # define LED_STRIPE_PIN 5
67 # define FEQ_PIN 6
68 # define AMP_PIN A0
69 # define AMP_HYST 100
70 # define maxAmpInit 600
71 # define minAmpInit 1000
72
73 # ifdef RAIL6
74
// RailInMetal
75 # define ampTop 1200
76 # define ampMid 800
77 # define ampBot 400
78 # endif
79
80 # ifdef RAIL7
81
// Rail on tree
82 # define ampTop 1800
Program Code
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
# define ampMid 1400
# define ampBot 1000
# endif
volatile boolean testLedToggle ;
volatile int errorFlag ;
File root ;
const int chipSelectSD = 4;
char filePrefix [] = " dr5a " ;
char fileName [16];
int fileNbrH =0;
int fileNbrL =0;
char fileEnd [] = " . txt " ;
volatile int pasTimerReset ;
volatile int sendTurnOff =0;
unsigned long fF , fR , sF , sR ;
boolean flagDetect = false ; // Detect
boolean flagCollectData = false ;
boolean flagCarDetect = false ;
volatile int stateCarPassed ;
volatile int lastState ;
volatile int nextInt ;
volatile int nextLow ;
# define BUFFER_SIZE 8 // 8=8 samples mean value . compered at
68 khz
109 # define BUFFER_SIZE_BINDEX 3
110 uint16_t buf [ BUFFER_SIZE ];
111
112 int val ;
113 int maxAmp ;
114 int maxAmpHalf ;
115 int minAmp ;
116 int ampState ;
117 int oldAmpState ;
118 int ampDetectHigh =0;
119 int ampDetectLow =0;
120 int ampFailDetect =0;
121 const int twoFactHighLow = 1; // high > 1^2 * low
122 # define NBR_STATE 8
123 unsigned long ampStateTime [ NBR_STATE ];
124 unsigned long ampDeltaLowTime ;
125 unsigned long ampDeltaHighTimeDiv ;
126 unsigned long ampStartTime ;
127 unsigned long ampNowTime ;
128 unsigned long ampLastTime ;
129 unsigned long ampDeltaRise ;
130 unsigned long ampDeltaFall ;
131 int ampCarDetect ;
132
61
62
Program Code
133 unsigned long timeTest =0;
134 unsigned long timeTestS =0;
135
136 static __inline__ void digitalWriteDirect ( int pin , boolean val
){
137
// http :// forum . arduino . cc / index . php ? topic =175617.0
138
if ( val ) g_APinDescription [ pin ]. pPort -> PIO_SODR =
g_APinDescription [ pin ]. ulPin ;
139
else
g_APinDescription [ pin ]. pPort -> PIO_CODR =
g_APinDescription [ pin ]. ulPin ;
140 }
141
142
143
144 void InitsdLogger () {
145
/*
146
The circuit :
147
* SD card attached to SPI bus as follows :
148
** MOSI - pin 11
149
** MISO - pin 12
150
** CLK - pin 13
151
** CS - pin 4
152
*/
153
// see if the card is present and can be initialized :
154
if (! SD . begin ( chipSelectSD ) ) {
155
errorFlag =1;
156
digitalWriteDirect ( LED1 , LOW ) ;
157
digitalWriteDirect ( LED4 , HIGH ) ;
158
// don ’t do anything more :
159
return ;
160
}
161
fileNbrL =0;
162
fileNbrH =0;
163
sprintf ( fileName , " % s % d % s " , filePrefix , fileNbrL , fileEnd ) ;
164
while ( SD . exists ( fileName ) ) {
165
digitalWriteDirect ( LED3 , HIGH ) ;
166
fileNbrL ++;
167
if ( fileNbrL >7) {
168
fileNbrH +=10;
169
fileNbrL =0;
170
}
171
int i = fileNbrL + fileNbrH ;
172
sprintf ( fileName , " % s % d % s " , filePrefix , ( i ) , fileEnd ) ;
173
174
}
175
digitalWriteDirect ( LED3 , LOW ) ;
176 }
177 void ledCount ( int count ) {
178
switch ( count )
179
{
180
case 0:
Program Code
63
181
di gitalWriteDirect ( LED4 , LOW ) ;
182
di gitalWriteDirect ( LED3 , LOW ) ;
183
di gitalWriteDirect ( LED2 , LOW ) ;
184
break ;
185
case 1:
186
di gitalWriteDirect ( LED4 , HIGH ) ;
187
di gitalWriteDirect ( LED3 , LOW ) ;
188
di gitalWriteDirect ( LED2 , LOW ) ;
189
break ;
190
case 2:
191
di gitalWriteDirect ( LED4 , LOW ) ;
192
di gitalWriteDirect ( LED3 , HIGH ) ;
193
di gitalWriteDirect ( LED2 , LOW ) ;
194
break ;
195
case 3:
196
di gitalWriteDirect ( LED4 , HIGH ) ;
197
di gitalWriteDirect ( LED3 , HIGH ) ;
198
di gitalWriteDirect ( LED2 , LOW ) ;
199
break ;
200
case 4:
201
di gitalWriteDirect ( LED4 , LOW ) ;
202
di gitalWriteDirect ( LED3 , LOW ) ;
203
di gitalWriteDirect ( LED2 , HIGH ) ;
204
break ;
205
case 5:
206
di gitalWriteDirect ( LED4 , HIGH ) ;
207
di gitalWriteDirect ( LED3 , LOW ) ;
208
di gitalWriteDirect ( LED2 , HIGH ) ;
209
break ;
210
case 6:
211
di gitalWriteDirect ( LED4 , LOW ) ;
212
di gitalWriteDirect ( LED3 , HIGH ) ;
213
di gitalWriteDirect ( LED2 , HIGH ) ;
214
break ;
215
case 7:
216
di gitalWriteDirect ( LED4 , HIGH ) ;
217
di gitalWriteDirect ( LED3 , HIGH ) ;
218
di gitalWriteDirect ( LED2 , HIGH ) ;
219
break ;
220
}
221 }
222
223 void InitTimerFast ( Tc * tc , uint32_t channel , IRQn_Type irq ,
uint32_t time100us )
224 // http :// ko7m . blogspot . se /2015/01/ arduino - due - timers - part -1.
html
225 {
226
p m c _ set_writeprotect ( false ) ;
227
p m c _ enabl e_per iph_cl k ( irq ) ;
228
// clock2 is /8 and clock4 is /128
229
TC_Configure ( tc , channel , TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC
64
230
Program Code
| TC_CMR_TCCLKS_TIMER_CLOCK3 );
uint32_t rc = 263 * time100us ; // VARIANT_MCK / 32 / 10000 *
time100us ;
TC_SetRC ( tc , channel , rc ) ;
// TC_Start ( tc , channel ) ;
tc - > TC_CHANNEL [ channel ]. TC_IER = TC_IER_CPCS ;
tc - > TC_CHANNEL [ channel ]. TC_IDR =~( TC_IER_CPCS ) ;
NVIC_EnableIRQ ( irq ) ;
231
232
233
234
235
236 }
237 void InitTimerSlow ( Tc * tc , uint32_t channel , IRQn_Type irq ,
uint32_t timeMilli )
238 // http :// ko7m . blogspot . se /2015/01/ arduino - due - timers - part -1.
html
239 {
240
pmc_set_writeprotect ( false ) ;
241
pmc _enabl e_peri ph_cl k ( irq ) ;
242
243
TC_Configure ( tc , channel , TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC
| TC_CMR_TCCLKS_TIMER_CLOCK5 );
244
uint32_t rc = 32 * timeMilli ; // 32000 / 1000 * timeMilli ;
245
TC_SetRC ( tc , channel , rc ) ;
246
// TC_Start ( tc , channel ) ;
247
tc - > TC_CHANNEL [ channel ]. TC_IER = TC_IER_CPCS ;
248
tc - > TC_CHANNEL [ channel ]. TC_IDR =~( TC_IER_CPCS ) ;
249
NVIC_EnableIRQ ( irq ) ;
250 }
251 void AdcInit ()
252 // http :// nicecircuits . com / playing - with - analog - to - digital converter - on - arduino - due /
253 {
254
// Setup all registers
255
pmc _enabl e_per iph_cl k ( ID_ADC ) ; // To use peripheral , we must
enable clock distributon to it
256
adc_init ( ADC , SystemCoreClock , ADC_FREQ_MAX ,
ADC_STARTUP_FAST ) ; // initialize
ADC_FREQ_MIN =20 ksample
ADC_FREQ_MAX =544 ksample
257
adc _disab le_in terrup t ( ADC , 0 xFFFFFFFF ) ;
258
adc_set_resolution ( ADC , ADC_10_BITS ) ;
259
a d c_ c o nf i g ur e _ po w e r_ s a ve ( ADC , 0 , 0) ; // Disable sleep
260
adc_configure_timing ( ADC , 0 , ADC_SETTLING_TIME_3 , 1) ; // Set
timings - standard values
261
adc_set_bias_current ( ADC , 1) ; // Bias current - maximum
performance over current consumption
262
adc_stop_sequencer ( ADC ) ; // not using it
263
adc_disable_tag ( ADC ) ; // it has to do with sequencer , not
using it
264
adc_disable_ts ( ADC ) ; // deisable temperature sensor
265
a d c _ d i s a b l e _ c h a n n e l _ d i f f e r e n t i a l _ i n p u t ( ADC , ADC_CHANNEL_7 ) ;
// pin A0
266
adc _confi gure_ trigge r ( ADC , ADC_TRIG_SW , 1) ; // triggering
from software , freerunning mode
Program Code
267
268
65
a d c _ d is a bl e_ a ll _c ha n ne l ( ADC ) ;
ad c_ enable_channel ( ADC , ADC_CHANNEL_7 ) ; // just one channel
enabled
269
270
// configure Peripheral DMA
271
272 }
273
274 // the setup routine runs once when you press reset :
275 void setup () {
276
sendTurnOff =0;
277
errorFlag =0;
278
pinMode ( FEQ_PIN , INPUT ) ;
279
pinMode ( AMP_PIN , INPUT ) ;
280
pinMode ( LED_CAR_PIN , OUTPUT ) ;
281
pinMode ( LED_STRIPE_PIN , OUTPUT ) ;
282
// pinMode (13 , OUTPUT ) ;
283
284
pinMode (39 , OUTPUT ) ;
285
digitalWrite (39 , LOW ) ;
286
testLedToggle = LOW ;
287
288
289
290
InitTimerSlow ( TC2 ,1 , TC7_IRQn , 500) ; // used for TimerReset
. last variabel : time [ ms ]
291
InitTimerFast ( TC2 , 2 , TC8_IRQn , 1800) ; // used for
TimerNoFreq . last variabel : time [ ms /10]
292
pasTimerReset =0;
293
294
295
AdcInit () ;
296
adc_start ( ADC ) ;
297
pinMode ( LED1 , OUTPUT ) ;
298
pinMode ( LED2 , OUTPUT ) ;
299
pinMode ( LED3 , OUTPUT ) ;
300
pinMode ( LED4 , OUTPUT ) ;
301
digitalWrite ( LED_CAR_PIN , LOW ) ;
302
digitalWrite ( LED_STRIPE_PIN , LOW ) ;
303
clearFreqState () ;
304
clearAmpState () ;
305
di gi talWriteDirect ( LED1 , HIGH ) ;
306
307
# ifdef DEBUG
308
Serial . begin (115200) ;
309
# endif
310
311
delay (100) ;
312
InitsdLogger () ;
313
PDC_ADC - > PERIPH_RPR = ( uint32_t ) buf ; // address of buffer
314
PDC_ADC - > PERIPH_RCR = BUFFER_SIZE ;
66
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
Program Code
PDC_ADC - > PERIPH_PTCR = PERIPH_PTCR_RXTEN ; // enable receive
delay (1000) ;
// start the Ethernet connection :
Ethernet . begin ( mac , ip ) ;
Udp . begin ( localPort ) ;
lastMsgNbr = 0;
}
void clearFreqState () {
lastState = -1;
stateCarPassed = -1;
nextInt =0;
nextLow =0;
fR = fF = sR = sF =0;
}
void clearAmpState () {
minAmp = minAmpInit ;
maxAmp = maxAmpInit ;
ampState =0;
oldAmpState =0;
ampDetectHigh =0;
ampDetectLow =0;
ampFailDetect =0;
digitalWriteDirect ( LED4 , LOW ) ;
digitalWriteDirect ( LED3 , LOW ) ;
digitalWriteDirect ( LED2 , LOW ) ;
// digitalWriteDirect ( LED1 , LOW ) ;
for ( int i =0; i < NBR_STATE ; i ++) {
ampStateTime [ i ]=0;
}
ampDeltaLowTime =0;
ampDeltaHighTimeDiv =0;
ampStartTime =0;
ampNowTime =0;
ampCarDetect =0;
// digitalWriteDirect ( LED_CAR_PIN , LOW ) ;
// digitalWriteDirect ( LED_STRIPE_PIN , LOW ) ;
ampDeltaRise =0;
ampDeltaFall =0;
ledCount ( fileNbrL ) ;
}
void startTimerReset () {
// Start and reset timmer to reset statemachine when no
change for long
362
// uses timmer TC2 chanel 1
363
TC2 - > TC_CHANNEL [1]. TC_CCR &= ~ TC_CCR_CLKDIS ;
364
TC2 - > TC_CHANNEL [1]. TC_CCR |=
Program Code
365
366
TC_CCR_CLKEN | // enables the clock if CLKDIS is not 1
TC_CCR_SWTRG ; // the counter is reset and the clock is
started
TC_GetStatus ( TC2 , 1) ;
di gi talWriteDirect ( LED1 , LOW ) ;
67
367
368
369
370 }
371
372 void startTurnOffTimer () {
373
// uses timmer TC2 chanel 2
374
TC2 - > TC_CHANNEL [2]. TC_CCR &= ~ TC_CCR_CLKDIS ;
375
TC2 - > TC_CHANNEL [2]. TC_CCR |=
376
TC_CCR_CLKEN | // enables the clock if CLKDIS is not 1
377
TC_CCR_SWTRG ; // the counter is reset and the clock is
started
378
TC_GetStatus ( TC2 , 2) ;
379 }
380 void s t a r t T i m e r S e nd T u r n O f f B a c k () {
381
// uses timmer TC2 chanel 0
382
TC2 - > TC_CHANNEL [0]. TC_CCR &= ~ TC_CCR_CLKDIS ;
383
TC2 - > TC_CHANNEL [0]. TC_CCR |=
384
TC_CCR_CLKEN | // enables the clock if CLKDIS is not 1
385
TC_CCR_SWTRG ; // the counter is reset and the clock is
started
386
TC_GetStatus ( TC2 , 0) ;
387 }
388
389 // the loop routine runs over and over again forever :
390 void loop () {
391
ethernet () ;
392
393
if ( primed ) { // start recive if primed
394
if (( adc_get_status ( ADC ) & ADC_ISR_ENDRX ) != 0) { // waiting
for buffer to fill upp (544 ksample /16=18 khz
395
ampCalcFix () ;
396
PDC_ADC - > PERIPH_RPR = ( uint32_t ) buf ; // address of
buffer
397
PDC_ADC - > PERIPH_RCR = BUFFER_SIZE ;
398
PDC_ADC - > PERIPH_PTCR = PERIPH_PTCR_RXTEN ; // enable
receive
399
}
400
}
401
// ampPrint () ;
402
if ( pasTimerReset ) {
403
clearAmpState () ;
404
pasTimerReset =0;
405
primed =0;
406
}
407
readCommand () ;
408
if ( sendTurnOff ) {
409
sendTurnOff =0;
68
Program Code
410
sendMsg ( preRail , turnOffMsg ) ;
411
# ifdef DEBUG
412
Serial . print ( " TurnOff sent " ) ;
413
# endif
414
}
415 }
416 void ethernet () {
417
char packetBuffer [ UDP_TX_PACKET ]={};
418
noInterrupts () ;
419
int packetSize = Udp . parsePacket () ;
420
interrupts () ;
421
int startIndex =0;
422
if ( packetSize )
423
{
424
IPAddress remote = Udp . remoteIP () ;
425
Udp . read ( packetBuffer , UDP_TX_PACKET ) ;
426
char checksum = 0;
427
for ( int i =0; i < packetSize ; i ++) {
428
checksum ^= packetBuffer [ i ];
429
if ( packetBuffer [ i ]== ’? ’) {
430
startIndex = i ;
431
# ifdef DEBUG
432
Serial . print ( " StartIndex : " ) ;
433
Serial . println ( startIndex ) ;
434
# endif
435
}
436
}
437
if ( packetBuffer [0]== ’? ’) {
438
if (! checksum ) {
439
data [0] = hexDecode ( packetBuffer [1]) < <4; // *16
440
data [0] += hexDecode ( packetBuffer [2]) ;
441
if (( data [0]== lastMsgNbr ) && (( data [0] & 0 xF0 ) != 0) ) {
442
# ifdef DEBUG
443
Serial . print ( " same : " ) ;
444
# endif
445
} else {
446
data [1] = hexDecode ( packetBuffer [3]) < <4; // *16
447
data [1] += hexDecode ( packetBuffer [4]) ;
448
for ( int i = 0; i < ( data [1] < <1) ; i +=2) {
449
# ifdef DEBUG
450
Serial . print ( " index : " ) ;
451
Serial . println ( i ) ;
452
# endif
453
data [2+( i > >1) ] = hexDecode ( packetBuffer [5+ i ])
< <4; // *16
454
data [2+( i > >1) ] += hexDecode ( packetBuffer [6+ i ]) ;
455
}
456
if ( packetBuffer [(4+ data [1]) < <1]) {
457
# ifdef DEBUG
458
Serial . println ( " correct ! " ) ;
459
# endif
Program Code
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
69
}
instruction () ;
lastMsgNbr = packetBuffer [1];
}
# ifdef DEBUG
Serial . println ( " awnser " ) ;
# endif
Udp . beginPacket ( Udp . remoteIP () , Udp . remotePort () ) ;
Udp . write ( ’! ’) ;
checksum = ’! ’;
for ( int i = 0; i < dataOut [1] + 2; i ++)
{
# ifdef DEBUG
Serial . print (( char ) hexEncode ( dataOut [ i ] > >4) ) ; //
/16
Serial . print (( char ) hexEncode ( dataOut [ i ] & 0 xF ) ) ; //
%16
# endif
checksum ^= hexEncode ( dataOut [ i ] > >4) ;
checksum ^= hexEncode ( dataOut [ i ] & 0 x0F ) ;
Udp . write ( hexEncode ( dataOut [ i ] > >4) ) ; // /16
Udp . write ( hexEncode ( dataOut [ i ] & 0 x0F ) ) ; // %16
}
475
476
477
478
479
480
481
482
Udp . write ( checksum ) ;
483
Udp . endPacket () ;
484
// lastInstruction = millis () ;
485
# ifdef DEBUG
486
Serial . println ( " done " ) ;
487
# endif
488
}
489
} else if ( packetBuffer [0]== ’! ’) {
490
// TODO send again if this is not recived after sendMsg .
491
# ifdef DEBUG
492
Serial . println ( " gotAwnser " ) ;
493
# endif
494
}
495
}
496
497
498 }
499 byte hexDecode ( byte c )
500 {
501
if ( c >= ’0 ’ && c <= ’9 ’)
502
{
503
return c - ’0 ’;
504
}
505
else if ( c >= ’a ’ && c <= ’f ’)
506
{
507
return c - ’a ’ + 10;
508
}
70
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
Program Code
else if ( c >= ’A ’ && c <= ’F ’)
{
return c - ’A ’ + 10;
}
else
{
return 0;
}
}
byte hexEncode ( byte n , boolean cap )
{
if ( n >= 0 && n <= 9)
{
return n + ’0 ’;
}
else if ( n >= 10 && n <= 15)
{
if ( cap )
{
return n - 10 + ’A ’;
}
else
{
return n - 10 + ’a ’;
}
}
else
{
return ’0 ’;
}
}
byte hexEncode ( byte n )
{
return hexEncode (n , true ) ;
}
void instruction () {
# ifdef DEBUG
Serial . print ( " msg recived . lenght " ) ;
Serial . println ( data [1]) ;
for ( int i = 0; i < data [1] + 2; i ++)
{
Serial . print (( char ) hexEncode ( data [ i ] > >4) ) ; // /16
Serial . print (( char ) hexEncode ( data [ i ] & 0 xF ) ) ; // %16
}
Serial . println ( " \ n msg end " ) ;
# endif
if ( data [0]== SETID ) {
Program Code
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
if ( data [1]==4) {
# ifdef DEBUG
Serial . println ( " setId start " ) ;
# endif
for ( int i =0; i < data [1]; i ++) {
tagId [ i ]= data [ i +2];
# ifdef DEBUG
Serial . println ( tagId [ i ]) ;
# endif
}
dataOut [0]= ACKSETID ;
dataOut [1]=1;
dataOut [2]= PRIME ;
# ifdef DEBUG
Serial . println ( " setId done " ) ;
# endif
}
}
if ( data [0]== GETID ) {
dataOut [0]= ACKGETID ;
dataOut [1]=4;
for ( int i =0; i < dataOut [1]; i ++) {
dataOut [ i +2]= tagId [ i ];
# ifdef DEBUG
Serial . println ( dataOut [ i +2]) ;
# endif
}
# ifdef DEBUG
Serial . println ( " getId done " ) ;
# endif
}
if ( data [0]== PRIME ) {
primed =1;
dataOut [0]= ACKPRIME ;
# ifdef DEBUG
Serial . println ( " priming " ) ;
# endif
if ( data [1]==2) {
int onTime = (( data [2] & 0 XFF ) << 8) + (( data [3])
& 0 XFF ) ;
# ifdef DEBUG
Serial . println ( onTime ) ;
# endif
InitTimerFast ( TC2 , 2 , TC8_IRQn , onTime ) ; // used
for TimerTurnoff . last variabel : time [ ms /10]
onTime = onTime > >3;
InitTimerSlow ( TC2 ,1 , TC7_IRQn , onTime ) ; // used
for TimerReset . last variabel : time [ ms ] > >3
makes wait time : 10/8=1. times longer
startTimerReset () ;
71
72
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
Program Code
dataOut [1]=1;
dataOut [2]=0;
InitTimerFast ( TC2 , 0 , TC6_IRQn , onTime ) ; // used
for TimerTurnoff . last variabel : time [ ms /10]
# ifdef DEBUG
Serial . println ( " time to send turnoff " ) ;
Serial . println ( onTime ) ;
# endif
}
}
if ( data [0]== TURNON ) {
# ifdef DEBUG
Serial . println ( " turning on " ) ;
# endif
digitalWriteDirect ( LED_CAR_PIN , HIGH ) ;
digitalWriteDirect ( LED_STRIPE_PIN , HIGH ) ;
dataOut [0]= ACKTURNON ;
dataOut [1]=1;
dataOut [2]= TURNON ;
}
if ( data [0]== TURNOFF ) {
# ifdef DEBUG
Serial . println ( " turning off " ) ;
# endif
dataOut [0]= ACKTURNOFF ;
dataOut [1]=0 x01 ;
dataOut [2]= TURNOFF ;
digitalWriteDirect ( LED_CAR_PIN , LOW ) ;
digitalWriteDirect ( LED_STRIPE_PIN , LOW ) ;
}
}
void sendMsg ( IPAddress rec , char msg []) {
Udp . beginPacket ( rec , localPort ) ;
Udp . write ( msg ,8) ;
Udp . endPacket () ;
}
void readCommand () {
if ( Serial . available () > 0) {
int command = Serial . parseInt () ;
if ( command ==0) {
Serial . println ( " 0= help , 1= list , 2= readCurentFile , 3=
chose file to read , 4= eraseAll " ) ;
} else if ( command ==1) {
char tempName [16];
Serial . println ( " ------ print list - - - - - - - " ) ;
int i = 0;
int ii = 0;
Program Code
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
73
sprintf ( tempName , " % s % d % s " , filePrefix , i , fileEnd ) ;
while ( SD . exists ( tempName ) ) {
Serial . print ( "
");
Serial . println ( tempName ) ;
i ++;
if (i >7) {
ii +=10;
}
int j = ii + i ;
sprintf ( tempName , " % s % d % s " , filePrefix , j , fileEnd ) ;
}
Serial . println ( " ------ Done ! - - - - - - -\ n \ n " ) ;
} else if ( command ==2) {
File tempFile = SD . open ( fileName ) ;
if ( tempFile ) {
Serial . println ( " - - - - - - - - - - - - - - - - - - - - - - " ) ;
Serial . println ( fileName ) ;
// read from the file until there ’s nothing else in it
:
while ( tempFile . available () ) {
Serial . write ( tempFile . read () ) ;
}
// close the file :
tempFile . close () ;
Serial . println ( " - - - - - - - - - - - - - - - - - - - - - -\ n \ n " ) ;
} else {
// if the file didn ’t open , print an error :
Serial . println ( " error opening file " ) ;
}
} else if ( command ==3) {
char tempName [16];
Serial . println ( " Read file number : " ) ;
while ( Serial . available () ==0) {
}
int i = Serial . parseInt () ;
if ( i ==0) {
return ;
}
sprintf ( tempName , " % s % d % s " , filePrefix , i , fileEnd ) ;
if ( SD . exists ( tempName ) ) {
File tempFile = SD . open ( tempName ) ;
if ( tempFile ) {
Serial . println ( " - - - - - - - - - - - - - - - - - - - - - - " ) ;
Serial . println ( tempName ) ;
// read from the file until there ’s nothing else in
it :
while ( tempFile . available () ) {
74
Program Code
705
Serial . write ( tempFile . read () ) ;
706
}
707
// close the file :
708
tempFile . close () ;
709
Serial . println ( " - - - - - - - - - - - - - - - - - - - - - -\ n \ n " ) ;
710
} else {
711
// if the file didn ’t open , print an error :
712
Serial . println ( " error opening file " ) ;
713
}
714
} else {
715
Serial . println ( " No file with that name exists " ) ;
716
}
717
718
719
} else if ( command ==4) {
720
char tempName [16];
721
Serial . println ( " remove All ? ( y / n ) " ) ;
722
while ( Serial . available () ==0) {
723
}
724
int temp = Serial . read () ;
725
Serial . println ( temp ) ;
726
if ( temp != ’y ’) {
727
Serial . println ( " Aborted " ) ;
728
return ;
729
} int i = 0;
730
int ii = 0;
731
sprintf ( tempName , " % s % d % s " , filePrefix , i , fileEnd ) ;
732
while ( SD . exists ( tempName ) ) {
733
SD . remove ( tempName ) ;
734
i ++;
735
if (i >7) {
736
ii +=10;
737
}
738
int j = ii + i ;
739
sprintf ( tempName , " % s % d % s " , filePrefix , j , fileEnd ) ;
740
}
741
Serial . println ( " Done removing " ) ;
742
}
743
}
744 }
745
746
747
748 boolean sdLog ( char dataString []) {
749
// open the file . note that only one file can be open at a
time ,
750
// so you have to close this one before opening another .
751
File dataFile = SD . open ( fileName , FILE_WRITE ) ;
752
753
// if the file is available , write to it :
754
if ( dataFile ) {
Program Code
755
dataFile . println ( dataString ) ;
756
dataFile . close () ;
757
return 1;
758
}
759
// if the file isn ’t open , pop up an error :
760
else {
761
di gitalWriteDirect ( LED1 , LOW ) ;
762
return 0;
763
}
764
765 }
766 void ampCalcFix () {
767
val =0;
768
for ( int i =0; i < BUFFER_SIZE ; i ++) {
769
val += buf [ i ];
770
}
771
val = val > > BUFFER_SIZE_BINDEX ;
772
if ( val < minAmp ) {
773
minAmp = val ;
774
}
775
if ( maxAmp < val ) {
776
maxAmp = val ;
777
}
778
// /
779
if (( ampState ==0) && ( ampMid < val ) ) {
780
# ifdef DEBUG
781
Serial . println ( " StartDetect " ) ;
782
// Serial . println ( startIndex ) ;
783
# endif
784
maxAmp = val ;
785
ampStartTime = micros () ;
786
ampStateTime [ ampState ]= ampStartTime ;
787
startTimerReset () ;
788
ampState =1;
789
minAmp = val ; // to find new minAmp
790
digitalWriteDirect ( LED4 , HIGH ) ;
791
digitalWriteDirect ( LED3 , LOW ) ;
792
digitalWriteDirect ( LED2 , LOW ) ;
793
// /
794
} else if (( ampState ==1) && ( ampTop < val ) ) {
795
ampNowTime = micros () ;
796
ampStateTime [ ampState ] = ampNowTime ;
797
ampState =2;
798
ampDeltaRise = ampNowTime - ampStartTime ;
799
digitalWriteDirect ( LED4 , LOW ) ;
800
digitalWriteDirect ( LED3 , HIGH ) ;
801
// digitalWriteDirect ( LED2 , LOW ) ;
802
// ^
803
} else if ( ampState ==2 && ( val + AMP_HYST ) < maxAmp ) {
804
ampDetectHigh = maxAmp ;
805
maxAmpHalf = maxAmp > >2;
75
76
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
Program Code
ampStateTime [ ampState ] = micros () ;
ampState =3;
digitalWriteDirect ( LED4 , HIGH ) ;
// digitalWriteDirect ( LED3 , HIGH ) ;
// digitalWriteDirect ( LED2 , LOW ) ;
// \
} else if ( ampState ==3 && ( val < ampMid ) ) {
ampNowTime = micros () ;
ampLastTime = ampNowTime ;
ampStateTime [3] = ampNowTime ;
ampDeltaHighTimeDiv = ( ampNowTime - ampStartTime ) ; // >>
twoFactHighLow ;
// FailDetect 1 To short High !
if ( ampDeltaHighTimeDiv <100) {
ampFailDetect =1;
ampState =20;
return ;
}
ampState =4;
// ampDeltaHighTimeDiv = ampDeltaHighTimeDiv *10; // fix
digitalWriteDirect ( LED4 , LOW ) ;
digitalWriteDirect ( LED3 , LOW ) ;
digitalWriteDirect ( LED2 , HIGH ) ;
// \+
//
} else if (( ampState ==3 || ampState ==4) && val <
maxAmpHalf ) {
//
ampStateTime [4] = micros () ;
//
ampState =5;
//
digitalWriteDirect ( LED4 , HIGH ) ;
//
// digitalWriteDirect ( LED3 , LOW ) ;
//
// digitalWriteDirect ( LED2 , HIGH ) ;
//
// v
} else if (( ampState ==4) && ( val < ampBot ) ) {
ampNowTime = micros () ;
ampStateTime [ ampState ] = ampNowTime ;
ampDeltaFall = ampNowTime - ampLastTime ;
ampState =5;
digitalWriteDirect ( LED4 , HIGH ) ;
digitalWriteDirect ( LED3 , LOW ) ;
// digitalWriteDirect ( LED2 , HIGH ) ;
// Faildetect 2 to long DeltaFall
if ( ampDeltaRise < ampDeltaFall ) {
ampState =20;
ampFailDetect =2;
}
} else if ( ampState ==5 && ( ampMid < val ) ) {
ampNowTime = micros () ;
ampStateTime [ ampState ]= ampNowTime ;
ampDeltaLowTime = ( ampNowTime - ampLastTime ) ;
ampDetectLow = minAmp ;
Program Code
855
ampState =6;
856
857
digitalWriteDirect ( LED4 , LOW ) ;
858
digitalWriteDirect ( LED3 , HIGH ) ;
859
} else if ( ampState ==5) {
860 // Faildetect 3 to long low
861
unsigned long currentMillis = micros () ;
862
if (( currentMillis - ampNowTime ) >=
ampDeltaHighTimeDiv ) {
863
ampState =20;
864
ampFailDetect =3;
865
ampStateTime [ ampState ]= currentMillis ;
866
}
867
// /
868
} else if ( ampState ==6 && ampTop < val ) {
869 // Correct Starting rail .
870
if ( ampDeltaLowTime < ampDeltaHighTimeDiv ) {
871
digitalWriteDirect ( LED_CAR_PIN , HIGH ) ;
872
digitalWriteDirect ( LED_STRIPE_PIN , HIGH ) ;
873
ampCarDetect =1;
874
startTurnOffTimer () ;
875
s t a r t Ti m e r S e n d T u rn O f f B a c k () ;
876
# ifdef DEBUG
877
Serial . println ( " detect " ) ;
878
// Serial . println ( startIndex ) ;
879
# endif
880
}
881
ampState =7;
882
digitalWriteDirect ( LED4 , HIGH ) ;
883
ampStateTime [6]= micros () ;
884
// digitalWriteDirect ( LED3 , HIGH ) ;
885
// digitalWriteDirect ( LED2 , HIGH ) ;
886
887
} else if (( ampState ==7) && ( val < ampBot ) ) {
888
ampStateTime [ ampState ] = micros () ;
889
ampState =0;
890
primed =0;
891
// digitalWriteDirect ( LED_STRIPE_PIN , LOW ) ;
892
// digitalWriteDirect ( LED_CAR_PIN , LOW ) ;
893
digitalWriteDirect ( LED4 , LOW ) ;
894
digitalWriteDirect ( LED3 , LOW ) ;
895
digitalWriteDirect ( LED2 , LOW ) ;
896
}
897
898 }
899 void ampPrint () {
900
if ( ampState ==20) {
901
char dataString [512] = " " ;
902
sprintf ( dataString , " Fail % d ! at System time s0 : % u uS
Lowest detect : % d Highest detect : % d " , ampFailDetect ,
ampStateTime [0] , minAmp , maxAmp ) ;
77
78
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
Program Code
if ( ampFailDetect ==2)
sprintf ( dataString , " % s dRise : %u , dFall : % u " , dataString ,
ampDeltaRise , ampDeltaFall ) ;
for ( int i = 1; i < NBR_STATE ; i ++) {
sprintf ( dataString , " %s , s %d - s0 : % u uS " , dataString , i
, ( ampStateTime [ i ] - ampStateTime [0]) ) ;
}
// Serial . println ( dataString ) ;
if (! sdLog ( dataString ) ) {
// Serial . println (" fail to write 2") ;
}
clearAmpState () ;
} else if ( pasTimerReset ) {
char dataString [256] = " " ;
if (( ampCarDetect ) ) {
// # define NBR_STATE 4
// unsigned long ampStateTime [4];
if ( ampCarDetect ) {
sprintf ( dataString , " Correct ! " ) ;
}
sprintf ( dataString , " % s Full Detect at System time s0 : % u
uS , dRise : %u , dFall : % u " , dataString , ampStateTime
[0] , ampDeltaRise , ampDeltaFall ) ;
for ( int i = 1; i < NBR_STATE ; i ++) {
sprintf ( dataString , " %s , s %d - s0 : % u uS " , dataString , i
, ( ampStateTime [ i ] - ampStateTime [0]) ) ;
}
sprintf ( dataString , " %s , time low between loobes : % u uS ,
lobMax : % d [ mV ] , min : % d [ mV ] " , dataString ,
ampDeltaLowTime , ampDetectHigh , ampDetectLow ) ;
// Serial . println ( dataString ) ;
if (! sdLog ( dataString ) ) {
// Serial . println (" fail to write 1") ;
}
} else {
sprintf ( dataString , " Fail ! detect at System time s0 : % u
uS Lowest detect : % d Highest detect : % d " ,
ampStateTime [0] , minAmp , maxAmp ) ;
for ( int i = 1; i < NBR_STATE ; i ++) {
sprintf ( dataString , " %s , s %d - s0 : % u uS " , dataString , i
, ( ampStateTime [ i ] - ampStateTime [0]) ) ;
}
// Serial . println ( dataString ) ;
if (! sdLog ( dataString ) ) {
// Serial . println (" fail to write 2") ;
}
}
clearAmpState () ;
pasTimerReset =0;
primed =0;
Program Code
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
}
}
// TC1 ch 0
void TC8_Handler ()
{
TC2 - > TC_CHANNEL [2]. TC_CCR &= ~ TC_CCR_CLKEN ;
TC2 - > TC_CHANNEL [2]. TC_CCR |= TC_CCR_CLKDIS ; // disable clock
// TC_Stop ( TC2 , 2) ;
TC_GetStatus ( TC2 , 2) ;
di gi ta lWriteDirect ( LED_CAR_PIN , LOW ) ;
di gi ta lWriteDirect ( LED_STRIPE_PIN , LOW ) ;
# ifdef DEBUG
Serial . print ( " TC8 timeout " ) ;
// Serial . println ( startIndex ) ;
# endif
}
// send turn off to previus rail
void TC6_Handler ()
{
TC2 - > TC_CHANNEL [0]. TC_CCR &= ~ TC_CCR_CLKEN ;
TC2 - > TC_CHANNEL [0]. TC_CCR |= TC_CCR_CLKDIS ; // disable clock
// TC_Stop ( TC2 , 2) ;
TC_GetStatus ( TC2 , 0) ;
# ifdef DEBUG
Serial . print ( " SendingTurnOff " ) ;
// Serial . println ( startIndex ) ;
# endif
sendTurnOff =1;
// sendMsg ( preRail , turnOffMsg )
}
void TC7_Handler () {
TC2 - > TC_CHANNEL [1]. TC_CCR &= ~ TC_CCR_CLKEN ;
TC2 - > TC_CHANNEL [1]. TC_CCR |= TC_CCR_CLKDIS ; // disable clock
// TC_Stop ( TC2 , 2) ;
TC_GetStatus ( TC2 , 1) ;
stateCarPassed =10;
pasTimerReset =1;
// d ig italWriteDirect ( LED2 , LOW ) ;
di gi ta lWriteDirect ( LED_CAR_PIN , LOW ) ;
di gi ta lWriteDirect ( LED_STRIPE_PIN , LOW ) ;
di gi ta lWriteDirect ( LED1 , HIGH ) ;
# ifdef DEBUG
Serial . print ( " TC7 timeout " ) ;
// Serial . println ( startIndex ) ;
# endif
79
80
995 }
Program Code
Program Code
A.2 RSU
A.2.1 StartServerUDP.java
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
import
import
import
import
import
java . net . DatagramSocket ;
java . net . InetAddress ;
java . util . ArrayList ;
java . util . Scanner ;
java . util . concurrent . ConcurrentHashMap ;
public class StartServerUDP {
Scanner scan = new Scanner ( System . in ) ;
Monitor mon = new Monitor () ;
long startTime ;
long endTime ;
ConcurrentHashMap < String , RoadConnectionUDP > clientsList =
new ConcurrentHashMap < String , RoadConnectionUDP >() ;
/* *
* @param args
*/
public static void main ( String [] args ) {
// TODO Auto - generated method stub
new StartServerUDP () . run () ;
}
public void run () {
Monitor mon = new Monitor () ;
CarServerThread carS = new CarServerThread ( mon , 5123) ;
carS . start () ;
int tempInt =0;
int port =8888;
try {
RoadConnectionUDP client1 = new RoadConnectionUDP (
InetAddress . getByName ( " 192.168.1.166 " ) , port , mon ) ;
RoadConnectionUDP client2 = new RoadConnectionUDP (
InetAddress . getByName ( " 192.168.1.167 " ) , port , mon ) ;
client1 . start () ;
client2 . start () ;
clientsList . put ( " 0025806 " , client1 ) ;
clientsList . put ( " 0025807 " , client2 ) ;
RSU2Road rsu2road = new RSU2Road ( clientsList , mon ) ;
rsu2road . start () ;
} catch ( Exception e ) {
// TODO Auto - generated catch block
System . out . println ( " fail " ) ;
e . printStackTrace () ;
}
81
82
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
Program Code
int allTagids [] = {25806 ,25807 ,25809};
RoadConnectionUDP picked = null ;
while ( true ) {
if ( scan . hasNext () ) {
String myLine = scan . next () ;
switch ( myLine ) {
case " list " :
for ( String s : clientsList . keySet () ) {
System . out . println ( " tag : " + s + " : Adress = " +
clientsList . get ( s ) . toString () ) ;
}
break ;
case " pick " :
System . out . print ( " tagNumber : " ) ;
String pick = scan . next () ;
picked = clientsList . get ( pick ) ;
if ( picked != null ) {
System . out . println ( " picked index : " + pick + " : " + picked ) ;
}
break ;
case " setid " :
if ( picked != null ) {
System . out . print ( " id : " ) ;
picked . setTagId ( Integer . parseInt ( scan . next () ) ) ;
} else {
System . out . println ( " no connection picked " ) ;
}
break ;
case " getid " :
if ( picked != null ) {
System . out . println ( " picked . getTagId () " ) ;
} else {
System . out . println ( " no connection picked " ) ;
}
break ;
case " sendsetid " :
if ( picked != null ) {
System . out . print ( " id : " ) ;
picked . sendSetTagId ( Integer . parseInt ( scan . next () ) ) ;
} else {
System . out . println ( " no connection picked " ) ;
}
break ;
case " sendgetid " :
if ( picked != null ) {
picked . sendGetTagId () ;
Program Code
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
} else {
System . out . println ( " no connection picked " ) ;
}
break ;
case " prime " :
if ( picked != null ) {
System . out . print ( " time [ ms /10 = *100 us ]: " ) ;
int timeset = Integer . parseInt ( scan . next () ) ;
System . out . print ( " \ n " ) ;
if ( timeset >0) {
picked . sendPrime ( timeset ) ;
} else {
picked . sendPrime () ;
}
} else {
System . out . println ( " no connection picked " ) ;
}
break ;
case " stop " :
if ( picked != null ) {
picked . sendStop () ;
clientsList . remove ( picked ) ;
picked = null ;
} else {
System . out . println ( " no connection picked " ) ;
}
break ;
case " turnon " :
if ( picked != null ) {
picked . sendTurnON () ;
} else {
System . out . println ( " no connection picked " ) ;
}
break ;
case " turnoff " :
if ( picked != null ) {
picked . sendTurnOFF () ;
} else {
System . out . println ( " no connection picked " ) ;
}
break ;
case " close " :
mon . removeCar (0) ;
break ;
default :
printHelp () ;
break ;
}
}
83
84
145
146
147
148
149
150
151
152
153
154
155
156
157
158
Program Code
}
}
private void printHelp () {
System . out . println ( " ---------- Help - - - - - - - - - " ) ;
System . out . println ( " h / help
= Print a list of all commands (
THIS ) " ) ;
System . out . println ( " list
= Print a list of all connected " ) ;
System . out . println ( " pick
= pick connection in list to do : " )
;
System . out . println ( " setid id = setid in class " ) ;
System . out . println ( " getid
= getid from class " ) ;
System . out . println ( " sendsetid id = send setid to road " ) ;
System . out . println ( " sendgetid = send getid to to road .
update class " ) ;
System . out . println ( " stop
= disconnect client " ) ;
System . out . println ( " turnon = send getid to to road . update
class " ) ;
System . out . println ( " turnoff = send getid to to road .
update class " ) ;
159
160
System . out . println ( " ------- End Help - - - - - - - - - " ) ;
161
162
}
163
public void printConnected ( String s ) {
164
System . out . println ( s ) ;
165
}
166
167 }
A.2.2 Monitor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import
import
import
import
import
import
import
import
java . io . IOException ;
java . util . Iterator ;
java . util . Arrays ;
java . util . ArrayList ;
java . util . ListIterator ;
java . util . ArrayDeque ;
java . util . HashMap ;
java . util . Map ;
public class Monitor {
private Map < Integer , Car > carMap ;
private ArrayDeque < String [] > latestTagsDetected ;
private int curSizeTD = 0;
/* current size of
latestTagsDetected */
15 private int maxCars = 50;
16 private int nextAvailableID = 0;
17
18 public Monitor () {
19
carMap = new HashMap < Integer , Car >(10) ;
Program Code
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
la te st TagsDetected = new ArrayDeque < >() ;
}
/* called by RecThread when a new car client has connected */
public synchronized int addCar ( String id ) {
Car c = new Car ( id ) ;
carMap . put ( nextAvailableID , c ) ;
int softID = nextAvailableID ;
nextAvailableID = nextAvailableID % maxCars ;
notifyAll () ;
return softID ;
}
public synchronized void removeCar ( int id ) {
carMap . get ( id ) . setRemove ( true ) ;
notifyAll () ;
}
public synchronized boolean shouldContinue ( int id ) {
boolean a = carMap . get ( id ) . getRemove () ;
if ( a ) {
carMap . remove ( id ) ;
notifyAll () ;
}
return ! a ;
}
/* called by RecThread */
public synchronized void tagDetected ( String t1 , String t2 ) {
String [] ret = { t1 , t2 };
la te st TagsDetected . add ( ret ) ;
curSizeTD ++;
notifyAll () ;
}
/* called by RoadSendTestThread */
public synchronized String [] getDetectedTagID () {
while ( curSizeTD == 0) {
try {
wait () ;
} catch ( InterruptedException e ) {
System . out . println ( " Error : Couldn ’t wait : " + e . getMessage
() ) ;
}
}
curSizeTD - -;
return latestTagsDetected . poll () ;
}
63
64
65
66
67
68
69 /* Car is an inner class in Monitor */
85
86
Program Code
70
private class Car {
71
72
boolean remove ;
73
String ID ;
74
75
public Car ( String id ) {
76
remove = false ;
77
ID = id ;
78
}
79
80
public void setRemove ( boolean r ) {
81
remove = r ;
82
}
83
84
public boolean getRemove () {
85
return remove ;
86
}
87
88
public String getID () {
89
return ID ;
90
}
91
}
92 }
A.2.3 RoadConnectionUDP.java
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
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java . io . IOException ;
java . io . InputStream ;
java . io . OutputStream ;
java . io . PrintStream ;
java . io . U n s u p p o r t e d E n c o d i n g E x c e p t i o n ;
java . math . BigInteger ;
java . net . DatagramPacket ;
java . net . DatagramSocket ;
java . net . InetAddress ;
java . net . Socket ;
java . nio . ByteBuffer ;
java . nio . ByteOrder ;
java . util . Queue ;
java . util . concurrent . Concu rrent Linked Queue ;
java . util . concurrent . TimeUnit ;
java . util . concurrent . locks . Lock ;
public class RoadConnectionUDP extends Thread {
private
private
private
private
private
Queue < int [] > sendQue ;
DatagramSocket socket ;
InetAddress address ;
int port ;
int stage =0;
Program Code
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
private
private
private
private
private
int dataLength =0;
boolean hexStage = false ;
int [] data = new int [256];
byte [] dataIn = new byte [256];
Monitor mon ;
private int id =0;
private Object lock = new Object () ;
private int lastCarEnergyUsed =0;
private boolean newEnergyUsed = false ;
final private int PRIME =0 X0F ;
final private int SETID =0 X0A ;
final private int GETID =0 x0B ;
final private int TURNON =0 X0C ;
final private int TURNOFF =0 x0D ;
final private int ACKPRIME =0 X06 ;
final private int ACKSETID =0 X05 ;
final private int ACKGETID =0 x04 ;
final private int ACKTURNON =0 X03 ;
final private int ACKTURNOFF =0 x02 ;
final private int PING
=0 x01 ;
private boolean stop = false ;
private int [] lastMsg ;
// Debug
long timeStart =0;
long timeEnd =0;
// constructor
public RoadConnectionUDP ( InetAddress address , int port ,
Monitor mon ) throws Exception
{
socket = new DatagramSocket () ;
socket . connect ( address , port ) ;
this . address = address ;
this . port = port ;
sendQue = new ConcurrentLinkedQueue < int [] >() ;
this . mon = mon ;
}
public synchronized void run () {
while ( true ) {
try {
if (! sendQue . isEmpty () ) {
lastMsg = sendQue . poll () ;
sendRecive ( lastMsg ) ; // protected
}
wait () ;
87
88
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
115
116
117
118
119
120
121
Program Code
} catch ( Exception e ) {
// TODO Auto - generated catch block
e . printStackTrace () ;
}
}
}
private void sendRecive ( int [] lastMsg2 ) throws IOException {
// TODO Auto - generated method stub
if ( lastMsg2 == null ) {
}
byte checksumSend ;
DatagramPacket dpSend ;
byte [] dataRec ;
byte [] dataToSend = new byte [(( lastMsg2 [1]) < <1) +6];
dataToSend [0]= ’? ’;
checksumSend = ’? ’;
int i3 =0;
while ( i3 <= ((( lastMsg2 [1]) < <1) +2) ) {
System . out . print ( i3 ) ;
checksumSend ^=( hexEncode (( lastMsg2 [( i3 /2) ] & 0 xFF ) > >4) ) ;
// /16
checksumSend ^=( hexEncode ( lastMsg2 [( i3 /2) ] & 0 xF ) ) ; // %16
dataToSend [ i3 +1] = ( hexEncode (( lastMsg2 [( i3 ) /2] & 0 xFF )
> >4) ) ; // /16
dataToSend [ i3 +2] = ( hexEncode ( lastMsg2 [( i3 /2) ] & 0 xF ) ) ; //
%16
i3 ++;
i3 ++;
}
dataToSend [ dataToSend . length -1]= checksumSend ;
boolean retry = true ;
int retrys = 0;
byte checksum =0;
dataRec = new byte [255];
while ( retry && retrys < 10) {
retry = false ;
dpSend = new DatagramPacket ( dataToSend , dataToSend . length ,
address , port ) ;
socket . send ( dpSend ) ;
DatagramPacket dp = new DatagramPacket ( dataRec , dataRec .
length , address , port ) ;
try {
socket . receive ( dp ) ;
} catch ( Exception e ) {
Program Code
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
89
// TODO Auto - generated catch block
// e . printStackTrace () ;
retry = true ;
retrys ++;
}
if ( dp . getLength () !=255) {
checksum =0;
for ( int i =0; i < dp . getLength () ; i ++) {
checksum ^= dataRec [ i ];
}
System . out . println ( " checksum = " + checksum ) ;
System . out . println ( new String ( dataRec ) ) ;
}
}
if ( checksum ==0) {
data [0] = hexDecode ( dataRec [1]) < <4; // *16
data [0] += hexDecode ( dataRec [2]) ;
data [1] = hexDecode ( dataRec [3]) < <4; // *16
data [1] += hexDecode ( dataRec [4]) ;
for ( int i = 0; i < ( data [1] < <1) ; i +=2) {
data [2+( i > >1) ] = hexDecode ( dataRec [5+ i ]) < <4; //
*16
data [2+( i > >1) ] += hexDecode ( dataRec [6+ i ]) ;
}
instruction ( data ) ;
}
timeEnd = System . nanoTime () ;
System . out . println ( " time : " +( timeEnd - timeStart ) + " ns \ n " ) ;
if ( retrys == 10) {
System . out . println ( " fail , no ack " ) ;
}
}
public String toString () {
return " " + address ;
}
synchronized public void sendStop () {
notifyAll () ;
stop = true ;
// TODO Auto - generated method stub
}
synchronized public void sendPrime () {
timeStart = System . nanoTime () ;
int [] b = { PRIME ,0 x01 ,0 x01 };
try {
sendQue . add ( b ) ; // protected
notifyAll () ;
} catch ( Exception e ) {
90
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
Program Code
// TODO Auto - generated catch block
e . printStackTrace () ;
}
}
synchronized public void sendPrime ( int time100us ) {
timeStart = System . nanoTime () ;
int [] bytes = intToByteArray ( time100us ) ;
System . out . println ( " DEBUG primeing , time : " + time100us ) ;
int [] b = { PRIME ,0 x02 , bytes [2] , bytes [3]};
try {
sendQue . add ( b ) ; // protected
notifyAll () ;
} catch ( Exception e ) {
// TODO Auto - generated catch block
e . printStackTrace () ;
}
}
synchronized public void sendTurnON () {
// TODO Auto - generated method stub
int [] b = { TURNON ,0 x01 ,0 x01 };
try {
sendQue . add ( b ) ; // protected
} catch ( Exception e ) {
// TODO Auto - generated catch block
e . printStackTrace () ;
}
notifyAll () ;
}
synchronized public void sendTurnOFF () {
// TODO Auto - generated method stub
int [] b = { TURNOFF ,0 x01 ,0 x01 };
try {
sendQue . add ( b ) ; // protected
} catch ( Exception e ) {
// TODO Auto - generated catch block
e . printStackTrace () ;
}
notifyAll () ;
}
synchronized public int getTagId () {
return id ;
}
public void sendGetTagId () {
int [] b = { GETID ,0 x01 ,0 x01 };
try {
sendQue . add ( b ) ; // protected
} catch ( Exception e ) {
// TODO Auto - generated catch block
e . printStackTrace () ;
Program Code
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
91
}
}
synchronized public void setTagId ( int id ) {
this . id = id ;
}
public synchronized void sendSetTagId ( int id ) {
int [] bytes = intToByteArray ( id ) ;
int [] b = { SETID , bytes . length };
int [] sum = new int [ b . length + bytes . length ];
System . arraycopy (b , 0 , sum , 0 , b . length ) ;
System . arraycopy ( bytes , 0 , sum , b . length , bytes . length ) ;
setTagId ( id ) ;
try {
sendQue . add ( sum ) ; // protected
} catch ( Exception e ) {
// TODO Auto - generated catch block
e . printStackTrace () ;
}
notifyAll () ;
}
private int [] intToByteArray ( int value ) {
return new int [] {
( value >>> 24) & 0 XFF ,
( value >>> 16) & 0 XFF ,
(( value >>> 8) & 0 XFF ) ,
( value & 0 xFF ) };
}
private void instruction ( int [] data ) {
if ( data [0]== ACKGETID ) {
int tempid = (( data [2]& 0 XFF ) << 24) +
(( data [3]& 0 XFF ) << 16) +
(( data [4] & 0 XFF ) << 8) +
(( data [5]) & 0 XFF ) ;
setTagId ( tempid ) ;
}
if ( data [0]== ACKPRIME ) {
}
}
private String toHex ( String arg ) {
try {
return String . format ( " %02 x " , new BigInteger (1 , arg . getBytes
( " UTF -8 " ) ) ) ;
} catch ( U n s u p p o r t e d E n c o d i n g E x c e p t i o n e ) {
// TODO Auto - generated catch block
e . printStackTrace () ;
}
92
273
return null ;
274
}
275
276
byte hexDecode ( int c )
277
{
278
if ( c >= ’0 ’ && c <= ’9 ’)
279
{
280
return ( byte ) ( c - ’0 ’) ;
281
}
282
else if ( c >= ’a ’ && c <= ’f ’)
283
{
284
return ( byte ) ( c - ’a ’ + 10) ;
285
}
286
else if ( c >= ’A ’ && c <= ’F ’)
287
{
288
return ( byte ) ( c - ’A ’ + 10) ;
289
}
290
else
291
{
292
return 0;
293
}
294
}
295
byte hexEncode ( int i , boolean cap )
296
{
297
if ( i >= 0 && i <= 9)
298
{
299
return ( byte ) ( i + ’0 ’) ;
300
}
301
else if ( i >= 10 && i <= 15)
302
{
303
if ( cap )
304
{
305
return ( byte ) ( i - 10 + ’A ’) ;
306
}
307
else
308
{
309
return ( byte ) ( i - 10 + ’a ’) ;
310
}
311
}
312
else
313
{
314
return ’0 ’;
315
}
316
}
317
byte hexEncode ( int i )
318
{
319
return hexEncode (i , true ) ;
320
}
321 }
Program Code
Program Code
A.2.4 CarServerThread.java
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
import java . net . ServerSocket ;
import java . net . Socket ;
import java . io . IOException ;
public class CarServerThread extends Thread {
private Monitor mon ;
private int port ;
public CarServerThread ( Monitor m , int p ) {
mon = m ;
port = p ;
}
public void run () {
ServerSocket serverSocket = null ;
try {
serverSocket = new ServerSocket ( port ) ;
while ( true ) {
new RecThread ( serverSocket . accept () , mon ) . start () ;
System . out . println ( " CarConnected " ) ;
}
} catch ( IOException e ) {
System . err . println ( " Could not listen on port : " + port ) ;
System . exit (1) ;
}
}
}
A.2.5 RecThread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import
import
import
import
import
import
import
java . net . Socket ;
java . io . BufferedReader ;
java . io . InputStreamReader ;
java . io . BufferedWriter ;
java . io . OutputStreamWriter ;
java . io . IOException ;
java . util . Arrays ;
public class RecThread extends Thread {
private Monitor mon ;
private Socket mySocket = null ;
private BufferedReader in ;
93
94
Program Code
15 private BufferedWriter out ;
16
17 public RecThread ( Socket socket , Monitor m ) {
18
mySocket = socket ;
19
mon = m ;
20
try {
21
in = new BufferedReader ( new InputStreamReader ( mySocket .
getInputStream () ) ) ;
22
out = new BufferedWriter ( new OutputStreamWriter ( mySocket .
getOutputStream () ) ) ;
23
} catch ( IOException e ) {
24
System . out . println ( " Error : Couldn ’t connect : " + e .
getMessage () ) ;
25
}
26 }
27
28 private int charArrayToInt ( char [] data , int start , int end )
throws Numb erForm atExce ption
29 {
30
int result = 0;
31
for ( int i = start ; i < end ; i ++)
32
{
33
int digit = ( int ) data [ i ] - ( int ) ’0 ’;
34
if (( digit < 0) || ( digit > 9) ) throw new
Numb erFor matExc eptio n () ;
35
result *= 10;
36
result += digit ;
37
}
38
return result ;
39 }
40
41
42
43
public void run () {
44
45
String speed = " 000 " ;
46
String tagID , ID ;
47
int s = 0 , t = 0 , i = 0;
48
int state = 0 , softID = 0;
49
char ch ;
50
char [] tagIDArray = new char [7];
51
char [] speedArray = new char [3];
52
boolean msgNotDone = true ;
53
boolean alive = true ;
54
boolean carAdded = false ;
55
56
while ( alive ) {
57
try {
58
if ( in . ready () ) {
59
msgNotDone = true ;
60
while ( msgNotDone ) {
Program Code
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
ch = ( char ) in . read () ;
// System . out . println (" I read char " + ch ) ;
switch ( state ) {
case 0:
if ( ch == ’? ’) {
state ++;
Arrays . fill ( tagIDArray , ’0 ’) ;
Arrays . fill ( speedArray , ’0 ’) ;
// System . out . println (" in case0 ") ;
}
break ;
case 1:
// System . out . println (" in case1 ") ;
if ( ch == ’? ’) {
state = 0;
} else if ( ch == ’S ’) {
state = 2;
} else if ( ch == ’T ’) {
state = 3;
} else if ( ch == ’I ’) {
state = 4;
} else if ( ch == ’! ’) {
msgNotDone = false ;
state = 0;
// System . out . println (" I rec !") ;
}
break ;
case 2:
if ( ch == ’? ’) {
state = 0;
break ;
} else if ( ch == ’! ’) {
msgNotDone = false ;
state = 0;
break ;
}
// System . out . println (" in case2 ") ;
speedArray [ s ] = ch ;
// System . out . println (" I put ch " + ch + " in speed at
index " + s ) ;
s ++;
if ( s == 3) {
speed = String . valueOf ( speedArray ) ;
s = 0;
state = 1;
System . out . println ( " speed : " + speed ) ;
}
break ;
case 3:
// System . out . println (" in case3 ") ;
95
96
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
Program Code
if ( ch == ’? ’) {
state = 0;
break ;
} else if ( ch == ’! ’) {
msgNotDone = false ;
state = 0;
break ;
}
tagIDArray [ t ] = ch ;
// System . out . println (" I put ch " + ch + " in tagID at
index " + t ) ;
t ++;
if ( t == 7) {
tagID = String . valueOf ( tagIDArray ) ;
mon . tagDetected ( tagID , speed ) ;
t = 0;
state = 1;
System . out . println ( " tagId : " + tagID ) ;
}
break ;
case 4:
// System . out . println (" in case4 ") ;
if ( ch == ’? ’) {
state = 0;
break ;
} else if ( ch == ’! ’) {
msgNotDone = false ;
state = 0;
break ;
} else {
ID = String . valueOf ( ch ) ;
softID = mon . addCar ( ID ) ;
carAdded = true ;
state = 1;
}
break ;
}
}
}
if ( carAdded && ! mon . shouldContinue ( softID ) ) {
System . out . println ( " Thread says : I should die " ) ;
try {
mySocket . close () ;
System . out . println ( " Clientsocket closed " ) ;
} catch ( IOException e ) {
e . printStackTrace () ;
}
alive = false ;
}
Thread . sleep (1) ;
} catch ( IOException e ) {
Program Code
97
161
e . printStackTrace () ;
162
} catch ( InterruptedException e ) {
163
}
164
}
165
}
166 }
A.2.6 RSU2Road.java
1 import java . util . concurrent . ConcurrentHashMap ;
2
3
4 public class RSU2Road extends Thread {
5
Monitor mon ;
6
ConcurrentHashMap < String , RoadConnectionUDP > clientsList ;
7
public RSU2Road ( ConcurrentHashMap < String , RoadConnectionUDP >
clientsList , Monitor mon ) {
8
this . clientsList = clientsList ;
9
this . mon = mon ;
10
}
11
public void run () {
12
while ( true ) {
13
String [] tagInfo = mon . getDetectedTagID () ;
14
if ( tagInfo != null ) {
15
if ( tagInfo . length ==2) {
16
RoadConnectionUDP client = clientsList . get ( tagInfo [0]) ;
17
if ( client != null ) {
18
int time = ( int ) (2.6*3.6/ ( Integer . parseInt ( tagInfo [1]) )
*10000) ; // time to turn on for 2.6 m ( avstand (
sandare , avtagare ) + 1.07 m + 1.15 m + maginal )
19
// 2.6/8 = 0.325 m
20
if ( time <65000) {
21
System . out . println ( " time : " + time + " , tagid : " +
tagInfo [0]) ;
22
client . sendPrime ( time ) ;
23
} else {
24
System . out . println ( " To slow speed ! time = " + time ) ;
25
}
26
}
27
}
28
}
29
}
30
}
31 }
98
Program Code
A.3 Car code
A.3.1 serial.c
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
# include " serialport . h "
# include
# include
# include
# include
# include
# include
# include
< sys / types .h >
< sys / stat .h >
< fcntl .h >
< termios .h >
< stdlib .h >
< strings .h >
< stdio .h >
/* baudrate settings are defined in < asm / termbits .h > , which is
* included by < termios .h > */
# ifndef BAUDRATE
# define BAUDRATE B9600
# endif
# define _POSIX_SOURCE 1
/* POSIX compliant source */
static int fd , c , res ;
static struct termios oldtio , newtio ;
static const char * device ;
int serial_init ( const char * modemdevice )
{
/*
* Open modem device for reading and writing and not as
controlling tty
* because we don ’t want to get killed if linenoise sends
CTRL - C .
* */
device = modemdevice ;
// fd = open ( device , O_RDWR | O_NOCTTY | O_NDELAY ) ;
fd = open ( device , O_RDWR | O_NOCTTY ) ;
if ( fd < 0)
{
perror ( device ) ;
exit ( -1) ;
}
tcgetattr ( fd , & oldtio ) ; /* save current serial port
settings */
bzero (& newtio , sizeof ( newtio ) ) ; /* clear struct for new
port settings */
/*
Program Code
43
44
45
46
47
48
49
50
51
52
53
54
55
56
99
* BAUDRATE : Set bps rate . You could also use cfsetispeed
and cfsetospeed .
* CRTSCTS : output hardware flow control ( only used if the
cable has
* all necessary lines . )
* CS8
: 8 n1 (8 bit , no parity ,1 stopbit )
* CLOCAL : local connection , no modem contol
* CREAD
: enable receiving characters
* */
newtio . c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD ;
/*
* IGNPAR : ignore bytes with parity errors
* ICRNL
: map CR to NL ( otherwise a CR input on the
other computer
*
will not terminate input )
*
otherwise make device raw ( no other input
processing )
* */
newtio . c_iflag = IGNPAR | ICRNL ;
57
58
59
60
/*
61
* Map NL to CR NL in output .
62
*
*/
63 # if 0
64
newtio . c_oflag = ONLCR ;
65 # else
66
newtio . c_oflag = 0;
67 # endif
68
69
70
/*
71
* ICANON : enable canonical input
72
*
disable all echo functionality , and don ’t
send signals to calling program
73
* */
74 # if 1
75
newtio . c_lflag = ICANON ;
76 # else
77
newtio . c_lflag = 0;
78 # endif
79
80 newtio . c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG ) ;
81
82
/*
83
* initialize all control characters
84
* default values can be found in / usr / include / termios .h ,
and are given
85
* in the comments , but we don ’t need them here
86
*
*/
87
newtio . c_cc [ VINTR ] = 0; /* Ctrl - c */
100
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
Program Code
newtio . c_cc [ VQUIT ] = 0; /* Ctrl -\ */
newtio . c_cc [ VERASE ] = 0; /* del */
newtio . c_cc [ VKILL ] = 0; /* @ */
newtio . c_cc [ VEOF ] = 4; /* Ctrl - d */
newtio . c_cc [ VTIME ] = 0; /* inter - character timer unused */
newtio . c_cc [ VMIN ] = 1; /* blocking read until 1 character
arrives */
newtio . c_cc [ VSWTC ] = 0; /* ’\0 ’ */
newtio . c_cc [ VSTART ] = 0; /* Ctrl - q */
newtio . c_cc [ VSTOP ] = 0; /* Ctrl - s */
newtio . c_cc [ VSUSP ] = 0; /* Ctrl - z */
newtio . c_cc [ VEOL ] = 0; /* ’\0 ’ */
newtio . c_cc [ VREPRINT ] = 0; /* Ctrl - r */
newtio . c_cc [ VDISCARD ] = 0; /* Ctrl - u */
newtio . c_cc [ VWERASE ] = 0; /* Ctrl - w */
newtio . c_cc [ VLNEXT ] = 0; /* Ctrl - v */
newtio . c_cc [ VEOL2 ] = 0; /* ’\0 ’ */
/*
* now clean the modem line and activate the settings for
the port
* */
tcflush ( fd , TCIFLUSH ) ;
tcsetattr ( fd , TCSANOW , & newtio ) ;
107
108
109
110
111
/*
112
* terminal settings done , return file descriptor
113
* */
114
115
return fd ;
116 }
117
118 void serial_cleanup ( int ifd ) {
119
if ( ifd != fd ) {
120
fprintf ( stderr , " WARNING ! file descriptor != the one
returned by serial_init () \ n " ) ;
121
}
122
/* restore the old port settings */
123
tcsetattr ( ifd , TCSANOW , & oldtio ) ;
124 }
A.3.2 testSync.cc
1
2
3
4
5
6
7
8
# include
# include
# include
# include
" serialport . h "
" connection . h "
" c o n n ec t i o n c l o s e d ex c e p t i o n . h "
" monitor . h "
# include < iostream >
# include < thread >
// std :: cout
// std :: thread
Program Code
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
# include
# include
# include
# include
# include
< chrono >
< sys / types .h >
< unistd .h >
< stdexcept >
< vector >
101
// std :: chrono :: seconds
# define BAUDRATE B9600
using namespace std ;
/* run method of comTSS thread */
void runTSS ( Monitor & mon ) {
unsigned char bufIn [100] = {0};
int bytes_read [100];
int pos = 0;
unsigned char STX = 2 , ETX = 3;
vector < unsigned char > send ;
// int fd = serial_init ("/ dev / ttyACM0 ") ;
int fd = serial_init ( " / dev / ttyUSB0 " ) ;
while ( true ) {
// read from RFID antenna
int i = 0;
while ( true ) {
cout < < " one more time " << endl ;
i = 0;
bytes_read [ pos ] = read ( fd , bufIn + pos , 1) ;
if ( bufIn [ pos ] == STX ) {
bytes_read [ pos ] = read ( fd , bufIn + pos , 1) ; // read command
bytes_read [ pos ] = read ( fd , bufIn + pos , 1) ;
cout < < " Tag read : " ;
while ( bufIn [ pos ] != ETX ) {
cout < < bufIn [ pos ] < < " " ;
send . push_back ( bufIn [ pos ]) ;
i ++;
bytes_read [ pos ] = read ( fd , bufIn + pos , 1) ;
}
cout < < endl ;
mon . putMsg ( send ) ;
send . clear () ;
bytes_read [ pos ] = read ( fd , bufIn + pos , 1) ; // read crc
} this_thread :: sleep_for ( chrono :: milliseconds (5) ) ;
}
}
serial_cleanup ( fd ) ;
}
102
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
Program Code
/* run method of comRSURec thread */
void runRSURec ( Monitor & mon , shared_ptr < Connection >& conn ) {
unsigned int recv_msg = 0;
while ( true ) {
try {
recv_msg = conn - > read () ;
} catch ( C o n n ec t i o n C l o s e dE x c e p t i o n &) {
cout << " no reply from server . Exiting . " << endl ;
exit (1) ;
}
this_thread :: sleep_for ( chrono :: milliseconds (500) ) ;
}
}
/* run method of comRSUSend thread */
void runcomRSUSend ( Monitor & mon , shared_ptr < Connection >& conn ,
unsigned char id ) {
80
vector < unsigned char > curMsg ;
81
vector < unsigned char > prevMsg ;
82
83
try {
84
conn - > write ( ’? ’) ;
85
conn - > write ( ’I ’) ;
86
conn - > write ( id ) ;
87
conn - > write ( ’! ’) ;
88
} catch ( C o n ne c t i o n C l o s e dE x c e p t i o n &) {
89
cout << " no reply from server . Exiting . " << endl ;
90
exit (1) ;
91
}
92
93
while ( true ) {
94
mon . getMsg ( curMsg ) ;
95
if ( curMsg != prevMsg ) {
96
cout < < " curMsg != prevMsg " << endl ;
97
98
for ( vector < unsigned char >:: iterator it = curMsg . begin () ;
it != curMsg . end () ; ++ it ) {
99
try {
100
conn - > write ((* it ) ) ;
101
cout < < " " < <* it ;
102
103
} catch ( C o n n ec t i o n C l o s e dE x c e p t i o n &) {
104
cout << " no reply from server . Exiting . " << endl ;
105
exit (1) ;
106
}
107
}
108
cout < < endl ;
Program Code
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
103
prevMsg = curMsg ;
curMsg . clear () ;
} else {
cout < < " curMsg == prevMsg " << endl ;
}
// this_thread :: sleep_for ( chrono :: milliseconds (2000) ) ;
}
}
void runSpeed ( Monitor & mon ) {
string line ;
int s = 0;
while ( cin >> s ) {
mon . putSpeed ( s ) ;
cout < < " Speed updated " << endl ;
this_thread :: sleep_for ( chrono :: milliseconds (500) ) ;
}
}
// int main () {
int main ( int argc , char * argv []) {
if ( argc != 3) {
cerr << " Usage : myclient host - name port - number " << endl ;
exit (1) ;
}
int port = -1;
try {
port = stoi ( argv [2]) ;
} catch ( exception & e ) {
cerr << " Wrong port number . " << e . what () << endl ;
exit (1) ;
}
shared_ptr < Connection > conn ( new Connection ( argv [1] , port ) ) ;
if (! conn - > isConnected () ) {
cerr << " Connection attempt failed " << endl ;
exit (1) ;
}
Monitor m ;
thread comTSS ( runTSS , std :: ref ( m ) ) ;
thread comRSURec ( runRSURec , std :: ref ( m ) , std :: ref ( conn ) ) ;
thread comRSUSend ( runcomRSUSend , std :: ref ( m ) , std :: ref ( conn ) , ’0
’) ;
thread carSpeed ( runSpeed , std :: ref ( m ) ) ;
carSpeed . join () ;
comTSS . join () ;
comRSURec . join () ;
comRSUSend . join () ;
104
Program Code
159 }
A.3.3 monitor.h
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
# ifndef MONITOR_H
# define MONITOR_H
# include
# include
# include
# include
< mutex >
// std :: mutex , std :: unique_lock
< condition_variable > // std :: condition_variable
< vector >
< chrono >
class Monitor {
public :
Monitor () ;
void putMsg ( std :: vector < unsigned char > d ) ;
void getMsg ( std :: vector < unsigned char >& d ) ;
void putSpeed ( int v ) ;
void updatePowerConsumed ( unsigned int a ) ;
private :
std :: mutex mtx ;
std :: condition_variable cv ;
bool controlCheck = false ;
// true means the car is
allowed to draw power from the road
unsigned int powerConsumed = 48;
int speed =0;
std :: vector < unsigned char > updatedSpeed ;
size_t nextRead = 0 , nextWrite = 0 , curSize = 0 , buffSize =
100;
std :: vector < std :: vector < unsigned char > > data ;
std :: chrono :: high _resol ution _clock :: time_point t_start , t_end
;
std :: clock_t c_start ;
28
29
30 };
31
32 # endif
A.3.4 monitor.cc
1
2
3
4
5
6
7
8
\ end {}
# include
# include
# include
# include
" monitor . h "
< iostream >
< chrono >
< ctime >
using namespace std ;
// std :: cout
Program Code
105
9 Monitor :: Monitor () : data ( buffSize ) {}
10
11 /* called by comTSS thread when it has read data from RFID
antennen */
12 void Monitor :: putMsg ( vector < unsigned char > d ) {
13
unique_lock < mutex > lck ( mtx ) ;
// take the mutex
14
while ( curSize == buffSize ) { cv . wait ( lck ) ;}
15
cout < < " in put msg " ;
16
data [ nextWrite ]. push_back ( ’? ’) ;
17
data [ nextWrite ]. push_back ( ’S ’) ;
18
char s [4]={ ’0 ’ , ’0 ’ , ’0 ’ , ’0 ’ };
19
sprintf (s , " %03 d " , speed ) ;
20
data [ nextWrite ]. push_back ( s [0]) ;
21
data [ nextWrite ]. push_back ( s [1]) ;
22
data [ nextWrite ]. push_back ( s [2]) ;
23
data [ nextWrite ]. push_back ( ’T ’) ;
24
data [ nextWrite ]. insert ( data [ nextWrite ]. end () , d . begin () , d .
end () ) ;
25
data [ nextWrite ]. push_back ( ’! ’) ;
26
27
for ( vector < unsigned char >:: iterator it = ( data [ nextWrite ]) .
begin () ; it != ( data [ nextWrite ]) . end () ; ++ it ) {
28
// cout << " " << hex << static_cast < unsigned int >(* it ) ;
29
cout << " " << * it ;
30
}
31
cout < < endl ;
32
nextWrite = ( nextWrite + 1) % buffSize ;
33
curSize ++;
34
lck . unlock () ;
// release the mutex
35
cv . notify_all () ;
36 }
37
38 /* called by comRSUSend thread */
39 void Monitor :: getMsg ( vector < unsigned char >& vec ) {
40
41
unique_lock < mutex > lck ( mtx ) ;
42
while ( curSize == 0) { cv . wait ( lck ) ;}
43
vec = data [ nextRead ];
44
data [ nextRead ]. clear () ;
45
nextRead = ( nextRead + 1) % buffSize ;
46
curSize - -;
47
// c_start = clock () ;
48
// t_start = chrono :: hig h_reso lutio n_cloc k :: now () ;
49
lck . unlock () ;
50
cv . notify_all () ;
51 }
52
53 /* called by carSpeed */
54 void Monitor :: putSpeed ( int a ) {
55
unique_lock < mutex > lck ( mtx ) ;
56
speed = a ;
106
Program Code
57
char s [4]={ ’0 ’ , ’0 ’ , ’0 ’ , ’0 ’ };
58
sprintf (s , " %03 d " , speed ) ;
59
updatedSpeed . push_back ( ’S ’) ;
60
updatedSpeed . push_back ( s [0]) ;
61
updatedSpeed . push_back ( s [1]) ;
62
updatedSpeed . push_back ( s [2]) ;
63
lck . unlock () ;
64
cv . notify_all () ;
65 }
66
67 /* called by comRSURec */
68 void Monitor :: updatePowerConsumed ( unsigned int a ) {
69
unique_lock < mutex > lck ( mtx ) ;
70
// clock_t c_end = clock () ;
71
// t_end = chrono :: hig h_res olutio n_clo ck :: now () ;
72
powerConsumed = a ;
73
cout < < " Power consumed updated : " << a << endl ;
74
// cout << chrono :: duration < double , milli >( t_end - t_start ) .
count () << " ms \ n " < < endl ;
75
// cout < < 1000.0 * ( c_end - c_start ) / CLOCKS_PER_SEC << " ms \ n
" < < endl ;
76
lck . unlock () ;
77
cv . notify_all () ;
78 }
A.3.5 connection.h
1 //
-----------------------------------------------------------------2
3
4
5
6
7
8
9
10
11
12
//
//
//
//
//
//
//
//
//
//
//
13
14
15
16
17
18
19
//
//
//
//
//
//
//
20 //
Client / Server communication package
Connection header file
Change log
950323 RH Initial version
951212 RH Modified to allow subclassing of class Connection
970127 RH Changed " private " to " protected "
990125 PH Changed function names : Read -> read , etc .
000114 PH int -> bool , virtual destructors , other minor
changes
010129 PH added void type to initConnection
011212 PH changed char * arguments to const char *
changed connection closed handling to exception
unsigned char instead of char / int in write / read
020102 PH split into separate file for each class
040421 PH added namespace , new casts , cleaned up a lot
050113 PH added deregisterConnection , new registration (
vector ) ,
added check for server shutdown , many more changes
Program Code
21 //
22 //
23 //
130515
107
PH
removed namespace
-----------------------------------------------------------------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
# ifndef CONNECTION_H
# define CONNECTION_H
class Server ;
/* A Connection object represents a connection ( a socket )
class Connection {
friend class Server ;
public :
/* Establishes a connection to the computer ’ host ’ via
the port ’ port ’ */
Connection ( const char * host , int port ) ;
*/
/* Creates a Connection object which will be initialized
by the server */
Connection () ;
/* Closes the connection */
virtual ~ Connection () ;
/* Returns true if the connection has been established */
bool isConnected () const ;
/* Writes a character */
void write ( unsigned char ch ) const ;
/* Reads a character */
unsigned char read () const ;
protected :
/* The socket number that this connections communicates on */
int my_socket ;
/* Set to true when the constructor has called signal ()
to ignore broken pipe . See comment in the constructor */
static bool ignoresPipeSignals ;
/* Initialization from server , receives socket number s */
void initConnection ( int s ) ;
/* Server fetches the socket number */
int getSocket () const ;
/* Prints error message and exits */
void error ( const char * msg ) const ;
108
Program Code
70 };
71
72 # endif
A.3.6 connection.cc
1 //
-----------------------------------------------------------------2
3
4
5
6
7
8
9
10
//
//
//
//
//
//
//
//
//
11 //
12 //
13
14
15
16
17
18
19
//
//
//
//
//
//
//
20
21
22
23
24
//
//
//
//
//
Client / Server communication package
Connection implementation file
Change log
950323 RH Initial version
951212 RH Modified to allow subclassing of class Connection
970127 RH Added extra include to make the file compile
under Linux
990125 PH Changed function names : Read -> read , ...
000114 PH int -> bool , virtual destructors , other minor
changes
010129 PH added void type to initConnection
011212 PH changed char * arguments to const char *
changed connection closed handling to exception
unsigned char instead of char / int in write / read
020102 PH split into separate file for each class
040421 PH added namespace , new casts , cleaned up a lot
050113 PH added deregisterConnection , new registration (
vector ) ,
added check for server shutdown , many more changes
090127 PH added include of cstdlib , for exit ()
130515 PH removed namespace
-----------------------------------------------------------------25
26
27
28
29
30
31
32
33
34
35
36
37
# include " connection . h "
# include " c o n ne c t i o n c l o s e de x c e p t i o n . h "
# include
# include
# include
# include
# include
() */
# include
# include
# include
# include
< iostream >
< cstdlib >
< cstring >
< csignal >
< sys / types .h >
/*
/*
/*
/*
exit () */
memcpy () */
signal () */
socket () , connect () , read () , write
< sys / socket .h >
< netdb .h >
< arpa / inet .h >
< unistd .h >
/*
/*
/*
/*
socket () , connect () */
gethostbyname () */
htons () */
close () , read () , write () */
Program Code
38
39
40
41
42
43
44
45
46
47
109
# include < sys / uio .h >
/* read () , write () */
# include < netinet / in .h > /* sockaddr_in */
bool Connection :: ignoresPipeSignals = false ;
Connection :: Connection ( const char * host , int port ) {
/*
* Ignore SIGPIPE signals ( broken pipe ) . A broken pipe ( only
?)
* occurs in a client , when it tries to write to a dead
server .
* When the signal is ignored , :: write () returns -1 as the
count
* of written bytes . Connection :: write () tests for this and
* throws C o n ne c t i o n C l o s ed E x c e p t i o n when it happens .
*/
if (! i gnoresPipeSignals ) {
signal ( SIGPIPE , SIG_IGN ) ;
ig no resPipeSignals = true ;
}
48
49
50
51
52
53
54
55
56
my_socket = socket ( AF_INET , SOCK_STREAM , 0) ;
57
if ( my_socket < 0) {
58
my_socket = -1;
59
return ;
60
}
61
62
sockaddr_in server ;
63
server . sin_family = AF_INET ;
64
hostent * hp = gethostbyname ( host ) ;
65
if ( hp == 0) {
66
my_socket = -1;
67
return ;
68
}
69
70
memcpy ( reinterpret_cast < char * >(& server . sin_addr ) ,
71
reinterpret_cast < char * >( hp - > h_addr ) ,
72
hp - > h_length ) ;
73
server . sin_port = htons ( port ) ;
74
if ( connect ( my_socket ,
75
reinterpret_cast < sockaddr * >(& server ) ,
76
sizeof ( server ) ) < 0) {
77
my_socket = -1;
78
}
79 }
80
81 Connection :: Connection () {
82
/*
83
* See previous constructor for comments .
84
*/
85
if (! i gnoresPipeSignals ) {
110
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
Program Code
signal ( SIGPIPE , SIG_IGN ) ;
ignoresPipeSignals = true ;
}
my_socket = -1;
}
Connection ::~ Connection () {
if ( my_socket != -1) {
close ( my_socket ) ;
}
}
bool Connection :: isConnected () const {
return my_socket != -1;
}
void Connection :: write ( unsigned char ch ) const {
if ( my_socket == -1) {
error ( " Write attempted on a not properly opened connection " )
;
}
int count = :: write ( my_socket , & ch , 1) ;
if ( count != 1) {
throw C o n n e c ti o n C l o s e d E x ce p t i o n () ;
}
}
unsigned char Connection :: read () const {
if ( my_socket == -1) {
error ( " Read attempted on a not properly opened connection " ) ;
}
char data = ’ ’;
int count = :: read ( my_socket , & data , 1) ;
if ( count != 1) {
throw C o n n e c ti o n C l o s e d E x ce p t i o n () ;
return data ;
}
return data ;
}
void Connection :: initConnection ( int s ) {
my_socket = s ;
}
int Connection :: getSocket () const {
return my_socket ;
}
void Connection :: error ( const char * msg ) const {
std :: cerr << " Class Connection : " << msg << std :: endl ;
Program Code
136
exit (1) ;
137 }
111
112
Program Code
Bibliography
EPCglobal 2008, EPC Radio-Frequency Identity Protocols Class-1 Generation-2
UHF RFID Protocol for Communications at 860 MHz – 960 MHz. EPCglobal Inc., 2008. Version 1.2.0. Available at http://www.gs1.org/sites/
default/files/docs/epc/uhfc1g2_1_2_0-standard-20080511.pdf, [2 December 2015].
Energiläget 2013. Svenska statens energimyndighet, 2013. Available in printed
form or at http://www.energimyndigheten.se/statistik/energilaget/.
Fossilfrihet på väg.
2013:84.
Statens offentliga utredningar, 2013.
ID-nummer: SOU
Traffic Supervisions Systems TSS, 2015. Available at http://www.compprof-rtp.
com/tss-tag/, [4 December 2015].
Elways, 2015. Available at http://elways.se, [4 December 2015].
eHighway, Siemens, 2016. Available at http://w3.siemens.se/home/se/sv/
Mobility/interurban_mobility/road_solutions/elvagar-klimatsmartaoch-kostnadseffektiva-transporter/Pages/elvagar-klimatsmarta-ochkostnadseffektiva-transporter.aspx, [22 December 2016].
Philip Abrahamsson. Electro mechanic design and test of conductive electrical
road system - overall system design and protection. Master’s thesis, Division of
Industrial Electrical Engineering and Automation Faculty of Engineering, Lund
University, 2015. CODEN:LUTEDX/(TEIE-5349)/1-53/(2015).
Marcus Andersson. Electro mechanic design and test of conductive electrical road
system - primary power circui. Master’s thesis, Division of Industrial Electrical
Engineering and Automation Faculty of Engineering, Lund University, 2014.
CODEN:LUTEDX/(TEIE-5348)/1-44(2014).
C.A. Balanis. Antenna theory. John Wiley & Sons, Inc., Hoboken, New Jersey,
third edition, 2005. ISBN 978-0-471-66782-7.
S. Evdokimov, B. Fabian, O. Günter, Ivantysynova L., and H. Ziekow. RFID
and the Internet of Things: Technology, Applications and Security Challenges,
113
114
BIBLIOGRAPHY
Foundation and Trends in Technology, Information and Operations Management. Publishers Inc., 2010. ISBN 978-1-601-98444-9. Volume 4, no 2.
K. Finkenzeller. RFID Handbook: Fundamentals and applications in contactless
smart cards, radio frequency identification and near-field communication. John
Wiley & Sons, Ltd, third edition, 2010. ISBN 978-0-470-69506-7.
E. H. Hall. On a new action of the magnet on electric currents. Technical report,
American Journal of Mathematics 2, No. 3, pages 287–292., 1879. Available at
http://www.jstor.org/stable/2369245?seq=6#page_scan_tab_contents ,
[15 January 2016].
Emil Landqvist and Theodor Hallerby. Thermal Modeling and Power Limitation
of the ElOnRoad system - Modelation and simulation of the thermic capabilities. Master’s thesis, Division of Industrial Electrical Engineering and Automation Faculty of Engineering, Lund University, 2015. CODEN:LUTEDX/(TEIE5350)/1-65/2015).
K&J Magnetics. Surface fields 101, 2016. URL https://www.kjmagnetics.com/
blog.asp?p=surface-fields-101. [28 February 2016].
NdFeB Specialists E-magnets UK. Grades of Neodymium, 2016. Available at
http://www.ndfeb-info.com/neodymium_grades.aspx,[20 February 2016].
Optys Corporation. OptRFID, High speed reader: reading tags at 43 & 113 km/h.
2011. Available at https://www.youtube.com/watch?v=n2g_4Do_3R4, [2 December 2015].
Naomi Oreskes. Vägar och gators utformning, VGU. Technical report, 2004. Science 03 Dec 2004: Vol. 306, Issue 5702, pp. 1686 DOI: 10.1126/science.1103618.
PTSFS. Post och telestyrelsens föreskrifter om undantag från tillståndsplikt för användning av vissa radiosändare. Post och telestyrelse, 2015. Available at http:
//www.pts.se/upload/Foreskrifter/Radio/PTSFS-2015_4-undantag.pdf.
A.W. Rudge, K. Milne, Olver A.D., and Knight P. The handbook of antenna
design. Peter Peregrinus Ltd., London, UK, 1982. ISBN 978-0-906-04882-5.
Volume 1.
Henrik Fritzon Sund. Electro mechanic design and test of conductive electrical
road system - implementation of the control unit. Master’s thesis, Division of
Industrial Electrical Engineering and Automation Faculty of Engineering, Lund
University, 2014. CODEN: LUTEDX/(TEIE-5327)/1-121/(2014).
Lee H. Thomas. The design of CMOS radio-frequency integrated circuits. Cambridge University Press, second edition, 2004. ISBN 978-0-521-83539-8.
A. Paul Tipler and Mosca Gene. Physics for scientists and engineers. W.H.
Freeman and Company, New York, sixth edition, 2008.
VGU. Vägar och gators utformning, VGU. Technical report, 2004. Available at http://www.trafikverket.se/TrvSeFiler/Foretag/Bygga_och_
underhalla/Vag/Vagutformning/Dokument_vag_och_gatuutformning/
BIBLIOGRAPHY
115
Vagar_och_gators_utformning/Sektion_landsbygd-vagrum/sektion_
%20landsbygd_vagrum.pdf,[30 November 2015].
R. Wermke, O. Wilmsmeier, and J. Regtmeier. How fast is fast? RFID identifies objects up to 200 km/h. Harting Technology Group, 2014a. Available
at
http://www.harting-rfid.com/fileadmin/harting/documents/rfid/
aktuelles/fachartikel/Whitepaper_RFID_highspeed_HARTING.pdf,
[2
December 2015].
R. Wermke, O. Wilmsmeier, and J. Regtmeier. How fast is fast? RFID identifies
objects up to 200 km/h. Harting Technology Group, 2014b. Available at https:
//www.youtube.com/watch?v=sZ9yE0Lw_so, [2 December 2015].
Zhang Xiaoqiang and Tentzeris Manos. Applications of Fast-Moving RFID Tags
in High-speed Railway Systems. Technical report, 2011. International Journal
of Engineering Business Management. Volume 3, No. 1, pp. 27-31.
Printed by Tryckeriet i E-huset, Lund 2017
Series of Master’s theses
Department of Electrical and Information Technology
LU/LTH-EIT 2017-564
http://www.eit.lth.se
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Related manuals

Download PDF

advertising