sean barowsky - electronic normalizer

47
Electronic Normalizer By Sean Barowsky Mike Goodlow Jonathan May Final Report ECE 445, Spring 2015 TA: Braedon Salz 6 May, 2015 Project No. 6

Upload: sean-barowsky

Post on 22-Jan-2018

71 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Sean Barowsky - Electronic Normalizer

Electronic Normalizer

By

Sean Barowsky

Mike Goodlow

Jonathan May

Final Report

ECE 445, Spring 2015

TA: Braedon Salz

6 May, 2015

Project No. 6

Page 2: Sean Barowsky - Electronic Normalizer

ii

Abstract

For this project we explored analog processing in an attempt to help the University of

Illinois’ Physics department perform power calculations in their optic labs. These labs perform

measurements using two monitoring sensors: a reference sensor and a test sensor. Calculations

are performed to measure the difference between them. In order to improve this process they

were looking to obtain a device that could complete these calculations accurately and

instantaneously. Our goal was to design a lab device that would take two inputs from both meters

and perform an analog division to represent the power ratio between the signals. This would

involve incorporating our design to work with the labs power meters and photon detectors and

then constructing analog circuitry to work with each signal. To complete the process a digital

processing design was then implemented to log the data through software, create a user interface,

and control a display for the system.

Through our design process we found that it was ideal to increase the role of software in

the design’s computations. It was also determined that due to the process by which photons occur

on the detector, our filter design would not extrapolate a representation of power with enough

accuracy for lab use. However, considering only the power meter aspect of our design, our

results proved this device is accurate enough to be used by the lab. Optimizing components and

improving the design of this instrument will further increase the accuracy by dropping the noise

level.

Page 3: Sean Barowsky - Electronic Normalizer

iii

Table of Contents

1. Introduction .................................................................................................................................................. 1

1.1 Statement of Purpose ................................................................................................................................. 1

1.2 Functionality .............................................................................................................................................. 1

1.3 Block Descriptions .................................................................................................................................... 1

2. Design ............................................................................................................................................................ 3

2.1 High Level Block Diagram and Software Flow Chart .............................................................................. 3

2.2 Design Specifications ................................................................................................................................ 4

2.2.1 Division Circuit ………………………………………………………………………………4

2.2.2 Filter Circuit………………………………………………………………………..…………6

2.2.3 Power Supply…………………………………………………………………………………8

2.2.4 Microcontroller…………………………………………………………………….…………9

2.2.5 24-Bit ADC……………………………………………………………………………….....10

2.2.6 Display………………………………………………………………………………………10

2.2.7 User Interface…………………………………………………………..……………………11

2.2.8 Memory……………………………………………………………………………………...11

3. Verification ................................................................................................................................................ 12

3.1 Analog Processing ................................................................................................................................... 12

3.2 Digital Processing.................................................................................................................................... 14

3.3 Tolerance Analysis .................................................................................................................................. 15

4. Cost Analysis ................................................................................................................................................ 17

4.1 Labor ....................................................................................................................................................... 17

4.2 Parts ......................................................................................................................................................... 17

4.3 Total Cost ................................................................................................................................................ 17

5. Conclusion .................................................................................................................................................... 18

3.1 Accomplishments .................................................................................................................................... 18

3.2 Ethical Considerations ............................................................................................................................. 18

3.3 Future Work ............................................................................................................................................ 18

6. References .................................................................................................................................................... 20

7. Appendices ................................................................................................................................................... 21

Appendix A – Requirements and Verification Table .................................................................................... 21

Appendix B - Schematics .............................................................................................................................. 24

Appendix C – Source Code ........................................................................................................................... 27

Page 4: Sean Barowsky - Electronic Normalizer

1

1. Introduction

1.1 Statement of Purpose

The University of Illinois physics department has an optics laboratory which performs

tests to determine the transmittance of different materials. The lab technicians currently perform

two separate measurements: a reference measurement from a light source transmitted only

through air, and a second measurement on light sent through, or reflected off, a tested material.

Both light beams come from the same source and are directed to the meter by a beam splitter.

Tedious hand calculations are necessary to then compare the two measurements. Also,

momentary changes in the optical source's strength can deter accurate results. Our project aimed

to solve these problems by designing an instrument that performs these measurements

automatically using the output of each power meter and photon detector. This eliminates the

necessity for awkward and possibly erroneous hand calculations, as well as accounts for small

errors through the instruments ability to perform these measurements in real-time.

This project has valuable use in the optics lab as it will eliminate hand calculations

entirely, allowing less steps to be involved in this calculation process. The software in the design

can also account for unexpected outliers due to power fluctuations. More importantly, this

project will provide a one-step process to output data onto a computer providing the ability to

plot the data on graphing software. This, along with averaging done inside the device, will

provide a strong representation of the dataset in an efficient, accurate, and convenient manner.

1.2 Functionality

The functionality of this project revolves around two major systems: digital processing

and analog processing. The analog processing was designed to incorporate signals from power

meters and photon detectors that are already existing in the labs. Output signals from the power

meters are fed into an analog division circuit that provides the power ratio used in this design. To

accommodate the photon detector output a separate filter circuit is required before entering the

division circuit. A switch is used to route each output signal through its respective process.

Digital processing involved digital conversion and a software element. The division

circuit output is converted to digital form through the use of an analog to digital converter

(ADC), which then relays the value to a microcontroller. This data is then processed by a

microcontroller that handles additional computations for the data. This microcontroller also acts

as the central unit for display, memory, and user interface communications. It provides the basis

to control the display, creates a navigable interface, and outputs results onto an SD card for data

logging purposes.

1.3 Block Descriptions

Power Meters: These meters output a 0-2 Volt signal that scales with the intensity of light

measured. This design was modeled after the Physic lab’s more common meter, the PM100D. A

BNC connector is used to connect to the analog output of the detector and integrate with our

design. These power meters are required to be used at both the source and reference

measurements for the device.

Page 5: Sean Barowsky - Electronic Normalizer

2

Photon Detector: The Physics labs most common photon detector is the id100 series

manufactured by IDQ technologies. This detectors output is a SMB female jack that provides a

10 ns DC pulse every time a photon is detected at a maximum rate of 5 GHz. A 50 ohm load is

expected at its output. The device’s operation in our circuit will be to produce a value

representing photons/second using the frequency of incoming pulses as a basis for the

measurement.

Filter: The use of a low pass filter allows the easy conversion of the pulse output of the photon

detector into a nearly constant DC voltage. This low pass filter is of order 3 and easily realizable

with a few discrete passive components and the TL072CDR IC.

Division Circuit: This circuit performs the division of the source and target detector outputs.

The circuit was implemented using analog signals and performs the division function through a

series of op-amps. 0-2V DC inputs are provided from the external power meters and/or the

photon counter filter circuits, and the output is a 0-3.5V DC signal, representing the ratio of the

two input signals on a logarithmic scale. The output is sent to an Analog-to-Digital conversion

circuit to be used by the microcontroller.

Power Supply: The purpose of the power supply circuit is to convert 120V AC into the

necessary DC power levels required for the design. The output voltage levels should be

consistent from no load to full load, with minimal ripple and noise.

Switches: The purpose of the input switches is to select between the power meters and photon

detector filter circuits, depending on which is being used during testing. This allows for any

combination of Power Meters and Photon Counter to be used.

Microcontroller: The microcontroller is the main source of control. It handles all

communication between the memory, display, ADC, and user interface. Its functionality consists

of system initialization, data sampling, memory output, and data display. The controller

interfaces with the ADC to sample the result of the division circuit. The microcontroller used for

this project is an Arduino Uno R3. It is powered by a 12V supply and operated at a clock rate of

16MHz. [1]

Display: There are two primary functions of the display. First and foremost it displays a

navigable user interface to show system flow. Secondly, it displays real-time results of the

measured power ratio. It has programmable windows to change system settings, delete memory,

calibrate, and begin data sampling.

User Interface: The user interface allows the user to navigate and control display menus and

options. This interface controls the system flow. The microcontroller waits on each key press in

order to determine its next operation. The method of communication is I2C. Button functionality

will be dependent on the current submenu the system is in. [2]

Page 6: Sean Barowsky - Electronic Normalizer

3

2. Design

2.1 High Level Block Diagram and Software Flow Chart

Detector Switch

LEGEND Measurement Instrumentation Digital Processing AnalogProcessing

Power Supply

Analog Filter Circuit

Detector Switch

Division Circuit

Analog Filter Circuit

Power Meter

Power Meter

Photon Detector

Photon Detector

Microcontroller

Memory

Display & User

Interface

Figure 1: High level block diagram

SetSample Rate

SetDisplay Rate

Memory Deletion

Calibration

Begin Measurements

Figure 2: Software Flow Chart

Page 7: Sean Barowsky - Electronic Normalizer

4

2.2 Design Specifications

2.2.1 Division Circuit

Figure 3: Division Circuit

The division circuit design is shown above in Figure 3. It can be broken down into three

smaller stages: 1st, the input switches; 2nd

, the logarithmic amplifiers; and 3rd, a differential

amplifier. The desired output from the overall circuit is a logarithmic representation of the ratio

