Sarful H. Arduino Programming for Absolute Beginners 2024
Sarful H. Arduino Programming for Absolute Beginners 2024
Absolute Beginners
First Edition
By Sarful Hassan, MechatronicsLAB
Preface
Welcome to the Second Edition of Arduino programming for
beginners. This edition builds upon the foundation laid in the
first, with expanded content, deeper insights into advanced
Arduino programming concepts, and a greater focus on real-
world applications. Whether you're just starting out or
looking to elevate your skills, this edition will provide the
knowledge you need to succeed in Arduino programming.
How to Contact Us
We encourage feedback and are happy to answer any
questions you may have. Please contact us at:
Email: mechatronicslab@gmail.com
Website: www.mechatronicslab.net
Copyright
© 2024 MechatronicsLAB
All rights reserved. No part of this book may be reproduced,
stored, or transmitted by any means without prior written
permission from the publisher, except in the case of brief
quotations for reviews or educational purposes.
Disclaimer
The information in this book is provided on an “as-is” basis
without any warranties. While every effort has been made to
ensure accuracy, the author and publisher are not
responsible for any errors, omissions, or inaccuracies.
Always exercise caution when working with electronics, and
consult product manuals and safety guidelines. The
examples provided are for educational purposes, and the
author and publisher are not liable for any damages or
injuries resulting from their use.
Contents
Arduino Programming for Absolute Beginners
Preface
Chapter-1 Introduction to Arduino
Overview of the Arduino Platform
Understanding the Arduino Board
How to Choose the Right Arduino Board for
Beginners
Setting Up the Arduino IDE
Writing Your First Program (The "Hello World" of Arduino)
Overview of Common Arduino Libraries
Chapter 2: Arduino Variables and Data Types
1. Introduction to Variables and Data Types in
Arduino
1.1 What are Variables and Data Types?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Data Types
2. Arrays in Arduino
2.1 Introduction to Arrays
2.2 Working with Arrays
3. Basic Data Types
3.1 The bool Data Type
3.2 The byte Data Type
3.3 The int Data Type
4. Advanced Data Types
4.1 The long Data Type
4.2 The float Data Type
4.3 The double Data Type
5. Strings in Arduino
5.1 Using char Arrays for Strings
5.2 The String Object in Arduino
6. Unsigned Variables in Arduino
6.1 The unsigned char Data Type
7. Constants in Arduino
7.1 The const Keyword
8. Practical Projects for Mastering Variables and Data
Types
8.1 Project 1: Controlling LEDs with Arrays
8.2 Project 2: Temperature-Based Fan Control
using float
8.3 Project 3: Measuring Distance Using long for Timing
8.4 Project 4: Displaying Text and Numbers Using char
Arrays and String
9. Common Troubleshooting and Debugging Tips
10. Conclusion and Next Steps
Chapter 4: Arduino Input/Output Functions
1. Introduction to Arduino Input/Output
Operations
2. Basic Digital Input/Output Functions
2.1 The digitalRead() Function: Reading Digital Inputs
2.2 The digitalWrite() Function: Controlling Digital
Outputs
2.3 The pinMode() Function: Configuring Pins for
Input/Output
3. Analog Input/Output Functions
3.1 The analogRead() Function: Reading Analog
Inputs
3.2 The analogWrite() Function: Controlling
Outputs with PWM
4. Advanced Input/Output Functions
4.1 The analogReadResolution() Function:
Increasing Input Precision
4.2 The analogWriteResolution() Function: Finer
Control Over PWM Signals
5. Practical Projects for Mastering Input/Output
5.1 Project 1: Controlling an LED with a Push
Button
5.2 Project 2: Temperature-Based Fan Control
5.3 Project 3: Analog Sensor-Controlled Motor
Speed
6. Common Troubleshooting and Debugging Tips
7. Conclusion and Next Steps
Chapter 4: Timing Functions in Arduino Programming
1.1 What is Timing in Arduino?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Timing Functions
2. Basic Timing Functions
2.1 The delay() Function: Pausing the Program
2.2 The delayMicroseconds() Function: Precise
Short Delays
2.3 The micros() Function: Measuring Microsecond
Time Intervals
3. Advanced Timing Functions
3.1 Comparing delay(), delayMicroseconds(),
micros(), and millis()
4. Practical Projects for Mastering Timing Functions
4.1 Project 1: Button-Controlled LED with delay()
4.2 Project 2: Precise PWM Signal Generation with
delayMicroseconds()
5. Common Troubleshooting and Debugging Tips
6. Conclusion and Next Steps
Chapter 5: Control Structures
1. Introduction to Control Structures
1.1 What are Control Structures?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Control Structures
2. Decision-Making Structures
2.1 The if Statement
2.2 The if...else Statement
2.3 The switch...case Statement
3. Loop Structures
3.1 The for Loop
3.2 The while Loop
3.3 The do...while Loop
4. Controlling Loops and Flow
4.1 The break Statement
4.2 The continue Statement
5. Functions and Program Flow
5.1 The return Statement
5.2 The goto Statement
6. Projects
6.1 Project 1: Smart Thermostat Control System
6.2 Project 2: Automated LED Control Based on
Temperature
6.3 Project 3: Smart Irrigation System with if...else
6.4 Project 4: Traffic Light Control with switch...case
and Loops
7. Common Troubleshooting and Debugging Tips
8. Conclusion and Next Steps
Chapter 6: Maths and Trigonometry Functions
1. Introduction to Math and Trigonometry Functions in
Arduino
1.1 What are Math and Trigonometry Functions in
Arduino?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Math and Trigonometry
Functions
2. Basic Math Functions
2.1 The abs() Function: Absolute Value
Calculation
2.2 The constrain() Function: Limiting Values
2.3 The map() Function: Re-mapping Values
2.4 The max() Function: Ensuring a Minimum
Value
2.5 The min() Function: Limiting Values to a
Maximum
3. Advanced Math and Trigonometry Functions
3.1 The pow() Function: Raising to a Power
3.2 The sq() Function: Squaring a Value
3.3 The sqrt() Function: Calculating Square Roots
3.5 The sin() Function: Calculating Sine of an
Angle
3.6 The tan() Function: Calculating Tangent of an
Angle
4. Practical Projects for Mastering Math and
Trigonometry Functions
4.1 Project 1: Using pow() for Exponential LED
Brightness Control
4.2 Project 2: Calculating Distance Between Two
Points using sqrt()
4.3 Project 3: Creating a Sine Wave for Servo
Motor Movement using sin()
4.4 Project 4: Mapping Temperature Readings
using map() for Fan Speed Control
5. Common Troubleshooting and Debugging Tips
6. Conclusion and Next Steps
Chapter 7: Comparison and Boolean Operators
1. Introduction to Comparison and Boolean
Operators
1.1 What are Comparison and Boolean Operators?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Comparison and Boolean
Operators
2. Core Comparison Operators
2.1 The == (Equal To) Operator
2.2 The != (Not Equal To) Operator
2.3 The > (Greater Than) Operator
2.4 The < (Less Than) Operator
3. Core Boolean Operators
3.1 The && (Logical AND) Operator
3.2 The || (Logical OR) Operator
3.3 The ! (Logical NOT) Operator
4. Combining Comparison and Boolean Operators
4.1 Using == and && Together
4.2 Using != and || Together
5. Practical Projects for Mastering Comparison and
Boolean Operators
5.1 Project 1: Smart Temperature and Humidity Control
System
5.2 Project 2: Home Security System with Multiple
Sensors and Alarms
5.3 Project 3: Automated Garden Watering System with
Multiple Conditions
5.4 Project 4: Traffic Light System with Emergency
Vehicle Detection
Chapter 8. Random Numbers in Arduino
1. Introduction to Random Numbers in Arduino
1.1 What are Random Numbers in Arduino?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Random Number Functions
2. Basic Random Number Functions
2.1 The random() Function: Generating Random
Numbers
2.2 The randomSeed() Function: Initializing
Random Number Generator
3. Advanced Random Number Applications
3.1 Generating Random Numbers for Dynamic LED
Behavior
3.2 Using random() in Games or Simulations
4. Practical Projects for Mastering Random Numbers
4.1 Project 1: Creating Random LED Blink Patterns
4.2 Project 2: Random Sensor Data Simulation
5. Common Troubleshooting and Debugging Tips
6. Conclusion and Next Steps
Chapter 9: Interrupts in Arduino
1. Introduction to Interrupts in Arduino
2. attachInterrupt() Function: Attaching
Interrupts to Pins
3. detachInterrupt() Function: Detaching
Interrupts
4. Interrupt Service Routine (ISR) in Arduino
5. Polling vs Interrupts
6. Debouncing and Interrupts
7. Edge Detection Modes in Interrupts
8. Common Mistakes and Best Practices with
Interrupts
9. Practical Project: Motion Detection using
Interrupts
10. Quiz: Test Your Understanding of Interrupts
11. Conclusion and Next Steps
Chapter 10: Advanced Input/Output Functions
1. Introduction to Advanced I/O Operations
1.1 What are Advanced I/O Functions?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Advanced I/O Functions
2. Basic Advanced I/O Functions
2.1 The noTone() Function: Stopping Sound
Output
2.2 The pulseIn() Function: Measuring Pulse
Widths
2.3 The pulseInLong() Function: Measuring Long
Pulses
2.4 The shiftIn() Function: Reading Data Bit by
Bit
2.5 The shiftOut() Function: Sending Data Bit by
Bit
4. Practical Projects for Mastering Advanced I/O
Functions
4.1 Project 1: Using pulseIn() with an Ultrasonic
Sensor
4.2 Project 2: Controlling an 8-Segment Display
using shiftOut()
4.3 Project 3: Reading Data from Multiple Shift
Registers with shiftIn()
5. Common Troubleshooting and Debugging Tips
6. Conclusion and Next Steps
Chapter 11: Communication Protocols with Arduino
1. Introduction to Communication Protocols in
Arduino
2. I2C Protocol: Communicating with Multiple
Devices
3. SPI Protocol: High-Speed Communication
4. UART Communication: Serial Data Transfer
5. Practical Project: Communication with Multiple
Devices
6. FAQ: Common Questions About Communication
Protocols
7. Quiz: Test Your Understanding of
Communication Protocols
Chapter 12: Bitwise Operators
1. Introduction to Bitwise Operators
1.1 What are Bitwise Operators?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Bitwise Operators
2. Core Bitwise Operators
2.1 The << (Left Shift) Operator
2.2 The >> (Right Shift) Operator
2.3 The & (Bitwise AND) Operator
2.4 The | (Bitwise OR) Operator
2.5 The ~ (Bitwise NOT) Operator
3. Combining Bitwise Operators
3.1 Using & and | for Bit Masking
3.2 Using ~ to Invert Bits for Complementary Values
3.3 Advanced Bit Shifting Techniques
4. Practical Projects for Mastering Bitwise Operators
4.1 Project 1: Controlling Multiple LEDs with a Single
Variable
5. Common Troubleshooting and Debugging Tips
6. Conclusion and Next Steps
Chapter 13: Memory Management in Arduino
1. Introduction to Memory Management in
Arduino
2. Understanding Memory Types in Arduino
3. Storing and Reading Data from EEPROM
4. Flash Memory: Storing Data Efficiently
5. Optimizing SRAM Usage in Large Projects
6. Practical Project: Using EEPROM for Non-
Volatile Storage
7. FAQ: Common Questions About Memory
Management
8. Quiz: Test Your Memory Management
Knowledge
Chapter 14: Conversion Techniques,
1. Introduction to Conversion Techniques
1.2 Overview of Common Conversion Functions
2. The byte() Function
3. The char() Function
4. The float() Function
5. The int() Function
6. The long() Function
7. The (unsigned int) Conversion
8. The (unsigned long) Conversion
9. Practical Projects for Mastering Conversion
Techniques
9.1 Project 1: Converting Analog Temperature
Data to Fahrenheit and Celsius
9.2 Project 2: Mapping Sensor Values Using int()
and long()
9.3 Project 3: Timing Events with (unsigned long)
and long() for LED Control
9.4 Project 4: Converting Sensor Data for
Communication with Other Devices
10. Common Troubleshooting and Debugging Tips
11. Conclusion and Next Steps
Chapter 15: Characters and Strings
1. Introduction to Character and String Functions
in Arduino
1.1 What are Characters and Strings in Arduino?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Character and String
Functions
2. Basic Character Validation Functions
2.1 The isAlpha() Function: Checking for Letters
2.2 The isDigit() Function: Checking for Numbers
2.3 The isAscii() Function: Checking for ASCII
Characters
3. Advanced Character and String Functions
3.1 The isUpperCase() Function: Checking for
Uppercase Letters
3.2 The isLowerCase() Function: Checking for
Lowercase Letters
3.3 The isPrintable() Function: Validating
Printable Characters
4. Practical Projects for Mastering Character and
String Functions
4.1 Project 1: Validating User Input
4.2 Project 2: Formatting and Displaying Text
4.3 Project 3: Creating a Password Input System
4.4 Project 4: Serial Monitor Data Entry and
Validation
4.5 Project 5: Data Logger with Validated Input
5. Common Troubleshooting and Debugging Tips
Chapter 16: Arithmetic and Compound Operators
1. Introduction to Arithmetic and Compound
Operators
1.1 What are Arithmetic and Compound
Operators?
1.2 Key Concepts and Terms (Glossary)
1.3 Overview of Core Arithmetic and Compound
Operators
2. Core Arithmetic Operators
2.1 The + (Addition) Operator
2.2 The - (Subtraction) Operator
2.3 The * (Multiplication) Operator
2.4 The / (Division) Operator
2.5 The % (Remainder) Operator
3. Core Compound Operators
3.1 The += (Compound Addition) Operator
3.2 The -= (Compound Subtraction) Operator
3.3 The *= (Compound Multiplication) Operator
3.4 The /= (Compound Division) Operator
4. Using Arithmetic and Compound Operators in
Projects
4.1 Project 1: LED Brightness Control with Compound
Operators
4.2 Project 2: Servo Motor Angle Control with Arithmetic
Operators
4.3 Project 3: Automated Fan Speed Control with
Compound Operators
5. Common Troubleshooting and Debugging Tips
6. Conclusion and Next Steps
Chapter 17: Arduino with Displays
1 Introduction to Arduino Display Systems
2 Key Concepts and Terms (Glossary)
3 Overview of Display-Related Functions
4 Using LCD with Arduino
4.1 LCD Initialization and Basic Displaying Functions
4.2 Displaying Sensor Data on LCD
5 Using OLED with Arduino
5.1 OLED Initialization and Basic Displaying Functions
5.2 Displaying Graphics on OLED
18.6 Using TFT with Arduino
6.1 TFT Initialization and Touch Input
18.7 Advanced Display Functions
7.1 Custom Fonts and Animations
18.8 Practical Projects for Display Mastery
8.1 Project 1: Simple Temperature and Humidity Monitor
8.2 Project 2: Touch-Controlled RGB LED Matrix
18.9 Advanced Display Functions
9.1 Project 3: Dynamic Sensor Data Visualization with
OLED
9.2 Project 4: Animated Weather Dashboard with TFT
9.3 Project 5: Custom Fonts and Animation in OLED
10 Conclusion and Next Steps
Chapter-1 Introduction to Arduino
Overview of the Arduino Platform
Arduino is an open-source electronics platform based on
simple, user-friendly hardware and software, designed to
make electronics accessible to a wide range of users, from
beginners to advanced professionals. The platform consists
of a physical programmable circuit board, often referred to
as a microcontroller, and a software component called the
Arduino Integrated Development Environment (IDE). The IDE
is used to write and upload code to the board. Programs for
Arduino are written in a language based on C/C++, but it
also uses a simplified Arduino library that makes creating
interactive projects much easier.
The platform's hardware comes in various models, each
featuring different specifications, like the Arduino Uno,
Arduino Mega, and others. These boards can be connected
to sensors, actuators, motors, and other components,
making them suitable for building anything from simple LED
light displays to sophisticated IoT applications.
History and Evolution of Arduino
The Arduino platform was created in 2005 by a group of
engineers, including Massimo Banzi, as a tool for students at
the Interaction Design Institute Ivrea, Italy. The intention
was to develop an affordable, open-source tool that would
make it easier for students and artists to work with
technology in creative ways.
Arduino quickly gained popularity, driven by its simplicity,
affordability, and the vast opportunities it offered for
learning and experimentation. Over the years, the Arduino
platform has evolved, introducing a wide range of boards to
meet the needs of different projects. The evolution included
developing boards like Arduino Uno for general purposes,
Arduino Mega for projects needing more input/output pins,
and specialized versions like the Arduino Nano and Arduino
Pro Mini for compact projects. The platform also supports
wireless communication with versions such as Arduino MKR
and the Arduino Nano 33 IoT, aimed at making IoT
prototyping easy.
Why Arduino is Popular for Beginners and
Professionals
Arduino has gained widespread popularity due to its unique
ability to appeal to both beginners and professionals alike.
Beginner-Friendly:
Easy to use with a plug-and-play experience.
Simple programming language based on C/C++.
Lots of tutorials, sample codes, and a helpful
community.
Arduino ATmega328P 14 6 6 5V 32 KB 16
Uno MHz
Arduino ATmega32u4 20 12 7 5V 32 KB 16
Micro MHz
Arduino ATmega328P 14 8 6 5V or 32 KB 16
Pro Mini 3.3V MHz
(5V)
/8
MHz
(3.3
V)
Arduino ATSAMD21G 14 6 10 3.3V 256 48
Zero 18 KB MHz
Arduino ATSAMW25 8 7 12 3.3V 256 48
MKR10 KB MHz
00
Image source:arduino.cc
1. Code Editor:
The main area is where you write the code
(called sketches). It’s simplified to avoid
overwhelming beginners, with features like
basic syntax highlighting to help differentiate
various code components.
Professionals can take advantage of
extensions and plugins to add more
functionality, such as code linting or
integration with external version control
systems.
2. Menu Bar:
The File menu allows you to create, open, and
save sketches. You can also find built-in
example codes here—perfect for beginners
wanting to learn how to use sensors or control
LEDs.
The Tools menu gives you options for board
selection, port selection, and other settings
needed to upload the code, allowing
professionals to configure advanced settings.
3. Buttons in the Toolbar:
Verify (checkmark icon): This button checks
your code for any errors. It helps beginners
ensure their code is correct before uploading.
Upload (arrow icon): After verifying, click this
button to upload the code to your board. This
is one of the first steps beginners learn.
New, Open, Save: These buttons make
managing your sketches easy, just like in other
text editors.
Serial Monitor: This button opens a window
that allows you to see real-time data from the
Arduino. Beginners often use this to display
sensor values, while professionals use it
extensively for debugging.
4. Status Area:
Below the code editor is a status bar that
shows information like compilation errors or
successful uploads. For beginners, this area
helps in identifying issues, while professionals
use the detailed output to troubleshoot their
projects effectively.
5. Examples and Libraries:
Arduino provides many built-in examples in
the IDE. Beginners can learn basic
functionality like blinking an LED or reading
sensor data by going to File > Examples.
Professionals can include external libraries
using Sketch > Include Library, enabling
advanced functionalities like networking,
communication, and more complex hardware
interaction.
Tips
The onboard LED (labelled L on many boards) is
connected to pin 13, making it an excellent first
experiment since no additional components are needed.
If you encounter errors, check that you selected the
correct board and port in the Tools menu, and ensure
your code doesn’t have typos.
2. Arrays in Arduino
2.1 Introduction to Arrays
What is an Array?
An array is a collection of variables stored in a single data structure,
all sharing the same data type. Instead of creating multiple individual
variables, an array groups them under one name, with each element
accessed by an index number. For example, you can use an array to
store multiple sensor readings or manage multiple LED states in a project.
Arrays make handling multiple values easier and efficient in Arduino.
Why are Arrays important?
Arrays are crucial when you need to manage multiple values efficiently.
Instead of creating many variables, you can store related data, like sensor
readings, in an array. This simplifies the code, reduces memory usage,
and helps with tasks like iterating over values in loops. Arrays also make
it easier to modify or update groups of values simultaneously.
Syntax
dataType arrayName[arraySize];
This is how you declare an array. The dataType specifies what type of
data the array holds, such as int or float.
Syntax Explanation
In dataType arrayName[arraySize] , the arraySize defines how many
elements the array can hold, and the arrayName is used to reference it.
Arrays in Arduino are zero-indexed, meaning the first element is
accessed with index 0.
Usage
Arrays are used to group related data, like storing multiple sensor
readings or managing multiple LED outputs. By accessing elements via
their index, you can loop through the array and perform tasks on each
value, making arrays useful in complex projects.
Code Example
int sensorReadings[5] = {0, 100, 200, 300, 400};
Serial.println(sensorReadings[2]); // Outputs the third value in the array
This example declares an array of five integers and prints the third
value, which is stored at index 2.
Notes
Remember that arrays in Arduino start at index 0. Accessing elements
outside the array’s bounds can lead to unexpected behavior.
Warnings
If you try to access an index that is out of bounds, the program may
crash or return undefined results, leading to potential errors.
Troubleshooting Tips
If your array isn't behaving as expected, check the array size and ensure
you're not accessing elements outside its bounds. Use the Serial
Monitor to debug the values stored in the array.
Code Example
bool buttonPressed = false;
if (digitalRead(buttonPin) == HIGH) {
buttonPressed = true;
}
if (buttonPressed) {
digitalWrite(ledPin, HIGH); // Turn on the LED
}
This code checks if a button is pressed and updates the bool variable. If
the button is pressed, the LED turns on.
Notes
Use bool for binary decisions like true/false or on/off. It simplifies code
where conditions need to be checked frequently.
Warnings
bool can only store true or false values. Attempting to store other types
of data, like numbers, will result in unexpected behavior.
Troubleshooting Tips
If your program isn't working as expected, check the bool variables using
Serial.print() . This will help you see whether they are correctly set to
true or false during execution, making it easier to find and fix problems.
Code Example
long duration = 1000000;
if (duration > 500000) {
Serial.println("Long value exceeded half a million");
}
This code creates a long variable to store a large value and checks if
the value exceeds 500,000. It then prints a message if the condition is
met.
Notes
Use long when you need to store numbers bigger than what int can
handle. It is commonly used for timing functions or any task involving
large numerical values.
Warnings
Beware of overflow with long if your number exceeds its limit. Values
over 2,147,483,647 or below -2,147,483,648 will cause errors and
result in incorrect values.
Troubleshooting Tips
If your long variable produces incorrect results, check for overflow by
ensuring values stay within the valid range. Use Serial.print() to monitor
the variable’s value during execution and verify that it doesn’t exceed the
allowed limits.
Warnings
float uses more memory than int or byte , so avoid using it
unnecessarily. Overusing float in memory-constrained programs can
slow down your Arduino’s performance.
Troubleshooting Tips
If you notice errors with float values, check that your calculations are
accurate and that you’re not losing precision during type conversions.
Use Serial.print() to display the float value and ensure the number is
being stored correctly.
5. Strings in Arduino
5.1 Using char Arrays for Strings
What is a char array?
A char array is a collection of characters that is used to store text
data, such as words or phrases. Each character in the array is
represented by an ASCII value, and the array must include a null
terminator( \0 ) to indicate the end of the string. This method is a low-
level approach to string manipulation, giving you full control over how
memory is used and how data is handled in Arduino.
Why use char arrays?
char arrays are more memory-efficient than using the String object.
They give you precise control over memory usage and string
manipulation, which is critical in resource-limited environments like
Arduino. This is important when you need to manipulate strings
manually for tasks such as serial communication, reading from
sensors, or managing text input/output.
Syntax
char str[] = "Hello";
This declares a char array named str and assigns it the value "Hello" ,
with the null terminator automatically added.
Syntax Explanation
In char str[] = "Hello"; , the array str holds five characters plus a null
terminator( \0 ) to mark the end of the string. This is required to properly
manage memory and ensure the string is handled correctly by functions
that process text.
Usage
Use char arrays when you need to store fixed-length strings or when
performance and memory efficiency are critical. This is often used in low-
level communication protocols, embedded systems, or programs
that require precise control over how text is processed.
Code Example
char greeting[] = "Arduino";
Serial.println(greeting); // Outputs "Arduino" to the Serial Monitor
This code defines a char array containing the word "Arduino" and prints
it to the Serial Monitor. The null terminator is automatically added to
the array to mark the end of the string.
Notes
Ensure that your char array has enough space to include the null
terminator( \0 ). If the null terminator is missing, string functions may
fail or produce incorrect results.
Warnings
If you attempt to store a string that exceeds the size of the char array, it
will overwrite memory, causing unpredictable behavior. Always
allocate enough memory for both the string and the null terminator.
Troubleshooting Tips
If your char array isn’t behaving as expected, check that the null
terminator is in place. Use Serial.print() to display the string and verify
that it ends correctly. If the string doesn’t terminate properly, the program
might crash or output unexpected characters.
Why is it important?
The String object simplifies text manipulation in Arduino, making it
easier to work with strings that may change in size. It eliminates the need
to manually handle memory allocation, and its built-in functions for
concatenation, comparison, and conversion make it highly versatile for
projects involving serial communication, text processing, and
dynamic data handling.
Syntax
String str = "Hello";
This declares a String object named str and assigns it the value
"Hello" .
Syntax Explanation
In String str = "Hello"; , str is an object that holds the string "Hello" .
Unlike char arrays, you don’t need to worry about manually handling the
null terminator or the string’s length, as the String object manages
this automatically.
Usage
Use the String object when working with dynamic strings that may
change size during program execution, such as when reading user input,
processing sensor data, or manipulating text files. The String object
simplifies handling these tasks, though it uses more memory.
Code Example
String greeting = "Hello";
greeting += " Arduino"; // Concatenates " Arduino" to the existing string
Serial.println(greeting); // Outputs "Hello Arduino"
This example demonstrates how to concatenate strings using the String
object and print the result to the Serial Monitor.
Notes
The String object is easier to use than char arrays, but it consumes
more memory. Be cautious when using it in memory-constrained
environments like Arduino.
Warnings
Overusing the String object in memory-limited projects can lead to
memory fragmentation, causing the program to slow down or crash
over time. Monitor memory usage carefully.
Troubleshooting Tips
If your program using the String object behaves unexpectedly, use
Serial.print() to monitor free memory. Memory fragmentation can be a
problem, especially if strings are frequently resized. Switching to char
arrays may help in memory-constrained projects.
7. Constants in Arduino
7.1 The const Keyword
What is const ?
The const keyword is used to define constant variables in Arduino.
These are variables whose values cannot be changed after being
initialized. This is useful when you need to define values that remain
fixed throughout the program, such as pin numbers, thresholds, or
configuration settings. Declaring constants improves code clarity and
prevents errors by ensuring critical values are not accidentally
modified.
Why is it important?
Using const is essential for ensuring that fixed values in your code
remain unmodified. This makes the program more stable and easier to
debug because you can guarantee that certain variables won’t be
accidentally altered during execution. It also helps improve code
readability, making it clear which values are constant.
Syntax
const int ledPin = 13;
This declares a constant integer ledPin with the value 13. This value
cannot be changed later in the program.
Syntax Explanation
In const int ledPin = 13; , const ensures that the value of ledPin
remains fixed throughout the program. Once defined, ledPin will always
represent 13, which makes it useful for pin numbers or settings that
don’t change.
Usage
Use const when working with values that should not change during
program execution, such as pin numbers, sensor thresholds, or
configuration constants. This prevents errors caused by accidental
modification and ensures stability in your program.
Code Example
const int ledPin = 13;
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH); // Turn on the LED connected to pin 13
This code demonstrates how to declare and use a constant for the pin
number controlling an LED. The const keyword ensures the pin number
is not changed accidentally.
Notes
Using const is good practice when dealing with values that should
remain unchanged, such as hardware pin assignments or
calibration settings. It helps prevent accidental changes.
Warnings
Once declared, a constant cannot be modified. If you attempt to change
the value of a const variable later in the program, it will result in a
compilation error. Ensure that you assign the correct value when
initializing.
Troubleshooting Tips
If you experience errors related to constants, ensure that you are not
trying to modify a const variable later in the program. Double-check that
the initial value is correct, as it cannot be changed after being set.
Components List:
Arduino
5 LEDs
Resistors (220Ω recommended for each LED)
Wires
Breadboard
Code:
int ledPins[] = {2, 3, 4, 5, 6}; // Array to store LED pin numbers
void setup() {
for (int i = 0; i < 5; i++) {
pinMode(ledPins[i], OUTPUT); // Set each pin as output
}
}
void loop() {
for (int i = 0; i < 5; i++) {
digitalWrite(ledPins[i], HIGH); // Turn on LED
delay(500); // Wait 500ms
digitalWrite(ledPins[i], LOW); // Turn off LED
delay(500); // Wait 500ms before next LED
}
}
Code Walkthrough:
1. Array Initialization: The array ledPins[] stores the digital
pin numbers to which the LEDs are connected. This allows
easy access to each LED.
2. Setup Function: Inside the setup() function, a for loop sets
each pin in the array as an OUTPUT using pinMode() .
3. Loop Function: In the loop() , a for loop iterates through the
ledPins[] array. For each iteration:
The current LED is turned on using digitalWrite() .
The code waits for 500ms.
The same LED is then turned off, and the code
waits another 500ms before moving to the next
LED.
4. This creates a sequence effect, where each LED turns on
and off in order.
Challenge: Create a Blinking Pattern
Modify the code to create a custom blinking pattern. For example:
Make two LEDs blink together at the same time.
Create a back-and-forth sequence, similar to the Knight
Rider light effect, where the LEDs light up in one direction and
then reverse.
Components List:
Arduino
Temperature sensor (e.g., LM35)
DC fan
Transistor (e.g., NPN type like 2N2222)
Diode (e.g., 1N4007)
Resistor (1kΩ for transistor base)
Wires
Breadboard
Circuit Diagram:
The temperature sensor is connected to an analog pin on the Arduino
to read temperature data. A transistor is used to control the DC fan,
with PWM from the Arduino adjusting its speed. A diode is placed across
the fan’s power terminals to protect the circuit from back EMF (voltage
spikes) generated when the motor turns off.
Circuit Connection:
1. LM35 Temperature Sensor:
VCC → 5V on Arduino
GND → Ground
Output → Analog pin A0
2. DC Fan:
Fan positive → 12V power supply
Fan negative → Collector of NPN transistor
3. Transistor:
Collector → Negative terminal of the fan
Emitter → Ground
Base → PWM pin 9 on the Arduino through a 1kΩ
resistor
4. Diode:
Place a diode (1N4007) across the fan’s terminals
to protect against voltage spikes caused by the
fan turning off (back EMF).
Cathode to positive terminal of the fan, anode to
negative terminal.
Code:
const int tempPin = A0; // Temperature sensor pin
const int fanPin = 9; // Fan control pin (PWM)
float temperature; // Variable to store temperature
void setup() {
pinMode(fanPin, OUTPUT); // Set fan pin as output
Serial.begin(9600); // Start serial communication
}
void loop() {
int sensorValue = analogRead(tempPin); // Read analog value from
sensor
// Convert analog value to temperature in Celsius
temperature = (sensorValue * 5.0 * 100.0) / 1024.0;
// Map temperature (20°C to 40°C) to fan speed (0 to 255)
int fanSpeed = map(temperature, 20, 40, 0, 255);
analogWrite(fanPin, fanSpeed); // Control fan speed using PWM
Serial.print("Temperature: "); // Print temperature to Serial Monitor
Serial.print(temperature);
Serial.println(" °C");
delay(1000); // Wait 1 second before reading again
}
Code Walkthrough:
1. Temperature Reading: The analogRead() function reads
the voltage from the LM35 sensor connected to pin A0. The
sensor output is proportional to temperature, with 10 mV/°C
sensitivity.
2. Temperature Conversion: The analog reading is converted
to Celsius using the formula:
(sensorValue * 5.0 * 100.0) / 1024.0 converts the
10-bit analog value (0-1023) to a temperature in
Celsius based on the 5V reference.
3. Fan Speed Control: The map() function maps the
temperature range (20°C to 40°C) to a PWM value range of
0 to 255. This value is used to control the fan speed via PWM
on pin 9.
4. Serial Output: The current temperature is printed to the
Serial Monitor to provide real-time feedback.
Components List:
Arduino
Ultrasonic sensor (e.g., HC-SR04)
Wires
Breadboard
Circuit Diagram:
The HC-SR04 ultrasonic sensor has 4 pins:
VCC → Connects to 5V on the Arduino.
GND → Connects to Ground (GND).
Trig → Sends the trigger signal to start the measurement.
Echo → Receives the reflected signal to measure the time
taken.
Circuit Connection:
1. Trig Pin → Connect to digital pin 9 on the Arduino.
2. Echo Pin → Connect to digital pin 10 on the Arduino.
3. VCC → Connect to 5V on the Arduino.
4. GND → Connect to GND on the Arduino.
Code:
const int trigPin = 9; // Trig pin
const int echoPin = 10; // Echo pin
long duration; // Variable to store the time of flight
int distance; // Variable to store the calculated distance
void setup() {
pinMode(trigPin, OUTPUT); // Set the trig pin as output
pinMode(echoPin, INPUT); // Set the echo pin as input
Serial.begin(9600); // Initialize serial communication
}
void loop() {
// Send the ultrasonic pulse
digitalWrite(trigPin, LOW);
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(trigPin, HIGH); // Trigger the pulse
delayMicroseconds(10); // Wait for 10 microseconds
digitalWrite(trigPin, LOW); // Stop the pulse
// Measure the time taken for the echo to return
duration = pulseIn(echoPin, HIGH); // Get the duration in microseconds
// Calculate the distance based on the speed of sound (0.034 cm per
microsecond)
distance = duration * 0.034 / 2;
// Display the distance in the Serial Monitor
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
delay(1000); // Wait 1 second before repeating the measurement
}
Code Walkthrough:
1. Pin Setup:
The Trig pin is set as an output, and the Echo pin
is set as an input to handle signals from the
ultrasonic sensor.
2. Sending the Ultrasonic Pulse:
The digitalWrite(trigPin, HIGH) sends a 10-
microsecond pulse from the Trig pin to initiate
the distance measurement.
3. Measuring Time:
The pulseIn() function measures the time it takes
for the sound to travel to the object and reflect back
to the Echo pin.
The time is stored in the duration variable, which is
of type long because the time can be large, and int
would not store the value correctly.
4. Distance Calculation:
The distance is calculated using the formula:
distance = duration * 0.034 / 2
0.034 cm per microsecond is the speed
of sound, and the result is divided by 2
because the sound travels to the object
and back.
5. Displaying the Distance:
The calculated distance is printed to the Serial
Monitor for easy monitoring.
6. Delay:
A 1-second delay is introduced to wait before the
next measurement is taken.
Components List:
Arduino
USB connection (for serial communication via Serial Monitor)
Circuit Diagram:
No additional hardware is required for this project, as all interaction will
happen through the Serial Monitor.
Circuit Connection:
No physical wiring is needed, simply connect your Arduino to the
computer via USB.
Code:
// Using a char array and a String object
char name[] = "Arduino"; // Using char array
String greeting = "Hello"; // Using String object
void setup() {
Serial.begin(9600); // Initialize Serial Monitor communication
// Display the String object in the Serial Monitor
Serial.println(greeting);
delay(2000); // Wait for 2 seconds
// Clear the Serial Monitor (optional)
Serial.println("");
// Display the char array in the Serial Monitor
Serial.println(name);
}
void loop() {
// Optionally add additional code for input or scrolling
}
Code Walkthrough:
1. Serial Communication Setup: The Serial.begin(9600)
function initializes the Serial Monitor for communication at a
baud rate of 9600.
2. Using String Object: The String object greeting is printed
using Serial.println() . String objects are easier to manipulate
and offer dynamic memory usage, but they can lead to
memory fragmentation in Arduino over time.
3. Delay: A 2-second delay is added using delay(2000) to
allow time for viewing the String object before printing the
next value.
4. Using Char Array: The char array name[] is printed next.
Char arrays are fixed-length strings, meaning they take up
less memory and are more efficient, but require manual
memory management and are less flexible than String
objects.
Key Differences:
Char Array ( name[] ):
Fixed-length string.
Efficient in terms of memory.
Requires manual memory management.
String Object ( greeting ):
Dynamic and easier to manipulate.
Uses more memory and can cause memory
fragmentation over time, especially in low-
memory environments like Arduino.
Code Example
int buttonState = digitalRead(2); // Read pin 2
if (buttonState == HIGH) {
// Do something, like turn on an LED
}
Notes
digitalRead() only works with pins set as input. You must use the
pinMode() function to set the pin as input.
Warnings
Always use pull-up or pull-down resistors to prevent floating pins, which
can lead to inconsistent readings.
Troubleshooting Tips
If your button doesn't seem to work, check for proper wiring, ensure the
pin is set to input, and use resistors to stabilize the signal.
Components List:
1. Arduino (e.g., Uno, Nano, etc.)
2. Push Button (momentary switch)
3. LED
4. Resistor (220 ohms for current-limiting the LED)
5. Breadboard and Wires
Circuit Diagram:
LED:
The LED is connected to pin 13 of the Arduino. The long leg
(anode) connects to pin 13, and the short leg (cathode)
connects to the ground through a 220-ohm resistor to limit
the current and prevent damage to the LED.
Push Button:
The push button is connected to pin 2 of the Arduino. One
side of the button connects to ground, and the other side
connects to pin 2. To ensure the button behaves reliably
(avoiding floating states), you should use a pull-down
resistor or configure an internal pull-up resistor.
Code Walkthrough:
1. Global Variables:
buttonPin : Pin 2 is used for the button input.
ledPin : Pin 13 is used to control the LED.
buttonState : This variable holds the state of the
button, either HIGH (pressed) or LOW (not
pressed).
2. setup() :
pinMode(ledPin, OUTPUT) : Sets pin 13 as an
output pin to control the LED.
pinMode(buttonPin, INPUT) : Sets pin 2 as an
input pin to read the state of the button.
3. loop() :
digitalRead(buttonPin) : This reads the current
state of the button (pressed or not pressed).
if (buttonState == HIGH) : If the button is
pressed, the button state is HIGH , and the LED is
turned on by setting pin 13 to HIGH .
else : If the button is not pressed (state is LOW ),
the LED is turned off by setting pin 13 to LOW .
Components List
1. Arduino (e.g., Uno, Nano)
2. Temperature Sensor (e.g., LM35 or similar)
3. Fan (small DC fan)
4. Transistor (e.g., NPN transistor like 2N2222 or TIP120)
5. Resistor (typically 220 ohms)
6. Diode (e.g., 1N4007)
7. Breadboard and wires
Circuit Diagram
Temperature Sensor (LM35): Connect the VCC of the
sensor to the 5V on the Arduino, the GND to the ground, and
the analog output to the A0 pin.
Fan and Transistor: The fan is connected to the external 12V
supply (or 5V, depending on your fan). The transistor drives
the fan, with the base connected to pin 9 (via a 220-ohm
resistor). A diode is placed in parallel with the fan to protect
the circuit from back EMF.
Code
int tempPin = A0; // Pin for temperature sensor
int fanPin = 9; // PWM pin for fan control
int tempValue = 0; // Variable to store temperature sensor reading
void setup() {
pinMode(fanPin, OUTPUT); // Set fan pin as output
}
void loop() {
tempValue = analogRead(tempPin); // Read the temperature sensor
value
int fanSpeed = map(tempValue, 0, 1023, 0, 255); // Map sensor reading
to PWM value
analogWrite(fanPin, fanSpeed); // Control the fan speed using PWM
}
Code Walkthrough
1. Global Variables:
tempPin : Defines A0 as the analog input pin for
reading the temperature sensor.
fanPin : Defines pin 9 as the PWM-capable pin for
controlling the fan.
tempValue : Holds the temperature sensor's analog
value (0–1023).
2. setup() :
Configures pin 9 as an output pin for the fan.
3. loop() :
analogRead(tempPin) : Reads the temperature
sensor's output.
map(tempValue, 0, 1023, 0, 255) : Maps the
temperature reading to the appropriate PWM range
(0-255).
analogWrite(fanPin, fanSpeed) : Uses the
mapped value to control the fan speed based on the
sensor's temperature reading.
Circuit Diagram:
Code:
int potPin = A0; // Pin for the potentiometer
int motorPin = 9; // Pin for the motor control (PWM)
void setup() {
pinMode(motorPin, OUTPUT); // Set motor pin as an output
}
void loop() {
int potValue = analogRead(potPin); // Read potentiometer value (0-
1023)
int motorSpeed = map(potValue, 0, 1023, 0, 255); // Map potentiometer
value to PWM range (0-255)
analogWrite(motorPin, motorSpeed); // Write PWM value to control
motor speed
}
Code Walkthrough:
1. Global Variables:
potPin : This defines A0 as the input pin for the
potentiometer.
motorPin : This defines pin 9 as the PWM output
pin to control the motor's speed.
2. setup() :
pinMode(motorPin, OUTPUT) : Sets pin 9 as an
output pin to control the motor.
3. loop() :
analogRead(potPin) : Reads the analog voltage
from the potentiometer, which ranges from 0 to
1023.
map(potValue, 0, 1023, 0, 255) : Maps the
potentiometer reading (0-1023) to a PWM range (0-
255). This is necessary because the analogWrite()
function accepts values from 0 to 255.
analogWrite(motorPin, motorSpeed) : Outputs
the PWM signal to the motor driver, adjusting the
motor speed based on the potentiometer's position.
Software Issues
Incorrect syntax, undefined variables, and wrong logic are
common programming errors. For example, forgetting to
declare a variable or setting an incorrect pin number in your
code can cause unexpected behavior. Always double-check
the pin numbers in your code and ensure that the pinMode()
is correctly set in the setup() function before using
digitalRead(), digitalWrite(), or analogRead().
Using the Serial Monitor for Debugging
The Serial Monitor is an essential tool for troubleshooting.
Use Serial.print() and Serial.println() to display sensor
values, button states, or other critical information from your
code. By printing the values in real-time, you can identify if a
sensor or a pin is functioning as expected. This makes it easier
to pinpoint where the problem lies.
Code Example
unsigned long startTime = micros(); // Start time
// Some fast operation
unsigned long elapsedTime = micros() - startTime; // Measure
time taken
if (elapsedTime > 1000) {
// Do something if more than 1 millisecond passed
}
Notes
millis() and micros() are preferred for non-blocking tasks, where you
need to measure time without halting the entire program.
Warnings
Mixing blocking ( delay() ) and non-blocking ( millis() , micros() ) functions
can lead to issues in your program’s timing and responsiveness. Use
them carefully.
Troubleshooting Tips
If your program isn’t performing as expected, check which timing function
you are using. Blocking delays may cause your program to stop
responding, while non-blocking timing lets other tasks continue.
Components List:
1. Arduino
2. Push button
3. LED
4. Resistor (220 ohms for the LED)
5. Breadboard and wires
Circuit Diagram:
Code:
const int buttonPin = 2; // Pin for the push button
const int ledPin = 13; // Pin for the LED
int buttonState = 0; // Variable to store button state
void setup() {
pinMode(ledPin, OUTPUT); // Set the LED pin as output
pinMode(buttonPin, INPUT); // Set the button pin as input
}
void loop() {
buttonState = digitalRead(buttonPin); // Read the button state
if (buttonState == HIGH) { // If the button is pressed
digitalWrite(ledPin, HIGH); // Turn the LED on
delay(1000); // Keep the LED on for 1 second
digitalWrite(ledPin, LOW); // Turn the LED off
}
}
Code Walkthrough:
Global Variables:
buttonPin : Pin 2 is designated as the input pin for the
push button.
setup() :
pinMode(ledPin, OUTPUT) : Configures pin 13 as an
output to control the LED.
loop() :
digitalRead(buttonPin) : Reads the state of the push
button (either HIGH or LOW ).
Motor
Transistor
Resistor
Circuit Diagram
Connect the motor to the Arduino through a transistor, using a PWM-
capable pin like pin 9 for precise control.
Code
int pwmPin = 9; // PWM-capable pin
int pwmValue = 128; // Variable to store PWM value (50% duty
cycle)
void setup() {
pinMode(pwmPin, OUTPUT); // Set the PWM pin as output
}
void loop() {
analogWrite(pwmPin, pwmValue); // Output the PWM signal
using the variable
delay(1000); // Wait for 1 second
pwmValue = 255; // Change PWM value to 100% duty
cycle
analogWrite(pwmPin, pwmValue); // Update the motor speed
delay(1000); // Wait for 1 second
pwmValue = 128; // Change PWM value back to 50%
duty cycle
}
Code Walkthrough
The code generates a PWM signal by alternating between HIGH and LOW
signals with microsecond pauses, controlling the motor speed.
Challenge: Increase PWM Precision
Experiment with different microsecond values in the
delayMicroseconds() function to achieve more precise motor control,
adjusting speed based on timing.
Syntax Table
Topic Syntax Simple Example
Name
if if (condition) { /* if (x > 0) {
Statement code */ } Serial.println("Positive"); }
3. Loop Structures
Syntax Explanation
The goto statement jumps to a labeled section of the code. The label
must be defined elsewhere in the program. When goto is executed,
control immediately transfers to the label, skipping any code between the
goto and the label.
Usage
Use goto when you need to jump to another part of the program.
However, it should be used sparingly, as it can make code difficult to
follow. Structured alternatives like loops or functions are often better.
Code Example
int x = 0;
void loop() {
x++;
if (x == 5) {
goto end;
}
Serial.println(x);
end:
}
In this example, the goto statement jumps to the label end , skipping
the Serial.println statement when x equals 5.
6. Projects
Circuit Diagram
Code
int temperature = 0;
int setTemp = 25; // Desired room temperature
void setup() {
pinMode(9, OUTPUT); // Set pin 9 for relay control
Serial.begin(9600); // Initialize serial communication for debugging
}
void loop() {
// Read the temperature sensor
temperature = analogRead(A0);
// Convert the sensor reading (0-1023) to Celsius (0-50°C range)
temperature = map(temperature, 0, 1023, 0, 50);
// Control the heater based on the current temperature
if (temperature < setTemp) {
digitalWrite(9, HIGH); // Turn on heater
Serial.println("Heater ON");
} else {
digitalWrite(9, LOW); // Turn off heater
Serial.println("Heater OFF");
}
// Wait 1 second before checking the temperature again
delay(1000);
}
Code Walkthrough
Temperature Reading: The sensor data is read from analog pin A0
using analogRead(A0) , which provides a value between 0 and 1023.
Mapping the Value: The map() function is used to convert the sensor
value into a Celsius reading (0-50°C). The raw analog value is mapped to
a temperature range that the sensor can measure.
Temperature Control:
If the temperature is below the set threshold
(25°C), the system turns on the heater by setting pin
9 to HIGH.
Serial Output: The system sends a message to the Serial Monitor for
debugging purposes, indicating whether the heater is ON or OFF.
Delay: A 1-second delay is added to prevent rapid toggling of the
heater and to give the system time to respond to temperature changes.
Challenge
Add a cooling system by incorporating a fan that turns on when the
temperature exceeds a set threshold, using additional if...else logic.
Circuit Diagram
The temperature sensor's output pin connects to analog pin A0 on
the Arduino.
The LED's positive leg connects to digital pin 9, and the negative leg
is connected to ground through a resistor.
Code
int temperature = 0;
int threshold = 30; // Temperature threshold for LED
void setup() {
pinMode(9, OUTPUT); // Set pin 9 for LED control
Serial.begin(9600); // Initialize serial communication
}
void loop() {
// Read the temperature from the sensor
temperature = analogRead(A0);
// Convert the analog reading (0-1023) to temperature in Celsius (0-
50°C)
temperature = map(temperature, 0, 1023, 0, 50);
// Control the LED based on the temperature
if (temperature >= threshold) {
digitalWrite(9, HIGH); // Turn LED on
Serial.println("LED ON");
} else {
digitalWrite(9, LOW); // Turn LED off
Serial.println("LED OFF");
}
// Delay for 1 second to prevent rapid changes
delay(1000);
}
Code Walkthrough
Temperature Reading: The temperature sensor’s analog
value is read using analogRead(A0) . The raw sensor value
ranges between 0 and 1023, representing the voltage output
by the sensor.
Challenge
Add a buzzer that sounds if the temperature exceeds a dangerous level
(e.g., 40°C), demonstrating multiple control outputs based on different
conditions.
Circuit Diagram
Connect the soil moisture sensor to analog pin A0 on the Arduino.
The water pump (or LED for simulation) is controlled by a relay module
connected to digital pin 9 on the Arduino.
Code
int moistureLevel = 0;
int threshold = 300; // Moisture threshold
void setup() {
pinMode(9, OUTPUT); // Set pin 9 for relay control
Serial.begin(9600); // Start serial communication
}
void loop() {
moistureLevel = analogRead(A0); // Read the moisture sensor value
if (moistureLevel < threshold) {
digitalWrite(9, HIGH); // Turn on water pump
Serial.println("Watering ON");
} else {
digitalWrite(9, LOW); // Turn off water pump
Serial.println("Watering OFF");
}
delay(1000); // Delay for 1 second before the next reading
}
Code Walkthrough
Reading Moisture Level: The analog value from the soil
moisture sensor is read using analogRead(A0) . This value
represents the current moisture level in the soil.
Threshold Check:
If the moisture level is below the threshold (300
in this example), the system activates the water
pump by sending a HIGH signal to digital pin 9,
which controls the relay.
If the moisture level is above the threshold, the
system turns off the water pump by sending a LOW
signal to the relay, stopping the watering process.
Challenge
Add a moisture sensor to automate water control. If the soil is too dry,
the system should automatically turn on the water pump, and turn it off
when the soil is wet enough.
Code
int state = 0;
void setup() {
pinMode(9, OUTPUT); // Red LED
pinMode(10, OUTPUT); // Yellow LED
pinMode(11, OUTPUT); // Green LED
}
void loop() {
switch (state) {
case 0: // Red light
digitalWrite(9, HIGH); // Turn on Red LED
digitalWrite(10, LOW); // Turn off Yellow LED
digitalWrite(11, LOW); // Turn off Green LED
delay(5000); // Red light stays on for 5 seconds
state = 1; // Move to the next state (green light)
break;
case 1: // Green light
digitalWrite(9, LOW); // Turn off Red LED
digitalWrite(10, LOW); // Turn off Yellow LED
digitalWrite(11, HIGH); // Turn on Green LED
delay(5000); // Green light stays on for 5 seconds
state = 2; // Move to the next state (yellow light)
break;
case 2: // Yellow light
digitalWrite(9, LOW); // Turn off Red LED
digitalWrite(10, HIGH); // Turn on Yellow LED
digitalWrite(11, LOW); // Turn off Green LED
delay(2000); // Yellow light stays on for 2 seconds
state = 0; // Reset back to the red light state
break;
}
}
Code Walkthrough
State Management: The variable state is used
to track the current phase of the traffic light (red,
green, or yellow). Based on the current state, the
appropriate LEDs are turned on or off, mimicking
the traffic light's phases.
switch...case Statement: The switch...case
statement is used to control which LED is active:
Case 0: The red LED is turned on for 5
seconds ( delay(5000) ) while the yellow
and green LEDs are turned off. After this,
the state changes to 1, moving to the
green light.
Case 1: The green LED is turned on for
5 seconds ( delay(5000) ), then the state
is updated to 2, moving to the yellow
light.
Case 2: The yellow LED is turned on for
2 seconds ( delay(2000) ), after which the
state is set back to 0, returning to the red
light.
Loop: The entire sequence repeats indefinitely
due to the loop() function, ensuring the traffic
lights cycle through red, green, and yellow
continuously.
Challenge
Modify the traffic light system to include pedestrian
control with a button. When the button is pressed, the
traffic light should change to red, allowing pedestrians to
cross.
Code:
int potPin = A0; // Pin for potentiometer
int ledPin = 9; // PWM pin for LED
int potValue;
int brightness;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
potValue = analogRead(potPin); // Read
potentiometer value (0-1023)
brightness = pow(potValue / 1023.0, 1.5) * 255; //
Exponential brightness control
analogWrite(ledPin, brightness); // Write the
brightness to the LED
delay(10); // Short delay to
smooth operation
}
Code Walkthrough:
1. Read the Potentiometer Value: The
analogRead() function reads the value from the
potentiometer (range 0-1023).
2. Exponential Control Using pow(): The
potentiometer value is normalized by dividing by
1023, then raised to the power of 1.5 using pow()
to create an exponential curve.
3. Scale to PWM Range: The result is multiplied by
255 to fit the PWM range (0-255), which controls
the LED brightness.
4. Write the Brightness: The analogWrite()
function outputs the brightness to the LED on a
PWM pin.
Code:
// Define pins for the ultrasonic sensor
const int trigPin = 7;
const int echoPin = 6;
void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
// Measure distance with ultrasonic sensor
long duration;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
float distanceX = (duration * 0.034) / 2; // Distance in cm
(for x-axis)
// Read accelerometer values for y-axis
float distanceY = analogRead(A1) * (5.0 / 1023.0); //
Analog to actual value scaling
// Calculate the distance between two points using the
Pythagorean theorem
float distance = sqrt(sq(distanceX) + sq(distanceY));
// Print the calculated distance
Serial.print("Distance: ");
Serial.println(distance);
delay(1000); // Add delay between measurements
}
Code Walkthrough:
1. Ultrasonic Sensor Measurement:
The trigger pin sends a pulse, and the
echo pin receives the time it takes for
the pulse to bounce back. The time is
converted into a distance (in cm) for the
x-axis.
2. Analog Read for Accelerometer:
The y-axis distance is obtained from the
accelerometer by reading the analog pin
and converting the value to a real-world
distance using a scaling factor.
3. Distance Calculation:
The Pythagorean theorem is applied:
distance = sqrt(x^2 + y^2) to calculate
the distance between two points based
on the x and y distances.
4. Serial Output:
The calculated distance is displayed on
the Serial Monitor for verification.
Code:
#include <Servo.h>
Servo servo; // Create a servo object
int potPin = A0; // Potentiometer pin
int potValue; // Variable to store the potentiometer
value
int angle; // Servo angle
void setup() {
servo.attach(9); // Attach the servo to pin 9
Serial.begin(9600); // Begin serial communication for
debugging
}
void loop() {
// Read the potentiometer value
potValue = analogRead(potPin);
// Map the potentiometer value to an angle range and
generate sine wave motion
angle = 90 + 30 * sin(potValue * 0.017); // Adjust the
0.017 factor to change wave speed
// Write the angle to the servo
servo.write(angle);
// Print the angle for debugging
Serial.println(angle);
// Delay for smooth movement
delay(15);
}
Code Walkthrough:
1. Servo Setup: The Servo library is included, and
the servo is attached to pin 9. The
potentiometer is connected to pin A0.
2. Read Potentiometer: The analogRead()
function reads the potentiometer value, which is
mapped to create wave-like motion.
3. Generate Sine Wave: The formula angle = 90 +
30 * sin(potValue * 0.017) uses the sin() function
to generate a smooth oscillation around 90
degrees, with an amplitude of 30 degrees. The
value 0.017 is a scaling factor to adjust the
speed of the wave.
4. Control Servo: The calculated angle is sent to
the servo motor, making it move in a smooth,
sinusoidal motion.
5. Serial Monitor: The servo angle is printed to the
Serial Monitor for debugging purposes.
This setup allows for fluid, natural movement of the
servo motor, controlled by the potentiometer. The
potentiometer affects the amplitude of the sine wave,
adjusting how far the servo swings back and forth.
Challenge: Adjust the Wave Frequency with
Potentiometer
Add another potentiometer to control the
frequency of the sine wave, allowing for smoother
or faster servo movements.
Circuit Connection:
1. Temperature sensor:
Connect the VCC and GND of the
temperature sensor to 5V and ground on
the Arduino.
Connect the output pin of the sensor to
an analog pin (e.g., A0) on the Arduino.
2. Fan control:
Connect the collector of the NPN
transistor to one lead of the fan.
The other fan lead goes to 5V.
Connect the emitter of the transistor to
ground.
The base of the transistor is connected
to a PWM pin (e.g., pin 9) on the
Arduino via a 1kΩ resistor.
This setup allows the PWM signal from the Arduino to
control the fan's speed based on the temperature.
Code:
int tempPin = A0; // Temperature sensor pin
int fanPin = 9; // PWM pin to control the fan
void setup() {
pinMode(fanPin, OUTPUT);
Serial.begin(9600); // Start serial communication for
monitoring
}
void loop() {
// Read temperature sensor value
int tempValue = analogRead(tempPin);
// Map the temperature sensor reading to a fan speed (0-
255 for PWM)
int fanSpeed = map(tempValue, 0, 1023, 0, 255);
// Output the mapped fan speed to the fan
analogWrite(fanPin, fanSpeed);
// Print temperature and fan speed to the Serial Monitor for
debugging
Serial.print("Temperature Sensor Value: ");
Serial.println(tempValue);
Serial.print("Fan Speed: ");
Serial.println(fanSpeed);
delay(500); // Small delay to stabilize readings
}
Code Walkthrough:
Reading Temperature: The analogRead()
function reads the temperature sensor's output
from A0 (range: 0-1023).
Mapping to Fan Speed: The map() function is
used to scale the sensor value (0-1023) to a PWM
output range (0-255), which corresponds to the
fan's speed.
Controlling the Fan: The analogWrite()
function sends the PWM signal to the fanPin,
controlling the speed of the fan based on the
temperature.
Serial Output: Temperature readings and fan
speed are printed to the Serial Monitor for
debugging and observation.
Syntax
The basic syntax of the < operator is:
if (a < b) {
// Do something
}
This checks if a is less than b.
Syntax Explanation
In this syntax, a < b compares two values. If a is less
than b, the code inside the curly braces is executed. This
operator is widely used in Arduino projects to control
devices based on sensor thresholds.
Usage
The < operator is commonly used in Arduino projects for
threshold-based actions. For example, it can be used to
turn on a heater when the temperature is below a certain
value.
Code Example
Here’s an example comparing a sensor reading to a
threshold:
int lightLevel = analogRead(A0);
if (lightLevel < 500) {
digitalWrite(LED_BUILTIN, HIGH); // Turn on LED if light
level is low
}
This code turns on the LED if the light level is below 500.
Troubleshooting Tips
If your < condition isn’t working, verify that:
You’re comparing the correct values.
The sensor reading is indeed lower than the
threshold.
Use Serial.print() to display values for
troubleshooting.
Circuit Diagram
DHT11/DHT22 sensor:
VCC to 5V
GND to ground
Data pin to digital pin 2 of Arduino
Relay module: Connects to the fan and heater,
with control signals coming from Arduino’s digital
output pins to switch devices on and off.
Circuit Connection
1. DHT Sensor: Connect the DHT sensor to the
Arduino for temperature and humidity
measurement.
2. Relay Module: The relay module controls the fan
and heater based on the sensor readings.
Depending on the environmental thresholds, the
relay switches on the appropriate device (fan or
heater) via the digital pins of the Arduino.
3. Fan and Heater: Connect the fan to digital pin 8
and the heater (optional) to digital pin 9. The relay
activates the devices based on temperature and
humidity conditions.
Code
#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
void setup() {
pinMode(8, OUTPUT); // Fan
pinMode(9, OUTPUT); // Heater
dht.begin();
}
void loop() {
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
// Check if the readings are valid
if (isnan(temp) || isnan(humidity)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Logic for controlling the fan and heater
if (temp > 25 && humidity > 60) {
digitalWrite(8, HIGH); // Turn on fan
digitalWrite(9, LOW); // Turn off heater
} else if (temp < 18 || humidity < 40) {
digitalWrite(9, HIGH); // Turn on heater
digitalWrite(8, LOW); // Turn off fan
} else {
// Normal conditions, turn both off
digitalWrite(8, LOW); // Turn off fan
digitalWrite(9, LOW); // Turn off heater
}
delay(2000); // Wait for 2 seconds before reading again
}
Code Walkthrough
1. DHT Sensor Initialization: The DHT object is
created to read temperature and humidity from
the sensor connected to pin 2 of the Arduino.
2. Setup Function: Pin modes are defined for the
fan (pin 8) and heater (pin 9). The DHT sensor is
initialized using dht.begin() .
3. Loop Function:
The system continuously reads
temperature and humidity values using
dht.readTemperature() and
dht.readHumidity() .
Validation: If readings are invalid
( isnan() ), an error message is printed,
and the loop skips to the next iteration.
Comparison Logic:
If temperature is above 25°C
and humidity is above 60%, the
fan turns on, and the heater
turns off.
If temperature is below 18°C or
humidity is below 40%, the
heater turns on, and the fan
turns off.
If temperature and humidity are
within the normal range (18°C ≤
temp ≤ 25°C and 40% ≤
humidity ≤ 60%), both the fan
and heater remain off.
4. Delay: The system waits for 2 seconds before
repeating the process to prevent excessive
readings.
Challenge:
Add an LCD display to show the current temperature,
humidity, and whether the fan or heater is active. This
will provide real-time feedback for users.
Circuit Connection
The PIR sensor detects motion, while the door
switch detects if the door is opened.
The buzzer and LEDs provide audible and
visual alerts.
If motion is detected or the door is opened,
the alarm is activated.
Code
int motionPin = 7;
int doorPin = 6;
int alarmPin = 9;
void setup() {
pinMode(motionPin, INPUT);
pinMode(doorPin, INPUT);
pinMode(alarmPin, OUTPUT);
}
void loop() {
int motionDetected = digitalRead(motionPin);
int doorOpened = digitalRead(doorPin);
if (motionDetected == HIGH || doorOpened == HIGH) {
digitalWrite(alarmPin, HIGH); // Turn on alarm
} else {
digitalWrite(alarmPin, LOW); // Turn off alarm
}
}
Code Walkthrough
The code reads inputs from the PIR motion
sensor and door switch.
Using the || (OR) operator, it checks if either
condition (motion detected or door opened) is
true.
If either is true, the alarm is triggered by
turning on the buzzer.
If both conditions are false, the alarm is turned
off.
Challenge:
Add a keypad to allow users to enter a code to disable the
alarm. This requires using char comparisons to check if the
entered code matches a preset code.
Circuit Diagram
The soil moisture sensor is connected to an
analog pin (e.g., A0).
The RTC module connects via I2C pins (SDA and
SCL).
The relay module controls the water pump.
Circuit Connection
The soil moisture sensor measures the
moisture level of the soil.
The RTC module keeps track of the current
time.
The relay activates the water pump when the
set conditions for moisture and time are met.
Code
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
void setup() {
Serial.begin(9600); // Optional for debugging
pinMode(A0, INPUT); // Soil moisture sensor
pinMode(8, OUTPUT); // Water pump relay
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1); // Stop the program if the RTC module isn't
found
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, setting time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Set
time to when the sketch was compiled
}
}
void loop() {
int moistureLevel = analogRead(A0); // Read soil moisture
level
DateTime now = rtc.now(); // Get current time from RTC
// Debugging information (optional)
Serial.print("Moisture Level: ");
Serial.println(moistureLevel);
Serial.print("Current Hour: ");
Serial.println(now.hour());
// If soil is dry and it's between 6 AM and 8 AM
if (moistureLevel < 400 && now.hour() >= 6 && now.hour()
<= 8) {
digitalWrite(8, HIGH); // Turn on water pump
} else {
digitalWrite(8, LOW); // Turn off water pump
}
delay(5000); // Check conditions every 5 seconds
}
Code Walkthrough
Soil moisture sensor measures the moisture
level and sends an analog value to the Arduino.
The RTC module provides the current time,
allowing the system to check if it is within the
watering period.
Comparison operators are used to check two
conditions:
1. If the moisture level is below a certain
threshold (400, indicating dry soil).
2. If the current time is between 6 AM
and 8 AM.
If both conditions are true, the water pump is
activated. If either condition is false, the pump
remains off.
Challenge:
Add a rain sensor to prevent the system from watering the
garden during rainfall. This would require adding another
condition to the logic to check if rain is detected.
5.4 Project 4: Traffic Light System with
Emergency Vehicle Detection
This project creates a traffic light system that gives
priority to emergency vehicles using an ultrasonic
sensor. When an emergency vehicle is detected within a
certain distance, the system overrides the regular traffic
light sequence, giving priority to the emergency vehicle.
The system uses comparison and Boolean operators to
manage both normal traffic flow and emergency overrides.
Why is it important?
This project simulates a real-world traffic management
system that prioritizes emergency vehicles, ensuring
they can move through intersections without delays. It
shows how conditional logic can be used to override
normal operations during critical conditions,
demonstrating how comparison and Boolean operators
allow for efficient decision-making in time-sensitive
scenarios.
Components List:
Arduino
Ultrasonic sensor
RGB LEDs (for traffic light simulation)
Resistors
Wires
Circuit Diagram
The ultrasonic sensor detects the distance of
approaching vehicles and is connected to digital
pins for distance measurement.
RGB LEDs simulate the traffic lights, with each
color (red, yellow, green) connected to separate
output pins.
Circuit Connection
The ultrasonic sensor is connected to the
Arduino and measures the distance to
approaching vehicles.
RGB LEDs are connected to digital pins to control
the red and green lights for the traffic light
system.
The system switches between normal traffic light
operation and emergency vehicle detection
mode based on the distance measured by the
ultrasonic sensor.
Code
#include <Ultrasonic.h>
Ultrasonic ultrasonic(12, 13); // Trigger pin = 12, Echo pin =
13
void setup() {
pinMode(8, OUTPUT); // Red light
pinMode(9, OUTPUT); // Green light
Serial.begin(9600); // Optional: Start the Serial monitor for
debugging
}
void loop() {
int distance = ultrasonic.read(); // Read distance from
ultrasonic sensor
// Debugging: Print the distance to the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);
// Control lights based on distance
if (distance < 50) {
digitalWrite(8, HIGH); // Turn on red light for emergency
vehicle
digitalWrite(9, LOW); // Turn off green light
} else {
digitalWrite(9, HIGH); // Normal green light
digitalWrite(8, LOW); // Turn off red light
}
delay(200); // Small delay to stabilize the sensor reading and
avoid flickering
}
Code Walkthrough
The ultrasonic sensor measures the distance of
an approaching vehicle.
If a vehicle is detected within 50 cm, the system
turns on the red light, stopping normal traffic to
allow the emergency vehicle to pass.
If no emergency vehicle is detected, the green
light remains on, simulating normal traffic flow.
The code uses comparison operators to check the
distance and Boolean logic to control the traffic
light system based on the sensor's reading.
Resistors
Wires
Breadboard
Circuit Diagram
Show how the LEDs are connected to the Arduino for random
control.
Circuit Connection
Each LED is connected to a digital pin through a resistor.
Connect the ground wire to the common ground.
Code
void setup() {
// Set pins 2 to 7 as output
for (int i = 2; i < 8; i++) {
pinMode(i, OUTPUT);
}
}
void loop() {
int ledPin = random(2, 8); // Randomly select an
LED pin
int brightness = random(0, 256); // Randomly select a
brightness value (0-255)
analogWrite(ledPin, brightness); // Set the brightness
of the selected LED
delay(500); // Wait for 500ms
digitalWrite(ledPin, LOW); // Turn off the LED
delay(500); // Wait for 500ms before
selecting another
}
Code Walkthrough
This code randomly selects one of the LED pins (2 to 7) and
turns it on. The randomness ensures that different LEDs light
up each time.
Challenge: Control Brightness Randomly
Modify the project to control LED brightness using
analogWrite() and random values between 0 and 255.
Push Button
LEDs
Buzzer
Wires
Breadboard
Circuit Diagram
Code:
// Define LED pins
int ledPins[] = {2, 3, 4, 5, 6}; // Array to hold LED pin
numbers
int numLeds = 5; // Number of LEDs
void setup() {
// Set all pins to OUTPUT
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
}
}
void loop() {
// Randomly choose an LED and turn it on
int ledPin = ledPins[random(0, numLeds)];
digitalWrite(ledPin, HIGH);
// Wait for a random duration between 100 and 1000
milliseconds
delay(random(100, 1000));
// Turn off the LED
digitalWrite(ledPin, LOW);
// Optional: Small delay to create a visual break between
blinks
delay(random(100, 500));
}
Code Walkthrough:
1. LED Pin Array: The ledPins[] array holds the pin
numbers for all the LEDs connected to the Arduino.
This makes it easy to randomly select one for
blinking.
2. Random LED Selection: The random() function
selects a random index from the ledPins[] array,
choosing an LED to turn on.
3. Random Delay: A random delay time is generated
(between 100 and 1000 milliseconds) to keep the
LED on for a random duration, making the blink
patterns unpredictable.
4. Turning Off the LED: After the delay, the selected
LED is turned off using digitalWrite(ledPin, LOW) .
5. Looping: The process repeats, ensuring the LEDs
blink in random patterns with random timings.
Code:
void setup() {
Serial.begin(9600); // Start serial communication for
debugging
}
void loop() {
// Simulate random sensor reading between 0 and 1023
(analog input range)
int sensorValue = random(0, 1023);
// Print the simulated sensor value to the Serial Monitor
Serial.println(sensorValue);
delay(500); // Wait 500ms before generating the next
random value
}
Code Walkthrough:
Serial Communication: The code begins with
Serial.begin(9600) to initialize communication with
the Serial Monitor for displaying simulated sensor
values.
Simulated Sensor Reading: The random(0,
1023) function generates a random number in the
range of 0 to 1023, simulating the range of an
analog sensor in Arduino.
Serial Output: The Serial.println(sensorValue)
command sends the simulated sensor value to the
Serial Monitor, allowing you to see the simulated
readings.
Delay: The delay(500) adds a half-second pause
between each simulated reading to prevent the
values from changing too quickly.
Syntax Table
Topic Name Syntax Simple Example
Real-Life Application
A motion detection system uses interrupts to trigger an alarm when a sensor detects
movement. The Arduino immediately pauses its current task to sound the alarm, ensuring
timely action.
Usage
Use attachInterrupt() when you need to respond to external events like button presses
or sensor inputs. It allows the Arduino to pause other tasks and focus on handling critical
inputs immediately.
Code Example
void setup() {
pinMode(2, INPUT);
attachInterrupt(digitalPinToInterrupt(2), buttonPress, RISING);
}
void buttonPress() {
// Code to execute on button press
}
This example triggers the buttonPress() function whenever the button connected to pin 2
is pressed.
Notes
The ISR function should be short and efficient, as the Arduino will not perform other
tasks while the ISR is running.
Warnings
Always use the volatile keyword for variables shared between the main program and the
ISR. This ensures proper handling of changes in memory.
Troubleshooting Tips
If the interrupt doesn’t trigger, ensure you’ve used the correct pin number and mode.
Make sure the ISR is properly defined and that no delays or complex operations are
performed inside it.
Syntax
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);
Syntax Explanation
The mode defines which type of edge will trigger the
interrupt. RISING detects when the signal changes from
LOW to HIGH, FALLING detects the reverse, and CHANGE
detects both. Use LOW when the interrupt needs to respond
to a continuous LOW signal rather than a transition.
Code Example
attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING);
This code triggers the toggleLED function whenever the
signal on pin 2 changes from LOW to HIGH, effectively
detecting a rising edge.
Notes
Choose the appropriate edge detection mode depending
on your application’s needs, whether you need to respond
to signal transitions or continuous states.
Warnings
Using the wrong edge detection mode can lead to missed
or false triggers. Ensure the mode matches your event’s
expected signal behavior.
Practical Exercise
Set up an Arduino project where an LED toggles on a rising
edge and resets to off on a falling edge. This will help you
understand edge detection in practice.
Best Practices
Keep ISRs short: Only handle critical, time-
sensitive tasks inside the ISR. Use flags or simple
variables to signal the main loop.
Avoid delays and complex operations: Use the
minimum necessary code in the ISR to avoid
freezing the system.
Use volatile for shared variables: Always
declare variables shared between the ISR and the
main program as volatile to ensure correct
handling.
Debounce input: When using interrupts with
mechanical switches, add debouncing to avoid
multiple triggers.
FAQ on Interrupts
Why isn’t my interrupt working? Check the
pin number and edge detection mode. Make
sure the ISR is properly defined and doesn’t
contain any forbidden functions like delay() .
Can I use multiple interrupts? Yes, but ensure
that each ISR is short and doesn’t interfere with
others.
Circuit Diagram
Connect the PIR sensor output to digital pin 2
of the Arduino.
The LED is connected to digital pin 9 with a
resistor in series to limit the current.
Connect power (5V) and ground to the sensor and
the LED.
Code Example
volatile bool motionDetected = false;
void setup() {
pinMode(2, INPUT); // PIR sensor pin
pinMode(9, OUTPUT); // LED pin
attachInterrupt(digitalPinToInterrupt(2), motionISR,
RISING); // Trigger on motion
Serial.begin(9600);
}
void motionISR() {
motionDetected = true;
}
void loop() {
if (motionDetected) {
digitalWrite(9, HIGH); // Turn on LED
Serial.println("Motion Detected!");
delay(2000); // Keep the LED on for 2 seconds
digitalWrite(9, LOW); // Turn off LED
motionDetected = false; // Reset the flag
}
}
This code triggers an interrupt when the PIR sensor
detects motion. The interrupt calls the motionISR()
function, setting the motionDetected flag to true. The loop
then turns on the LED for 2 seconds and prints a message to
the Serial Monitor.
Challenge
Extend this project by adding a buzzer that sounds when
motion is detected. Modify the code to include the buzzer,
ensuring the system can handle multiple events
simultaneously by using additional interrupts or
managing them within the main loop.
Components List:
1. Arduino (e.g., Uno, Nano)
2. Ultrasonic Sensor (HC-SR04)
3. Resistors (as needed for signal conditioning)
4. Wires
5. Breadboard
Circuit Diagram:
Code:
const int trigPin = 9; // Trigger pin for the ultrasonic sensor
const int echoPin = 10; // Echo pin for the ultrasonic sensor
long duration; // Variable to store the time it takes for the pulse to return
int distance; // Variable to store the calculated distance
void setup() {
pinMode(trigPin, OUTPUT); // Set trigger pin as an output
pinMode(echoPin, INPUT); // Set echo pin as an input
Serial.begin(9600); // Begin serial communication for output
}
void loop() {
// Clear the trigger pin by setting it LOW
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
Code Walkthrough:
1. Global Variables:
trigPin : Pin 9 is used to send the trigger
pulse to the sensor.
echoPin : Pin 10 is used to read the
returning pulse from the sensor.
duration : Stores the time (in
microseconds) between sending the
pulse and receiving the echo.
distance : Stores the calculated distance
based on the duration of the pulse.
2. setup() :
pinMode(trigPin, OUTPUT) configures the
trigger pin as an output to send the
pulse.
pinMode(echoPin, INPUT) configures the
echo pin as an input to receive the pulse.
Serial.begin(9600) initializes the serial
communication to display the calculated
distance.
3. loop() :
The code sends a 10-microsecond pulse
to the trigPin to initiate the distance
measurement.
The pulseIn(echoPin, HIGH) function
measures the time (in microseconds) that
the echo pin remains HIGH, which
corresponds to the time taken for the
ultrasonic wave to bounce off an object
and return.
The duration is then converted to a
distance in centimeters using the
formula: Distance (in
cm)=Duration×0.0342\text{Distance (in
cm)} = \frac{\text{Duration} \times
0.034}{2}Distance (in
cm)=2Duration×0.034
The calculated distance is printed to the
Serial Monitor.
The loop delays for 1 second before
repeating the measurement.
Circuit Diagram:
The shift register receives data from the Arduino using
three control pins:
Data pin (e.g., D11) connects to the shift
register’s data input
Clock pin (e.g., D12) connects to the clock input
Latch pin (e.g., D8) connects to the latch
control
The display’s segments connect to the shift
register’s outputs (Q0-Q7). Resistors are
placed between the display’s segments and the
register’s outputs to prevent overcurrent.
Circuit Connection:
The shift register takes serial data from the
Arduino and controls the display’s segments in
parallel.
The shiftOut() function is used to send a byte
from the Arduino to the register. Each bit in the
byte corresponds to a segment on the display.
Code:
int latchPin = 8; // ST_CP
int clockPin = 12; // SH_CP
int dataPin = 11; // DS
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
// Send data to display '0'
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, 0x3F); // 0x3F
corresponds to '0'
digitalWrite(latchPin, HIGH);
delay(1000);
}
Code Walkthrough:
Pin Definitions: latchPin , clockPin , and dataPin
are connected to the shift register.
In the setup() function, the pins are set to
output mode.
In the loop(), latchPin is set LOW to prepare for
data. The shiftOut() function sends the byte
0x3F to the shift register, lighting up the display
to show the number 0. After the byte is sent,
latchPin is set HIGH to lock the data, and there is
a 1-second delay before repeating.
Circuit Connection:
Data pin from each shift register is connected to
a single pin on the Arduino.
The clock signal is shared by all shift registers,
allowing synchronized data reads.
This setup enables the Arduino to read data from
multiple shift registers in series using only
three pins (data, clock, and latch/load).
Code:
int latchPin = 8; // Connected to shift/load pin of 74HC165
int clockPin = 12; // Connected to clock pin
int dataPin = 11; // Connected to data pin
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT); // Set the data pin as an
input
Serial.begin(9600); // Initialize serial communication
}
void loop() {
// Load parallel data into the shift registers
digitalWrite(latchPin, LOW); // Pulse the latch pin to load
data
digitalWrite(latchPin, HIGH);
// Read data from the first shift register
byte inputs1 = shiftIn(dataPin, clockPin, MSBFIRST);
// Read data from the second shift register
byte inputs2 = shiftIn(dataPin, clockPin, MSBFIRST);
// Print the results to the serial monitor
Serial.print("Shift Register 1: ");
Serial.println(inputs1, BIN); // Display in binary format
Serial.print("Shift Register 2: ");
Serial.println(inputs2, BIN); // Display in binary format
delay(1000); // Add a delay between readings
}
Code Walkthrough:
Pin Definitions:
latchPin controls when the shift registers
load data.
clockPin provides the clock signal for
reading data.
dataPin reads the serial data from the
shift registers.
setup(): Initializes the pins and sets up serial
communication for monitoring input data.
loop():
First, the latch pin is pulsed to load the
data from the switches/inputs into the
shift registers.
Then, the shiftIn() function is used to
read a byte of data from each shift
register. Each byte represents the state
of 8 inputs.
The input states are printed to the Serial
Monitor in binary format, showing
whether each input is HIGH or LOW.
The code reads from two shift registers in this
example, but it can be extended to handle more.
Usage
I2C allows efficient communication between multiple
devices like sensors and displays, using only two wires. It’s
ideal for projects where you need to minimize wiring and
connect several peripherals.
Code Example
#include <Wire.h>
void setup() {
Wire.begin(); // Join I2C bus as master
Serial.begin(9600);
}
void loop() {
Wire.requestFrom(0x48, 1); // Request 1 byte from device
at address 0x48
while (Wire.available()) {
char c = Wire.read(); // Read byte
Serial.println(c);
}
delay(500);
}
This example reads data from an I2C temperature sensor.
Notes
Remember to connect pull-up resistors to the SDA and
SCL lines for proper I2C communication.
Warnings
Ensure that each I2C device has a unique address.
Address conflicts can prevent proper communication.
Troubleshooting Tips
If your I2C device isn’t responding, check for correct wiring,
device addresses, and proper use of pull-up resistors.
Use the I2C scanner sketch to identify active devices on
the bus.
Usage
SPI is ideal for speed-critical projects, such as reading data
from SD cards or controlling displays, where fast
communication is essential.
Code Example
#include <SPI.h>
void setup() {
SPI.begin();
pinMode(10, OUTPUT); // SS pin
Serial.begin(9600);
}
void loop() {
digitalWrite(10, LOW); // Select the slave
byte response = SPI.transfer(0x42); // Send data and
receive response
digitalWrite(10, HIGH); // Deselect the slave
Serial.println(response);
delay(1000);
}
This example demonstrates communication with an SPI
device.
Notes
Use separate SS pins for each slave device to prevent
communication conflicts.
Warnings
Ensure the clock speed is set appropriately for each
device.
Troubleshooting Tips
If SPI isn’t working, check that MOSI, MISO, and SCLK are
correctly wired, and the clock speed is compatible with the
slave device.
Usage
UART is commonly used for sending sensor data to a
computer or communicating between multiple Arduino
boards in simple projects. It’s essential for debugging
because you can monitor real-time data using the Serial
Monitor.
Code Example
void setup() {
Serial.begin(9600); // Start UART communication at 9600
baud
}
void loop() {
if (Serial.available() > 0) {
char incomingData = Serial.read(); // Read incoming data
Serial.print("Received: ");
Serial.println(incomingData); // Send the received data
back to the serial monitor
}
}
This example demonstrates basic UART communication,
reading and echoing data.
Notes
Ensure that both devices use the same baud rate for
successful communication.
Warnings
Mismatch in baud rates between devices will result in
incorrect or lost data during transmission.
Troubleshooting Tips
If UART communication is unreliable, check for correct
wiring of TX and RX pins and ensure that both devices
are using the same baud rate. Also, make sure no other
devices are interfering with the serial port.
5. Practical Project: Communication with
Multiple Devices
Project Overview: Reading Data from Multiple
Sensors Using I2C
In this project, we’ll use the I2C bus to communicate with
multiple sensors connected to a single Arduino. The Arduino
will gather data from a temperature sensor and a light
sensor, displaying the data on the Serial Monitor.
Why is This Project Important?
This project shows how to handle multiple devices
efficiently using the I2C protocol. It’s useful in large-scale
projects like weather stations or home automation
systems, where multiple sensors need to share data with a
single Arduino.
Components List
Arduino
Temperature sensor (I2C-based, e.g., TMP102)
Light sensor (I2C-based, e.g., BH1750)
Jumper wires
Breadboard
Circuit Diagram
Connect SDA and SCL from the Arduino to both
sensors.
The TMP102 and BH1750 share the same SDA
and SCL lines, with unique addresses.
Power the sensors with 5V and GND.
Code Example
#include <Wire.h>
#include <Adafruit_Sensor.h> // Include I2C libraries for
sensors
#include <Adafruit_BH1750.h>
#include <Adafruit_TMP102.h>
Adafruit_BH1750 lightSensor;
Adafruit_TMP102 tempSensor;
void setup() {
Serial.begin(9600); // Initialize serial communication
Wire.begin(); // Start the I2C bus
if (!lightSensor.begin()) {
Serial.println("Light sensor not detected");
while (1);
}
if (!tempSensor.begin()) {
Serial.println("Temp sensor not detected");
while (1);
}
}
void loop() {
float lightLevel = lightSensor.readLightLevel();
float temperature = tempSensor.readTemperature();
Serial.print("Light Level: ");
Serial.print(lightLevel);
Serial.print(" lx | Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
delay(1000); // Wait 1 second before the next reading
}
This code reads data from a light sensor and a temperature
sensor on the I2C bus, displaying it on the Serial Monitor.
Challenge
Enhance this project by adding an SPI-based SD card
module to log sensor data. Use I2C for the sensors and SPI
for the SD card, allowing you to store readings in a text file
for later analysis.
The 8 LEDs are connected to the Arduino, each with its own
resistor. The cathodes of the LEDs are connected to
ground via resistors, while the anodes are connected to 8
digital pins (e.g., pins 2 through 9).
Circuit Connection
Each LED is controlled by a specific bit in the variable. For
example, bit 0 might represent LED 1, bit 1 might
represent LED 2, and so on. By changing the bits in the
variable, you can control which LEDs are on (1) or off (0).
Code
int ledState = 0b00000000; // All LEDs off
int ledPins[8] = {2, 3, 4, 5, 6, 7, 8, 9}; // Pins for the LEDs
void setup() {
for (int i = 0; i < 8; i++) {
pinMode(ledPins[i], OUTPUT);
}
}
void loop() {
ledState |= (1 << 3); // Turn on LED 4 (bit 3)
ledState &= ~(1 << 5); // Turn off LED 6 (bit 5)
updateLEDs();
delay(500);
}
void updateLEDs() {
for (int i = 0; i < 8; i++) {
digitalWrite(ledPins[i], (ledState >> i) & 1); // Shift the
bits and update each LED
}
}
Code Walkthrough
The ledState variable holds the state of all 8
LEDs.
The | operator is used to set a bit (turning an
LED on), while the & operator combined with ~
(NOT) clears a bit (turning an LED off).
The updateLEDs function shifts the bits of the
ledState variable and updates the LEDs
accordingly by checking whether each bit is 1 or
0.
Challenge:
Add push buttons to allow users to toggle individual LEDs.
Use bitwise XOR ( ^ ) to toggle a specific bit in the
ledState variable when a button is pressed, flipping the
LED’s current state.
5. Common Troubleshooting and
Debugging Tips
5.1 Common Errors with Bitwise Operators and How to Fix
Them
Usage
Use EEPROM to store critical data like counters, settings,
or sensor readings that need to be retained across
restarts.
Code Example
#include <EEPROM.h>
int counter = EEPROM.read(0); // Read the counter from
EEPROM
void setup() {
counter++;
EEPROM.write(0, counter); // Store the updated counter
Serial.begin(9600);
Serial.print("Counter: ");
Serial.println(counter);
}
This code reads and writes a counter value to EEPROM.
Practical Exercise
Create a project where a counter is stored in EEPROM, and
each time the Arduino restarts, the counter value is
incremented and saved.
Troubleshooting Tips
If EEPROM isn’t working, ensure that you are not exceeding
the write cycle limit. Excessive writes can wear out
EEPROM memory.
4. Flash Memory: Storing Data Efficiently
What is Flash Memory in Arduino?
Flash Memory stores the Arduino program code and
constant data. It is non-volatile, so the data is retained
even when the device is powered off. Flash is typically used
for storing large constant data like lookup tables and
string constants.
Why is Flash Memory Important?
Flash memory is crucial for efficiently storing large
datasets that don't need to change during program
execution. It helps free up SRAM for variable storage,
improving the overall performance of the program.
Syntax Explanation
PROGMEM : Used to store data in Flash memory
instead of SRAM.
pgm_read_byte_near() : Reads data stored in
Flash memory.
Circuit Diagram:
Connect the potentiometer to an analog input
pin to adjust brightness.
Connect the LED to a digital output pin to
display brightness.
Use the push button to save the current
brightness setting to EEPROM.
Code Walkthrough:
#include <EEPROM.h>
int brightness;
int potPin = A0; // Potentiometer pin
int ledPin = 9; // LED pin
int buttonPin = 2; // Button pin
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
brightness = EEPROM.read(0); // Read saved brightness
from EEPROM
analogWrite(ledPin, brightness);
}
void loop() {
int potValue = analogRead(potPin);
brightness = map(potValue, 0, 1023, 0, 255);
analogWrite(ledPin, brightness);
if (digitalRead(buttonPin) == LOW) { // Button pressed
EEPROM.write(0, brightness); // Save brightness to
EEPROM
delay(500); // Debounce delay
}
}
This project uses a potentiometer to adjust the LED
brightness, and the push button saves the brightness to
EEPROM.
Challenge
Extend the project by storing multiple user profiles in
EEPROM, each containing settings like brightness and
mode. Use multiple EEPROM addresses to save different
profiles and allow the user to switch between them.
What is byte() ?
The byte() function in Arduino converts a value to the byte
data type, which stores numbers from 0 to 255. It’s useful
when your program only needs to handle small positive
numbers. For example, if you have a value that will always
be between 0 and 255, converting it to a byte saves
memory compared to using an int . This is especially
important in memory-constrained projects, ensuring you
use resources effectively.
Why is it Important?
The byte() function helps optimize memory usage by
allowing you to store small values using less space. This is
especially useful when working with many variables or when
the program needs to run efficiently on Arduino’s limited
memory. By storing values as bytes, you can prevent
memory overuse, which helps your projects run smoothly.
Syntax
The syntax for using the byte() function is:
byte(variable)
This converts the value of a variable to the byte data type,
storing numbers from 0 to 255.
Syntax Explanation
The byte() function takes a value or variable as its
parameter and converts it to a byte. If the value is larger
than 255, it will be truncated to fit within the byte’s
range of 0 to 255. This makes it perfect for small positive
numbers, helping you manage memory efficiently.
Usage
You can use byte() to store sensor values or other small
numbers. For example, if a light sensor provides values
between 0 and 100, you can store these as bytes to save
memory. This is especially useful when handling multiple
sensors in a project.
Code Example
Here’s an example of how to use byte() to store a sensor
reading:
int sensorValue = analogRead(A0); // Read sensor value
byte sensorByte = byte(sensorValue); // Convert sensor
value to byte
Serial.println(sensorByte); // Print the byte value
This code reads a sensor value, converts it to a byte, and
then prints it to the Serial Monitor.
Notes
The byte() function is useful when working with small
positive numbers. It helps save memory, which is
important in projects where you need to optimize
resources.
Warnings
Be cautious when converting values larger than 255. If you
try to store a number beyond this range using byte() , the
value will be truncated, potentially causing unexpected
results in your program.
Troubleshooting Tips
If your program behaves unexpectedly when using byte() ,
check if the values you're converting are too large.
Numbers greater than 255 will be truncated. Also, make
sure you are using byte() in cases where small numbers
are sufficient. Always monitor variable values with the
Serial Monitor to check for problems.
What is char() ?
The char() function converts a value to the char data
type, which represents characters using ASCII values. For
example, the integer 65 corresponds to the character ‘A’ in
ASCII. This function is useful when you need to display or
send characters in your project. It is often used when you
need to work with text characters in serial
communication or when handling characters on displays
like LCDs.
Why is it Important?
The char() function is important because it allows you to
convert numeric data into characters. This is essential for
serial communication, where devices transmit or receive
characters as part of text strings. Without converting data
to the char type, communication or displaying readable
text would not be possible.
Syntax
The basic syntax for the char() function is:
char(variable)
This converts the given variable into a char, which
corresponds to a character based on its ASCII value.
Syntax Explanation
The char() function takes a number or variable and
converts it to a character using the ASCII table. For
example, the number 65 corresponds to the character ‘A’.
This is useful for serial communication when transmitting
text characters to devices.
Usage
You can use char() to convert numeric values into
characters for display or serial transmission. For
instance, converting an integer into a character allows it to
be sent to the Serial Monitor or displayed on an LCD.
Code Example
Here’s a basic example of using char() to convert an
integer into a character for serial display:
int value = 65; // ASCII value for 'A'
char character = char(value); // Convert to character
Serial.println(character); // Display character in Serial
Monitor
This code converts the value 65 into the character ‘A’ and
sends it to the Serial Monitor for display.
Notes
The char() function is helpful when working with ASCII
characters in serial communication. Make sure to use
valid ASCII values to avoid unexpected behavior.
Warnings
Make sure that the values you convert to char are within
the valid ASCII range. Converting numbers outside this
range may result in unintended characters or errors in
your program.
Troubleshooting Tips
If characters are not displaying correctly, ensure that you
are using valid ASCII values. Check that the baud rate for
serial communication is set correctly. Use Serial.print() to
debug and track converted characters. This can help
pinpoint conversion issues.
What is float() ?
The float() function converts values to the float data
type, which stores numbers with decimal points. It is ideal
when precise values are required, such as in sensor
readings or calculations involving fractions. Without
float() , Arduino would only handle whole numbers,
limiting accuracy. For example, using float(1.234) allows
your program to work with more precise values compared to
using integers.
Why is it Important?
The float() function is necessary for projects requiring
decimal precision, such as temperature readings, distance
calculations, or other sensor data. Without using float() ,
you would lose accuracy when working with decimal
numbers. This is important in projects where small
variations in numbers matter.
Syntax
The syntax for the float() function is:
float(variable)
This converts the variable to a floating-point number for
calculations involving decimal precision.
Syntax Explanation
The float() function converts a numeric value or variable
to a floating-point number, meaning it can store numbers
with decimal points. This is crucial when working with
measurements that require high precision, such as
temperature or distance.
Usage
Use float() to convert numbers for precise calculations,
such as when reading data from sensors that provide
decimal values. For instance, when working with
temperature or distance sensors, float() ensures the
accuracy of the data.
Code Example
Here is an example of using float() in an Arduino program:
int sensorValue = analogRead(A0);
float voltage = float(sensorValue) * (5.0 / 1023.0);
Serial.println(voltage);
This code reads a sensor value and converts it into a
floating-point number for more accurate voltage
calculations.
Notes
Use the float() function for calculations involving decimal
values. This helps ensure the accuracy of data, especially
when working with sensors.
Warnings
Be aware that floating-point precision is limited on
Arduino. Extremely large or small decimal numbers may not
be handled accurately, especially on memory-constrained
devices.
Troubleshooting Tips
If your program gives incorrect results, check that the
values are within Arduino's precision limits for floating-
point numbers. Use Serial.print() to monitor the converted
values and ensure the float conversion is correct.
What is int() ?
The int() function converts values to the int data type,
which stores whole numbers. It is useful when you do not
need decimal precision, such as in counting or
performing simple arithmetic. For example, int(3.8) will
convert the value to 3, ignoring the decimal part. Using
int() helps save memory when working with whole
numbers.
Why is it Important?
The int() function helps save memory by storing whole
numbers. It is ideal for projects where precision is not
needed, like counting or dealing with simple operations.
Using int() instead of float() reduces memory usage and
improves performance.
Syntax
The syntax for the int() function is
int(variable)
This converts the variable to an integer, ignoring any
decimal places.
Syntax Explanation
The int() function converts a number or variable into an
integer by truncating the decimal part. For example,
using int(4.9) will convert the value to 4, discarding the
decimal. This is useful for saving memory when decimals
are unnecessary.
Usage
Use int() when you don’t need decimal precision and
want to store whole numbers. For instance, when counting
events or using digital inputs, the int() function is
sufficient.
Code Example
Here’s an example of converting a float to an int in an
Arduino program:
float temperature = 25.67;
int roundedTemperature = int(temperature);
Serial.println(roundedTemperature);
This code converts the float temperature into an integer,
truncating the decimal part.
Notes
The int() function is best used when decimal values are
unnecessary. It saves memory by storing only whole
numbers.
Warnings
The int() function truncates decimal values instead of
rounding them. Make sure that you do not need the decimal
part before converting.
Troubleshooting Tips
If decimal values are being cut off, remember that int()
does not round numbers; it simply truncates them. If you
need decimal precision, consider using float() instead.
What is long() ?
The long() function converts values to the long data type,
which stores larger whole numbers than int. The long
data type is necessary when dealing with large integers
that exceed the range of an int. For example, millis()
returns a long value representing time in milliseconds.
Using long() helps prevent overflow errors when storing
large numbers.
Why is it Important?
The long() function is essential for storing large numbers
that go beyond the capacity of int. Without long() ,
numbers would overflow, leading to errors in calculations
involving time or other large values.
Syntax
The syntax for the long() function is:
long(variable)
This converts the variable to a long integer, allowing it to
store large numbers.
Syntax Explanation
The long() function converts a numeric value into a long
integer. This is used when the number is too large for an
int. For instance, time values in milliseconds from the
millis() function often require long() .
Usage
Use long() when you need to store large numbers, such
as time intervals in milliseconds. This ensures that
numbers do not overflow, which would lead to errors.
Code Example
Here’s an example of using long() to store the time in
milliseconds:
long timeElapsed = millis();
Serial.println(timeElapsed);
This code stores the elapsed time in a long variable to
prevent overflow.
Notes
The long() function is essential for handling large
integers. Use it in projects where int cannot store large
enough values.
Warnings
Ensure the numbers you store with long() are within the
valid range. Storing values outside this range can cause
overflow errors.
Troubleshooting Tips
If you experience overflow when dealing with large
numbers, check if the int type is insufficient. Use long() to
handle numbers that exceed the range of int.
Why is it Important?
The (unsigned int) conversion is important when you know
that your values will always be non-negative. By using
unsigned int , you can store larger positive numbers
without needing more memory. This is helpful for projects
involving timing, counting, or storing values that are
always positive.
Syntax
The syntax for the (unsigned int) conversion is:
(unsigned int)(variable)
This converts the given variable to an unsigned integer,
meaning it will store positive values only.
Syntax Explanation
The (unsigned int) function converts a number or
variable into an unsigned integer. This means that it can
only store positive values and the range of values
increases to 65,535. For example, (unsigned int)(50000)
would convert the number 50,000 to an unsigned integer.
Usage
The (unsigned int) conversion is often used when dealing
with values that can’t be negative, like counting time
intervals or sensor readings that are always positive.
Using unsigned int ensures memory efficiency.
Code Example
Here’s an example of using (unsigned int) to count non-
negative values:
int count = -5;
unsigned int positiveCount = (unsigned int)(count);
Serial.println(positiveCount);
In this example, the negative value -5 is converted to a
large positive number due to the limitations of (unsigned
int) , so you should avoid converting negative values.
Notes
The (unsigned int) function is ideal for storing positive
values. It’s helpful for projects where you know that
negative numbers will not be encountered, such as
counting events.
Warnings
Be careful when converting negative values using
(unsigned int) . Doing so will result in incorrect outputs, as
negative numbers are converted into large positive
values.
Troubleshooting Tips
If you experience unexpected results when using (unsigned
int) , check if negative values are being converted.
Converting negative numbers can lead to incorrect
large values, which can cause issues. Make sure your data
is strictly non-negative.
Syntax
The syntax for the (unsigned long) conversion is:
(unsigned long)(variable)
This converts the variable to an unsigned long, allowing it
to store very large numbers.
Syntax Explanation
The (unsigned long) function converts a number or
variable into an unsigned long integer. This allows you
to store much larger values compared to unsigned int . For
example, the result of (unsigned long)(1000000) would be
a large positive number.
Usage
The (unsigned long) conversion is commonly used in time-
related functions like millis(), which return the time in
milliseconds. Using (unsigned long) ensures you can store
large numbers without risking overflow.
Code Example
Here’s an example of using (unsigned long) to store time in
milliseconds:
unsigned long currentTime = millis();
Serial.println(currentTime);
In this code, the current time is stored in an unsigned long
to handle the large value returned by millis().
Notes
The (unsigned long) conversion is essential for storing
large positive values. It is typically used in time
calculations or large counters.
Warnings
Ensure that the values you store using (unsigned long) do
not exceed its maximum range. If you exceed this range, it
will result in overflow errors.
Troubleshooting Tips
If your program starts showing overflow errors or incorrect
values, check that the numbers you are using are within the
valid range for (unsigned long) . Make sure that your
calculations do not exceed 4,294,967,295.
Components List:
Arduino
LM35 Temperature Sensor
Breadboard
Wires
LCD display (optional)
Circuit Diagram:
Circuit Connection:
1. VCC pin of the LM35 connects to 5V on the
Arduino.
2. GND pin of the LM35 connects to ground (GND)
on the Arduino.
3. Output pin of the LM35 connects to the analog
input pin A0 on the Arduino.
Code:
void setup() {
Serial.begin(9600); // Initialize the Serial Monitor at 9600
baud rate
}
void loop() {
int sensorValue = analogRead(A0); // Read the analog
value from LM35
float temperatureC = (sensorValue / 1024.0) * 500.0; //
Convert analog reading to Celsius
float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0; //
Convert Celsius to Fahrenheit
// Print temperature values to the Serial Monitor
Serial.print("Temperature in Celsius: ");
Serial.println(temperatureC);
Serial.print("Temperature in Fahrenheit: ");
Serial.println(temperatureF);
delay(1000); // Delay for 1 second for readability
}
Code Walkthrough:
1. sensorValue:
The analogRead(A0) function reads the analog
value from the LM35 sensor, which outputs a
value between 0 and 1023. This value
corresponds to the measured temperature.
2. temperatureC:
The formula (sensorValue / 1024.0) * 500.0
converts the analog value to Celsius. The LM35
sensor outputs 10 mV/°C, and this calculation
scales the analog reading to represent the
temperature in Celsius.
3. temperatureF:
The Celsius temperature is converted to
Fahrenheit using the formula (C * 9/5) + 32 .
This is a standard conversion formula to switch
from Celsius to Fahrenheit.
4. Serial Output:
The temperatures in both Celsius and
Fahrenheit are printed to the Serial Monitor for
easy monitoring.
5. Delay:
A 1-second delay( delay(1000) ) is added to
space out the readings and make them more
readable on the Serial Monitor.
Components List:
Arduino
Potentiometer
Servo motor
Breadboard
Wires
Circuit Diagram:
Potentiometer:
Connect the middle pin (signal) to A0
on the Arduino.
The other two pins go to 5V and GND.
Servo Motor:
Connect the control wire of the servo to
pin 9 (a PWM pin).
Connect the power pin of the servo to
5V.
Connect the GND pin of the servo to
GND on the Arduino.
Circuit Connection:
1. Potentiometer:
The potentiometer acts as a variable
resistor, providing an analog value
between 0-1023.
This value is read by the Arduino and
mapped to control the servo’s angle
from 0° to 180°.
2. Servo Motor:
The potentiometer’s raw value is
converted to a servo angle using int()
and long() conversions to ensure
precision in the movement of the servo.
Code:
#include <Servo.h>
Servo myServo; // Create servo object
int potValue; // Variable to store potentiometer value
int servoAngle; // Variable to store the calculated servo
angle
void setup() {
myServo.attach(9); // Attach the servo to pin 9
}
void loop() {
potValue = analogRead(A0); // Read the potentiometer
value (0-1023)
servoAngle = map(potValue, 0, 1023, 0, 180); // Map the
value to a range of 0-180 for the servo
myServo.write(servoAngle); // Move the servo to the
calculated angle
}
Code Walkthrough:
1. Analog Reading:
The analogRead(A0) function reads the
potentiometer’s value, which ranges
from 0 to 1023. This represents the
potentiometer’s current position.
2. Mapping the Value:
The map() function is used to convert
the potentiometer’s range (0-1023)
into a servo angle range (0°-180°).
The int type is sufficient to store the
mapped servo angle, while long could
be used for larger ranges, but is not
needed in this case.
3. Servo Control:
The servo is then moved to the mapped
angle using the
myServo.write(servoAngle) function, and
the position is adjusted as the
potentiometer is turned.
This allows for real-time control of the
servo motor’s angle by simply turning
the potentiometer.
Components List:
Arduino
3 LEDs
Resistors (220Ω recommended for each LED)
Push button
Breadboard
Wires
Circuit Diagram:
Circuit Connection:
1. LEDs:
Connect the positive leg (anode) of the
LEDs to pins 8, 9, and 10 on the
Arduino.
Connect a 220Ω resistor between the
negative leg (cathode) of each LED and
GND.
2. Push Button:
Connect one pin of the push button to
pin 2 on the Arduino.
Connect the other pin to GND.
Add a 10kΩ pull-down resistor
between pin 2 and GND to stabilize the
signal.
Code:
unsigned long pressStartTime = 0; // Store time when
button is pressed
bool buttonPressed = false; // Track button press state
void setup() {
pinMode(2, INPUT); // Button pin
pinMode(8, OUTPUT); // LED 1 pin
pinMode(9, OUTPUT); // LED 2 pin
pinMode(10, OUTPUT); // LED 3 pin (optional for further
timing control)
digitalWrite(8, LOW); // Ensure LED 1 is off initially
digitalWrite(9, LOW); // Ensure LED 2 is off initially
digitalWrite(10, LOW); // Ensure LED 3 is off initially
}
void loop() {
// Check if button is pressed and not already pressed
before
if (digitalRead(2) == HIGH && !buttonPressed) {
pressStartTime = millis(); // Record time of press
buttonPressed = true; // Set button press state to true
}
if (buttonPressed) {
// Turn on LED 1 after 1 second
if (millis() - pressStartTime > 1000) {
digitalWrite(8, HIGH);
}
// Turn on LED 2 after 3 seconds
if (millis() - pressStartTime > 3000) {
digitalWrite(9, HIGH);
}
// Turn on LED 3 after 5 seconds (optional)
if (millis() - pressStartTime > 5000) {
digitalWrite(10, HIGH);
}
// Reset if button is released
if (digitalRead(2) == LOW) {
buttonPressed = false; // Reset button state
digitalWrite(8, LOW); // Turn off LED 1
digitalWrite(9, LOW); // Turn off LED 2
digitalWrite(10, LOW); // Turn off LED 3 (optional)
}
}
}
Code Walkthrough:
1. Tracking Time with millis():
When the button is pressed,
pressStartTime stores the current time in
milliseconds using millis() . This is done
using unsigned long to handle the
potentially large numbers generated over
time.
2. LED Control Based on Time:
The millis() function continuously checks
how much time has passed since the
button was pressed:
If 1 second has passed, LED 1
turns on.
If 3 seconds have passed, LED
2 turns on.
If 5 seconds have passed
(optional), LED 3 turns on.
3. Button Release and Reset:
When the button is released
( digitalRead(2) == LOW ), the state is
reset, and all LEDs turn off, allowing the
process to repeat the next time the
button is pressed.
Components List:
Arduino
DHT11 sensor
OLED display (optional) or I2C module
Breadboard
Wires
Circuit Diagram:
DHT11 sensor:
VCC → Connect to 5V.
GND → Connect to GND.
Data pin → Connect to digital pin 7.
OLED display (if using):
SDA → Connect to A4 (I2C data).
SCL → Connect to A5 (I2C clock).
Circuit Connection:
1. Connect the DHT11 sensor to the Arduino:
VCC to 5V
GND to GND
Data pin to pin 7 on the Arduino.
2. (Optional) OLED display via I2C:
SDA to A4 on the Arduino.
SCL to A5 on the Arduino.
Code:
#include <DHT.h>
#define DHTPIN 7 // Pin where the DHT sensor is
connected
#define DHTTYPE DHT11 // DHT11 sensor type
DHT dht(DHTPIN, DHTTYPE); // Initialize DHT sensor
void setup() {
Serial.begin(9600); // Start Serial communication
dht.begin(); // Initialize the DHT sensor
}
void loop() {
// Reading temperature and humidity
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
// Check if any readings failed
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Print humidity and temperature to Serial Monitor
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %");
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" *C");
delay(2000); // Wait 2 seconds between measurements
}
Code Walkthrough:
1. DHT Sensor Setup:
The DHT11 sensor is connected to pin
7, and the DHT library is used to read
the temperature and humidity values.
The DHT dht(DHTPIN, DHTTYPE) line
initializes the sensor with the correct pin
and sensor type.
2. Reading Sensor Data:
dht.readHumidity() and
dht.readTemperature() functions are
used to retrieve the humidity and
temperature values, which are stored
as float for precise calculations.
3. Error Handling:
The code checks for failed sensor
readings using isnan() (which stands for
"is not a number"). If any reading fails,
an error message is printed to the Serial
Monitor.
4. Displaying Data:
The temperature and humidity values are
displayed on the Serial Monitor using
Serial.print() and Serial.println() .
5. Delay:
A 2-second delay( delay(2000) ) is
introduced between each reading to
avoid flooding the monitor with data and
to allow time for the sensor to take new
measurements.
Circuit Diagram:
The push button is used to simulate input, and the Serial
Monitor displays the validation result.
Circuit Connection:
1. Push button:
One side of the button is connected to
pin 2 on the Arduino.
The other side is connected to ground.
A 10kΩ pull-down resistor is
connected between pin 2 and ground to
ensure a stable input state.
Code:
char input = 'A'; // Simulate user input
void setup() {
Serial.begin(9600); // Initialize serial communication
}
void loop() {
// Simulated input (you can replace this with actual input
logic)
input = 'A'; // Example character
// Validate the input and print the result to the Serial
Monitor
if (isAlpha(input)) {
Serial.println("Valid letter input");
} else if (isDigit(input)) {
Serial.println("Valid digit input");
} else if (isPrintable(input)) {
Serial.println("Valid special character");
} else {
Serial.println("Invalid input");
}
delay(2000); // Wait for 2 seconds before the next
validation
}
Code Walkthrough:
1. Serial Communication Setup: The
Serial.begin(9600) command initializes the Serial
Monitor for displaying validation results.
2. Simulated Input: The code simulates a user
input ( 'A' in this case). In real-world applications,
this input could be captured from a keypad or
another input device.
3. Input Validation:
isAlpha() checks if the input is a letter
(A-Z, a-z).
isDigit() checks if the input is a
number (0-9).
isPrintable() checks if the input is a
printable special character (such as
! , @ , # ).
4. Serial Output: Depending on the validation
result, a corresponding message is printed to the
Serial Monitor (e.g., "Valid letter input" or
"Invalid input").
5. Loop: The process repeats after a 2-second delay,
simulating continuous input validation.
Circuit Connection
Row 1 (Pin 1) D3
Row 2 (Pin 2) D4
Row 3 (Pin 3) D5
Row 4 (Pin 4) D6
Column 1 (Pin D7
5)
Column 2 (Pin D8
6)
Column 3 (Pin D9
7)
Steps:
1. Connect the Row Pins:
Pin 1 → D3 (Row 1)
Pin 2 → D4 (Row 2)
Pin 3 → D5 (Row 3)
Pin 4 → D6 (Row 4)
2. Connect the Column Pins:
Pin 5 → D7 (Column 1)
Pin 6 → D8 (Column 2)
Pin 7 → D9 (Column 3)
Pin 8 → D10 (Column 4)
3. Power the Arduino: Connect the USB cable to
the Arduino for power and to use the Serial
Monitor.
4. Optional: Add pull-down resistors (10kΩ)
between row/column pins and ground if
necessary to stabilize input readings.
Code:
#include <Keypad.h>
// Define the Keypad layout
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {3, 4, 5, 6}; // Row pin connections
byte colPins[COLS] = {7, 8, 9, 10}; // Column pin
connections
Keypad keypad = Keypad(makeKeymap(keys), rowPins,
colPins, ROWS, COLS);
String input = ""; // Store user input
void setup() {
Serial.begin(9600); // Initialize Serial Monitor
Serial.println("Enter Text:");
}
void loop() {
char key = keypad.getKey(); // Get key press
if (key) {
// '*' clears the input, '#' submits the input
if (key == '*') {
input = ""; // Clear input
Serial.println("Input cleared.");
} else if (key == '#') {
Serial.println("Final input: " + input); // Display final
input
input = ""; // Reset after submission
} else {
input += key; // Add key to input string
Serial.println("Current input: " + input); // Show input
}
}
delay(100); // Short delay to avoid multiple inputs from a
single press
}
Code Explanation:
Keypad Setup: The keypad layout is defined,
with rows and columns connected to the Arduino's
digital pins. The Keypad library handles the row
and column scanning.
Serial Communication: The program uses
Serial.begin(9600) to initialize the Serial
Monitor for displaying input.
Handling Key Input:
* clears the input.
# submits the input and displays it.
Any other key is appended to the input
string and displayed in real-time.
Delays: A short delay ensures debouncing and
avoids multiple keypresses from a single button
press
Challenge: Add a Text Editor Feature
Expand the project by adding text editing functionality.
Allow users to delete characters, move the cursor, or
reformat text before displaying it on the LCD. This creates a
simple text editor for modifying input before confirming
the final output.
Circuit Connection:
1. Keypad:
Wire the keypad to digital pins 2-9 on
the Arduino.
Pins 2-5 for rows.
Pins 6-9 for columns.
2. Buzzer:
Connect the buzzer to pin 11 on the
Arduino for sound feedback during wrong
password attempts.
3. Power and Ground:
Ensure connections for 5V and GND for
all components.
Code:
#include <Keypad.h>
// Keypad setup
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5}; // Row pins of the
keypad
byte colPins[COLS] = {6, 7, 8, 9}; // Column pins of the
keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins,
colPins, ROWS, COLS);
String password = "Arduino123"; // **Pre-set password**
String input = ""; // **Store user input**
void setup() {
Serial.begin(9600); // **Initialize Serial Monitor**
Serial.println("Enter Password:"); // **Prompt user for
password**
}
void loop() {
char key = keypad.getKey(); // **Read key from keypad**
if (key) {
if (key == '*') { // Clear input if * is pressed
input = "";
Serial.println("Input cleared");
}
else if (key == '#') { // **Submit password when # is
pressed**
if (input == password) {
Serial.println("Access Granted"); // **Correct
password**
} else {
Serial.println("Access Denied"); // **Incorrect
password**
tone(11, 1000, 200); // **Buzzer feedback for wrong
password**
}
input = ""; // Reset input after submission
}
else {
input += key; // **Append the pressed key to input**
Serial.print("*"); // Display a * for each key pressed
}
}
}
Code Explanation:
Keypad Setup: The keypad is initialized with row
and column pins connected to digital pins 2-9 on
the Arduino.
Serial Monitor: The code uses
Serial.begin(9600) to print messages and receive
feedback in the Serial Monitor.
Handling Key Input:
* key clears the input.
# key submits the input and checks if
the entered password matches the pre-
set password.
If the password is correct, "Access
Granted" is displayed; otherwise,
"Access Denied" is shown, and the
buzzer sounds for wrong password
attempts.
Password Masking: Each key press is masked
with an asterisk ( * ) in the Serial Monitor for
privacy.
Circuit Diagram:
No additional hardware is needed, just the Arduino board
connected to your computer via USB.
Circuit Connection:
No physical wiring is required. All interaction occurs via the
serial monitor.
Code:
String input = "";
void setup() {
Serial.begin(9600); // Initialize Serial Monitor
communication
Serial.println("Enter text:");
}
void loop() {
// Check if there is data available in the Serial Monitor
if (Serial.available() > 0) {
input = Serial.readString(); // Read input from the Serial
Monitor
// Loop through each character of the input string
for (int i = 0; i < input.length(); i++) {
// Check if each character is printable
if (!isPrintable(input[i])) {
Serial.println("Invalid character in input"); // Alert if an
invalid character is found
break;
}
}
// Display the validated input
Serial.println("Valid input: " + input);
}
}
Code Walkthrough:
1. Serial Communication Setup: The Serial
Monitor is initialized with Serial.begin(9600) to
allow communication at a 9600 baud rate.
2. Reading Serial Input: The Serial.available()
function checks if any data is present in the
Serial Monitor. If so, Serial.readString() reads
the input.
3. Validation of Input: The program loops through
each character of the input string, checking if it is
printable using isPrintable() . If an invalid
character is found, the program prints an error
message and stops further validation.
4. Displaying Valid Input: If all characters are
valid, the program prints the entire string to the
Serial Monitor.
Components List:
Arduino
Keypad or Serial Monitor
SD card module
Resistors
Wires
Breadboard
Circuit Diagram:
Circuit Connection:
1. SD Card Module:
Connect the SD card module to the
Arduino’s SPI pins:
MOSI (pin 11) → SD card
module's MOSI
MISO (pin 12) → SD card
module's MISO
SCK (pin 13) → SD card
module's SCK
CS (pin 10) → SD card module's
CS
5V and GND for power and
ground.
2. Keypad or Serial Monitor:
For serial input, no extra wiring is
required, just the USB connection.
For a keypad, connect the row and
column pins to the Arduino’s digital
pins, similar to earlier keypad projects.
Code:
#include <SD.h>
File dataFile; // File object to handle SD card writing
String input = "";
void setup() {
Serial.begin(9600); // Start serial communication
if (!SD.begin(10)) { // Initialize SD card module on pin 10
(CS)
Serial.println("SD card initialization failed!");
return;
}
Serial.println("SD card initialized.");
}
void loop() {
if (Serial.available()) {
input = Serial.readString(); // Read input from Serial
Monitor
// Validate the input
if (validateInput(input)) {
// Open file for writing
dataFile = SD.open("log.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(input); // Write data to file
dataFile.close(); // Close the file
Serial.println("Data logged: " + input); // Feedback
} else {
Serial.println("Error opening file.");
}
} else {
Serial.println("Invalid input.");
}
}
}
// Function to validate input
bool validateInput(String input) {
for (int i = 0; i < input.length(); i++) {
if (!isPrintable(input[i])) return false; // Check if character
is printable
}
return true;
}
Code Walkthrough:
1. SD Card Initialization: The SD.begin(10)
function initializes the SD card module using pin
10 as the chip select (CS) pin. If initialization
fails, an error message is displayed.
2. Input from Serial Monitor: The program reads
the user's input from the serial monitor using
Serial.readString() and stores it in the input
variable.
3. Input Validation: The validateInput() function
checks if each character in the input is printable
(i.e., valid). If any character fails this check, the
function returns false.
4. Logging to SD Card: If the input is valid, the
program opens the log.txt file in write mode,
logs the input, and closes the file.
5. Feedback: The program provides feedback to the
user, confirming whether the data was
successfully logged or if an error occurred.
Both arithmetic and compound operators are important in programming as they allow
precise control over variables, calculations, and data manipulation, contributing to
efficient and clean code execution.
Syntax Table
Topic Name Syntax Simple Example
Syntax:
value -= decrement;
Syntax Explanation:
The -= operator subtracts decrement from value and stores the result in value .
This is a concise way to write value = value - decrement , especially useful in loops
where values are decremented repeatedly.
Usage:
Use the -= operator when reducing values, such as counting down or decreasing
sensor values over time. It is helpful in loops where counters are decreased at each
iteration.
Code Example:
int counter = 10;
counter -= 2; // counter = counter - 2
Serial.println(counter); // Outputs 8
In this code, the counter is decremented by 2 using the -= operator, simplifying the
subtraction.
Code Example:
int value = 20;
value /= 4; // value = value / 4
Serial.println(value); // Outputs 5
This example divides value by 4 using the /= operator, simplifying the division
process.
Circuit Diagram:
This setup allows the Arduino to read the potentiometer value from A0 and adjust the
LED brightness using PWM on pin 9.
Circuit Connection:
The LED is controlled by the PWM signal generated by the Arduino. As
the PWM value changes, the brightness of the LED changes proportionally.
The potentiometer acts as a variable resistor, providing an analog
input to the Arduino. This input can later be used to adjust the brightness
manually, though in this code, the brightness is automated with
compound operators.
Code:
int potValue = 0; // Potentiometer value (to be used for analog control)
int ledBrightness = 0; // LED brightness level (0 to 255)
int increment = 5; // Step value for brightness adjustment
void setup() {
pinMode(9, OUTPUT); // Set pin 9 as output for LED
}
void loop() {
// Read the potentiometer value (currently unused in this example)
potValue = analogRead(A0);
// Increase or decrease the LED brightness
ledBrightness += increment;
// Check boundaries (0 to 255) and reverse the direction if needed
if (ledBrightness >= 255 || ledBrightness <= 0) {
increment = -increment; // Reverse the direction of brightness change
}
// Apply the brightness to the LED using PWM
analogWrite(9, ledBrightness);
// Delay to control the speed of brightness change
delay(50); // 50ms delay for smooth transition
}
Code Walkthrough:
1. Variable Declaration:
potValue : Stores the potentiometer reading, which is an
analog value between 0 and 1023.
ledBrightness : Represents the current brightness level of
the LED, ranging from 0 (off) to 255 (full brightness).
increment : Determines the step size for how fast the LED
brightness will increase or decrease. In this case, the
brightness changes in steps of 5.
2. Setup Function:
The LED is connected to pin 9, which is set as an output pin
using pinMode(9, OUTPUT) .
3. Loop Function:
Reading Potentiometer: The potentiometer value is read
using analogRead(A0) , which could be used later to control
the brightness interactively. However, in this code, the
potentiometer reading is just stored but not used.
Brightness Adjustment: The brightness of the LED is
adjusted using the += operator. Each loop increases the
brightness by the value of increment (initially set to 5).
Boundary Check: When the brightness reaches its
maximum ( 255 , full brightness) or minimum ( 0 , off), the
direction of the brightness change is reversed. This is achieved
by flipping the sign of increment using increment = -
increment; . This results in a smooth oscillating brightness
pattern.
PWM Signal: The analogWrite(9, ledBrightness) function
sends a PWM signal to pin 9, setting the brightness of the
LED. The ledBrightness variable controls the duty cycle of
the PWM signal, which ranges from 0 (off) to 255 (full
brightness).
Delay: A small delay of 50 milliseconds is added at the end
of each loop cycle using delay(50) . This delay controls how
fast the LED fades in and out, making the brightness transition
smooth and visible to the human eye.
Challenge:
Add a push button that resets the brightness to 50% when pressed. Use a digital
input for the button and modify the code to handle the reset function.
Components List:
Arduino: Microcontroller to process input and control the servo motor.
Servo motor: A small motor with the ability to rotate between 0 and 180
degrees.
Potentiometer: Analog sensor used to adjust the angle of the servo.
Jumper wires: For making connections between components and the
Arduino.
Circuit Diagram:
Servo Motor:
Connect the control wire of the servo motor to digital pin 9
on the Arduino.
Connect the power wire of the servo motor to the 5V pin.
Connect the ground wire of the servo motor to GND.
Potentiometer:
Connect the middle pin of the potentiometer to analog pin
A0.
Connect one outer pin of the potentiometer to 5V and the
other to GND.
Circuit Connection:
The potentiometer provides a variable resistance, producing an
analog signal between 0 and 1023.
This value is read by the Arduino through analog pin A0, and mapped
to control the servo motor, which moves between 0 and 180 degrees
based on the potentiometer’s position.
Code:
#include <Servo.h>
Servo myServo; // Create servo object to control a servo motor
int potValue = 0; // Store potentiometer value (0 to 1023)
int servoAngle = 0; // Store calculated servo angle (0 to 180)
void setup() {
myServo.attach(9); // Attach the servo motor to pin 9
}
void loop() {
potValue = analogRead(A0); // Read the potentiometer value
servoAngle = map(potValue, 0, 1023, 0, 180); // Map the value to a servo angle
myServo.write(servoAngle); // Move the servo to the calculated angle
delay(50); // Short delay for stability
}
Code Walkthrough:
1. Library Import:
The Servo.h library is included to simplify the control of the
servo motor. It provides a simple interface for attaching the
servo to a pin and moving it to a specific angle.
2. Variable Declarations:
potValue : Holds the analog value read from the
potentiometer, ranging from 0 to 1023.
servoAngle : Stores the mapped angle for the servo motor,
ranging from 0 to 180 degrees.
3. Setup Function:
The servo motor is attached to pin 9 of the Arduino using the
myServo.attach(9) function. This establishes communication
between the Arduino and the servo motor.
4. Loop Function:
The potentiometer value is read using analogRead(A0) and
stored in potValue . This value will range from 0 to 1023,
depending on the potentiometer's position.
The map() function is used to convert the potentiometer's range (0 to 1023) into the
servo's range (0 to 180 degrees). This is where arithmetic operators come into
play. Internally, the map() function uses multiplication and division to scale the
input value proportionally to the desired output range:
servoAngle = map(potValue, 0, 1023, 0, 180);
Here, potValue is mapped from its natural range (0-1023) to
the angle range (0-180) that the servo motor can handle.
Components List:
Arduino: Microcontroller to control the fan and read temperature data.
Temperature sensor (e.g., LM35): Used to measure temperature.
DC fan: Controlled based on temperature data.
Motor driver (e.g., L298N): To control the speed of the fan motor.
Resistors: Used to protect the components.
Jumper wires: For making the connections.
Circuit Diagram:
Temperature Sensor:
The output pin of the temperature sensor is connected to
analog pin A0 on the Arduino.
The VCC and GND pins of the temperature sensor are
connected to 5V and GND, respectively.
DC Fan:
The fan motor is connected to the motor driver (e.g.,
L298N), which acts as an interface between the fan and the
Arduino.
The control pins of the motor driver are connected to two
PWM pins on the Arduino (e.g., pins 9 and 10), which allows
for precise control of the fan speed via PWM.
Circuit Connection:
The temperature sensor reads the current temperature and sends an
analog signal to the Arduino.
The motor driver controls the DC fan based on the PWM signal
received from the Arduino, which adjusts the fan speed according to the
temperature.
The fan's speed is controlled by varying the PWM signal on pin 9 of the
Arduino.
Code:
int tempValue = 0; // Temperature sensor value
int fanSpeed = 0; // Fan speed value
int increment = 10; // Speed adjustment step
void setup() {
pinMode(9, OUTPUT); // Set pin 9 for fan control as output
}
void loop() {
// Read the temperature sensor value from analog pin A0
tempValue = analogRead(A0);
// Map the temperature sensor value (0-1023) to a fan speed (0-255)
fanSpeed = map(tempValue, 0, 1023, 0, 255);
// Increase the fan speed gradually
fanSpeed += increment;
// Ensure the fan speed stays within valid limits (0-255)
if (fanSpeed >= 255) {
fanSpeed = 255; // Limit fan speed to max value
} else if (fanSpeed <= 0) {
fanSpeed = 0; // Limit fan speed to min value
}
// Write the calculated fan speed to pin 9 (PWM control)
analogWrite(9, fanSpeed);
// Small delay to stabilize fan speed control
delay(100);
}
Code Walkthrough:
1. Variable Declaration:
tempValue : Holds the analog input from the temperature
sensor. The range of values from the sensor will be 0 to 1023.
fanSpeed : The value representing the fan’s speed, mapped
to a range of 0 to 255 for PWM control.
increment : Determines how fast the fan speed will increase or
decrease each time the loop runs.
2. Setup Function:
Pin 9 is configured as an output pin using pinMode(9,
OUTPUT) , which will send the PWM signal to the motor driver
controlling the fan.
3. Loop Function:
Reading the temperature: The analog value from the
temperature sensor is read using analogRead(A0) and stored
in tempValue .
Mapping the temperature: The map() function is used to scale the temperature
sensor’s range of 0-1023 to a PWM range of 0-255. This allows the temperature
sensor’s value to control the fan speed proportionally:
fanSpeed = map(tempValue, 0, 1023, 0, 255);
Adjusting fan speed: The compound operator += is used to gradually increase the
fan speed by the step value stored in increment :
fanSpeed += increment;
Limiting fan speed: To prevent the fan speed from exceeding
the valid range of 0 to 255, the code checks for boundary
conditions:
If fanSpeed exceeds 255, it’s capped at 255.
If fanSpeed drops below 0, it’s set to 0.
Challenge:
Modify the system to turn off the fan when the temperature falls below a certain
threshold, using a simple if condition to detect low temperatures and halt the fan's
operation.
Syntax Table
Topic Syntax Simple Example
Name
This code initializes the OLED and displays the text "Hello, OLED!".
Practical Exercise
Initialize your OLED display and display your favorite quote. Adjust the text size
and position to fit on the screen.
Circuit Diagram:
Connect the DHT sensor to an analog pin on the Arduino and the display to the I2C
pins (for OLED) or designated digital pins (for LCD). Make sure the sensor is powered
properly and grounded.
Code Walkthrough:
#include <DHT.h>
#include <LiquidCrystal.h>
DHT dht(2, DHT11); // Sensor on pin 2
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
dht.begin();
lcd.begin(16, 2);
}
void loop() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temperature);
lcd.print(" C");
lcd.setCursor(0, 1);
lcd.print("Humidity: ");
lcd.print(humidity);
lcd.print(" %");
delay(2000);
}
This code reads data from the DHT sensor and displays temperature and humidity
values on the LCD.
Challenge
Enhance the project by adding a CO2 sensor to monitor air quality. Display the CO2
levels along with temperature and humidity on the LCD or OLED display. This
creates a more comprehensive environmental monitoring system.
Circuit Diagram:
Connect the TFT display to the Arduino’s SPI pins and wire the RGB LED matrix to
the PWM pins. The TFT will act as the interface, and touching different areas will
control the RGB LEDs.
Code Walkthrough:
#include <Adafruit_GFX.h>
#include <Adafruit_TFTLCD.h>
#include <Adafruit_NeoPixel.h>
#define PIN 6 // Pin for LED matrix
Adafruit_TFTLCD tft(A3, A2, A1, A0, A4);
Adafruit_NeoPixel strip = Adafruit_NeoPixel(64, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
tft.begin();
tft.setRotation(1);
strip.begin();
strip.show();
}
void loop() {
int x, y;
if (tft.getTouch(&x, &y)) {
int color = strip.Color(random(0, 255), random(0, 255), random(0, 255));
strip.setPixelColor(map(x, 0, 240, 0, 63), color); // Map touch to LED matrix
strip.show();
}
}
This code sets up the TFT to detect touch inputs and changes the RGB color of the
corresponding LEDs in the matrix.
Challenge
Add additional touch controls, like a brightness slider on the TFT display, to allow
users to adjust the LED brightness dynamically.
Circuit Diagram:
Connect the OLED to the I2C pins of the Arduino, and wire the sensor to one of the
analog inputs. The display will show a graph that updates in real time.
Code Walkthrough:
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
int sensorPin = A0;
int sensorValue;
void setup() {
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.clearDisplay();
}
void loop() {
sensorValue = analogRead(sensorPin);
oled.drawLine(0, 63, map(sensorValue, 0, 1023, 0, 127), 63, WHITE); // Draw graph
oled.display();
delay(1000);
oled.clearDisplay(); // Clear screen before next draw
}
This code reads data from a light sensor and updates the graph on the OLED
screen to reflect the changes in light intensity.
Challenge
Modify the project to track multiple sensor readings (e.g., temperature and
humidity) and plot them as two separate lines on the OLED graph. This will give you a
more complex visual representation.
Code Walkthrough:
#include <Adafruit_GFX.h>
#include <Adafruit_TFTLCD.h>
#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
Adafruit_TFTLCD tft(A3, A2, A1, A0, A4);
void setup() {
tft.begin();
dht.begin();
tft.fillScreen(BLUE);
}
void loop() {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
tft.setCursor(10, 10);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("Temp: "); tft.print(temp); tft.print("C");
tft.setCursor(10, 40);
tft.print("Humidity: "); tft.print(hum); tft.print("%");
// Draw weather icon (e.g., sun)
tft.fillCircle(100, 100, 20, YELLOW); // Sun icon
delay(2000);
}
This code displays temperature and humidity readings on a TFT screen along with
an animated sun icon.
Challenge
Add cloud and rain icons to represent different weather conditions dynamically. You
can use sensor inputs or randomize the weather icons to simulate various weather
conditions.
Circuit Diagram:
Connect the OLED to the I2C pins of the Arduino. The display will show custom text
and animations such as a moving bar or shape.
Code Walkthrough:
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeMonoBoldOblique12pt7b.h>
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
void setup() {
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.setFont(&FreeMonoBoldOblique12pt7b); // Use custom font
oled.setTextSize(1);
oled.setCursor(0, 30);
oled.print("Custom Font");
oled.display();
}
void loop() {
for (int i = 0; i < 128; i++) {
oled.clearDisplay();
oled.drawRect(i, 20, 10, 10, WHITE); // Animate a moving square
oled.display();
delay(50);
}
}
This code displays custom text using a custom font and animates a moving square
across the OLED screen.
Challenge
Create an animated clock with custom fonts, where the second hand is a moving
line on the OLED. Use timing functions to update the display every second.