Controlling The Real World With Computers
::. Control And Embedded Systems .::

Table Of Contents
Previous: Reading a Schematic & Basic Electronics
Next: Datalines, bits, nibbles, bytes, words, binary and HEX

Putting It All Together - Controlling The Hardware With The Software
Programming Part 1

Much of the world's software is written in the C programming language. A significant improvement, the C++ language, is now finding use in embedded systems and is extensively used in factory control systems. We will concentrate on the basics of the C language here.

C language source code is written in plain text format. C programs have a .c extension. C++ program files have a .cpp extension. Only basic C will be discussed here.

Flowcharting is used to make a picture of the flow of a program before typing it into text. Many symbols are available, but only a few will be covered here.

A circle is used as a connector. To keep things simple, it is used here for start and end as well as to show flow has moved to a different part of the page. It is often used to show flow continues at the top of the page:



A rectangle is used to show a process:


A diamond is used to show a decision. A question with a true or false answer is entered, then the flow splits according to the answer:

Let's say we have a robotic vehicle. On the front, sides, corners and back are bump switches. We want to flowchart what action to take for each of the switches:


The chart would continue until all switches were considered. Many potential problems can be avoided by using flowcharts, as they present a picture of the flow. Text for the actual program pretty easily follows a flowchart.

Two programs are used to turn the source code into a program the computer can use. One is called a compiler. It produces what is called object code. Then a program called a linker builds the final executable program from one or more files called object code files. The linker is often left out in discussions (including here) but they are both needed.

It's very important to comment your code as you go along. It's tempting to put it off thinking all will be remembered. Murphy says it won't (Murphy's law: "Anything that can go wrong, will go wrong."). There are two kinds of comments in the Arduino world which are the same as those in a C or C++ program. Incidentally, Arduino calls code a sketch, I suspect because it's simplified in that the code doesn't have to have a lot of the requirements of, say, a C++ or C program. One format for commenting in a sketch is the single line form which uses the double slash:

// double slash, single line comment

The other type of comment is used for either a single line or multiple lines. The comment section is started with /* and ended with */:

/* This is the type of

comment that can be used with

more than one line. */

/*
This is also a multi-line comment.

*/

Some compilers recognize only the /* */ sequence. If you get errors related to comments and you are using the double-slash type, try changing to the /* */ sequence to see if that will fix the problem.

A sketch in an Arduio system starts with something called setup(), which looks something like this:

void setup()
{
}

Setup is where one sets things up (duh).

You will see something like this when you first start the Arduino software before you have worked with any of the programs. The software is free at arduino.cc:



What you see will be a “do nothing” program.


A very basic program that comes with the Arduino software is called Blink. Load it by clicking on File at top left, then Examples then 01Basics then Blink:

You will see something like the following:

/*
Blink Turns on an LED on for one second, then off for one second, repeatedly.
This example code is in the public domain.
*/


// declare the integer led so that it refers to pin 13 on the UNO
// notice the semicolon
// all C statements or groups of
// statements end with a semicolon


int led = 13;

// the setup routine runs once when you press reset or restore power after turning the UNO off:

void setup()
{
   // initialize the digital pin as an output.
   pinMode(led, OUTPUT);
}

// the loop routine runs over and over again until a restart:

void loop()
{
   digitalWrite(led, HIGH);    // turn the LED on (HIGH is the voltage level)
   delay(1000);    // wait for a second (1000ms)
   digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
   delay(1000); // wait for a second
}