between the two input voltages. The 1st stage consists of the input selector switches.

Figure 4: Logarithmic Amplifier

In the 2nd

stage, two logarithmic amplifiers are used to convert the input signals to a logarithmic

representation, shown above in Figure 4. The non-inverting terminal of the op-amp is held at

ground, and using ideal op-amp calculations, the inverting terminal will also be at ground.

Therefore, the current through the input resistor will be equal to the current through the diode.

Equation (2.1) shows this relationship.

𝐼𝐷 = 𝐼𝐼𝑁 =𝑉𝐼𝑁

𝑅 (Equation 2.1)

Page 8: Sean Barowsky - Electronic Normalizer

5

The current through the diode is also represented by the ideal diode equation [3]

, shown in

Equation (2.2).

𝐼𝐷 = 𝐼𝑆 (𝑒(

𝑉𝐷𝑉𝑇

)− 1) (Equation 2.2)

Using Kirchhoff’s Voltage Law, the output voltage (VOUT) is equal to the inverse of the

diode voltage (VD). Combining the previous two equations below in Equation (2.3) the output

voltage is proportional to the natural log of the input voltage. It is scaled by the input resistance

(R), the saturation current of the diode (IS), and the thermal voltage of the diode (VT).

𝑉𝑂𝑈𝑇 = −𝑉𝐷 = −𝑉𝑇 ln (𝑉𝐼𝑁

𝐼𝑆𝑅) (Equation 2.3)

Figure 5: Differential Amplifier

In the 3rd

stage, the two logarithmic signals from the previous stage are provided to a

differential amplifier via the resistors shown in Figure 5. The output can be calculated by

superposition. First, with V1 providing an input, and V2 at zero.

𝑉1 − 𝑉−

𝑅3=

𝑉− − 𝑉𝑂𝑈𝑇

𝑅4

Because V2 = 0V, V+ and V- are also 0V. Therefore, the equation becomes simplified.

𝑉1

𝑅3= −

𝑉𝑂𝑈𝑇

𝑅4

Solving for Vout gives the following relationship of Equation (2.4):

𝑉𝑜𝑢𝑡 = −𝑉1(𝑅4

𝑅3) (Equation 2.4)

Now, performing the same analysis with V2 as the input, and V1 at zero:

𝑉− = 𝑉+ = 𝑉2(𝑅6

𝑅5 + 𝑅6)

Page 9: Sean Barowsky - Electronic Normalizer

6

And the second equation becomes:

𝑉𝑂𝑈𝑇 − 𝑉−

𝑅4

=𝑉−

𝑅3

Combining the two equations, and solving for Vout:

𝑉𝑜𝑢𝑡 = 𝑉2 (𝑅6

𝑅5 + 𝑅6

) (𝑅3 + 𝑅4

𝑅3

)

Selecting resistors R3 = R5, and R4 = R6, this simplifies to Equation (2.5):

𝑉𝑜𝑢𝑡 = 𝑉2(𝑅4

𝑅3) (Equation 2.5)

Finally, by superposition, Vout will be the sum of the Equations (2.4) and (2.5), into

Equation (2.6):

𝑉𝑂𝑢𝑡 = 𝑉2 (𝑅4

𝑅3) − 𝑉1 (

𝑅4

𝑅3) = (𝑉2 − 𝑉1) (

𝑅4

𝑅3) (Equation 2.6)

Finally, substituting the equations from the logarithmic amplifier stages (Equation (2.3)), into

Equation (2.6) the result for the division circuit becomes that shown below in Equation (2.7):

𝑉𝑂𝑢𝑡 = (−𝑉𝑇 ln (𝑉1

𝐼𝑆𝑅) − −𝑉𝑇 ln (

𝑉2

𝐼𝑆𝑅)) (

𝑅4

𝑅3) = −𝑉𝑇 (

𝑅4

𝑅3) (ln (

𝑉1

𝐼𝑆𝑅) − ln (

𝑉2

𝐼𝑆𝑅)) = −𝑉𝑇 (

𝑅4

𝑅3) l n (

𝑉1

𝑉2)

𝑽𝒐𝒖𝒕 = 𝑽𝑻 (𝑹𝟒

𝑹𝟑) 𝐥 𝐧 (

𝑽𝟐

𝑽𝟏) (Equation 2.7)

Because the natural log of V2/V1 approaches infinity as V1 approaches zero, the proper

resistance ratio for R4/R3 could not be obtained through simple mathematical calculation. Instead

it was obtained through pSpice simulations, with a ratio of 10.125/1 giving a maximum of 5V

output when V1 approached zero. During actual testing it was found that to prevent damage to

the ADC circuit, a regular diode and a Zener diode were necessary to clip the output voltage at -

0.3V and 3.5V, respectively.

The final output of the division circuit is the desired ratio of the two input signals in

logarithmic form, and scaled by the biasing resistors and diode thermal voltage. This logarithmic

ratio will be converted back to linear ratio by the microprocessor.

2.2.2 Filter Circuit

The simplest way to convert the output of the photon detector to a signal that is usable in

the division circuit is to use a low pass filter between the detector and the division circuit.

Alternatively, a counter could have been used to achieve this conversion. Using a counter would

have involved recording the number of photons detected per unit time. The counter would need

to be reset often and would be prone to overflow and missed detections. Keeping in mind the

faults of the counter design the decision was made to do the conversion with a low pass filter.

The filter will convert a pulse signal coming from the photon detector into a 0-2 VDC signal

which can be used by the division circuit. This method allows the end user to mix types of

detectors. Figure 6 shows the top level block diagram of the filter circuitry.

Page 10: Sean Barowsky - Electronic Normalizer

7

Figure 6: Top Level Filter Block diagram

The first step of the filter design process is to prove that a low pass filter can fulfill the

role needed. In simulation software, generating an input to a low pass Butterworth filter with a

passband frequency of 500 kHz, the output is shown in the circuit diagram in Figure 7. This filter

is not a realistic filter as it is of order 14 and has a cutoff frequency which is too high. The

physics department requested a response range of 100 Hz to 5 MHz. Regardless, it is important

to show here how varying frequency content at the input of the filter effects its output, shown in

figure 7. This data shows that varying photon detection rate will produce linearly varying output

voltages.

From the output of the simulation, it can be shown that the output voltage stabilizes

within 8 microseconds. This is an acceptable rate because our ADC, at the microcontroller, will

sample this output on the order of a thousand samples per second. This sampling rate is well

below the stabilization rate and thus there is little chance of a sample being taken before the

output has stabilized.

Decreasing photon detection rate gives a decreasing output voltage. In this case, when

the frequency of incoming pulses goes below the cutoff frequency of the filter, the entire signal

is effectively passed through the filter and the output becomes unusable. Increasing photon

detection rate gives increasing output voltage.

Another important consideration is the cutoff frequency of the low pass filter. A filter

with a lower cutoff frequency gives an output which is less smooth in the passband and stabilizes

more slowly. A filter with a higher cutoff frequency gives an output which stabilizes more

quickly and is smoother in the passband. A good cutoff frequency for the detection levels needed

is 10 kHz. This cutoff frequency gives a stabilization time less than the sampling interval and a

flat passband.

Next, it was necessary to prove the filter circuit response was linear. At the maximum

output of the photon counter the output of the filter circuit needed to be 2 volts. Also, it was

necessary to show that at the minimum output of the photon counter, which in this case was

limited by the cutoff frequency of the filter, 10 kHz, the output of the filter was near zero. Then,

at a few points between the extremes the output of the filter circuit was shown to be linear.

Page 11: Sean Barowsky - Electronic Normalizer

8

Finally, the filter was translated to a printed circuit board for assembly. The board

required two instances of the filter circuit. The filter required a dual op amp chip, the

TL072CDR, a few inductors, resistors, and capacitors.

The final filter design is a low pass Butterworth filter of order three. The component

values were determined via table lookup for a Butterworth low pass prototype filter. Cutoff

frequency was determined to be 10 kHz. Component values are shown as in the figure 7.

Figure 7: Filter Diagram with Component Values

2.2.3 Power Supply

The devices powered by this supply include: the Arduino microprocessor with associated

LCD display and operational amplifiers in both the division and filter circuits. The power

requirements for these devices are shown below in Table 1. To meet the requirements for all

devices and power levels, a supply capable of providing +/- 12V DC, at 6 watts was used.

Table 1: Power Requirements

Device Voltage

Required (V)

Max. Current

(mA)Note 1

Voltage Required

(V)

Max. Current (mA)Note

1

Arduino

Microprocessor

and LCD

Display

+9 to +12 VDC

~80 mA for Arduino

~100 mA @ 5V for

LCD display

-- --

Division

Circuit

Amplifiers (x3) +5 to +18 VDC 4 mA each -5 to -18 VDC 4 mA each

Note 1: Maximum Currents are approximate based on datasheets and catalogues, with an added 15% for

safety margin

Page 12: Sean Barowsky - Electronic Normalizer

9

Shown below in Figure 16 is the power supply design. It consists of a 6W self-contained

PWM switching power supply. [4]

A 1 amp slow blow fuse is used on the input to provide fault

