SunFounder Electronic Kit for Raspberry Pi and Arduino

About the Electronic Kit

This kit is suitable for SunFounder Uno, SunFounder Mega 2560, SunFounder Duemilanove and SunFounder Nano. All the code in this user guide is compatible with these boards. With this kit, we will walk you through the know-how of using the Arduino board in a hands-on way. Starting with the basics of electronics, you’ll learn through building several creative projects. Including a selection of the most common and useful electronic components, this kit will help you “control” the physical world.

If you want to learn another projects which we don’t have, please feel free to send Email and we will update to our online tutorials as soon as possible, any suggestions are welcomed.

Here is the Email: cs@sunfounder.com.

About the display language

In addition to English, we are working on other languages for this course. Please contact service@sunfounder.com if you are interested in helping, and we will give you a free product in return. In the meantime, we recommend using Google Translate to convert English to the language you want to see.

The steps are as follows.

  • In this course page, right-click and select Translate to xx. If the current language is not what you want, you can change it later.

_images/translate1.png
  • There will be a language popup in the upper right corner. Click on the menu button to choose another language.

_images/translate2.png
  • Select the language from the inverted triangle box, and then click Done.

_images/translate3.png

Component List

Note

After unpacking, please check that the number of components is correct and that all components are in good condition.

_images/image5.jpeg _images/image6.jpeg _images/image7.jpeg _images/image8.jpeg _images/image9.jpeg _images/image10.jpeg _images/image11.jpeg _images/image170.png

For Raspberry Pi User

Preparation

In this chapter, we firstly learn to start up Raspberry Pi. The content includes installing the OS, Raspberry Pi network and how to open terminal.

Note

You can check the complete tutorial on the official website of the Raspberry Pi: raspberry-pi-setting-up.

If your Raspberry Pi is set up, you can skip the part and go into the next chapter.

Installing the OS

Required Components

Any Raspberry Pi

1 * Personal Computer

1 * Micro SD card

Step 1

Raspberry Pi have developed a graphical SD card writing tool that works on Mac OS, Ubuntu 18.04 and Windows, and is the easiest option for most users as it will download the image and install it automatically to the SD card.

Visit the download page: https://www.raspberrypi.org/software/. Click on the link for the Raspberry Pi Imager that matches your operating system, when the download finishes, click it to launch the installer.

_images/image11.png

Step 2

When you launch the installer, your operating system may try to block you from running it. For example, on Windows I receive the following message:

If this pops up, click on More info and then Run anyway, then follow the instructions to install the Raspberry Pi Imager.

_images/image12.png

Step 3

Insert your SD card into the computer or laptop SD card slot.

Step 4

In the Raspberry Pi Imager, select the OS that you want to install and the SD card you would like to install it on.

_images/image131.png

Note

  1. You will need to be connected to the internet the first time.

  2. That OS will then be stored for future offline use(lastdownload.cache, C:/Users/yourname/AppData/Local/Raspberry Pi/Imager/cache). So the next time you open the software, it will have the display “Released: date, cached on your computer”.

Step 5

Select the SD card you are using.

_images/image148.png

Step 6

Press Ctrl+Shift+X to open the Advanced options page to enable SSH and configure wifi, these 2 items must be set, the others depend on your choice . You can choose to always use this image customization options.

_images/image151.png

Then scroll down to complete the wifi configuration and click SAVE.

Note

wifi country should be set the two-letter ISO/IEC alpha2 code for the country in which you are using your Raspberry Pi, please refer to the following link: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements.

_images/image161.png

Step 7

Click the WRITE button.

_images/image1710.png

Step 8

If your SD card currently has any files on it, you may wish to back up these files first to prevent you from permanently losing them. If there is no file to be backed up, click Yes.

_images/image1810.png

Step 9

After waiting for a period of time, the following window will appear to represent the completion of writing.

_images/image1910.png
Set up Your Raspberry Pi
If You Have a Screen

If you have a screen, it will be easy for you to operate on the Raspberry Pi.

Required Components

Any Raspberry Pi

1 * Power Adapter

1 * Micro SD card

1 * Screen Power Adapter

1 * HDMI cable

1 * Screen

1 * Mouse

1 * Keyboard

  1. Insert the SD card you’ve set up with Raspberry Pi OS into the micro SD card slot on the underside of your Raspberry Pi.

  2. Plug in the Mouse and Keyboard.

  3. Connect the screen to Raspberry Pi’s HDMI port and make sure your screen is plugged into a wall socket and switched on.

Note

If you use a Raspberry Pi 4, you need to connect the screen to the HDMI0 (nearest the power in port).

  1. Use the power adapter to power the Raspberry Pi. After a few seconds, the Raspberry Pi OS desktop will be displayed.

    _images/image2010.png
If You Have No Screen

If you don’t have a display, you can log in to the Raspberry Pi remotely, but before that, you need to get the IP of the Raspberry Pi.

Get the IP Address

After the Raspberry Pi is connected to WIFI, we need to get the IP address of it. There are many ways to know the IP address, and two of them are listed as follows.

1.  Checking via the router

If you have permission to log in the router(such as a home network), you can check the addresses assigned to Raspberry Pi on the admin interface of router.

The default hostname of the Raspberry Pi OS is raspberrypi, and you need to find it. (If you are using ArchLinuxARM system, please find alarmpi.)

2. Network Segment Scanning

You can also use network scanning to look up the IP address of Raspberry Pi. You can apply the software, Advanced IP scanner and so on.

Scan the IP range set, and the name of all connected devices will be displayed. Similarly, the default hostname of the Raspberry Pi OS is raspberrypi, if you haven’t modified it.

Use the SSH Remote Control

We can open the Bash Shell of Raspberry Pi by applying SSH. Bash is the standard default shell of Linux. The Shell itself is a program written in C that is the bridge linking the customers and Unix/Linux. Moreover, it can help to complete most of the work needed.

For Linux or/Mac OS X Users

Step 1

Go to Applications->Utilities, find the Terminal, and open it.

_images/image2110.png

Step 2

Type in ssh pi@ip_address . “pi” is your username and “ip_address” is your IP address. For example:

ssh pi@192.168.18.197

Step 3

Input “yes”.

_images/image2210.png

Step 4

Input the passcode and the default password is raspberry.

_images/image234.png

Step 5

We now get the Raspberry Pi connected and are ready to go to the next step.

_images/image24.png

Note

When you input the password, the characters do not display on window accordingly, which is normal. What you need is to input the correct password.

For Windows Users

If you’re a Windows user, you can use SSH with the application of some software. Here, we recommend PuTTY.

Step 1

Download PuTTY.

Step 2

Open PuTTY and click Session on the left tree-alike structure. Enter the IP address of the RPi in the text box under Host Name (or IP address) and 22 under Port (by default it is 22).

_images/image25.png

Step 3

Click Open. Note that when you first log in to the Raspberry Pi with the IP address, there prompts a security reminder. Just click Yes.

Step 4

When the PuTTY window prompts “login as:”, type in “pi” (the user name of the RPi), and password: “raspberry” (the default one, if you haven’t changed it).

_images/image26.png

Step 5

Here, we get the Raspberry Pi connected and it is time to conduct the next steps.

Note

When you input the password, the characters do not display on window accordingly, which is normal. What you need is to input the correct password.

If you are not satisfied with using the command window to control the Raspberry Pi, you can also use the remote desktop function, which can help us manage the files in the Raspberry Pi easily.

For details on how to do this, please refer to Remote Desktop.

Libraries

Two important libraries are used in programming with Raspberry Pi, and they are wiringPi and RPi.GPIO. The Raspbian OS image of Raspberry Pi installs them by default, so you can use them directly.

RPi.GPIO

If you are a Python user, you can program GPIOs with API provided by RPi.GPIO.

RPi.GPIO is a module to control Raspberry Pi GPIO channels. This package provides a class to control the GPIO on a Raspberry Pi. For examples and documents, visit http://sourceforge.net/p/raspberry-gpio-python/wiki/Home/.

Test whether RPi.GPIO is installed or not, type in python:

python
_images/image49.png

In Python CLI, input “import RPi.GPIO”, if no error prompts, it means RPi.GPIO is installed.

import RPi.GPIO
_images/image501.png

If you want to quit python CLI, type in:

exit()

Install and Check the WiringPi

wiringPi is a C language GPIO library applied to the Raspberry Pi. It complies with GUN Lv3. The functions in wiringPi are similar to those in the wiring system of Arduino. They enable the users familiar with Arduino to use wiringPi more easily.

wiringPi includes lots of GPIO commands which enable you to control all kinds of interfaces on Raspberry Pi.

Please run the following command to install wiringPi library.

sudo apt-get update
git clone https://github.com/WiringPi/WiringPi
cd WiringPi
./build

You can test whether the wiringPi library is installed successfully or not by the following instruction.

gpio -v
_images/image51.png

Check the GPIO with the following command:

gpio readall
_images/image521.png

For more details about wiringPi, you can refer to WiringPi.

Download the Code

Before you download the code, please note that the example code is ONLY test on Raspbian. We provide two methods for download:

Method 1: Use Git Clone (Recommended)

Log into Raspberry Pi and then change directory to /home/pi.

cd /home/pi/

Note

cd to change to the intended directory from the current path. Informally, here is to go to the path /home/pi/.

Clone the repository from GitHub.

git clone https://github.com/sunfounder/electronic-kit.git

Method 2: Download the Code.

Download the source code from GitHub: https://github.com/sunfounder/electronic-kit.git.

Lessons

Lesson 1 Blinking LED
Introduction

In this lesson, with Raspberry Pi, we will learn how to make a blinking LED by programming. By the way, you can get many interesting phenomena by applying LED. Now get to start and you will enjoy the fun of DIY at once!

Newly Added Components
_images/image1941.png
Components

Note

This table gives the necessary product components of all lessons.

In the following lessons, if there is no newly added component, the table will not appear again; instead, the list of newly added components will present for you.

_images/image1951.png
Principle

Breadboard

A breadboard is a construction base for prototyping of electronics. It is used to build and test circuits quickly before finishing any circuit design. And it has many holes into which components mentioned above can be inserted like ICs and resistors as well as jumper wires. The breadboard allows you to plug in and remove components easily.

The picture shows the internal structure of a half+ breadboard. Although these holes on the breadboard appear to be independent of each other, they are actually connected to each other through metal strips internally.

_images/image60.png

Resistor

Resistor is an electronic element that can limit the branch current. A fixed resistor is a kind of resistor whose resistance cannot be changed, while that of a potentiometer or a variable resistor can be adjusted.

Fixed resistor is applied in this kit. In the circuit, it is essential to protect the connected components. The following pictures show a real object, 220Ω resistor and two generally used circuit symbols of resistor. Ω is the unit of resistance and the larger units include KΩ, MΩ, etc. Their relationship can be shown as follows: 1 MΩ=1000 KΩ, 1 KΩ = 1000 Ω, which means 1 MΩ = 1000,000 Ω = 10^6 Ω.

_images/image1961.png

Normally, the resistance can be marked directly, in color code, and by character. The resistors offered in this kit are marked by different colors. Namely, the bands on the resistor indicate the resistance.

When using a resistor, we need to know its resistance first. Here are two methods: you can observe the bands on the resistor, or use a multimeter to measure the resistance. You are recommended to use the first method as it is more convenient and faster.

As shown in the card, each color stands for a number.

_images/image65.jpeg

LED

Semiconductor light-emitting diode is a type of component which can turn electric energy into light energy via PN junctions. In terms of wavelength, it can be categorized into laser diode, infrared light-emitting diode and visible light-emitting diode, known as light-emitting diode (LED).

_images/image1971.png

Diode has unidirectional conductivity, so the current flow will be as the arrow indicates in figure circuit symbol. You can only provide the anode with a positive power and the cathode with a negative one. Thus the LED will light up.

An LED has two pins. The longer one is anode, and the shorter one, cathode. Pay attention not to connect them inversely. There is fixed forward voltage drop in the LED, so it cannot be connected with the circuit directly because the supply voltage can outweigh this drop and cause the LED to be burnt. The forward voltage of the red, yellow, and green LED is 1.8 V and that of the white one is 2.6 V. Most LEDs can withstand a maximum current of 20 mA, so we need to connect a current limiting resistor in series.

The formula of the resistance value is as follows:

R = (Vsupply – VD)/I

R stands for the resistance value of the current limiting resistor, Vsupply for voltage supply, VD for voltage drop and I for the working current of the LED.

If we provide 5 Volt for the red LED, the minimum resistance of the current limiting resistor should be: (5V-1.8V)/20mA = 160Ω. Therefore, you need a 160Ωor larger resistor to protect the LED. You are recommended to use the 220Ω resistor offered in the kit.

Jumper Wires

Wires that connect two terminals are called jumper wires. There are various kinds of jumper wires. Here we focus on those used in breadboard. Especially, they are used to transfer electrical signals from anywhere on the breadboard to the input/output pins of a microcontroller.

Jump wires are fitted by inserting their “end connectors” into the slots provided in the breadboard, beneath whose surface there are a few sets of parallel plates that connect the slots in groups of rows or columns depending on the area. The “end connectors” are inserted into the breadboard, without soldering, in the particular slots that need to be connected in the specific prototype.

There are three types of jumper wire: Female-to-Female, Male-to-Male, and Male-to-Female.

_images/image1981.png

More than one type of them may be used in a project. The color of the jump wires is different but it doesn’t mean their function is different accordingly; it’s just designed as this way to better identify the connection between each circuit.

Schematic Diagram

In this experiment, connect a 220Ω resistor to the anode (the long pin of the LED), then the resistor to Pin11 of Raspberry Pi, and connect the cathode (the short pin) of the LED to GND. Therefore, to turn on a LED, we need to make pin11 high level. We can get this phenomenon by programming.

Note: Pin11 refers to the 11th pin of the Raspberry Pi from left to right, and its corresponding wiringPi and BCM pin numbers are shown in the following table.

In the C language related content, we make GPIO 0 equivalent to 0 in the wiringPi. Among the Python language related content, BCM 17 is 17 in the BCM column of the following table. At the same time, they are the same as the 11th pin on the Raspberry Pi Physical, Pin 11.

_images/image1991.png
Build the Circuit

Note

the pin with a curve is the anode of the LED.

_images/image72.png
For C Language Users:
Command

1. Go to the folder of the code.

If you use a monitor, you’re recommended to take the following steps.

Go to /home/pi/ and find the folder electronic-kit/for-raspberry-pi.

Find c in the folder, right-click on it and select Open in Terminal.

_images/image73.png

Then a window will pop up as shown below. So now you’ve entered the path of the code 1_BlinkingLed.c

_images/image74.png

In the following lessons, we will use command to enter the code file instead of right-clicking. But you can choose the method you prefer.

If you log into the Raspberry Pi remotely, use “cd” to change directory:

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_1_BlinkingLed

Note

Change directory to the path of the code via cd in this experiment.

_images/image75.png

In either way, now you are in the folder Lesson_1_BlinkingLed. The subsequent procedures based on these two methods are the same. Let’s move on.

2. Compile the code.

gcc 1_BlinkingLed.c -o BlinkingLed -lwiringPi

Note

gcc is GNU Compiler Collection. Here, its functions like compiling the C language file 1_BlinkingLed.c and outputting an executable file. In the command, -o means outputting (the character immediatelyfollowing -o is the filename output after compilation, and an executable named BlinkingLed will generate here) and -lwiringPi is to load the library wiringPi (l is the abbreviation of library).

_images/image76.png

3. Run the executable file output in the previous step:

sudo ./BlinkingLed

Note

To control the GPIO, you need to run the program by the command, sudo(superuser do). The command “./” indicates the current directory. The whole command is to run the BlinkingLed in the current directory.

_images/image77.png

As the code runs, you will see the LED blinking. You can press Ctrl + C to stop running the current code.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

4. If you want to edit the code file 1_BlinkingLed.c, type the following command to open 1_BlinkingLed.c .

nano 1_BlinkingLed.c

Note

nano is a text editor tool. The command is used to open the code file 1_BlinkingLed.c by this tool.

Code

The program code is shown as follows:

#include <wiringPi.h>
#include <stdio.h>
#define LedPin      0

int main(void)
{
    // When initialize wiring failed, print message to screen
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(LedPin, OUTPUT);

    while(1){
        // LED off
        digitalWrite(LedPin, LOW);
        printf("...LED off\n");
        delay(500);
        // LED on
        digitalWrite(LedPin, HIGH);
        printf("LED on...\n");
        delay(500);
    }

    return 0;
}
Code Explanation
#include <wiringPi.h>

The hardware drive library is designed for the C language of Raspberry Pi. Adding this library is conducive to the initialization of hardware,and the output of I/O ports, PWM, etc.

#include <stdio.h>

Standard I/O library. The printf function used for printing the data displayed on the screen is realized by this library. There are many other performance functions for you to explore.

#define LedPin      0

Assign GPIO 0 to LedPin that represents GPIO 0 in the code later.

8.      if (wiringPiSetup() == -1){

9.          printf("setup wiringPi failed !");

10.         return 1;

This initializes wiringPi library and assumes that the calling program is going to be using the wiringPi pin numbering scheme. This function needs to be called with root privileges. When initialize wiring failed, print message to screen.

13.     pinMode(LedPin, OUTPUT);

This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK. Note that only wiringPi pin 1 (BCM_GPIO 18) supports hardware PWM output, you can also set other pins to PWM output using the softPWM library. Only wiringPi pin 7 (BCM_GPIO 4) supports CLOCK output modes. Here we set LedPin as OUTPUT mode to write value to it.

17.         digitalWrite(LedPin, LOW);

Writes the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as OUTPUT. On Raspberry Pi, when the output voltage is less than 0.4V, by default, it is low level, LOW, and when the voltage is greater than 2.4V, it is high level, HIGH. Since the anode of LED is connected to GPIO 0, thus the LED will light up if GPIO 0 is set high. On the contrary, set GPIO 0 as low level, digitalWrite (LedPin, LOW), LED will go out.

18.         printf("...LED off\n");

The printf function is a standard library function and its function prototype is in the header file “stdio.h”. The general form of the call is: printf(“format control string”, output table columns). The format control string is used to specify the output format, which is divided into format string and non-format string. The format string starts with “%” followed by format characters such as “%d”for decimal integer output. Non-format strings are printed as prototypes. What is used here is a non-format string, followed by “n” that is a newline character, representing automatic line wrapping after printing a string.

19.         delay(500);

This is a function that suspends the program for a period of time. And the speed of the program is determined by our hardware. Here we turn on or off the LED. If there is no delay function, the program will run the whole program very fast and continuously loop and we can hardly observe the phenomenon. So we need the delay function to help us write and debug the program. delay (500) keeps the current HIGH or LOW state for 500ms(0.5s).

26.    return 0;

Usually, it is placed in the last position of the main function, indicating that the function returns 0 after executing the function.

For Python Language Users

If you use a monitor, you’re recommended to take the following steps.

Find 1_BlinkingLed.py and double click it to open the file.

_images/image79.png

Click Run ->Run Module in the window and the following contents will appear.

_images/image80.png

To stop it from running, just click the X button on the top right corner to close it and then you’ll back to the code. If you modify the code, before clicking Run Module (F5) you need to save it first. Then you can see the results.

If you log into the Raspberry Pi remotely, type in the command:

cd /home/pi/electronic-kit/for-raspberry-pi/python

Note

Change directory to the path of the code via cd in this experiment.

_images/image81.png

2. Run the code.

sudo python3 1_BlinkingLed.py

Note

Here, sudo means superuser do, and the command python3 means to run the file by the programming language, Python 3.0.

_images/image82.png

As the code runs, you will see the LED blinking. You can press Ctrl+C to stop running the current code.

3. If you want to edit the code file 1_BlinkingLed.c, type the following command to open 1_BlinkingLed.c

nano 1_BlinkingLed.py

Note

nano is a text editor tool. The command is used to open thecode file 1_BlinkingLed.c by this tool.

_images/image83.png
Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

The following is the program code:

import RPi.GPIO as GPIO
import time

# Set BCM 17 as LED pin
LedPin = 17

# Define a setup function for some setup
def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.LOW)

# Define a main function for main process
def main():
    while True:
        print ('...LED ON')
        # Turn on LED
        GPIO.output(LedPin, GPIO.HIGH)
        time.sleep(0.5)
        print ('LED OFF...')
        # Turn off LED
        GPIO.output(LedPin, GPIO.LOW)
        time.sleep(0.5)

# Define a destroy function for clean up everything after the script finished
def destroy():
    # Turn off LED
    GPIO.output(LedPin, GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()

Code Explanation

1.import RPi.GPIO as GPIO

In this way, import the RPi.GPIO library, then define a variable, GPIO to replace RPI.GPIO in the following code.

2.import time

Import time library to help use delay function in the following program.

5.LedPin = 17

LED connects to the pin 11 of the board, namely, the BCM 17 of the Raspberry Pi.

9.    GPIO.setmode(GPIO.BCM)

There are two ways of numbering the I/O pins on a Raspberry Pi within RPi.GPIO: BOARD numbers and BCM numbers. In our lessons, what we use is BCM numbering method.

10.    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.LOW)

You need to set up every channel you use as input mode or output mode. Here we set the mode of LedPin to GPIO.OUT, and initial level to LOW( 0v ).

17.        GPIO.output(LedPin, GPIO.HIGH)

Set LedPin to output high level to light up LED.

18.        time.sleep(0.5)

Delay for 0.5 second. Here, the statement is similar to delay function in C language, the unit is second.

32.if __name__ == '__main__':
33.    setup()
34.    try:
35.        main()
36.    # When 'Ctrl+C' is pressed, the program
37.    # destroy() will be  executed.
38.    except KeyboardInterrupt:
39.        destroy()

This is the general running structure of the code. When the program starts to run, it initializes the pin by running the setup(), and then runs the code in the main() function to set the pin to high and low levels. When ‘Ctrl+C’ is pressed, the program, destroy() will be executed.

Phenomenon Picture
_images/image84.jpeg
Lesson 2 Flowing LED Lights
Introduction

In this lesson, we will learn how to make eight LEDs blink as flowing water based on Raspberry Pi.

Newly Added Components
_images/image2001.png
Schematic Diagram

In this experiment, connect 220Ωresistors to the anode (the longer pin of the LED) respectively, then the resistors to Pin 11, 12, 13, 15, 16, 18, 22 and 24 of Raspberry Pi, and connect the cathode (the short pin) of the LEDs to GND. We can see from the schematic diagram that the anode of LED connect to a current-limiting resistor and then to Raspberry Pi. Therefore, to turn on an LED, we need to make pins high level. This process can be realized by programming.

_images/image2011.png
Build the Circuit
_images/image2021.png
For C Language Users:
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_2_FlowingLedLights

2. Compile the code.

gcc 2_FlowingLedLights.c -lwiringPi

Note

When using the gcc command, if you do not use -o, it will automatically output as a.out.

3. Run the executable file.

sudo ./a.out

Now, you will see these 8 LEDs are lit one by one from left to right, and then one by one from right to left.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

const int LedPin[]={0,1,2,3,4,5,6,10};   //Define 8 LED pin

int main(void)
{
    // When initialize wiring failed, print message to screen
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }

    for(int j=0;j<8;j++)
    {
        pinMode(LedPin[j], OUTPUT);// Set LedPin as output to write value to it.
        digitalWrite(LedPin[j], LOW);
    }

    while(1){
        for(int i=0;i<8;i++)
        {
            // LED on
            digitalWrite(LedPin[i], HIGH);
            delay(100);
        }
        for(int i=7;i>-1;i--)
        {
            // LED off
            digitalWrite(LedPin[i], LOW);
            delay(100);
        }
    }

    return 0;
}
Code Explanation
4.const int LedPin[]={0,1,2,3,4,5,6,10};

Create an array, LedPin to define the eight LEDs then connect them to GPIO0 ~ GPIO6, GPIO10 respectively.

14.    for(int j=0;j<8;j++)
15.    {
16.        pinMode(LedPin[j], OUTPUT);
17.        digitalWrite(LedPin[j], LOW);
18.    }

Use a for loop to set all 8 pins connected to LEDs to OUTPUT mode and LOW level.

21.        for(int i=0;i<8;i++)
22.        {
23.            // LED on
24.            digitalWrite(LedPin[i], HIGH);
25.            delay(100);
26.        }

Light up the LEDs in GPIO0~6 and GPIO10 successively. i increases progressively from 0 to 7, LED0 to LED7 changes accordingly, making it like a flowing LED light from left to right.

27.        for(int i=7;i>-1;i--)
28.        {
29.            // LED off
30.            digitalWrite(LedPin[i], LOW);
31.            delay(100);
32.        }

Close the LEDs in GPIO0~6 and GPIO10 successively. i increases progressively from 7 to 0, LED0 to LED7 changes accordingly, making it like a flowing LED light from right to left.

For Python Language Users
Command

1. Go to the folder of the code

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 2_FlowingLed.py

Now, you will see these 8 LEDs are lit one by one from left to right, and then one by one from right to left.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

pins = [17,18,27,22,23,24,25,8]

# Define a setup function for some setup
def setup():
    GPIO.setmode(GPIO.BCM)
    for i in range(0, 8, 1):
        GPIO.setup(pins[i], GPIO.OUT, initial=GPIO.LOW)

# Define a main function for main process
def main():
    while True:
        # print ('...LED ON')
        # Turn on LED
        for i in range(0, 8, 1):
            GPIO.output(pins[i], GPIO.HIGH)
            time.sleep(0.1)

        # print ('LED OFF...')
        # Turn off LED
        for i in range(7, -1, -1):
            GPIO.output(pins[i], GPIO.LOW)
            time.sleep(0.1)

# Define a destroy function for clean up everything after the script finished
def destroy():
    # Turn off LED
    for i in range(0, 8, 1):
            GPIO.output(pins[i], GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
9.    for i in range(0, 8, 1):
10.        GPIO.setup(pins[i], GPIO.OUT, initial=GPIO.LOW)

Use a for loop to set all 8 pins connected to LEDs to output mode and LOW level.

17.        for i in range(0, 8, 1):
18.            GPIO.output(pins[i], GPIO.HIGH)
19.                         time.sleep(0.1)

Variable i increases progressively from 0 to 8, increasing by 1 every time. Accordingly, set the pins in the array pins[i] to HIGH respectively to light up the LEDs and the lighting time is 0.1s. Then, you will see 8 LEDs light up one by one.

23.        for i in range(7, -1, -1):
24.            GPIO.output(pins[i], GPIO.LOW)
25.            time.sleep(0.1)

Variable i decreases progressively from 7 to -1, decreasing by 1 every time. Then LED0~LED7 change accordingly, making it like a flowing LED light from right to left.

Phenomenon Picture
_images/image2031.png
Lesson 3 Breathing LED
Introduction

In this lesson, we will try something interesting - gradually increase or decrease the luminance of an LED with PWM, just like breathing. So we give it a magical name - Breathing LED.

Newly Added Components
_images/image2041.png
Principle

PWM

Pulse Width Modulation, or PWM, is a technique for getting analog results with digital means. Digital control is used to create a square wave, a signal switched between on and off. This on-off pattern can simulate voltages in between full on (5 Volts) and off (0 Volts) by changing the portion of the time the signal spends on versus the time that the signal spends off. The duration of “on time” is called pulse width. To get varying analog values, you can change or modulate this width. If you repeat this on-off pattern fast enough with some device, an LED for example, the result would be like this: the signal is a steady voltage between 0 and 5v controlling the brightness of the LED.

Duty Cycle

A duty cycle is the percentage of one period in which a signal is active. A period is the time it takes for a signal to complete an on-and-off cycle. As a formula, a duty cycle may be expressed as:

D=T/Px100%

Where is the duty cycle, is the time the signal is active, and is the total period of the signal. Thus, a 60% duty cycle means the signal is on 60% of the time but off 40% of the time. The “on time” for a 60% duty cycle could be a fraction of a second, a day, or even a week, depending on the length of the period.

_images/image90.jpeg
Schematic Diagram
_images/image262.png _images/image263.png
Build the Circuit
_images/image92.png
For C Language Users:
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_3_BreathingLed

2. Compile the code.

gcc 3_BreathingLed.c -lwiringPi

3. Run the executable file.

sudo ./a.out

As the code runs, you can see that the brightness of the LED becomes stronger or weaker.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <stdio.h>
#include <wiringPi.h>
#include <softPwm.h>

#define LedPin 1

int main (void)
{
// When initialize wiring failed, print message to screen
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }

    softPwmCreate(LedPin,  0, 100);

    int i;

    while(1) // loop forever
    {
        for(i=0;i<100;i++){  // i,as the value of pwm, increases progressively during 0-1024.
            softPwmWrite(LedPin, i);
            delay(10);
        }

        for(i=100;i>=0;i--){
            softPwmWrite(LedPin, i);
            delay(10);
        }
    }
    return 0 ;
}
Code Explanation
#include <softPwm.h>

WiringPi includes a software-driven PWM library of outputting a PWM signal on any of the Raspberry Pi’s GPIO pins. To maintain a low CPU usage, the minimum pulse width is 100μS. That combined with the default suggested range of 100 gives a PWM frequency of 100Hz. Within these limitations, control of a light/LED or a motor is very achievable.

15.    softPwmCreate(LedPin,  0, 100);

The function is to use software library to create a PWM pin, set its period between 0x100us-100x100us. The prototype of the function softPwmCreate(LedPinRed, 0, 100) is as follows:

int softPwmCreate(int pin,int initialValue,int pwmRange);

pin: Any GPIO pin of Raspberry Pi can be set as a PWM pin.

initialValue: The initial pulse width is that initialValue times100us.

pwmRange: The period of PWM is that pwmRange times100us.

22.            softPwmWrite(LedPin, i);

The function is used to write the PWM value i to the LedPin.

The prototype of the function softPwmWrite(LedPinBlue, b_val) is as follows:

void softPwmWrite (int pin, int value) ;

pin: Any GPIO pin of Raspberry Pi can be set as a PWM pin.

Value: The pulse width of PWM is value times 100us. Note that value can only be less than pwmRange defined previously, if it is larger than pwmRange, the value will be given a fixed value, pwmRange.

23.            delay(10);

Wait for 10ms, interval time between the changes indicates the speed of breathing.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 3_BreathingLed.py

As the code runs, you can see that the brightness of the LED becomes stronger or weaker.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

LedPin = 18

def setup():
    global pLed
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.LOW)
    pLed = GPIO.PWM(LedPin, 1000)
    pLed.start(0)

