salinity measurements with arduino 43layout...arduino sketch to average readings copy values to...

22
Salinity Measurements with an Arduino ME 121 Mechanical and Materials Engineering Portland State University

Upload: others

Post on 11-Mar-2020

15 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Salinity Measurementswith an Arduino

ME 121Mechanical and Materials Engineering

Portland State University

Page 2: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Goals of this presentation areReview operation of the salinity sensor

• Motivate need for turning power on and off• Location of sensor in the voltage divider circuit

Create functions for averaging sensor input• Encapsulate code for re-use with different sensors• Keep main loop code more compact

Page 3: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Salinity measurementPrinciples of operation• Ions migrate to the electrodes

having the opposite charge• Ions exchange electrons at the

probes, which causes current flow• Ion concentrations increase over

time while power is on• Turn power on only during brief

measurement period to prevent ion build-up on probes

!"!

"#!!

!"!

$%!&'!

!"!

#$"!#$!

#$!

#$%!

#$"!

!" !

#$"!! "!

!"!

&'"!

'%&!

'%&!&'"!

'!

'!!"!

!"!

()*+,!-!*./+(0*)!!"#$$%#&%'"'()*#+$,!

1(23*+,!-!4,+510*)!!-./+%#&%'"'()*#+$,!

#$"!

#$"!

#$"!

#$"!

()*!

()*!

()*!

()*!()*!

()*!#$"!

#$"!

#$"!

#$"!

()*!()*!

()*!

()*!

()*!

#$"!