protection. The 12uF capacitors (C3 and C4) provide an extra level of filtering to reduce output

voltage ripple, while the smaller 0.024uF capacitors (C1 and C2) are placed near the power

converter outputs for decoupling purposes.

Figure 8: Power Supply Circuit

2.2.4 Microcontroller

The microcontroller was programmed using the Arduino integrated development

environment (IDE) which is a set of C/C++ functions. [1]

In order to save processing power,

operations that are easily programmed through direct interaction with on-board components were

utilized instead. Programming entailed acknowledgement of user interface signals and respective

decision making based on the systems current state. Additionally, the microcontroller was used

to add a software conversion to our results and to computer the final power ratio output. Two

different types of communication were required to transmit data between the microcontroller and

its units: SPI and I2C. User interface and display use the I

2C bus, and the SD card (memory) and

ADC use the SPI bus.

The design involved programming the microcontroller to communicate with all of these

devices, sometimes simultaneously. This required optimization of the code to perform with

minimal delays. Due to the two different communications, three clock cycles had to be accounted

for in the programming architecture. Both SPI and I2C operate at separate clock cycles, and the

microcontroller at another clock cycle. For the Arduino Uno, SPI operates at 4 MHz, I2C at 400

kHz, and the ATMEGA328 processor at 16 MHz. With a much higher clock rate on the

processor, the design required critically timed delays to avoid overlapping data transmission on

either bus.

The microcontroller processes the data that is passed from the ADC. By design, the

microcontroller uses software to create the functionality of an anti-logarithmic amplifier. The

reasoning behind not implementing a hardware amplifier was the operating ranges for diodes and

transistors. Due to our differential op amp acting as a divider, the operating range does not fit the

corner cases well enough to accurately translate the value to software. In order to compensate for

this, the microcontroller reads data from the ADC, scales it up to normal exponential value, and

performs an inverse-logarithm to the voltage. This equation is created by the curve-fitting

technique discussed on page 12.

Page 13: Sean Barowsky - Electronic Normalizer

10

Equation (2.8) shows the methodology behind the process where Vin represents the value

from the ADC. Here A and B represent scaling factors on the equation to produce the desired

output based on the exponential curve. To produce a positive result a negative exponent is

required. This is not done in hardware due to the fact that the ADC can be destroyed by very

small negative voltages.

𝑅𝑎𝑡𝑖𝑜 ≡𝐼2

𝐼1′= 𝐴𝑒−(𝑉𝑖𝑛∗𝐵) (Eq. 2.8)

2.2.5 24-Bit ADC

The ADC used in this system is the LTC2440. It is a 24-bit, high resolution, low noise

converter. This was needed to meet the lab requirement of 6 significant figures per data sample.

The Arduino Uno’s onboard ADC is only 10 bits of resolution and was therefore unusable. The

converter has programmable sampling speeds that the user can choose from. A key characteristic

however is that the higher sampling rate, the less accuracy in the data resolution. [5]

It operates at

a voltage between Vcc+0.3V and -0.3V. [6]

These voltage limits are established by wiring the

ADC as seen in Figure 15. We used the 5V supply from the Arduino for Vcc in this design. This

converter is very prone to burning out by overloading its voltage range. [7]

To prevent this, input

to the ADC is limited by a shunt diode to prevent negative voltage and a clipping diode to

prevent excessive positive voltage. Figure 10 shows how this is implemented. [6]

Figure 9: 24 bit ADC Circuit [3]

Figure 10: DC Circuit

2.2.6 Display

The display provides the user menus for each of the blocks in Figure 2. The user knows

what state the system is in based on the LCD screen’s current menu. Certain functionality of the

user interface is enabled and disabled depending on each submenu. The design involved

programming each submenu listed below to perform its respective operation.

Settings Menu: The settings menu offers two functions. The first is to choose the

sampling rate of the memory unit. The second is to choose the update rate on the display.

Once in submenu, options to scale each sampling rate are available via the user interface.

Clear Memory Menu: Overwrites the entire SD card to allow for a new and clean set of

data.

Page 14: Sean Barowsky - Electronic Normalizer

11

Calibration Menu: The calibration menu waits on the user to press select. Its

functionality involves running the system for 10 seconds to stabilize the measurements

and averaging them together to get a value that is stored in the Arduino’s EEPROM.

Begin Measurement Menu: This submenu is the main programming design for this

system. It simultaneously works with the ADC, SD card, and display. The functionality

involves reading the ADC, performing the software conversion on the data, dividing by

the calibration value, and then outputting the result to both the display and memory at

their respective rates.

2.2.7 User Interface

Powered by the Arduino, the user interface provides the input to the microcontroller. It

has four directional buttons that can be programmed. Each button is active based on the systems

current submenu. Functionality for each button is as follows:

Scroll Left / Scroll Right: While in setting menus, these

scroll between the different sampling and display rates

Scroll up: Active in every menu except when beginning

measurements. This allows the user to revert to previous

menus and change selections. Figure 11: Keypad

Select: Active in every menu. Provides the ability to scroll down by selecting each menus

options and verifying it with the microcontroller.

2.2.8 Memory

The memory unit is a micro SD adapter for the Arduino made by Adafruit. It interfaces

with both FAT16 and FAT32 formatted cards. The board is powered directly through the

Arduino’s 5V on-board power supply. The memory is used to write every sample to a data file so

it can be averaged or plotted by graphing software.

This project requires storage over long sampling intervals. In order to estimate the ideal

operating time for this device a simple calculation is performed. Multiplying the memory per

sample by samples per unit time gives us memory per second. To estimate our storage capacity

in terms of time our SD memory was divided by this value. This calculation can be seen in

Equation (2.9).

(Eq. 2.9)

The maximum data transmission rates for this system would be a sampling rate of 4000 samples

per second with 4 bytes per sample. Using an 8GB SD card, max storage time is estimated

around 104.17 hours which absolves any worries about memory storage in this design.

ScrollUp

ScrollLeft

ScrollRight

Select

Page 15: Sean Barowsky - Electronic Normalizer

12

3. Verification

3.1 Analog Processing

Division Circuit

After assembly, it was found during testing that while the output did represent a

logarithmic ratio of the two input signals, losses in the circuit preventing the output from being

the exact desired logarithmic ratio represented in Equation (2.7). However, testing various input

signals showed that the functionality of the circuit was accurate when compared to the different

test points. It was determined that the correction for the errors present would be completed

during software conversion.

Inverse Logarithmic Function

The logarithmic ratio that was originally provided to the microprocessor needs to be

converted back to a linear ratio of the two input signals. The original design was to perform this

function via an analog anti-logarithmic amplifier. This design was not working properly during

simulation when dealing with corner cases, so this design was thrown out.

The new design to convert the logarithmic ratio to a linear ratio involves empirical data

analysis and software conversion. After the division circuit was assembled, the division circuit

output was recorded at various input voltages. Over 100 data points were obtained, and the

output was compared to the mathematically calculated ratio of the two inputs. The resulting plot

is shown below in Figure 12. Using the software program CurveExpert, the equation of best fit

was obtained from this empirical data to convert the logarithmic ratio back to a linear

mathematical ratio.

Figure 12: Empirical Data

Page 16: Sean Barowsky - Electronic Normalizer

13

The equation that fit this curve is shown below in Equation (3.1).

𝑅𝑎𝑡𝑖𝑜 = 0.91397 ∗ 𝑒−3.755399∗(𝐷𝑖𝑣𝑖𝑠𝑖𝑜𝑛 𝐶𝐼𝑟𝑐𝑢𝑖𝑡 𝑂𝑢𝑡𝑝𝑢𝑡) (Equation 3.1)

Filter

In order to verify the functionality of the filter it was necessary to provide realistic inputs

to the filter and verify outputs are within the needed range. The verification was performed on

both filters. The maximum photon detection rate corresponds to a 10-ns 2 V pulse at 5 MHz.

This is the input which is required to produce a two volt output. The filter produced a 1.97 volt

output when given this input. On the other end of the input spectrum, the filter is required to

give a near zero input when given a detection rate near, but above, the cutoff frequency of the

filter. The filter was tested again at 50 kHz. It produced a 3 millivolt output. There is a floor

through which the filter output is unable to go below at the low end of the input range. This

floor is due to residual voltage residing on the PCB and not the output of the filter itself.

The output verification steps in the design process were repeated on the realized filter.

The output was checked for linearity from maximum and minimum output. This was done by

placing inputs to the filter ranging from the maximum detection rate to the minimum rate at

regular intervals. Inputs ranged from 5 MHz to 50 kHz. The outputs were observed to be linear

over the correct range of inputs. The requirement was for the filter to stabilize in a time less than

the sample interval. The smallest sample interval is 0.2 milliseconds and the filter was able to

stabilize within this time.

The filter was further tested to have a passband ripple less than 1 dB and stopband

attenuation of more than 20 dB as stated in the requirements and verification table (Appendix

A.1). Power consumption of the filter proved not to be an issue as the op amps compensated for

power lost in the ohmic losses of the filter. The op amps are powered by wall supply so that the

amount of power available to the filter was sufficient to negate the losses in the filter.

