Anda di halaman 1dari 104

[Type text]

A Three-Phase Voltage Source


Inverter Using Adaptive Space
Vector Algorithm

Group Members:

Bilal Sarwar B-17707


Mubashar Ali B-18442
Mudasar Bashir B-17540
MubashirLatif B-17671

Supervisor: Engr. M. Ali Azaz

Co- Supervisor: Engr. Iqra

Submitted in partial fulfilment of the requirements for the Bachelors in


Electrical Engineering
Acknowledgements

I would like to take the opportunity to acknowledge the direct and indirect help
of all the people who made this thesis possible.

I would like to express my sincere appreciation to my supervisor for his


continuous support, guidance and valuable advices. The advices were not only
based on my thesis, but also for my future career.

I would like to thank my parents for always supporting me. Without them this
degree would not have been possible.

Also most importantly thanks and praises to the God almighty for successful
completion of thesis.

1 | University of South Asia


Table of Contents

Acknowledgements............................................................................................ 1
Table of Contents .............................................................................................. 2
Motivation .......................................................................................................... 5
Abstract .............................................................................................................. 6

Chapter 1 Introduction ............................................................................... 7

• 1.1 Purpose .................................................................................... 8

• 1.2 Objective .................................................................................. 9

• 1.2 Block Diagram ......................................................................... 8

• 1.4 Research Methodology ............................................................. 9

• 1.5 Organization of the Report ...................................................... 9


Chapter 2 Literature Review ......................................................................... 13

• 2.1 Background ............................................................................ 13

• 2.2 IEEE Power Quality Standards ............................................. 13

• 2.2 Application of multilevel Inverters ........................................ 14


Chapter 3 ............................................................. Error! Bookmark not defined.

• 3.1 Simulation constraints and parameters ......... Error! Bookmark not


defined.
• 3.10 Simulink Block Diagram of 2 level 3 phase Inverter .......... Error!
Bookmark not defined.

2 | University of South Asia


Chapter 4 DC-DC Converter ............................. Error! Bookmark not defined.
• 4.1 DC to DC Topologies: .................................................................... 20
• 4.2Modules of DC-DC Converter ....................................................... 23
• 4.3 Topology selection:- ....................................................................... 25
Chapter 5 DC-AC Inverter ............................................................................ 41

• 5.1 Three Phase Solar Inverters ................................................... 42

• 5.2 Space Vector Modulation ....................................................... 43

• 5.3 Working Principle .................................................................. 43

• 5.4 Gate Driver Circuit ................................................................ 44

• 5.5 PCB Design ............................................................................ 45


Chapter 6 Three-Phase Energy Meter .......................................................... 48
• 6.1 Purpose of energy meter ................................................................ 49
• 6.2 Design of energy meter .................................................................. 49
• 6.3 Energy Meter Schematic Diagram ............................................... 50
• 6.4 Real Power Calculation ................................................................. 50
• 6.3 Energy Meter Schematic Diagram ............................................... 51
• 6.5 RMS Voltage and Current Measurement ................................... 51
• 6.6 Zero-Crossing Voltage Detector For Power Factor Calculation52
• 6.7 Implement Zero Crossing Detector Using Arduino ................... 52
• 6.7 PCB design ...................................................................................... 54
Chapter 7 Conclusion& Future Work .......................................................... 55

• 7.1Summary &Conclusion ........................................................... 56

• 7.2Future Work ........................................................................... 57


REFERENCES ................................................................................................ 60
Appendix .......................................................................................................... 63

Matlab Code for Perturb and Observe Algorithm ................................. 64

Matlab Code for Boost Converter Calculation ...................................... 65

3 | University of South Asia


List of Figures
Figure 1.1 Block Diagram 09
Figure 2.1 Voltage Distortation Limits 13
Figure3.1: Subsystem for Sector evaluation 17

Figure 3.46 Frequency VS Voltage for IGBT and MOSFET


47
Figure 3.47 PWM signal Generation through comparison 48
Figure 3.48 Three-Level PWM Modulation Generation 49
Figure 1.1 Central Inverter Configuration 53
Figure 4.11 PV String Inverter Topology 54
Figure 4.12 PV Multi-String Inverter Topology
54
Figure 4.13 PV Grid-Tie Inverter based on Module Integrated Inverter 55
Figure 4.14 PV Array Module In Matlab Software 56
Figure 4.15 Voltage VS Power Characteristics of PV Array 57
Figure 4.16 Voltage VS Current Characteristics of PV Array
57
Figure 4.17 PV Module attached to Boost Converter
58
Figure 4.18 Matlab algorithm to Calculate Boost Converter Parameters 59
Figure 4.19 Two PV Modules Attached to Two Boost Converters 60
Figure 4.20 Perturb & Observe Algorithm Flowchart
61
Figure 4.21 MPPT Controller in Matlab 62
Figure 4.22 MPPT Algorithm Modeled in Matlab 63
Figure 4.23 MPPT based Boost Converter attached to PV Modules 64
Figure 4.24 Boost Converter Voltage Output & Modulation index 64
Figure 4.25 Three-Phase VSC Inverter Model
65
Figure 4.26 VSC Converter In Matlab
66
Figure 4.27 Matlab Library with PWM Generators 67
Figure 4.28 PWM Generator Selected for the Inverter Design
67
Figure 4.29 Parameters Matlab Block for PWM Generator 68
Figure 4.30 PV Modules and Boost Converters connected to VSC Inverter
69
Figure 4.31 Three-Phase VSC Output
70
Figure 4.32 Addition of Choke & Capacitor Bank to the Output 71
Figure 4.33 Three-Phase Transformer Parameters in Matlab
71
Figure 4.34 Grid Feeder Configuration 72
Figure 4.35 Three Phase Voltage Source for Transmission Level 73
Figure 4.36 Complete Utility Grid Design 73

4 | University of South Asia


Motivation

A planet where more than 2 billion people don't have any access to electricity,
energy is a key issue in people's lives. It's also an important factor that shapes
the development of any modern day economy. As the demand for energy keeps
on increasing each year, new alternative ways to generate energy are looked
into. It's been estimated the demand for electricity will increase threefold till
2050. So to keep up with the energy demands, renewable energy (RE) plays a
vital role in today's world . The study focuses on importance of Inverters which
are the core part of any modern day power system. It also looks into factors that
affect efficiency, cost and reliability of these systems. Further this study looks
into Space vector algorithm implementation in analysed in Matlab SIMULINK
software and real-time.

5 | University of South Asia


Abstract

The thesis focuses on integration of large scale renewable energy resources


such as wind and solar farms into the utility grid. By modelling grid tie inverter
and analysing different inverter topologies based on cost, efficiency and
reliability. While there has been a great deal of work done in different
convertor technologies but there has been little done in analysing these
systems. In addition to the modelling and analysis, the author justifies on
essence and the need of carrying out such research based on renewable energy
technologies. The thesis describes a Three Phase voltage source inverter which
compromises of a DC-DC boost convertor along with a three phase DC-AC
inverter. While the control of the inverter is implemented using space vector
(SVM) algorithm. Finally a three phase energy meter is used to monitor active
and reactive power and upload those values to the internet.

6 | University of South Asia


CHAPTER # 1
INTRODUCTION

7 | University of South Asia


Chapter 1

1.1 Purpose
As RE technologies are growing at a fast pace worldwide, still vast majority of
people don't have any sufficient knowledge in terms of their need and impact.
Inverters are a key component in any RE technology. Inverter is a device that is
widely used all over the world to convert DC input voltage into AC. The
output typically of an Inverter should be a pure sinusoidal waveform. However,
most of the practical inverters don't have pure sinusoidal output and they also
contain harmonics. This study focuses on these challenges and tries to provide
a solution. Following problems are focused in this thesis:

 The importance of RE technology and its impact


 Design of DC-DC Converter
 Design of DC-AC Inverter
 Design of Three-Phase Energy Meter

1.2 Objective

The main objective of our project is to develop a novel highly efficient, cost
effective, compact, reliable three-phase two-level inverter by implementing
Space Vector Modulation (SVPWM) using the programming environment of
MATLAB as its basis. All renewable energy sources are in need of multilevel
power electronics in form of multilevel inverters. The mind behind the pulses
created by the inverters is the SVPWM. This modulation type uses a space
vector, referred to as the reference vector, to locate and create the desired
sinusoidal-shaped waveform. We will also construct a DC-DC Boost Converter
using Push-Pull topology, which will supply 650-700V to the high voltage DC
bus of the multilevel inverter. Finally we will construct a Three-Phase Energy
meter to display the energy being consumed by the inverter. This energy meter
will be capable of saving data and logging it onto to the internet

1.2 Block Diagram

8 | University of South Asia


Figure 1.1 Block Diagram

1.4 Research Methodology


The methods that will be carried out in order to complete the research are
illustrated in the flowchart Fig.1.1.

Online research Simulation and Designing Boost Three-Phase Grid-


material and books analysis in MATLAB Converter DC-DC Tie Inverter
for inverter design SIMULINK

Designing Three- Future


Phase Energy Meter Work/Conclusion

Figure 1.1 Research Methodology Flowchart

1.5 Organization of the Report


The thesis consists of eight chapters. A short explanation of the chapters are
provided below

9 | University of South Asia


Chapter 1: Introduction

This chapter gives the introduction about the thesis. Also it describes the need
of the project, objectives that will be achieved and research methodology
regarding the project.

Chapter 2: Literature Review

This chapter is about the various research papers used to inquire information
about our project

Chapter 3: Simulation of Inverter

This chapter is related to all the modules and techniques used to design a PV
Grid-Tie Inverter. Basic characteristics of a PV module are analysed in the start
of chapter. Then single phase and three phase inverter topologies of PV
inverters are compared to each other. Different types of boost DC-DC
converters, MPPT algorithms, AC-DC converters are described ahead in the
chapter. Also different switching modulation techniques are mentioned. In the
end description about protection systems, harmonics in system and different
type of switching semiconductors are described.

Chapter 4: DC-DC Converter

In this chapter different topologies of inverters are compared, in terms of cost,


efficiency and reliability. Then the PV array module and its characteristics are
modelled In Matlab Simulink software. The DC-DC boost converter with
MPPT controller is modelled in the next stage. Then the DC-DC boost
converter is attached to a VSC three phase DC-AC converter. A complete
standard grid with all the essential attributes is also modelled in this chapter.
Finally the simulation and analysis of the complete PV system is done.

Chapter 5: DC-AC Inverter

This chapter is about the wind systems and its different components. This
chapter begins with different types of wind turbines and generators. Then
different control methods used for wind turbines are mentioned. Also power
converter and grid topologies for wind systems are described. Finally the
typical characteristics of a standard wind turbine are described in the chapter.

10 | University of South Asia


Chapter 6: Conclusion & Future Work

The chapter summarizes the entire research project and the outcomes achieved
in it. Also future work regarding the enhancement of the project is discussed in
the end.

11 | University of South Asia


CHAPTER # 2
Literature Review

12 | University of South Asia


Chapter 2
2.1 Background

Multi-level Inverter is burning topic of the era and its implementation in


FACTS devices is on the top of IEEE spectrum. The concept of MLI came into
existence in the year 1975.Nabae was the first person who introduces the
concept of the multi-level inverter. This was developed while he was trying to
improve the two-level inverter. He had used a neutral point of dc to construct
three levels. This inverter was first presented as neutral point clamped three-
level inverter. A lot of work is going on in the field of increasing efficiency and
reducing Harmonic distortions. Multi-level inverters reduce the harmonic
content in the output ac voltage waveform and thereby reduce the size of filters.

2.2 IEEE Power Quality Standards

As per IEEE Facts (Flexible AC Transmission system) is defined as “a power


electronics based system and other static equipment that provide control of one
or more AC transmission system parameters to enhance the controllability and
increase power capability”.

These Facts devices are classified as:

 Series compensator
 Shunt compensator
 Combined series compensators
 Combined shunt compensators

Figure 2.1 Voltage Distortation Limits

13 | University of South Asia


2.3 Multilevel Inverter Applications

Multi-level inverters have lots of applications such as in FACTS (Flexible AC


Transmission System) as active filters D-STATCOM (Distribution- STATic
synchronous COMpensator), T-STATCOM (Transmission-STATic
synchronous COMpensator), UPFC (Unified Power Flow Controller) and
UPQC (Unified Power Quality Conditioning). Beyond FACTS as in
conventional applications such as solar energy conditioning and Electrical
drives where VFD control is required.

IEEE definition of STATCOM is a subset of the broad-based shunt connected


controller which includes the possibility of an active power source or storage
on the dc side so that the injected current may include active power [10]. In the
year 1976 Gyugyi proposed the concept of STATCOM. In the case of D-
STATCOM (Distribution synchronous STATic COMpensator) two-level
bridge converter of low capacity can be used at much higher switching
frequency [11]. These converters are connected at medium voltage bus using a
step-up transformer. In the case of T-STATCOM as capacity is high the static
switches must be triggered at low frequencies. So in T-STATCOM system
three-level neutral point clamped inverter is used [11], [12], [13], [14]. In [15]
author presents the analysis of dead-time how it effect the harmonics of three-
level. NPC inverter. Hybrid-STATCOM with low voltage on dc side reduces
the cost of the system [16].Lots of theory are proposed for controlling
STSTCOM such as p-q theory [19], [20], [21] and d-q theory [17], [3], [14],
[18]. In [23] fixed modulation index based STATCOM is presented with
variable dc capacitor voltage this STATCOM is used to compensate voltage
fluctuations.

14 | University of South Asia


CHAPTER # 3
MATLAB Simulations

15 | University of South Asia


Chapter 3

3.1 Simulation constraints and parameters

The simulation for the different modulation strategies are carried out in open
loop, since the purpose is to make a comparison between the performance of
the system with synchronized pulses, shifted pulses and the proposed system
using two-level SVM. In addition, simulation results of the inverter will be
briefly discussed. By running the system in open loop it can be observed what
amount of THD and which harmonics the different strategies will generate.

 Simulation Parameters:
 Power for each inverter = 2kW
 VDC = 700V
 Carrier frequency fcarrier = 5000Hz
 Modulation index ma = 0.9 (Vref = 280V)
 Three-phase load inductor = 7.2mH
 Load resistor = 40

