4  Introduction to Programming and Program Development

Author
Affiliation

Ben Clifford

Welsh Centre for Printing and Coatings

Published

October 15, 2024

lecture cover image showing architecture, some gates and an Arduino nano board

Introduction

When developing an application to run on a microcontroller or other embedded system, there are five key steps which should be followed:

  1. Clearly define the requirements of the system, planning the number of inputs and outputs required, speed, storage etc. to identify suitable hardware candidates.
  2. Plan/design the software using flowcharts and pseudocode to describe the program and identify functions, or blocks of code, and how they link to other blocks.
  3. Translate the flowchart into the required programming language.
  4. Once the program is at a level where its functionality can start to be tested, testing and debugging is performed to look for errors or unexpected behaviour in software called bugs.
  5. When the final software is commissioned, it is important to document the code so as a developer can come back to it at later date or pass the task to another team member.

Lecture Topics

4.1 Useful Terminology


4.1.1 Hello, World!

Listing 4.1 is a reproduction of “Hello, world!” written in C.

Listing 4.1: Hello World Program written in C (Code reproduced from: en.wikipedia.org/wiki/File:C_Hello_World_Program.png). Run this programme by following this link hello_world.c.
/* 
 * This line basically imports the "stdio" header file, part of
 * the standard library. It provides input and output functionallity 
 * to the program.
 */
 # include <stdio.h>

 /* 
    * Function (method) declaration. This outputs "Hello, world\n" to
    * standard output when invoked.
    */
void sayHello(void) {
    // printf() in C outputs the specified text (with optional
    // formatting options) when invoked.
    printf("Hello, world\n");
}

/* 
 * This is a "main function"/ The compiled program will run the code
 * defined here.
 */
int main(void) {
    // invoke the sayHello() function.
    sayHello();
    return 0; 
 }

The first version of Hello, World! was published in the classic book The C Programming Language (Kerningham and Ritchie 1978).

Since then, it has become common to introduce each new programming language with a version of this program.

Unfortunately, there is a lot of hidden complexity in this simple program, and it is not easy to run “Hello, World!” on a microcontroller!


4.1.2 What is a program?

A program or algorithm is a recorded sequence of instructions that performs a task or set of tasks when executed to produce a specific result.


4.1.3 What is software?

Software is the term used to describe collections of programs, libraries, and related data.


4.1.4 What is a programming language?

A programming language is a formal notation comprising a set of instructions and rules for writing programs.


4.1.5 Development of programming

The next few slides provide some historical context to the development of computer programming. For example Figure 4.1 is a photograph, taken in 1957, of an early mainframe computer based at NASA Langley Research Centre. This may have well been used in the research that led to the moon landing in 1969.