Power Supply

After assembling the finished circuit, it was found that while the power supply did

provide the necessary voltages at up to 6W, it only worked when the positive and negative legs

of the power supply were evenly loaded. This was due to the components in this design requiring

more power from the +12VDC side. This caused the common output of the power supply to

“float”. This meant that while the power supply still provided 24V from end to end, the ±12V to

common voltages varied. (I.E. 16V and -8V, 20V and -4V.)

Page 17: Sean Barowsky - Electronic Normalizer

14

3.2 Digital Processing

Due to every digital component depending on the microcontroller, two steps were taken

to verify functionality. First, each unit was tested alone with the microcontroller in an attempt to

perform its simple functions without other parts of the system. Secondly, testing was done to

verify that each of these systems would run simultaneously.

ADC

Verification for the ADC was done using a code sample known as Beale Code,

referenced in Appendix C.3. This code involved hard wiring the sampling rate to either 5V or

ground to select between 3.5 kHz and 8 Hz sampling rates. The SPI line is intentionally wired to

ground to set a low sampling rate. The code was tested by having a function generator provide an

input to the ADC and programming the microcontroller to read the ADC over a SPI bus. No

problems were encountered in this process.

Memory

Two operations were necessary to verify memory operation: Write and delete. Using the

Arduino Uno’s built in SPI and SD libraries, simple sketches were programmed to write words to

a data file, and then delete them. The major concern was ensuring this could be done continually

without crashing. Thus, a never ending loop was created to make sure the file was properly

opening and closing without the code malfunctioning.

User Interface & Display

The testing for the user interface and the LCD display was quite simple. The 16x2 LCD

Shield came with an easy to integrate Arduino library. The wiring schematic is located in

Appendix B.3 and involved only 2 connections to communicate with the Arduino over I2C. After

wiring the LCD shield to the Arduino simple sketches were programmed to create a menu. Using

only built in functions from the shields library; menus were able to be written to the display.

However, one flaw was encountered during implementation.

The microprocessor and the I2C clock rates are different, and therefore the possibility of

them becoming out of sync is possible, which was not originally considered. The original

implementation involved continuously refreshing the display at the clock rate of the

microprocessor. This meant writing to the display at an incredible fast rate which forced the

display out of sync. Unable to properly diagnose the problem in time, the first LCD display

failed due to high stress on its processor. After diagnosing the problem, built in delays were

added between LCD functions and display print functions were removed from code loops.

Code Integration

The last step of the verification process on the digital side involved incorporating all the

individual code segments. To do this, a menu system was established by using a state machine.

Due to the nature of communicating with two modules over SPI as well as one over I2C, timing

in the code was crucial. Programming the user interface to control the state machine flow

allowed implementation of functions at different times dependent on the system state. A critical

component to combining the code was changing the type of code used for the ADC. ‘Schaeffer

Page 18: Sean Barowsky - Electronic Normalizer

15

Code,’ was used instead of the ‘Beale’ code discussed earlier. It is similar but allows for control

of the sampling rate.

The settings menu had two operations to perform. First the LCD display had to properly

show the current option for the sampling and display rates, and secondly it had to actually

program the ADC to sample at that rate. This was done by waiting on a select signal and then

setting the ADC sampling rate depending on what the menu is currently showing.

The calibration menu was similar to the setting menu, but instead of communicating with

the ADC, the ADC sampled a value and sent it to the microcontroller. Schaeffer code was

implemented here to sample the ADC and average values over a 10 second interval. This was

tested by printing each value onto the SD card and making sure the calibration value equaled the

average calculated in memory.

The measurement menu communicates with all modules. The first step calls the Schaeffer

function and samples the ADC. This value is then divided by the calibration value. After the

ADC performs its operation, the slave select changes so the value can be written to the SD card

which is on the same SPI bus. Additional functionality included displaying the value on the LCD

display. For testing purposes the main priority was to ensure the ADC could sample and write

data to the SD card in a repetitive fashion. The majority of this was trial and error to figure out

how to best perform this implementation. It was ultimately decided to create a very large array of

values from the output of the conversion function, and then the array was stored to the SD card.

3.3 Tolerance Analysis

The primary component of the design is the division circuit. Without precise

measurements by the division circuit, this device is inaccurate and useless. Thus, low tolerance

components are necessary to achieve a high level of accuracy. The physics department requested

the device to be accurate to six significant figures. The device is unable to achieve this level of

accuracy as the error introduced by the log amps and the differential amp is on the order of

1/10,000. This level of accuracy from the output of the division circuit is calculated using

resistors within 1/1000 of their claimed resistance value.

The output of the division circuit is the input to the ADC. The ADC has resolution of 18

bits. Resolution of 18 bits is accurate to 1/1,000,000. This means that the noise floor of the

ADC is 100 times smaller than the noise floor of the division circuit. For this reason, this error

was not calculated as it is negligible when compared to the division circuit.

The next source of error in the device is the mathematical function which converts the

output of the ADC into the desired quotient. An exponential regression was performed on

empirical data to determine a function with the best fit to the data. The fit of this function to the

data recorded at the output of the division circuit determines the accuracy of the last step of

division and thus is a component in the accuracy of the device. Since this calculation is

performed in software the accuracy of the calculation is on the order of 1/1020

. This meant that

the software does not introduce errors above the noise floor of the division circuit. The limit of

accuracy of the software is the accuracy of the regression function.

Page 19: Sean Barowsky - Electronic Normalizer

16

At the output of the entire device, it was found that an error of 1/100 is produced.

Possible sources of this error include variations in the power supplied to the ADC, component

value tolerances, and ohmic losses due to hand soldering. The requirement for the accuracy of

the device is stated as 1/100000. The final device does not meet this requirement. Component

inaccuracies are the greatest contributor to this noise. As stated in the design review, the division

circuit is causing the most error. All other modules of the device have lower error by at least an

order of magnitude.

Some methods to reduce error in this device include selecting components with lower

tolerances and inaccuracies. Since the division circuit produces the most error in this device this

is a reasonable place to start eliminating error. Additionally, averaging can be performed in

software to further reduce variation due to noise. Depending on the length of time for which

values are averaged, noise can be reduced to a more acceptable level. With these two

improvements it is reasonable that the accuracy of the device can be brought to within the

requirements of the physics department.

Page 20: Sean Barowsky - Electronic Normalizer

17

4. Cost Analysis

4.1 Labor

4.2 Parts

4.3 Total Cost

Section Total

Labor $67,500.00

Parts $122.19

Grand Total $67,622.19

Design Section Type Description Manufacturer Part # Price Quantity Total

Inductor 160uH API Delevan Inc. DN2313TR-ND $1.39 2 $2.78

Capacitor 0.12uF Murata Electronics 490-6430-2-ND $0.12 1 $0.12

Photon Conversion Circuit Subtotal $2.90

Op-Amps High Precision, Low Noise Op-Amp Texas Instruments OPA2227-EP $9.00 2 $18.00

Diode 1 Amp Rectifier MCC D1n4007 $0.17 2 $0.34

Resistor 10kΩ (+- .1%) 1/4W Stackpole Electronics RNF14BTE10K0 $0.91 4 $3.64

Resistor 1kΩ (+- .1%) 1/4W Yageo MFP-25BRD52-1k $0.46 2 $0.92

Resistor 100Ω (+- .1%) 1/4W TE Connectivity 1622796-2 $0.67 2 $1.34

Resistor 20Ω (+- .1%) 1/4W TE Connectivity 3-1879026-2 $0.67 2 $1.34

Detector Selection Toggle Switches Single Pole, Double Throw Toggle Switch Copal Electronics, Inc. ATE1E2M3-10-Z $2.87 2 $5.74

Division Circuit Subtotal $31.32

Microcontroller Arduino Arduino Uno - R3 Arduino A000066 $24.95 1 $24.95

Microcontroller ADC 24-Bit Low Noise High-Precision ADC Linearr Technology LTC2440 $7.25 1 $7.25

Memory SD Reader MicroSD Card Breakout Board Adafruit 254 $14.95 1 $14.95

Memory SD Card 8GB Class 6 SD SDHC Flash Memory AGPTek 700697066869 $3.99 1 $3.99

Display LCD RGB LCD and Keypad Adafruit 714 $24.95 1 $24.95

The Brain Subtotal $76.09

Power Supply Converter 6W AC to +/- 12VDC Power Converter Recom Power RAC06-12DC $17.85 1 $17.85

Power Supply Fuse 1 Amp Slow-Blow, 250VAC Littelfuse, Inc. 0229001.MXP $0.69 1 $0.69

Power Supply Fuse Carriage Fuse Carriage Littelfuse, Inc. 02540101Z $1.19 1 $1.19

Power Supply Capacitor 12uF, 63V Ceramic Plate Capacitor Panasonic Electric EEU-FC1J120 $0.33 2 $0.66

Power Supply Capacitor .024uF, 50V Film Capacitor AVX Corp 08055C243JAT4A $0.06 2 $0.12

Power Supply Power Cord Generic AC Power Cord Multiple N/A $2.04 1 $2.04

$0.00