def main():
    # Set increase/decrease step
    step =2
    delay = 0.05
    while True:
        # Increase duty cycle from 0 to 100
        for dc in range(0, 101, step):
            pLed.ChangeDutyCycle(dc)
            print (' ++ Duty cycle: %s'%dc)
            time.sleep(delay)
        time.sleep(1)

        # decrease duty cycle from 100 to 0
        for dc in range(100, -1, -step):
            # Change duty cycle to dc
            pLed.ChangeDutyCycle(dc)
            print ('  -- Duty cycle: %s'%dc)
            time.sleep(delay)
        time.sleep(1)

def destroy():
    # Stop pLed
    pLed.stop()
    # Turn off LED
    GPIO.output(LedPin, GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
10.    pLed = GPIO.PWM(LedPin, 1000)

To create a PWM instance. Set pLed as pwm output and frequence to 1K Hz.

11.    pLed.start(0)

Set pLed begin with value 0.

19.        for dc in range(0, 101, step):
20.            # Change duty cycle to dc
21.            pLed.ChangeDutyCycle(dc)
22.            print (' ++ Duty cycle: %s'%dc)
23.            time.sleep(delay)

Increase the duty cycle by 2 at a time, from 0 to 101, and you’ll see the LED getting brighter and brighter.

26. for dc in range(100, -1, -step):
27.            pLed.ChangeDutyCycle(dc)
28.            print ('  -- Duty cycle: %s'%dc)
29.            time.sleep(delay)

Similarly, when the duty cycle is reduced by 2 from 100 to -1, the LED brightness will be dimmer and dimmer.

Phenomenon Picture
_images/image84.jpeg
Lesson 4 RGB LED
Introduction

Previously we’ve used the PWM technology to control an LED’s brightness. In this lesson, we will use it to control an RGB LED to flash various kinds of colors.

Newly Added Components
_images/image2061.png
Principle

RGB LED

_images/image207.png

The three primary colors of the RGB LED can be mixed into various colors by brightness. The brightness of LED can be adjusted with PWM. Raspberry Pi has only one channel for hardware PWM output, but it needs three channels to control the RGB LED, which means it is difficult to control the RGB LED with the hardware PWM of Raspberry Pi. Fortunately, the softPwm library simulates PWM (softPwm) by programming. You only need to include the header file softPwm.h (for C language users), and then call the API it provides to easily control the RGB LED by multi-channel PWM output, so as to display all kinds of color.

Schematic Diagram

After connecting the pins of R, G, and B to a current limiting resistor, connect them to the pin 11, pin 12, and pin 13 respectively. The longest pin (GND) of the LED connects to the GND of the Raspberry Pi. When the three pins are given different PWM values, the RGB LED will display different colors.

_images/image264.png
Build the Circuit
_images/image98.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_4_RGBLed

2. Compile the code.

gcc 4_rgbLed.c -lwiringPi

3. Run the executable file.

sudo ./a.out

After the code runs, you will see that RGB displays red, green, blue, yellow, pink, and cyan.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <softPwm.h>
#include <stdio.h>

#define uchar unsigned char

#define LedPinRed    0
#define LedPinGreen  1
#define LedPinBlue   2

// define function used for initializing I/O port to output for pwm.
void ledInit(void){
    softPwmCreate(LedPinRed,  0, 100);
    softPwmCreate(LedPinGreen,0, 100);
    softPwmCreate(LedPinBlue, 0, 100);
}

void ledColorSet(uchar r_val, uchar g_val, uchar b_val){
    softPwmWrite(LedPinRed,   r_val);
    softPwmWrite(LedPinGreen, g_val);
    softPwmWrite(LedPinBlue,  b_val);
}

int main(void){
    if(wiringPiSetup() == -1){ //when initialize wiring failed, printf message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    ledInit();

    while(1){
        printf("Red\n");
        ledColorSet(0xff,0x00,0x00);   //red
        delay(500);
        printf("Green\n");
        ledColorSet(0x00,0xff,0x00);   //green
        delay(500);
        printf("Blue\n");
        ledColorSet(0x00,0x00,0xff);   //blue
        delay(500);
        printf("Yellow\n");
        ledColorSet(0xff,0xff,0x00);   //yellow
        delay(500);
        printf("Purple\n");
        ledColorSet(0xff,0x00,0xff);   //purple
        delay(500);
        printf("Cyan\n");
        ledColorSet(0xc0,0xff,0x3e);   //cyan
        delay(500);
    }

    return 0;
}
Code Explanation
12.void ledInit(void){
13.    softPwmCreate(LedPinRed,  0, 100);
14.    softPwmCreate(LedPinGreen,0, 100);
15.    softPwmCreate(LedPinBlue, 0, 100);
16.}

Create a function to set the LedPinRedLedPinGreen and LedPinBlue as PWM pins, then set their period between 0x100us-100x100us.

The prototype of the function softPwmCreate(LedPinRed, 0, 100) is as follows:

int softPwmCreate(int pin,int initialValue,int pwmRange);

pin: Any GPIO pin of Raspberry Pi can be set as a PWM pin.

initialValue: The initial pulse width is that initialValue times100us.

pwmRange: the period of PWM is that pwmRange times100us.

18.void ledColorSet(uchar r_val, uchar g_val, uchar b_val){
19.    softPwmWrite(LedPinRed,   r_val);
20.    softPwmWrite(LedPinGreen, g_val);
21.    softPwmWrite(LedPinBlue,  b_val);
22.}

This function is to set the colors of the LED. Using RGB, the formal parameter r_val represents the luminance of the red one, g_val of the green one, b_val of the blue one.

The prototype of the function softPwmWrite(LedPinBlue, b_val) is as follows:

void softPwmWrite (int pin, int value) ;

pin: Any GPIO pin of Raspberry Pi can be set as a PWM pin.

Value: The pulse width of PWM is value times 100us. Note that value can only be less than pwmRange defined previously, if it is larger than pwmRange, the value will be given a fixed value, pwmRange.

30.    ledInit();

Call the ledInit() function in the main function to initialize the LED.

34.    ledColorSet(0xff,0x00,0x00);   //red

Call the function defined before. Write 0xff into LedPinRed and 0x00 into LedPinGreen and LedPinBlue.

Only the Red LED lights up after running this code. If you want to light up LEDs in other colors, just modify the parameters.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 4_rgbLed.py

After the code runs, you will see that RGB displays red, green, blue, yellow, pink, and cyan.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

COLOR = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF]
pins = {'Red':17, 'Green':18, 'Blue':27}

def setup():
    global p_R, p_G, p_B
    GPIO.setmode(GPIO.BCM)
    for i in pins:
        GPIO.setup(pins[i], GPIO.OUT, initial=GPIO.LOW)

    # Set all led as pwm channel and frequece to 2KHz
    p_R = GPIO.PWM(pins['Red'], 2000)
    p_G = GPIO.PWM(pins['Green'], 2000)
    p_B = GPIO.PWM(pins['Blue'], 2000)

    # Set all begin with value 0
    p_R.start(0)
    p_G.start(0)
    p_B.start(0)

def MAP(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

def setColor(color):
    # Devide colors from 'color' veriable
    R_val = (color & 0xFF0000) >> 16
    G_val = (color & 0x00FF00) >> 8
    B_val = (color & 0x0000FF) >> 0

    # Map color value from 0~255 to 0~100
    R_val = MAP(R_val, 0, 255, 0, 100)
    G_val = MAP(G_val, 0, 255, 0, 100)
    B_val = MAP(B_val, 0, 255, 0, 100)

    # Change the colors
    p_R.ChangeDutyCycle(R_val)
    p_G.ChangeDutyCycle(G_val)
    p_B.ChangeDutyCycle(B_val)

    print ("color_msg: R_val = %s,  G_val = %s, B_val = %s"%(R_val, G_val, B_val))

def main():
    while True:
        for color in COLOR:
            setColor(color)
            time.sleep(0.5)

def destroy():
    # Stop all pwm channel
    p_R.stop()
    p_G.stop()
    p_B.stop()
    # Turn off all LEDs
    GPIO.output(pins, GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
14.    p_R = GPIO.PWM(pins['Red'], 2000)

This statement is used to set the pin to a specific PWM frequency, in this case 2000 Hz.

23.def MAP(x, in_min, in_max, out_min, out_max):
24.    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

Define a map function for mapping values. For instance, x=50, in_min=0, in_max=255, out_min=0, out_max=100. After the map function mapping, it returns (50-0) * (100-0)/(255-0) +0=19.6, meaning that 50 in 0-255 equals 19.6 in 0-100.

26.def setColor(color):
27.    R_val = (color & 0xFF0000) >> 16
28.    G_val = (color & 0x00FF00) >> 8
29.    B_val = (color & 0x0000FF) >> 0

Create a setColor() function to assign different value to the three variables: R_val, G_val, B_val. Input color should be hexadecimal with red value, blue value, green value. Assign the first two values of the hexadecimal to R_val, the middle two to G_val, assign the last two values to B_val, please refer to the shift operation of the hexadecimal for details. For example, color=0xFF00FF, then R_val=(0xFF00FF & 0xFF0000)>>16 = 0xFF, G_val = 0x00, B_val=0xFF.

32.# Map color value from 0~255 to 0~100
33.    R_val = MAP(R_val, 0, 255, 0, 100)
34.    G_val = MAP(G_val, 0, 255, 0, 100)
35.    B_val = MAP(B_val, 0, 255, 0, 100)
36.
37.    # Change the colors
38.    p_R.ChangeDutyCycle(R_val)
39.    p_G.ChangeDutyCycle(G_val)
40.    p_B.ChangeDutyCycle(B_val)

Map the RGB value from 0 - 255 to 0 - 100. After that, get a value. Then set it to be the duty cycle of R_val, G_val and B_val, and the RGB LED displays corresponding colors.

46.            for color in COLOR:
47.            setColor(color)
48.            time.sleep(0.5)

Assign every item in the COLOR list to the color respectively and change the color of the RGB LED via the setColor() function.

Phenomenon Picture
_images/image99.jpeg
Lesson 5 Controlling LED by Button
Introduction

In this lesson, we will learn how to turn an LED on or off by a button.

Newly Added Components
_images/image2091.png
Principle

Button

Button is a common component used to control electronic devices. It is usually used as switch to connect or break circuits. Although buttons come in a variety of sizes and shapes, the one used here is a 6mm mini-button as shown in the following pictures.

Two pins on the same side are connected, which is shown below:

_images/image102.png

The symbol shown as below is usually used to represent a button in circuits.

_images/image2101.png

When the button is pressed, the 4 pins are connected, thus closing the circuit.

Schematic Diagram

When the button is pressed once, pin 32 is 3.3V (HIGH). Set the pin 11(integrated with an LED) as high level by programming at the same time. Then press the button again and set pin 11 to Low. So we will see the LED light on and off alternately as the button is pressed many times.

_images/image2111.png _images/image265.png
Build the Circuit
_images/image267.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_5_Controlling_Led_by_Button

2. Compile the code.

gcc 5_Button.c -lwiringPi

3. Run the executable file.

sudo ./a.out

When you press the button for the first time, the LED lights up. When the button is pressed again, the LED lights off.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define LedPin      0
#define ButtonPin   26
int state = 0;

int main(void){
    // When initialize wiring failed, print message to screen
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(LedPin, OUTPUT);
    pinMode(ButtonPin, INPUT);
    pullUpDnControl(ButtonPin, PUD_DOWN);

    while(1){
        // Indicate that button has pressed down
        if(digitalRead(ButtonPin) == 1)
        {
            delay(10);
            if(digitalRead(ButtonPin) == 1)
            {
                state ++;
                if(state%2 == 1)
                {
                    digitalWrite(LedPin,HIGH);
                    delay(100);
                }
                if(state%2 == 0)
                {
                    digitalWrite(LedPin,LOW);
                    delay(100);
                }
            }
        }
    }
    return 0;
}
Code Explanation
6. int state = 0;

Define a variable state to record the number of times it is pressed and the initial number of times is 0.

15.  pinMode(LedPin, OUTPUT);
16.  pinMode(ButtonPin, INPUT);

Set the LedPin to OUTPUT mode, ButtonPin to INPUT mode.

17.    pullUpDnControl(ButtonPin, PUD_DOWN);

When the button is not pressed, ButtonPin is in suspension at which time the read value is changing. To enable ButtonPin to output a stable low level, PUD_DOWN is added to the code, keeping ButtonPin at the forced pull-down state till the button is pressed.

21.        if(digitalRead(ButtonPin) == 1)
22.        {
23.            delay(10);
24.            if(digitalRead(ButtonPin) == 1)
25.            {

Usually the buttons we use are mechanical buttons, so in the process of pressing down and releasing, there will be no direct change from 0 to 1, but will be more than 10ms of level jitter. In order to ensure that the program only responds to the button once when it is closed or broken, the jitter elimination of the button must be carried out. An if function is used to detect whether the button is pressed. When the signal of the button is pressed is detected, a delay of 10ms is used to eliminate the possibility of false judgment, and another if function is used to detect again. If both if conditions are met, confirm that it is a button press, and then execute the program in the if.

26.                state ++;

If the button is pressed, the number of times it is pressed is increased by one. (state ++ is the same as state = state+1).

27.                if(state%2 == 1)
28.                {
29.                    digitalWrite(LedPin,HIGH);
30.                    delay(100);
31.                }

% is a modulo operator in C language; state%2 is that state is divided by 2 to return the remainder. If state=17, then state%2 =1. Here, determine whether state%2 is equal to 1. If it is, it means that the number of times of pressing the button is a singular number, and then turn on the LED.

32.                if(state%2 == 0)
33.                {
34.                    digitalWrite(LedPin,LOW);
35.                    delay(100);
36.                }

Here, judge whether state%2 is equal to 0. If so, it means that the number of times the button is pressed is an even number, and then turn off the LED.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 5_Button.py

When you press the button for the first time, the LED lights up. When the button is pressed again, the LED lights off.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

LedPin = 17
BtnPin = 12
Led_status = False

# Define a setup function for some setup
def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BtnPin, GPIO.IN)
    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.LOW)
    GPIO.add_event_detect(BtnPin, GPIO.FALLING, callback=swLed)

# Define a callback function for button callback
def swLed(ev=None):
    global Led_status
    Led_status = not Led_status
    GPIO.output(LedPin, Led_status)

# Define a main function for main process
def main():
    while True:
        # Don't do anything.
        time.sleep(1)

# Define a destroy function for clean up everything after
# the script finished
def destroy():
    # Turn off LED
    GPIO.output(LedPin, GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
6. Led_status = False

Set a variable Led_status to record the current status of the LED; when Led_status is True, it indicates that the current lamp is in bright state; when Led_status is False, it means that the light is off.

11.    GPIO.setup(BtnPin, GPIO.IN)

Set BtnPin as input mode to read the state of the button to determine whether to execute the corresponding program. Note that when GPIO.setup sets the pin to input mode, then there is no need to set the initial value.

12.    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.LOW)

Specify an initial value for your output channel. Here the LED is the output component, so we set LedPin to GPIO.OUT mode. Then initialize the state of LED to GPIO.LOW which means that the light is off.

13.    GPIO.add_event_detect(BtnPin, GPIO.FALLING, callback=swLed)

The event_detected() function is designed to be used in a loop with other things, but unlike polling it is not going to miss the change in state of an input while the CPU is busy working on other things. Set up a falling detect on BtnPin, when the BtnPin pin is detected to change from high level to low level, swLed function is called.

13.def swLed(ev=None):
14.    global Led_status
15.    Led_status = not Led_status
16.    GPIO.output(LedPin, Led_status)

RPi.GPIO runs a second thread for callback functions. This means that callback functions can be run at the same time as your main program, in immediate response to an edge. Define a callback function for button callback, execute the function after the callback of the interrupt. When this function is executed, the state of the LED is firstly reversed(If True, make it False, and vice versa). Then input the function to LedPin. And “ev = None” means that if no parameter is passed when calling swLed, take None as the default value of ev.

Phenomenon Picture
_images/image107.jpeg
Lesson 6 Tilt Switch
Introduction

In this lesson, we’ll learn a new switch component, tilt switch. Here we apply two LEDs to indicate the current state of tilt switch. You can also use this kind of switch to make a sense light with the clamshell box.

Newly Added Components
_images/image213.png
Principle

The principle is very simple. When the switch is tilted in a certain angle, the ball inside rolls down and touches the two contacts connected to the pins outside, thus triggering circuits. Otherwise the ball will stay away from the contacts, thus breaking the circuits.

_images/image110.jpeg
Schematic Diagram
_images/image2141.png
Build the Circuit
_images/image112.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_6_TiltSwitch

2. Compile the code.

gcc 6_Tilt.c -lwiringPi

3. Run the executable file.

sudo ./a.out

When the tilt switch is level, the green LED turns on. If you tilt the switch, the red LED will turn on.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define TiltPin     0
#define Gpin        2
#define Rpin        3

int main(void)
{
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(TiltPin, INPUT);
    pinMode(Gpin, OUTPUT);
    pinMode(Rpin, OUTPUT);

    while(1){

        if(1 == digitalRead(TiltPin)){
            delay(10);
            if(1 == digitalRead(TiltPin)){
                digitalWrite(Rpin, HIGH);
                digitalWrite(Gpin, LOW);
                printf("RED\n");
            }
        }
        else if(0 == digitalRead(TiltPin)){
            delay(10);
            if(0 == digitalRead(TiltPin)){
                while(!digitalRead(TiltPin));
                digitalWrite(Rpin, LOW);
                digitalWrite(Gpin, HIGH);
                printf("GREEN\n");
            }
        }
    }
    return 0;
}
Code Explanation
15.    pinMode(TiltPin, INPUT);
16.    pinMode(Gpin, OUTPUT);
17.    pinMode(Rpin, OUTPUT);

Initialize pins, then set the pin of tilt switch to INPUT mode, and LEDs to OUTPUT mode.

21.        if(1 == digitalRead(TiltPin)){

It is used to judge whether the tilt switch is tilted or not. The value of TiltPin is firstly read, if it is equal to 1, the codes inside the if() statement run; otherwise, the codes of if are skipped.

21.    if(1 == digitalRead(TiltPin)){
22.            delay(10);
23.            if(1 == digitalRead(TiltPin)){
24.                digitalWrite(Rpin, HIGH);
25.                digitalWrite(Gpin, LOW);
26.                printf("RED\n");
27.            }
28.        }

When the tilt is tilted, the tilt switch is on; the Raspberry Pi reads a high level at the tilt pin, so the red LED is on and green LED off.

29.        else if(0 == digitalRead(TiltPin)){
30.            delay(10);
31.            if(0 == digitalRead(TiltPin)){
32.                while(!digitalRead(TiltPin));
33.                digitalWrite(Rpin, LOW);
34.                digitalWrite(Gpin, HIGH);
35.                printf("GREEN\n");
36.            }
37.        }

When the tilt is level, the tilt switch is off; the Raspberry Pi reads a low level at the tilt pin, so the red LED is off and green LED on.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 6_Tilt.py

When the tilt switch is level, the green LED turns on. If you tilt the switch, the red LED will turn on.

code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO

TiltPin = 17
Gpin   = 27
Rpin   = 22

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(Gpin, GPIO.OUT,initial=GPIO.HIGH)
    GPIO.setup(Rpin, GPIO.OUT,initial=GPIO.LOW)
    GPIO.setup(TiltPin, GPIO.IN)
    GPIO.add_event_detect(TiltPin, GPIO.BOTH, callback=detect, bouncetime=200)

def Led(x):
    if x == 0:
        GPIO.output(Rpin, 1)
        GPIO.output(Gpin, 0)
    if x == 1:
        GPIO.output(Rpin, 0)
        GPIO.output(Gpin, 1)

def Print(x):
    if x == 0:
        print ('    *************')
        print ('    *   Tilt!   *')
        print ('    *************')

def detect(chn):
    Led(GPIO.input(TiltPin))
    Print(GPIO.input(TiltPin))

def loop():
    while True:
        pass

def destroy():
    GPIO.output(Gpin, GPIO.LOW)       # Green LED off
    GPIO.output(Rpin, GPIO.LOW)       # Red LED off
    GPIO.cleanup()                     # Release resource

if __name__ == '__main__':     # Program start from here
    setup()
    try:
        loop()
        # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
12.    GPIO.add_event_detect(TiltPin, GPIO.BOTH, callback=detect, bouncetime=200)

Set up a falling detect on TiltPin, and callback function to detect. Here bouncetime is to add rise threshold detection on the channel and ignore edge operations less than 200ms caused by switch jitter.

13.def Led(x):
14.    if x == 0:
15.        GPIO.output(Rpin, 1)
16.        GPIO.output(Gpin, 0)
17.    if x == 1:
18.        GPIO.output(Rpin, 0)
19.        GPIO.output(Gpin, 1)

Define a Led() function to set the mode of the two LEDs. When x = 0, the red LED goes on and the green light goes off; when x = 1, the red LED goes off, the green LED goes on. When the function is called, the mode of the LED can be set directly with the statement Led(1) or Led(0).

28.def detect(chn):
29.    Led(GPIO.input(TiltPin))
30.    Print(GPIO.input(TiltPin))

This is a callback function that executes when a trigger is detected. Assign the current TiltPin state (0 or 1) to the Led function, that is, pass parameters to the Led function. The Led function then performs the corresponding operation on the LEDs.

Phenomenon Picture
_images/image113.jpeg
Lesson 7 Slide Switch
Introduction

In this lesson, we are going to use a slide switch to turn on the 2 LEDs. The slide switch is a device to connect or disconnect the circuit by sliding its handle. They are quite common in our surroundings. Now let’s see how it works.

Newly Added Components
_images/image2151.png
Principle

Slide Switch

_images/image1151.jpeg

Just as its name suggests, slide switch is to connect or disconnect the circuit by sliding its switch handle so as to switch the circuit. The common types of slide switch include single pole double throw, single pole triple throw, double pole double throw, and double pole triple throw and so on. Generally, it is used in circuits with a low voltage and features flexibility and stabilization. Slide switches are commonly used in all kinds of instruments/meters equipment, electronic toys and other fields related.

How it works: The middle pin is fixed. When the handle is pushed to the left, the left two pins are connected; when push it to the right, the two pins on the right connect, thus switching circuits.

Just as its name suggests, slide switch is to connect or disconnect the circuit by sliding its switch handle so as to switch the circuit. The common types of slide switch include single pole double throw, single pole triple throw, double pole double throw, and double pole triple throw and so on. Generally, it is used in circuits with a low voltage and features flexibility and stabilization. Slide switches are commonly used in all kinds of instruments/meters equipment, electronic toys and other fields related.

How it works: The middle pin is fixed. When the handle is pushed to the left, the left two pins are connected; when push it to the right, the two pins on the right connect, thus switching circuits.

_images/image2161.png

See the circuit symbol of slide switch and 2 is the middle pin.

_images/image254.png
Schematic Diagram

Here we use a slide switch to turn the LED on/off, which is simple. Connect the middle pin of the switch to pin 11. Connect the left pin of the switch to GND, the right to 3.3V. Attach the anode pins (the longer pins) of the two LEDs to pin 13 and pin 15 respectively after getting them connected with two 220Ω resistors. In addition, insert the cathodes of the two LEDs into GND. Get the slide switch connected to the left, the signal read on pin 11 is 0 (a low level), so the LED 1 lights up; to the right, the signal read on pin 11 is 1 (a high level), then the LED 2 turns on.

_images/image2171.png
Build the Circuit
_images/image120.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_7_SlideSwitch

2. Compile the code.

gcc 7_Slider.c -lwiringPi

3. Run the executable file.

sudo ./a.out

When the slide is pulled to the right, the LED2 is on and LED1 off. If the slide is pulled to the left, the LED1 is on and LED2 off.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define slidePin        0
#define led1            2
#define led2            3

int main(void)
{
    // When initialize wiring failed, print message to screen
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(slidePin, INPUT);
    pinMode(led1, OUTPUT);
    pinMode(led2, OUTPUT);

    while(1){
        // slide switch high, led1 on
        if(digitalRead(slidePin) == 1){
            digitalWrite(led1, HIGH);
            digitalWrite(led2, LOW);
            printf("LED1 on\n");
            delay(100);
        }
        // slide switch low, led2 on
        if(digitalRead(slidePin) == 0){
            digitalWrite(led2, HIGH);
            digitalWrite(led1, LOW);
            printf(".....LED2 on\n");
            delay(100);
        }
    }
    return 0;
}
Code Explanation
16.    pinMode(slidePin, INPUT);
17.    pinMode(led1, OUTPUT);
18.    pinMode(led2, OUTPUT);

Initialize the pins connected to slide switch to the INPUT mode, and initialize the LED lights to the OUTPUT mode.

22.        if(digitalRead(slidePin) == 1){
23.            digitalWrite(led1, HIGH);
24.            digitalWrite(led2, LOW);
25.            printf("LED1 on\n");
26.            delay(100);
27.        }

When the slide is pulled to the left, the middle pin and left one are connected; the Raspberry Pi reads a high level at the middle pin, so the LED1 is on and LED2 off.

28.        if(digitalRead(slidePin) == 0){
29.            digitalWrite(led2, HIGH);
30.            digitalWrite(led1, LOW);
31.            printf(".....LED2 on\n");
32.            delay(100);
33.        }

When the slide is pulled to the right, the middle pin and right one are connected; the Raspberry Pi reads a low, so the LED2 is on and LED1 off.

For Python Language Users
Command
  1. Go to the folder of the code

cd /home/pi/electronic-kit/for-raspberry-pi/python
  1. Run the code

sudo python3 7_Slider.py

When the slide is pulled to the right, the LED2 is on and LED1 off. If the slide is pulled to the left, the LED1 is on and LED2 off.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

slidePin = 17
led1Pin = 27
led2Pin = 22

# Define a setup function for some setup
def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(slidePin, GPIO.IN)
    GPIO.setup(led1Pin, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(led2Pin, GPIO.OUT, initial=GPIO.LOW)

def main():
    while True:
        # slide switch high, led1 on
        if GPIO.input(slidePin) == 1:
            print ('LED1 ON ')
            GPIO.output(led2Pin, GPIO.LOW)
            GPIO.output(led1Pin, GPIO.HIGH)

        # slide switch low, led2 on
        if GPIO.input(slidePin) == 0:
            print ('    LED2 ON ')
            GPIO.output(led1Pin, GPIO.LOW)
            GPIO.output(led2Pin, GPIO.HIGH)
        time.sleep(0.5)

def destroy():
    # Turn off LED
    GPIO.output(led1Pin, GPIO.LOW)
    GPIO.output(led2Pin, GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
11.    GPIO.setup(slidePin, GPIO.IN)
12.    GPIO.setup(led1Pin, GPIO.OUT, initial=GPIO.LOW)
13.    GPIO.setup(led2Pin, GPIO.OUT, initial=GPIO.LOW)

Initialize the pin, then set the pin connected to slide switch to the input mode and LEDs to the output mode.

18.    if GPIO.input(slidePin) == 1:
19.            GPIO.output(led2Pin, GPIO.LOW)
20.            GPIO.output(led1Pin, GPIO.HIGH)

When the slide is pulled to the left, the middle pin and left one are connected; the Raspberry Pi reads a high level at the middle pin, so the LED1 is on and LED2 off.

24.       if GPIO.input(slidePin) == 0:
25.            GPIO.output(led1Pin, GPIO.LOW)
26.            GPIO.output(led2Pin, GPIO.HIGH)

When the slide is pulled to the right, the middle pin and right one are connected; the Raspberry Pi reads a low, so the LED2 is on and LED1 off.

Phenomenon Picture
_images/image121.jpeg
Lesson 8 Relay
Introduction

In this lesson, we will learn to use a relay. It is one of the commonly used components in automatic control system. When the voltage, current, temperature, pressure, etc., reaches, exceeds or is lower than the predetermined value, the relay will connect or interrupt the circuit, to control and protect the equipment.

Newly Added Components
_images/image218.png
Principle

Relay

As we may know, relay is a device which is used to provide connection between two or more points or devices in response to the input signal applied. In other words, relays provide isolation between the controller and the device as devices may work on AC as well as on DC. However, they receive signals from a microcontroller which works on DC hence requiring a relay to bridge the gap. Relay is extremely useful when you need to control a large amount of current or voltage with small electrical signal.

There are 5 parts in every relay:

1. Electromagnet - It consists of an iron core wounded by coil of wires. When electricity is passed through, it becomes magnetic. Therefore, it is called electromagnet.

2. Armature - The movable magnetic strip is known as armature. When current flows through them, the coil is energized thus producing a magnetic field which is used to make or break the normally open (N/O) or normally close (N/C) points. And the armature can be moved with direct current (DC) as well as alternating current (AC).

3. Spring - When no currents flow through the coil on the electromagnet, the spring pulls the armature away so the circuit cannot be completed.

  1. Set of electrical contacts - There are two contact points:

  • Normally open - connected when the relay is activated, and disconnected when it is inactive.

  • Normally close - not connected when the relay is activated, and connected when it is inactive.

  1. Molded frame - Relays are covered with plastic for protection.

Working of Relay

The working principle of relay is simple. When power is supplied to the relay, currents start flowing through the control coil; as a result, the electromagnet starts energizing. Then the armature is attracted to the coil, pulling down the moving contact together thus connecting with the normally open contacts. So the circuit with the load is energized. Then breaking the circuit would a similar case, as the moving contact will be pulled up to the normally closed contacts under the force of the spring. In this way, the switching on and off of the relay can control the state of a load circuit.

_images/image125.jpeg

Transistor

_images/image126.jpeg

Transistor is a semiconductor device that controls current by current. It functions by amplifying weak signal to larger amplitude signal and is also used for non-contact switch. A transistor is a three-layer structure composed of P-type and N-type semiconductors. They form the three regions internally. The thinner in the middle is the base region; the other two are both N-type or P-type ones – the smaller region with intense majority carriers is the emitter region, while the other one is the collector region. This composition enables the transistor to be an amplifier.

From these three regions, three poles are generated respectively, which are base (b), emitter (e), and collector (c). They form two P-N junctions, namely, the emitter junction and collection junction. The direction of the arrow in the transistor circuit symbol indicates that of the emitter junction. Based on the semiconductor type, transistors can be divided into two groups, the NPN and PNP ones. From the abbreviation, we can tell that the former is made of two N-type semiconductors and one P-type and that the latter is the opposite. See the figure below.

_images/image127.png

When a High level signal goes through an NPN transistor, it is energized. But a PNP one needs a Low level signal to manage it. Both types of transistor are frequently used for contactless switches, just like in this experiment.

Diode1N4007

_images/image128.jpeg

1N4007 is a semiconductor device for converting alternating current into direct current. By using the one-way conductivity of the diode, alternating current with alternating directions can be converted into a single-direction pulse direct current.

With a positive large current, 1N4007 has a low voltage drop (representative value 0.7 V ) called as forward conduction state. If the opposite voltage is applied, the potential barrier is increased to withstand a high reverse voltage or to flow through a very small reverse current (called reverse leakage current) called as a reverse blocking state. Thus, the rectifier diode has a significant one-way conductivity. In this lesson, we apply this characteristic of diode.

Schematic Diagram

When a high level signal is given to Pin 11, the transistor is energized, thus making the coil of the relay conductive. Then its normally open contact is closed, and the LED will light up. When Pin 11 is given a Low level, the LED will stay dim. In this experiment, we apply Freewheeling Diode that connects to both ends of the relay coil in parallel to prevent relay from breakdown or burnout caused by induced voltage.

_images/image268.png
Build the Circuit
_images/image130.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_8_Relay

2. Compile the code.

gcc 8_Relay.c -lwiringPi

3. Run the executable file.

sudo ./a.out

Now, the LED will blink, you can hear a tick-tock caused by breaking the normally close contact and closing the normally open one.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define RelayPin 0

int main(void){
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(RelayPin, OUTPUT);

    while(1){
        // Tick
        printf("......Relay Open \n");
        digitalWrite(RelayPin, LOW);
        delay(1000);
        // Tock
        printf("Relay Close......\n");
        digitalWrite(RelayPin, HIGH);
        delay(1000);
    }
    return 0;
}
Code Explanation
17.        digitalWrite(RelayPin, LOW);

Set the I/O port RelayPin as LOW (0V), so the transistor is not energized and the coil is not powered. There is no electromagnetic force, so the relay opens and the LED remains off.

21.        digitalWrite(RelayPin, HIGH);

Set the I/O port as HIGH (5V) to energize the transistor. The coil of the relay is powered and generate electromagnetic force, and the relay closes. Then you can see the LED is lit.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 8_Relay.py

Now, the LED is blinking, you can hear a tick-tock caused by breaking the normally closed contact and closing the normally open one.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

relayPin = 17

# Define a setup function for some setup
def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(relayPin, GPIO.OUT, initial=GPIO.LOW)

# Define a main function for main process
def main():
    while True:
        print ('...Relay open')
        # Tick
        GPIO.output(relayPin, GPIO.LOW)
        time.sleep(1)
        print ('Relay close...')
        # Tock
        GPIO.output(relayPin, GPIO.HIGH)
        time.sleep(1)

def destroy():
    # Turn off LED
    GPIO.output(relayPin, GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
9.    GPIO.setup(relayPin, GPIO.OUT, initial=GPIO.LOW)

Initialize pins. And the output pin of relay is set to output mode and default low level.

17.        time.sleep(1)

Wait for 1 second. Change the switching frequency of the relay by changing this parameter. Note: Relay is a kind of metal dome formed in mechanical structure. So its lifespan will be shortened under high-frequency using.

16.        GPIO.output(relayPin, GPIO.LOW)

Set the I/O port as low level (0V), thus the transistor is not energized and the coil is not powered. There is no electromagnetic force, so the relay opens and the LED remains off.

20.        GPIO.output(relayPin, GPIO.HIGH)

Set the I/O port as high level (5V) to energize the transistor. The coil of the relay is powered and generate electromagnetic force, and the relay closes. Then you can see the LED is lit.

Phenomenon Picture
_images/image131.jpeg
Lesson 9 4N35
Introduction

In this lesson, let’s learn the operational principle of 4N35 chip. We analyze the principle in this way: using 4N35 chip to drive a LED, and then explaining the phenomenon of LED and the internal structure of the chip.

Newly Added Components
_images/image2201.png
Principle

4N35

4N35 is a general-purpose optocoupler. It consists of gallium arsenide infrared LED and a silicon NPN phototransistor. What an optocoupler does is to break the connection between signal source and signal receiver, so as to stop electrical interference. 4N35 can be used in AV conversion audio circuits that is widely used in electrical isolation of a general optocoupler.

_images/image2211.png

See the internal structure of the 4N35 above. Pin 1 and 2 are connected to an infrared LED. When the LED is electrified, it’ll emit infrared rays. To protect the LED from burning, usually a resistor (about 1K) is connected to pin 1. Then the NPN phototransistor is power on when receiving the rays, and then it can control the load connected to the phototransistor. Even when the load short circuit occurs, it won’t affect the control board, thus realizing good electrical isolation.

Schematic Diagram

In this experiment, use an LED as the load connected to the NPN phototransistor. In program, a LOW level is given to Pin 11, then the infrared LED will emit infrared rays. After that, the phototransistor receives infrared rays and gets electrified, and the LED cathode is LOW, thus turning on the LED.

_images/image2221.png
Build the Circuit

Note

pay attention to the direction of the chip by the concave on it.

_images/image136.png
For C Language Users

Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_9_4N35

2. Compile the code.

gcc 9_4N35.c -lwiringPi

3. Run the executable file.

sudo ./a.out

You will see the LED blinking.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define OptoPin  0

int main(void)
{
    // When initialize wiring failed, print message to screen
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(OptoPin,OUTPUT);

    while(1){
        // Turn LED off
        digitalWrite(OptoPin, HIGH);
        delay(500);
        // Turn LED on
        digitalWrite(OptoPin, LOW);
        delay(500);
    }
    return 0;
}
Code Explanation
14.    pinMode(OptoPin,OUTPUT);

Initialize pins. Set the output pin of 4N35, Optopin to OUTPUT mode.

18.        digitalWrite(OptoPin, HIGH);

Set OptoPin as LOW (0V), thus the optocoupler is energized, and the pin connected to LED conduct to low level. Then the LED will light up.

21.        digitalWrite(OptoPin, LOW);

Set OptoPin as HIGH (3.3V), thus the optocoupler is not energized, and the pin connected to LED cannot conduct to low level. Then the LED goes out.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 9_4N35.py

You will see the LED blinking.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

Pin_4N35 = 17

# Define a setup function for some setup
def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(Pin_4N35, GPIO.OUT, initial=GPIO.LOW)

# Define a main function for main process
def main():
    while True:
        # Turn off LED
        GPIO.output(Pin_4N35, GPIO.HIGH)
        time.sleep(0.5)
        # Turn on LED
        GPIO.output(Pin_4N35, GPIO.LOW)
        time.sleep(0.5)

def destroy():
    # Turn off LED
    GPIO.output(Pin_4N35, GPIO.HIGH)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
1.         GPIO.output(Pin_4N35, GPIO.HIGH)

Set OptoPin as high level (3.3V), thus the optocoupler is not energized, and the pin connected to LED cannot conduct to low level. Then the LED goes out.

1.         time.sleep(0.5)

Wait for 0.5 second. The on-off frequency of the optocoupler can be changed by modifying this parameter.

1.         GPIO.output(Pin_4N35, GPIO.LOW)

Set OptoPin as low level (0V), thus the optocoupler is energized, and the pin connected to LED conduct to low level. Then the LED will light up.

Phenomenon Picture
_images/image137.jpeg
Lesson 10 Active Buzzer
Introduction

A buzzer is a great tool in your experiments whenever you want to make sounds.

Newly Added Components
_images/image223.png
Principle

As a type of electronic buzzer with an integrated structure, buzzers, which are supplied by DC power, are widely used in computers, printers, photocopiers, alarms, electronic toys, automotive electronic devices, telephones, timers and other electronic products or voice devices. Buzzers can be categorized as active and passive ones (see the following picture). Turn the buzzer so that its pins are facing up, and the buzzers with a green circuit board is a passive buzzer, while the one enclosed with a black tape is an active one.

The difference between an active buzzer and a passive buzzer:

_images/image139.png

An active buzzer has a built-in oscillating source, so it will make sounds when electrified. But a passive buzzer does not have such source, so it will not tweet if DC signals are used; instead, you need to use square waves whose frequency is between 2K and 5K to drive it. The active buzzer is often more expensive than the passive one because of multiple built-in oscillating circuits.

In this experiment, we use an active buzzer.

Schematic Diagram

When Pin11 is input into high voltage, the transistor will be switched on, and the collector will output low level. When there is a level difference between the two pins of the buzzer, the buzzer is ringing. When Pin11 inputs low power level, the transistor is cut off and the collector is at high level, here, both ends of the buzzer are at high level, the buzzer will be silent.

_images/image224.png
Build the Circuit
_images/image141.png
For C Language Users
Command
  1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_10_ActiveBuzzer
  1. Compile the code.

gcc 10_ActiveBuzzer.c -lwiringPi
  1. Run the executable file.

sudo ./a.out

Now, you may hear the buzzer beep.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define BeepPin 0

int main(void){
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(BeepPin, OUTPUT);

    while(1){
        //beep on
        digitalWrite(BeepPin, HIGH);
        delay(100);
        //beep off
        digitalWrite(BeepPin, LOW);
        delay(100);
    }
    return 0;
}
Code Explanation
12.    pinMode(BeepPin, OUTPUT);

Set the pin connected to the buzzer to OUTPUT mode.

16.        digitalWrite(BeepPin, HIGH);

When BeepPin is at high level, the base pin(b pin) of the connected transistor inputs high level and the collector pin(c pin) output low level. That is, when the cathode of the buzzer is at low level and the anode of the buzzer is connected to a 5V high level, the buzzer sounds.

19.        digitalWrite(BeepPin, LOW);

The BeepPin is connected to the transistor and then to the cathode of the buzzer. When BeepPin is low level, the base pin (b pin) of the connected transistor inputs low level, then the collector pin(c pin) outputs high level; that is, when the level at both ends of the connected buzzer is high, the buzzer is silent.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 10_ActiveBuzzer.py

Now, you should hear the buzzer beep.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

BeepPin = 17

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BeepPin, GPIO.OUT, initial=GPIO.LOW)

def main():
    while True:
        # Buzzer on (Beep)
        GPIO.output(BeepPin, GPIO.HIGH)
        time.sleep(0.1)
        # Buzzer off
        GPIO.output(BeepPin, GPIO.LOW)
        time.sleep(0.1)

def destroy():
    # Turn off buzzer
    GPIO.output(BeepPin, GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
1.    GPIO.setup(BeepPin, GPIO.OUT, initial=GPIO.LOW)

Initialize the pin connected to the buzzer to output mode and set it to the default low level.

1.         GPIO.output(BeepPin, GPIO.HIGH)

The BeepPin is connected to the transistor and then to the cathode of the buzzer. When BeepPin is at high level, the base pin(b pin) of the connected transistor inputs high level, then the collector pin(c pin) outputs low level; that is, when the cathode of the buzzer is at low level and the anode of the buzzer is connected to a 5V high level, the buzzer sounds.

1.         GPIO.output(BeepPin, GPIO.LOW)

When BeepPin is at low level, the base pin(b pin) of the connected transistor inputs low level, then the collector pin(c pin) outputs high level; that is, when the level at both ends of the connected buzzer is high, the buzzer is silent.

Phenomenon Picture
_images/image142.jpeg
Lesson 11 Doorbell
Introduction

In this lesson, we will learn how to drive an active buzzer to build a simple doorbell.

Newly Added Components
_images/image225.png
Schematic Diagram

When the button is pressed, Pin13 is connected to the 5V power supply and reads out high level; therefore, the program responds to make Pin11 output the high level so as to energize the transistor, and the collector will output low level that means the buzzer rings. When pin11 outputs at low level the buzzer will be silent.

_images/image226.png _images/image255.png
Build the Circuit

Note

Long pins of buzzer is the Anode and the short pin is Cathode.

_images/image144.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_11_DoorBell

2. Compile the code.

gcc 11_DoorBell.c -lwiringPi

3. Run the executable file.

sudo ./a.out

When the button is pressed, the buzzer makes a sound to simulate a doorbell.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define BeepPin 0
#define ButtonPin   2

int main(void){
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(BeepPin, OUTPUT);
    pinMode(ButtonPin, INPUT);
    pullUpDnControl(ButtonPin, PUD_DOWN);

    while(1){
        // Indicate that button has pressed down
        if(digitalRead(ButtonPin) == 1){
            delay(10);
            if(digitalRead(ButtonPin) == 1){
            //beep on
            printf("Buzzer on\n");
            digitalWrite(BeepPin, HIGH);
            delay(100);
            }
        }
        else{
            printf("Buzzer off\n");
            //beep off
            digitalWrite(BeepPin, LOW);
            delay(100);
        }
    }
    return 0;
}
Code Explanation
20.            delay(10);

Software removes button jitter. When the signal that the button is pressed is detected, a delay of 10ms is used to eliminate the possibility of false judgment. If both if conditions are met, confirm that the button is pressed, and then execute the program in if.

21.            if(digitalRead(ButtonPin) == 1){
22.            //beep on
23.            printf("Buzzer on\n");
24.            digitalWrite(BeepPin, HIGH);
25.            delay(100);
26.            }

If the button is recognized to be pressed, the BeepPin is at high level. The base pin(b pin) of the connected transistor inputs high level, while the collector pin(c pin) outputs low level. That is, the cathode of buzzer is at low level, and the anode is connected with a high level 5V. Then the buzzer rings.

28.        else{
29.            printf("Buzzer off\n");
30.            //beep off
31.            digitalWrite(BeepPin, LOW);
32.            delay(100);
33.        }

Otherwise, BeepPin is at low level, and the base pin(b pin) of the connected transistor inputs low level, then the collector pin(c pin) outputs high level; that is, the level at both ends of the buzzer is high, and the buzzer does not ring.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 11_DoorBell.py

When the button is pressed, the buzzer makes a sound to simulate a doorbell.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

BeepPin = 17
BtnPin = 27

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BtnPin, GPIO.IN)
    GPIO.setup(BeepPin, GPIO.OUT, initial=GPIO.LOW)

def main():
    while True:
        if GPIO.input(BtnPin) == 0:
            #Buzzer off
            print ('Buzzer Off')
            GPIO.output(BeepPin, GPIO.LOW)
            time.sleep(0.1)
        if GPIO.input(BtnPin) == 1:
            #Buzzer on
            print ('Buzzer On')
            GPIO.output(BeepPin, GPIO.HIGH)
            time.sleep(0.1)

def destroy():
    # Turn off buzzer
    GPIO.output(BeepPin, GPIO.LOW)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
14.        if GPIO.input(BtnPin) == 0:
15.            #Buzzer off
16.            print ('Buzzer Off')
17.            GPIO.output(BeepPin, GPIO.LOW)
18.            time.sleep(0.1)

If it is judged that the button is not pressed, BeepPin is at low level, and the base pin(b pin) of the connected transistor inputs low level, then the collector pin(c pin) outputs high level; that is, when the level at both ends of the connected buzzer is high, the buzzer does not ring.

19.        if GPIO.input(BtnPin) == 1:
20.            #Buzzer off
21.            print ('Buzzer On')
22.            GPIO.output(BeepPin, GPIO.HIGH)
23.             time.sleep(0.1)

If the button is recognized to be pressed, the BeepPin is at high level. The base pin(b pin) of the connected transistor inputs high level, while the collector pin(c pin) outputs low level. That is, the cathode of buzzer is at low level, and the anode is connected with a high level 5V. Then the buzzer rings.

Phenomenon Picture
_images/image145.jpeg
Lesson 12 Passive Buzzer
Introduction

In this lesson, we will learn how to make a passive buzzer to play music.

Newly Added Components
_images/image227.png
Schematic Diagram

The base pin(b pin) of the transistor is connected to pin11, the collector pin(c pin) to the cathode pin of the buzzer, and the emitter pin(e pin) to GND. The anode of the buzzer is connected to 5 v power supply. When pin11 inputs high voltage, the transistor will be switched on, and the collector will output low level. When there is a level difference between the two pins of the buzzer, the buzzer rings. When pin11 inputs low power level, the transistor is cut off, and the collector is at high level, and both ends of the buzzer are at high level, so the buzzer is silent.

_images/image228.png _images/image256.png
Build the Circuit
_images/image147.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_12_PassiveBuzzer

2. Compile the code.

gcc 12_PassiveBuzzer.c -lwiringPi

3. Run the executable file.

sudo ./a.out

Now, the buzzer automatically plays music on a loop.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <softTone.h>
#include <stdio.h>

#define BuzPin    0

#define  CM1  262
#define  CM2  294
#define  CM3  330
#define  CM4  350
#define  CM5  393
#define  CM6  441
#define  CM7  495

#define  CH1  525
#define  CH2  589
#define  CH3  661
#define  CH4  700
#define  CH5  786
#define  CH6  882
#define  CH7  990

int song[] = {CH5,CH2,CM6,CH2,CH3,CH6,0,CH3,CH5,CH3,CM6,CH2,0};
int beat[] = {1,1,1,1,1,1,2,1,1,1,1,1,3};

int main(void)
{
    int i, j;

    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    if(softToneCreate(BuzPin) == -1){
        printf("setup softTone failed !");
        return 1;
    }

    while(1){
        printf("music is being played...\n");
        for(int i=0;i<sizeof(song)/4;i++){
            softToneWrite(BuzPin, song[i]);
            delay(beat[i] * 250);
        }
    }
    return 0;
}
Code Explanation
#include <softTone.h>

WiringPi includes a software-driven sound handler capable of outputting a simple tone/square wave signal on any of the Raspberry Pi’s GPIO pins. To maintain a low CPU usage, the minimum pulse width is 100μS. That gives a maximum frequency of 1/0.0002 = 5000Hz. Within these limitations, simple tones on a high impedance speaker or piezo sounder is possible.

#define  CM1  262
#define  CM2  294
#define  CM3  330
#define  CM4  350
#define  CM5  393
#define  CM6  441
#define  CM7  495

These frequencies of each note are as shown. CM refers to middle note, CH high note, 1-7 correspond to the notes C, D, E, F, G, A, B.

23.int song[] = {CH5,CH2,CM6,CH2,CH3,CH6,0,CH3,CH5,CH3,CM6,CH2,0};
24.int beat[] = {1,1,1,1,1,1,2,1,1,1,1,1,3};

Define a section of music and the corresponding beat. The number in beat[] refers to the beat of each note in the song (0.5s for each beat).

35.    if(softToneCreate(BuzPin) == -1){

softToneCreate( ) creates a software controlled tone pin. You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used. The return value is 0 for success. This is used to determine whether it is successful for the software to control tone pin; if it fails, it will not execute the program.

42.        for(int i=0;i<sizeof(song)/4;i++){
43.            softToneWrite(BuzPin, song[i]);
44.            delay(beat[i] * 250);
45.        }

Employ a for statement to play song_1.In the judgment condition, i<sizeof(song_1)/4,”devide by 4” is used because the array song_1[] is an array of the data type of integer, and each element takes up four bytes.

The number of elements in song (the number of musical notes) is gotten by deviding sizeof(song) by 4.

To enable each note to play for beat * 500ms, the function delay(beat_1[i] * 500) is called.

The prototype of softToneWrite(BuzPin, song_1[i]):

void softToneWrite (int pin, int freq);

This updates the tone frequency value on the given pin. The tone does not stop playing until you set the frequency to 0.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 12_PassiveBuzzer.py

Now, the buzzer automatically plays music on a loop.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

Buzzer = 17

CL = [0, 131, 147, 165, 175, 196, 211, 248]        # Frequency of Low C notes
CM = [0, 262, 294, 330, 350, 393, 441, 495]        # Frequency of Middle C notes
CH = [1, 525, 589, 661, 700, 786, 882, 990]        # Frequency of High C notes

song = [    CH[5], CH[2], CM[6], CH[2], CH[3], CH[6],CH[0], CH[3], # Notes of song
            CH[5], CH[3], CM[6], CH[2],CH[0]]

beat = [    1,1,1,1,1,1,2,1,1,1,1,1,3    ]

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(Buzzer, GPIO.OUT)
    global Buzz



def loop():
    while True:
        print ('\n    Playing song...')
        for i in range(1, len(song)):
            if  song[i] == 1 :
                time.sleep(beat[i] *0.25)
            else:
                Buzz = GPIO.PWM(Buzzer, song[i])
                Buzz.start(50)
                time.sleep(beat[i] * 0.25)
                Buzz.stop()
        time.sleep(1)             # Wait a second for next song.

def destory():
    Buzz.stop()
    GPIO.output(Buzzer, LOW)
    GPIO.cleanup()

if __name__ == '__main__':        # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:     # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destory()
Code Explanation
6.CL = [0, 131, 147, 165, 175, 196, 211, 248]
7.CM = [0, 262, 294, 330, 350, 393, 441, 495]
8.CH = [1, 525, 589, 661, 700, 786, 882, 990]

These are the frequencies of each note. The first 0 is to skip CL[0] so that the number CL[1]-CL[7] corresponds to the CDEFGAB of the note.

10.int song[] = {CH5,CH2,CM6,CH2,CH3,CH6,0,CH3,CH5,CH3,CM6,CH2,0};
13.int beat[] = {1,1,1,1,1,1,2,1,1,1,1,1,3};

Define a section of music and the corresponding beats. The number in beat[] refers to the beat of each note in the song (0.5s for each beat).

29.    Buzz = GPIO.PWM(Buzzer, song[i])
30.    Buzz.start(50)

Define pin Buzzer as PWM pin, then set its frequency to 786(song[0]) and Buzz.start(50) is used to run PWM. What’s more, set the duty cycle to 50%.

22. def loop():
23.    while True:
24.        print ('\n    Playing song...')
25.        for i in range(1, len(song)):
26.            if  song[i] == 1 :
27.                time.sleep(beat[i] *0.25)
28.            else:
29.                Buzz = GPIO.PWM(Buzzer, song[i])
30.                Buzz.start(50)
31.                time.sleep(beat[i] * 0.25)
32.                Buzz.stop()
33.   time.sleep(1)

Play music in the while loop. As i increases gradually, the buzzer plays following the note in song[].

Phenomenon Picture
_images/image148.jpeg
Lesson 13 Button Piano
Introduction

In our past lesson, we learned how to use PWM waves to drive a passive buzzer to ring. In this lesson, we make a simple keyboard by applying a passive buzzer. Let’s get started!

Newly Added Components
_images/image229.png
Schematic Diagram
_images/image230.png _images/image257.png
Build the Circuit
_images/image231.png _images/image150.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_13_Button_Piano

2. Compile the code.

gcc 13_ButtonPiano.c -lwiringPi

3. Run the executable file.

sudo ./a.out

Now press the seven buttons, and the buzzer will emit the notes: DO, RE, MI, FA, SO, LA, TI. You can play a song with these seven buttons.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <softTone.h>
#include <stdio.h>

#define BuzPin    0

const int Tone[] = {262,294,330,350,393,441,495};//define DO, RE, MI, FA, SO, LA, TI
int beat[] = {1,1,1,1,1,1,1};
const int Btn[] = {2,3,4,5,6,10,11};//define 7 buttons

int main(void)
{
    int i, j;

    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    if(softToneCreate(BuzPin) == -1){
        printf("setup softTone failed !");
        return 1;
    }

    //set the buttons mode
    for(int j=0;j<7;j++)
    {
        pinMode(Btn[j], INPUT);
    }

    while(1){
        //printf("Please press button to play the piano\n");
        // Indicate that button has pressed down
        for(i=0;i<7;i++)
        {
            if(digitalRead(Btn[i])==1)
            {
                delay(10);//Prevent the button' s vibration
                if(digitalRead(Btn[i])==1)
                {
                    softToneWrite(BuzPin, Tone[i]);
                    delay(beat[i]*250);
                    printf("1");
                }
            }
            else
                softToneWrite(BuzPin, 0);
            if(i==7)
                i=0;
        }
    }
    return 0;
}
Code Explanation
7.  const int Tone[] = {262,294,330,350,393,441,495};
8.  int beat[] = {1,1,1,1,1,1,1};

In the array Tone[], define the frequencies of DO, RE, MI, FA, SO, LA, TI and the number in beat[] refers to the beat of each note in this song(0.5s for each beat).

26.    for(int j=0;j<7;j++)
27.    {
28.        pinMode(Btn[j], INPUT);
29.    }

Set the mode of all buttons to input mode in the for loop.

34.        for(i=0;i<7;i++)
35.        {
36.            if(digitalRead(Btn[i])==1)
37.            {
38.                delay(10);//Prevent the button' s vibration
39.                if(digitalRead(Btn[i])==1)
40.                {
41.                    softToneWrite(BuzPin, Tone[i]);
42.                    delay(beat[i]*250);
43.                    printf("1");
44.                }
45.            }

Use a for loop to check all the buttons. When one button in array Btn[i] is detected to be pressed, the buzzer will respond to the corresponding note in array Tone[i].

46.            else
47.                softToneWrite(BuzPin, 0);
48.            if(i==7)
49.                i=0;
50.        }

If no button is pressed, turn off the buzzer.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 13_ButtonPiano.py

Now press the seven buttons, and the buzzer will emit the notes: DO, RE, MI, FA, SO, LA, TI. You can play a song with these seven buttons.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

Buzzer = 17
BtnPin = [18,27,22,23,24,25,8,7]

CL = [0, 131, 147, 165, 175, 196, 211, 248]        # Frequency of Low C notes
CM = [0, 262, 294, 330, 350, 393, 441, 495]        # Frequency of Middle C notes
CH = [1, 525, 589, 661, 700, 786, 882, 990]        # Frequency of High C notes

song = [     0,CM[1],CM[2],CM[3],CM[4],CM[5],CM[6],CM[7]    ]
beat = [    1,1, 1, 1, 1, 1, 1,  1]

def setup():
    GPIO.setmode(GPIO.BCM)
    for i in range(1, len(BtnPin)):
        GPIO.setup(BtnPin[i],GPIO.IN)
    GPIO.setup(Buzzer, GPIO.OUT)

def loop():
    global Buzz
    while True:
        #print ('\n    Please playing piano...')
        for i in range(1, len(BtnPin)):
            if GPIO.input(BtnPin[i]) == 1:
                Buzz = GPIO.PWM(Buzzer, song[i])
                Buzz.start(50)
                time.sleep(beat[i] * 0.25)
                Buzz.stop()

def destory():
    Buzz.stop()
    GPIO.output(Buzzer, 0)
    GPIO.cleanup()

if __name__ == '__main__':        # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:      # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destory()
Code Explanation
7.CL = [0, 131, 147, 165, 175, 196, 211, 248]        # Frequency of Low C notes
8.CM = [0, 262, 294, 330, 350, 393, 441, 495]        # Frequency of Middle C notes
9.CH = [1, 525, 589, 661, 700, 786, 882, 990]        # Frequency of High C notes

These are the frequencies of each note. The first 0 is to skip CL[0] so that the number CL[1]-CL[7] corresponds to the CDEFGAB of the note.

10.song = [     0,CM[1],CM[2],CM[3],CM[4],CM[5],CM[6],CM[7]    ]
11.beat = [    1,1, 1, 1, 1, 1, 1,  1]

Define a section of music and the corresponding beats. The number in beat[] refers to the beat of each note in the song(0.5s for each beat).

16.   for i in range(1, len(BtnPin)):
17.        GPIO.setup(BtnPin[i],GPIO.IN)

Set the mode of all buttons to input mode in the for loop.

24.        for i in range(1, len(BtnPin)):
25.            if GPIO.input(BtnPin[i]) == 1:
26.                Buzz = GPIO.PWM(Buzzer, song[i])
27.                Buzz.start(50)
28.                time.sleep(beat[i] * 0.25)
29.                Buzz.stop()

Use a for loop to check all the buttons. When one button in array button[i] is detected to be pressed, the buzzer will respond to the corresponding note in array song[i].

Phenomenon Picture
_images/image151.jpeg
Lesson 14 Quiz Buzzer System
Introduction

In quiz shows, especially entertainment activities (e.g. competitive answering activities), organizers often apply a quiz buzzer system in order to accurately, fairly and visually determine the seat number of a responder. In this lesson, we will use some buttons, buzzers, and LEDs to make a quiz buzzer system.

Newly Added Components
_images/image232.png
Schematic Diagram

Button 2, 3 and 4 are answer buttons, and button 1 is the reset button. If button 2 is pressed first, the buzzer will beep, the corresponding LED will light up and all the other LEDs will go out. If you want to start another round, press button 1 to reset.

_images/image233.png _images/image258.png
Build the Circuit
_images/image156.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_14_AnswerMachine

2. Compile the code.

gcc 14_AnswerMachine.c -lwiringPi

3. Run the executable file.

sudo ./a.out

Now, first press button 4 to get started. If you press button 1 first, you will see the corresponding LED light up and the buzzer will beep. Then press button 4 again to reset before you press other buttons.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code

#include <wiringPi.h>
#include <stdio.h>

#define BeepPin 0
#define ResetBtnPin 1
const int BtnPin[] = {2,3,4};
const int LedPin[] = {21,22,23,24};

void Alarm()
{
    for(int i=0;i<50;i++){
    digitalWrite(BeepPin,HIGH); //the buzzer sound
    delay(2); //delay 2ms
    digitalWrite(BeepPin,LOW);  //without sound
    delay(2);
  }
}

int main(void){
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(BeepPin, OUTPUT);
    for(int j=1;j<4;j++)
    {
        pinMode(LedPin[j], OUTPUT);
        digitalWrite(LedPin[j],LOW);
    }
    pinMode(LedPin[0], OUTPUT);
    digitalWrite(LedPin[0],HIGH);
    for(int k;k<3;k++)
    {
        pinMode(BtnPin[k], INPUT);
    }

    int flag = 1;

    while(1){
        // if reset button is pressed
        if(digitalRead(ResetBtnPin) == 1)
        {
            flag = 1;
            digitalWrite(LedPin[0], HIGH);//Reset Led turns on
            digitalWrite(LedPin[1],LOW);
            digitalWrite(LedPin[2],LOW);
            digitalWrite(LedPin[3],LOW);
        }
        if(flag==1)
        {
            //If the button1 press the first
            if(digitalRead(BtnPin[0]) == 1)
            {
                flag = 0;
                digitalWrite(LedPin[0],LOW);
                Alarm();  //buzzer sound
                digitalWrite(LedPin[1],HIGH);//turn the LED1 on only
                digitalWrite(LedPin[2],LOW);
                digitalWrite(LedPin[3],LOW);
                while(digitalRead(ResetBtnPin));
            }
            if(digitalRead(BtnPin[1]) == 1)
            {
                flag = 0;
                digitalWrite(LedPin[0],LOW);
                Alarm();  //buzzer sound
                digitalWrite(LedPin[1],LOW);
                digitalWrite(LedPin[2],HIGH);//turn the LED2 on only
                digitalWrite(LedPin[3],LOW);
                while(digitalRead(ResetBtnPin));
            }
            if(digitalRead(BtnPin[2]) == 1)
            {
                flag = 0;
                digitalWrite(LedPin[0],LOW);
                Alarm();  //buzzer sound
                digitalWrite(LedPin[1],LOW);
                digitalWrite(LedPin[2],LOW);
                digitalWrite(LedPin[3],HIGH);//turn the LED3 on only
                while(digitalRead(ResetBtnPin));
            }
        }
    }
    return 0;
}
Code Explanation
9. void Alarm()
10.{
11.    for(int i=0;i<50;i++){
12.    digitalWrite(BeepPin,HIGH); //the buzzer sound
13.    delay(2);
14.    digitalWrite(BeepPin,LOW);  //without sound
15.    delay(2);
16.  }
17.}

Define a function to control the buzzer. The buzzer rings when this function is called in the main function.

38.    int flag = 1;

Define a flag to judge whether the answer device is in the state of answering. When flag = 0, it indicates that someone is currently scrambling, and others cannot continue to answer first; when flag = 1, it means that the reset button has been pressed, and a new round of answer rush can be conducted.

42.        if(digitalRead(ResetBtnPin) == 1)
43.        {
44.            flag = 1;
45.            digitalWrite(LedPin[0], HIGH);//Reset Led turns on
46.            digitalWrite(LedPin[1],LOW);
47.            digitalWrite(LedPin[2],LOW);
48.            digitalWrite(LedPin[3],LOW);
49.        }

If the reset button is detected to have been pressed, it means that the answer begins. Now set flag to 1 and let the referee LED light up, the rest of the LED lights out.

53.            if(digitalRead(BtnPin[0]) == 1)
54.            {
55.                flag = 0;
56.                digitalWrite(LedPin[0],LOW);
57.                Alarm();  //buzzer sound
58.                digitalWrite(LedPin[1],HIGH);//turn the LED1 on only
59.                digitalWrite(LedPin[2],LOW);
60.                digitalWrite(LedPin[3],LOW);
61.                while(digitalRead(ResetBtnPin));
62.            }

In the process of quick answering, if the first button is recognized to have been pressed, the flag is set to 0, and then no other buttons are detected. At this time, the buzzer alarms, indicating that someone has successfully responsed, and the corresponding LED lights up. The identification codes of the remaining buttons are explained as above.

61.                    while(digitalRead(ResetBtnPin));

Having executed the instruction of successful quick answer, it enters the loop to judge whether the button reset is pressed. Here, if the button reset is pressed, then the next round of quickfire answering begins.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 14_AnswerMachine.py

Now, first press button 4 to get started. If you press button 1 first, you will see the corresponding LED light up and the buzzer will beep. Then press button 4 again to reset before you press other buttons.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

BeepPin = 17
ResetBtnPin = 18
BtnPin =(27,22,23)
LedPin =(5,6,13,19)

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BeepPin, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(ResetBtnPin, GPIO.IN)
    GPIO.setup(LedPin[0], GPIO.OUT, initial=GPIO.HIGH)
    for i in range(1,4):
        GPIO.setup(LedPin[i], GPIO.OUT, initial=GPIO.LOW)
    for i in range(0,3):
        GPIO.setup(BtnPin[i], GPIO.IN)

def Alarm():
    for i in range(0,50):
        GPIO.output(BeepPin,GPIO.HIGH)
        time.sleep(0.003)
        GPIO.output(BeepPin,GPIO.LOW)
        time.sleep(0.003)

def loop():
    flag = 1
    while True:
        if GPIO.input(ResetBtnPin) == 1:
            flag = 1
            GPIO.output(LedPin[0],GPIO.HIGH)
            GPIO.output(LedPin[1],GPIO.LOW)
            GPIO.output(LedPin[2],GPIO.LOW)
            GPIO.output(LedPin[3],GPIO.LOW)
        if flag == 1:
            if GPIO.input(BtnPin[0]) == 1:
                flag = 0
                GPIO.output(LedPin[0],GPIO.LOW)
                Alarm()
                GPIO.output(LedPin[1],GPIO.HIGH)
                GPIO.output(LedPin[2],GPIO.LOW)
                GPIO.output(LedPin[3],GPIO.LOW)
            elif GPIO.input(BtnPin[1]) == 1:
                flag = 0
                GPIO.output(LedPin[0],GPIO.LOW)
                Alarm()
                GPIO.output(LedPin[1],GPIO.LOW)
                GPIO.output(LedPin[2],GPIO.HIGH)
                GPIO.output(LedPin[3],GPIO.LOW)
            elif GPIO.input(BtnPin[2]) == 1:
                flag = 0
                GPIO.output(LedPin[0],GPIO.LOW)
                Alarm()
                GPIO.output(LedPin[1],GPIO.LOW)
                GPIO.output(LedPin[2],GPIO.LOW)
                GPIO.output(LedPin[3],GPIO.HIGH)

def destroy():
    # Turn off buzzer
    GPIO.output(BeepPin, GPIO.LOW)
    GPIO.output(LedPin[0],GPIO.LOW)
    GPIO.output(LedPin[1],GPIO.LOW)
    GPIO.output(LedPin[2],GPIO.LOW)
    GPIO.output(LedPin[3],GPIO.HIGH)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        loop()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
Code Explanation
19.def Alarm():
20.    for i in range(0,50):
21.        GPIO.output(BeepPin,GPIO.HIGH)
22.        time.sleep(0.003)
23.        GPIO.output(BeepPin,GPIO.LOW)
24.        time.sleep(0.003)

Define a function to control the buzzer. The buzzer rings when this function is called in the function main.

27.    flag = 1

Define a flag bit to judge whether the responder is in the state of answering. When flag = 0, it indicates that someone is currently scrambling, and others cannot continue to answer first; when flag = 1, it means that the reset button has been pressed, and a new round of answer rush can be conducted.

29.        if GPIO.input(ResetBtnPin) == 1:
30.            flag = 1
31.            GPIO.output(LedPin[0],GPIO.HIGH)
32.            GPIO.output(LedPin[1],GPIO.LOW)
33.            GPIO.output(LedPin[2],GPIO.LOW)
34.            GPIO.output(LedPin[3],GPIO.LOW)

If the recognition that reset button has been pressed is done, it means that answer begins. Now, set flag to 1, and let the referee LED light up, other LEDs light out.

36.            if GPIO.input(BtnPin[0]) == 1:
37.                flag = 0
38.                GPIO.output(LedPin[0],GPIO.LOW)
39.                Alarm()
40.                GPIO.output(LedPin[1],GPIO.HIGH)
41.                GPIO.output(LedPin[2],GPIO.LOW)
42.                GPIO.output(LedPin[3],GPIO.LOW)

In the process of quick answering, if the first button is recognized to have been pressed, the flag is set to 0, and then no other buttons are detected. At this time, the buzzer alarms, indicating that there is a successful response, and the corresponding LED lights up. The identification codes of the remaining buttons are explained as above.

Phenomenon Picture
_images/image157.jpeg
Lesson 15 NE555 Timer
Introduction

The NE555 Timer, a mixed circuit composed of analog and digital circuits, integrates analog and logical functions into an independent IC, thus tremendously expanding the applications of analog integrated circuits. It is widely used in various timers, pulse generators, and oscillators. In this experiment, the Raspberry Pi is used to test the frequencies of square waves generated by the 555 oscillating circuit and show them on terminal windows.

Newly Added Components
_images/image235.png
Principle

Potentiometer

_images/image236.png

Potentiometer is also a resistance component with 3 terminals and its resistance value can be adjusted according to some regular variation. Potentiometer usually consists of resistor and movable brush. When the brush is moving along the resistor, there is a certain resistance or voltage output depending on the displacement.

The functions of the potentiometer in the circuit are as follows:

1.Serving as a voltage divider Potentiometer is a continuously adjustable resistor. When you adjust the shaft or sliding handle of the potentiometer, the movable contact will slide on the resistor. At this point, a voltage can be output depending on the voltage applied onto the potentiometer and the angle the movable arm has rotated to or the distance it moves.

2.Serving as a rheostat When the potentiometer is used as a rheostat, connect the middle pin and one of the other 2 pins in the circuit. Thus you can get a smoothly and continuously changed resistance value cused by moving contact.

3.Serving as a current controller When the potentiometer acts as a current controller, the sliding contact terminal must be connected as one of the output terminals.

555 IC

The 555 IC was originally used as a timer, hence the name 555 time base circuit. It is now widely used in various electronic products because of its reliability, convenience, and low price. The 555 is a complex hybrid circuit with dozens of components such as a divider, comparator, basic R-S trigger, discharge tube, and buffer.

Pins and functions:

_images/image162.png

As shown in the picture, the pins are set dual in-line with the 8-pin package.

  • Pin 1 (GND): the ground

  • Pin 2 (TRIGGER): when the voltage at the pin reduces to 1/3 of the VCC (or the threshold defined by the control board), the output terminal sends out a High level

  • Pin 3 (OUTPUT): outputs High or Low, two states 0 and 1 decided by the input electrical level; maximum output current approx. 200mA at High

  • Pin 4 (RESET): when a Low level is received at the pin, the timer will be reset and the output will return to Low level; usually connected to positive pole or neglected

  • Pin 5 (CONTROL VOLTAGE): to control the threshold voltage of the chip (if it skips connection, by default, the threshold voltage is 1/3 VCC and 2/3 VCC)

  • Pin 6 (THRESHOLD): when the voltage at the pin increases to 2/3 VCC (or the threshold defined by the control board), the output terminal sends out a High level.

  • Pin 7 (DISCHARGE): output synchronized with Pin 3, with the same logical level; but this pin does not output current, so pin 3 is the real High (or Low) when pin 7 is the virtual High (or Low); connected to the open collector (OC) inside to discharge the capacitor.

  • Pin 8 (VCC): positive terminal for the NE555 timer IC, ranging +4.5V to +16V

The NE555 timer works under the monostable, astable and bistable modes. In this experiment, apply it under the astable mode, which means it works as an oscillator, as shown below:

Cap

_images/image163.jpeg

A ceramic capacitor is a capacitor that is made of ceramic material and works as a dielectric. It is coated with a metal film on the surface of the ceramic and sintered at a high temperature. The ceramic capacitor is commonly used in high-stability oscillator circuits as loops, bypass capacitors, and pad capacitors. It is a non-polar capacitor, so this capacitor does not need to distinguish between positive and negative during installation.

In the circuit of this lesson, the main function of the ceramic capacitor, high-frequency filtering is to remove some clutter that may occur in the working process of the NE555 chip, so that the waveform is more stable.

Schematic Diagram

Build the circuit according to the following schematic diagram.

_images/image237.png

Working Process:

The oscillator starts to shake once the circuit is power on. During energizing, since the voltage at C1 cannot change abruptly, which means pin 2 is Low level initially, set the timer to 1, so pin 3 is High level. The capacitor C1 charges via R1 and R2 in a time span:

When the voltage at C1 reaches the threshold 2/3Vcc, the timer is reset and pin 3 is Low level. Then C1 discharges via R2 till 2/3Vcc in a time span:

Then the capacitor is recharged and the output voltage flips again:

Build the Circuit
_images/image238.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_15_NE555_Timer

2. Compile the code.

gcc 15_NE555_Timer.c -lwiringPi

3. Run the executable file.

sudo ./a.out

When the code is running, you will see the number of pulses on the display screen and the level of pin3 in NE555 at this time.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <wiringPi.h>

#define  OutPin  1

static volatile int globalCounter = 0 ;

void exInt0_ISR(void)  //GPIO 1 interrupt service routine
{
    ++globalCounter;
}

int main (void)
{
    if(wiringPiSetup() < 0){
        fprintf(stderr, "Unable to setup wiringPi:%s\n",strerror(errno));
        return 1;
    }

    delay(2000);
    pinMode(OutPin,INPUT);
    pullUpDnControl(OutPin,PUD_UP);
    wiringPiISR(OutPin, INT_EDGE_FALLING, &exInt0_ISR);

    while(1){
        printf("Current pluse number is : %d, %d\n", globalCounter,digitalRead(OutPin));
        delay(100);
    }
    return 0;
}
Code Explanation
9.static volatile int globalCounter = 0 ;

Define a variable to record the number of pulses, and initialize the number of pulses to 0.

11.void exInt0_ISR(void)
12.{
13.    ++globalCounter;
14.}

Set an external interrupt function and globalCounter will automatically +1 when an interrupt occurs.

24. pinMode(OutPin,INPUT);
25. pullUpDnControl(OutPin,PUD_UP);

Set the out pin of NE555 to INPUT mode, then let the pin be in pull-up state (1).

26.  wiringPiISR(OutPin, INT_EDGE_FALLING, &exInt0_ISR);

Set an interrupt in OutPin, when the value of OutPin changes from 1 to 0. Then call the exInt0_ISR() function to let the variable globalCounter add 1.

29.    printf("Current pluse number is : %d, %d\n", globalCounter,digitalRead(OutPin));

Print out the number of pulses, globalCounter and the value of OutPin at this time.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 15_NE555.py

When the code is running, you can see the number of pulses on the display.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

SigPin = 18

g_count = 0

def count(ev=None):
    global g_count
    g_count += 1

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(SigPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.add_event_detect(SigPin, GPIO.RISING, callback=count) # wait for rasing

def main():
    while True:
        print ('g_count = %d' % g_count)
        time.sleep(0.01)

def destroy():
    GPIO.cleanup()    # Release resource

if __name__ == '__main__':     # Program start from here
    setup()
    try:
        main()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()
Code Explanation
6. g_count = 0

Define a variable to record the number of pulses, and initialize the number of pulses to 0.

7.def count(ev=None):
8.global g_count
9.g_count += 1

This function will change the value of the global variable g_count.

14.      GPIO.setup(SigPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

Set the SigPin to input mode and pull up to high level(3.3V).

15.  GPIO.add_event_detect(SigPin, GPIO.RISING, callback=count)

Set an interrupt in SigPin, when the value of SigPin changes from 0 to 1. Then call the count() function to let the variable g_count add 1.

18.    while True:
19.        print ('g_count = %d' % g_count)
20.        time.sleep(0.01)

Print out the value of the number of pulse g_count at an interval of 0.01s.

Phenomenon Picture
_images/image166.jpeg
Lesson 16 Servo
Introduction

Servo is a type of geared motor that can only rotate 180 degrees. It is controlled by sending electrical pulses from your board. These pulses tell the servo what position it should move to.

A servo has three wires: the brown wire is GND, the red one is VCC, and the orange one is signal line.

Newly Added Components
_images/image266.png
Principle

Servo

A servo is generally composed of the following parts: case, shaft, gear system, potentiometer, DC motor, and embedded board.

_images/image168.png

It works like this: The microcontroller sends out PWM signals to the servo, and then the embedded board in the servo receives the signals through the signal pin and controls the motor inside to turn. As a result, the motor drives the gear system and then motivates the shaft after deceleration. The shaft and potentiometer of the servo are connected together. When the shaft rotates, it drives the potentiometer, so the potentiometer outputs a voltage signal to the embedded board. Then the board determines the direction and speed of rotation based on the current position, so it can stop exactly at the right position as defined and hold there.

_images/image269.png

The angle is determined by the duration of a pulse that is applied to the control wire. This is called Pulse width Modulation. The servo expects to see a pulse every 20 ms. The length of the pulse will determine how far the motor turns. For example, a 1.5ms pulse will make the motor turn to the 90 degree position (neutral position).

When a pulse is sent to a servo that is less than 1.5 ms, the servo rotates to a position and holds its output shaft some number of degrees counterclockwise from the neutral point. When the pulse is wider than 1.5 ms the opposite occurs. The minimal width and the maximum width of pulse that will command the servo to turn to a valid position are functions of each servo. Generally the minimum pulse will be about 0.5 ms wide and the maximum pulse will be 2.5 ms wide.

_images/image170.jpeg
Schematic Diagram
_images/image240.png
Build the Circuit

Note: Connect the brown to GND, Red to VCC, Orange to pin12 of the control board.

_images/image172.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_16_Servo

2. Compile the code.

gcc 16_Servo.c -lwiringPi

3. Run the executable file.

sudo ./a.out

After the program is executed, the servo will rotate from 0 degrees to 180 degrees, and then from 180 degrees to 0 degrees, circularly.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <softPwm.h>
#include <stdio.h>

#define ServoPin    1
long Map(long value,long fromLow,long fromHigh,long toLow,long toHigh){
    return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow;
}
void setAngle(int pin, int angle){    //Specif a certain rotation angle (0-180) for the servo
    if(angle < 0)
        angle = 0;
    if(angle > 180)
        angle = 180;
    softPwmWrite(pin,map(angle,0,180,5,25));
}

int main(void)
{
    int i;

    if(wiringPiSetup() == -1){ //when initialize wiring faiservo,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }
    softPwmCreate(servoPin,  0, 200);       //initialize PMW pin of servo
    while(1){
        for(i=0;i<181;i++){
            setAngle(ServoPin,i);
            delay(1);
        }
        delay(500);
        for(i=181;i>-1;i--){
            setAngle(ServoPin,i);
            delay(1);
        }
        delay(500);
    }
    return 0;
}
Code Explanation
6.long Map(long value,long fromLow,long fromHigh,long toLow,long toHigh){
7.    return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow;
8.}

Create a map() function to map value in the following code.

9.void setAngle(int pin, int angle){    //Specif a certain rotation angle (0-180) for the servo
10.    if(angle < 0)
11.        angle = 0;
12.    if(angle > 180)
13.        angle = 180;
14.    softPwmWrite(pin,map(angle,0,180,5,25));
15.}

Define a function to limit the angle of the servo to 0 to 180 in order to set the angle of servo.

softPwmWrite(pin,map(angle,0,180,5,25));

This function can change the duty cycle of the PWM pin.

To make the servo rotate to 0 ~ 180 °, the pulse width should change within the range of 0.5ms ~ 2.5ms when the period is 20ms; in the function, softPwmCreate(), we have set that the period is 200x100us=20ms, thus we need to map 0 ~ 180 to 5x100us ~ 25x100us.

25.    softPwmCreate(ServoPin,  0, 200);

The function is to use softwares to create a PWM pin, servoPin, then the initial pulse widths of them are set to 0, and the period of PWM is 200 x100us.

27.        for(i=0;i<181;i++){
28.            setAngle(ServoPin,i);
29.            delay(1);
30.        }

In a for loop, we want servo to rotate from 0 degrees to 180 degrees.

32.        for(i=181;i>-1;i--){
33.            setAngle(ServoPin,i);
34.            delay(1);
35.        }

In a for loop, we want servo to rotate from 180 degrees to 0 degrees.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 16_Servo.py

After the program is executed, the servo will rotate from 0 degrees to 180 degrees, and then from 180 degrees to 0 degrees, circularly.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

SERVO_MIN_PULSE = 500
SERVO_MAX_PULSE = 2500

ServoPin = 18

def map(value, inMin, inMax, outMin, outMax):
    return (outMax - outMin) * (value - inMin) / (inMax - inMin) + outMin

def setup():
    global p
    GPIO.setmode(GPIO.BCM)       # Numbers GPIOs by BCM
    GPIO.setup(ServoPin, GPIO.OUT)   # Set ServoPin's mode is output
    GPIO.output(ServoPin, GPIO.LOW)  # Set ServoPin to low
    p = GPIO.PWM(ServoPin, 50)     # set Frequecy to 50Hz
    p.start(0)                     # Duty Cycle = 0

def setAngle(angle):      # make the servo rotate to specific angle (0-180 degrees)
    angle = max(0, min(180, angle))
    pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
    pwm = map(pulse_width, 0, 20000, 0, 100)
    p.ChangeDutyCycle(pwm)#map the angle to duty cycle and output it

def loop():
    while True:
        for i in range(0, 181, 5):   #make servo rotate from 0 to 180 deg
            setAngle(i)     # Write to servo
            time.sleep(0.002)
        time.sleep(1)
        for i in range(180, -1, -5): #make servo rotate from 180 to 0 deg
            setAngle(i)
            time.sleep(0.001)
        time.sleep(1)

def destroy():
    p.stop()
    GPIO.cleanup()

if __name__ == '__main__':     #Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destroy()
Code Explanation
9.def map(value, inMin, inMax, outMin, outMax):
10.    return (outMax - outMin) * (value - inMin) / (inMax - inMin) + outMin

Create a map() function to map value in the following code.

17.  p = GPIO.PWM(ServoPin, 50)
18.  p.start(0)

Set the servoPin to PWM pin, then the frequency to 50 hz, and the period to 20ms. p.start(0): Run the PWM function,and set the initial value to 0.

20.def setAngle(angle):      # make the servo rotate to specific angle (0-180 degrees)
21.    angle = max(0, min(180, angle))
22.    pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
23.    pwm = map(pulse_width, 0, 20000, 0, 100)
24.    p.ChangeDutyCycle(pwm)#map the angle to duty cycle and output it

Create a function, setAngle() to write angle that ranges from 0 to 180 into the servo.

24.p.ChangeDutyCycle(pwm)

This function can change the duty cycle of the PWM. To render a range 0 ~ 180° to the servo, the pulse width of the servo is set to 0.5ms-2.5ms.

In the previous codes, the period of PWM was set to 20ms, thus the duty cycle of PWM is (0.5/20)%-(2.5/20)%, and the range 0 ~ 180 is mapped to 2.5 ~ 12.5.

28.        for i in range(0, 181, 5):   #make servo rotate from 0 to 180 deg
29.            setAngle(i)     # Write to servo
30.            time.sleep(0.002)

In a for loop, we want servo to rotate from 0 degrees to 180 degrees.

32.        for i in range(180, -1, -5): #make servo rotate from 180 to 0 deg
33.            setAngle(i)
34.            time.sleep(0.001)

In a for loop, we want servo to rotate from 180 degrees to 0 degrees.

Phenomenon Picture
_images/image173.jpeg
Lesson 17 LCD1602
Introduction

In this lesson, we will learn how to use an LCD1602 to display characters and strings. LCD1602, or 1602 character-type liquid crystal display, is a kind of dot matrix module to show letters, numbers, and characters and so on. It’s composed of 5x7 or 5x11 dot matrix positions; each position can display one character. Now let’s check more details!

Newly Added Components
_images/image241.png
Principle

Generally, LCD1602 has parallel ports, that is, it would control several pins at the same time. LCD1602 can be categorized into eight-port and four-port connections. If the eight-port connection is used, then all the digital ports of the Raspberry Pi are almost completely occupied. If you want to connect more sensors, there will be no ports available. Therefore, the four-port connection is used here for better application.

_images/image176.png
Pins of LCD1602 and their Functions

VSS: connected to ground.

VDD: connected to a +5V power supply.

VO: to adjust the contrast.

RS: A register select pin that controls where in the LCD’s memory you are writing data to. You can select either the data register, which holds what goes on the screen, or an instruction register, which is where the LCD’s controller looks for instructions on what to do next.

R/W: A Read/Write pin to select between reading and writing mode.

E: An enabling pin that reads the information when High level (1) is received. The instructions are run when the signal changes from High level to Low level.

D0-D7: to read and write data.

A and K: Pins that control the LCD backlight. Connect K to GND and A to 3.3v. Open the backlight and you will see clear characters in a comparatively dark environment.

Schematic Diagram

Connect K to GND and A to 3.3 V, and then the backlight of the LCD1602 will be turned on. Connect VSS to GND and the LCD1602 to the power source. Connect VO to the middle pin of the potentiometer - with it you can adjust the contrast of the screen display. Connect RS to Pin 13 and R/W pin to GND. Connect E to Pin 15 and the characters displayed on the LCD1602 are controlled by D4-D7. For programming, it is optimized by calling function libraries.

_images/image242.png _images/image259.png
Build the Circuit

Note

Make sure the pins are connected correctly. Otherwise, characters will not be displayed properly. You may need to adjust the potentiometer till the LCD1602 can display clearly.

_images/image243.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_17_LCD1602

2. Compile the code.

gcc 17_Lcd1602.c -lwiringPiDev -lwiringPi

Note

In order to use the LCD driver in the wiringPi devLib, you need to use -lwiringPiDev at compile time.

3. Run the executable file.

sudo ./a.out

You may see the “SunFounder” and “hello, world” appear one by one on the LCD.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <lcd.h>

const unsigned char Buf[] = "---SUNFOUNDER---";
const unsigned char myBuf[] = "  sunfounder.com";

int main(void)
{
    int fd;
    int i;

    if(wiringPiSetup() == -1){
        exit(1);
    }

    fd = lcdInit(2,16,4,2,3, 0,0,0,0,6,5,4,1); //see /usr/local/include/lcd.h
    printf("%d", fd);
    if (fd == -1){
        printf("lcdInit 1 failed\n") ;
        return 1;
    }

    delay(1000);
    lcdClear(fd);
    lcdPosition(fd, 0, 0);
    lcdPuts(fd, "Welcome To--->");
    lcdPosition(fd, 0, 1);
    lcdPuts(fd, "sunfounder.com");
    delay(1000);
    lcdClear(fd);

    while(1){
        lcdClear(fd);
        for(i=0; i<16; i++){
            lcdPosition(fd, i, 0);
            lcdPutchar(fd, *(myBuf+i));
            delay(100);
        }
        for(i=0;i<sizeof(Buf)-1;i++){
            lcdPosition(fd, i, 1);
            lcdPutchar(fd, *(Buf+i));
            delay(200);
        }
        delay(500);
    }
    return 0;
}
Code Explanation
#include <lcd.h>

This is a library that integrates lcd1602 functional functions, in which functions are defined such as lcdClear(), lcdPosition(), lcdPuts(), and so on. These functions can be called directly after importing into the library.

18.    fd = lcdInit(2,16,4,2,3, 0,0,0,0,6,5,4,1); //see /usr/local/include/lcd.h
19.    printf("%d", fd);
20.    if (fd == -1){
21.        printf("lcdInit 1 failed\n") ;
22.    return 1;

Initialize the lcd1602. The prototype of lcdInit() is as follows:

int lcdInit (int rows, int cols, int bits, int rs, int strb, int d0, int d1, int d2, int d3, int d4, int d5, int d6, int d7) ;

This is the main initialisation function and must be called before you use any other LCD functions.

Rows and cols are the rows and columns on the display (e.g. 2, 16 or 4,20). Bits is the number of bits wide on the interface (4 or 8). The rs and strb represent the pin numbers of the display RS pin and Strobe (E) pin. The parameters d0 through d7 are the pin numbers of the 8 data pins connected from the Pi to the display. Only the first 4 are used if you are running the display in 4-bit mode.

The return value is the ‘handle’ to be used for all subsequent calls to the lcd library when dealing with that LCD, or -1 to indicate a fault. (Usually incorrect parameters)

26.    lcdClear(fd);

This function is used to clear the lcd screen. After calling this function, all information displayed on the screen will be cleared.

27. lcdPosition(fd, 0, 0);

Set the position of the cursor at row 0 and col 0 (in fact it’s the first line and first column) for subsequent text entry.

The prototype of lcdpostion function is as follows:

lcdPosition (int handle, int x, int y) ;

Set the position of the cursor for subsequent text entry. x is the column and 0 is the left-most edge. y is the line and 0 is the top line.

28.    lcdPuts(fd, "Welcome To--->");

Display “Welcome To—>” at the specified location of LCD1602.

36.        for(i=0; i<16; i++){
37.            lcdPosition(fd, i, 0);
38.            lcdPutchar(fd, *(myBuf+i));
39.            delay(100);
40.        }

Use the lcdPosition() function to place the cursor at col i and row 0(the top line ) for subsequent text entry. Then the characters in the array myBuf [] are displayed one by one to the LCD1602.

* is the address of myBuf, the real address of characters stored in memory. After calling lcdPutchar(fd, *(myBuf+ I)), the program will find the real address of the character, read the information stored in the address, and display it on the LCD screen.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 17_Lcd1602.py

You may see the “SunFounder” and “hello, world” appear one by one on the LCD.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

#!/usr/bin/env python3

from time import sleep

class LCD:
    # commands
    LCD_CLEARDISPLAY                = 0x01
    LCD_RETURNHOME              = 0x02
    LCD_ENTRYMODESET                = 0x04
    LCD_DISPLAYCONTROL              = 0x08
    LCD_CURSORSHIFT                 = 0x10
    LCD_FUNCTIONSET                 = 0x20
    LCD_SETCGRAMADDR                = 0x40
    LCD_SETDDRAMADDR                = 0x80

    # flags for display entry mode
    LCD_ENTRYRIGHT          = 0x00
    LCD_ENTRYLEFT           = 0x02
    LCD_ENTRYSHIFTINCREMENT         = 0x01
    LCD_ENTRYSHIFTDECREMENT         = 0x00

    # flags for display on/off control
    LCD_DISPLAYON           = 0x04
    LCD_DISPLAYOFF          = 0x00
    LCD_CURSORON            = 0x02
    LCD_CURSOROFF           = 0x00
    LCD_BLINKON             = 0x01
    LCD_BLINKOFF            = 0x00

    # flags for display/cursor shift
    LCD_DISPLAYMOVE         = 0x08
    LCD_CURSORMOVE          = 0x00

    # flags for display/cursor shift
    LCD_DISPLAYMOVE         = 0x08
    LCD_CURSORMOVE          = 0x00
    LCD_MOVERIGHT           = 0x04
    LCD_MOVELEFT            = 0x00

    # flags for function set
    LCD_8BITMODE            = 0x10
    LCD_4BITMODE            = 0x00
    LCD_2LINE                       = 0x08
    LCD_1LINE                       = 0x00
    LCD_5x10DOTS            = 0x04
    LCD_5x8DOTS             = 0x00

    def __init__(self, pin_rs=27, pin_e=22, pins_db=[25, 24, 23, 18], GPIO = None):
        # Emulate the old behavior of using RPi.GPIO if we haven't been given
        # an explicit GPIO interface to use
        if not GPIO:
            import RPi.GPIO as GPIO
            self.GPIO = GPIO
            self.pin_rs = pin_rs
            self.pin_e = pin_e
            self.pins_db = pins_db

            self.used_gpio = self.pins_db[:]
            self.used_gpio.append(pin_e)
            self.used_gpio.append(pin_rs)

            self.GPIO.setwarnings(False)
            self.GPIO.setmode(GPIO.BCM)
            self.GPIO.setup(self.pin_e, GPIO.OUT)
            self.GPIO.setup(self.pin_rs, GPIO.OUT)

            for pin in self.pins_db:
                self.GPIO.setup(pin, GPIO.OUT)

        self.write4bits(0x33) # initialization
        self.write4bits(0x32) # initialization
        self.write4bits(0x28) # 2 line 5x7 matrix
        self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor
        self.write4bits(0x06) # shift cursor right

        self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF

        self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS
        self.displayfunction |= self.LCD_2LINE

        """ Initialize to default text direction (for romance languages) """
        self.displaymode =  self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) #  set the entry mode

        self.clear()

    def begin(self, cols, lines):
        if (lines > 1):
            self.numlines = lines
            self.displayfunction |= self.LCD_2LINE
            self.currline = 0

    def home(self):
        self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero
        self.delayMicroseconds(3000) # this command takes a long time!

    def clear(self):
        self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display
        self.delayMicroseconds(3000)        # 3000 microsecond sleep, clearing the display takes a long time

    def setCursor(self, col, row):
        self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ]

        if ( row > self.numlines ):
            row = self.numlines - 1 # we count rows starting w/0

        self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row]))

    def noDisplay(self):
        # Turn the display off (quickly)
        self.displaycontrol &= ~self.LCD_DISPLAYON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def display(self):
        # Turn the display on (quickly)
        self.displaycontrol |= self.LCD_DISPLAYON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def noCursor(self):
        # Turns the underline cursor on/off
        self.displaycontrol &= ~self.LCD_CURSORON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def cursor(self):
        # Cursor On
        self.displaycontrol |= self.LCD_CURSORON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def noBlink(self):
        # Turn on and off the blinking cursor
        self.displaycontrol &= ~self.LCD_BLINKON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def noBlink(self):
        # Turn on and off the blinking cursor
        self.displaycontrol &= ~self.LCD_BLINKON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def DisplayLeft(self):
        # These commands scroll the display without changing the RAM
        self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT)

    def scrollDisplayRight(self):
        # These commands scroll the display without changing the RAM
        self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT);

    def leftToRight(self):
        # This is for text that flows Left to Right
        self.displaymode |= self.LCD_ENTRYLEFT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode);

    def rightToLeft(self):
        # This is for text that flows Right to Left
        self.displaymode &= ~self.LCD_ENTRYLEFT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def autoscroll(self):
        # This will 'right justify' text from the cursor
        self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def noAutoscroll(self):
        # This will 'left justify' text from the cursor
        self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def write4bits(self, bits, char_mode=False):
        # Send command to LCD
        self.delayMicroseconds(1000) # 1000 microsecond sleep
        bits=bin(bits)[2:].zfill(8)
        self.GPIO.output(self.pin_rs, char_mode)
        for pin in self.pins_db:
            self.GPIO.output(pin, False)
        for i in range(4):
            if bits[i] == "1":
                self.GPIO.output(self.pins_db[::-1][i], True)
        self.pulseEnable()
        for pin in self.pins_db:
            self.GPIO.output(pin, False)
        for i in range(4,8):
            if bits[i] == "1":
                self.GPIO.output(self.pins_db[::-1][i-4], True)
        self.pulseEnable()

    def delayMicroseconds(self, microseconds):
        seconds = microseconds / float(1000000)     # divide microseconds by 1 million for seconds
        sleep(seconds)

    def pulseEnable(self):
        self.GPIO.output(self.pin_e, False)
        self.delayMicroseconds(1)           # 1 microsecond pause - enable pulse must be > 450ns
        self.GPIO.output(self.pin_e, True)
        self.delayMicroseconds(1)           # 1 microsecond pause - enable pulse must be > 450ns
        self.GPIO.output(self.pin_e, False)
        self.delayMicroseconds(1)           # commands need > 37us to settle

    def message(self, text):
        # Send string to LCD. Newline wraps to second line
        for char in text:
            if char == '\n':
                self.write4bits(0xC0) # next line
            else:
                self.write4bits(ord(char),True)

    def destroy(self):
        self.GPIO.cleanup(self.used_gpio)

def print_msg():
    print ("========================================")
    print ("|                LCD1602               |")
    print ("|    ------------------------------    |")
    print ("|         D4 connect to BCM25          |")
    print ("|         D5 connect to BCM24          |")
    print ("|         D6 connect to BCM23          |")
    print ("|         D7 connect to BCM18          |")
    print ("|         RS connect to BCM27          |")
    print ("|         CE connect to BCM22          |")
    print ("|          RW connect to GND           |")
    print ("|                                      |")
    print ("|           Control LCD1602            |")
    print ("|                                      |")
    print ("|                            SunFounder|")
    print ("========================================\n")
    print ('Program is running...')
    print ('Please press Ctrl+C to end the program...')
    #input ("Press Enter to begin\n")

def main():
    global lcd
    print_msg()
    lcd = LCD()
    line0 = "  sunfounder.com"
    line1 = "---SUNFOUNDER---"

    lcd.clear()
    lcd.message("Welcome to --->\n  sunfounder.com")
    sleep(3)

    msg = "%s\n%s" % (line0, line1)
    while True:
        lcd.begin(0, 2)
        lcd.clear()
        for i in range(0, len(line0)):
            lcd.setCursor(i, 0)
            lcd.message(line0[i])
            sleep(0.1)
        for i in range(0, len(line1)):
            lcd.setCursor(i, 1)
            lcd.message(line1[i])
            sleep(0.1)
        sleep(1)

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        lcd.clear()
        lcd.destroy()

Note

Because the source code contains so many definitions, we only list few code here. Please download the complete code from the address marked in the document.

Code Explanation
1.     line0 = "  sunfounder.com"
2.     line1 = "---SUNFOUNDER---"

Define 2 lines of characters that will be displayed on the LCD 1602.

1.     lcd.message("Welcome to --->\n  sunfounder.com")

On LCD1602, “Welcome to —>n sunfounder.com” pops up.

1.         lcd.begin(0, 2)

Initializes the LCD screen and specifies the dimensions (width and height) of the display. begin() function needs to be called before any other LCD library commands.

1.         lcd.clear()

This function is used to clear the lcd screen. After calling this function, all information displayed on the screen will be cleared.

1.             lcd.setCursor(i, 0)

Set the position of the cursor at col i and row 0 (the first line) for subsequent text entry.

1.             lcd.message(line0[i])

The characters in the array line0[] will be displayed at the specified location one by one.

Phenomenon Picture
_images/image179.jpeg
Lesson 18 Driving LEDs by 74HC595
Introduction

In this lesson, we will learn how to use 74HC595 to make eight LEDs blink regularly. Now let’s get started!

Newly Added Components
_images/image244.png
Principle

74HC595

The 74HC595 consists of an 8−bit shift register and a storage register with three−state parallel outputs. It converts serial input into parallel output so you can save IO ports of an MCU.

When MR (pin10) is high level and OE (pin13) is low level, data is input in the rising edge of SHcp and goes to the memory register through the rising edge of SHcp. If the two clocks are connected together, the shift register is always one pulse earlier than the memory register. There is a serial shift input pin (Ds), a serial output pin (Q) and an asynchronous reset button (low level) in the memory register. The memory register outputs a Bus with a parallel 8-bit and in three states. When OE is enabled (low level), the data in memory register is output to the bus.

_images/image181.png

Pins of 74HC595 and their Functions:

Q0-Q7: 8-bit parallel data output pins, able to control 8 LEDs or 8 pins of 7-Segment Display directly.

Q7’: Series output pin, connected to DS of another 74HC595 to connect multiple 74HC595s in series.

MR: Reset pin, active at low level;

SHcp: Time sequence input of shift register. On the rising edge, the data in shift register moves successively one bit, i.e. data in Q1 moves to Q2, and so forth. While on the falling edge, the data in shift register remain unchanged.

STcp: Time sequence input of storage register. On the rising edge, data in the shift register moves into memory register.

OE: Output enable pin, active at low level.

DS: Serial data input pin.

VCC: Positive supply voltage.

GND: Ground.

Schematic Diagram

In the experiment MR is connected to 3.3V (HIGH Level) and OE to GND (LOW Level). Therefore, the data is input into the rising edge of SHcp and enters the memory register through the rising edge. In the rising edge of the SHcp, the data in the shift register moves successively one bit in one time, i.e. data in Q1 moves to Q2, and so forth. In the rising edge of STcp, data in the shift register moves into the memory register. All data will be moved to the memory register 8 times. Then the data in the memory register is output to the bus (Q0-Q7).

_images/image245.png _images/image260.png
Build the Circuit

Note

Recognize the direction of the chip according to the concave on it.

_images/image246.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_18_Driving_Leds_by_74hc595

2. Compile the code.

gcc 18_74hc595.c -lwiringPi

3. Run the executable file.

sudo ./a.out

As the code runs, you can see these eight LEDs are lit up from left to right, and then all LEDs light up and flash 3 times. After that, these eight LEDs are lit from right to left, then they all turn on before flashing 3 times. This loop continues in this way.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define   SDI   0   //serial data input
#define   RCLK  1   //memory clock input(STCP)
#define   SRCLK 2   //shift register clock input(SHCP)

unsigned char LED[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

void pulse(int pin){
    digitalWrite(pin, 0);
    digitalWrite(pin, 1);
}

void SIPO(unsigned char byte){
    int i;
    for(i=0;i<8;i++){
        digitalWrite(SDI, ((byte & (0x80 >> i)) > 0));
        pulse(SRCLK);
    }
}

void init(void){
    pinMode(SDI, OUTPUT);
    pinMode(RCLK, OUTPUT);
    pinMode(SRCLK, OUTPUT);

    digitalWrite(SDI, 0);
    digitalWrite(RCLK, 0);
    digitalWrite(SRCLK, 0);
}

int main(void){
    int i;

    if(wiringPiSetup() == -1){ //when initialize wiring failed, print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    init();

    while(1){
        for(i=0;i<8;i++){
            SIPO(LED[i]);
            pulse(RCLK);
            delay(150);
        }
        delay(500);

        for(i=0;i<3;i++){
            SIPO(0xff);
            pulse(RCLK);
            delay(100);
            SIPO(0x00);
            pulse(RCLK);
            delay(100);
        }
        delay(500);

        for(i=0;i<8;i++){
            SIPO(LED[8-i-1]);
            pulse(RCLK);
            delay(150);
        }
        delay(500);

        for(i=0;i<3;i++){
            SIPO(0xff);
            pulse(RCLK);
            delay(100);
            SIPO(0x00);
            pulse(RCLK);
            delay(100);
        }
        delay(500);
    }
    return 0;
}
Code Explanation
10.void pulse(int pin){
11.    digitalWrite(pin, 0);
12.    digitalWrite(pin, 1);
13.}

Define an pulse function to generate an pulse.

15.void SIPO(unsigned char byte){
16.    int i;
17.    for(i=0;i<8;i++){
18.        digitalWrite(SDI, ((byte & (0x80 >> i)) > 0));
19.        pulse(SRCLK);
20.    }
21.}

The function SIPO is used to assign the byte data to SDI(DS) by bits.

Among them, the inequality in statement digitalWrite() ((byte & (0x80>>i))>0) is used to confirm each value written into the register and it realizes the function by Shift operator (>>).

For example, if byte=0x01:

When the condition “i=0” is met, 0x80(1000 0000)>>0 becomes 0x80(1000 0000), if byte&0x80=0, the inequality is false, and output 0 (false).

If “i=1” is true, 0x80>>1 changes into 0x40(0100 0000); when byte&0x40=0, output 0.

Deduce the rest from this, when and only when “i=8” is met, 0x80>>8 is 0x01(0000 0001), byte&0x01=1, and output 1(true).

Pulse(SRCLK) generates a rising edge pulse on input pin of shift register to shift the 8 bit data on SDI to shift register successively.

In a word, this for loop produces 8 times to shift the 8 bits of 0000 0001 to shift register.

23.void init(void){
24.    pinMode(SDI, OUTPUT);
25.    pinMode(RCLK, OUTPUT);
26.    pinMode(SRCLK, OUTPUT);
27.
28.    digitalWrite(SDI, 0);
29.    digitalWrite(RCLK, 0);
30.    digitalWrite(SRCLK, 0);
31.}

Initialize pins. Set all control pins of 74HC595 to output mode and initialize them to low level. At the same time, the LEDs are set to output mode, default low level.

44.        for(i=0;i<8;i++){
45.            SIPO(LED[i]);
46.            pulse(RCLK);
47.            delay(150);
48.        }

Use the for loop to count 8 times in cycle, and write a 1-bit data to the SDI each time.

When i=0, LED[0]=0x01(0000 0001), through the function SIPO(LED[0]), shifts the 8 bits of 0x01 to shift register successively. Pulse(SRCLK) generates a rising edge signal on input pin of storage register to shift the 0x01 on shift register to storage register at once. Then the data in the memory register are output to the bus (Q7-Q0), so you’ll see the LED on Q0 is lit up. After loops, output all eight elements in the array LED[i] to the bus (Q7-Q0), and you’ll see eight LEDs turning on from left to right.

51.        for(i=0;i<3;i++){
52.            SIPO(0xff);
53.            pulse(RCLK);
54.            delay(100);
55.            SIPO(0x00);
56.            pulse(RCLK);
57.            delay(100);
58.        }

In this part, the for loop is used to three times repeat the program in for() statement. SIPO(0xff) means 8 LEDs are lit up, SIPO(0x00) represents 8 LEDs turn off. That is, let 8 LEDs turn off 3 times simultaneously.

61.        for(i=0;i<8;i++){
62.            SIPO(LED[8-i-1]);
63.            pulse(RCLK);
64.            delay(150);
65.        }

By the same token, this for loop allows 8 LEDs be lit up one by one in reverse order. Here, i gradually increases from 0, and 8-i-1 gradually decreases. SIPO(LED[8-i-1]) can be used to call the data in the LED[] array from back to front so that you can get 8 LEDs lit up one by one in reverse order.

68.        for(i=0;i<3;i++){
69.            SIPO(0xff);
70.            pulse(RCLK);
71.            delay(100);
72.            SIPO(0x00);
73.            pulse(RCLK);
74.            delay(100);
75.        }

Then, make the eight LEDs turn on or off 3 times simultaneously.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 18_74HC595.py

As the code runs, you can see these eight LEDs are lit up from left to right, and then all LEDs light up and flash 3 times. After that, these eight LEDs are lit from right to left, then they all turn on before flashing 3 times. This loop continues in this way.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

#!/usr/bin/env python3

#================================================
#
#   This program is for SunFounder SuperKit for Rpi.
#
#   Extend use of 8 LED with 74HC595.
#
#   Change the  WhichLeds and sleeptime value under
#   loop() function to change LED mode and speed.
#
#=================================================

import RPi.GPIO as GPIO
import time

SDI   = 17
RCLK  = 18
SRCLK = 27

#===============   LED Mode Defne ================
#   You can define yourself, in binay, and convert it to Hex
#   8 bits a group, 0 means off, 1 means on
#   like : 0101 0101, means LED1, 3, 5, 7 are on.(from left to right)
#   and convert to 0x55.

LED0 = [0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80]    #original mode
BLINK = [0xff,0x00,0xff,0x00,0xff,0x00]         #blink
#=================================================

def print_message():
    print ("========================================")
    print ("|           LEDs with 74HC595          |")
    print ("|    ------------------------------    |")
    print ("|         SDI connect to GPIO 0        |")
    print ("|         RCLK connect to GPIO 1       |")
    print ("|        SRCLK connect to GPIO 2       |")
    print ("|                                      |")
    print ("|       Control LEDs with 74HC595      |")
    print ("|                                      |")
    print ("|                            SunFounder|")
    print ("========================================\n")
    print ('Program is running...')
    print ('Please press Ctrl+C to end the program...')
    #input ("Press Enter to begin\n")

def setup():
    GPIO.setmode(GPIO.BCM)    # Number GPIOs by its BCM location
    GPIO.setup(SDI, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(RCLK, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(SRCLK, GPIO.OUT, initial=GPIO.LOW)

# Shift the data to 74HC595
def hc595_shift(dat):
    for bit in range(0, 8):
        GPIO.output(SDI, 0x80 & (dat << bit))
        GPIO.output(SRCLK, GPIO.HIGH)
        time.sleep(0.001)
        GPIO.output(SRCLK, GPIO.LOW)
    GPIO.output(RCLK, GPIO.HIGH)
    time.sleep(0.001)
    GPIO.output(RCLK, GPIO.LOW)

def main():
    print_message()
    mode = LED0
    sleeptime = 0.15        # Change speed, lower value, faster speed
    blink_sleeptime = 0.15

    while True:
        # Change LED status from mode
        for onoff in mode:
            hc595_shift(onoff)
            time.sleep(sleeptime)

        for onoff in BLINK:
            hc595_shift(onoff)
            time.sleep(blink_sleeptime)

        # Change LED status from mode reverse
        for onoff in reversed(mode):
            hc595_shift(onoff)
            time.sleep(sleeptime)

        for onoff in BLINK:
            hc595_shift(onoff)
            time.sleep(blink_sleeptime)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    setup()
    try:
        main()
    except KeyboardInterrupt:
        destroy()
Code Explanation
8.LED0 = [0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80]    #original mode

Use array to define LED flashing mode, you can also customize several hexadecimals to light up 8 LEDs.

11.def setup():
1.     GPIO.setmode(GPIO.BCM)    # Number GPIOs by its BCM location
2.     GPIO.setup(SDI, GPIO.OUT, initial=GPIO.LOW)
3.     GPIO.setup(RCLK, GPIO.OUT, initial=GPIO.LOW)
4.     GPIO.setup(SRCLK, GPIO.OUT, initial=GPIO.LOW)

Initialize pins. Set all control pins of 74HC595 to output mode and initialize them to low level. At the same time, the LED lights are set to output mode, default low level.

18.def hc595_shift(dat):

Define a function hc595_shift() to output the 8 bits of dat to Q0-Q7.

1.  for bit in range(0, 8):
2.         GPIO.output(SDI, 0x80 & (dat << bit))
3.         GPIO.output(SRCLK, GPIO.HIGH)
4.         time.sleep(0.001)
5.         GPIO.output(SRCLK, GPIO.LOW)

Assign the dat to SDI(DS) according to bits. Pin SRCLK will convert from low to high, and generate a rising edge pulse, then shift the data in pin SDI to shift register. Execute the loop 8 times to shift the 8 bits of dat to the shift register in proper order.

1.     GPIO.output(RCLK, GPIO.HIGH)
2.     time.sleep(0.001)
3.     GPIO.output(RCLK, GPIO.LOW)

Pin RCLK converts from low to high and generate a rising edge, then shift data from shift register to storage register. Finally the data in the memory register is output to the bus (Q0-Q7).

1.         for onoff in mode:
2.             hc595_shift(onoff)
3.             time.sleep(sleeptime)

Here we use a onoff variable to control the LED that changes within the range of mode, and hc595_shift (onoff) means lighting up LED one by one. For example, when mode is the first datum in LED0, or 0x01, onoff = mode = 0x01 = 00000001. In this course, the LED is lit by high level. To put it another way, it is Hc595_shift (onoff) = hc595_shift (00000001) that lights up the last LED. Along the same vein, when the value of mode is the second datum of LED0 (onoff = 0x02 = 00000010), the second last LED turns on.

1.         for onoff in reversed(mode):
2.             hc595_shift(onoff)
3.             time.sleep(sleeptime)

According to the same principle, a reversed is used here to get LEDs lit up in reverse order.

1.         for onoff in BLINK:
2.             hc595_shift(onoff)
3.             time.sleep(blink_sleeptime)

In the same way, light up 8 LEDs; exactly, 8 LEDs are turned on or off 3 times synchronously in the same pattern as that of the LEDs in the BLINK array.

Phenomenon Picture
_images/image184.jpeg
Lesson 19 7-segment
Introduction

Generally, there are two ways to drive a single 7-Segment Display. One way is to connect its 8 pins directly to eight ports on the Raspberry Pi. Or you can connect the 74HC595 to three ports of the Raspberry Pi and then the 7- segment display to the 74HC595. In this experiment, we will use the latter. By this way, we can save five ports – considering the board’s limited ports, and this is very important. Now let’s get started!

Newly Added Components
_images/image247.png
Principle

7-Segment Display

A 7-Segment Display is an 8-shaped component which packages 7 LEDs. Each LED is called a segment – when energized, one segment forms part of a numeral to be displayed.

There are two types of pin connection: Common Cathode (CC) and Common Anode (CA). As the name suggests, a CC display has all the cathodes of the 7 LEDs connected when a CA display has all the anodes of the 7 segments connected. In this kit, we use the former.

_images/image186.jpeg

Each of the LEDs in the display is given a positional segment with one of its connection pins led out from the rectangular plastic package. These LED pins are labeled from “a” through to “g” representing each individual LED. The other LED pins are connected together forming a common pin. So by forward biasing the appropriate pins of the LED segments in a particular order, some segments will brighten and others stay dim, thus showing the corresponding character on the display.

Display Codes

To help you get to know how 7-Segment Displays(Common Cathode) display Numbers, we have drawn the following table. Numbers are the number 0-F displayed on the 7-Segment Display; (DP) GFEDCBA refers to the corresponding LED set to 0 or 1, For example, 00111111 means that DP and G are set to 0, while others are set to 1. Therefore, the number 0 is displayed on the 7-Segment Display, while HEX Code corresponds to hexadecimal number.

_images/image248.png
Schematic Diagram
_images/image249.png
Build the Circuit

Note

Recognize the direction of the chip according to the concave on it.

_images/image250.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_19_7-segment

2. Compile the code.

gcc 19_7-Segment.c -lwiringPi

3. Run the executable file.

sudo ./a.out

You may see 0 to 9 and A to F on the 7-Segment Display.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>

#define   SDI   0   //serial data input
#define   RCLK  1   //memory clock input(STCP)
#define   SRCLK 2   //shift register clock input(SHCP)

unsigned char SegCode[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x80};

void init(void){
    pinMode(SDI, OUTPUT);
    pinMode(RCLK, OUTPUT);
    pinMode(SRCLK, OUTPUT);

    digitalWrite(SDI, 0);
    digitalWrite(RCLK, 0);
    digitalWrite(SRCLK, 0);
}

void hc595_shift(unsigned char dat){
    int i;
    for(i=0;i<8;i++){
        digitalWrite(SDI, 0x80 & (dat << i));
        digitalWrite(SRCLK, 1);
        delay(1);
        digitalWrite(SRCLK, 0);
    }

        digitalWrite(RCLK, 1);
        delay(1);
        digitalWrite(RCLK, 0);
}

int main(void){
    int i;

    if(wiringPiSetup() == -1){ //when initialize wiring failed, print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    init();

    while(1){
        for(i=0;i<17;i++){
            hc595_shift(SegCode[i]);
            delay(500);
        }
    }
    return 0;
}
Code Explanation
10.void init(void){
11.    pinMode(SDI, OUTPUT);
12.    pinMode(RCLK, OUTPUT);
13.    pinMode(SRCLK, OUTPUT);
14.
15.    digitalWrite(SDI, 0);
16.    digitalWrite(RCLK, 0);
17.    digitalWrite(SRCLK, 0);
18.}

Initialize pins. Set all control pins of 74HC595 to output mode and initialize them to low level. At the same time, the LEDs are set to output mode, default low level.

19. void hc595_shift(unsigned char dat)

To assign 8 bit value to 74HC595’s shift register.

22.    for(i=0;i<8;i++){
23.        digitalWrite(SDI, 0x80 & (dat << i));
24.        digitalWrite(SRCLK, 1);
25.        delay(1);
26.        digitalWrite(SRCLK, 0);
27.    }

Assign the dat value to SDI(DS) by bits. Then shift them to the shift register by bits. Execute the loop 8 times to shift the 8 bits of dat to the shift register in proper order.

29.        digitalWrite(RCLK, 1);
30.        delay(1);
31.        digitalWrite(RCLK, 0);

Pin RCLK converts from low to high and generates a rising edge, then shifts data from shift register to storage register. Finally the data in the memory register are output to the bus (Q0-Q7).

45.        for(i=0;i<17;i++){
46.            hc595_shift(SegCode[i]);
47.            delay(500);
48.        }

In the for loop, output 16 values from array Segcode[] to 7-Segment Display.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 19_7-Segment.py

You may see 0 to 9 and A to F on the 7-Segment Display.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time

# Set up pins
SDI   = 17
RCLK  = 18
SRCLK = 27

segCode = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71]

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(SDI, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(RCLK, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(SRCLK, GPIO.OUT, initial=GPIO.LOW)

# Shift the data to 74HC595
def hc595_shift(dat):
    for bit in range(0, 8):
        GPIO.output(SDI, 0x80 & (dat << bit))
        GPIO.output(SRCLK, GPIO.HIGH)
        time.sleep(0.001)
        GPIO.output(SRCLK, GPIO.LOW)
    GPIO.output(RCLK, GPIO.HIGH)
    time.sleep(0.001)
    GPIO.output(RCLK, GPIO.LOW)

def main():
    while True:
        # Shift the code one by one from segCode list
        for code in segCode:
            hc595_shift(code)
            time.sleep(0.5)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    setup()
    try:
        main()
    except KeyboardInterrupt:
        destroy()
Code Explanation
12.def setup():
13.    GPIO.setmode(GPIO.BCM)
14.    GPIO.setup(SDI, GPIO.OUT, initial=GPIO.LOW)
15.    GPIO.setup(RCLK, GPIO.OUT, initial=GPIO.LOW)
16.    GPIO.setup(SRCLK, GPIO.OUT, initial=GPIO.LOW)

Initialize pins. Set all control pins of 74HC595 to output mode and initialize them to low level.

19.def hc595_shift(dat):

To assign 8 bit value to 74HC595’s shift register.

20.    for bit in range(0, 8):
21.        GPIO.output(SDI, 0x80 & (dat << bit))
22.        GPIO.output(SRCLK, GPIO.HIGH)
23.        time.sleep(0.001)
24.        GPIO.output(SRCLK, GPIO.LOW)

Assign the dat value to SDI(DS) by bits. Then shift them to the shift register by bits. Execute the loop 8 times to shift the 8 bits of dat to the shift register in proper order.

25.    GPIO.output(RCLK, GPIO.HIGH)
26.    time.sleep(0.001)
27.    GPIO.output(RCLK, GPIO.LOW)

Pin RCLK converts from low to high and generates a rising edge, then shifts data from shift register to storage register. Finally the data in the memory register are output to the bus (Q0-Q7).

32.        for code in segCode:
33.            hc595_shift(code)
34.            time.sleep(0.5)

In the for loop, output 16 values from array Segcode [] to 7-Segment Display.

Phenomenon Picture
_images/image189.jpeg
Lesson 20 Traffic Light
Introduction

In last lesson, we learned how to use a 74HC595 chip to drive a 7-Segment Display. Based on that, we can apply it more widely now, such as making a simple traffic light. Now let’s get started!

Newly Added Components
_images/image251.png
Schematic Diagram
_images/image252.png _images/image261.png
Build the Circuit
_images/image253.png
For C Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_20_TrafficLight

2. Compile the code.

gcc 20_TrafficLight.c -lwiringPi

3. Run the executable file.

sudo ./a.out

You can see the following phenomenon of traffic lights. The red LED lights up for 9 seconds, green LED for 5s, and yellow LED for 3s.

Note

If it does not work after running, or there is an error prompt: “wiringPi.h: No such file or directory”, please refer to C code is not working?.

Code
#include <wiringPi.h>
#include <stdio.h>
#include <wiringShift.h>
#include <signal.h>
#include <unistd.h>
#define     SDI     0   //serial data input(DS)
#define     RCLK    1   //memory clock input(STCP)
#define     SRCLK    2    //shift register clock input(SHCP)
const int ledPin[]={3,4,5};   //Define 3 LED pin(Red, Green, Yellow)
unsigned char SegCode[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x80};

int greentime = 5;
int yellowtime = 3;
int redtime = 9;
int colorState = 0;
char *lightColor[]={"Red","Green","Yellow"};
int counter = 9;

void init(void){
    pinMode(SDI, OUTPUT);
    pinMode(RCLK, OUTPUT);
    pinMode(SRCLK, OUTPUT);

    digitalWrite(SDI, 0);
    digitalWrite(RCLK, 0);
    digitalWrite(SRCLK, 0);

      for(int i=0;i<3;i++){
        pinMode(ledPin[i],OUTPUT);
        digitalWrite(ledPin[i],LOW);
    }
}

void hc595_shift(unsigned char dat){
    int i;
    for(i=0;i<8;i++){
        digitalWrite(SDI, 0x80 & (dat << i));
        digitalWrite(SRCLK, 1);
        delay(1);
        digitalWrite(SRCLK, 0);
    }
        digitalWrite(RCLK, 1);
        delay(1);
        digitalWrite(RCLK, 0);
}

void timer(int  sig){       //Timer function
    if(sig == SIGALRM){
        counter --;
        alarm(1);
        if(counter == 0){
            if(colorState == 0) counter = greentime;
            if(colorState == 1) counter = yellowtime;
            if(colorState == 2) counter = redtime;
            colorState = (colorState+1)%3;
        }
        printf("counter : %d \t light color: %s \n",counter,lightColor[colorState]);
    }
}

void display(int num)
{
    hc595_shift(SegCode[num%10]);
    delay(1);
}

void lightup(int state)
{
    for(int i=0;i<3;i++){
        digitalWrite(ledPin[i],LOW);
    }
        digitalWrite(ledPin[state],HIGH);
}

int main(void)
{
    int i;

    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    init();

    signal(SIGALRM,timer);  //configure the timer
    alarm(1);               //set the time of timer to 1s
    while(1){
        display(counter);
        lightup(colorState);
    }
    return 0;
}
Code Explanation
12.int greentime = 5;
13.int yellowtime = 3;
14.int redtime = 9;

Define the duration of lighting of three LEDs. Since what we use is a 7-Segment Display here, we shorten the length of seconds of lighting of traffic lights, setting the green LED to light up for 5 seconds, the yellow LED to 3 seconds, and the red LED to 9 seconds.

15.int colorState = 0;
16.int counter = 9;

The variable colorState corresponds to the state of the traffic lights, and we only need to do a simple calculation of colorState to indicate the order change of the state of the traffic lights. The Variable counter is used to count down the time to each traffic light status and will be output on a 7-Segment Display.

19.void init(void){
20.    pinMode(SDI, OUTPUT);
21.    pinMode(RCLK, OUTPUT);
22.    pinMode(SRCLK, OUTPUT);
23.
24.    digitalWrite(SDI, 0);
25.    digitalWrite(RCLK, 0);
26.    digitalWrite(SRCLK, 0);
27.
28.      for(int i=0;i<3;i++){
29.        pinMode(ledPin[i],OUTPUT);
30.        digitalWrite(ledPin[i],LOW);
31.    }
32.}

Initialize pins. Set all control pins of 74HC595 to output mode and initialize them to low level. At the same time, the LEDs are set to output mode, default low level.

47.void timer(int  sig){
48.    if(sig == SIGALRM){
49.        counter --;
50.        alarm(1);
51.        if(counter == 0){
52.            if(colorState == 0) counter = greentime;
53.            if(colorState == 1) counter = yellowtime;
54.            if(colorState == 2) counter = redtime;
55.            colorState = (colorState+1)%3;
56.        }
57.        printf("counter : %d \t light color: %s \n",counter,lightColor[colorState]);
58.    }
59.}

On this timer, counter decreases gradually with every second passing, and when it goes to 0, the state of the traffic light changes accordingly.

67.void lightup(int state)
68.{
69.    for(int i=0;i<3;i++){
70.        digitalWrite(ledPin[i],LOW);
71.    }
72.        digitalWrite(ledPin[state],HIGH);
73.}

The function is to turn off all the lights first, and then light up the corresponding LED according to the value of the traffic light state.

For Python Language Users
Command

1. Go to the folder of the code.

cd /home/pi/electronic-kit/for-raspberry-pi/python

2. Run the code.

sudo python3 20_TrafficLight.py

You can see the following phenomenon of traffic lights. The red LED lights up for 9 seconds, green LED for 5s, and yellow LED for 3s.

Code

Note

You can Modify/Reset/Copy/Run/Stop the code below. But before that, you need to go to source code path like electronic-kit/for-raspberry-pi/python. After modifying the code, you can run it directly to see the effect.

import RPi.GPIO as GPIO
import time
import threading

#define the pins connect to 74HC595
SDI   = 17      #serial data input(DS)
RCLK  = 18      #memory clock input(STCP)
SRCLK = 27       #shift register clock input(SHCP)
number = (0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x80)

ledPin =(22,23,24)

greenLight = 5
yellowLight = 3
redLight = 9
lightColor=("Red","Green","Yellow")

colorState=0
counter = 9
t = 0

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(SDI, GPIO.OUT)
    GPIO.setup(RCLK, GPIO.OUT)
    GPIO.setup(SRCLK, GPIO.OUT)
    for pin in ledPin:
        GPIO.setup(pin,GPIO.OUT)


def hc595_shift(dat):
    for bit in range(0, 8):
        GPIO.output(SDI, 0x80 & (dat << bit))
        GPIO.output(SRCLK, GPIO.HIGH)
        GPIO.output(SRCLK, GPIO.LOW)
    GPIO.output(RCLK, GPIO.HIGH)
    GPIO.output(RCLK, GPIO.LOW)

def display(num):
    hc595_shift(0xff)
    hc595_shift(number[num%10])
    time.sleep(0.003)


def timer():        #timer function
    global counter
    global colorState
    global t
    t = threading.Timer(1.0,timer)
    t.start()
    counter-=1
    if (counter is 0):
        if(colorState is 0):
            counter= greenLight
        if(colorState is 1):
            counter=yellowLight
        if (colorState is 2):
            counter=redLight
        colorState=(colorState+1)%3
    print ("counter : %d    color: %s "%(counter,lightColor[colorState]))

def lightup(state):
    for i in range(0,3):
        GPIO.output(ledPin[i], GPIO.LOW)
    GPIO.output(ledPin[state], GPIO.HIGH)

def loop():
    global t
    global counter
    global colorState
    t = threading.Timer(1.0,timer)
    t.start()
    while True:
        display(counter)
        lightup(colorState)

def destroy():   # When "Ctrl+C" is pressed, the function is executed.
    global t
    GPIO.cleanup()
    t.cancel()      #cancel the timer

if __name__ == '__main__': # Program starting from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()
Code Explanation
13.greenLight = 5
14.yellowLight = 3
15.redLight = 9

Define the duration of lighting of three LEDs. Since what we use is a 7-Segment Display here, we shorten the length of seconds of lighting of traffic LEDs, setting the green LED to light up for 5 seconds, the yellow LED to 3 seconds, and the red LED to 9 seconds.

18.colorState=0
19.counter = 9

The variable colorState corresponds to the state of the traffic LEDs, and we only need to do a simple calculation of colorState to indicate the order change of the state of the traffic LEDs.

counter is used to count down the time to each traffic LED status and will be output on a 7-Segment Display.

45.def timer():        #timer function
46.    global counter
47.    global colorState
48.    global t
49.    t = threading.Timer(1.0,timer)
50.    t.start()
51.    counter-=1
52.    if (counter is 0):
53.        if(colorState is 0):
54.            counter= greenLight
55.        if(colorState is 1):
56.            counter=yellowLight
57.        if (colorState is 2):
58.            counter=redLight
59.        colorState=(colorState+1)%3
60.    print ("counter : %d    color: %s "%(counter,lightColor[colorState]))

On this timer, counter decreases gradually with every second passing, and when it goes to 0, the state of the traffic LED changes accordingly.

62.def lightup(state):
63.    for i in range(0,3):
64.        GPIO.output(ledPin[i], GPIO.LOW)
65.    GPIO.output(ledPin[state], GPIO.HIGH)

The function is to turn off all the LEDs first, and then light up the corresponding LED according to the value of the traffic LED state.

Phenomenon Picture
_images/image192.jpeg

Appendix

Remote Desktop

If you are not satisfied with using the command window to control the Raspberry Pi, you can also use the remote desktop function, which can help us manage the files in the Raspberry Pi easily. There are two ways to control the desktop of the Raspberry Pi remotely : VNC and XRDP.

VNC

You can use the function of remote desktop through VNC.

Enable VNC Service

The VNC service has been installed in the system. By default, VNC is disabled. You need to enable it in config.

Step 1

Input the following command:

sudo raspi-config

_images/image36.png

Step 2

On the config interface, select “Interfacing Options” by the up, down, left and right keys on the keyboard.

_images/image37.png

Step 3

Select VNC.

_images/image38.png

Step 4

Select Yes -> OK -> Finish to exit the configuration.

_images/image39.png
Login to VNC

Step 1

You need to install the VNC Viewer on personal computer. After the installation is done, open it.

Step 2

Then select “New connection”.

_images/image40.png

Step 3

Input IP address of Raspberry Pi and any Name.

_images/image41.png

Step 4

Double click the connection just created:

_images/image421.png

Step 5

Enter Username (“pi”) and Password (“raspberry” by default).

_images/image431.png

Step 6

Now you can see the desktop of the Raspberry Pi:

_images/image441.png
XRDP

XRDP provides a graphical login to remote machines using RDP (Microsoft Remote Desktop Protocol).

Install XRDP

Step 1

Login to Raspberry Pi by using SSH.

Step 2

Input the following instructions to install XRDP.

sudo apt-get update

sudo apt-get install xrdp

Step 3

Later, the installation starts.

Enter “Y”, press key “Enter” to confirm.

_images/image451.png

Step 4

Finished the installation, you should login to your Raspberry Pi by using Windows remote desktop applications.

Login to XRDP

Step 1

If you are a Windows user, you can use the Remote Desktop feature that comes with Windows. If you are a Mac user, you can download and use Microsoft Remote Desktop from the APP Store, and there is not much difference between them. The next example is Windows remote desktop.

Step 2

Type in “mstsc” in Run (WIN+R) to open the Remote Desktop Connection, and input the IP address of Raspberry Pi, then click on “Connect”.

_images/image461.png

Step 3

Then the xrdp login page pops out. Please type in your username and password. After that, please click “OK”. At the first time you log in, your username is “pi” and the password is “raspberry”.

_images/image47.png

Step 4

Here, you successfully login to RPi by using the remote desktop.

_images/image48.png

For Arduino User

Install and Introduce Arduino IDE

Description

Arduino is an open source platform with simple software and hardware. You can pick it up in short time even if you are a beginner. It provides an integrated development environment (IDE) for code compiling, compatible with multiple control boards. So you can just download the Arduino IDE, upload the sketches (i.e. the code files) to the board, and then you can see relative experimental phenomena. For more information, refer to http://www.arduino.cc.

Install Arduino IDE

Here are the installation steps on the windows system.

For other systems, please refer to: Install Arduinio IDE in different system and FAQ.pdf

The code in this kit is written based on Arduino, so you need to install the IDE first. Skip it if you have done this.

Now go to arduino.cc and click SOFTWARE -> DOWNLOADs. on the page, check the software list on the right side.

_images/image13.png

Find the one that suits your operation system and click to download. There are two versions of Arduino for Windows: Installer or ZIP file. You’re recommended to download the former.

For Installer File

Step 1: Find the .exe file just downloaded.

_images/image14.png

Step 2: Double click the file and a window will pop up as below. Click I Agree.

_images/image15.png

Step 3: Click Next.

_images/image16.png

Step 4: Select the path to install. By default, it’s set in the C disk. You can click Browse and choose other paths. Click OK. Then click Install.

_images/image17.png

Step 5: Meanwhile, it will prompts install the needed drivers, please select the ‘Always trust software from “Arduino LLC” ’. After the installation is done, click Close

Note

The new IDE may prompt errors when you’re compiling code under Windows XP. So if your computer is running on XP, you’re suggested to install Arduino 1.0.5 or 1.0.6. Also you can upgrade your computer.

For ZIP File

If you download the zip file before, when you connect the MCU to the computer, it may not be recognized. Then you need to install the driver manually. Take the following steps.

Step1: Plug in the board to the computer with a 5V USB cable. After a while, a prompt message of failed installation will appear.

Step2: Go to the Device Manager. You will find under other devices, Arduino Uno with an exclamation mark appear, which means the computer did not recognize the board.

_images/image18.png

Step3: Right click on Arduino Uno and select Update Driver Software.

_images/image19.png

Step4: Choose the second option, Browse my computer for Driver software.

_images/image20.png

Step5: A window pops up then. Click Browse. Then go to the folder where you just extracted the file. Go to the drivers folder and click OK -> Next.

_images/image20.png

Step6: Select ‘Always trust software from “Arduino LLC” ‘ then click Install.

_images/image21.png

It may need a sec. Then the system prompts you the driver has been installed successfully. So the computer can recognize the board now. Click Close.

_images/image22.png

Open the Arduino Software (IDE)

Double-click the Arduino icon (arduino.exe) created by the installation process. Then the Arduino IDE will appear. Let’s check details of the software.

_images/image23.png
  1. Verify: Compile your code. Any syntax problem will be prompted with errors.

  2. Upload: Upload the code to your board. When you click the button, the RX and TX LEDs on the board will flicker fast and won’t stop until the upload is done.

  3. New: Create a new code editing window.

  4. Open: Open an .ino sketch.

  5. Save: Save the sketch.

  6. Serial Monitor: Click the button and a window will appear. It receives the data sent from your control board. It is very useful for debugging.

  7. File: Click the menu and a drop-down list will appear, including file creating, opening, saving, closing, some parameter configuring, etc.

  8. Edit: Click the menu. On the drop-down list, there are some editing operations like Cut, Copy, Paste, Find, and so on, with their corresponding shortcuts.

  9. Sketch: Includes operations like Verify, Upload, Add files, etc. More important function is Include Library – where you can add libraries.

  10. Tool: Includes some tools – the most frequently used Board (the board you use) and Port (the port your board is at). Every time you want to upload the code, you need to select or check them.

  11. Help: If you’re a beginner, you may check the options under the menu and get the help you need, including operations in IDE, introduction information, troubleshooting, code explanation, etc.

  12. In this message area, no matter when you compile or upload, the summary message will always appear.

  13. Detailed messages during compile and upload. For example, the file used lies in which path, the details of error prompts.

  14. Board and Port: Here you can preview the board and port selected for code upload. You can select them again by Tools -> Board / Port if any is incorrect.

  15. The editing area of the IDE. You can write code here.

_images/image24.jpeg

Download the Code

We have uploaded the Arduino codes of this kit to the Arduino Cloud, you can see and download it in every lesson.

If you want to download all the codes to your local folder at once, please visit the link below:

https://github.com/sunfounder/electronic-kit

This is a github repository, which contains information about Arduino and Raspberry Pi. You can download it via the Download ZIP button.

_images/download_arduino.jpg

The Arduino code path is as follows: electronic-kit/for-Arduino/code/.

Lessons

Lesson 1 Blinking LED
Introduction

You should’ve learnt how to install Arduino IDE and add libraries before. Now you can start with a simple experiment to learn the basic operation and code in the IDE.

Component
_images/image171.png _images/image1721.png
Component Introduction

Breadboard

A breadboard is a construction base for prototyping of electronics. It is used to build and test circuits quickly before finalizing any circuit design. And it has many holes into which components like ICs and resistors as well as jumper wires mentioned above can be inserted. The breadboard allows you to easily plug in and remove components.

This is the internal structure of a full+ breadboard. Although there are holes on the breadboard, internally some of them are connected with metal strips.

_images/image31.png

Resistor

Resistor is an electronic element that can limit the branch current. A fixed resistor is one whose resistance cannot be changed, when that of a potentiometer or variable resistor can be adjusted.

The resistors in this kit are fixed ones. It is essential in the circuit to protect the connected components. The following pictures show a real 220Ω resistor and two generally used circuit symbols for resistor. Ω is the unit of resistance and the larger includes KΩ, MΩ, etc. Their relationship can be shown as follows: 1 MΩ=1000 KΩ, 1 KΩ = 1000 Ω, which means 1 MΩ = 1000,000 Ω = 10^6 Ω. Normally, the resistance is marked on it. So if you see these symbols in a circuit, it stands for a resistor.

_images/image173.png

The resistance can be marked directly, in color code, and by character. The resistors offered in this kit are marked by different colors. Namely, the bands on the resistor indicate the resistance.

When using a resistor, we need to know its resistance first. Here are two methods: you can observe the bands on the resistor, or use a multimeter to measure the resistance. You are recommended to use the first method as it is more convenient and faster. If you are not sure about the value, use the multimeter.

As shown in the card, each color stands for a number.

_images/image35.jpeg

LED

Semiconductor light-emitting diode is a type of component which can turn electric energy into light energy via PN junctions. By wavelength, it can be categorized into laser diode, infrared light-emitting diode and visible light-emitting diode which is usually known as light-emitting diode (LED).

_images/image174.png

Diode has unidirectional conductivity, so the current flow will be as the arrow indicates in figure circuit symbol. You can only provide the anode with a positive power and the cathode with a negative. Thus the LED will light up.

An LED has two pins. The longer one is the anode, and shorter one, the cathode. Pay attention not to connect them inversely. There is fixed forward voltage drop in the LED, so it cannot be connected with the circuit directly because the supply voltage can outweigh this drop and cause the LED to be burnt. The forward voltage of the red, yellow, and green LED is 1.8 V and that of the white one is 2.6 V. Most LEDs can withstand a maximum current of 20 mA, so we need to connect a current limiting resistor in series.

The formula of the resistance value is as follows:

R = (Vsupply – VD)/I

R stands for the resistance value of the current limiting resistor, Vsupply for voltage supply, VD for voltage drop and I for the working current of the LED.

If we provide 5 voltage for the red LED, the minimum resistance of the current limiting resistor should be: (5V-1.8v)/20mA = 160Ω. Therefore, you need a 160Ω or larger resistor to protect the LED. You are recommended to use the 220Ω resistor offered in the kit.

Jumper Wires

Wires that connect two terminals are called jumper wires. There are various kinds of jumper wires. Here we focus on those used in breadboard. Among others, they are used to transfer electrical signals from anywhere on the breadboard to the input/output pins of a microcontroller.

Jump wires are fitted by inserting their “end connectors” into the slots provided in the breadboard, beneath whose surface there are a few sets of parallel plates that connect the slots in groups of rows or columns depending on the area. The “end connectors” are inserted into the breadboard, without soldering, in the particular slots that need to be connected in the specific prototype.

There are three types of jumper wire: Female-to-Female, Male-to-Male, and Male-to-Female.

_images/image175.png

More than one type of them may be used in a project. The color of the jump wires is different but it doesn’t mean their function is different accordingly; it’s just designed so to better identify the connection between each circuit.

Principle:

Connect one end of the 220ohm resistor to pin 9 of the Uno and the other end to the anode (the long pin) of the LED, and the cathode (the short pin) of the LED to GND. When the pin 9 outputs high level, the current gets through the current limiting resistor to the anode of the LED. And since the cathode of the LED is connected to GND, the LED will light up. When pin 9 outputs low level, the LED goes out.

The schematic diagram:

_images/image204.png
Experimental Procedures

Step 1: Build the circuit (the pin with a curve is the anode of the LED).

Then plug the board into the computer with a 5V USB cable.

_images/image42.png

Step 2: Open the Lesson_1_Blinking_LED.ino code file in the path of electronic-kit\for-Arduino\code\Lesson_1_Blinking_LED

Step 3: Select the Board and Port

Before uploading the code, you need to select the Board and Port. Click Tools ->Board and select Arduino/Genuino Uno.

_images/image43.png

Then select Tools ->Port. Your port should be different from mine.

_images/image44.png

Step 4: Upload the sketch to the Uno board.

Click the Upload icon to upload the code to the control board.

_images/image45.png

If “Done uploading” appears at the bottom of the window, it means the sketch has been successfully uploaded.

_images/image46.png

You should now see the LED blinking.

_images/image47.jpeg
Code
Code Analysis 1-1 Define variables
const int ledPin = 9; // the number of the LED pin

You should define every variable before using in case of making mistakes. This line defines a constant variable ledPin for the pin 9. In the following code, ledPin stands for pin 9. You can also directly use pin 9 instead.

Code Analysis 1-2 setup() function

A typical Arduino program consists of two subprograms: setup() for initialization and loop() which contains the main body of the program.

The setup() function is usually used to initialize the digital pins and set them as input or output as well as the baud rate of the serial communication.

The loop() function contains what the MCU will run circularly. It will not stop unless something happens like power outages.

void setup()

{

    pinMode(ledPin,OUTPUT); // initialize the digital pin as an output

}

The setup() function here sets the ledPin as OUTPUT.

pinMode(Pin): Configures the specified pin to behave either as an input or an output.

The void before the setup means that this function will not return a value. Even when no pins need to be initialized, you still need this function. Otherwise there will be errors in compiling.

Code Analysis 1-3 loop function
void loop()

{

    digitalWrite(ledPin,HIGH); // turn the LED on

    delay(500); // wait for half a second

    digitalWrite(ledPin,LOW); // turn the LED off

    delay(500); // wait for half a second

}

This program is to set ledPin as HIGH to turn on the LED, with a delay of 500ms. Set ledPin as LOW to turn the LED off and also delay 500ms. The MCU will run this program repeatedly and you will see that the LED brightens for 500ms and then dims for 500ms. This on/off alternation will not stop until the control board runs out of energy.

digitWrite(Pin): Write a HIGH or a LOW value to a digital pin. When this pin has been set as output in pinModel(), its voltage will be set to the corresponding value: 5V (or 3.3V on 3.3V boards) for HIGH, 0V (ground) for LOW.

Experiment Summary

Through this experiment, you have learned how to turn on an LED. You can also change the blinking frequency of the LED by changing the num value in the delay function delay (num). For example, change it to delay (250) and you will find that the LED blinks more quickly.

Lesson 2 Controlling LED by Button
Introduction

In this experiment, we will learn how to turn on/off an LED by using an I/O port and a button. The “I/O port” refers to the INPUT and OUTPUT port. Here the INPUT port of the Uno board is used to read the output of an external device. Since the board itself has an LED (connected to Pin 13), you can use this LED to do this experiment for convenience.

Components
_images/image171.png _images/image1761.png
Experimental Principle
Button

Buttons are a common component used to control electronic devices. They are usually used as switches to connect or break circuits. Although buttons come in a variety of sizes and shapes, the one used here is a 6mm mini-button as shown in the following pictures.

Two pins on the left is connected, and the right is similar as the left, which is shown in the below:

_images/image50.png

The following is the internal structure of a button. The symbol on the right below is usually used to represent a button in circuits.

_images/image205.png

When the button is pressed, the 4 pins are connected, thus closing the circuit.

Principle:

Connect one end of the buttons to pin 12 which connects with a pull-down resistor (to eliminate jitter and output a stable level when the button is working). Connect the other end of the resistor to GND and one of the pins at the other end of the button to 5V. When the button is pressed, pin 12 is 5V (HIGH), then pin 13 is set (integrated with an LED) as HIGH at the same time. If the button release, the pin 12 changes to LOW and pin 13 is set to LOW. So we will see the LED lights up and goes out alternately as the button is pressed and released.

The schematic diagram:

_images/image52.png
Experimental Procedures

Step 1: Build the circuit

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

_images/image2281.png

Now, press the button, and the LED on the Uno board will light up.

_images/image2291.png
Code
Code Analysis 2-1 Define variables
const int buttonPin = 12; // the button connect to pin 12

const int ledPin = 13; // the led connect to pin13

int buttonState = 0; // variable for reading the pushbutton status

Connect the button to pin 12. LED has been connected to pin 13. Define a variable buttonState to restore the state of the button.

Code Analysis 2-2 Set the input and output status of the pins
pinMode(buttonPin, INPUT); // initialize thebuttonPin as input

pinMode(ledPin, OUTPUT); // initialize the led pin as output

We need to know the status of the button in this experiment, so here set the buttonPin as INPUT; to set HIGH/LOW of the LED, we set LedPin as OUTPUT.

Code Analysis 2-3 Read the status of the button
buttonState = digitalRead(buttonPin);

buttonPin(Pin12) is a digital pin; here is to read the value of the button and store it in buttonState.

digitalRead (Pin): Reads the value from a specified digital pin, either HIGH or LOW.

Code Analysis 2-4 Turn on the LED when the button is pressed
if (buttonState == HIGH )

{

    digitalWrite(ledPin, HIGH); // turn the led on

}

else

{

    digitalWrite(ledPin, LOW); // turn the led off

}

In this part, when the buttonState is High level, write ledPin as High and the LED will be turned on. As one end of the button has been connected to 5V and the other end to pin 12, when the button is pressed, pin 12 is 5V (HIGH). And then determine with the if(conditional); if the conditional is true, then the LED will light up.

Else means that when the if(conditional) is determined as false, run the code in else.

Experiment Summary

You can also change the code to: when the button is pressed, if (buttonState=HIGH). The LED goes out (digitalWrite(ledPin, LOW)). When the button is released (the else), the LED lights up ((digitalWrite(ledPin, HIGH)). You only need to replace the code in if with those in else.

Lesson 3 Controlling an LED by Potentiometer
Introduction

In this lesson, let’s see how to change the luminance of an LED by a potentiometer, and receive the data of the potentiometer in Serial Monitor to see its value change.

_images/image171.png _images/image177.png
Experimental Principle

Potentiometer

Potentiometer is also a resistance component with 3 terminals and its resistance value can be adjusted according to some regular variation. Potentiometer usually consists of resistor and movable brush. When the brush is moving along the resistor, there is a certain resistance or voltage output depending on the displacement.

_images/image178.png

The functions of the potentiometer in the circuit are as follows:

  1. Serving as a voltage divider

Potentiometer is a continuously adjustable resistor. When you adjust the shaft or sliding handle of the potentiometer, the movable contact will slide on the resistor. At this point, a voltage can be output depending on the voltage applied onto the potentiometer and the angle the movable arm has rotated to or the travel it has made.

  1. Serving as a rheostat

When the potentiometer is used as a rheostat, connect the middle pin and one of the other 2 pins in the circuit. Thus you can get a smoothly and continuously changed resistance value within the travel of the moving contact.

  1. Serving as a current controller

When the potentiometer acts as a current controller, the sliding contact terminal must be connected as one of the output terminals.

Serial Monitor

Serial Monitor is used for communication between the Mega 2560 board and a computer or other devices. It is a built-in software in the Arduino environment and you can click the button on the upper right corner to open it. You can send and receive data via the serial port on the control board and control the board by input from the keyboard.

_images/image59.png

Here, the Serial Monitor serves as a transfer station for communication between your computer and the Uno board. First, the computer transfers data to the Serial Monitor, and then the data is read by the Uno board. Finally, the Uno will perform related operations. Click the icon at the top right corner and a window will pop up as shown below:

_images/image601.png

Analog V.S. Digital

A linear potentiometer is an analog electronic component. So what’s the difference between an analog value and a digital one? Simply put, digital means on/off, high/low level with just two states, i.e. either 0 or 1. But the data state of analog signals is linear, for example, from 1 to 1000; the signal value changes over time instead of indicating an exact number. Analog signals include those of light intensity, humidity, temperature, and so on.

_images/image61.png

Principle:

In this experiment, the potentiometer is used as voltage divider, meaning connecting devices to all of its three pins. Connect the middle pin of the potentiometer to pin A0 and the other two pins to 5V and GND respectively. Therefore, the voltage of the potentiometer is 0-5V. Spin the knob of the potentiometer, and the voltage at pin A0 will change. Then convert that voltage into a digital value (0-1024) with the AD converter in the control board. Through programming, we can use the converted digital value to control the brightness of the LED on the control board.

The schematic diagram:

_images/image214.png
Experimental Procedures

Step 1: Build the circuit

_images/image63.png

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

Step5: Open the Serial Monitor.

Find the Serial.begin() code to see what baud rate is set, here is 9600. Then click the top right corner icon to open the Serial Monitor.

_images/image64.png

Step6: Set the baud rate to 9600.

The default baud rate for serial monitors is 9600, and if the code is also set to 9600, there is no need to change the baud rate bar.

_images/image65.png

Spin the shaft of the potentiometer and you should see the luminance of the LED change.

If you want to check the corresponding value changes, open the Serial Monitor and the data in the window will change with your spinning of the potentiometer knob.

_images/image66.jpeg
Code
Code Analysis 3-1 Read the value from A0
inputValue = analogRead(analogPin); // read the value from the potentiometer

This line is to store the values A0 has read in the inputValue which has been defined before.

analog Read() reads the value from the specified analog pin. This means that it will map input voltages between 0 and 5 volts into integer values between 0 and 1023.

Code Analysis 3-2 Print values on Serial Monitor
Serial.print("Input: "); // print "Input"

Serial.println(inputValue); // print inputValue

Serial.print():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.

Serial.print(): Commandant takes the same forms as Serial.print(), but it is followed by a carriage return character (ASCII 13, or ‘\r’) and a newline character (ASCII 10, or ‘\n’).

Code Analysis 3-3 Map the values
outputValue = map(inputValue, 0, 1023, 0, 255);
// Convert from 0-1023 proportional to the number of a number of from 0 to 255

map(value, Fromm, from High, to Low, thigh) re-maps a number from one range to another. That is, a value of Fromm would get mapped to one of to Low, and a value of from High to one of thigh, values in-between to values in-between, etc.

As the range of led Pin (pin 9) is 0-255, we need to map 0-1023 with 0-255.

Display the output value in Serial Monitor in the same way. If you are not so clear about the map() functions, you can observe the data in the Serial Monitor and analyze it.

Serial.print("Output: "); // print "Output"

Serial.println(outputValue); // print outputValue
Code Analysis 3-4 Write the value of the potentiometer to LED
analogWrite(ledPin, outputValue); // turn the LED on depending on the output value

Write the output value to led Pin and you will see that the luminance of LED changes with your spinning of the potentiometer knob.

analog Write(): Writes an analog value (PWM wave) to a pin. It has nothing to do with an analog pin, but is just for PWM pins. You do not need to call the incommode() to set the pin as output before calling analog Write().

Experiment Summary

This experiment can also be changed to others as you like. For example, use the potentiometer to control the time interval for the LED blinking. It is to use the value read from the potentiometer for delaying, as shown below. Have a try!

_images/image67.png
Lesson 4 Doorbell
Introduction

A buzzer is a great tool in your experiments whenever you want to make some sounds. In this lesson, we will learn how to drive an active buzzer to build a simple doorbell.

Components
_images/image171.png _images/image179.png
Experimental Principle

As a type of electronic buzzer with an integrated structure, buzzers, which are supplied by DC power, are widely used in computers, printers, photocopiers, alarms, electronic toys, automotive electronic devices, telephones, timers and other electronic products for voice devices. Buzzers can be categorized as active and passive ones (see the following picture). Turn the pins of two buzzers face up, and the one with a green circuit board is a passive buzzer, while the other enclosed with a black tape is an active one.

The difference between an active buzzer and a passive buzzer:

_images/image70.png

An active buzzer has a built-in oscillating source, so it will make sounds when electrified. But a passive buzzer does not have such source, so it will not tweet if DC signals are used; instead, you need to use square waves whose frequency is between 2K and 5K to drive it. The active buzzer is often more expensive than the passive one because of multiple built-in oscillating circuits.

In this experiment, we use an active buzzer.

The schematic diagram:

_images/image206.png
Experimental Procedures

Step 1: Build the circuit (Long pins of buzzer is the Anode and the short pin is Cathode).

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

_images/image215.png

Now, you should hear the buzzer beep.

_images/image73.jpeg
Code
Code Analysis 4-1 Define variables
const int buttonPin = 2; //the button connect to pin2

const int buzzerPin = 8; //the led connect to pin8

/**********************************/

int buttonState = 0; //variable for reading the pushbutton status

Connect the button to pin 2 and buzzer to pin 8. Define a variable buttonState to restore the state of the button.

Code Analysis 4-2 Set the input and output status of the pins
void setup()

{

    pinMode(buttonPin, INPUT); //initialize the buttonPin as input

    pinMode(buzzerPin, OUTPUT); //initialize the buzzerpin as output

}

We need to know the status of the button in this experiment, so here set the buttonPin as INPUT; to set HIGH/LOW of the buzzer, we set buzzerPin as OUTPUT.

Code Analysis 4-3 Read the status of the button
buttonState = digitalRead(buttonPin);

buttonPin(Pin2) is a digital pin; here is to read the value of the button and store it in buttonState.

digitalRead (Pin): Reads the value from a specified digital pin, either HIGH or LOW.

Code Analysis 4-4 Turn on the LED when the button is pressed
if (buttonState == HIGH ) //When press the button, run the following code.

{

    for (i = 0; i < 50; i++) /*When i=o, which accords with the condition
    i<=50, i++ equals to 1 (here in i = i + 1, the two "i"s are not the
    same, but i_now = i_before + 1). Run the code in the curly braces:
    let the buzzer beep for 3ms and stop for 3ms. Then repeat 50 times.*/

    {
        digitalWrite(buzzerPin, HIGH); //Let the buzzer beep.

        delay(3);//wait for 3ms

        digitalWrite(buzzerPin, LOW); //Stop the buzzer.

        delay(3);//wait for 3ms
    }

    for (i = 0; i < 80; i++) //Let the buzzer beep for 5ms and stop for 5ms, repeat 80 times.

    {
        digitalWrite(buzzerPin, HIGH);

        delay(5);//wait for 5ms

        digitalWrite(buzzerPin, LOW);

        delay(5);//wait for 5ms
    }
}

In this part, when the buttonState is High level, then let the buzzer beeping in different frequency which can simulate the doorbell.

Lesson 5 Photoresistor
Introduction

In this lesson, you will learn to how to measure light intensity using a photo resistor. The resistance of a photo resistor changes with incident light intensity. If the light intensity gets higher, the resistance decreases; if it gets lower, the resistance increases.

Components
_images/image171.png _images/image180.png
Experimental Principle

A photo resistor or photocell is a light-controlled variable resistor. The resistance of a photo resistor decreases with increasing incident light intensity; in other words, it exhibits photo conductivity. A photo resistor can be applied in light-sensitive detector circuits, and light- and darkness-activated switching circuits.

In this experiment, we will use 8 LEDs to show the light intensity. The higher the light intensity is, the more LEDs will light up. When the light intensity is high enough, all the LEDs will be on. When there is no light, all the LEDs will go out.

The schematic diagram:

_images/image771.png
Experimental Procedures

Step 1: Build the circuit

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

_images/image216.png

Now, shine some light on the photo resistor, and you will see several LEDs light up. Shine more light and you will see more LEDs light up. When you place it in a dark environment, all the LEDs will go out.

_images/image79.jpeg
Code
Code Analysis 5-1 Set the variables
const int NbrLEDs = 8;  // 8 leds

const int ledPins[] = {5, 6, 7, 8, 9, 10, 11, 12}; // 8 leds attach to pin 5-12 respectively

const int photocellPin = A0; // photoresistor attach to A0

int sensorValue = 0; // value read from the sensor

int ledLevel = 0; // sensor value converted into LED 'bars'

The 8 LEDs are connected to pin5-pin12, in this code, use a array to store the pins, ledPins[0] is equal to 5, ledPins[1] to 6 and so on.

Code Analysis 5-2 Set 8 pins to OUTPUT
for (int led = 0; led < NbrLEDs; led++)

{

    pinMode(ledPins[led], OUTPUT);// make all the LED pins outputs

}

Using the for() statement set the 8 pins to OUTPUT. The variable led is added from 0 to 8, and the pinMode() function sets pin5 to pin12 to OUTPUT in turn.

Code Analysis 5-3 Read the analog value of the photoresistor
sensorValue = analogRead(photocellPin); // read the value of A0

Read the analog value of the photocellPin(A0) and store to the variable sensorValue.

analogRead(): Reads the value from the specified analog pin. Arduino boards contain a multichannel, 10-bit analog to digital converter. This means that it will map input voltages between 0 and the operating voltage(5V or 3.3V) into integer values between 0 and 1023.

Serial.print("SensorValue: ");

Serial.println(sensorValue); // Print the analog value of the photoresistor

Use the Serial.print()function to print the analog value of the photoresistor. You can see them on the Serial Monitor.

Serial.print(): 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.

Serial.println(): Thiscommand takes the same forms as Serial.print(), but it is followed by a carriage return character (ASCII 13, or ‘\r’) and a newline character (ASCII 10, or ‘\n’).

Code Analysis 5-4 Map the analog value to 8 LEDs
ledLevel = map(sensorValue, 0, 1023, 0, NbrLEDs); // map to the number of LEDs

Serial.print("ledLevel: ");

Serial.println(ledLevel);

The map() command is used to map 0-1023 to 0-NbrLEDs(8), (1023-0)/(8-0)=127.875

_images/image1811.png

If sensorValue is 560, then the ledLevel is 4.

map(value, fromLow, fromHigh, toLow, toHigh) re-maps a number from one range to another. That is, a value of fromLow would get mapped to one of toLow, and a value of fromHigh to one of toHigh, values in-between to values in-between, etc.

Code Analysis 5-5 Light up the LEDs
for (int led = 0; led < NbrLEDs; led++)

{

    if (led <= ledLevel ) // When led is smaller than ledLevel, run the following code.

    {

        digitalWrite(ledPins[led], HIGH); // turn on pins less than the level

    }

    else

    {

        digitalWrite(ledPins[led], LOW); // turn off pins higher than

    }

}

Light up the corresponding LEDs. Such as, when the ledLevel is 4, then light up the ledPins[0] to ledPins[4] and go out the ledPins[5] to ledPins[7].

Lesson 6 RGB LED
Introduction

Previously we’ve used the digital pin to control an LED brighten and dim. In this lesson, we will use PWM to control an RGB LED to flash various kinds of color. When different PWM values are set to the R, G, and B pins of the LED, its brightness will be different. When the three different colors are mixed, we can see that the RGB LED flashes different colors.

Components
_images/image171.png _images/image182.png
Experimental Principle

PWM

Pulse width modulation, or PWM, is a technique for getting analog results with digital means. Digital control is used to create a square wave, a signal switched between on and off. This on-off pattern can simulate voltages in between full on (5 Volts) and off (0 Volts) by changing the portion of the time the signal spends on versus the time that the signal spends off. The duration of “on time” is called pulse width. To get varying analog values, you change, or modulate, that width. If you repeat this on-off pattern fast enough with some device, an LED for example, it would be like this: the signal is a steady voltage between 0 and 5V controlling the brightness of the LED. (See the PWM description on the official website of Arduino).

In the graphic below, the green lines represent a regular time period. This duration or period is the inverse of the PWM frequency. In other words, with Arduino’s PWM frequency at about 500Hz, the green lines would measure 2 milliseconds each.

_images/image81.jpeg

A call to analogWrite() is on a scale of 0 - 255, such that analogWrite(255) requests a 100% duty cycle (always on), and analogWrite(127) is a 50% duty cycle (on half the time) for example.

You will find that the smaller the PWM value is, the smaller the value will be after being converted into voltage. Then the LED becomes dimmer accordingly. Therefore, we can control the brightness of the LED by controlling the PWM value.

RGB LED

RGB LEDs emit light in various colors. An RGB LED packages three LEDs of red, green, and blue into a transparent or semitransparent plastic shell. It can display various colors by changing the input voltage of the three pins and superimpose them, which, according to statistics, can create 16,777,216 different colors.

_images/image82.jpeg

RGB LEDs can be categorized into common anode and common cathode ones. In this experiment, the latter is used. The common cathode, or CC, means to connect the cathodes of the three LEDs. After you connect it with GND and plug in the three pins, the LED will flash the corresponding color.

_images/image183.png

An RGB LED has 4 pins: the longest one is GND; the others are Red, Green and Blue. Touch its plastic shell and you will find a cut. The pin closest to the cut is the first pin, marked as Red, then GND, Green and Blue in turn.

_images/image85.png

Or you can distinguish them in another way. As GND is the longest one and can be defined directly, you can test the other three pins by giving them a small voltage. In addition, you need to add the current limiting resistor to protect the component.

Principle:

On the Uno board, 3, 5, 6 and 9-11 is the PWM pins. Provide 8-bit PWM output with the analogWrite() function. You can connect any of these pins.Here we input a value between 0 and 255 to the three pins of the RGB LED to make it display different colors. After connecting the pins of R, G, and B to a current limiting resistor, connect them to the pin 9, pin 10, and pin 11 respectively. The longest pin (GND) of the LED connects to the GND of the Uno. When the three pins are given different PWM values, the RGB LED will display different colors.

The schematic diagram:

_images/image86.png
Experimental Procedures

Step 1: Build the circuit

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

_images/image217.png

Here you should see the RGB LED flash circularly red, green, and blue first, then red, orange, yellow, green, blue, indigo, and purple.

_images/image88.jpeg
Code
Code Analysis 6-1 Set the color

Here use the color() function to set the color of the RGB LED. In the code, it is set to flash 7 different colors.

You can use the paint tool on your computer to get the RGB value.

  1. Open the paint tool on your computer and click to Edit colors.

_images/image89.png
  1. Select one color, then you can see the RGB value of this color. Fill them in the code.

_images/image90.png
void loop() // run over and over again

{

    // Basic colors:

    color(255, 0, 0);   // turn the RGB LED red

    delay(1000);        // delay for 1 second

    color(0,255, 0);   // turn the RGB LED green

    delay(1000);        // delay for 1 second

    color(0, 0, 255);  // turn the RGB LED blue

    delay(1000);        // delay for 1 second

    // Example blended colors:

    color(255,0,252); // turn the RGB LED red

    delay(1000);        // delay for 1 second

    color(237,109,0); // turn the RGB LED orange

    delay(1000);        // delay for 1 second

    color(255,215,0); // turn the RGB LED yellow

    delay(1000);        // delay for 1 second

    color(34,139,34); // turn the RGB LED green

    delay(1000);        // delay for 1 second

    color(0,112,255); // turn the RGB LED blue

    delay(1000);        // delay for 1 second

    color(0,46,90);     // turn the RGB LED indigo

    delay(1000);        // delay for 1 second

    color(128,0,128); // turn the RGB LED purple

    delay(1000);        // delay for 1 second

}
Code Analysis 6-2 color() function
void color (unsigned char red, unsigned char green, unsigned char blue)
// the color generating function

{

    analogWrite(redPin, red);

    analogWrite(greenPin, green);

    analogWrite(bluePin, blue);

}

Define three unsigned char variables, i.e., red, green and blue. Write their values to redPin, greenPin and bluePin. For example, color(128,0,128) is to write 128 to redPin, 0 to greenPin and 128 to bluePin. Then the result is the LED flashing purple.

analogWrite(): Writes an analog value (PWM wave) to a pin. It has nothing to do with an analog pin, but is just for PWM pins. You do not need to call the pinMode() to set the pin as output before calling analogWrite().

Lesson 7 Tilt Switch
Introduction

The tilt switch used here is a ball one with a metal ball inside. It is used to detect inclinations of a small angle.

Components
_images/image184.png
Experimental Principle

The principle is very simple. When the switch is tilted in a certain angle, the ball inside rolls down and touches the two contacts connected to the pins outside, thus triggering circuits. Otherwise the ball will stay away from the contacts, thus breaking the circuits.

_images/image93.jpeg

The schematic diagram:

_images/image921.png
Experimental Procedures

Step 1: Build the circuit

_images/image94.png

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

Now, tilt the switch, and the LED attached to pin 13 on Uno board will light up.

_images/image95.jpeg
Code
Code Analysis 7-1 Whole Code
const int ledPin = 13;      // the led attach to

void setup()

{

    pinMode(ledPin,OUTPUT); // initialize the ledPin as an output

    pinMode(2,INPUT);       // set pin2 as INPUT

    digitalWrite(2, HIGH);  // set pin2 as HIGH

}

/******************************************/

void loop()

{

    int digitalVal = digitalRead(2); // Read the value of pin2

    if(HIGH == digitalVal)           // if tilt switch is not breakover

    {

        digitalWrite(ledPin,LOW);    // turn the led off

    }

    else //if tilt switch breakover

    {

        digitalWrite(ledPin,HIGH);   // turn the led on

    }

}

The whole code are very simple, one pin of the tilt switch is connected to pin2, another pin is connected to GND, when tilt the switch, the two pins of the switch will be connected to GND, then let the LED on the pin13 lights up.

Lesson 8 Slide Switch
Introduction

In this lesson, we are going to use a slide switch to turn on/off an external LED. The slide switch is a device to connect or disconnect the circuit by sliding its handle. They are quite common in our surroundings. Now let’s see how it works.

Components
_images/image171.png _images/image185.png
Experimental Principle
Slide Switch
_images/image97.jpeg

Just as its name suggests, slide switch is to connect or disconnect the circuit by sliding its switch handle so as to switch the circuit. The common types of slide switch include single pole double throw, single pole triple throw, double pole double throw, and double pole triple throw and so on. Generally, it is used in circuits with a low voltage and features flexibility and stabilization. Slide switches are commonly used in all kinds of instruments/meters equipment, electronic toys and other fields related.

How it works: The middle pin is fixed. When the handle is pushed to the left, the left two pins are connected; push it to the right, the two pins on the right connect, thus switching circuits.

_images/image186.png

See the circuit symbol for slide switch and 2 is the middle pin.

_images/image2071.png _images/image187.png
Principle:

Here we use a slide switch to control the on/off of an LED which is simple. Connect the middle pin of the switch to pin 12. Connect one pin at one end to VCC. After connecting a 10K resistor and a 104 capacitor, connect the last one pin to GND (to let the switch output stable level signal). Connect an LED to pin 6. Push the handle of the slide switch to the pin connected with pin 12 which is High level, we can light up the LED at pin 6 by programming.

Experimental Procedures

Step 1: Build the circuit

_images/image1021.png

Step 2: Open the code file

Step 3: Select correct Board and Port

Step 4: Upload the sketch to the SunFounder Uno board

When you toggle the switch to pin12, the LED lights.

_images/image103.jpeg
Code
Code Analysis 8-1 Read the switch state to turn on/off the LED
void loop()

{

    //read the state of the switch value

    switchState = digitalRead(switchPin);

    if (switchState == HIGH )       //if it is,the state is HIGH

    {

        digitalWrite(ledPin, HIGH); //turn the led on

    }

    else

    {

        digitalWrite(ledPin, LOW);  //turn the led off

    }

}

First, read the state of the switchPin and see whether you have moved the switch handle. If it has been pushed to pin 12, then the switchState is High level, so set ledPin as High level, which means to light up the LED; otherwise, to turn it off.

Lesson 9 Relay
Introduction

As we may know, relay is a device which is used to provide connection between two or more points or devices in response to the input signal applied. In other words, relays provide isolation between the controller and the device as devices may work on AC as well as on DC. However, they receive signals from a microcontroller which works on DC hence requiring a relay to bridge the gap. Relay is extremely useful when you need to control a large amount of current or voltage with small electrical signal.

Components
_images/image171.png _images/image188.png
Experimental Principle
Relay

There are 5 parts in every relay:

1. Electromagnet – It consists of an iron core wounded by coil of wires. When electricity is passed through, it becomes magnetic. Therefore, it is called electromagnet.

2. Armature – The movable magnetic strip is known as armature. When current flows through them, the coil is it energized thus producing a magnetic field which is used to make or break the normally open (N/O) or normally close (N/C) points. And the armature can be moved with direct current (DC) as well as alternating current (AC).

3. Spring – When no currents flow through the coil on the electromagnet, the spring pulls the armature away so the circuit cannot be completed.

  1. Set of electrical contacts – There are two contact points:

  • Normally open – connected when the relay is activated, and disconnected when it is inactive.

  • Normally close – not connected when the relay is activated, and connected when it is inactive.

  1. Molded frame – Relays are covered with plastic for protection.

Working of Relay

The working principle of relay is simple. When power is supplied to the relay, currents start flowing through the control coil; as a result, the electromagnet starts energizing. Then the armature is attracted to the coil, pulling down the moving contact together thus connecting with the normally open contacts. So the circuit with the load is energized. Then breaking the circuit would a similar case, as the moving contact will be pulled up to the normally closed contacts under the force of the spring. In this way, the switching on and off of the relay can control the state of a load circuit.

_images/image108.jpeg
Transistor _images/image109.jpeg

Transistor is a semiconductor device that controls current by current. It functions by amplifying weak signal to larger amplitude signal and is also used for non-contact switch. A transistor is a three-layer structure composed of P-type and N-type semiconductors. They form the three regions internally. The thinner in the middle is the base region; the other two are both N-type or P-type ones – the smaller region with intense majority carriers is the emitter region, when the other one is the collector region. This composition enables the transistor to be an amplifier.

From these three regions, three poles are generated respectively, which are base (b), emitter (e), and collector (c). They form two P-N junctions, namely, the emitter junction and collection junction. The direction of the arrow in the transistor circuit symbol indicates that of the emitter junction. Based on the semiconductor type, transistors can be divided into two groups, the NPN and PNP ones. From the abbreviation, we can tell that the former is made of two N-type semiconductors and one P-type and that the latter is the opposite. See the figure below.

_images/image110.png

When a High level signal goes through an NPN transistor, it is energized. But a PNP one needs a Low level signal to manage it. Both types of transistor are frequently used for contactless switches, just like in this experiment.

Principle:

Connect a 1K resistor (for current limiting when the transistor is energized) to pin 8 of the SunFounder Uno board, then to an NPN transistor whose collector is connected to the coil of a relay and emitter to GND; connect the normally open contact of the relay to an LED and then GND. Therefore, when a High level signal is given to pin 8, the transistor is energized, thus making the coil of the relay conductive. Then its normally open contact is closed, and the LED will light up. When pin 8 is given a Low level, the LED will stay dim.

Function of the freewheeling diode:

When the voltage input changes from High (5V) to Low (0V), the transistor changes from saturation (three working conditions: amplification, saturation, and cut-off) to cut-off, the current in the coil suddenly has no way to flow through. At this moment, without the freewheeling diode, a counter-electromotive force (EMF) will be generated at the ends of the coil, with positive at the bottom and negative at the top, a voltage higher than 100V. This voltage plus that from the power at the transistor are big enough to burn it. Therefore, the freewheeling diode is extremely important in discharging this counter-EMF in the direction of the arrow in the figure above, so the voltage of the transistor to GND is no higher than +5V (+0.7V).

In this experiment, when the relay closes, the LED will light up; when the relay opens, the LED will go out.

The schematic diagram:

_images/image2181.png
Experimental Procedures

Step 1: Build the circuit

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

_images/image219.png

Now, send a High level signal, and the relay will close and the LED will light up; send a low one, and it will open and the LED will go out. In addition, you can hear a tick-tock caused by breaking the normally close contact and closing the normally open one.

_images/image1131.jpeg
Code
void loop()

{

    digitalWrite(relayPin, HIGH); //drive relay closure conduction

    delay(1000);                  //wait for a second

    digitalWrite(relayPin, LOW);  //drive the relay is closed off

    delay(1000);                  //wait for a second

}

The code in this experiment is simple. First, set relayPin as HIGH level and the LED connected to the relay will light up. Then set relayPin as LOW level and the LED goes out.

Lesson 10 4N35
Introduction

The 4N35 is an optocoupler that consists of a gallium arsenide infrared LED and a silicon NPN phototransistor. When the input signal is applied to the LED in the input terminal, the LED lights up. After receiving the light signal, the light receiver then converts it into electrical signal and outputs the signal directly or after amplifying it into a standard digital level. Thus, the transition and transmission of electricity-light-electricity is completed. Since light is the media of the transmission, meaning the input terminal and the output one are isolated electrically, this process is also be known as electrical isolation.

Components
_images/image171.png _images/image189.png
Experimental Principle
4N35 _images/image115.jpeg

The 4N35 is an optocoupler for general purpose application. It consists of gallium arsenide infrared LED and a silicon NPN phototransistor.

What an optocoupler does is to break the connection between signal source and signal receiver, so as to stop electrical interference. In other words, it is used to prevent interference from external electrical signals. 4N35 can be used in AV conversion audio circuits. Broadly it is widely used in electrical isolation for a general optocoupler.

_images/image116.png

See the internal structure of the 4N35 above. Pin 1 and 2 are connected to an infrared LED. When the LED is electrified, it’ll emit infrared rays. To protect the LED from burning, usually a resistor (about 1K) is connected to pin 1. Then the NPN phototransistor is power on when receiving the rays. This can be done to control the load connected to the phototransistor. Even when the load short circuit occurs, it won’t affect the control board, thus realizing good electrical isolation.

The schematic diagram:

_images/image117.png
Principle:

In this experiment, use an LED as the load connected to the NPN phototransistor. Connect pin 2 of the 4N35 to pin 7 of the control board, and pin 1 to a 1K current limiting resistor and then to 5V. Connect pin 4 to GND of the Uno, and pin 5 to the cathode of the LED. Then hook the anode of the LED to 5V after connecting with a 220 Ohm resistor. When in program, a LOW level is given to pin 7, the infrared LED will emit infrared rays. Then the phototransistor receives infrared rays and gets electrified, and the LED cathode is LOW, thus

turning on the LED. Also you can control the LED by circuits only – connect pin 2 to ground and it will brighten.

Experimental Procedures

Step 1: Build the circuit (pay attention to the direction of the chip by the concave on it)

_images/image118.png

Step 2: Open the code file.

Step 3: Select correct Board and Port.

Step 4: Upload the sketch to the SunFounder Uno board.

You will see the LED blinks.

_images/image119.jpeg
Exploration

4N35 is usually used for driving relay as well as motor circuits. As there is no direct connection between the input and output, even if a short circuit at the output end occurs, the control board will not be burnt. Have a try!

Code
void loop()

{

    digitalWrite(OptoPin, LOW);
    //set the OptoPin as LOW level,then the led connected on the output of 4n35 will be light

    delay(500);                  //delay 500ms

    digitalWrite(OptoPin, HIGH); //turn off the led

    delay(500);                  //delay 500ms

}

The code in this experiment is very easy to understand. Set pin 7 as Low level and the LED will light up; set it as High, and the LED goes out.

Lesson 11 NE555 Timer
Introduction

The NE555 Timer, a mixed circuit composed of analog and digital circuits, integrates analog and logical functions into an independent IC, thus tremendously expanding the applications of analog integrated circuits. It is widely used in various timers, pulse generators, and oscillators. In this experiment, the SunFounder Uno board is used to test the frequencies of square waves generated by the 555 oscillating circuit and show them on Serial Monitor.

Components
_images/image171.png _images/image220.png
Experimental Principle

555 IC

The 555 IC was originally used as a timer, hence the name 555 time base circuit. It is now widely used in various electronic products because of its reliability, convenience, and low price. The 555 is a complex hybrid circuit with dozens of components such as a divider, comparator, basic R-S trigger, discharge tube, and buffer.

Its pins and their functions:

_images/image121.png

As shown in the picture, the pins are set dual in-line with the 8-pin package.

  • Pin 1 (GND): the ground

  • Pin 2 (TRIGGER ): when the voltage at the pin reduces to 1/3 of the VCC (or the threshold defined by the control board), the output terminal sends out a High level

  • Pin 3 (OUTPUT): outputs High or Low, two states 0 and 1 decided by the input electrical level; maximum output current approx. 200mA at High

  • Pin 4 (RESET): when a Low level is received at the pin, the timer will be reset and the output will return to Low level; usually connected to positive pole or neglected

  • Pin 5 (CONTROL VOLTAGE): to control the threshold voltage of the chip (if it skips connection, by default, the threshold voltage is 1/3 VCC and 2/3 VCC)

  • Pin 6 (THRESHOLD): when the voltage at the pin increases to 2/3 VCC (or the threshold defined by the control board), the output terminal sends out a High level

  • Pin 7 (DISCHARGE): output synchronized with Pin 3, with the same logical level; but this pin does not output current, so pin 3 is the real High (or Low) when pin 7 is the virtual High (or Low); connected to the open collector (OC) inside to discharge the capacitor

  • Pin 8 (VCC): positive terminal for the NE555 timer IC, ranging +4.5V to +16V

  • The NE555 timer works under the monostable, astable and bistable modes. In this experiment, apply it under the astable mode, which means it works as an oscillator, as shown below:

_images/image122.jpeg

Connect a resistor R1 between the VCC and the discharging pin DS, another resistor between pin DS and the trigger pin TR which is connected to the threshold pin TH and then to the capacitor C1. Connect the RET (pin 4) to VCC, CV (pin 5) to another capacitor C2 and then to the ground.

Working process:

The oscillator starts to shake once the circuit is power on. Upon the energizing, since the voltage at C1 cannot change abruptly, which means pin 2 is Low level initially, set the timer to 1, so pin 3 is High level. The capacitor C1 charges via R1 and R2, in a time span:

Tc=0.693(R1+R2)

When the voltage at C1 reaches the threshold 2/3Vcc, the timer is reset and pin 3 is Low level. Then C1 discharges via R2 till 2/3Vcc, in a time span:

Td=0.693(R2)

Then the capacitor is recharged and the output voltage flips again:

Duty cycle D=Tc/(Tc+Td) x 100%

Since a potentiometer is used for resistor, we can output square wave signals with different duty cycles by adjusting its resistance. But R1 is a 10K resistor and R2 is 0k-10k, so the range of the ideal duty cycle is 66.7%-100%. If you want another else, you need to change the resistance of R1 and R2.

Dmin=(0.693(10K+0K))/(0.693(10K+0K)+0.693x0k) x100%=100%

Dmax=(0.693(10K+10K))/(0.693(10K+10K)+0.693x10k) x100%=66.7%

Experimental Procedures

Step 1: Build the circuit.

_images/image123.png

Step 2: Open the code file.

Step 3: Select correct Board and Port.

Step 4: Upload the sketch to the SunFounder Uno board.

After uploading, open the Serial Monitor and you will see the following window.

_images/image191.png
Code
Code Analysis 11-1 Calculate the duty cycle
void loop()

{

    duration1 = pulseIn(ne555, HIGH);  // Reads a pulse on ne555

    duration2 = pulseIn(ne555, LOW);   // Reads a pulse on ne555

    dc = float (duration1) / (duration1 + duration2) * 100;

    Serial.print("Duty cycle: ");

    Serial.print(dc);  // print the length of the pulse on the serial monitor

    Serial.print(" %");

    Serial.println();  // print an blank on serial monitor

    delay(500);        // wait for 500 microseconds

}

Read a pulse waits for the ne555(pin 7) from HIGH to LOW firstly, then read a pulse waits for pin 7 from LOW to HIGH. So the range of the ideal duty cycle dc is float (duration1) / (duration1 + duration2) * 100; You can rotate the potentiometer and read the duty cycle from the serial monitor.

pulseIn()

[Advanced I/O]

Description

Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go from LOW to HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds or gives up and returns 0 if no complete pulse was received within the timeout.

The timing of this function has been determined empirically and will probably show errors in longer pulses. Works on pulses from 10 microseconds to 3 minutes in length.

Syntax

pulseIn(pin, value)

pulseIn(pin, value, timeout)

Parameters

pin: the number of the pin on which you want to read the pulse. (int)

value: type of pulse to read: either HIGH or LOW. (int)

timeout (optional): the number of microseconds to wait for the pulse to start; default is one second. (unsigned long)

Returns

the length of the pulse (in microseconds) or 0 if no pulse started before the timeout. (unsigned long)

Lesson 12 Servo
Introduction

Servo is a type of geared motor that can only rotate 180 degrees. It is controlled by sending electrical pulses from your board. These pulses tell the servo what position it should move to.

A servo has three wires: the brown wire is GND, the red one is VCC, and the orange one is signal line.

Components
_images/image192.png
Experimental Principle

Servo

A servo is generally composed of the following parts: case, shaft, gear train, adjustable potentiometer, DC motor, and control circuit board.

It works like this: The Uno board sends out PWM signals to the servo, and then the control circuit in the servo receives the signals through the signal pin and controls the motor inside to turn. As a result, the motor drives the gear chain and then motivates the shaft after deceleration. The shaft and adjustable potentiometer of the servo are connected together. When the shaft rotates, it drives the pot, so the pot outputs a voltage signal to the circuit board. Then the board determines the direction and speed of rotation based on the current position, so it can stop exactly at the right position as defined and hold there.

The schematic diagram:

_images/image193.png
Experimental Procedures

Step 1: Build the circuit. (Brown to GND, Red to VCC, Orange to pin 9 of the control board)

_images/image128.png

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

Now, you can see the rocker arm of the servo rotate and stop at 90 degrees (15 degrees each time). And then it rotates in the opposite direction.

_images/image129.jpeg
Code
Code Analysis 12-1 Include a library
#include <Servo.h>
Servo myservo;     //create servo object to control a servo

With the Servo.h file included, you can call the functions in this file later. Servo is a built-in library in the Arduino IDE. You can find the Servo folder under the installation path C:\Program Files\Arduino\libraries.

Code Analysis 12-2 Initialize the servo
{

    myservo.attach(9);  //attachs the servo on pin 9 to servo object

    myservo.write(0);   //back to 0 degrees

    delay(1000);        //wait for a second

}

myservo.attach(): Attach the Servo variable to a pin. Initialize the servo attach to pin9.

myservo.write(): Writes a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. Here let the servo stay in the 0 angle firstly.

Code Analysis 12-3 Servo rotate
void loop()

{

    for (int i = 0; i <= 180; i++)

    {

        myservo.write(i);   //write the i angle to the servo

        delay(15);          //delay 15ms

    }

    for (int i = 180; i >= 0; i--)

    {

        myservo.write(i);   //write the i angle to the servo

        delay(15);          //delay 15ms

    }

}

Use 2 for() statement to write 0 - 180 to the servo, so that you can see the servo rotate from 0 to 180 angle, then turn back to 0.

Lesson 13 LCD1602
Introduction

In this lesson, we will learn how to use an LCD1602 to display characters and strings. LCD1602, or 1602 character-type liquid crystal display, is a kind of dot matrix module to show letters, numbers, and characters and so on. It’s composed of 5x7 or 5x11 dot matrix positions; each position can display one character. There’s a dot pitch between two characters and a space between lines, thus separating characters and lines. The number 1602 means on the display, 2 rows can be showed and 16 characters in each. Now let’s check more details!

Components
_images/image171.png _images/image194.png
Experimental Principle

Generally, LCD1602 has parallel ports, that is, it would control several pins at the same time. LCD1602 can be categorized into eight-port and four-port connections. If the eight-port connection is used, then all the digital ports of the Uno board are almost completely occupied. If you want to connect more sensors, there will be no ports available. Therefore, the four-port connection is used here for better application.

Pins of LCD1602 and their functions

VSS: connected to ground

VDD: connected to a +5V power supply

VO: to adjust the contrast

RS: A register select pin that controls where in the LCD’s memory you are writing data to. You can select either the data register, which holds what goes on the screen, or an instruction register, which is where the LCD’s controller looks for instructions on what to do next.

R/W: A Read/Write pin to select between reading and writing mode

E: An enabling pin that reads the information when High level (1) is received. The instructions are run when the signal changes from High level to Low level.

D0-D7: to read and write data

A and K: Pins that control the LCD backlight. Connect K to GND and A to 3.3v. Open the backlight and you will see clear characters in a comparatively dark environment.

Principle:

Connect K to GND and A to 3.3 V, and then the backlight of the LCD1602 will be turned on. Connect VSS to GND and the LCD1602 to the power source. Connect VO to the middle pin of the potentiometer - with it you can adjust the contrast of the screen display. Connect RS to D4 and R/W pin to GND, which means then you can write characters to the LCD1602. Connect E to pin6 and the characters displayed on the LCD1602 are controlled by D4-D7. For programming, it is optimized by calling function libraries.

The schematic diagram:

_images/image208.png
Experimental Procedures

Step 1: Build the circuit (make sure the pins are connected correctly. Otherwise, characters will not be displayed properly):

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

Note

you may need to adjust the potentiometer until the LCD1602 can display clearly.

_images/image221.png

You should now see the characters “SunFounder” and “hello, world” rolling on the LCD.

_images/image133.jpeg
Code
Code Analysis 13-1 Include a library
#include <LiquidCrystal.h> // include the library code

With the LiquidCrystal.h file included, you can call the functions in this file later.

LiquidCrystal is a built-in library in the Arduino IDE. You can find the LiquidCrystal folder under the installation path C:\Program Files\Arduino\libraries.

_images/image134.png

There is an example in the examples folder. The src folder contains the major part of the library: LiquidCrystal.cpp (execution file, with function implementation, variable definition, etc.) and LiquidCrystal.h (header file, including function statement, Macro definition, struct definition, etc.). If you want to explore how a function is implemented, you can look up in the file LiquidCrystal.cpp.

Code Analysis 13-2 Displayed characters
char array1[]=" SunFounder ";   // the string to print on the LCD

char array2[]="hello, world! ";   // the string to print on the LCD

These are two character type arrays: arry1[] and array2[]. The contents in the quotation marks ”xxx” are their elements, including 26 characters in total (spaces counted). array1[0] stands for the first element in the array, which is a space, and array1[1] means the second element S and so on. So array1[25] is the last element (here it’s also a space).

Code Analysis 13-3 Define the pins of LCD1602
LiquidCrystal lcd(4, 6, 10, 11, 12, 13);

Define a variable lcd of LiquidCrystal type. Here use lcd to represent LiquidCrystal in the following code.

The basic format of the LiquidCrysral() function is: LiquidCrystal (rs, enable, d4, d5, d6, d7). You can check the LiquidCrystal.cpp file for details.

So this line defines that pin RS is connected to pin 4, the enable pin to pin 6, and d4-d7 to pin10-13 respectively.

Code Analysis 13-4 Initialize the LCD
lcd.begin(16, 2);
// set up the LCD's number of columns and rows: begin(col,row) is to set the display of LCD. Here set as 16 x 2.
Code Analysis 13-5 Set the cursor position of LCD
lcd.setCursor(15,0); // set the cursor to column 15, line 0

setCursor(col,row) sets the position of the cursor which is where the characters start to show. Here set it as 15col, 0 row.

Code Analysis 13-6 LCD displays the elements inside array1[]and array2[]
for (int positionCounter1 = 0; positionCounter1 < 26; positionCounter1++)

{

    lcd.scrollDisplayLeft();             // Scrolls the contents of the display one space to the left.

    lcd.print(array1[positionCounter1]); // Print a message to the LCD.

    delay(tim);                          // wait for 250 microseconds

}

When positionCounter1=0, which accords with positionCounter1<26, positionCounter1 adds 1. Move one bit to the left through lcd.scrollDisplayLeft(). Make the LCD display array1[0] by lcd.print(array1[positionCounter1]) and delay for tim ms (250 ms). After 26 loops, all the elements in array1[] have been displayed.

lcd.clear(); // Clears the LCD screen.

Clear the screen with lcd.clear() so it won’t influence the display next time.

lcd.setCursor(15,1);
// set the cursor to column 15, line 1
// Set the cursor at Col. 15 Line 1, where the characters will start to show.

for (int positionCounter2 = 0; positionCounter2 < 26; positionCounter2++)
{

    lcd.scrollDisplayLeft();             // Scrolls the contents of the display one space to the left.

    lcd.print(array2[positionCounter2]); // Print a message to the LCD.

    delay(tim);                          // wait for 250 microseconds

}

Similarly, the code is to display the elements in array2[] on the LCD. Therefore, you will see “SunFounder” scroll in the top line of the LCD, move left until it disappears. And then in the bottom line, “hello, world ! ” appears, scrolls to the left until it disappears.

Lesson 14 Thermistor
Introduction

We’ve learnt many devices so far. To make more things, you need to have a good command of more knowledge. Today we’re going to meet a thermistor. It is similar to photoresistor in being able to change their resistance based on the outer change. Different from photoresistor, resistance of thermistor varies significantly with temperature in the outer environment.

Components
_images/image171.png _images/image195.png
Experimental Principle

Thermistor is a sensitive element, it has two types: Negative Temperature Coefficient (NTC) and Positive Temperature Coefficient (PTC), also NTC and PTC. Its resistance varies significantly with temperature. The resistance of PTC thermistor increases with higher temperature when that of NTC, decreases. In this experiment we use an NTC one.

The schematic diagram:

_images/image209.png

The principle is that the resistance of the NTC thermistor changes with the temperature difference in the outer environment. It detects the real-time temperature of the environment. When the temperature gets higher, the resistance of the thermistor decreases and the voltage of pin A0 increases accordingly. The voltage data then is converted to digital quantities by the A/D adapter. The temperature in Celsius and Fahrenheit then is output via programming and then displayed on LCD1602.

In this experiment a thermistor and a 10k pull-up resistor are used. Each thermistor has a normal resistance. Here it is 10k ohm, which is measured under 25 degree Celsius.

Here is the relation between the resistance and temperature change:

RT =RN expB(1/TK – 1/TN)

RT: resistance of the NTC thermistor when the temperature is TK.

RN: resistance of the NTC thermistor under the rated temperature which is TN.

TK is a Kelvin temperature and the unit is K.

TN is a rated Kelvin temperature; the unit is K, also.

And, beta, here is the material constant of NTC thermistor, also called heat sensitivity index.

exp is short for exponential, an exponential with the base number e, which is a natural number and equals 2.7 approximately.

Note that this relation is an empirical formula. It is accurate only when the temperature and resistance are within the effective range.

Since TK =T+273, T is Celsius temperature, the relation between resistance and temperature change can be transformed into this:

R =Ro expB[1/(T+273) – 1/(To+273)]

B, short for beta, is a constant. Here it is 4090. Ro is 10k ohms and To is 25 degrees Celsius. The data can be found in the datasheet of thermistor. Again, the above relation can be transformed into one to evaluate temperature:

T= B/[ ln(R/ 10) + (B/ 298) ] – 273 (So ln here means natural logarithm, a logarithm to the base e)

If we use a resistor with fixed resistance as 10k ohms, we can calculate the voltage of the analog input pin A0 with this formula:

V =10k x 5/(R+10K)

So, this relation can be formed:

R = (5 x 10k /V) - 10k

The voltage of A0 is transformed via A/D adaptor into a digital number a.

a=V x (1024/5)

V=a/205

Then replace V in the relation R = (5 x 10k /V) - 10k with the expression, and we can get this: R=1025 x 10k/a-10k.

Finally replace R in the formula here T= B/[ ln(R/ 10) + (B/ 298) ] – 273, which is formed just now. Then we at last get the relation for temperature as this:

T =B/[ ln{[ 1025 X 10/a) - 10]/10} 十(B/298)] – 273

Experimental Procedures

Step 1: Build the circuit

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

_images/image222.png

Now, you can see the current temperature displayed both in Celsius and Fahrenheit degrees on the LCD1602.

_images/image138.jpeg
Code
Code Analysis 14-1 Set the variables
#define analogPin A0   // the thermistor attach to

#define beta 3950      // the beta of the thermistor

#define resistance 10  // the value of the pull-up resistor

Define the beta coefficient as 3950, which is described in the datasheet of thermistor.

Code Analysis 14-2 Get the temperature
long a = analogRead(analogPin);
// Read the resistance value of the thermistor to a via the signal from the analog pin.
// Here use a long type to make the value of a to be a long integer.

float tempC = beta / (log((1025.0 * 10 / a - 10) / 10) + beta / 298.0) - 273.0;
// The formula here is to calculate the temperature in Celsius, which we deduced previously.

float tempF = 1.8 * tempC + 32.0;
// define the temperature in Fahrenheit. As we know Fahrenheit equals to 1.8 * Celsius + 32.
Code Analysis 14-3 Display the temperature on LCD1602
lcd.setCursor(0, 0);   // set the cursor to column 0, line 0

lcd.print("Temp: ");   // Print a message of "Temp: "to the LCD.

lcd.print(tempC);      // Print the tempC value on display.

lcd.print(char(223));  // print the unit" ° "

lcd.print("C");

// (note: line 1 is the second row, since counting begins with 0):

lcd.setCursor(0, 1);   // set the cursor to column 0, line 1

lcd.print("Fahr: ");

lcd.print(tempF);    // Print a Fahrenheit temperature to the LCD.

lcd.print(" F");       // Print the unit of the Fahrenheit temperature to the LCD.

delay(200);           // wait for 100 milliseconds
Lesson 15 Voltmeter
Introduction

In this lesson, we will use two potentiometers and an LCD1602 to make a DIY voltmeter.

Components
_images/image196.png _images/image197.png
Experimental Principle

Here one potentiometer is used to adjust the contrast of the LCD1602 and the other to divide voltage. When you adjust the potentiometer connected to pin A0 of the SunFounder Uno board, the resistance of the potentiometer will change and the voltage at pin A0 will change accordingly. This voltage change is converted into digital values by A/D converter on the SunFounder Uno board. We can see this change on the serial monitor. Then convert the digital values into voltage with the following formula: the voltage equals the digital value divides by 1024 and then multiplies by 5.0. Finally, display the voltage on the LCD1602.

The schematic diagram:

_images/image210.png
Experimental Procedures

Step 1: Build the circuit

Step 2: Open the code file

Step 3: Select the correct Board and Port

Step 4: Upload the sketch to the SunFounder Uno board

_images/image2231.png

Now, adjust the potentiometer connected to pin A0, and you will see the voltage displayed on the LCD1602 varies accordingly.

_images/image141.jpeg
Code
Code Analysis 15-1 Define the pins of LCD1602 andpotentiometer
#include <LiquidCrystal.h>

/****************************************************/

float analogIn = 0;                      // store the analog value of A0

LiquidCrystal lcd(4, 6, 10, 11, 12, 13); // lcd(RS,E,D4,D5,D6.D7)

float vol = 0;                           // store the voltage

Call the LiquidCrystal library and define the pins of LCD1602 connect to 4,6 and 10 to 13 of Uno board.

Assign the value of A0 to analogIn.

Code Analysis 15-2 Initialize the LCD1602 and serial monitor
void setup()

{

    Serial.begin(9600);          // Initialize the serial monitor

    lcd.begin(16, 2);            // set the position of the characters on the LCD as Line 2, Column 16

    lcd.print("Voltage Value:"); // print "Voltage Value:"

}

Initialize the baud rate of serial monitor to 9600bps and set the position of the characters on the LCD as Line 2, Column 16. Print “Voltage Value: ” on the LCD1602.

Code Analysis 15-3 Read the analog of A0 and convert to voltage
void loop()

{

    analogIn = analogRead(A0); // Read the value of the potentiometer to val

    vol = analogIn/1024*5.0;     // Convert the data to the corresponding voltage value in a math way

    Serial.print(vol);           // Print the number of val on the serial monitor

    Serial.println("V");       // print the unit as V, short for voltage on the serial monitor

    lcd.setCursor(6,1);      // Place the cursor at Line 1, Column 6. From here the characters are to be displayed

    lcd.print(vol);             // Print the number of val on the LCD

    lcd.print("V");            // Then print the unit as V, short for voltage on the LCD

    delay(200);                // Wait for 200ms

}

The analog value of A0 is: Analog value=5/VA0 * 1024, so VA0= Analog value/1024 * 5, if you connect the potentiometer to 3.3v, then modify 5V to 3.3V.

Print the voltage to serial monitor or the LCD1602.

Lesson 16 Automatically Tracking Light Source
Introduction

In this lesson, we will make some interesting creations – use a servo motor, a photoresistor and a pull-down resistor to assemble an automatically tracking light source system.

Components
_images/image198.png
Experimental Principle

The rocker arm of the servo and the bundled photoresistor sway together to scan and “look” for light source within 180 degrees and record the location of light source when finding one. Then they stop swaying just at the direction of the light source.

The schematic diagram:
_images/image142.png
Experimental Procedures

Step 1: Build the circuit

_images/image143.png

Note

you need to bind one end of the resistor and photoresistor to the rocker arm of the servo (cross the pin through the holes of the arm).

1) Insert one pin of the photoresistor and 10 resistor through the holes on the rocker arm. Pay attention here to tightly winding them because you need to make sure they are connected in the circuit.

_images/image1441.png

2) Plug in the rock arm to the servo and use 3 jumper wires to hook up the 3 pins.

pay attention to plug the pin tightly in case of disentanglement.

_images/image2241.png

3) Hook up the middle pin to pin A0 of the Uno board, another pin of the 10k resistor to GND, photoresistor to 5V.

_images/image146.png

4) Connect the brown wire of servo to GND and red to 5v. Since the 5v usually used is occupied already, you need to connect the other 5v as the following picture shows.

_images/image1471.png

5) Next connect the orange wire to pin 9 of the SunFounder Uno board. OK now the circuit is completed! Connect the Uno board to your computer with a USB cable.

_images/image145.png

Step 2: Open the code file

Step 3: Select the correct Board and Port

Step 4: Upload the sketch to the SunFounder Uno board

Now, shine a flashlight onto the photoresistor. Then you will see the rocker arm of the servo and the photoresistor rotate and finally stop at the direction of light source.

Code
Code Analysis 16-1 Initialize and define variables
#include <Servo.h>

const int photocellPin = A0; //The photoresistor is connected to A0

/************************************************/

Servo myservo;//create servo object to control a servo

int outputValue = 0; //Save the value read from A0

int angle[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180};
//Define the angle of servo

int maxVal = 0; //Record the maximum number

int maxPos = 0; //Record the angle of the servo when the read the maximum number of photoresistor.

Define an integer array angle[], which contains 19 elements from 0 to 18, representing 0 to 180 which indicates the degree of servo rotation. For example, angle[0] means 0 degree, angle[1] is 10 degrees, and so forth.

Code Analysis 16-2 Servo rock arm stop at the direction of light source
void loop()

{

    for(int i = 0; i < 19; i ++)

    {

        myservo.write(angle[i]);
        //write the angle from the angle[i] array to servo.
        //When i=0, angle[0]=0, i=1, angle[1]=10, and so on.

        outputValue = analogRead(photocellPin); //read the value of A0

        Serial.println(outputValue); //print it

        if(outputValue > maxVal)
        //if the current value of A0 is greater than previous

        {

            maxVal = outputValue; // write down the value

            maxPos =i; // write down the angle

        }

        delay(200); // delay 200ms

    }

    myservo.write(angle[ maxPos]);
    // write the angle to servo which A0 has greatest value

    delay(1000); //delay 1s

}

Set the servo to rotate from 0 to 180, and the angle is defined in the angle [] array. Since the photoresistor is wound with the servo rock arm, the resistance of the photoresistor changes with different light intensities each time the servo is rotated, so the analog value of A0 is changed at the same time.

By comparing the value of A0 with the previously recorded maximum value, record the maximum A0 value and current angle of the servo. Finally let the servo turn to this angle.

Lesson 17 Light Alarm
Introduction

This experiment is a very interesting one – a DIY phototransistor. DIY phototransistors use the glow effect and photoelectric effect of LEDs. That is, LEDs will generate weak currents when some light is shined on it. And we use a transistor to amplify the currents generated, so the SunFounder Uno board can detect them.

Components
_images/image171.png _images/image199.png
Experimental Principle

LEDs not only have a glow effect, but also a photoelectric effect. They will generate weak currents when exposed to light waves.

NPN consists of a layer of P-doped semiconductor (the “base”) between two N-doped layers (see the picture above). A small current entering the base is amplified to produce a large collector and emitter current. That is, when there is a positive potential difference measured from the emitter of a NPN transistor to its base (i.e., when the base is high relative to the emitter) as well as positive potential difference measured from the base to the collector, the transistor becomes active. In this “on” state, current flows between the collector and emitter of the transistor.

A 10kΩ pull-down resistor is attached to the transistor output stage in order to avoid analog port suspending to interfere with signals and cause misjudgment.

When the LED exposed to light waves, the LED generates weak currents, then the NPN transistor becomes active. Then read the analog value of A0, when A0>0, then set pin 5(buzzer) to high level.

The schematic diagram:

_images/image211.png

Experimental Procedures

Step 1: Build the circuit.

Step 2: Open the code file

Step 3: Select the correct Board and Port

Step 4: Upload the sketch to the board

_images/image2251.png

Now, you can hear the buzzer beep when shining a flashlight on the LED.

Note

You need to do this experiment in a dark environment, or the lights you give need to be much stronger than ambient light.

_images/image1511.jpeg
Code
Code Analysis 17-1 Whole Code
void setup()

{

    Serial.begin(9600);    // start serial port at 9600 bps:

}

void loop()

{

    int n=analogRead(A0); //read the value from analog pin AO

    Serial.println(n);

    if(n>0) //If there is a voltage

    {

        pinMode(5,OUTPUT); //set the digital pin 5 as an output

        tone(5,10000);
        //Generates a square wave of the frequency of 10000 Hz (and 50% duty cycle) on pin 5

        pinMode(5,INPUT); //set the pin 5 as an input

    }

}
tone()
Description

Generates a square wave of the specified frequency (and 50% duty cycle) on a pin. A duration can be specified, otherwise the wave continues until a call to noTone(). The pin can be connected to a piezo buzzer or other speaker to play tones.

Only one tone can be generated at a time. If a tone is already playing on a different pin, the call to tone() will have no effect. If the tone is playing on the same pin, the call will set its frequency.

Use of the tone() function will interfere with PWM output on pins 3 and 11 (on boards other than the Mega).

Syntax

tone(pin, frequency)

tone(pin, frequency, duration)

Parameters

pin: the pin on which to generate the tone

frequency: the frequency of the tone in hertz - unsigned int

duration: the duration of the tone in milliseconds (optional) - unsigned long

Lesson 18 Answer Machine
Introduction

In quiz shows, especially entertainment activities (e.g. competitive answering activities), organizers often apply a buzzer system in order to accurately, fairly and visually determine the seat number of a responder.

Now the system can illustrate the accuracy and equity of the judgment by data, which improves the entertainment. At the same time, it is more fair and just. In this lesson, we will use some buttons, buzzers, and LEDs to make a quiz buzzer system.

Components
_images/image171.png _images/image200.png
Experimental Principle

Button 1, 2 and 3 are answer buttons, and button 4 is the reset button. If button 1 is pressed first, the buzzer will beep, the corresponding LED will light up and all the other LEDs will go out. If you want to start another round, press button 4 to reset.

The schematic diagram:

_images/image155.png

Experimental Procedures

Step 1:Build the circuit

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

_images/image2261.png

Now, first press button 4 to start. If you press button 1 first, you will see the corresponding LED light up and the buzzer will beep. Then press button 4 again to reset before you press other buttons.

_images/image1571.jpeg
Code

The code for this experiment may be a bit long. But the syntax issimple. Let’s see. Workflow: Read the state of button 4, if button 4 is pressed, theLED on pin 10 is illuminated while reading the state of the remaining buttons. If one of the buttons is detected to be pressed, the buzzer beeps and lights the corresponding LED until button 4 is pressed again.

Code Analysis 18-1 loop() function
b4State = digitalRead(button4); // read the value of button4 to see if it was pressed.

Serial.println(b4State); // print it value.

//when button4 pressed

if(b4State == 0) // if the button4 is pressed, the b4State=0

{

    if(b4State == 0) /*confirm that the button4 is pressed. One pin of the
    button is connected to pin 9, the other pin is connected to GND, and
    when the button is pressed, pin 9 is pulled low.*/

    {

        flag = 1; // if so,flag is 1

        digitalWrite(LED4, HIGH); // turn the reset LED on

        delay(200); // delay 200ms

    }

}

if(1 == flag)

{

    // read the state of other buttons

    b1State = digitalRead(button1);

    b2State = digitalRead(button2);

    b3State = digitalRead(button3);

    // If the button1 press the first

    if(b1State == 0) // if button1 is pressed

    {

        flag = 0; // flag equals to 0

        digitalWrite(LED4, LOW);

        Alarm(); // buzzer sound

        digitalWrite(LED1,HIGH); // turn the LED1 on only

        digitalWrite(LED2,LOW);

        digitalWrite(LED3,LOW);

        while(digitalRead(button4)); // detect the button4,if pressed,out of the while loop

    }

    ...

Use the same way to detect the button2 and button3, if one of the buttons is detected to be pressed, the buzzer beeps and lights the corresponding LED until button 4 is pressed again.

Code Analysis 18-2 Alarm() function
void Alarm()

{

    for(int i=0;i<100;i++)
    {

        digitalWrite(buzzerPin,HIGH); // the buzzer sound

        delay(2); // delay 2ms

        digitalWrite(buzzerPin,LOW); // without sound

        delay(2); // when delay time changed,the frequency changed

    }

}

The alarm() function is to set the buzzer to beep. You can change the frequency and time of the buzzer sound.

Lesson 19 Controlling Voice by Light
Introduction

Previously we have learnt how to use a photoresistor. In this lesson, let’s get further - control a buzzer to beep in different frequencies by the photoresistor.

Components
_images/image171.png _images/image201.png
Experiment Principle

When you shine some light on the photoresistor, if the incident light gets stronger, the resistance of the photoresistor will decrease; if the incident light becomes weaker, the resistance will increase. We can apply this principle to change the voltage distribution in the circuit.

In this experiment, the output of the photoresistor is sent to pin A0 on the SunFounder Uno board and then processed by the ADC on the board to output a digital signal. We use this digital signal as the parameter of the delay() function in the sketch to make the buzzer beep.

When the incident light is strong, the output value gets greater, thus the buzzer will beep slowly; when incident light is weak, the output value is smaller, thus the buzzer will beep sharply.

The schematic diagram:

_images/image158.png

Experiment Procedures

Step 1: Build the circuit

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

_images/image2271.png

Now, if you place the photoresistor in a dark environment, the buzzer will beep sharply; if you shine a flashlight on the photoresistor, the buzzer beeping will slow down.

_images/image160.jpeg
Code
Code Analysis 19-1 Set the array elements
void loop()

{

    sensorValue = analogRead(photocellPin); //read the value of A0

    digitalWrite(buzzerPin, HIGH);

    delay(sensorValue); //wait for a while,and the delay time depend on the sensorValue

    digitalWrite(buzzerPin, LOW);

    delay(sensorValue);

}

The value of the photoresistor is read, and when the incident light is strong, the output value becomes large. Then set the buzzer to high level to make it beep, delay the sensorvalue ms, then turn off the buzzer and also delay the sensorvalue ms. So you can see that if you put the photoresistor in a dark environment, the buzzer will make a sharp humming sound; if you illuminate the flashlight on the photoresistor, the buzzer will beep.

Lesson 20 74HC595
Introduction

Generally, there are two ways to drive a single 7-segment display. One way is to connect its 8 pins directly to eight ports on the Uno board. Or you can connect the 74HC595 to three ports of the Uno board and then the 7- segment display to the 74HC595. In this experiment, we will use the latter. By this way, we can save five ports – considering the Uno board’s limited ports, this is very important. Now let’s get started!

Components
_images/image171.png _images/image202.png
Experimental Principle
7-Segment Display

A 7-segment display is an 8-shaped component which packages 7 LEDs. Each LED is called a segment – when energized, one segment forms part of a numeral (both decimal and hexadecimal) to be displayed. An additional 8th LED is sometimes used within the same package thus allowing the indication of a decimal point (DP) when two or more 7-segment displays are connected together to display numbers greater than ten.

_images/image1631.jpeg

Each of the LEDs in the display is given a positional segment with one of its connection pins led out from the rectangular plastic package. These LED pins are labeled from “a” through to “g” representing each individual LED. The other LED pins are connected together forming a common pin. So by forward biasing the appropriate pins of the LED segments in a particular order, some segments will brighten and others stay dim, thus showing the corresponding character on the display.

The common pin of the display generally tells its type. There are two types of pin connection: a pin of connected cathodes and one of connected anodes, indicating Common Cathode (CC) and Common Anode (CA). As the name suggests, a CC display has all the cathodes of the 7 LEDs connected when a CA display has all the anodes of the 7 segments connected.

Common Cathode 7-Segment Display

In a common cathode display, the cathodes of all the LED segments are connected to the logic “0” or ground. Then an individual segment (a-g) is energized by a “HIGH”, or logic “1” signal via a current limiting resistor to forward bias the anode of the segment.

_images/image164.jpeg
Common Anode 7-Segment Display

In a common anode display, the anodes of all the LED segments are connected to the logic “1”. Then an individual segment (a-g) is energized by a ground, logic “0” or “LOW” signal via a current limiting resistor to the cathode of the segment.

_images/image165.jpeg
74HC595

The 74HC595 consists of an 8−bit shift register and a storage register with three−state parallel outputs. It converts serial input into parallel output so you can save IO ports of an MCU.

When MR (pin10) is high level and OE (pin13) is low level, data is input in the rising edge of SHcp and goes to the memory register through the rising edge of SHcp. If the two clocks are connected together, the shift register is always one pulse earlier than the memory register. There is a serial shift input pin (Ds), a serial output pin (Q) and an asynchronous reset button (low level) in the memory register. The memory register outputs a Bus with a parallel 8-bit and in three states. When OE is enabled (low level), the data in memory register is output to the bus.

_images/image166.png

Pins of 74HC595 and their functions:

Q0-Q7: 8-bit parallel data output pins, able to control 8 LEDs or 8 pins of 7-segment display directly.

Q7’: Series output pin, connected to DS of another 74HC595 to connect multiple 74HC595s in series

MR: Reset pin, active at low level; here it is directly connected to 5V.

SHcp: Time sequence input of shift register. On the rising edge, the data in shift register moves successively one bit, i.e. data in Q1 moves to Q2, and so forth. While on the falling edge, the data in shift register remain unchanged.

STcp: Time sequence input of storage register. On the rising edge, data in the shift register moves into memory register.

OE: Output enable pin, active at low level. Here connected to GND.

DS: Serial data input pin

VCC: Positive supply voltage

GND: Ground

Principle:

In the experiment MR (pin10) is connected to 5V (HIGH Level) and OE (pin 13) to GND (LOW Level). Therefore, the data is input into the rising edge of SHcp and enters the memory register through the rising edge. We use the shiftout() function to output a 8-bit data to the shift register through DS. In the rising edge of the SHcp, the data in the shift register moves successively one bit in one time, i.e. data in Q1 moves to Q2, and so forth. In the rising edge of STcp, data in the shift register moves into the memory register. All data will be moved to the memory register after 8 times. Then the data in the memory register is output to the bus (Q0-Q7). So the 16 characters are displayed in the 7-segment in turn.

The schematic diagram:

_images/image212.png
Experimental Procedures

Step 1: Build the circuit (pay attention to the direction of the chip by the concave on it)

_images/image203.png

Step 2: Open the code file.

Step 3: Select the Board and Port.

Step 4: Upload the sketch to the board.

You should now see the 7-segment display from 0 to 9 and A to F.

_images/image169.jpeg
Code
Code Analysis 20-1 Set the array elements
int datArray[16] = {252, 96, 218, 242, 102, 182, 190, 224, 254, 246, 238, 62, 156, 122, 158, 142};

This array stores the data of the 16 characters from 0 to F. 218 stands for 2, which you can calculate by yourself. To display 2, the segment f and c of the 7-segment display must be low level (dim).

Since the segment f and c are connected to Q2 and Q5 of the 74HC595, set both Q0, Q2 and Q5 (the dot) as low level and leave the rest pins as high level. Therefore, the values of Q7 Q6 Q5 Q4 Q3 Q2 Q1 Q0 are 1 1 0 1 1 0 1 0.

Change the binary numbers into decimal ones: 1x27+1x26+0x25+1x24+1x23+0x22+1x21+0x20=218.

_images/image1701.jpeg

So that’s the value for the number 2 to be displayed. You can calculate other characters similarly.

Code Analysis 20-2 Display 0-F in the 7-segment display
for(int num = 0; num < 16; num++)

{

    digitalWrite(STcp,LOW); // ground ST_CP and hold low for as long as you are transmitting

    shiftOut(DS,SHcp,MSBFIRST,datArray[num]);

    // return the latch pin high to signal chip that it

    // no longer needs to listen for information

    digitalWrite(STcp,HIGH); // pull the ST_CPST_CP to save the data

    delay(1000); // wait for a second

}

Set STcp as low level first and then high level. It will generate a rising edge pulse of STcp.

shiftOut() is used to shift out a byte of data one bit at a time, which means to shift a byte of data in dataArray[num] to the shifting register with the DS pin. MSBFIRST means to move from high bits.

After digitalWrite(STcp,HIGH) is run, the STcp will be at the rising edge. At this time, the data in the shift register will be moved to the memory register.

A byte of data will be transferred into the memory register after 8 times. Then the data of memory register is output to the bus (Q0-Q7). You will see a character is displayed on the 7-segment. Then delay for 1000ms. After that line, go back to for(). The loop repeats until all the characters are displayed in the 7-segment display one by one after 16 times.

FAQ

C code is not working?

  • Check your wiring for problems.

  • Check if the code is reporting errors, if so, refer to: Check and Install the WiringPi.

  • Has the code been compiled before running.

  • If all the above 3 conditions are OK, it may be that your wiringPi version (2.50) is not compatible with your Raspberry Pi 4B and above, refer to Check and Install the WiringPi to manually upgrade it to version 2.52.

Thank You

Thanks to the evaluators who evaluated our products, the veterans who provided suggestions for the tutorial, and the users who have been following and supporting us. Your valuable suggestions to us are our motivation to provide better products!

Particular Thanks

  • Len Davisson

  • Kalen Daniel

  • Juan Delacosta

Now, could you spare a little time to fill out this questionnaire?

Note

After submitting the questionnaire, please go back to the top to view the results.