Functions
Package code into functions with parameters and return values, pass variables by reference, and build formatted text with snprintf.
Why write functions?
A function gives a name to a piece of work. You write it once and call it wherever you need it. Parameters carry values in; return sends one value back:
int square(int x) { return x * x; }- takes an int, gives back an intvoid printLine(int width)-voidmeans it returns nothing
In this chapter the tests call your functions directly with many different values - just like a real test suite - so each function must work on its own.
Parameters and return values
square returns a value that setup() can print or use in a calculation. printLine returns nothing.
------------ 49 25 ------------
celsiusToFahrenheit()
Complete celsiusToFahrenheit so it returns the temperature in Fahrenheit (F = C × 9 / 5 + 32). Do not print inside the function - the tests call it with several values and check what comes back.
70.70
Write a function from scratch
Resistors in series add up. Write the whole function yourself, first line included:
- it is called
totalResistance - it takes two
intvalues in ohms - it returns their total as an
int
Then print totalResistance(220, 330) in setup().
550
clampPwm()
analogWrite only accepts 0 to 255. Write clampPwm so it returns value limited to that range: below 0 becomes 0, above 255 becomes 255, everything else is unchanged.
255
percentToPwm()
People think in percentages; analogWrite wants 0 to 255. Write percentToPwm so it turns a percentage into a duty value: 0 % gives 0, 100 % gives 255, 50 % gives 127.
127
Write your own map()
Arduino's map() rescales a number from one range to another - an analogRead value 0-1023 to a PWM value 0-255, say. Write your own version called scale, using whole-number maths and without calling map():
result = (x − inMin) × (outMax − outMin) / (inMax − inMin) + outMin
It must also work when the output range runs backwards, like 100 down to 0.
127
Passing by reference
Normally a function receives copies of its arguments, so changing a parameter does not change the caller's variable. Put & after the type - int &a - and the parameter becomes another name for the caller's variable. That is how one function can change two variables.
Swap two variables
swapValues swaps its own copies, so x and y in setup() never change. Change the function so it swaps the caller's variables. Only the first line needs to change.
Before: x = 3, y = 8 After: x = 8, y = 3
Formatted text with snprintf
snprintf(buffer, sizeof(buffer), format, values...) writes text into a char array, following a format like "%02d:%02d". %d is an int, %02d pads it to two digits with a leading zero, and %s is text. Lesson 19 uses it to format clock times.
On the Uno %f does not work - it prints ?. Use dtostrf() to turn a float into text first.
formatMinutes()
Write formatMinutes so it returns a time in seconds as MM:SS text - 125 seconds becomes 02:05. Use snprintf with %02d into the char array, then return String(buffer).
02:05
formatTime()
Now the full clock: write formatTime so it returns the time as HH:MM:SS - 3725 seconds becomes 01:02:05. Same idea as the last exercise, with hours added.
01:02:05
Why does it print a question mark?
formatVolts should return text like 4.73 V, but on an Uno it returns ? V, because the Uno's snprintf cannot handle %f. Fix it so the voltage appears with two decimals. dtostrf(value, 1, 2, text) writes a float into a char array; print that with %s.
4.73 V
Try it on a real Uno
Put two of these functions together on real hardware: read a potentiometer with analogRead(A0), turn it into a percentage, then use percentToPwm and analogWrite to dim an LED on pin 9. Print the percentage with formatVolts-style text so the Serial Monitor shows what the knob is doing.