Miscellaneous Subtotal $22.55

TOTAL COST $132.86

Engineer Hourly Rate Total Hours

Invested

Total = Hourly rate

x 2.5 x Total Hours

Invested

Jon $37.50 240 $22,500

Mike $37.50 240 $22,500

Sean $37.50 240 $22,500

Total

720 $67,500

Page 21: Sean Barowsky - Electronic Normalizer

18

5. Conclusion

5.1 Accomplishments

The completed design was demonstrated satisfactorily, with the exception of the power

supply circuit. As mentioned previously, the power supply design requires changes to

accommodate the different levels of loading on the +12V and -12V DC levels. Also, because the

ADC would be more accurate with a better regulated 5V DC supply than the Arduino provides, a

redesign of the power supply incorporating all three desired power levels would be apt.

As for the rest of the design, each section performed the required functions, with a total

combined error of just over 1%. More detailed analysis of this error was covered in section 3.

5.2 Ethical Considerations

While the entire IEEE Code of Ethics points applies when designing and implementing any

engineering project, the most applicable points to this design project are noted below, with the

actions we will take to meet them:

“To accept responsibility in making decisions consistent with safety, health, and welfare

of the public…”[8]

o We ensured that our completed design is safe for use by lab technicians, even

those unfamiliar with general electrical safety principles. This included ensuring

that there are no exposed electrical parts that could shock the user, and also

included fault protection to prevent hazardous conditions.

“To avoid injuring others, their property…”[8]

o Because this design is used with power meters and photon counters in the

Physics Optical lab, our design prevents the possibility of faults from damaging

other equipment.

“To be honest and realistic in stating claims...”[8]

o The Physics Department and Professor Kwiat are essentially our “customers” on

this project, and we ensured that we were realistic in our communication and did

not oversell on something we could not deliver.

5.3 Future Work

Moving forward with this project a few major concerns will have to be addressed. First

and foremost, our power supply implementation will have to change to account for even loading.

This is planned to be done by buying a market power supply to perform the operations we need

rather than designing our own.

Secondly, our filter will need to be redesigned to account for the Poisson distribution that

more accurately represents the output of the photon detector. This can be done through using a

DSP on the photon detector. For simplicity sake, the filter may be dropped entirely to focus on

the power meter aspect of the design.

Page 22: Sean Barowsky - Electronic Normalizer

19

Third, it is critical that better components are placed on the PCB to reduce the noise floor.

This will involve using surface mount components, a more specific op-amp, and diodes with less

thermal loss. Using simulations, the maximum current in the system can be calculated and trace

widths can correspond to that value. Minimizing traces and thereby minimizing the total PCB

size will provide incredible noise reduction on the system.

Lastly, using a regulated power supply for the ADC will create a very accurate digital

conversion. Using the Arduino, 18 bits of accuracy was not achieved, as guaranteed by the

LTC2440 datasheet. By this datasheet, a minimum of 4uV of inaccuracy will be in the data under

ideal conditions. The unregulated Arduino supply was fluctuating far too much to be reliable and

was thus producing noise far greater than the 4uV minimum possible by the ADC.

Page 23: Sean Barowsky - Electronic Normalizer

20

6. References

[1] ATMEL 8-BIT Microcontroller with 4/8/16/32KBYTES In-System Programmable Flash

Datasheet. Atmel Corporation. Oct. 2014. 1600 Technology Drive, San Jose, CA 95110 USA.

[2] RGB LCD Shield. Adafruit Industries. July 2014

[3] Sedra and Smith, Microelectronic Circuits, 6th

ed., Oxford University Press. 2009.

[4] RAC06-C Datasheet. Recom Power International. Gmunden, Austria. Mar. 2014

[5] Interfacing to High Speed ADCs via SPI. Analog Devices. 2005-2007. P.O. Box 9106

Norwood, MA02062-9106, USA

[6] LTC2440 24-Bit High Speed Differential ADC Datasheet. Linear Technology. 1630

McCarthy Blvd., Milpita, CA 95035-7417

[7] General Aplications of the LTC2440 24 BIT ADC. Rev 2.2. Steve Luce, Jan 2015

[8] IEEE Code of Ethics, IEEE Policies, section 7. Jan. 2015

Page 24: Sean Barowsky - Electronic Normalizer

21

Appendix A. Requirements and Verification

A.1 Table of Requirements, Verification

Requirements Verification

Filter

1. Filter output varies at a rate lower than the

sampling rate of 1kHz

2. Filter power consumption is minimal.

3. Attenuation in the passband is <1dB,

stopband attenuation is >20dB

4. -3dB point lies at the cutoff frequency

5. Filter noise floor is below the noise floor of

the division circuit

6. Filter output is in range 0-2V

Filter

1. Use function generator to provide a signal

which varies over a range from 10 kHz to 20

MHz with 2 Volt amplitude, check that filter

output is stable within one period of sampling

time on an oscilloscope.

2. Measure power at the input terminals of the

filter and the output terminals of the filter,

power loss should be very near zero

3. Using a network analyzer, observe the

frequency response of the filter in the frequency

domain, ensure attenuation is <1db in the

passband and >20dB in the stopband

4. Using a network analyzer locate the -3dB point

ensure it lies at the cutoff frequency of 50 kHz

5. Using an oscilloscope observe the noise of both

the division circuit and the filter when they both

have nothing connected to them, observe that

the filter noise floor is lower than the division

circuit noise floor.

6. Using an multimeter, observe the output of the

filter, ensure it is in the range of 0-2 V

Division Circuit

1. Divides two analog signals within accuracy

2. Outputs a 0-5V signal to microcontroller

Division Circuit

1. Using known inputs from 2 separate function

generators, measure output of division circuit

with multimeter. Output voltage should vary

logarithmically.

2. With minimum difference (0V) between the

two input signals, circuit output should be 0V

(±30mV), as read on multimeter. With

maximum difference (~2V), circuit output

should be read maximum difference (~3.5V), as

read on multimeter.

Microcontroller

1. Reads from the ADC, performs

calculations, and stores data at greater

than or equal to 3.5kHz

2. Stores calibration memory on SRAM

Microcontroller

1. Using calculations, run the Arduino for a

sampled period of time and check to see if

the estimated number of samples are stored

into the memory.

2. Run the board and continuously write

SRAM to the memory to make sure it is

Page 25: Sean Barowsky - Electronic Normalizer

22

3. Outputs ratio of current measurement

divided by calibration measurement to

the memory and display at different

rates

4. Write ratio to memory.

5. Communicates with 5 Interface buttons

on the display via I2C.

6. Ability to clear memory

7. Scaling factor for the software inverse-

log function scales to accurate ratio

stored.

3. Verify output ratio is sampled value divided

by the calibration value.

4. Write ‘hello world’ continuously and check

if stored on memory.

5. Use on-board LED’s via I2C to test buttons

6. Send clear signal from the microcontroller

to write over the SD card. Check SD card

via a computer to make sure no data is

entered.

7. Use function generators and test ADC’s

input to get correct scaling factor

Memory

1. Writes over 1.4Kb/sec via SPI

2. Capable of over 1 hour of data storage

3. Interfaces with FAT16 & FAT32 SD

cards

Memory

1. Write test code that outputs data with 4

bytes and run at the max 3.5 KHz rate of

the ADC to see if memory is writing

quickly enough.

2. Run the system for over 1 hour under ideal

conditions and check that the quantity of

data entries correspond to amount of

samples sent to memory.

3. Use both FAT16 and FAT32 SD cards and

test to see data is stored on memory.

Power Supply

1. AC/DC converter provides +12V and -

12V at full load, ±1%.

2. Less than ±2% ripple on voltage output

at full load.

Power Supply

1. Under full load conditions, measure

power supply output voltages with a

multimeter or oscilloscope.

2. Under full load conditions, and using an

oscilloscope, measure output voltage.

Voltage should always fall between

11.76 and 12.24V

Display

1. Continuously updates measurements at

the display update rate

2. Prompts user to power down and to

reset when buttons are pressed

Display

1. Write test code using random functions to

see if the display will continuously update

values at the correct interval.

2. Write interrupt code that prompts user

whether they actually want to reset or

power down. Verify that the execution of

these tasks does not occur until another key

Page 26: Sean Barowsky - Electronic Normalizer

23

3. Displays a navigable interface between

menu options

4. Displays different settings for display

update rate and sampling rate.

press verifies the task.

3. Use directional buttons on interface to

make sure menu scrolls accordingly. Debug

software if incorrect.

4. Verify menu correctly displays the rate

levels when scrolling through menu. Debug

software if incorrect.

User Interface

1. All 5 buttons on the user interface

correctly output a signal when pressed

User Interface

1. Program each button to an LED on Arduino

or memory unit LED’s and check for light

on key press.

Detector Switches 1. Routes the AC signals from the power

meter and detector switch circuits

Detector Switches

1. Hook up both inputs to the switch. Use

multimeter to verify the correct signal is

being passed through the switch without

interference.

Page 27: Sean Barowsky - Electronic Normalizer

24

Appendix B. Schematics

B.1 Microprocessor, ADC, LCD Display, SD card communication wiring