In the early days of programming, programs were typed on teletypes and encoded as ASCII characters onto paper tape (Figure 4.2). These paper tapes where used to load programs and data into mainframes like that shown in Figure 4.1`. Later, programs were stored on magnetic tape, then magnetic disks and these days are stored servers to be downloaded over networks and loaded into powerful PCs or mobile devices using flash memory and SSD drives.

Figure 4.3 shows an image of a modern laptop and the programming tools and languages (in this case Python) that are used to develop programs these days.


Man and woman shown working with IBM type 704 electronic data processing machine used for making computations for aeronautical research at Langley Research Center.
Figure 4.1: IBM type 704 electronic data processing machine used for making computations for aeronautical research at NASA Langley Research Center – 21st March 1957. (Image source: www.flickr.com/photos/nasacommons/9467782802)

A picture of some punched paper tape
Figure 4.2: Early program source code! Input into a computer with punched paper tape. Image Source: How it was: Paper tapes and punched cards | EETimes

A computer screen with a bunch of code on it.
Figure 4.3: Writing programs on a modern high resolution display screen. (Image source: unsplash.com/photos/ieic5Tq8YMk by Chris Reid)

4.2 Programming Languages

{fig-alt=“Decorative section background - showing code.”


4.2.1 Programming Language Level vs Complexity

Figure 4.4 shows how code complexity that must be handled by the programmer is related to language level.

A pyramid comparing code complexity with language level.
Figure 4.4: Programming language level versus complexity

There is more code complexity at the top because the languages there are “low level” - you need to tell the computer what to do at a very granular level. Languages at the bottom of the pyramid are “high-level” because they provide a simpler way for the programmer to define complex operations without needing to be explicit about how the processor will perform the tasks. Tools are needed to convert that code into the low-level instructions that the computer needs to execute. High-level codes are converted into machine code by compilers, interpreters and web browsers.


4.2.2 Programming levels

Word cloud of common programming languages.
Figure 4.5: Word cloud of common programming languages

4.2.2.1 High-level languages

  • High level languages are written in a form that is close to human language, enabling the programmer to just focus on the problem being solved without any knowledge of the hardware it is running on.
  • Examples include: C++, Java, Pascal, Python, Visual Basic.

4.2.2.2 Low-level languages

  • Low level languages are used to write programs that relate to the specific architecture and hardware of a particular type of computer and are much closer to the native language of a computer (binary).
  • Examples include: Assembly Language, Machine Code

4.2.2.3 The C Programming language

C is a general-purpose computer programming language. It was created in the 1970s by Dennis Ritchie, and remains very widely used and influential. Wikipedia - C (programming language)

  • C might be described as a “mid-level language”. It is a compiled language and it has features that allow code to be written at a fair distance from the machine instructions. At the same time it provides structures that allow the detailed manipulation of data, memory and I/O at a level that is quite close to the machine.
  • In this course, we will be using a dialect of C that has been specifically designed for the programming of Arduino devices such as the 8-bit Atmel ATmega328 which is used in the Arduino Nano.
  • C is a very influential language. It is still used widely for writing operating system kernels, command-line tools, hardware drivers, and microcontroller applications. The syntax of C is the basis of many of the compiled and interpreted high-level languages that are in use today.

4.3 Flowcharts

A flowchart https://upload.wikimedia.org/wikipedia/commons/a/a6/

A flowchart – This Image by Unknown Author is licensed under CC BY-SA


4.3.1 What is a Flowchart?

A flowchart is a pictorial representation of the logic flow through a program.

Flowcharts are a useful tool for planning, visualizing and documenting a program without having to write any code.


Basic flowcharts are convenient because they

  • Don’t require the viewer to have an in-depth knowledge of programming
  • Don’t require the viewer to have knowledge of a specific programming language
  • Useful for visualizing how blocks of code interact with one another
  • Can be a useful tool in identifying flaws and bottlenecks in large and complex algorithms

4.3.2 Flowcharts vs Code

Consider the simple flowchart shown in Figure 4.6 representing the printing of the text string “Hello, World!”1.

A flowchart representing the hellow world program.
Figure 4.6: A flowchart representing the “Hello, World!” program.

Bash (a command-line shell used in Unix and MacOS)

echo "Hello, World!"

BASIC

PRINT "Hello, World!"

MATLAB

disp('Hello, World!')

Python

print("Hello, World!")

C (for Arduino)

puts("Hello, World!");

C++

std::cout << "Hello, World!" << std:endl;

HTML

<p>Hello, World!</p>

JavaScript

document.write('Hello, World!');

4.3.3 Flowchart building blocks

Terminal: start/end block

Flowchart start/end block

Suprocess block

Flowchart suprocess block

Terminal: program flow

Flowchart program flow

4.3.3.1 Decision block

Flowchart decision block

Process block

Flowchart process block

I/O block

Flowchart I/O block


4.3.4 Rules for drawing flowcharts

  • Flowcharts are usually drawn top to bottom but can be also be drawn left to right.
  • Flowcharts must begin with a “start” symbol and finish with an “end” symbol.
  • The spacing between all items should be consistent
  • The direction of flow between each block should be indicated with an arrow.
  • Connecting lines should never overlap.

In short flow charts should look visually tidy and the program flow should be obvious to the viewer.


4.3.5 Flowchart Drawing Packages

4.3.5.1 Microsoft Visio (Windows and web only)

A screenshot of the Microsoft visio program being used to draw a flowchart.
Figure 4.7: A screenshot of the Microsoft Visio program being used to draw a flowchart.

4.3.5.2 Microsoft 365

Screenshot of the flowchart symbols available in Microsoft 365 - Word, PowerPoint, Excel, etc.
Figure 4.8: Screenshot of the flowchart symbols available in Microsoft 365 - Word, PowerPoint, Excel, etc

Get Microsoft 365) from myuni.swan.ac.uk.


4.3.6 Other flowchart drawing tools

4.3.6.1 SmartDraw

For MacOS

Screenshot from the smartdraw flowchart editor
Figure 4.9: Screenshot from the smartdraw flowchart editor www.smartdraw.com

4.3.6.2 Creately

Web-based drawing tool

Figure 4.10: Screenshot from the creately flowchart editor creately.com/diagram-type/flowchart/

4.3.7 Using flowcharts to capturing the most common program constructs

From a software designer’s point of view, any program function can be described using only three program constructs:

  • Sequence: this construct performs one task after another in a sequence. It is a group of instructions to be performed one after another in the order shown in the program.
  • Decision: this construct performs a task or a sequence of tasks based on the result of a test condition.
  • Repetition: this construct is for a process that repeats until a condition which will stop the process is satisfied2. Repetition is used to repeat a a sequence over and over again.

4.3.7.1 Sequence

A sequence (Figure 4.11) is represented as a set of process blocks (tasks) connected by program flows. The tasks are executed in the order shown by the arrows from top to bottom.

Flowchart for a sequence of instructions computed in the order shown, one after the other.
Figure 4.11: Flowchart for a sequence of tasks

The program shown in Figure 4.11 might be represented in psuedocode3 as

START;
 Task 1;
 Task 2;
 Task 3;
END;

4.3.7.2 Decision

A decision (Figure 4.12) is represented as a decision block followed by flows which depend on the outcome of the decision.

Flowchart for a decision.
Figure 4.12: Flowchart for a decision

The program shown in Figure 4.12 might be represented in psuedocode as

START;
 IF condition one is true
     DO
             Task 1;
             :
     END_DO
 IF condition two is true
     DO
             Task 2;
             :
     END_DO
END;

4.3.7.3 Repetition

Repetition (Figure 4.13) is represented as a decision block, then a sequence of tasks and a flow that returns to the original decision. The tasks are repeated until the condition for ending the repeated sequence is met.

Flowchart for a sequence of instructions with repetition.
Figure 4.13: Flowchart for a sequence of tasks

The program shown in Figure 4.13 might be represented in psuedocode as

START;
 UNTIL condition is true
     Task 1;
     :
     Task n;
 THEN
     Task 2;
     :
END;

4.4 Example Programs


4.4.1 Example 1: A sequence

Task: Find the sum of the numbers 1 to 10

Program design method 1:

  • Brute force method using the Sequence construct,
  • Add number 1 to sum, then add, number 2, then add number 3 …
  • Continue the process until all numbers are added!

4.4.1.1 Solution to task as a sequence

Figure 4.14 shows the flow chart of this program.

Flowchart of a program to sum the first 10 numbers written as a sequence.
Figure 4.14: Flowchart of a program to sum the first 10 numbers written as a sequence.

4.4.1.2 Program shown in Figure 4.14 written in pseudo code

START
    sum = 0
    sum = sum + 1
    sum = sum + 2
    sum = sum + 3
    sum = sum + 4
    sum = sum + 5
    sum = sum + 6
    sum = sum + 7
    sum = sum + 8
    sum = sum + 9
    sum = sum + 10
END

4.4.2 Example 2: Decision and a Loop

Task: Find the sum of numbers 1 to 10

Program design method 2:

  • Use the decision and repetition constructs:

4.4.2.1 Solution to task 1 using a decision and repetition

Figure 4.15 shows the solution of task 1 using a decision and repetition.

Flowchart of the solution to task 1 using a decision and repetition.
Figure 4.15: Flowchart of the solution to task 1 using a decision and repetition.

4.4.2.2 Program shown in Figure 4.15 written in pseudo code

START
    sum = 0
    counter = 1
    WHILE counter < 11
    DO 
        sum = sum + counter
        counter = counter + 1
    END_DO
END

4.4.3 Another Example Program

Consider a program that asks a user for a ‘limit’ value and sums the numbers up to that limit before outputting the sum?

I.e. \(\mathrm{sum} = 1 + 2 + 3 + \dots n\)

The program that solves this project is illustrated by the flowchart shown in Figure 4.16. This program has a sequence, a decision and repetition. It also has an input where the limit (\(n\)) is entered and an output where the sum is displayed.


A program that asks for a limit value and sums numbers up to that limit before outputting the sum.
Figure 4.16: A program that asks for a limit value and sums numbers up to that limit before outputting the sum.

Let us tabulate the results of this program assuming that \(n=4\).

We will complete the table in class:

sum counter counter > limit
\(0\) \(1\) No
\(2\)
\(3\)
\(4\)
\(5\)

4.4.4 How many ways can we write the same program?

For our program summing the numbers up to a limit, there are three key parts.

  • Sum (S): sum = sum + counter
  • Increment (I): counter = counter + 1
  • Check (C): Has condition been met?

These can be theoretically be combined in 8 different ways, the first six of which as shown in Table 4.1.

Three implementations three are illustrated in Figure 4.17 (variation 6), Figure 4.18 (variation 4), Figure 4.19 (variation 2).


Table 4.1: How many ways can a program be written?
Variation Part 1 Part 2 Part 3
1 C S I
2 C I S
3 I C S
4 I S C
5 S C I
6 S I C

Variation 6 - Sum - Increment - Check
Figure 4.17: Variation 6: Sum - Increment - Check

Variation 4 - Increment - Sum - Check
Figure 4.18: Variation 4: Increment - Sum - Check

Variation 2 - Check - Increment - Sum
Figure 4.19: Variation 2: Check - Increment - Sum

4.4.5 Any more?

What if we counted backawards from \(n\)?

\[\mathrm{sum} = 1 + 2 + 3 + \cdots + \left(n - 1\right) + n\]

\[\equiv\]

\[\mathrm{sum} = n + \left(n-1\right) + \cdots 3 + 2 + 1\]


Let us tabulate the results of this program assuming that \(n=4\).

sum counter counter > limit
\(0\) \(4\)
\(3\)
\(2\)
\(1\)
\(0\)

A flow chart that implements this variation is given in Figure 4.20.


Figure 4.20: Another variation: Check - Decrement - Sum

4.4.6 Self-directed learning

  1. See if you can write the other eight flowcharts for a program that sums the numbers 1 to n.
  2. To get you thinking from a programmer’s point of view, consider the steps required to perform a task we usually take for granted, such as making a cup of tea, and what a flowchart for this might look like.
  3. After you’ve had a go at these, drop a message on the discussion forum for this week to let us know how you got on and which drawing package you found the best. Feel free to include any tips you find useful.

4.5 Modular Programming

This Image by Unknown Author is licensed under CC BY-SA


4.5.1 What is a module?

The basic approach to modularization is to consider a top-down design where the top level defines the main function, and a separate module represents each smaller function in the program (see Figure 4.21).

Figure 4.21: A program built from modules

Each module is treated as a black box4 which operates on its input and produces an output.

As long as the input and output requirements remain the same, the module code can be changed without affecting the rest of the program.


4.5.1.1 Example Task

Write a program to perform n different tasks with a ten second delay between each task.

The program we have been discussing that sums the numbers 1-10 can be used to simulate a delay.


Example program - Non-Modular Approach
DO 
    Task 1
END

/* Delay between task 1 and task 2 */
DO
    number = 0
    WHILE number < 11
        DO
            number = number + 1
        END_DO
    END_WHILE
END

DO 
    Task 2
END

/* Delay between task 2 and task 3 */
DO
    number = 0
    WHILE number < 11
        DO
            number = number + 1
        END_DO
    END_WHILE
END

DO 
    Task 3
END

:

Change the specification

Now suppose that we want to change the delay between tasks to 20 seconds.

Using a non-modular approach the developer/programmer now needs to change the line

WHILE number < 11

to

WHILE number < 21

For each of the n-1 times it is used.


Example program - Modular Approach

The code that implements the delay is made into a module which is called when needed

MODULE delay
    DO
        number = 0
        WHILE number < 21
            DO
                number = number + 1
            END_DO
        END_WHILE
    END
END_MODULE

The modular program becomes:

DO 
    Task 1
END

/* Delay between task 1 and task 2 */
DO
    delay
END

DO 
    Task 2
END

/* Delay between task 2 and task 3 */
DO 
    delay
END

DO 
    Task 3
END

:

By using a modular approach to program this task, the developer/programmer need only change one value to adjust the delay, independent of how many times the delay is called between tasks in the program.

We can take this idea further by parameterising the delay value itself. To code might now look like:

MODULE delay(delay)
    DO
        number = 0
        WHILE number < delay
            DO
                number = number + 1
            END_DO
        END_WHILE
    END
END_MODULE

We can now have variable length delays between tasks:

DO 
    Task 1
END

/* Ten second delay between task 1 and task 2 */
DO
    delay(10)
END

DO 
    Task 2
END

/* Twenty second delay between task 2 and task 3 */
DO 
    delay(20)
END

DO 
    Task 3
END

:

We will return to this idea when we look at functions in C.


4.5.1.2 Activity

With the time remaining can you represent this program as a flow chart?

Feel free to work individually or in small groups.


Solution

See Figure 4.22 in the notes online.

Implementing a delay sub-program.
Figure 4.22: Implementing a delay sub-program using a modular approach

Summary

In this chapter we have:

  • Defined terminology relating to programming and looked at how languages can be classified as high or low based on the level of abstraction from the architecture it is to be run on.
  • Looked at flowcharts defining the standard symbols and looking at how they are used to represent a program.
  • Looked at some example programs presented as flow charts and in pseudo code.
  • Noted that there may be more than one way to present a program to achieve the same results.
  • Introduced the use of sub-processes to allow modular programming for splitting up a program or repeating common elements.

4.5.2 On Canvas

This week on the canvas course page, there is:


Any Questions?

Please use the Course Question Board on Canvas or take advantage of the lecturers’ office hours.


4.5.3 Next time



  1. In most programming languages, text is stored in memory as a sequence of binary codes which each represent the individual characters as in 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!'. Such a sequence is usually called a string.↩︎

  2. Repetition is used a lot in microcontroller programming.↩︎

  3. Pseudocode is a formal text which is used to represent the operation of a section of code in a way that can be understood without needing to resort to formal rules of a programming language.↩︎

  4. In science, computing, and engineering, a black box is a system which can be viewed in terms of its inputs and outputs (or transfer characteristics), without any knowledge of its internal workings. Its implementation is “opaque” (black). The term can be used to refer to many inner workings, such as those of a transistor, an engine, an algorithm, the human brain, or an institution or government.—Blackbox (Wikipedia)↩︎

Copyright © 2021-2024 Swansea University. All rights reserved.