3.2 Simulink Block Diagram of 2 level 3 phase Inverter

16 | University of South Asia


Figure3.1: Subsystem for Sector evaluation

Figure 3.2: Subsystem of Phase voltage and Line voltage generation

17 | University of South Asia


Figure 3.3: Space vector switching pattern for upper switches

Figure 3.4: Phase voltage Vdc=400; 2/3vdc=267 ; 1/3vdc=133

Line voltage THD=2.60%

From simulation it can be seen that the Total harmonic


distortion (THD) and lower order harmonics (LOH)
contents are very less in SVPWM.

18 | University of South Asia


CHAPTER # 4
DC-DC Boost Converter

19 | University of South Asia


Chapter 4 DC-DC Converter

4.1 DC to DC Topologies:
A switching mode DC to DC converter is a simple device that converts low
voltage level to high voltage level. Boost convertors are really important part of
any modern day solar invertors. As solar cells alone or even when combined
together in different configurations, cannot provide the sufficient voltage
output levels. Three phase voltage output are usually around 480-500V and to
achieve such voltage levels DC voltage output from the panels must be boosted
accordingly. Boost converter functions by increasing the VDC to a higher value
by controlling the duty cycle of signal generator. There are three types of boost
converters: Buck Boost converter, Boost converter and CUK converter. Basic
circuit all these three converters contain the same four components that are:
capacitor, inductor, diode and a switching component like an MOSFET/IGBT.
The only difference is the arrangement of these components in their respective
circuits.

Buck-Boost Converter

Buck-Boost converter is a DC-DC converter which can convert the voltage


levels to lower or greater than the input voltage. Simple buck converter is a
step down converter and when coupled with a boost converter it becomes a
buck-boost converter. Buck-Boost converter is very similar to a fly back
transformers converter, with exception of the transformer in the circuit. Fig.4.0
shows the basic circuit of a buck-boost converter.

Figure 4.0 Basic Model of a DC-DC Buck Boost Converter

When the switch S is turned on, energy starts to accumulate inside the inductor
L. At this point capacitor C starts supplying energy to the output load. While

20 | University of South Asia


the switch is turned off the energy in inductor is supplied to capacitor and
hence from C to the load R. MOSFET's or IGBT's are usually used as a
switching component that is controlled through a high frequency signal
generator.

CUK Converter

CUK converters are another type of DC-DC converters that can boost the input
voltage levels to the desired level. CUK converters are mostly used in
applications where a battery needs to be charged. CUK converter basic
circuitry consists of two inductors, two capacitors, a diode and switching
component (IGBT/MOSFET). CUK converters output is always inverted,
meaning the voltage is negative at the output. Fig.4.1 shows a CUK converter.

Figure 4.1 General Model of a CUK Converter


Two capacitors are used to transfer the energy and are connected at input and
the output as shown in the figure above. Two inductors are also used to convert
the voltage at the input and output into current sources. Also inductors for a
short period of time could be considered as a current source. Charging the
capacitor through a current source increases the efficiency by preventing the
resistive current limiting [21].

BOOST Converter

Boost converter is the most widely used DC-DC converter to boost the input
DC voltage. The key thing to all the boost converters is the property of an
inductor. As inductor can resist the current changes it undergoes by generating
or destroying a magnetic field. In all boost converters output can never be less
than the input. Fig.4.2 shows basic circuit diagram of a boost converter.

21 | University of South Asia


Figure 4.2 DC-DC Boost Converter Model
When switch S is closed, current starts flowing in clockwise direction through
the inductor L. This generates a magnetic field around the inductor with the
right side having negative polarity and left side with positive. When the
switched is opened the magnetic field that was generated at the start will be
destroyed and current will start decreasing due to high impendence. The
polarities will be different now with left side having negative and right side
with positive. This causes the both sources to be in series configuration
resulting in a high voltage build-up across the capacitor. This high voltage will
charge the capacitor through the diode. As Signal generator switches the gate
of a MOSFET at a fast pace, there won't be enough time for the inductor to be
discharged. As a result the load will always see a voltage greater than the input
DC source. Load current remains the same throughout the entire process.
Calculations for the DC-DC boost converter can be calculated using the
equations (4.1) and (4.2).

 Inductance L=D(1-D)R/2*F Equation (4.1)

 Capacitance=D/2*F*R Equation(4.2)

Where D stands for duty cycle that can be calculated as D= 1- Vin/Vout, R is


denoted for the resistance, F is the switching frequency that equals to F=1/T.
Once voltage output from the PV panels and the desired output voltage level is
known. Values for the duty cycle, inductance and capacitance can be found out.
Switching frequency in the converter also needs to be adjusted while
calculating values for inductance and capacitance.

The input can be through renewable energy sources or by storing in battery by


anyway. Mostly input gets by solar PV cells it is an easy way to produce
energy. Comparing the linear power supply and a switched mode power supply
the benefit with a switched mode converter over the linear one is: size, weight
and efficiency [1]. This is due to higher frequencies, allowing the usage of
smaller transformers using ferrite cores. DC to DC topologies depends on two
stages such as ON and OFF. Then there is a major downside this is noise.

22 | University of South Asia


These noises caused by high switching speed. Higher frequencies increase the
switching losses and transformer core losses. Due to higher frequencies prefer a
smaller ferrite core transformer. Then we use low power losses components
such as ferrite core transformer,capacitor, inductors and switching MOSFET.
There are several switched mode DC/DC topologies. The ones focused on in
this paper are doubled ended push-pull topologies, which mean that the flux
swing in the transformer primarily is bi-directional (see fig.4.3). This allows
more power handling compared to single ended ones, which use a uni-
directional core excitation where only the positive first quadrant is used [2].

Figure 4.3Uni-Directional and Bi-Directional flux swing

4.2 Modules of DC-DC Converter


The push-pull converter operates alternately two switching transistors they
are never ON same time. The basic push-pull topology shown in the figure.
It contains a pair of switches S1 and S2, a centre tapped transformer, a full
wave rectifier with diodes D1 and D2 in the secondary, an output filter
inductor L and an output capacitor C. According to the ON/OFF states of the
switches S1 and S2the converter has the following switching modes [3]

Mode 1:- when S1 is ON and S2 is OFF, the diode D1 is forward biased and
D2 is reverse biased.
Mode 2:-when S2 is ON and S1 is OF, the diodeD2 is forward biased and D1 is
reverse biased.
Mode 3:- when S1 and S2 are OFF, the diodes D1 and D2 are forward biased.
The frequency on the secondary side voltage pulses twice the switching
frequency of the transistors [4].

23 | University of South Asia


Figure 4.4 Circuit diagram of a push-pull converter

The output can be expressed by equation 4.3:-


 Vout= 2.Vin.D.Ns/Np (4.3)
 D is duty cycle
 Ns/Np is turns ratio.

Half-bridge:

Compared to a push-pull converter, the half-bridge converter does not have a


centre tap on the primary side. The input capacitor split the input voltage
equally so that the primary only faces half the input voltage when either
transistor is turned ON[5].The output can be expressed by equation 4.4:-

 Vout=Vin/2 .D.Ns/Np (4.4)

24 | University of South Asia


Figure 4.5 Circuit diagram of a Half-bridge converter

Full-bridge:-
Four switching transistor use in full-bridge convertor. They are switched
alternately pair wise. Due to high cost and complexity, the full-bridge topology
is used in very high power applications [6].The output is full wave bridge
configuration with approximately half number of secondary turns.

Figure 4.6 Circuit diagram of full-bridge converter

4.3 Topology selection:-


The push-pull topology finally chose for implementation because of its easy
implementation as compared to other. Multiple stages increase the power
rating.The choice of MOSFET is limited due to the fact that twice the input
voltage is required and the availability of high voltage with high current ratings
is limited [1].

25 | University of South Asia


PUSH PULL CONVERTER DESIGN AND CIRCUIT:-
The circuit and calculation given are to step up 12V DC supply to 325V DC to
deliver 1KW and Power. SG3525 push-pull SMPS controller is used.

Figure 4.7 SMPS Controller


Basic component of push-pull converter:-
We use in highly efficient component for reducing the power losses and
reducing size of our overall project. Our main task is reducing the size of our
project.
According to our requirement we use these component:

1. Gate driver
2. Ferrite Core Transformer E65/32/27
3. Inductor
4. Capacitor
5. MOSFET IRF3808
6. Ultrafast Rectifier diodes MUR1560

26 | University of South Asia


Power Semiconductor switches

Introduction
The development of semiconductor devices has made converters more
affordable in a large number of applications. This is due to increased power
capabilities, easier control and reduced cost of modern power semiconductors.
Currently the power semiconductors can be classified into three groups
according to their controllability [7]:
1. Diodes controlled by the power circuit
2. Controllable switches turned off and on by a control signal
3. Thyristors, latched on by a control signal but turned off by the power circuit

IRF3808:-
Switching behavior
The switching times of a power MOSFET are
Determined by the speed at which its internal capacitances can be
Charged and discharged by the chosen drive circuit [8].
Therefore the switching characteristics of the power MOSFET are determined
by its
Three internal capacitances. These capacitances are not fixed but are a function
of
The voltages between the MOSFET’s terminals.
Switching performance
Turn-on
During the turn-on phase the following parameters are of relevance [9]:
1. Turn-on time
2. Turn-off loss
3. Peak dv/dt
4. Peak dI/dt
The turn-on time is simply determined by the speed of which the drive circuit
can charge the gate.

27 | University of South Asia


Figure 4.8 IRF 3808PBF Datasheet

Diodes

A diode begins to conduct when it is forward biased. The voltage drop across
the device is small, on the order of 1 V depending on the diode type. When the
diode instead is reversed biased, a small negligibly leakage current will flow
until the reverse breakdown voltage level is reached [10].
A diode can be considered as an ideal component at turn-on because it turns on
more rapidly than the transients in the power circuit. At turn-off the current
instead reverses for a time trr before it falls to zero. This phenomenon occurs
because excessive carriers have to be swept out and block a negative voltage.
The circuit symbol can be seen in figure 4a, the steady-state i-v characteristic
and its idealized characteristics in figure 4.9.

28 | University of South Asia


Figure 4.9 Characteristics Steady state
Ultrafast Rectifier diodes MUR1560:-
The Ultrafast Rectifier is designed for use in switching power supplies,
inverters and as free wheeling diodes [11].
Features

1. Ultrafast 35 and 60 Nanosecond Recovery Time

2. 175 C Operating Junction Temperature

3. High Voltage Capability to 600 Volts

4. Low Forward Drop

5. Low Leakage Specified @ 150 C Case Temperature

6. Current Derating Specified @ Both Case and Ambient Temperatures

Gate driver:-
We use gate driver for generating high frequency signal and it’s generate two
signals for operating push-pull MOSFET. The frequency of gate driver is 40
kHz and it’s generate two signals of 40 kHz frequency which use for operating
MOSFET.

29 | University of South Asia


Schematic gate driver:-

Figure 4.10 This is the schematic diagram of our push-pull gate


driver

Main components of gate driver:-


1. SG3525
2. Totem Pole Transistors

SG5325:-
SG3525 use for generating PWM. SG3525 has 16 pins IC
Every pin has own function and importance for generating signals.

30 | University of South Asia


Figure 4.11 SG3525 Diagram
SG3525 diagram
Pins 1 is Inverting Input and pin 2 is Non Inverting. This functions use to
increase or decrease the duty cycle depending on the voltage levels on the
Inverting and Non-Inverting Inputs.
1. When voltage on the Inverting Input pin1 is greater than voltage on the
Non-Inverting Input pin2 then duty cycle is decreased.
2. When voltage on the Non-Inverting Input pin2 is greater than voltage on
the Inverting Input pin1then duty cycle is increased.

The frequency of PWM is depend on the timing capacitance and the timing
resistance.

The frequency is related to RT, CT and RD by the relationship:

Calculation:-
Timing Capacitor CT= 0.01 µF
Timing Capacitor RT= 3.3 KΩ
Deadtime RD= 0 Ω
Maximum duty cycle Dmax = 49%

31 | University of South Asia


Frequency of oscillator FOSC = f == 1 / (0.01*10-6 * (0.7 *3.3*103 + 3 * 0)) =
43.2 kHz
Switching frequency Fs = f / 2 = 43.2 / 2 = 21.6 kHz
Switching time period T = 1 / Fs = 1 / 21.6x103 = 46.2 µS T/2 =23.1µS
Minimum input voltage Vmin = 10.5V
Drain source on voltage VDS (on) = 1

Pin16 is the output from the voltage reference.


Pin15 is VCC -the supply voltage to the SG3525 that makes it run.
Pin13 is VC -the supply voltage to the SG3525 driver stage.
Pin12 is the Ground connection.
Pin11 and pin14 are the outputs from which the drive signals are to be taken.
Pin10 is shutdown. When this pin is low then PWM is enabled. When this pin
is high, the PWM latch is immediately set.
Pin9 is compensation. It may be used in conjunction with pin 1 to provide
feedback compensation.
Gate driver testing:-
43 kHz frequency
Gate driver test by oscilloscope and get the required signals.
Actually we have two signal with same frequency and just have Nanosecond
timedelay ON/OFF.

32 | University of South Asia


Figure 4.12 Gate driver test Shown on oscilloscope

PCB design of gate driver:-

PCB make on easyEDA before pcb design we make it on breadboard and


perform testing. Then make pcb

Figure 4.13 PCB Design

33 | University of South Asia


Recommended operating conditions:-

Table 4.1 Illustrates operating conditions

Ferrite core transformer :-

Ferrite are ceramic compound which are the mixer ofIron oxide (Fe2O3).
Ferrite cores are used in Transformers where the supply voltage has a high
frequency. Its work near 70MHz.our simple transformer never b handle this
frequency.
Core material
As the purpose of the thesis is to implement a DC/DC converter that operates at
frequencies up to 1 MHz, the ferrite core is chosen to have low losses at those
frequencies. Ferroxcube is a leading supplier of ferrite components [7].