Below is the software configuration for the device. The components featured are the

microcontroller, memory, SD card, user interface, display, and ADC. The only input coming

from the circuit design is the data transferred from the ADC via serial connection, and

therefore is not included in the schematics. The circuit design schematics can be referenced

in their respective block descriptions in section 2.2.

The schematic shows two inputs to the SPI ports for the 24-Bit ADC and the SD memory

card. Using the DC pin 9 on the Arduino a second slave can be used so the second device can

interact with the BUS. The RGB LCD display is also shown, connecting to analog 4 and 5 on

the Arduino to communicate by I2C. The schematic is the full wiring diagram and shows no

pin conflicts with the Arduino Uno R3.

Page 28: Sean Barowsky - Electronic Normalizer

25

Drawn By: SAB

Microcontroller Schematic

TITLE: Microcontroller Circuit

FIGURE 2.2 REV:

1A

Date: 2/24/2015 10:58:27 AM Sheet: 1/1

Page 29: Sean Barowsky - Electronic Normalizer

26

B.2 Beale Code Schematic

B.3 LCD Display Wiring Schematic

Page 30: Sean Barowsky - Electronic Normalizer

27

Appendix C. Source Code

C.1 Filter Matlab Code

As the filter generated by Agilent’s Advanced Design System is of order 14, MATLAB was used

to generate a filter of a reasonable order. The following code generates a Butterworth low pass

filter of order 3. This filter is a physically realizable filter with just a few components. Also, the

plot generated of the filtered signal shows that the order 3 filter is capable of performing the

work of the higher order filter to within reason. This filter takes about 100 microseconds to

stabilize. This is still acceptable as we will be sampling the output signal at a much slower rate,

on the order of thousands of samples per second. The input signal generated in the following

MATLAB code is comparable to that of the photon detectors limitations of detection.

2 function Hd = filter 3 % ECE 445 4 % Jonathan May 5 % jmmay3 6 % 2/23/2015 7

8 % design a filter and apply it to a square wave 9 % observe the response of the filter to determine order 10 % and best cutoff frequency 11

12 %FILTER Returns a discrete-time filter object. 13

14 % MATLAB Code 15 % Generated by MATLAB(R) 8.3 and the Signal Processing Toolbox 6.21. 16 % Generated on: 23-Feb-2015 16:38:46 17

18 % Butterworth Lowpass filter designed using FDESIGN.LOWPASS. 19

20 % All frequency values are in kHz. 21 Fs = 10000; % Sampling Frequency 22 N = 3; % Order 23 Fc = 50; % Cutoff Frequency 24

25 % Construct an FDESIGN object and call its BUTTER method. 26 h = fdesign.lowpass('N,F3dB', N, Fc, Fs); 27 Hd = design(h, 'butter'); 28

29 % Get the transfer function values. 30 [b, a] = tf(Hd); 31

32 % Convert to a singleton filter. 33 Hd = dfilt.df2(b, a); 34

Page 31: Sean Barowsky - Electronic Normalizer

28

35 % define the input signal 36 t = linspace(0, 100, 1000 ); 37 duty = 10; 38 x = square(t,duty); 39

40 % remove negative values 41 x = x + ones(1,length(x)); 42

43 plot(x) 44 hold on 45

46 % apply the filter 47 y = filter(b,a,x); 48 plot(y, ' r') 49 title('filtered photon detector signal'); 50 ylabel('magnitude(V)');xlabel('time(us)'); 51 legend('signal','filtered signal'); 52

53 % [EOF]

Figure 19: MATLAB plot showing the input signal and the output of the filter

Page 32: Sean Barowsky - Electronic Normalizer

29

C.2 Arduino Program Code

#include <Time.h>

#include <math.h>

#include <Wire.h>

#include <Adafruit_MCP23017.h>

#include <Adafruit_RGBLCDShield.h>

#include <SD.h>

#include <SPI.h>

#include <QuikEval_EEPROM.h> //from Linduino library

#include <LTC2440.h> //from Linduino library

#include <UserInterface.h> //from Linduino library

#include <LTC24XX_general.h> //from Linduino library

#include <LT_SPI.h> //from Linduino library

#include <Linduino.h> //from Linduino library

#include <LT_I2C.h>

#include <digitalWriteFast.h>//from Linduino library

#include <Average.h>

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

#define OFF 0x0

#define RED 0x1

#define YELLOW 0x3

#define GREEN 0x2

#define TEAL 0x6

#define BLUE 0x4

#define VIOLET 0x5

#define WHITE 0x7

#define VREF (5.0) // ADC voltage reference

#define PWAIT (19) // milliseconds delay between readings

#define SLAVESELECT 10 // digital pin 10 for CS/

#define BUSYPIN 9 // digital pin 9 for BUSY or READY/

#include <QuikEval_EEPROM.h> //from Linduino library

#include <LTC2440.h> //from Linduino library

#include <UserInterface.h> //from Linduino library

#include <LTC24XX_general.h> //from Linduino library

#include <LT_SPI.h> //from Linduino library

#include <Linduino.h> //from Linduino library

#include <LT_I2C.h> //from Linduino library

static int16_t OSR_MODE; // here type values from 2^6 to 2^15, i.e.: 64, 128, 256, 512,

const int nsamples = 1;

static double LTC2440_vref = 5.0;

File myFile;

void setup()

{

quikeval_SPI_init();

quikeval_SPI_connect();

Serial.begin(115200);

pinMode (SLAVESELECT, OUTPUT);

Page 33: Sean Barowsky - Electronic Normalizer

30

pinMode (BUSYPIN, INPUT);

digitalWriteFast(SLAVESELECT, LOW); // take the SS pin low to select the chip

delayMicroseconds(1);

digitalWriteFast(SLAVESELECT, HIGH); // take the SS pin high to start new ADC conversion

SPI.begin(); // initialize SPI, covering MOSI,MISO,SCK signals

SPI.setBitOrder(MSBFIRST); // data is clocked in MSB first

SPI.setDataMode(SPI_MODE0); // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)

SPI.setClockDivider(SPI_CLOCK_DIV16); // set SPI clock at 1 MHz. Arduino xtal = 16 MHz, LTC2440 max =

20 MHz

//SD card shit starts here

pinMode(8, OUTPUT);

if (!SD.begin(8)) {

// Serial.println("initialization failed!");

return;

}

// Serial.println("initialization done.");

lcd.begin(16, 2);

//configure menu

lcd.setBacklight(YELLOW);

delay(2);

lcd.setCursor(0, 0);

delay(2);

lcd.print("Electronic");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print("Normalizer");

delay(2500);

} // setup()...

void loop()

{

uint8_t buttons = lcd.readButtons();

Menu();

}

void Menu() {

//Start Sample Rate code

SampleRate: // jump call -> This allows the up button to move up to the previous menu option, no functionality for

down button

delay(500); // should actually be some kind of flow control

//Variables

int buttons; // set first display for sample rate to start at 8sps

int rate_samp = 8; // set sample rate to start at 8sps

int state;

int nextstate = 1;

OSR_MODE = LTC2440_OSR_32768; // set beginning rate = 8SPS

lcd.setBacklight(BLUE);

delay(2);

Page 34: Sean Barowsky - Electronic Normalizer

31

PrintSampRate(rate_samp);

//Set sample rate for state 1 here, before loop

while (buttons != BUTTON_SELECT)

{

//state

state = nextstate;

//button read

buttons = lcd.readButtons();

delay(20);

//State 1 Transition

if ( (buttons == BUTTON_RIGHT) && (state == 1) ) {

rate_samp = 16;

OSR_MODE = LTC2440_OSR_16384;

nextstate++;

PrintSampRate(rate_samp);

}

else if ( (buttons == BUTTON_LEFT) && (state == 1) ) {

rate_samp = 4000;

nextstate = 10;

OSR_MODE = LTC2440_OSR_64;

PrintSampRate(rate_samp);

}

//State 2 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 2) ) {

rate_samp = 31;

OSR_MODE = LTC2440_OSR_8192;

nextstate++;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 2) ) {

rate_samp = 8;

OSR_MODE = LTC2440_OSR_32768;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

//State 3 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 3) ) {

rate_samp = 62;

OSR_MODE = LTC2440_OSR_4096;

nextstate++;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 3) ) {

rate_samp = 16;

OSR_MODE = LTC2440_OSR_16384;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

//State 4 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 4) ) {

rate_samp = 125;

Page 35: Sean Barowsky - Electronic Normalizer

32

OSR_MODE = LTC2440_OSR_2048;

nextstate++;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 4) ) {

rate_samp = 31;

OSR_MODE = LTC2440_OSR_8192;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

//State 5 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 5) ) {

rate_samp = 250;

OSR_MODE = LTC2440_OSR_1024;

nextstate++;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 5) ) {

rate_samp = 62;

OSR_MODE = LTC2440_OSR_4096;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

//State 6 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 6) ) {

rate_samp = 500;

OSR_MODE = LTC2440_OSR_512;

nextstate++;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 6) ) {

rate_samp = 125;

OSR_MODE = LTC2440_OSR_2048;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

//State 7 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 7) ) {

rate_samp = 1000;

OSR_MODE = LTC2440_OSR_256;

nextstate++;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 7) ) {

rate_samp = 250;

OSR_MODE = LTC2440_OSR_1024;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

Page 36: Sean Barowsky - Electronic Normalizer

33

}

