Skip to main content
Engineering LibreTexts

6.3: Coding

  • Page ID
    25713
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)

    ( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\id}{\mathrm{id}}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\kernel}{\mathrm{null}\,}\)

    \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\)

    \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\)

    \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    \( \newcommand{\vectorA}[1]{\vec{#1}}      % arrow\)

    \( \newcommand{\vectorAt}[1]{\vec{\text{#1}}}      % arrow\)

    \( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vectorC}[1]{\textbf{#1}} \)

    \( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)

    \( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)

    \( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)

    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)

    Ordinarily, all code will be contained within a single file. When you create a new project, or “sketch” in Arduino, a new directory will be created for it. Unlike ordinary C language source files, Arduino sketches utilize a “.ino” extension instead of “.c”. Further, the normal main() entry point is not used. In essence, the Arduino system has already written main() for you and it looks something like this:

    void main()
    {
          init();
    
          setup();
    
          while(1)
                loop();
    }
    

    The first function call is where various system initializations occur such as allocating and presetting timers, the ADC system, etc. This has already been written for you. The other two calls, setup() and loop(), are for you to write. setup() is your own initialization function (i.e., things you need to do just once at start-up) and loop() is the portion that will be called repeatedly. So you usually start coding with something that looks like the first figure, above.

    One of the issues with embedded programming is that you don’t have a console for input and output via scanf() and printf(). Normally, an embedded program won’t need these but they are very useful when it comes to debugging a program. Without printf(), how can you insert test points in your code to check progress, values, etc? One technique is to simply flash an LED at specific points in the program. The Arduino boards include a small LED on one of the ports for this purpose. While this is useful, it is limited, so a second and more powerful technique involves two-way communication with the host computer. On the Arduino, this is done via the Serial library. The IDE includes a serial monitor under the tools menu. Selecting this will open a small window. You can use it to send data to the board or send data from the board back to the host computer.

    Let’s look at an example of communicating via the Serial Monitor. First, let’s consider write data from the board back to the host. Here’s a “Hello World” program.

    void setup()
    {
          Serial.begin(9600);
    }
    
    void loop()
    {
          Serial.print("Hello World\n");
          delay( 1000 );   
    }
    

    In the setup function we open the serial library and set the communication speed at 9600 baud (more or less standard speed for the Arduino) using the Serial.begin() function. There is a complimentary Serial.end() function should you decide that you need the particular port pins that are used for serial communication for other purposes later on. Note that all of the calls to functions in this library will start with the library’s name. The loop() functions writes our message using Serial.print() and then waits for about one second using the delay() function, the argument of which is measured in milliseconds. Once that’s done program flow returns back to main(). Of course, main() just repeats on the loop() function so it calls it again. Our message is printed a second time, a third time and so on.

    Enter the bit of code above, compile and download it to the target. Once that’s done, open the Serial Monitor and look at the output. Each second you should see the message “Hello World” printed again. That’s all the controller program does. Not too useful by itself here, but the power to print items back to the host will be very useful once we get going.

    Get used to using the on-line documentation. Two good places to start are the Reference page at http://arduino.cc/en/Reference/HomePage and the Tutorial page at http://arduino.cc/en/Tutorial/HomePage The Reference page includes information on all of the operators and functions built into the Arduino system. The Tutorial gives information on programming concepts and ideas. For example, here is a copy of the on-line documentation of the Serial.print() function:

    6.3.1: Serial.print()

    Description

    Prints data to the serial port as human-readable ASCII text. This command can take many forms. Numbers are printed using an ASCII character for each digit. Floats are similarly printed as ASCII digits, defaulting to two decimal places. Bytes are sent as a single character. Characters and strings are sent as is. For example:

    • Serial.print(78) gives "78"
    • Serial.print(1.23456) gives "1.23"
    • Serial.print('N') gives "N"
    • Serial.print("Hello world.") gives "Hello world."

    An optional second parameter specifies the base (format) to use; permitted values are BIN (binary, or base 2), OCT (octal, or base 8), DEC (decimal, or base 10), HEX (hexadecimal, or base 16). For floating point numbers, this parameter specifies the number of decimal places to use. For example:

    • Serial.print(78, BIN) gives "1001110"
    • Serial.print(78, OCT) gives "116"
    • Serial.print(78, DEC) gives "78"
    • Serial.print(78, HEX) gives "4E"
    • Serial.println(1.23456, 0) gives "1"
    • Serial.println(1.23456, 2) gives "1.23"
    • Serial.println(1.23456, 4) gives "1.2346"

    You can pass flash-memory based strings to Serial.print() by wrapping them with F(). For example :

    • Serial.print(F(“Hello World”))

    To send a single byte, use Serial.write().

    Syntax

    Serial.print(val)
    Serial.print(val, format)

    Parameters

    val: the value to print - any data type

    format: specifies the number base (for integral data types) or number of decimal places (for floating point types)

    Returns

    size_t (long): print() returns the number of bytes written, though reading that number is optional

    /**** end of copied reference material ****/

    The cool thing about this function is the optional second argument that allows you to specify format information. The ability to print out values in hex and binary are particularly useful, for example, when examining bit fields. Modify your program so that it appears as follows, compile, download and run it:

    void setup()
    {
          int i = 27; // try different values for this
    
          Serial.begin(9600);
    
          // println is just print with an added newline character
          Serial.println(i, DEC);
          Serial.println(i, BIN);
          Serial.println(i, HEX);
    }
    
    void loop()
    {
          // nothing to do here  
    }
    

    Less common but still useful from time to time when debugging is the ability to pass values into the running program. The Serial Monitor window includes a small data entry field at the top with an associated Send button. The Serial functions of greatest interest are Serial.available(), Serial.parseFloat() and Serial.parseInt():

    6.3.2: Serial.available()

    Description

    Get the number of bytes (characters) available for reading from the serial port. This is data that's already arrived and stored in the serial receive buffer (which holds 64 bytes). available() inherits from the Stream utility class.

    Syntax

    Serial.available()

    Parameters

    none

    Returns

    the number of bytes available to read

    6.3.3: Serial.parseFloat()

    Description

    Serial.parseFloat() returns the first valid floating point number from the Serial buffer. Characters that are not digits (or the minus sign) are skipped. parseFloat() is terminated by the first character that is not a floating point number.

    Serial.parseFloat() inherits from the Stream utility class.

    Syntax

    Serial.parseFloat()

    Parameters

    none

    Returns

    float

    /**** end of copied reference material ****/

    Serial.parseInt() is similar to Serial.parseFloat() but returns an integer rather than a floating point value. The two parsing functions examine the input string and begin by discarding non-numeral characters. Once a numeral is found, it continues to look at characters in the string until another non-numeral is found. It then translates the ASCII numeral bytes into a single integer value (or float, as the case may be). Note that it is possible to send multiple values at the same time.

    Here’s an example of how they might be used to create a decimal to hex converter. Enter the following chunk of code, compile and download it.

    int i1, i2; // globals to hold the data
    
    void setup()
    {
          Serial.begin(9600);    
    }
    
    void loop()
    {
    
          // Anything in the buffer?
          if (Serial.available() > 0)
          {
                i1 = Serial.parseInt();
                i2 = Serial.parseInt();
    
                // Echo back what you got, but in hex
                Serial.println("In hex, that is: ");
    
                Serial.println(i1, HEX);
                Serial.println(i2, HEX);
            }
    }
    

    Once the program has been downloaded, open the Serial Monitor and enter 10 27 into the text box at the top and then hit the Send button next to it (you could also hit the Enter key on your keyboard). The result should be:

    In hex, that is:
    A
    1B
    

    You can try other values as well. If you enter only one value, i2 will come back as 0. If you enter several values, multiple returns will follow. Try them both before proceeding.

    If you enter a negative value, something interesting will happen. Try typing in -1 -2. What do you see and why?

    Now that you have some basic knowledge of the IDE and how to perform simple text debugging, we can turn to examining how to read from and write to external circuitry.


    This page titled 6.3: Coding is shared under a CC BY-NC-SA 4.0 license and was authored, remixed, and/or curated by James M. Fiore via source content that was edited to the style and standards of the LibreTexts platform.