Why we chose ferrite core transformer?

Ferrite has a high permeability which make it suitable for use as a core for
higher frequencies. It also very highly resistivity. This ensures that eddy
currents and hysteresis losses are minimum.
The combination of high permeability and high resistivity make Ferrite ideal
for high frequency transformer core design. The only disadvantage is that being
a ceramic it is brittle and is vulnerable to cracks [2]

Selection of turn ratio:-

34 | University of South Asia


For selection of turn ratio and other parameter are select by powersim software.
PowerSim tell us about all parameters according to our requirements.

What is powerESim?
PowerESim is a tool that allow you to complete a switching power design in
few minutes. It is a tool that allows you to design without looking at
component datasheets or design equations. It is a tool that brings engineers and
components vendors closer together separated only by a click on the web.
Switching power supply design is a tedious process. Although the know-how
and design techniques for popular circuit topology are largely known to design
engineers, the many choices of electronic components make it a very tedious
process for engineers to recalculate for the whole design every time he changes
a component. There are numerous combinations of electronic components that
can be used in a single circuit, and very often the choice of components is
critical to the success of the product both in terms of product performance and
market competitiveness. The design iteration process is time consuming and
can be erroneous if done manually. Now here is a tool that can do all this
automatically in seconds [3]

Figure 4.14 Component Calculator


Ferrite transformer turns calculation:-
Turns ratio of ferrite core transformer for high frequency switchmode power
supply inverters. High ferrite core transformers are used in almost every power
electronics circuits like inverters and pure sine wave inverters. They are used to
35 | University of South Asia
boost up or step up low dc voltage of battery and other dc sources like solar
panels. Ferrite core transformers are also used in isolated dc to dc converters to
step up or step down dc voltage.
Ferrite core selected for Transformer: E 65/32/27
Area of ferrite core Ae = 540 mm2
Max flux density Bm = 0.1 Wb/m2 (for push-pull configuration)
Air gap = 0
Push pull topology ferrite core turns ratio calculation:-
We want to design a 1k watt boost up dc to dc converter. We are using push
pull topology for this design. We are using 12 volt battery. We want to step up
dc voltage from 12 volt 350 volt. Switching frequency of design is 40 KHz. We
are using ETD39 ferrite core which can handle 1000 watt. It is beyond the
scope of this topic to tell how to select ferrite core according to power rating.

Figure 4.15 Turn Ratio Calculation


Ferrite transformer primary turns calculation:-
Battery voltage does not remain same all the time. As the load on battery on
increases, battery voltage will be less than 12 volt. With no load with fully
charged battery, battery voltage will be near to 13.5 volt. Therefore input
voltage is not constant, we must consider it while calculating turns ratio of
ferrite core transformer. Cut off voltage for battery is usually 10.5 volt. We
can take it as smallest possible value of input voltage to boost up dc converter.
So we have following parameters now:

Vinput = 10.5 volt


Vout=350 volt
Formula of turn’s ratio calculation in transformer is
N = Npri / Nsc = Vin / Vout
Where Npri is number of primary turns and Nsc is number of secondary turns.
We have three know variables like turns ratio which can be calculated by above

36 | University of South Asia


equation, input voltage and output voltage. But we need to calculate primary
turns to find secondary turn of ferrite core transformer. Formula to calculate
primary turns for ferrite core transformer is given below:

Primary turns Np (min) = Vi x T/2/ΔB x Ae


Np(min) = (10.5-1) x 23.1x10-6 /2 x 0.1 x 540x10-6
Np(min) = 2.03 T

Take primary turns Np as 3 Turns

But for push pull it will be half the primary number of turns.
Where Npi is primary number of turn, Vin( nom) is normal input voltage
Bmax is maximum flux density.
T/2 is switching time and is equal to 23.1x10-6s
Ae is Effective magnetic cross section of ferrite core. We have to refer data
sheet for this value. In this example, we are using ETD39 core. The effective
cross sectional area of E 65/32/27is 540mm2.

We have all the values to calculate primary number of turns.


By putting these parameters in two above formula, we can calculate turns
primary number of turns.

Hence Npri = 3
Its mean we can take Npri = 3 for further calculations. Primary number of turns
for push pull ferrite center tap transformer is 3 turns + 3 turns.

Ferrite transformer secondary turns calculation:-


So we know all values to calculate secondary turns of ferrite core transformer.
Output Voltage Vo = 325V
Dmax=0.49
Diode voltage drop Vf = 1V
Secondary Voltage Vs = (Vo + 2 x Vf) / (2 x Dmax)
= (325 + 2 x 1) / (2 x 0.49)
= 334 V
Secondary Turns Ns = Np x Vs / Vi
= 3 x 334 / 9.5
Secondary Turns Ns = 106 Turns

So number of primary turns is equal to 3 and number of secondary turns is


equal to 106. So it is all about turn’s ratio calculation for high frequency
transformers.
Selection of wire gauge

Output Power = 1000 W


Output Current Io = 1000 / 325 = 3.1 A
J = I/A

37 | University of South Asia


J = current density in amperes/m2
I = current through a conductor, in amperes=3.1A
A = cross-sectional area of the conductor, =540mm2

J=3.1/540m=5.7A/m2
Take current density of 5 A/mm2
Secondary wire cross section area = 3.1 / 5 = 0.62 mm2

So 20 SWG wire selected for secondary winding.

Assume efficiency = 85%


Input power = 1000 / 0.85 = 1176 W
Input current = Pi / (Vmin x 2 x Dmax) = 114 A
Per limb Input Current = 114 / 2 = 57 A

As primary turns are only 3, higher current density may be allowed (9 A/mm2).
Primary wire cross section area = 57 / 9 = 6.3 mm2

Primary wire cross section area=2x3.15=6.3mm2

So 2 x 14 SWG wire selected for primary winding / Limb.

Design of Output Inductor L:-


Assume the maximum input voltage of 12 V under fully loaded condition
Secondary voltage= Vs = Ns x VI / Np = 106 x (12-1) / 3
= 389 V
MOSFET on Time Ton = VO*T/2/ (Vmax-1) = 23.1 x 325 / (389 - 2)
= 19.7 µS
Voltage applied across Output inductor VL = Vs - 2 x Vf – Vo
VL = 389 - 2 – 325
VL = 62 V

Assume Maximum allowed current ripple ∆Io = 0.3 x Io =0.3x3.1= 0.93 A


Inductance L = e x dt / di
Output Inductor L = 62 x 19.7x10-6/ 0.93
Output Inductor L = 1.3milli Henry
Peak Inductor current Ipeak = Io + ∆Io / 2 = 3.1 + 0.93 / 2
Ipeak = 3.6 A

Ferrite core selected for Output Inductor: E 42/21/15


Cross section area Ae = 178 mm2
Saturation flux density Bsat = 0.35 Wb/m2
From datasheet of core AL = 3600 nH/T2
Minimum Inductor Turns N = L x Ipeak / (Bsat x Ae)

38 | University of South Asia


= 1.3x10-3x 3.6 / (0.35 x 178x10-6 )
Inductor Turns N = 76 Turns
Air gap required = µo x Ae x ((N2 /L) – (1/AL))
= 4 x π x 10-7x 178x10-6 x ((76 / 1.3x10-3 ) – (1/3600x10-9
))
= 0.93 mm
Per limb Air gap = 0.93 / 2 = 0.465 mm

Same secondary current flows through this inductor also, so the same 20 SWG
wire may be used.

Ferrite Core Transformer Testing

A Sawtooth wave of peak 473Volts under 100W Load is observed

39 | University of South Asia


PCB Design

\
Final Prototype

40 | University of South Asia


CHAPTER # 5
DC-AC Inverter

41 | University of South Asia


Chapter 5 DC-AC Inverter

5.1 Three Phase Solar Inverters

Three phase PV inverters are commonly used in large scale commercial


applications that use electro-mechanical loads such as industries. Three phase
power is mostly used in grids all over the world for power transmission and
distribution. As they offer better efficiency and reduction in operating losses.
Using three phase power systems saves up cost by reducing the size of wires
and electrical equipment due to reduction in current requirement. In case of
three phases there are 4 wire legs with three of them carrying power and fourth
is neutral. Three phase power systems can offer different configurations such as
delta and wye. In case of wye connection of 208/120V , each of the three
power wires are providing 120V and have 120 degree phase shift from each
other .

Figure 5.1 Three-Phase connections

Figure 5.3 Three-Phase Three level DC-AC Inverter

42 | University of South Asia


5.2 Space Vector Modulation:

SVM technique is more complex compared to SPWM, it significantly reduces


the harmonic distortions at the output and also efficiently uses the supply
voltage, compared to SPWM. The main task of SVM is to approximate the
output voltage vector U_out by a combination of different switching patterns.
The phase voltages are mapped by using the corresponding eight switching
combinations onto a dq plane. For that, a dq transformation is performed which
is equivalent to the projection of the switching patterns [a b c] into two
dimensional plane which is perpendicular to the vector [1 1 1], this results in
the generation of eight vectors which form an hexagon as U0, U60, U120,
U180, U240, U300, U000 and U111. Among the eight vectors, six are non-zero
and two are zero vectors which apply zero voltage to the output of load or grid.
The envelope formed by the eight basic space vectors as shown in Figure 3.16,
is the locus of maximum U_out voltage and the magnitude of U_out is limited
to the shorted radius of the envelop when it is a rotating.

5.3 Working Principle


 The circuit model of a typical three-phase voltage source PWM inverter
is shown in above.
 S1 to S6 are the six power switches that shape the output, which are
controlled by the switching variables a, a’, b, b’, c and c’.
 When an upper transistor is switched on, i.e., when a, b or c is 1, the
corresponding lower transistor is switched off, i.e., the corresponding a′,
b′ or c’ is 0.
 Therefore, the on and off states of the upper transistors S1, S3 and S5
can be used to determine the output voltage.

Figure 5.4 Space Vector Switching Pattern

43 | University of South Asia


5.4 Gate Driver Circuit

TLP250 as Low Side Driver

Figure 5.5 Space Vector Switching Pattern

TLP250 as High Side Driver

Figure 5.6 Space Vector Switching Pattern

44 | University of South Asia


5.5 PCB Design

Figure 5.7 Phase Bridge with Filtering

45 | University of South Asia


Figure 5.8 Gate Driving Circuit

46 | University of South Asia


Figure 5.8 Inverter Output

47 | University of South Asia


CHAPTER # 6
Three Phase Energy Meter

48 | University of South Asia


Chapter 6 Three-Phase Energy Meter

6.1 Purpose of energy meter


• Modern Grid Tied Inverter control active and reactive power to support
grid with a lagging Power Factor by providing reactive power for
inductive loads.

• Over load, short circuit and over voltage protection using interrupts.

• Energy monitoring and Internet data logging.

Figure 6.1 Tesla’s Energy Meter For Grid Tied Inverters

6.2 Design of energy meter

The basic design of our energy meter consists of three current transformer and
voltage transformers connected to the output of the three-phase inverter.
Atmega2560 measures current and voltage and uploads the values to the
internet using ESP8266. Finally energy consumption graph is drawn on the
website hosting our meter values

49 | University of South Asia


6.3 Energy Meter Schematic Diagram

Figure 6.2 Circuit Diagram

6.4 Real Power Calculation

Instantaneous power is calculated by atmega2560 by multiplying instantaneous


voltage with instantaneous current. Actual power is the average of
instantaneous power of a number of samples. Formula for real power in
discrete time is the following

50 | University of South Asia


Real Power Definition in Discrete Time

Following is the arduino code for calculating real power:

6.5 RMS Voltage and Current Measurement

The discrete time equation for calculating current/voltage RMS is as follows:

An RMS value is the square root of the mean value of the squared
instantaneous values, averaged over one complete AC cycle.

51 | University of South Asia


Following is the arduino code for calculating RMS voltage and current:

Apparent power = RMS Voltage x RMS current

6.6 Zero-Crossing Voltage Detector For Power Factor Calculation

We have used zero-crossing concept to measure phase difference between


current and voltage waveforms of the inverter, to find if the inverter is working
at leading or lagging power factor. The signal from current transformer starts
timer 0 and generates an interrupt service routine when it crosses zero. The
signal from potential transformer stops the timer by generating another
interrupt service routine.

From the time difference between these two waves, we calculate the phase
difference. Since we know the crystal frequency is 16MHZ and machine cycle
takes 0.3uS hence we can easily find the phase difference.

6.7 Implement Zero Crossing Detector Using Arduino

52 | University of South Asia


Testing Zero Cross Detector Code

Digital Pin 9 Turns High whenever AC Sine Wave Crosses Zero

Figure 6.3 Zero Cross Detector

53 | University of South Asia


6.8 PCB design

Figure 6.4 PCB Design

54 | University of South Asia


CHAPTER # 7
Conclusion and Future Work

55 | University of South Asia


Chapter 7 Conclusion and Future Work

7.1Summary &Conclusion
In this thesis, the focus of research work is on the importance of renewable
energy, development of Grid-Tie inverters for PV and wind, development of
utility grid and finally the use of multi-level inverters. Main attention is paid on
development of these technologies on the basis of cost, efficiency and
reliability. The research was also carried in areas of, different control
modulation techniques, development of MPPT controller and different
wind/PV related devices.

Renewable Energy

The Investigation into the importance of renewable energy was done using the
worldwide statistics for wind and PV related devices. The trend clearly is
shifting globally towards the RE technologies. Every year more than 50 percent
of the new energy projects are based on RE. As due to the increase in
development of these technologies over the last decade, cost/watt output
through RE is clearly decreasing. As Europe is far from the equator, it doesn't
receive too many sunny hours yearly. Therefore, wind energy is commonly
used in Europe. As the energy demand continues to grow, fossil fuels cannot
keep up for too long. Also fossil fuels are hindrance in the path of preservation
of environment; governments are investing more in cleaner form of energy. As
due to these facts, it justifies the research being carried on RE technologies.