//State 8 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 8) ) {

rate_samp = 2000;

OSR_MODE = LTC2440_OSR_128;

nextstate++;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 8) ) {

rate_samp = 500;

OSR_MODE = LTC2440_OSR_512;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

//State 9 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 9) ) {

rate_samp = 4000;

OSR_MODE = LTC2440_OSR_64;

nextstate++;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 9) ) {

rate_samp = 1000;

OSR_MODE = LTC2440_OSR_256;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

//State 10 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 10) ) {

rate_samp = 8;

OSR_MODE = LTC2440_OSR_32768;

nextstate = 1;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

else if ( (buttons == BUTTON_LEFT) && (state == 10) ) {

rate_samp = 2000;

OSR_MODE = LTC2440_OSR_128;

nextstate--;

PrintSampRate(rate_samp);

//Set sample rate variable here

}

}

// ***************** TRANSITION ***********************

DisplayRate: //Jump call

delay(500); // should actually be some kind of flow control

// Start Display Rate Code

buttons = lcd.readButtons();

delay(2);

// Reset Variables

Page 37: Sean Barowsky - Electronic Normalizer

34

int rate = 30; //Starting display rate

nextstate = 1;

// LCD Reset and recolor

lcd.setBacklight(RED);

delay(2);

PrintDispRate(rate);

//Begin Display Rate menu items

while (buttons != BUTTON_SELECT)

{

// state reading

state = nextstate;

// button read

buttons = lcd.readButtons();

delay(20); // slow down the loop

if (buttons == BUTTON_UP) {

goto SampleRate;

}

//State 1 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 1) ) {

rate = 20;

nextstate++;

PrintDispRate(rate);

}

else if ( (buttons == BUTTON_LEFT) && (state == 1) ) {

rate = 4;

nextstate = 4;

PrintDispRate(rate);

}

//State 2 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 2) ) {

rate = 10;

nextstate++;

PrintDispRate(rate);

}

else if ( (buttons == BUTTON_LEFT) && (state == 2) ) {

rate = 30;

nextstate--;

PrintDispRate(rate);

}

//State 3 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 3) ) {

rate = 4;

nextstate++;

PrintDispRate(rate);

}

else if ( (buttons == BUTTON_LEFT) && (state == 3) ) {

rate = 20;

nextstate--;

PrintDispRate(rate);

}

//State 4 Transition

else if ( (buttons == BUTTON_RIGHT) && (state == 4) ) {

rate = 30;

nextstate = 1;

Page 38: Sean Barowsky - Electronic Normalizer

35

PrintDispRate(rate);

}

else if ( (buttons == BUTTON_LEFT) && (state == 4) ) {

rate = 10;

nextstate--;

PrintDispRate(rate);

}

}

// ****************************************************TRANSITION

*********************************************************

MemoryDelete: //Jump call

delay(500); // should actually be some kind of flow control

//Serial.begin(9600);

// Begin Option to delete memory off SD Card

// Start Memory Delete Code

//buttons = lcd.readButtons();

// LCD Reset and recolor

lcd.setBacklight(GREEN);

delay(2);

lcd.clear();

delay(2);

//LCD print logic for display

lcd.setCursor(0, 0);

delay(2);

lcd.print(" Delete Memory?");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print("<--No Yes-->");

delay(2);

//state machine

nextstate = 1;

while ((state != 0) && (state != 100))

{

state = nextstate;

buttons = lcd.readButtons();

delay(20);

if (buttons == BUTTON_LEFT) {

goto Calibration; // move to calibration, we are not deleting

}

else if (buttons == BUTTON_RIGHT) {

nextstate = 100;

}

else if (buttons == BUTTON_UP) {

goto DisplayRate;

}

}

delay(200);

// Yes Selected, now delete the memory file!

if (state == 100)

{

//display logic to alert deletion

lcd.clear();

Page 39: Sean Barowsky - Electronic Normalizer

36

delay(2);

lcd.setCursor(0, 0);

delay(2);

lcd.print("Deleting");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print("Memory");

delay(500);

state = 1;

//actual deletion logic

//pinMode(10, OUTPUT);

//digitalWrite(10, HIGH); // Jon added this - it chip selects the SD card

delay(500);

if (SD.exists("data.txt")) {

SD.remove("data.txt");

lcd.clear();

delay(2);

lcd.setCursor(0, 0);

delay(2);

lcd.print("Memory Deleted");

delay(500);

goto MemoryDelete; // should this goto calibration ??

//add a new file at this point????

}

else {

lcd.clear();

delay(2);

lcd.setCursor(0, 0);

delay(2);

lcd.print("No Memory File");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print("Exists");

delay(500);

goto MemoryDelete; //

}

}

//add a new file at this point if there isn't one, in case the file is empty

// code to delete the memory file goes here

//END OF MEMORY DELETION FILE

// ***************************************************** TRANSITION

*************************************************************************

// Calibration code, first ADC incorporation

Calibration:

delay(500);

nextstate = 1;

Page 40: Sean Barowsky - Electronic Normalizer

37

double calib_value;

lcd.setBacklight(VIOLET);

delay(2);

lcd.clear();

delay(2);

lcd.setCursor(0, 0);

delay(2);

lcd.print("Calibrate Ready?");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print("-----> To Begin");

delay(2);

while ((state != 0) && (state != 101)) {

state = nextstate;

buttons = lcd.readButtons();

delay(20);

if (buttons == BUTTON_RIGHT) {

nextstate = 101;

}

else if (buttons == BUTTON_UP) {

goto MemoryDelete;

}

}

if (state == 101) {

state = 1; // Reset Variable for next time we loop

lcd.clear();

delay(2);

lcd.setCursor(0, 0);

delay(2);

lcd.print("Calibrating.....");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print("Please Wait...");

int maxx_calib = 10;// rate_samp * 10; // set calibration array length based on sample rate

double calib_array[maxx_calib];

for (int i = 0; i < maxx_calib; i++) {

// mikes function goes here

calib_array[i] = 0.913973 * pow(2.71828, -3.75539 * shfr_func(OSR_MODE));

Serial.println(calib_array[i], 7);

}

// get the average of the calib_array here:

double sum_calib = 0;

for (int i = 0; i < maxx_calib; i++) {

sum_calib = sum_calib + calib_array[i];

}

calib_value = sum_calib / maxx_calib;

Page 41: Sean Barowsky - Electronic Normalizer

38

lcd.setCursor(0, 0);

delay(2);

lcd.print("Calibration Val:");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print(calib_value, DEC);

delay(2500);

}

MeasurementMode:

delay(500);

int maxx = 50;

double data_array[maxx];

lcd.clear();

delay(2);

lcd.setCursor(0,0);

delay(2);

lcd.print("Press Select");

delay(2);

lcd.setCursor(0,1);

delay(2);

lcd.print("To Begin");

delay(2);

buttons = lcd.readButtons();

while (buttons != BUTTON_SELECT) {

buttons = lcd.readButtons();

delay(20);

}

lcd.clear();

delay(2);

lcd.setCursor(0,0);

delay(2);

lcd.print("Select to Stop");

delay(2);

buttons = 1500;

// int display_rate_mod;

while (buttons != BUTTON_SELECT) {

//reset button

for (int i = 0; i < maxx; i++) {

// mikes function goes here

data_array[i] = (0.913973 * pow(2.71828, -3.75539 * shfr_func(OSR_MODE))) / calib_value;

// display_rate_mod = (1 /rate) * 60;

// if(0 == (second()%display_rate_mod)){

// lcd.print(data_array[i], DEC);

// }

// lcd.setCursor(0,1);

Serial.println(data_array[i], 7);

}

Page 42: Sean Barowsky - Electronic Normalizer

39

lcd.setCursor(0, 1);

lcd.print(data_array[25], DEC);

myFile = SD.open("data.txt", FILE_WRITE);

for (int i = 0; i < maxx; i++) {

myFile.println(data_array[i], 7);

// Serial.println("collecting data and writing to SD card");

//

Serial.println("collecting data and writing to SD card");

}

myFile.close();

buttons = lcd.readButtons();

}

//END Measurement Mode

goto MemoryDelete;

}

// SHAFFER CODE ///

////////////////////////////////

///////////////////////////////

//////////////////////////////