/*)!6/74(0*)!!

()*!8(9!/:!(!:;,12(2*4!/*)!!

Page 4: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Salinity measurement with voltage divider

Sensor circuit is a voltage divider• Arduino cannot measure resistance

directly.• Use a voltage divider to measure

change in voltage due to change in resistance

• Sensor resistance decreases as salt concentration increases

• Measure voltage across the fixed resistor – Why?

salinty sensor(variable resistance)

10 kΩ

Analog input

Digital output

Page 5: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Study questionsHow does analog input value vary when …• Electrical resistance of water decreases?• Electrical resistance of water becomes very large?

If the resistance of the sensor varied linearly with salinity, would the analog input reading (voltage) also vary linearly with salinity?

salinty sensor(variable resistance)

10 kΩ

Analog input

Digital output

!"#$ = !&'()

(* + ()R2 is the fixed (10 kΩ) resistor

R1

R2

Page 6: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Programs for reading the salinity sensorRead one value at a time

• Encapsulate in a function so it can be reused

Read multiple values and return the average• Keep averaging calculations in the function

Both Arduino codes use the same circuit

Page 7: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Outline of salinity measurement codeAlgorithm

1. Turn on 5V power with digital output pin2. Wait for initial voltage transient to settle3. Read voltage across fixed resistor4. Turn off the power

salinty sensor(variable resistance)

10 kΩ

Analog input

Digital output

Page 8: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Single reading of salinity sensor

salinty sensor(variable resistance)

10 kΩ

Analog input

Digital output

int salinity_power_pin = 4; // Digital I/O pin, Global variable

void setup() {Serial.begin(9600);pinMode(salinity_power_pin, OUTPUT);

}

void loop() {

int salinity_input_pin = A2;int reading;

digitalWrite(salinity_power_pin, HIGH); // Turn on sensordelay(100); // Wait to settlereading = analogRead(salinity_input_pin); // Read voltagedigitalWrite(salinity_power_pin, LOW); // Turn off sensor

Serial.println(reading);}

Page 9: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Why move the sensor reading code into auser-defined function?Make the code reusable

• Reusable by other sensors in the same program• Reusable in other programs: write and debug once, reuse

more than once

Isolate details• Simplify and shorten the code in the loop function• Use simple variable names in local function, and more

descriptive names in the loop function

Make the code easier to maintain• Code in the user-defined function can be improved without

(necessarily) making changes in the loop function• Code in the user-defined function does not need to change

as the loop function changes, e.g. adding new variables or features.

Page 10: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

A function to make a single readingint salinity_power_pin = 4; // Digital I/O pin, Global variable

void setup() {Serial.begin(9600);pinMode(salinity_power_pin, OUTPUT);

}

void loop() {

int salinity_input_pin = A2; // Analog input pinint salinity;

salinity = sensor_reading(salinity_power_pin, salinity_input_pin);Serial.println(salinity);

}// -------------------------------------------------int sensor_reading(int power_pin, int input_pin) {

int reading;

digitalWrite(power_pin, HIGH); // Turn on the sensordelay(100); // Wait to settlereading = analogRead(input_pin); // Read voltagedigitalWrite(power_pin, LOW); // Turn off the sensorreturn reading;

}

Salinity reading occurs inone line of loop function

Page 11: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

A function to make a single readingint salinity_power_pin = 4; // Digital I/O pin, Global variable

void setup() {Serial.begin(9600);pinMode(salinity_power_pin, OUTPUT);

}

void loop() {

int salinity_input_pin = A2; // Analog input pinint salinity;

salinity = sensor_reading(salinity_power_pin, salinity_input_pin);Serial.println(salinity);

}// -------------------------------------------------int sensor_reading (int power_pin, int input_pin) {

int reading;

digitalWrite(power_pin, HIGH); // Turn on the sensordelay(100); // Wait to settlereading = analogRead(input_pin); // Read voltagedigitalWrite(power_pin, LOW); // Turn off the sensorreturn reading;

}

Copy values to inputs.Variable names can be different.

return copies the result toa variable in the calling function.

power_pin and input_pin are local variables inside the function.

Page 12: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Improve the user-defined functionCode in the loop function has variables for the inputs and outputs

• salinity_power_pin to supply 5V power• salinity_input_pin to make analog reading• salinity receives the result of the measurement

Change the internal details of the reading without affecting loop• Add averaging to the function• Variable names local to the function are not visible to loop

Page 13: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Account for variability in analog input readings

Output of the salinity sensor is not constant• Variation is due to electrical noise and system unsteadiness• Small variations are OK• We need to look at the data graphically

0 5 10 15

550

600

650

700

time (s)

Ana

log

read

ing

Mean = 634.2

Page 14: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Account for variability in analog input readings

If salinity is truly constant (not varying in time), then• Averaging the data is reasonable• Confirm data quality with a dot plot or histogram

A dot plot puts a “dot” for each reading• Result is stacks of dots along the horizontal axis• A “good” dot plot has a strong central tendency – a tall central stack at the

average value• The spread in the stacks is a measure of variability

Analog input readings

620 625 630 635 640 645 650

Mean = 634.2Std. dev. = 6.5

0 5 10 15

550

600

650

700

time (s)

Ana

log

read

ing

Mean = 634.2

Page 15: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Account for variability in analog input readings

A histogram groups the readings in bins – same data as a dot plot• Shape of the histogram depends on width of the bins• A “good” histogram t has a strong central tendency – a tall central stack at

the average value• The spread in the bins is a measure of variability

Mean = 634.2Std. dev. = 6.5

Page 16: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Since averaging smooths out the variation in the readings, let’s add averaging to our code

The average

The standard deviation<latexit sha1_base64="(null)">(null)</latexit>

<latexit sha1_base64="(null)">(null)</latexit>

Page 17: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Evaluate the sum with a loopDefine s as a variable to hold the sum

Add one term at a time to s

Code becomes this, with xi replaced with analogRead(pin)

<latexit sha1_base64="(null)">(null)</latexit>

sum = 0.0;

for (int i; i<=n; i++) {reading = analogRead(input_pin);sum = sum + reading;

}ave = sum/float(n);

<latexit sha1_base64="(null)">(null)</latexit>

Page 18: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Code to compute the average of n readings

To compute

Use this code snippet

<latexit sha1_base64="(null)">(null)</latexit>

int n; // Number of readingsint reading; // Value of current analog input readingfloat sum; // sum of x_i (sum of readings)float ave; // average of n readings

sum = 0.0;

for (int i; i<=n; i++) {

reading = analogRead(input_pin);sum = sum + reading;delay(10); // pause briefly between readings

}ave = sum/float(n);

Add current reading to accumulated sum

Set initial value of sum to zero

} Declare variables once,outside of the loop!

Page 19: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Same effect in more compact code

Original code snippet

More compact version using the += operator

int n; // Number of readingsint reading; // Value of current analog input readingfloat sum; // sum of x_i (sum of readings)float ave; // average of n readings

sum = 0.0;for (int i; i<=n; i++) {reading = analogRead(input_pin);sum = sum + reading;delay(10);

}ave = sum/float(n);

int n; // Number of readingsfloat sum; // sum of x_i (sum of readings)float ave; // average of n readings

sum = 0.0;for (int i; i<=n; i++) {sum += analogRead(input_pin);delay(10);

}ave = sum/float(n);

Replaces two linesreading = analogRead(…)sum = sum + reading;

Page 20: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Arduino sketch to average readingsint salinity_power_pin = 4; // Digital I/O pin, Global variable

void setup() {Serial.begin(9600);pinMode (salinity_power_pin, OUTPUT);

}

void loop() {int salinity_input_pin = A2; // Analog input pinint n = 15; // number of readings to averagefloat salinity; // Average reading is a float

salinity = sensor_reading_ave(salinity_power_pin, salinity_input_pin, n);Serial.println (salinity);

}// -------------------------------------------------float sensor_reading_ave(int power_pin, int input_pin, int nave) {float ave, sum;

digitalWrite(power_pin, HIGH); // Turn sensor ondelay (100); // Wait to settlesum = 0.0;for (int i; i<=nave; i++) {sum += analogRead(input_pin); // Accumulate the sumdelay(10); // Pause, briefly

}digitalWrite(power_pin, LOW); // Turn sensor offave = sum/float(nave); // Compute averagereturn ave;

}

Page 21: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

int salinity_power_pin = 4; // Digital I/O pin, Global variable

void setup() {Serial.begin(9600);pinMode (salinity_power_pin, OUTPUT);

}

void loop() {int salinity_input_pin = A2; // Analog input pinint n = 15; // number of readings to averagefloat salinity; // Average reading is a float

salinity = sensor_reading_ave(salinity_power_pin, salinity_input_pin, n);Serial.println (salinity);

}// -------------------------------------------------float sensor_reading_ave (int power_pin, int input_pin, int nave) {float ave, sum;

digitalWrite (power_pin, HIGH); // Turn sensor ondelay (100); // Wait to settlesum = 0.0;for (int i; i<=nave; i++) {sum += analogRead(input_pin); // Accumulate the sumdelay(10); // Pause, briefly

}digitalWrite (power_pin, LOW); // Turn sensor offave = sum/float(nave); // Compute averagereturn ave;

}

Arduino sketch to average readings

Copy values to inputs.

return copies result to a variable in the calling function.

power_pin, input_pin and nare local variables in the function.

Page 22: salinity measurements with Arduino 43layout...Arduino sketch to average readings Copy values to inputs. return copies result to a variable in the calling function. power_pin, input_pinand

Summary1. Salinity sensor is used in a voltage divider2. Salinity sensor is turned on only while readings are taken3. User-defined function computes the average

You should know• How to build the voltage divider circuit• How to write a re-usable function that computes average of analog input