Development of PV Grid-Tie Inverter

The design of the 1MW grid tie PV inverter is based on string and multi string
inverter topologies. These topologies were selected to increase the efficiency
and reliability of system. The PV inverter compromised of PV panel, DC-DC
converter and DC-AC converter. Total of 10 PV panels modules were used,
each module compromised of 8 series and 66 parallel solar cells. The power
output from each PV module was 100KW at MPP. Each PV module has its
own DC-DC boost converter with a built-in MPPT controller. This
configuration increased the efficiency of system greatly, as each individual
module can track down its own MPP. The MPPT controller successfully tracks
the MPP point as the irradiation varies. The DC-DC output was regulated at
500V, through a grid side PWM based voltage regulator. For the DC-AC part
three phase three level voltage source converter (VSC) was used. The output of
VSC was attached to a choke and capacitor bank before injecting the power
into the grid. Power was injected by stepping up 260V, 50 Hz voltage to 25KV
(distribution level voltage) by a three phase transformer. The power of 1MW
was successfully transferred into the grid.

56 | University of South Asia


Development of Wind Grid-Tie Inverter

The design for Grid-Tie inverter is based on permanent magnet synchronous


generator (PMSG). Most of the new worldwide research work has proposed
models based on PMSG. These generators don't require a gearbox, are very
efficient, reliable and can be controlled easily. The proposed wind system
compromises of PMSG machine, wind generator, three phase AC-DC rectifier
and DC-AC converter.

Development of Utility Grid

The proposed utility grid has all the essential components of a standard grid.
For the distribution level 25 KV voltage level is used. The total transmission
line (Feeders) in the system is 30KM. These feeders act like a bridge between
the distribution and transmission level. Two loads of 30MW and 2MW are
attached to the grid. Transmission level is maintained at 120KV using a three
phase voltage source. A step-up transformer is used to connect the distribution
level of 25KV to 120KV transmission level. Also a grounding transformer is
used to create a neutral point in a three phase system.

Development of Multi-Level Inverter

The inverter is based on 9 level cascaded H-bridge configurations. The design


was selected as it offers every n level for (n-1) H-bridges. This reduces the cost
of overall multi-level inverter. Also the reliability of multi-level is better than a
one level. As the units are split in many parts, it makes the system redundant in
case failure of any unit.The system has 8 single phase H-bridges connected in
series together. The switching frequency is varied using pulse generators of all
the eight h bridges. Also the dc source for all 8 H-bridges is kept constant. This
approach successfully implements a low cost, efficient and reliable 9 level
converter, which has an output waveform close to a pure sin wave.

7.2Future Work

For the thesis models for PV and wind grid-tie inverters and multi-level
inverter are proposed.For the future development and enhancement of the
models, these factors can be investigated:

Implementation of Model in Real-Time

The proposed models for wind and PV are only implemented using simulation
software. In actual scenario many of the factors may affect the system. So a

57 | University of South Asia


thorough investigation needs to be done by implementing the proposed models
in real-time.

Multi-Levelfor Grid-Tie Inverters

The future work can be carried in enhancing the wind and grid inverters by
using more levels for the inverter design. For this thesis only three level VSC
converters are used for PV and Wind. To improve the output, more levels
based VSC can be adopted.

Modulation Control Techniques

There are many new modulation techniques such as space vector pulse width
modulation (SVPWM) or multi-level pulse width modulation that can offer
better control and harmonic suppression in the system. For the wind systems,
Matrix Converter Modulation can be used. Matrix Converter Modulation
increases the efficiency of wind systems considerably.

New Semiconductor Devices

There are new semiconductor devices based silicon carbide (SiC) and gallium
nitrate (GaN). These semiconductors devices can be used in inverters to
improve the efficiency and reliability of system even more. So for the future
work, the proposed models in this thesis could be used with SiC and GaN
based semiconductors.

Integration of Wind & PV Systems

The proposed models of PV and wind systems can be integrated together for
the future work. These types of systems are called as hybrid systems,
containing different types of power generation elements. This can be helpful to
analyze the behavior of PV and wind systems when combined together.

58 | University of South Asia


REFERENCES

[1] WorldBank. (2010). Energy Povery. Available: http://web.worldbank.org/.


Last accessed 10th aug 2014.

[2]Conserve-energy. (2010). land pollution. Available: http://www.conserve-


energy-future.com/causes-effects-solutions-of-land-pollution.php. Last
accessed 01 aug 2014.

[3] tececo. (2013). basic fossil fuel facts. Available:


http://www.tececo.com/sustainability.fossil_fuel_facts.php. Last accessed 03rd
aug 2014.

[4] Simon Rogers. (2011). World carbon dioxide Emissions. Available:


http://www.theguardian.com/news/datablog/2011/jan/31/world-carbon-dioxide-
emissions-country-data-co2. Last accessed 5th aug 2014.

[5] Zachary Shahan . (2013). 18 Fun Renewable Energy Charts .Available:


http://cleantechnica.com/2013/11/07/renewable-energy-charts-renewable-
energy-facts/. Last accessed 5th aug 2014.

[6] Government UK. (2013). Renewable energy in 2013 . Available:


https://restats.decc.gov.uk/cms/welcome-to-the-restats-web-site/. Last accessed
06th aug 2014.

[7] European Environment Agency. (2013). EEA Technical report. An


assessment of environment constraints. ISSN 1725-2237 (1), p04-p15

[8] New and Renewable Energy Authority (NREA). Annual report 2010/2011..

[9] smith. (2013). solar technologies. Available:


http://depts.washington.edu/cmditr/modules/opv/solar_technologies.html. Last
accessed 07th aug 2014

[10] north carlolina solar center. (2011). solar center information. 7401. 2 (3),
p01-06.

[11] J. Haeberlin. Inverters evolution for Grid connected PV-Systems from


1989 to 2005. Munich, Germany, : 24th European Photovoltaic Solar Energy
Conference, Oct. 22 – Oct. 26, 2005.

[12] windea. (2013). small wind farm applications. Available:


http://www.wwindea.org/. Last accessed 08 aug 2014.

[13] Faiz Mohammad Bhutta. (2012). solar applications. Available:


http://www.altenergymag.com/. Last accessed 09 aug 2014

59 | University of South Asia


[14] jane. (2014). statistics uk wind generation. Available:
http://www.renewableuk.com/en/renewable-energy/wind-energy/onshore-
wind/. Last accessed 10 aug 2014

[15] dong energy. (2013). uk offshore wind farms. Available:


http://www.dongenergy.co.uk/en/uk_business_activities/renewables/windfarms
/pages/default.aspx. Last accessed 10 aug 2014.

[16] bibek mishra. (2009). PV grid-tie inverter. . 1 (2), p05-p30.

[17] pantec solutions. (2010). three phase power. Available:


https://www.pantechsolutions.net/power-electronics/three-phase-inverter. Last
accessed 11 aug 2014.

[18] Purnomo Sidi Priambodo. (2011). Electric Energy Management and


Engineering in Solar Cell System. . 52572 (1), p05-25

[19] James worden. (2010). How inverters work. Available:


http://solarprofessional.com/articles/products-equipment/inverters/how-
inverters-work/page/0/1. Last accessed 12th aug 2014.

[21] unknown. (2014). dc-dc converter. Available:


http://en.wikipedia.org/wiki/DC-to-DC_converter. Last accessed 14th aug
2014.

[22] David Sanz Morales. (2011). Maximum Power Point Tracking Algorithms
for Photovoltaic Applications. . 1 (1), pg8-p40.

[23] Carlos Silva. (2011). MPPT. Available:


http://paginas.fe.up.pt/~ee07308/pages/conversor.html. Last accessed 14th aug
2014.

[24] Gozuk. (2012). harmonic solutions. Available:


http://www.frequencyinverter.org/frequency-inverter-harmonics-
solutions.html. Last accessed 15 aug 2014.
[25] Electronic design. (). Igbt or mosfet , the better design. Available:
http://electronicdesign.com/interconnects/igbts-or-mosfets-which-better-your-
design. Last accessed 12th aug 2014.

[26] Purnomo Sidi Priambodo. (2011). Electric Energy Management and


Engineering in Solar Cell System. . 52572 (1), p05-25

[28] Mark. (2011). pv protection. Available: http://www.circuit-


protection.co.uk/latest-news/135-protection-of-photovoltaic-pv-systems. Last
accessed 10th aug 2014.

60 | University of South Asia


[29] David Sanz Morales. (2011). PV Grid-Tie Inverter.. 1 (1), pg8-p40.

[30] Prajwal Raval. (2009). REACTIVE POWER INJECTION CONTROL


METHODS FOR FAULT RIDE THROUGH CAPABILITY IN
DISTRIBUTED GENERATION. . 1 (1), p18-40

[31] David Whaley. (2012). Low cost small scale wind turbine. . 1 (1), p19-44.

[32] Prajwal Raval. (2010). Wind turbine generators. . 1 (1), p14-25

[33] Nathabhat Phankong. (2004). Three-Level Back-to-Back Converter


Simulation for Wind Turbine Energy Source. EMSES2012. 1 (2), p01-08.

[34] Christian Freitag. (2006). Variable Speed Wind Turbine equipped with a
Synchronous Generator. . 1 (1), p20-45.

[35] Nurul Aisyah Yusof. (2013). A Comparative Study of 5-level and 7-level
Multilevel Inverter Connected to the Grid. . 1 (3), p2-8.

[36] Surin Khomfoi and Leon M. Tolbert. (2009). Multilevel Power


Converters. . 1 (1), p04-30.

[37] Surin Khomfoi and Leon M. Tolbert. (2009). Multilevel Power


Converters. . 1 (1), p32-40.

61 | University of South Asia


Appendix

Matlab Code for Perturb and Observe Algorithm


function D = PandO(Param, Enabled, V, I)

% MPPT controller based on the Perturb & Observe algorithm.

% D output = Duty cycle of the boost converter (value between 0 and 1)


%
% Enabled input = 1 to enable the MPPT controller
% V input = PV array terminal voltage (V)
% I input = PV array current (A)
%
% Param input:
Dinit = Param(1); %Initial value for D output
Dmax = Param(2); %Maximum value for D
Dmin = Param(3); %Minimum value for D
deltaD = Param(4); %Increment value used to increase/decrease the duty cycle
D
% ( increasing D = decreasing Vref )
%

persistent Vold Pold Dold;

dataType = 'double';

if isempty(Vold)
Vold=0;
Pold=0;
Dold=Dinit;
end
P= V*I;
dV= V - Vold;
dP= P - Pold;

if dP ~= 0 & Enabled ~=0


if dP < 0
if dV < 0
D = Dold - deltaD;
else
D = Dold + deltaD;
end
else

62 | University of South Asia


if dV < 0
D = Dold + deltaD;
else
D = Dold - deltaD;
end
end
else D=Dold;
end

if D >= Dmax | D<= Dmin


D=Dold;
end

Dold=D;
Vold=V;
Pold=P;

Matlab Code for Boost Converter Calculation


%The following four parameters are needed to calculate the power stage:
% 1. Input Voltage Range: VIN(min)and VIN(max)
%2. Nominal Output Voltage: VOUT
%3. Maximum Output Current: IOUT(max)
clc;
disp('BOOST CONVERTER CALCULATION')
Vin=input('enter the minimum input voltage:: ');
Vin1=input('enter the maximum input voltage:: ');
Vout=input('enter the output voltage:: ');
I=input('enter the maximum output current:: ');
fs=input('enter the switching frequency:: ');
%calculation of maximum switch current
n=0.9;
D=1-((Vin*n)/Vout); %duty cycle
di=.2*I*(Vout/Vin); %inductor ripple current
L=(Vin*(Vout-Vin1))/(di*fs*Vout); %inductor value
%dv=(I/(1-D))+(di/2);
dv=0.5;
C=I*D/(fs*dv);%output capacitor value
R=Vout/I;
disp('*****************************')
disp('DUTY CYCLE::::')
D=D*100;
D

63 | University of South Asia


disp('RIPPLE CURRENT:::')
di
disp('INDUCTOR VALUE:::')
L
disp('VOLTAGE RIPPLE:::')
dv
disp('CAPACITOR VALUE micro farad:::')
C=C;
C
R
disp('**************************')

Arduino Sine Look-up Table


ifndef _FAST_SIN_H_INCLUDED_
#define _FAST_SIN_H_INCLUDED_

#if (ARDUINO >= 100)


#include "Arduino.h"
#else
#include "WProgram.h"
#endif
//#include "Wire.h"

// 91 x 2 bytes ==> 182 bytes


const unsigned int isinTable16[] = {
0, 1144, 2287, 3430, 4571, 5712, 6850, 7987, 9121, 10252, 11380,
12505, 13625, 14742, 15854, 16962, 18064, 19161, 20251, 21336, 22414,
23486, 24550, 25607, 26655, 27696, 28729, 29752, 30767, 31772, 32768,

33753, 34728, 35693, 36647, 37589, 38521, 39440, 40347, 41243, 42125,
42995, 43851, 44695, 45524, 46340, 47142, 47929, 48702, 49460, 50203,
50930, 51642, 52339, 53019, 53683, 54331, 54962, 55577, 56174, 56755,

57318, 57864, 58392, 58902, 59395, 59869, 60325, 60763, 61182, 61583,
61965, 62327, 62671, 62996, 63302, 63588, 63855, 64103, 64331, 64539,
64728, 64897, 65047, 65176, 65286, 65375, 65445, 65495, 65525, 65535,
};

64 | University of South Asia


float isin(int x)
{
boolean pos = true; // positive - keeps an eye on the sign.
if (x < 0)
{
x = -x;
pos = !pos;
}
if (x >= 360) x %= 360;
if (x > 180)
{
x -= 180;
pos = !pos;
}
if (x > 90) x = 180 - x;
// if (pos) return isinTable8[x] * 0.003921568627; // = /255.0
// return isinTable8[x] * -0.003921568627 ;
if (pos) return isinTable16[x] * 0.0000152590219; // = /65535.0
return isinTable16[x] * -0.0000152590219 ;
}