The only differences between the above and the code you will get from the Arduino software is that there are a few more comments in their software, and the open curley braces ({ ) are right after the parenthesis for setup and loop. I prefer the open curley braces under the routine names and on the left border as above. The compiler doesn't care.

Notice the line that reads int led above setup(). It declares the led variable which is used in the program. A variable is something that you can change as needed in the program. The label int means integer, which means that led is a simple counting number that can be negative or positive, but does not have a fractional part to it. Here, it's set to 13, which is the connector pin number on the UNO board. Pin 13 also connects to an LED on the board.

There are a few rules for variables and other labels in a C program:

1. Every variable name in C must start with a letter.

2. The rest of the name can consist of letters, numbers and underscore characters.

3. The use of a blank space in a label name is not permitted. For example, The label "this is a name" is not allowed, but "this_is_a_name" and ThisIsAName are OK.

4.Don't worry, the compiler will let you know if it doesn't like a name. Note that setup knows nothing about variables declared after it. They are said to be out of scope for setup.

After setup you will find something called loop:

void loop()
{
}

Everything between the open curly brace ( { ) and close curly brace ( } ) will run in a loop until the reset button is pushed or power is lost.


Now click the right arrow, which is the compile button:

The program should compile, be sent to the UNO and run. It just blinks one of the LEDs on the UNO board. It turns on the LED for 1 second (1000ms), then turns it off for 1 second. How would you change the program so it turns the LED on for 100ms and off for 1 second?

Now let's say we are going to call another function from inside loop(). We will make it return an integer that is what we send it squared.

int x,y;    // declare the integers x and y
               // notice the semicolon
               // all C statements or groups of
               // statements end with a semicolon

void loop()
{
   x = 5;  // set x equal to 5
   y = squared(x);   // set y equal to whatever squared returns
                            // squared is sent a copy of x, not x itself,
                            // so x is not modified by the squared routine
}

/* ======================================================================
The following begins "squared." Notice that the argument name in the
parentheses does not need to have the same name as the variable in the
sending program. The subroutine returns an integer that is the input
argument times itself (squared). We have given the input argument the
name "indat." We could have called it anything. Also notice the way
this comment is set off. Use either format you wish. Either declare
a comment with // or with the /* */ sequence. Most importantly, be sure
to describe a subroutine with a comment section above it.
====================================================================== */

int squared(int indat)
{
   return indat * indat;   // return the input indat times itself -- square it
}

To see what's going on, let's print the results of several calls to squared(..).

The sample program is exmpl1.c Download it here. Once it's loaded, press the control button and, while holding it down, press A and C at the same time (Ctrl AC). This will copy all of the text in the program. Now go to the Arduino software text area and press Ctrl AV. This will paste the text you copied into the Arduino text area, replacing what text is there. Save the program as exmpl1.

Its setup starts serial communication to the programming computer To see the result, click on Tools then Serial Monitor:

void setup()
{
   Serial.begin(9600); // set up serial to 9600 bits per second for test
}

Then loop prints through the serial connection like this:

void loop()
{
   for(x=0; x<11; x++) // set x equal to 0, then 1, etc. through 10
   {
      y = squared(x);    // set y equal to whatever squared returns
      Serial.print( "x = " ); // literal string sent to host computer
      Serial.print( x ); // value sent to squared
      Serial.print( " y = " ); // literal string sent to host computer
      Serial.println( y ); // squared value sent to computer with a line feed
      delay(1000); // 1 second
   }

}

The output of the above program is below:
x = 0 y = 0
x = 1 y = 1
x = 2 y = 4
x = 3 y = 9
x = 4 y = 16
x = 5 y = 25
x = 6 y = 36
x = 7 y = 49
x = 8 y = 64
x = 9 y = 81
x = 10 y = 100

Let's see what the program did. The first addition in this version is what is called a for loop. The following shows how it works:

           _Start x at 0
           |     _Run the loop as long as x
           |    |  is less than (<) 11
           |    |          _Increment x by 1 each time
           |    |         |  through the loop
           |    |         |
           |    |         |
for(x=0; x<11; x++)

What this says is to first set x to 0, then run the loop as long as x is less than 11, incrementing it each time around. Everything inside the curley braces ({ }) under the for() loop statement is part of the loop:

for(x=0; x<11; x++)
{
    // everything in here is part of the for() loop
}

For loops are very flexible. Consider the following:

for(x = 12; x >= -20; x-=2)
{
}

Notice the spaces between x, = and 12, as well as other characters. Except for labels, C does not care if you add white space,
which is anything that is not readable, such as tabs, spaces, blank lines, etc. The C compiler ignores white space.
It is a very good idea to use that fact to spread things out a little if it makes the code easier to read.

Here, x is started at 12. The loop continues as long as x is greater than or equal to (>=) -20.
Each time around, x is decrement by 2 (-=2). Thus, x would follow the sequence
12, 10, 8 etc., 2, 0, -2 etc., -14, -16, and finally reach -20. Try this loop in the
squared program and see what happens.

Back to the original program. The first thing that happens inside the for loop is a call to the squared() function.
The x variable is used as the value for the argument to be squared, and y gets the result from the squared() function:

y = squared(x);   // set y equal to whatever squared returns

After y is set by the return of squared, both x and y are printed using the Serial.print() function.
Serial.print() is one of the built-in Arduino functions that means print to the serial line back to the programming computer.

Serial.println() means to print with a new line following the information printed.

We are now going to look at something called Chase. Its purpose is to turn on the first LED for 250ms, turn it off, then turn on the next LED for 250ms and so on for four LEDs. Let's cover one other thing first. It's called the switch statement. It looks like this:

switch(var) // var is just about any variable, usually an integer
{
   case 1:
   // do something when var = 1
   break;

   case 25:
   // do something else when var = 25
   break;

   default:
   // do default stuff here
   break;
}

But for now, let's look at something called Chase. It can be described as a program that causes several lights to follow each other in a sequence. For example, get some LEDs and resistors and connect them in the following manner using an UNO and a breadboard, all of which you can get at any electronics store, such as Radio Shack or Jameco (the previous section shows how to hook things up -- hint, assume the UNO provides 5 volts on its outputs):

You will learn more if you work the problem, but if you give up, there's a cheatsheet here, and if you highlight a little, you might find the answer: 150

One way to do a chase program can be found in chase1.c:

// Chase1

int LED1_Pin_7 = 7;
int LED2_Pin_8 = 8;
int LED3_Pin_12 = 12;
int LED4_Pin_13 = 13;

void setup()
{
   pinMode(LED1_Pin_7, OUTPUT);// set the pin for LED1 as an output
   pinMode(LED2_Pin_8, OUTPUT);// set the pin for LED2 as an output
   pinMode(LED3_Pin_12, OUTPUT);// set the pin for LED3 as an output
   pinMode(LED4_Pin_13, OUTPUT);// set the pin for LED4 as an output
   digitalWrite(LED1_Pin_7, LOW);// turn LED1 off
   digitalWrite(LED2_Pin_8, LOW);// turn LED2 off
   digitalWrite(LED3_Pin_12, LOW);// turn LED3 off
   digitalWrite(LED4_Pin_13, LOW);// turn LED4 off
}

Then, next in Chase1, we simply turn on an LED wait 250ms then turn it off:

void loop()
{
   digitalWrite(LED1_Pin_7, HIGH); // turn the LED on (HIGH is the voltage level)
   delay(250); // wait fo 250ms
   digitalWrite(LED1_Pin_7, LOW); // turn the LED off
   delay(250); // wait fo 250ms
   digitalWrite(LED2_Pin_8, HIGH); // turn the LED on (HIGH is the voltage level)
   delay(250); // wait fo 250ms
   digitalWrite(LED2_Pin_8, LOW); // turn the LED off
   delay(250); // wait fo 250ms
   digitalWrite(LED3_Pin_12, HIGH); // turn the LED on (HIGH is the voltage level)
   delay(250); // wait fo 250ms
   digitalWrite(LED3_Pin_12,LOW); // turn the LED off
   delay(250); // wait fo 250ms
   digitalWrite(LED4_Pin_13,HIGH); // turn the LED on (HIGH is the voltage level)
   delay(250); // wait fo 250ms
   digitalWrite(LED4_Pin_13,LOW); // turn the LED off
   delay(250); // wait fo 250ms
}

// end Chase1

Download Chase1.c here

But how would this be done using a for loop and a switch statement?
The port variables LED1_Pin_7, etc. would still be declared the same and the LEDs turned off, but their use inside loop() will change.
See chase2.c for one answer. Why do the lights run faster?

What happens in chase3.c? Comment the programs to explain what's happening.
How could you set up a single value so that the timing would change for all four LEDs?
It would need to be a constant, at least when used in the manner I used it in chase4.c; something like this:

const int TotalMilliseconds = 300; // total time used in for loop at 1ms per step

Download Chase2.c here
Download Chase3.c here
Download Chase4.c here


Table Of Contents
Previous: Reading a Schematic & Basic Electronics
Next: Datalines, bits, nibbles, bytes, words, binary and HEX

Copyright © 2000 - 2015, Joe D. Reeder. All Rights Reserved.