double shfr_func(int OSR_MODE) {

double GAIN = 1;

double OFFSET = 0;

double Volts_Out = 0; //set initial value to "0"

//quikeval_SPI_init(); // Configure the spi port for 4MHz SCK

//quikeval_SPI_connect(); // Connect SPI to main data port

//Serial.begin(115200); // Initialize and set baud rate for the serial port to the P

//begin ADC read and output loop

uint8_t adc_command; // The LTC2440 command word

int32_t adc_code = 0; // The LTC2440 code

double adc_voltage = 0; // The LTC2440 voltage

double adc_summe = 0; // sum of voltages in for-loop

double adc_average = 0; // averaged voltage after for-loop

uint16_t miso_timeout = 1000; // Used to wait for EOC

int i;

adc_command = OSR_MODE; // Build the OSR command code

for (i = 0; i < nsamples; i++)

{ //Begin "for"

if (!LTC2440_EOC_timeout(LTC2440_CS, miso_timeout)) // Check for EOC

{

LTC2440_read(LTC2440_CS, adc_command, &adc_code); // Throws out reading

adc_voltage = LTC2440_code_to_voltage(adc_code, LTC2440_vref);

} //End "if"

Page 43: Sean Barowsky - Electronic Normalizer

40

adc_summe = adc_summe + adc_voltage;

} //End "for"

adc_average = adc_summe / nsamples; // Get average value over nsamples sum

Volts_Out = (adc_average) * (GAIN) + OFFSET; // Allow for linear ADC voltage output calibration

//Serial.println(Volts_Out, 7);

return Volts_Out; // REMEMBER THAT GAIN IS INITIALLY SET TO 1.0 AND OFFSET IS

SET TO 0.0

// Serial.println(Volts_Out, 6); // to 6 decimal places // Send Arduino Board Output from to serial

USB/com port

// to be read by PC/MAC/LINUX serial read program, input

} //end ADC read and output loop

//LCD Sample Rate Function

void PrintSampRate(int rate_samp) {

lcd.clear();

delay(2);

lcd.setCursor(0, 0);

delay(2);

lcd.print("Sample rate: ");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print(rate_samp, DEC);

delay(2);

lcd.setCursor(5, 1);

delay(2);

lcd.print("per second");

delay(2);

}

// LCD Display Rate Function

void PrintDispRate(int rate) {

lcd.clear();

delay(2);

lcd.setCursor(0, 0);

delay(2);

lcd.print("Display Rate: ");

delay(2);

lcd.setCursor(0, 1);

delay(2);

lcd.print(rate, DEC);

delay(2);

lcd.setCursor(5, 1);

delay(2);

lcd.print("per minute");

delay(2);

}

Page 44: Sean Barowsky - Electronic Normalizer

41

C.3 Beale ADC Code

#include <digitalWriteFast.h>

/*

BEALE CODE

Interface between Arduino DM board and Linear Tech LTC2440 24-bit ADC

Oct. 24 2012 John Beale

LTC2440 <----------> Arduino

10: /EXT : ground (use external serial clock)

11: /CS <- to digital pin 10 (SS pin)

12: MISO -> to digital pin 12 (MISO pin)

13: SCLK <- to digital pin 13 (SCK pin)

15: BUSY -> to digital pin 9 (low when result ready)

1,8,9,16: GND : all grounds must be connected

2: Vcc : +5V supply

3: REF+ : +5.0V reference

4: REF- : GND

5: IN+ : Input+

6: IN- : Input-

7: SDI : wire ADC Pin 7 high (+5 VDC) for a 6.9 Hz output rate, or low (GND) for 880 samples

per second.

NOTE: I strongly recommend wiring Pin 7 to +5 VDC to start - this will give you a very slow

but, easy to work with, sample rate. "nsamples" is set to one in the code below. This will give

you a 6.9 sample per second output rate.

14: Fo : GND (select internal 9 MHz oscillator)

*/

#include <SPI.h> // include the SPI library

#include <digitalWriteFast.h> // from http://code.google.com/p/digitalwritefast/downloads/list

// I had to update the WriteFast library for Arduino 1.0.1: replace "#include wiring.h" and

"#include WProgram.h"

// with "#include <Arduino>" in libraries/digitalwritefast/digitalWriteFast.h

#define VREF (5.0) // ADC voltage reference

#define PWAIT (19) // milliseconds delay between readings

#define SLAVESELECT 10 // digital pin 10 for CS/

#define BUSYPIN 9 // digital pin 9 for BUSY or READY/

const int nsamples = 1; // how many ADC readings to average together or CPS setting. nsamples

= 10 yeilds (880/10) or 110 samples per second.

Page 45: Sean Barowsky - Electronic Normalizer

42

// SPI_CLOCK_DIV16 gives me a 1.0 MHz SPI clock, with 16 MHz crystal on Arduino

void setup() {

Serial.begin(9600); // set up serial comm to PC at this baud rate

pinMode (SLAVESELECT, OUTPUT);

pinMode (BUSYPIN, INPUT);

digitalWriteFast(SLAVESELECT,LOW); // take the SS pin low to select the chip

delayMicroseconds(1);

digitalWriteFast(SLAVESELECT,HIGH); // take the SS pin high to start new ADC conversion

SPI.begin(); // initialize SPI, covering MOSI,MISO,SCK signals

SPI.setBitOrder(MSBFIRST); // data is clocked in MSB first

SPI.setDataMode(SPI_MODE0); // SCLK idle low (CPOL=0), MOSI read on rising edge

(CPHI=0)

SPI.setClockDivider(SPI_CLOCK_DIV16); // set SPI clock at 1 MHz. Arduino xtal = 16 MHz,

LTC2440 max = 20 MHz

for (int i=0;i<2;i++) { // throw away the first few readings, which seem to be way off

SpiRead();

}

} // end setup()

//

=====================================================================

========

// Main Loop:

// acquire 'nsamples' readings, convert to units of volts, and send out on serial port

void loop() {

int i;

float uVolts; // average reading in microvolts

float datSum; // accumulated sum of input values

float sMax;

float sMin;

long n; // count of how many readings so far

float x,mean,delta,sumsq;

sMax = -VREF; // set max to minimum possible reading

sMin = VREF; // set min to max possible reading

sumsq = 0; // initialize running squared sum of differences

n = 0; // have not made any ADC readings yet

datSum = 0; // accumulated sum of readings starts at zero

for (i=0; i<nsamples; i++)

{

Page 46: Sean Barowsky - Electronic Normalizer

43

x = SpiRead(); /// ORIGINAL DATA?

datSum += x;

if (x > sMax) sMax = x;

if (x < sMin) sMin = x;

n++;

} // end for (i..)

uVolts = datSum/ n; //Average over N modified original-works

Serial.println(uVolts,7); //original code included...Serial.print(uVolts,6);

} // end main loop

// =================================================================

// SpiRead() -- read 4 bytes from LTC2440 chip via SPI, return Volts

// =================================================================

float SpiRead(void) {

long result = 0;

byte sig = 0; // sign bit

byte b;

float v;

/*

(ADC) "Gain" is innitally set at 1.0 and offset is at 0.0. Adjust these values as needed. A typical

value

for gain with a 1 uV souce voltage and an op amp gain of 1000 would be GAIN = 1000.

These "word" equations might help you to get started:

ADC OUTPUT READING = (SOURCE VOLTS) * (OP AMP GAIN) * (ADC GAIN) [ = 1.0

in example above ]

OP AMP GAIN = (ADC OUTPUT READING) / [ (ADC GAIN) * (SOURCE VOLTS) ]

SOURCE VOLTS = ADC OUTPUT READING / [ (OP AMP GAIN) * (ADC GAIN ]

ADC input voltage = (SOURCE VOLTS) * (OP AMP GAIN) >>> The max safe neg #

of this expression is - 0.250 Volts

*/

float GAIN = 1; // Set GAIN to 1 to start - this varible is the ADC

// multiplacation factor of the ADC output number

float OFFSET = 0; //Offset of the serial number from zero

Page 47: Sean Barowsky - Electronic Normalizer

44

while (digitalReadFast(BUSYPIN)==HIGH) {} // wait until ADC result is ready

digitalWriteFast(SLAVESELECT,LOW); // take the SS pin low to select the chip

delayMicroseconds(1); // probably not needed, only need 25 nsec delay

b = SPI.transfer(0xff); // B3

if ((b & 0x20) ==0) sig=1; // is input negative ?

b &=0x1f; // discard bits 25..31

result = b; //org code..."result = b";

result <<= 8;

b = SPI.transfer(0xff); // B2

result |= b;

result = result<<8;

b = SPI.transfer(0xff); // B1

result |= b;

result = result<<8;

b = SPI.transfer(0xff); // B0

result |= b;

digitalWriteFast(SLAVESELECT,HIGH); // take the SS pin high to bring MISO to hi-Z and start

new conversion

if (sig) result |= 0xf0000000; // if input is negative, insert sign bit (0xf0.. or 0xe0... ?)

v = result;

v = v / 16.0; // scale result down , last 4 bits are "sub-LSBs"

v = v * VREF / (2*(16777216)); // ORIGINAL CODE: +Vfullscale = +Vref/2, max scale (2^24

= 16777216)

/*

THE LINES BELOW ALLOW CALIBRATION OF THE ADC SERIAL OUTPUT VALUE

Change GAIN or OFFSET of the ADC OUTPUT for calibration of your source voltage. The line

below uses

the equation -> v = (GAIN) * (v) + (OFFSET). This is the straight line graph equation "y=ax+b".

The initial value of the GAIN is "1" and OFFSET is set to zero. For a non-linear source voltage

output change the equation

to fit your source equation.

*/

v=v*GAIN + OFFSET;

return(v);

}//END CODE HERE