float icos(int x)
{
return isin(x + 90);
}

float itan(int x)
{
return isin(x) / icos(x);
}

#endif

Arduino Space Vector Algorithm

#include "FastSin.h"
#include <TimerThree.h>

#define debugPin (8)

65 | University of South Asia


//use timer3 for PWM
//T3A pin 5 ; T3B pin 2 ; T3C pin 3
#define phaseA (5)
#define phaseB (2)
#define phaseC (3)

unsigned int degree = 0; // to count degree: 0, 6, 12, 18, ... 354, 0, 6, 12,...
unsigned int SV_angle = 0; //angle of space vector: from [0 to 360)
float SV_magnitude = 0.8f; //magnitude of space vector: from [0 to 1]

//timer3 interupt
void timer3Int(void) //278us
{
//debug pin high when begin interupt
digitalWrite(debugPin, HIGH);

if (degree == 360){
degree = 0;
}
else{
degree += 6;
}

SV_angle = degree;
SVPWM_run(SV_angle, SV_magnitude);

//debug pin low when exit interupt


digitalWrite(debugPin, LOW);
}

void setup()
{
pinMode(debugPin, OUTPUT);
Timer3.initialize(278*5); //timer period us
// we divide 360 degree (1 sin wave cycle (~16,667us) into 60 part)
// 16,667 / 60 ~ 278
// real cycle = 278*60 = 16,680 us (~ 60hz)
// pwm freq : 1/ 278us ~ 3.6kHz

//call these func to setup ports to ouput PWM // These are prettly slow
compare to Timer3.setPwmDuty
Timer3.pwm(phaseA, 0);
Timer3.pwm(phaseB, 0);
Timer3.pwm(phaseC, 0);

66 | University of South Asia


Timer3.attachInterrupt(timer3Int); // Timer 3 overflow will call
timer3Int()

Serial.begin(9600);
}

void loop()
{

//this func will calculate and output PWM for 3 switches from angle and
magnitude of space vector
void SVPWM_run(unsigned int a, float m)
{
// use "static" to make it a little bit faster. But consume more memory
static float Ualpha, Ubeta;
static float X, Y, Z;
static float PWMa, PWMb, PWMc;
uint8_t sector;

//change from polar to rectangular coordinate


Ualpha = m*icos(a);
Ubeta = m*isin(a);

//X Y Z is temporary variables for convenient


X = Ubeta; //Ubeta
Y = Ubeta*0.5f + Ualpha*0.8660254f; // Ubeta/2 + Ualpha*sqrt(3)/2
Z = Y - X; // -Ubeta/2 + Ualpha*sqrt(3)/2

if (a < 60){
sector = 1;
}
else if (a < 120){
sector = 2;
}
else if (a < 180){
sector = 3;
}
else if (a < 240){
sector = 4;
}
else if (a < 300){

67 | University of South Asia


sector = 5;
}
else{
sector = 6;
}

// the calculation below is taken from TI code. I it would take a long


time to prove it mathematically.
// So just use the result.. lol.. :)
switch (sector){
case 1: // sector 1 or 4
case 4:
PWMa = Y;
PWMb = X - Z;
PWMc = -Y;
break;
case 2: // sector 2 or 5
case 5:
PWMa = Z + Y;
PWMb = X;
PWMc = -X;
break;
default: // sector 3 or 6
PWMa = Z;
PWMb = -Z;
PWMc = -(X+Y);
break;
}

//after the calculation, PWM is a number from -1 to 1


// we scale it to 0 to 1
PWMa = (PWMa+1)*0.5;
PWMb = (PWMb+1)*0.5;
PWMc = (PWMc+1)*0.5;

//maximum PWM for each pin is 1023. We just need the percentage of
1023
Timer3.setPwmDuty(phaseA, 1023 * PWMa);
Timer3.setPwmDuty(phaseB, 1023 * PWMb);
Timer3.setPwmDuty(phaseC, 1023 * PWMc);

//this is for debugging purposes


//Serial.print("\n");
//Serial.print(a); Serial.print("\t"); Serial.print(sector);
//Serial.print("\n");

68 | University of South Asia


//Serial.print(Ualpha, 5); Serial.print("\t");Serial.print(Ubeta,
5);Serial.print("\t");Serial.print(sqrt(Ubeta*Ubeta + Ualpha*Ualpha), 5);
//Serial.print(sector);Serial.print("\t");Serial.print(PWMa, 5);
Serial.print("\t"); Serial.print(PWMb, 5); Serial.print("\t"); Serial.print(PWMc,
5);
}

ATMEGA2560 Energy Meter Code

/*
* Adapted: 28/04/2017
* Author: supernova432
*/

//Imports for Current measuring


#include "Arduino.h"
#define F_CPU 16000000L
#include <JeeLib.h>
#include <stdio.h>
#include <avr/eeprom.h>
//Imports for LCD
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <LcdBarGraph.h>
//Imports for Ethernet
#include <EtherCard.h>

//enable Serial Debug


#define SERIAL 1

// Conversion float into string with justifying


char * floatToString(char *, float, int, int=0, bool=false);

//Button for switching LCD Screen


#define BUTTON_PIN 49
//Led blink at each cycle
#define LED_ACTIVITY_PIN 9

//------------------------------------------------------------------------------------
// DEFINES For LCD Display

69 | University of South Asia


//------------------------------------------------------------------------------------

#define NUMBER_OF_SCREENS 3
#define MAX_AMPS_PER_PHASE 15 // 15 A per phase supply
#define MAX_WATTS_PER_PHASE 3450 // 3450 W per phase supply

#if defined(ARDUINO) && ARDUINO >= 100


#define printByte(args) write(args);
#else
#define printByte(args) print(args,BYTE);
#endif

uint8_t sum[8] = {0x1F,0x10,0x8,0x4,0x8,0x10,0x1F};


uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};

// set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x3F,20,4);
LcdBarGraph lbg1(&lcd, 10, 10, 0); // -- creating bargraph line 1
LcdBarGraph lbg2(&lcd, 10, 10, 1); // -- creating bargraph line 2
LcdBarGraph lbg3(&lcd, 10, 10, 2); // -- creating bargraph line 3

char bufferString[25];
int lcdEcranAmp = 1;
boolean activityLed = true;

//------------------------------------------------------------------------------------
// DEFINES For Ethernet
//------------------------------------------------------------------------------------
// ethernet interface mac address
static byte mymac[] = { 0x00,0x01,0x02,0x03,0x04,0x05 };
// ethernet interface ip address
static byte myip[] = { 192,168,0,202 };
// gateway ip address
static byte gwip[] = { 192,168,0,254 };
// server Ip
static byte webServerIp[] = { 192,168,0,200};
static int webServerPort = 80;
// remote website name (for testing ethernet OK)
char website[] PROGMEM = "www.google.com";

byte Ethernet::buffer[300]; // a very small tcp/ip buffer is enough here


static long timer;
char cParam[255];

70 | University of South Asia


// called when the client request is complete
static void my_result_cb (byte status, word off, word len) {
Serial.print("<<<<<<< reply ");
Serial.print(millis() - timer);
Serial.println(" ms");
//Serial.println((const char*) Ethernet::buffer + off);
//Blink Heart when server request is complete
lcd.setCursor(19, 3);
lcd.printByte(7);
}

#define CONFIG_EEPROM_ADDR ((byte*) 0x10)

#define VERSION 3
#define NODE_TYPE 0x01

#define CALC_INTERVAL 2 //in seconds - time wich arduino will do power


calculations.
#define FREQUENCY 50 // IN HZ
//How many CTS for the main breaker (may not be on the same phase)
#define PHASE_SENSORS 3
// how many voltage sensors do you have (Open energy monitor dafaults to 1)
#define VOLTAGE_SENSORS 1
//Phase shift angle between phases (defaults to 120 for 3 phase circuits)
#define PHASE_SHIFT = 120
//samples per second are F_CPU / ADC prescaler(128) / 13 clock cycles per
adc / channel count
#define SAMPLES_PER_SECOND (F_CPU / 128 / 13 / (PHASE_SENSORS
+ VOLTAGE_SENSORS))

//SAMPLES_PER_SECOND are F_CPU / ADC prescaler(128) / 13 clock


cycles per adc / channel count
//the buffer size is samples per second / degrees to go back
//for 3-phase circuits, the degree is 240
//for 2-phase is 90 - i cannot test this...
//for 2-phases of a 3-phase system in theory is 120.

//MAX_SHIFT_DEGREE = 240
#define ADC_BUFFER_SIZE 33 //
((((SAMPLES_PER_SECOND/FREQUENCY) * MAX_SHIFT_DEGREE) /
360) +1);
#define PHASE1_OFFSET 16
#define PHASE2_OFFSET 32

71 | University of South Asia


/*
Input pins
[index] - Arduino AD
Example: for 3-phase with 1 voltage sensors:
[0] Phase1 voltage
[1] Phase1 current
[2] Phase2 current
[3] Phase3 current

Example: for 3-phase with 3 voltage sensors:


[0] Phase1 voltage
[1] Phase1 current
[2] Phase2 voltage
[3] Phase2 current
[4] Phase3 voltage
[5] Phase3 current

*/

/*
Pooling Order:
3-Phase voltages and 3-CT:
Voltage1, Current1, Voltage2, Current2, V3, C3, V1, C1...
1Phase Voltage - 3 Phase CT:
Voltage1 - Current1, Current2, Current3, Voltage1...
*/

//unsigned char input_analog_pins[PHASE_SENSORS +


VOLTAGE_SENSORS] = {1,2,3,0};
//unsigned char input_analog_pins[PHASE_SENSORS +
VOLTAGE_SENSORS] = {2,3,0,1};
//unsigned char input_analog_pins[PHASE_SENSORS +
VOLTAGE_SENSORS] = {0,1,2,3};
unsigned char input_analog_pins[PHASE_SENSORS +
VOLTAGE_SENSORS] = {0,1,2,3};

struct Config {
byte band;
byte group;
byte nodeID;
byte sendTo;
byte transmitinterval;
float Phase_Calibration[3];
float Current_Calibration[3];

72 | University of South Asia


float Voltage_Calibration[3];
float Voltage;
byte valid; // keep this as last byte
} config;

static void ConfigDefaults() {


config.valid = 253;
config.band = 4;
config.group = 210;
config.nodeID = 10;
config.sendTo = 1;
config.transmitinterval = 5;
config.Phase_Calibration[0] = 1.7;
config.Phase_Calibration[1] = 1.7;
config.Phase_Calibration[2] = 1.7;
//config.Current_Calibration[0] = 0.1080;
config.Current_Calibration[0] = 0.1315;
config.Current_Calibration[1] = 0.1487;
config.Current_Calibration[2] = 0.1026;
//config.Voltage_Calibration[0] = 0.4581;
config.Voltage_Calibration[0] = 1.0098;
config.Voltage_Calibration[1] = 1.0098;
config.Voltage_Calibration[2] = 1.0098;
config.Voltage = 230.0;
}

//End of User defineable variables


//---------------------------------------------------
// Do not touch the code below this point, unless you know what you are doing
//---------------------------------------------------

static void ConfigDefaults();


static void loadConfig();
static void saveConfig();
//void initRF();
//void process_rf();

//tx data - 62 bytes in total


typedef struct {
byte nodeId; //1 Byte
byte command; //1 Byte
unsigned int txCount; //2 bytes
float totalP; //4 bytes

73 | University of South Asia


float cummKw; //4 bytes
unsigned char numV; //1 Byte
unsigned char numI; //1 Byte
float V1; //4 bytes
float Irms1; //4 bytes
float RP1; //4 bytes
float PF_1; //4 bytes
float V2; //4 bytes
float Irms2; //4 bytes
float RP2; //4 bytes
float PF_2; //4 bytes
float V3; //4 bytes
float Irms3; //4 bytes
float RP3; //4 bytes
float PF_3; //4 bytes
} PayloadTX; // create structure - a neat way of packaging data for RF
comms

//1 voltage sensor


#if (VOLTAGE_SENSORS == 1)
#define V0 0
#if (PHASE_SENSORS > 0)
#define I0 1
#if (PHASE_SENSORS > 1)
#define I1 2
#if (PHASE_SENSORS > 2)
#define I2 3
#endif
#endif
#endif
//2 voltage sensors
#elif (VOLTAGE_SENSORS == 2)
#define V0 0
#if (PHASE_SENSORS > 0)
#define I0 1
#define V1 2
#if (PHASE_SENSORS > 1)
#define I1 3
#if (PHASE_SENSORS > 2)
#define I2 4
#endif
#endif
#else
#define V1 1
#endif
//3 voltage sensors

74 | University of South Asia


#elif (VOLTAGE_SENSORS == 3)
#define V0 0
#if (PHASE_SENSORS == 1)
#define I0 1
#define V1 2
#define V2 3
#elif (PHASE_SENSORS == 2)
#define I0 1
#define V1 2
#define I1 3
#define V2 4
#elif (PHASE_SENSORS == 3)
#define I0 1
#define V1 2
#define I1 3
#define V2 4
#define I2 5
#else
#define V1 1
#define V2 2
#endif
#else
//no voltage sensors
#if (PHASE_SENSORS > 0)
#define I0 0
#if (PHASE_SENSORS > 1)
#define I1 1
#if (PHASE_SENSORS > 2)
#define I2 2
#endif
#endif
#endif
#endif

//Temp variables
PayloadTX emontx;
long adcval;
volatile unsigned char AdcIndex = 1; //keeps track of sampled channel
volatile unsigned int SampleCounter, crossCounter, LastSampleCounter;
volatile boolean Cycle_Full; //stores wherever the cycle has been computed
boolean lastVCross, checkVCross; //Used to measure number of times
threshold is crossed.
unsigned char tempidx;

struct CurrentSampleS {

75 | University of South Asia


float New, Previous;
float Filtered,PreviousFiltered, Calibrated, Sum, InstPower;
} CurrentSample[3]; //for now i will maintain 3 here hardcoded
because i dont want to put 300 ifs on the code yet.

struct VoltageSampleS {
float New, Previous;
float Filtered,PreviousFiltered, PhaseShifted, Calibrated, Sum;
} VoltageSample[3]; //Yes phases here, because we are going to create
the voltage data based on what we have //for now i will maintain 3 here
hardcoded because i dont want to put 300 ifs on the code yet.

struct LastCurrentS {
float Sum, InstPower;
} LastCurrent[3];//for now i will maintain 3 here hardcoded because i
dont want to put 300 ifs on the code yet.
struct LastVoltageS {
float Sum;
} LastVoltage[VOLTAGE_SENSORS];

//struct AccDataStructure { float Sum;


// float InstantPower;
// } AccData[2], LastAccData[2];

float AccVrms[3];
float AccIrms[3];
float AccRealPower[3] ;
float AccAparentPower[3];
float AccPowerFactor[3];

float cummP; //cummulative power

//TODO fix if the 3 sensors are on the same phase, puto some code here
#if VOLTAGE_SENSORS == 1 && PHASE_SENSORS > 1
#define ADC_BUFFER 1
//declare voltage buffer
float ADC_V_BUFFER[ADC_BUFFER_SIZE+2];
unsigned char adc_buffer_index = (ADC_BUFFER_SIZE-1);
#endif

boolean temp = 0;
float tempdbl = 0.0;
unsigned char tmpchar;
volatile unsigned long LastInterruptTime;

unsigned char tcount;

76 | University of South Asia


unsigned int counts;

static long timerCalculation;

static void loadConfig() {


for (byte i = 0; i < sizeof config; ++i)
((byte*) &config)[i] = eeprom_read_byte(CONFIG_EEPROM_ADDR +
i);
if (config.valid != 253) {
ConfigDefaults();
#ifdef SERIAL
Serial.println("Load Config Defaults Values");
#endif
}

static void saveConfig() {


for (byte i = 0; i < sizeof config; ++i)
eeprom_write_byte(CONFIG_EEPROM_ADDR + i, ((byte*)
&config)[i]);
}

/*
void initRF(){
byte freq = config.band == 4 ? RF12_433MHZ :
config.band == 8 ? RF12_868MHZ :
RF12_915MHZ;
#ifdef SERIAL
Serial.print("Initialiazing RF: Node:");
Serial.print(config.nodeID);
Serial.print(" Freq:");
Serial.print(freq);
Serial.print(" group:");
Serial.println(config.group);
#endif
rf12_initialize(config.nodeID, freq, config.group);

}
*/

void setup()
{
#ifdef SERIAL
Serial.begin(57600); //begin Serial comm

77 | University of South Asia


Serial.println("emonTX UP and Running");
#endif

//Setup LCD
lcd.init(); // initialize the lcd
lcd.backlight();
lbg1.init();
lbg2.init();
lbg3.init();
lcd.createChar(6, sum);
lcd.createChar(7, heart);
lcd.home();
lcd.print("emonTX UP & Running!");
lcd.setCursor(19, 3);
lcd.printByte(7);

digitalWrite(BUTTON_PIN, HIGH); // set button to high -> activate pullup


resistor
pinMode(LED_ACTIVITY_PIN, OUTPUT);
digitalWrite(LED_ACTIVITY_PIN, HIGH);

// Check source of reset


if (MCUSR & 1) // Power-on Reset
{
// put POR handler here, if required
}
else if (MCUSR & 2) // External Reset
{
// put external reset handler here, if required
}
else if (MCUSR & 4) // Brown-Out Reset
{
// put BOR handler here, if required
}
else // Watchdog Reset
{
// put watchdog reset handler here, if required
};

lcd.setCursor(0,2);
lcd.print(" Init Ethernet ");
#ifdef SERIAL
Serial.println("Setup Ethernet .......");
#endif
if (ether.begin(sizeof Ethernet::buffer, mymac, 53) == 0) {
#ifdef SERIAL

78 | University of South Asia


Serial.println( "Failed to access Ethernet controller");
#endif
lcd.clear();
lcd.print("Failed to access Ethernet controller");
}

ether.staticSetup(myip, gwip);

if (!ether.dnsLookup(website))
Serial.println("DNS failed");
ether.printIp("Google Server: ", ether.hisip);

//Changing Server URL


memcpy(ether.hisip, webServerIp, 4);
ether.hisport = webServerPort;
ether.printIp("EmonCMS Server: ", ether.hisip);

lcd.setCursor(0, 1);
lcd.print(" Ethernet OK : ");
lcd.setCursor(0, 2);
lcd.print("IP : ");
lcd.print(ether.myip[0]);
lcd.print(".");
lcd.print(ether.myip[1]);
lcd.print(".");
lcd.print(ether.myip[2]);
lcd.print(".");
lcd.print(ether.myip[3]);

loadConfig();

//initRF();

emontx.numV = VOLTAGE_SENSORS;
emontx.numI = PHASE_SENSORS;

// ADC initialization:
// Enable ADC interrupt and use external voltage reference.
// Set multiplexer input to first channel and do not set
// ADC to High Speed Mode. Set Auto Trigger Source to Free Running Mode.
//
// fCLK | ADPS | Prescaler | ADCCLK | Sampl.Rate
// ------+------+-----------+--------+-----------
// 4.000 | 111 | 128 | 125000 | 9615

79 | University of South Asia


//ADC INIT
ADMUX = (input_analog_pins[0] & 0x07); // Set ADC reference to external
VFREF and first defined port
ADMUX |= (1 << REFS0);

ADCSRA |= (1 << ADEN); // Enable ADC


ADCSRA |= (1 << ADATE); // Enable auto-triggering
ADCSRA |= (1 << ADIE); // Enable ADC Interrupt

sei(); // Enable Global Interrupts

//put code here to start adc after zero crossing. *TODO* but not a problem,
because we do not pick up first sampled data...
//...
//Start ADC
#ifdef SERIAL
Serial.println("Open Energy Monitor Hack by Pcunha");
Serial.println("Starting ADC in next cycle");
#endif

lcd.setCursor(0, 3);
lcd.print("Starting measuring");

//timer to watch (on serial port) duration of ADC interrupt service routine
timerCalculation = millis();

ADCSRA=0xEF; // Enable ADC, start, auto trigger, int enable, presc = 128

//------------------------------------------------------------------------------------
//ADC INTERRUPT SERVICE ROUTINE
//------------------------------------------------------------------------------------
ISR(ADC_vect){ //ADC interrupt
//unsigned long t1;
unsigned char IndexAtual = 0;
//t1 = micros();

unsigned char nextindex = AdcIndex;


if (++nextindex >= (PHASE_SENSORS + VOLTAGE_SENSORS))
nextindex=0;
ADMUX=(input_analog_pins[nextindex]);// Select next ADC input
ADMUX |= (1 << REFS0);
//uint8_t low = ADCL;

80 | University of South Asia


//uint8_t high = ADCH;
//// combine the two bytes
//int adcValue = (high << 8) | low;

//
if (AdcIndex > 0)
IndexAtual = AdcIndex - 1;
else
IndexAtual = PHASE_SENSORS + VOLTAGE_SENSORS -1;
//IndexAtual = (PHASE_SENSORS + VOLTAGE_SENSORS - 1); // adc is
always 1 nextindex negative

//Voltage1 - First voltage sensor (Open Energy Monitor only have this voltage
sensor)
#ifdef V0
if (IndexAtual == V0){ //Very strange behavior when using ifdef here
with 0 value
// Store Last Values for future use
VoltageSample[0].Previous = VoltageSample[0].New; //Put
last sample on its place
VoltageSample[0].PreviousFiltered = VoltageSample[0].Filtered;
//Put last sample on its place
// Read in raw voltage and current samples
VoltageSample[0].New=ADC; //Read in raw voltage signal
from index sample
// Apply digital high pass filters to remove 2.5V DC offset
(centered on 0V).
VoltageSample[0].Filtered = 0.996 * (
VoltageSample[0].PreviousFiltered + VoltageSample[0].New -
VoltageSample[0].Previous );
// Root-mean-square method Index Channel
// -> sum the square of voltage values
VoltageSample[0].Sum += VoltageSample[0].Filtered *
VoltageSample[0].Filtered;
// Phase calibration
VoltageSample[0].PhaseShifted =
VoltageSample[0].PreviousFiltered + config.Phase_Calibration[0] *
(VoltageSample[0].Filtered - VoltageSample[0].PreviousFiltered);
//If using ADC BUFFERING
//unsigned int ADC_V_BUFFER[ADC_BUFFER_SIZE];
//volatile unsigned char adc_buffer_index;
#ifdef ADC_BUFFER
if (--adc_buffer_index == 255)
adc_buffer_index=(ADC_BUFFER_SIZE-1);

81 | University of South Asia


ADC_V_BUFFER[adc_buffer_index] =
VoltageSample[0].PhaseShifted;
#endif
}
#endif

//Current1
#if ((IO == 0) || (IO == 1))//Very strange behavior when using ifdef here with 0
value
if (IndexAtual == I0){ //First CT
//A) Store Last Values for future use
CurrentSample[0].Previous = CurrentSample[0].New; //Put
last sample on its place
CurrentSample[0].PreviousFiltered = CurrentSample[0].Filtered;
//Put last sample on its place
// Read in raw voltage and current samples
CurrentSample[0].New=ADC; //Read in raw voltage signal
from index sample
// Apply digital high pass filters to remove 2.5V DC offset
(centered on 0V).
CurrentSample[0].Filtered = 0.996 * (
CurrentSample[0].PreviousFiltered + CurrentSample[0].New -
CurrentSample[0].Previous );
// Root-mean-square method Index Channel
// -> sum the square of voltage values
CurrentSample[0].Sum += CurrentSample[0].Filtered *
CurrentSample[0].Filtered;
// Instantaneous power calc now that we have I and V
#if VOLTAGE_SENSORS > 0
CurrentSample[0].InstPower +=
VoltageSample[0].PhaseShifted * CurrentSample[0].Filtered; //Instantaneous
Power //mudar pphaseshift
#else
CurrentSample[0].InstPower = CurrentSample[0].Filtered;
#endif
}
#endif

#ifdef V1
if (IndexAtual == V1){
//A) Store Last Values for future use
VoltageSample[1].Previous = VoltageSample[1].New; //Put last sample
on its place
VoltageSample[1].PreviousFiltered = VoltageSample[1].Filtered; //Put
last sample on its place
// Read in raw voltage and current samples

82 | University of South Asia


VoltageSample[1].New=ADC; //Read in raw voltage signal from index
sample
// Apply digital high pass filters to remove 2.5V DC offset (centered on 0V).
VoltageSample[1].Filtered = 0.996 * ( VoltageSample[1].PreviousFiltered +
VoltageSample[1].New - VoltageSample[1].Previous );
// Root-mean-square method Index Channel
// -> sum the square of voltage values
VoltageSample[1].Sum += VoltageSample[1].Filtered *
VoltageSample[1].Filtered;
// Phase calibration
VoltageSample[1].PhaseShifted = VoltageSample[1].PreviousFiltered +
config.Phase_Calibration[1] * (VoltageSample[1].Filtered -
VoltageSample[1].PreviousFiltered);
}
#endif

#ifdef I1
if (IndexAtual == I1){ //First CT
//A) Store Last Values for future use
CurrentSample[1].Previous = CurrentSample[1].New; //Put last
sample on its place
CurrentSample[1].PreviousFiltered = CurrentSample[1].Filtered;
//Put last sample on its place
// Read in raw voltage and current samples
CurrentSample[1].New=ADC; //Read in raw voltage signal from
index sample
// Apply digital high pass filters to remove 2.5V DC offset (centered on
0V).
CurrentSample[1].Filtered = 0.996 * (
CurrentSample[1].PreviousFiltered + CurrentSample[1].New -
CurrentSample[1].Previous );
// Root-mean-square method Index Channel
// -> sum the square of voltage values
CurrentSample[1].Sum += CurrentSample[1].Filtered *
CurrentSample[1].Filtered;
// Instantaneous power calc now that we have I and V
#if VOLTAGE_SENSORS > 1
CurrentSample[1].InstPower += VoltageSample[1].PhaseShifted
* CurrentSample[1].Filtered; //Instantaneous Power
#else
#ifdef ADC_BUFFER //if there is adc buffering
tmpchar = (adc_buffer_index + PHASE1_OFFSET) %
ADC_BUFFER_SIZE;
tempdbl = ADC_V_BUFFER[tmpchar];//
(adc_buffer_index + PHASE1_OFFSET)% ADC_BUFFER_SIZE);
//aqui

83 | University of South Asia


CurrentSample[1].InstPower += tempdbl *
CurrentSample[1].Filtered;
#else //if adc_buffer is inactve
CurrentSample[1].InstPower = CurrentSample[1].Filtered;
#endif
#endif
}
#endif

#ifdef V2
if (IndexAtual == V2){
//A) Store Last Values for future use
VoltageSample[2].Previous = VoltageSample[2].New; //Put last sample
on its place
VoltageSample[2].PreviousFiltered = VoltageSample[2].Filtered; //Put
last sample on its place
// Read in raw voltage and current samples
VoltageSample[2].New=ADC; //Read in raw voltage signal from index
sample
// Apply digital high pass filters to remove 2.5V DC offset (centered on 0V).
VoltageSample[2].Filtered = 0.996 * ( VoltageSample[2].PreviousFiltered +
VoltageSample[2].New - VoltageSample[2].Previous );
// Root-mean-square method Index Channel
// -> sum the square of voltage values
VoltageSample[2].Sum += VoltageSample[2].Filtered *
VoltageSample[2].Filtered;
// Phase calibration
VoltageSample[2].PhaseShifted = VoltageSample[2].PreviousFiltered +
config.Phase_Calibration[2] * (VoltageSample[2].Filtered -
VoltageSample[2].PreviousFiltered);
}
#endif

#ifdef I2
if (IndexAtual == I2){ //First CT
//A) Store Last Values for future use
CurrentSample[2].Previous = CurrentSample[2].New; //Put
last sample on its place
CurrentSample[2].PreviousFiltered = CurrentSample[2].Filtered;
//Put last sample on its place
// Read in raw voltage and current samples
CurrentSample[2].New=ADC; //Read in raw voltage signal
from index sample
// Apply digital high pass filters to remove 2.5V DC offset
(centered on 0V).

84 | University of South Asia


CurrentSample[2].Filtered = 0.996 * (
CurrentSample[2].PreviousFiltered + CurrentSample[2].New -
CurrentSample[2].Previous );
// Root-mean-square method Index Channel
// -> sum the square of voltage values
CurrentSample[2].Sum += CurrentSample[2].Filtered *
CurrentSample[2].Filtered;
// Instantaneous power calc now that we have I and V
#if VOLTAGE_SENSORS > 2
CurrentSample[2].InstPower +=
VoltageSample[2].PhaseShifted * CurrentSample[2].Filtered; //Instantaneous
Power
#else
#ifdef ADC_BUFFER //if there is adc buffering
tmpchar = (adc_buffer_index +
PHASE2_OFFSET) % ADC_BUFFER_SIZE;
tempdbl = ADC_V_BUFFER[tmpchar];//
(adc_buffer_index + PHASE2_OFFSET)% ADC_BUFFER_SIZE);
CurrentSample[2].InstPower += tempdbl *
CurrentSample[2].Filtered;
#else //if adc_buffer is inactve
CurrentSample[2].InstPower =
CurrentSample[2].Filtered;
#endif
#endif
}
#endif

if (AdcIndex == 0) SampleCounter++;

//4807 for 2 channels


//1602 for 6 channels
//1 sec
if (SampleCounter > (SAMPLES_PER_SECOND * CALC_INTERVAL)){
LastSampleCounter = SampleCounter;

#if VOLTAGE_SENSORS > 0


LastVoltage[0].Sum = VoltageSample[0].Sum;
VoltageSample[0].Sum = 0;
#if VOLTAGE_SENSORS > 1
LastVoltage[1].Sum = VoltageSample[1].Sum;
VoltageSample[1].Sum = 0;
#if VOLTAGE_SENSORS > 2
LastVoltage[2].Sum = VoltageSample[2].Sum;
VoltageSample[2].Sum = 0;
#endif

85 | University of South Asia


#endif
#endif

#if PHASE_SENSORS > 0


LastCurrent[0].Sum = CurrentSample[0].Sum;
CurrentSample[0].Sum = 0;
LastCurrent[0].InstPower = CurrentSample[0].InstPower;
CurrentSample[0].InstPower = 0;
#if PHASE_SENSORS > 1
LastCurrent[1].Sum = CurrentSample[1].Sum;
CurrentSample[1].Sum = 0;
LastCurrent[1].InstPower = CurrentSample[1].InstPower;
CurrentSample[1].InstPower = 0;
#if PHASE_SENSORS > 2
LastCurrent[2].Sum = CurrentSample[2].Sum;
CurrentSample[2].Sum = 0;
LastCurrent[2].InstPower = CurrentSample[2].InstPower;
CurrentSample[2].InstPower = 0;
#endif
#endif
#endif

SampleCounter = 0;
Cycle_Full = true;
}

// Maintain multiplexing of input channels


if (++AdcIndex >= (PHASE_SENSORS + VOLTAGE_SENSORS))
AdcIndex=0;

//LastInterruptTime = micros() - t1;

/*
void process_rf(){

int node_id = (rf12_hdr & 0x1F);


byte remoteid = rf12_data[0];
byte command = rf12_data[1];
char txbuffer[6] = {0,0,0,0,0,0};
txbuffer[0] = config.nodeID;

switch (command){

case 0x00: // Set all config defaults

86 | University of South Asia


txbuffer[1] = NODE_TYPE;
txbuffer[2] = VERSION;
//send the ack with the data
rf12_sendStart(RF12_ACK_REPLY, &txbuffer, 3);
break;

case 0x01: // Set all config defaults


ConfigDefaults();
saveConfig();
break;

case 0x02: // get config value

switch (rf12_data[1]){
case 0x01: //radio band
txbuffer[2] = config.band;
break;
case 0x02: // radio group
txbuffer[2] = config.group;
break;
case 0x03: // radio nodeID
txbuffer[2] = config.nodeID;
break;
case 0x04: // radio nodeID
txbuffer[2] = config.sendTo;
break;

case 0x10: // transmit interval


txbuffer[2] = config.transmitinterval;
break;
case 0x11: // Phase Calibration \u2013 Phase 1
*(float *)(&(txbuffer[2])) = config.Phase_Calibration[0];
break;
case 0x12: // Phase Calibration \u2013 Phase 2
*(float *)(&(txbuffer[2])) = config.Phase_Calibration[1];
break;
case 0x13: // Phase Calibration \u2013 Phase 3
*(float *)(&(txbuffer[2])) = config.Phase_Calibration[2];
break;

case 0x14: // Current Calibration \u2013 Phase 1


*(float *)(&(txbuffer[2])) = config.Current_Calibration[0];
break;
case 0x15: // Current Calibration \u2013 Phase 2
*(float *)(&(txbuffer[2])) = config.Current_Calibration[1];
break;

87 | University of South Asia


case 0x16: // Current Calibration \u2013 Phase 3
*(float *)(&(txbuffer[2])) = config.Current_Calibration[2];
break;

case 0x17: // Voltage Calibration \u2013 Phase 1


*(float *)(&(txbuffer[2])) = config.Voltage_Calibration[0];
break;
case 0x18: // Voltage Calibration \u2013 Phase 2
*(float *)(&(txbuffer[2])) = config.Voltage_Calibration[1];
break;
case 0x19: // Voltage Calibration \u2013 Phase 3
*(float *)(&(txbuffer[2])) = config.Voltage_Calibration[2];
break;

case 0x1A: // Voltage ( if no voltage sensors are defined)


*(float *)(&(txbuffer[2])) = config.Voltage;
break;
}

txbuffer[1] = 3;
//send the ack with the data
rf12_sendStart(RF12_ACK_REPLY, &txbuffer, 6);

break;

case 0x04: // set config value


switch (rf12_data[2]){
case 0x01: //radio band
config.band = (byte) rf12_data[3];
initRF();
break;
case 0x02: // radio group
config.group = (byte) rf12_data[3];
initRF();
break;
case 0x03: // radio nodeID
config.nodeID = (byte) rf12_data[3];
initRF();
break;
case 0x04: // radio nodeID
config.sendTo = (byte) rf12_data[3];
break;

case 0x10: // transmit interval


config.transmitinterval = (byte) rf12_data[3];

88 | University of South Asia


break;
case 0x11: // Phase Calibration \u2013 Phase 1

config.Phase_Calibration[0] = *( (float*)(rf12_data +3) );

break;
case 0x12: // Phase Calibration \u2013 Phase 2
config.Phase_Calibration[1] = *( (float*)(rf12_data +3) );
break;
case 0x13: // Phase Calibration \u2013 Phase 3
config.Phase_Calibration[2] = *( (float*)(rf12_data +3) );
break;

case 0x14: // Current Calibration \u2013 Phase 1


config.Current_Calibration[0] = *( (float*)(rf12_data +3) );
break;
case 0x15: // Current Calibration \u2013 Phase 2
config.Current_Calibration[1] = *( (float*)(rf12_data +3) );
break;
case 0x16: // Current Calibration \u2013 Phase 3
config.Current_Calibration[2] = *( (float*)(rf12_data +3) );
break;

case 0x17: // Voltage Calibration \u2013 Phase 1


config.Voltage_Calibration[0] = *( (float*)(rf12_data +3) );
break;
case 0x18: // Voltage Calibration \u2013 Phase 2
config.Voltage_Calibration[1] = *( (float*)(rf12_data +3) );
break;
case 0x19: // Voltage Calibration \u2013 Phase 3
config.Voltage_Calibration[2] = *( (float*)(rf12_data +3) );
break;

case 0x1A: // Voltage ( if no voltage sensors are defined)


config.Voltage = *( (float*)(rf12_data +3) );
break;
}
saveConfig();
//send the ack
if(RF12_WANTS_ACK){
rf12_sendStart(RF12_ACK_REPLY, &txbuffer, 1);
}
break;

89 | University of South Asia


}
*/

void loop()
{

boolean transmit = false;


float Vrms[3];
float Irms[3];
float realPower[3] ;
float apparentPower[3];
float powerFactor[3];

//receive ethernet packet


ether.packetLoop(ether.packetReceive());

//skip first cycle to stabilize readings


//and init LCD
if (tcount == 0 && Cycle_Full == true){
tcount = 1;
Cycle_Full = false;

initLcd3Phases();
}

if (tcount > 0){


if (digitalRead(BUTTON_PIN) == LOW) {
lcdEcranAmp++;
if(lcdEcranAmp > NUMBER_OF_SCREENS) lcdEcranAmp = 1;

if(lcdEcranAmp == 1 || lcdEcranAmp == 2){


lbg1.drawValue(0, 1);
lbg2.drawValue(0, 1);
lbg3.drawValue(0, 1);
initLcd3Phases();
}else if(lcdEcranAmp == 3){
initLcdPowerAndAmps();
}

//Print LCD
printLCD();
}
}

90 | University of South Asia


//-------------------------------------------
if (Cycle_Full == true){
Serial.print("\tCycleDuration = ");
Serial.print(millis() - timerCalculation);
Serial.println(" ms");
timerCalculation = millis();

// blink led at each cycle


if(activityLed) digitalWrite(LED_ACTIVITY_PIN, HIGH);
else digitalWrite(LED_ACTIVITY_PIN, LOW);
activityLed = !activityLed;

Cycle_Full = false;
//Calculation of the root of the mean of the voltage and current squared
(rms)
//Calibration coeficients applied.
#if VOLTAGE_SENSORS > 0
Vrms[0] = config.Voltage_Calibration[0] * sqrt(LastVoltage[0].Sum /
LastSampleCounter);
#ifdef ADC_BUFFER
#if PHASE_SENSORS > 1
Vrms[1] = Vrms[0];
#if PHASE_SENSORS > 2
Vrms[2] = Vrms[0];
#endif
#endif
#else
#if VOLTAGE_SENSORS > 1
Vrms[1] = config.Voltage_Calibration[1] * sqrt(LastVoltage[1].Sum /
LastSampleCounter);
#if VOLTAGE_SENSORS > 2
Vrms[2] = config.Voltage_Calibration[2] * sqrt(LastVoltage[2].Sum /
LastSampleCounter);
#endif
#endif
#endif
#else
Vrms[0] = config.Voltage;
Vrms[1] = config.Voltage;
Vrms[2] = config.Voltage;
#endif

91 | University of South Asia


#if PHASE_SENSORS > 0
//colocar if para 1 ct.
Irms[0] = config.Current_Calibration[0] * sqrt(LastCurrent[0].Sum /
LastSampleCounter);
#if VOLTAGE_SENSORS > 0
realPower[0] = config.Voltage_Calibration[0] *
config.Current_Calibration[0] * (LastCurrent[0].InstPower /
LastSampleCounter);
#else
realPower[0] = Vrms[0] * Irms[0];
#endif
apparentPower[0] = Vrms[0] * Irms[0];
powerFactor[0] = realPower[0] / apparentPower[0];
//--------------------------
#if PHASE_SENSORS > 1
//colocar if para 1 ct.
Irms[1] = config.Current_Calibration[1] * sqrt(LastCurrent[1].Sum /
LastSampleCounter);
#if VOLTAGE_SENSORS > 1
realPower[1] = config.Voltage_Calibration[1] *
config.Current_Calibration[1] * (LastCurrent[1].InstPower /
LastSampleCounter);
apparentPower[1] = Vrms[1] * Irms[1];
#else
#ifdef ADC_BUFFER
realPower[1] = config.Voltage_Calibration[0] *
config.Current_Calibration[1] * (LastCurrent[1].InstPower /
LastSampleCounter);
apparentPower[1] = Vrms[0] * Irms[1];
#else
realPower[1] = Vrms[1] * Irms[1];
apparentPower[1] = realPower[1];
#endif
#endif
powerFactor[1] = realPower[1] / apparentPower[1];
//--------------------------
#if PHASE_SENSORS > 2
//colocar if para 1 ct.
Irms[2] = config.Current_Calibration[2] * sqrt(LastCurrent[2].Sum /
LastSampleCounter);
#if VOLTAGE_SENSORS > 2
realPower[2] = config.Voltage_Calibration[2] *
config.Current_Calibration[2] * (LastCurrent[2].InstPower /
LastSampleCounter);
apparentPower[2] = Vrms[2] * Irms[2];
#else

92 | University of South Asia


#ifdef ADC_BUFFER
realPower[2] = config.Voltage_Calibration[0] *
config.Current_Calibration[2] * (LastCurrent[2].InstPower /
LastSampleCounter);
apparentPower[2] = Vrms[0] * Irms[2];
#else
realPower[2] = Vrms[2] * Irms[2];
apparentPower[2] = realPower[2];
#endif
#endif
powerFactor[2] = realPower[2] / apparentPower[2];
#endif
#endif
#endif

//calc transmission interval data

#if VOLTAGE_SENSORS > 0


AccVrms[0] = AccVrms[0] + (Vrms[0] / config.transmitinterval) ;
#ifdef ADC_BUFFER
AccVrms[1] = AccVrms[0];
AccVrms[2] = AccVrms[0];
#endif
#if VOLTAGE_SENSORS > 1
AccVrms[1] = AccVrms[1] + (Vrms[1] / config.transmitinterval) ;
#if VOLTAGE_SENSORS > 2
AccVrms[2] = AccVrms[2] + (Vrms[2] / config.transmitintervalL) ;
#endif
#endif
#else
AccVrms[0] = Voltage;
AccVrms[1] = Voltage;
AccVrms[2] = Voltage;
#endif

#if PHASE_SENSORS > 0


AccIrms[0] = AccIrms[0] + (Irms[0] / config.transmitinterval) ;
AccRealPower[0] = AccRealPower[0] + (realPower[0] /
config.transmitinterval) ;
AccAparentPower[0] = AccAparentPower[0] + (apparentPower[0] /
config.transmitinterval) ;
AccPowerFactor[0] = AccPowerFactor[0] + (powerFactor[0] /
config.transmitinterval) ;
#if PHASE_SENSORS > 1

93 | University of South Asia


AccIrms[1] = AccIrms[1] + (Irms[1] / config.transmitinterval) ;
AccRealPower[1] = AccRealPower[1] + (realPower[1] /
config.transmitinterval) ;
AccAparentPower[1] = AccAparentPower[1] + (apparentPower[1] /
config.transmitinterval) ;
AccPowerFactor[1] = AccPowerFactor[1] + (powerFactor[1] /
config.transmitinterval) ;
#if PHASE_SENSORS > 2
AccIrms[2] = AccIrms[2] + (Irms[2] / config.transmitinterval) ;
AccRealPower[2] = AccRealPower[2] + (realPower[2] /
config.transmitinterval) ;
AccAparentPower[2] = AccAparentPower[2] + (apparentPower[2] /
config.transmitinterval) ;
AccPowerFactor[2] = AccPowerFactor[2] + (powerFactor[2] /
config.transmitinterval) ;
#endif
#endif
#endif
tcount++;

//transmit
if (tcount > config.transmitinterval) {
tcount = 1;
counts++;
emontx.command = 0x20;
emontx.nodeId = config.nodeID;
emontx.txCount = counts;
emontx.totalP = AccRealPower[0]
#if PHASE_SENSORS > 1
+ AccRealPower[1]
#if PHASE_SENSORS > 2
+ AccRealPower[2]
#endif
#endif
;

//calculate kw increment
float whInc = emontx.totalP *((CALC_INTERVAL *
config.transmitinterval)/3600.0);
emontx.cummKw += whInc / 1000;

emontx.V1 = AccVrms[0];
#if (PHASE_SENSORS > 0)

94 | University of South Asia


emontx.Irms1 = AccIrms[0];
emontx.RP1 = AccRealPower[0];
emontx.PF_1 = AccPowerFactor[0];
#endif

#if (VOLTAGE_SENSORS > 1)


emontx.V1 = AccVrms[1];
#endif
#if (PHASE_SENSORS > 1)
emontx.Irms2 = AccIrms[1];
emontx.RP2 = AccRealPower[1];
emontx.PF_2 = AccPowerFactor[1];
#endif
#if (VOLTAGE_SENSORS > 2)
emontx.V1 = AccVrms[2];
#endif
#if (PHASE_SENSORS > 2)
emontx.Irms3 = AccIrms[2];
emontx.RP3 = AccRealPower[2];
emontx.PF_3 = AccPowerFactor[2];
#endif

#ifdef SERIAL
Serial.print("Total = ");
Serial.print(emontx.totalP);
Serial.println(" W ");
Serial.print("KwIncrement = ");
Serial.print(emontx.cummKw);
Serial.println(" Kw ");

Serial.print("L1 : ");
Serial.print(emontx.V1);
Serial.print(" V - ");
Serial.print(emontx.Irms1);
Serial.print(" A - ");
Serial.print(emontx.RP1);
Serial.print(" W - ");
Serial.println(emontx.PF_1);

Serial.print("L2 : ");
Serial.print(emontx.V2);
Serial.print(" V - ");
Serial.print(emontx.Irms2);
Serial.print(" A - ");
Serial.print(emontx.RP2);

95 | University of South Asia


Serial.print(" W - ");
Serial.println(emontx.PF_2);

Serial.print("L3 : ");
Serial.print(emontx.V3);
Serial.print(" V - ");
Serial.print(emontx.Irms3);
Serial.print(" A - ");
Serial.print(emontx.RP3);
Serial.print(" W - ");
Serial.println(emontx.PF_3);
#endif

//Print LCD
printLCD();

//transmit Ethernet
#ifdef SERIAL
Serial.println("\n>>> REQ");
#endif
//build URL with values
String param = "input/post?json={voltage:";
param += floatToString(bufferString, emontx.V1, 2);
param += ",power1:";
param += floatToString(bufferString, emontx.RP1, 2);
param += ",power2:";
param += floatToString(bufferString, emontx.RP2, 2);
param += ",power3:";
param += floatToString(bufferString, emontx.RP3, 2);
param += ",powerSum:";
param += floatToString(bufferString, emontx.totalP, 2);
param += ",current1:";
param += floatToString(bufferString, emontx.Irms1, 2);
param += ",current2:";
param += floatToString(bufferString, emontx.Irms2, 2);
param += ",current3:";
param += floatToString(bufferString, emontx.Irms3, 2);
param += "}&apikey=b4b22e89c0f72a426ae948e97497709c";
param.toCharArray(cParam, 255);
#ifdef SERIAL
Serial.println(cParam);
#endif

//Blink Heart & Led Activity


lcd.setCursor(19, 3);

96 | University of South Asia


lcd.print(" ");
digitalWrite(LED_ACTIVITY_PIN, LOW);
ether.browseUrl(PSTR("/emoncms/"),cParam, website, my_result_cb);
timer = millis();
//transmit Ethernet OK

//erase data
#if VOLTAGE_SENSORS > 0
AccVrms[0] = 0 ;
#if VOLTAGE_SENSORS > 1
AccVrms[1] = 0 ;
#if VOLTAGE_SENSORS > 2
AccVrms[2] = 0 ;
#endif
#endif
#else
AccVrms[0] = 0;
AccVrms[1] = 0;
AccVrms[2] = 0;
#endif

#if PHASE_SENSORS > 0


AccIrms[0] = 0 ;
AccRealPower[0] = 0 ;
AccAparentPower[0] = 0 ;
AccPowerFactor[0] = 0 ;
#if PHASE_SENSORS > 1
AccIrms[1] = 0 ;
AccRealPower[1] = 0 ;
AccAparentPower[1] = 0 ;
AccPowerFactor[1] = 0 ;
#if PHASE_SENSORS > 2
AccIrms[2] = 0 ;
AccRealPower[2] = 0 ;
AccAparentPower[2] = 0 ;
AccPowerFactor[2] = 0 ;
#endif
#endif
#endif
}//transmit
}//cycle full
}

void printLCD(){

97 | University of South Asia


//Print LCD
if(lcdEcranAmp == 1){
printAmps(emontx.Irms1, emontx.Irms2, emontx.Irms3, emontx.V1);
}else if(lcdEcranAmp == 2){
printWatts(emontx.RP1, emontx.RP2, emontx.RP3, emontx.totalP,
emontx.V1);
}else if(lcdEcranAmp == 3){
printPowerAndAmps(emontx.Irms1, emontx.Irms2, emontx.Irms3,
emontx.RP1, emontx.RP2, emontx.RP3, emontx.totalP, emontx.PF_1,
emontx.PF_2, emontx.PF_3, emontx.V1);
}

// Print LCD Screen with Intensity Values


void printAmps(float irms1, float irms2, float irms3, float voltage) {

lcd.setCursor(0, 0);
lcd.print("L1 ");
lcd.print(floatToString(bufferString, irms1, 2, 5,true));
lcd.print("A ");
lbg1.drawValue(int(irms1 * 100), MAX_AMPS_PER_PHASE * 100);
lcd.setCursor(0, 1);
lcd.print("L2 ");
lcd.print(floatToString(bufferString, irms2, 2, 5,true));
lcd.print("A ");
lbg2.drawValue(int(irms2 * 100), MAX_AMPS_PER_PHASE * 100);
lcd.setCursor(0, 2);
lcd.print("L3 ");
lcd.print(floatToString(bufferString, irms3, 2, 5,true));
lcd.print("A ");
lbg3.drawValue(int(irms3 * 100), MAX_AMPS_PER_PHASE * 100);

float sum = irms1 + irms2 + irms3;


lcd.setCursor(0, 3);
lcd.printByte(6);
lcd.setCursor(1, 3);
lcd.print(" ");
lcd.print(floatToString(bufferString, sum, 2, 6,true));
lcd.print("A ");
lcd.print(floatToString(bufferString, voltage, 1, 5,true));
lcd.print("V ");

// Print LCD Screen with Power Values

98 | University of South Asia


void printWatts(float power1, float power2, float power3, float powersSum,
float voltage) {

lcd.setCursor(3, 0);
lcd.print(floatToString(bufferString, power1, 0, 6,true));
lcd.print("W ");
lbg1.drawValue(int(power1), MAX_WATTS_PER_PHASE);
lcd.setCursor(3, 1);
lcd.print(floatToString(bufferString, power2, 0, 6,true));
lcd.print("W ");
lbg2.drawValue(int(power2), MAX_WATTS_PER_PHASE);
lcd.setCursor(3, 2);
lcd.print(floatToString(bufferString, power3, 0, 6,true));
lcd.print("W ");
lbg3.drawValue(int(power3), MAX_WATTS_PER_PHASE);

lcd.setCursor(2, 3);
lcd.print(floatToString(bufferString, powersSum, 0, 7,true));
lcd.print("W ");
lcd.print(floatToString(bufferString, voltage, 1, 5,true));
lcd.print("V ");

// Print LCD Screen with Power Values


void printPowerAndAmps(float irms1, float irms2, float irms3, float power1,
float power2, float power3, float powersSum, float cosPhi1, float cosPhi2, float
cosPhi3, float voltage) {

lcd.setCursor(3, 0);
lcd.print(floatToString(bufferString, power1, 0, 5,true));
lcd.print("W ");
lcd.print(floatToString(bufferString, irms1, 1, 4,true));
lcd.print("A ");
lcd.print(floatToString(bufferString, cosPhi1, 1, 4,true));
lcd.printByte(242);

lcd.setCursor(3, 1);
lcd.print(floatToString(bufferString, power2, 0, 5,true));
lcd.print("W ");
lcd.print(floatToString(bufferString, irms2, 1, 4,true));
lcd.print("A ");
lcd.print(floatToString(bufferString, cosPhi2, 1, 4,true));

99 | University of South Asia


lcd.printByte(242);

lcd.setCursor(3, 2);
lcd.print(floatToString(bufferString, power3, 0, 5,true));
lcd.print("W ");
lcd.print(floatToString(bufferString, irms3, 1, 4,true));
lcd.print("A ");
lcd.print(floatToString(bufferString, cosPhi3, 1, 4,true));
lcd.printByte(242);

float currentSum = irms1 + irms2 + irms3;


lcd.setCursor(2, 3);
lcd.print(floatToString(bufferString, powersSum, 0, 6,true));
lcd.print("W ");
lcd.print(floatToString(bufferString, currentSum, 1, 4,true));
lcd.print("A");

void initLcd3Phases(){
lcd.clear();

//init first line


lcd.setCursor(0, 0);
lcd.print("L1 ");
initEmptyBargraph();

//init second line


lcd.setCursor(0, 1);
lcd.print("L2 ");
initEmptyBargraph();

//init third line


lcd.setCursor(0, 2);
lcd.print("L3 ");
initEmptyBargraph();

//init last line


lcd.setCursor(0, 3);
lcd.printByte(6);
}

void initLcdPowerAndAmps(){
lcd.clear();
lcd.setCursor(0, 0);

100 | University of South Asia


lcd.print("L1");
lcd.setCursor(0, 1);
lcd.print("L2");
lcd.setCursor(0, 2);
lcd.print("L3");
lcd.setCursor(0, 3);
lcd.printByte(6);
}

void initEmptyBargraph(){
for(int i=0; i<10;i++){
lcd.printByte(5);
}
}

char * floatToString(char * outstr, float value, int places, int minwidth, bool
rightjustify) {
// this is used to write a float value to string, outstr. oustr is also the return
value.
int digit;
float tens = 0.1;
int tenscount = 0;
int i;
float tempfloat = value;
int c = 0;
int charcount = 1;
int extra = 0;
// make sure we round properly. this could use pow from <math.h>, but
doesn't seem worth the import
// if this rounding step isn't here, the value 54.321 prints as 54.3209

// calculate rounding term d: 0.5/pow(10,places)


float d = 0.5;
if (value < 0)
d *= -1.0;
// divide by ten for each decimal place
for (i = 0; i < places; i++)
d/= 10.0;
// this small addition, combined with truncation will round our values properly
tempfloat += d;

// first get value tens to be the large power of ten less than value
if (value < 0)
tempfloat *= -1.0;
while ((tens * 10.0) <= tempfloat) {
tens *= 10.0;

101 | University of South Asia


tenscount += 1;
}

if (tenscount > 0)
charcount += tenscount;
else
charcount += 1;

if (value < 0)
charcount += 1;
charcount += 1 + places;

minwidth += 1; // both count the null final character


if (minwidth > charcount){
extra = minwidth - charcount;
charcount = minwidth;
}

if (extra > 0 and rightjustify) {


for (int i = 0; i< extra; i++) {
outstr[c++] = ' ';
}
}

// write out the negative if needed


if (value < 0)
outstr[c++] = '-';

if (tenscount == 0)
outstr[c++] = '0';

for (i=0; i< tenscount; i++) {


digit = (int) (tempfloat/tens);
itoa(digit, &outstr[c++], 10);
tempfloat = tempfloat - ((float)digit * tens);
tens /= 10.0;
}

// if no places after decimal, stop now and return

// otherwise, write the point and continue on


if (places > 0)
outstr[c++] = '.';

102 | University of South Asia


// now write out each decimal place by shifting digits one by one into the ones
place and writing the truncated value
for (i = 0; i < places; i++) {
tempfloat *= 10.0;
digit = (int) tempfloat;
itoa(digit, &outstr[c++], 10);
// once written, subtract off that digit
tempfloat = tempfloat - (float) digit;
}
if (extra > 0 and not rightjustify) {
for (int i = 0; i< extra; i++) {
outstr[c++] = ' ';
}
}

outstr[c++] = '\0';
return outstr;
}

103 | University of South Asia

Anda mungkin juga menyukai